Bootstrap of 'captive-install-acquire' for W32 modules acquiration process.
[captive.git] / src / install / acquire / moduriload.c
diff --git a/src/install/acquire/moduriload.c b/src/install/acquire/moduriload.c
new file mode 100644 (file)
index 0000000..4d67e44
--- /dev/null
@@ -0,0 +1,241 @@
+/* $Id$
+ * W32 disk modules finder for acquiration installation utility
+ * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "config.h"
+
+#include "moduriload.h"        /* self */
+#include <glib/gmessages.h>
+#include <mntent.h>
+#include <glib/ghash.h>
+#include <glib/glist.h>
+#include <libgnomevfs/gnome-vfs-uri.h>
+#include "../libcaptive-install/proc_partitions.h"
+#include "main.h"
+#include <string.h>
+#include "captivemodid.h"
+#include "cabinet.h"
+#include <libgnomevfs/gnome-vfs-ops.h>
+#include <libgnomevfs/gnome-vfs-directory.h>
+
+
+/* Config: */
+#define MAX_FILE_LOAD_LENGTH 5000000   /* Otherwise use cabextract-over-http. */
+
+
+static void mod_uri_load_module_from_memory
+               (struct captivemodid_module *module,gconstpointer file_base,size_t file_length,GnomeVFSURI *uri)
+{
+gchar *uri_text;
+
+       g_return_if_fail(module!=NULL);
+       g_return_if_fail(file_base!=NULL);
+       g_return_if_fail(uri!=NULL);
+
+       uri_text=gnome_vfs_uri_to_string(uri,GNOME_VFS_URI_HIDE_PASSWORD);
+       g_message("type=%s,id:%s: %s",module->type,module->id,uri_text);
+       g_free(uri_text);
+}
+
+void mod_uri_load_file_from_memory(gconstpointer file_base,size_t file_length,GnomeVFSURI *uri)
+{
+gchar *file_md5;
+struct captivemodid_module *module;
+
+       g_return_if_fail(file_base!=NULL);
+       g_return_if_fail(uri!=NULL);
+
+       file_md5=calc_md5(file_base,file_length);
+       if (!(module=captivemodid_module_md5_lookup(file_md5)))
+               goto fail_free_file_md5;
+
+       if (strcmp("cabinet",module->type))
+               mod_uri_load_module_from_memory(module,file_base,file_length,uri);
+       else {
+               struct acquire_cabinet *acquire_cabinet;
+               /* acquire_cabinet_load() will call mod_uri_load_module_from_memory(): */
+               acquire_cabinet=acquire_cabinet_new_from_memory(file_base,file_length,uri);
+               acquire_cabinet_load(acquire_cabinet);
+               acquire_cabinet_free(acquire_cabinet);
+               }
+
+fail_free_file_md5:
+       g_free(file_md5);
+}
+
+static void mod_uri_load_file_handle_to_memory(GnomeVFSHandle *handle,GnomeVFSFileInfo *file_info,GnomeVFSURI *uri)
+{
+guint8 *file_buffer,file_tail_check;
+GnomeVFSFileSize bytes_read;
+GnomeVFSResult errvfsresult;
+
+       g_return_if_fail(handle!=NULL);
+       g_return_if_fail(file_info!=NULL);
+       g_return_if_fail(uri!=NULL);
+
+       /* gnome_vfs_read_entire_file() reads the file by chunks although
+        * it does not need to know the file size.
+        */
+       file_buffer=g_malloc(file_info->size);
+       
+       errvfsresult=gnome_vfs_read(handle,file_buffer,file_info->size,&bytes_read);
+       if (errvfsresult!=GNOME_VFS_OK || bytes_read!=file_info->size)
+               goto fail_free_file_buffer;
+       errvfsresult=gnome_vfs_read(handle,&file_tail_check,1,NULL);
+       if (errvfsresult!=GNOME_VFS_ERROR_EOF)
+               goto fail_free_file_buffer;
+       mod_uri_load_file_from_memory(file_buffer,file_info->size,uri);
+
+fail_free_file_buffer:
+       g_free(file_buffer);
+}
+
+static void mod_uri_load_file_handle_remote_cabinet(GnomeVFSHandle *handle,GnomeVFSFileInfo *file_info,GnomeVFSURI *uri)
+{
+struct acquire_cabinet *acquire_cabinet;
+
+       g_return_if_fail(handle!=NULL);
+       g_return_if_fail(file_info!=NULL);
+       g_return_if_fail(uri!=NULL);
+
+       acquire_cabinet=acquire_cabinet_new_from_handle(handle,file_info,uri);
+       /* acquire_cabinet_load() will call mod_uri_load_module_from_memory(): */
+       acquire_cabinet_load(acquire_cabinet);
+       acquire_cabinet_free(acquire_cabinet);
+}
+
+static void mod_uri_load_file(GnomeVFSURI *uri)
+{
+GnomeVFSResult errvfsresult;
+GnomeVFSFileInfo file_info_local;
+GnomeVFSHandle *handle;
+
+       g_return_if_fail(uri!=NULL);
+
+       if (GNOME_VFS_OK!=(errvfsresult=gnome_vfs_open_uri(&handle,uri,GNOME_VFS_OPEN_READ)))
+               goto fail;
+       if (GNOME_VFS_OK!=(errvfsresult=gnome_vfs_get_file_info_from_handle(handle,&file_info_local,GNOME_VFS_FILE_INFO_DEFAULT)))
+               goto fail_close_handle;
+       if (file_info_local.type!=GNOME_VFS_FILE_TYPE_REGULAR) {
+               errvfsresult=GNOME_VFS_ERROR_WRONG_FORMAT;
+               goto fail_close_handle;
+               }
+       if (!(file_info_local.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE)) {
+               errvfsresult=GNOME_VFS_ERROR_WRONG_FORMAT;
+               goto fail_close_handle;
+               }
+       if (!captivemodid_module_length_is_valid(file_info_local.size)) {
+               errvfsresult=GNOME_VFS_ERROR_WRONG_FORMAT;
+               goto fail_close_handle;
+               }
+       if (file_info_local.size<=MAX_FILE_LOAD_LENGTH)
+               mod_uri_load_file_handle_to_memory(handle,&file_info_local,uri);
+       else
+               mod_uri_load_file_handle_remote_cabinet(handle,&file_info_local,uri);
+       errvfsresult=GNOME_VFS_OK;
+       /* PASSTHRU */
+fail_close_handle:
+       gnome_vfs_close(handle);
+fail:;
+}
+
+static gboolean mod_uri_load_directory_visit_func
+               (const gchar *rel_path,GnomeVFSFileInfo *info,gboolean recursing_will_loop,GnomeVFSURI *root_uri /* data */,
+               gboolean *recurse)
+{
+       g_return_val_if_fail(rel_path!=NULL,FALSE);
+       g_return_val_if_fail(info!=NULL,FALSE);
+       g_return_val_if_fail(root_uri!=NULL,FALSE);
+       g_return_val_if_fail(recurse!=NULL,FALSE);
+
+       *recurse=FALSE;
+
+       switch (info->type) {
+               case GNOME_VFS_FILE_TYPE_REGULAR: {
+GnomeVFSURI *file_uri;
+
+                       file_uri=gnome_vfs_uri_append_path(root_uri,rel_path);
+                       mod_uri_load_file(file_uri);
+                       gnome_vfs_uri_unref(file_uri);
+                       } break;
+               case GNOME_VFS_FILE_TYPE_DIRECTORY: {
+GnomeVFSURI *directory_uri;
+GnomeVFSDirectoryHandle *directory_handle;
+
+                       /* Never set '*recurse' if it would cause 'Access denied' error
+                        * as it would completely abort the upper gnome_vfs_directory_visit_uri().
+                        * Check the directory accessibility manually:
+                        */
+                       directory_uri=gnome_vfs_uri_append_path(root_uri,rel_path);
+                       if (GNOME_VFS_OK==gnome_vfs_directory_open_from_uri(&directory_handle,directory_uri,GNOME_VFS_FILE_INFO_DEFAULT)) {
+                               *recurse=TRUE;
+                               gnome_vfs_directory_close(directory_handle);    /* errors ignored */
+                               }
+                       gnome_vfs_uri_unref(directory_uri);
+                       } break;
+               default:;
+               }
+
+       return TRUE;    /* continue traversal */
+}
+
+static void mod_uri_load_directory(GnomeVFSURI *uri)
+{
+GnomeVFSResult errvfsresult;
+
+       g_return_if_fail(uri!=NULL);
+
+       errvfsresult=gnome_vfs_directory_visit_uri(uri,
+                       GNOME_VFS_FILE_INFO_DEFAULT,    /* info_options */
+                       GNOME_VFS_DIRECTORY_VISIT_SAMEFS,       /* visit_options; 'GNOME_VFS_DIRECTORY_VISIT_LOOPCHECK'? */
+                       (GnomeVFSDirectoryVisitFunc)mod_uri_load_directory_visit_func,
+                       uri);   /* data */
+       if (errvfsresult!=GNOME_VFS_OK) {
+gchar *uri_text;
+
+               uri_text=gnome_vfs_uri_to_string(uri,GNOME_VFS_URI_HIDE_PASSWORD);
+               g_warning(_("Error scanning sub-tree of \"%s\": %s"),uri_text,gnome_vfs_result_to_string(errvfsresult));
+               g_free(uri_text);
+               }
+}
+
+void mod_uri_load(GnomeVFSURI *uri)
+{
+GnomeVFSFileInfo file_info_local;
+GnomeVFSResult errvfsresult;
+
+       g_return_if_fail(uri!=NULL);
+
+       if (optarg_verbose) {
+gchar *uri_text;
+
+               uri_text=gnome_vfs_uri_to_string(uri,GNOME_VFS_URI_HIDE_PASSWORD);
+               g_message(_("Scanning...: %s"),uri_text);
+               g_free(uri_text);
+               }
+
+       file_info_local.type=GNOME_VFS_FILE_TYPE_UNKNOWN;
+       if (GNOME_VFS_OK!=(errvfsresult=gnome_vfs_get_file_info_uri(uri,&file_info_local,GNOME_VFS_FILE_INFO_DEFAULT)))
+               return /* errvfsresult */;
+       switch (file_info_local.type) {
+               case GNOME_VFS_FILE_TYPE_REGULAR:   return mod_uri_load_file(uri);
+               case GNOME_VFS_FILE_TYPE_DIRECTORY: return mod_uri_load_directory(uri);
+               default:                            return /* GNOME_VFS_ERROR_WRONG_FORMAT */;
+               }
+       /* NOTREACHED */
+}