X-Git-Url: https://git.jankratochvil.net/?a=blobdiff_plain;f=src%2Finstall%2Facquire%2Fmoduriload.c;h=dbc86fee4f1bef0d9dc0ff0a40f8923613e273a1;hb=56c29066a72eaeb7e84a28aedc597f13f419359e;hp=4d67e44c7f2a147fb66af7790c5b14960dae41e6;hpb=ccde52f4919c0ef58a77353b6819f3613d7d76dd;p=captive.git diff --git a/src/install/acquire/moduriload.c b/src/install/acquire/moduriload.c index 4d67e44..dbc86fe 100644 --- a/src/install/acquire/moduriload.c +++ b/src/install/acquire/moduriload.c @@ -28,48 +28,126 @@ #include "../libcaptive-install/proc_partitions.h" #include "main.h" #include -#include "captivemodid.h" #include "cabinet.h" #include #include +#include +#include + +#include +#include /* Config: */ #define MAX_FILE_LOAD_LENGTH 5000000 /* Otherwise use cabextract-over-http. */ +/* map: (const xmlChar *)type -> (struct module_available *) */ +GHashTable *module_available_hash; + +static void module_available_hash_value_destroy_func(struct module_available *module_available) +{ + g_return_if_fail(module_available!=NULL); + + g_free(module_available->file_base); + g_free(module_available->uri_text); + g_free(module_available); +} + +static void module_available_hash_init(void) +{ + if (module_available_hash) + return; + module_available_hash=g_hash_table_new_full(g_str_hash,g_str_equal, + (GDestroyNotify)NULL, + (GDestroyNotify)module_available_hash_value_destroy_func); +} + + +void (*acquire_module_available_notify)(struct module_available *module_available); +void (*acquire_module_all_modules_found_notify)(void); + static void mod_uri_load_module_from_memory - (struct captivemodid_module *module,gconstpointer file_base,size_t file_length,GnomeVFSURI *uri) + (struct captive_captivemodid_module *module,gconstpointer file_base,size_t file_length,GnomeVFSURI *uri) { -gchar *uri_text; +struct module_available *module_available; +gint best_priority; +gboolean all_modules_found; g_return_if_fail(module!=NULL); g_return_if_fail(file_base!=NULL); g_return_if_fail(uri!=NULL); + g_return_if_fail((size_t)module->length==file_length); - 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); + module_available_hash_init(); + if ((module_available=g_hash_table_lookup(module_available_hash,module->type))) { + if (module_available->module->priority>=module->priority) + return; + } + + captive_new(module_available); + module_available->module=module; + module_available->file_base=g_memdup(file_base,file_length); + module_available->uri_text=gnome_vfs_uri_to_string(uri,GNOME_VFS_URI_HIDE_PASSWORD); + /* It may possibly destroy the old 'module_available': */ + g_hash_table_insert(module_available_hash,(/* de-const */ xmlChar *)module->type,module_available); + + if (!optarg_dry) { +const gchar *dest_pathname; +int dest_fd; + + dest_pathname=captive_printf_alloca("%s/%s",G_STRINGIFY(VARLIBCAPTIVEDIR),module->type); + if (-1==(dest_fd=open(dest_pathname,O_CREAT|O_TRUNC|O_WRONLY,0644))) + g_warning(_("Cannot open target file \"%s\": %m"),dest_pathname); + else { + if ((ssize_t)file_length!=write(dest_fd,file_base,file_length)) + g_warning(_("Error writing target file \"%s\": %m"),dest_pathname); + if (close(dest_fd)) + g_warning(_("Error closing target file \"%s\": %m"),dest_pathname); + } + } + + all_modules_found=FALSE; + + best_priority=captive_captivemodid_module_type_best_priority_lookup(captivemodid,module->type); + if (best_priority==G_MININT /* no longer seeking for such module */ + || module_available->module->priority==best_priority) { + if (captive_captivemodid_module_type_best_priority_found(captivemodid,module->type)) { + /* Postpone (*acquire_module_all_modules_found_notify)() + * after (*acquire_module_available_notify)(). + */ + all_modules_found=TRUE; + } + } + + if (acquire_module_available_notify) + (*acquire_module_available_notify)(module_available); + if (all_modules_found) + if (acquire_module_all_modules_found_notify) + (*acquire_module_all_modules_found_notify)(); } void mod_uri_load_file_from_memory(gconstpointer file_base,size_t file_length,GnomeVFSURI *uri) { gchar *file_md5; -struct captivemodid_module *module; +struct captive_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))) + if ((*ui_progress)(uri)) + return; + + file_md5=captive_calc_md5(file_base,file_length); + if (!(module=captive_captivemodid_module_md5_lookup(captivemodid,file_md5))) goto fail_free_file_md5; - if (strcmp("cabinet",module->type)) + if (strcmp("cabinet",(const char *)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=acquire_cabinet_new_from_memory(file_base,file_length,uri,module->cabinet_used); acquire_cabinet_load(acquire_cabinet); acquire_cabinet_free(acquire_cabinet); } @@ -96,8 +174,15 @@ GnomeVFSResult errvfsresult; 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) + /* 'bytes_read' must be !=NULL for GnomeVFS-2.0.x! */ + errvfsresult=gnome_vfs_read(handle,&file_tail_check,1,&bytes_read); + if (!(errvfsresult==GNOME_VFS_ERROR_EOF + /* At least RedHat gnome-vfs2-2.0.2-5 + * and ntfsprogs-200309071734-1captive1 and ntfsprogs-gnomevfs-1.0.1-0 + * do not report GNOME_VFS_ERROR_EOF. + * FIXME: Check if it is a bug in ntfsprogs-gnomevfs-1.0.1-0. + */ + || (errvfsresult==GNOME_VFS_OK && bytes_read==0))) goto fail_free_file_buffer; mod_uri_load_file_from_memory(file_buffer,file_info->size,uri); @@ -105,17 +190,26 @@ fail_free_file_buffer: g_free(file_buffer); } -static void mod_uri_load_file_handle_remote_cabinet(GnomeVFSHandle *handle,GnomeVFSFileInfo *file_info,GnomeVFSURI *uri) +static void mod_uri_load_file_handle_remote_cabinet + (GnomeVFSHandle **handlep,GnomeVFSFileInfo *file_info,GnomeVFSURI *uri,gint cabinet_used) { struct acquire_cabinet *acquire_cabinet; - g_return_if_fail(handle!=NULL); + g_return_if_fail(handlep!=NULL); + g_return_if_fail(*handlep!=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=acquire_cabinet_new_from_handle(handlep,file_info,uri,cabinet_used); /* acquire_cabinet_load() will call mod_uri_load_module_from_memory(): */ acquire_cabinet_load(acquire_cabinet); + if (optarg_verbose) { +gchar *uri_text; + + uri_text=gnome_vfs_uri_to_string(uri,GNOME_VFS_URI_HIDE_PASSWORD); + g_message("cabinet_used: %s - %d",uri_text,acquire_cabinet->cabinet_done); + g_free(uri_text); + } acquire_cabinet_free(acquire_cabinet); } @@ -127,28 +221,39 @@ GnomeVFSHandle *handle; g_return_if_fail(uri!=NULL); - if (GNOME_VFS_OK!=(errvfsresult=gnome_vfs_open_uri(&handle,uri,GNOME_VFS_OPEN_READ))) + if (GNOME_VFS_OK!=(errvfsresult=gnome_vfs_open_uri(&handle,uri,GNOME_VFS_OPEN_READ|GNOME_VFS_OPEN_RANDOM))) goto fail; + CAPTIVE_MEMZERO(&file_info_local); 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) { + if (1 + && file_info_local.type!=GNOME_VFS_FILE_TYPE_REGULAR + /* FC4 gnome-vfs2-2.10.0-5 "http" returns GNOME_VFS_FILE_TYPE_UNKNOWN + * on the original info query so we need to try directory first. + */ + && file_info_local.type!=GNOME_VFS_FILE_TYPE_UNKNOWN) { errvfsresult=GNOME_VFS_ERROR_WRONG_FORMAT; - goto fail_close_handle; + goto fail_file_info_local_clear; } if (!(file_info_local.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE)) { errvfsresult=GNOME_VFS_ERROR_WRONG_FORMAT; - goto fail_close_handle; + goto fail_file_info_local_clear; } - if (!captivemodid_module_length_is_valid(file_info_local.size)) { + if (!captive_captivemodid_module_length_is_valid(captivemodid,file_info_local.size)) { errvfsresult=GNOME_VFS_ERROR_WRONG_FORMAT; - goto fail_close_handle; + goto fail_file_info_local_clear; } 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); + else { +gint cabinet_used=captive_captivemodid_cabinet_length_to_used(captivemodid,file_info_local.size); + + mod_uri_load_file_handle_remote_cabinet(&handle,&file_info_local,uri,cabinet_used); + } errvfsresult=GNOME_VFS_OK; /* PASSTHRU */ +fail_file_info_local_clear: + gnome_vfs_file_info_clear(&file_info_local); fail_close_handle: gnome_vfs_close(handle); fail:; @@ -165,11 +270,20 @@ static gboolean mod_uri_load_directory_visit_func *recurse=FALSE; + /* Do not: (*ui_progress)(root_uri); + * here as we are called with the same 'root_uri' for all of our 'rel_path's. + */ + (*ui_progress)(NULL); + switch (info->type) { case GNOME_VFS_FILE_TYPE_REGULAR: { GnomeVFSURI *file_uri; file_uri=gnome_vfs_uri_append_path(root_uri,rel_path); + if ((*ui_progress)(file_uri)) { + gnome_vfs_uri_unref(file_uri); + return FALSE; /* abort traversal */ + } mod_uri_load_file(file_uri); gnome_vfs_uri_unref(file_uri); } break; @@ -182,6 +296,10 @@ GnomeVFSDirectoryHandle *directory_handle; * Check the directory accessibility manually: */ directory_uri=gnome_vfs_uri_append_path(root_uri,rel_path); + if ((*ui_progress)(directory_uri)) { + gnome_vfs_uri_unref(directory_uri); + return FALSE; /* abort traversal */ + } 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 */ @@ -205,6 +323,13 @@ GnomeVFSResult errvfsresult; GNOME_VFS_DIRECTORY_VISIT_SAMEFS, /* visit_options; 'GNOME_VFS_DIRECTORY_VISIT_LOOPCHECK'? */ (GnomeVFSDirectoryVisitFunc)mod_uri_load_directory_visit_func, uri); /* data */ + /* FC4 gnome-vfs2-2.10.0-5 "http" returns GNOME_VFS_FILE_TYPE_UNKNOWN + * on the original info query so we need to try directory first. + */ + if (errvfsresult==GNOME_VFS_ERROR_NOT_A_DIRECTORY) { + mod_uri_load_file(uri); + return; + } if (errvfsresult!=GNOME_VFS_OK) { gchar *uri_text; @@ -214,7 +339,7 @@ gchar *uri_text; } } -void mod_uri_load(GnomeVFSURI *uri) +static void mod_uri_load_internal(GnomeVFSURI *uri,gboolean base_reporting) { GnomeVFSFileInfo file_info_local; GnomeVFSResult errvfsresult; @@ -229,13 +354,42 @@ gchar *uri_text; g_free(uri_text); } + CAPTIVE_MEMZERO(&file_info_local); 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 */; + if (GNOME_VFS_OK!=(errvfsresult=gnome_vfs_get_file_info_uri(uri,&file_info_local,GNOME_VFS_FILE_INFO_DEFAULT))) { + if (base_reporting) { +gchar *uri_text; + + uri_text=gnome_vfs_uri_to_string(uri,GNOME_VFS_URI_HIDE_PASSWORD); + g_warning(_("Error loading \"%s\": %s"),uri_text,gnome_vfs_result_to_string(errvfsresult)); + g_free(uri_text); + } + return; + } 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 */; + case GNOME_VFS_FILE_TYPE_REGULAR: mod_uri_load_file(uri); break; + case GNOME_VFS_FILE_TYPE_DIRECTORY: mod_uri_load_directory(uri); break; + /* FC4 gnome-vfs2-2.10.0-5 "http" returns GNOME_VFS_FILE_TYPE_UNKNOWN + * on the original info query so we need to try directory first. + */ + case GNOME_VFS_FILE_TYPE_UNKNOWN: mod_uri_load_directory(uri); break; + default: /* GNOME_VFS_ERROR_WRONG_FORMAT */; } - /* NOTREACHED */ + gnome_vfs_file_info_clear(&file_info_local); +} + +void mod_uri_load(GnomeVFSURI *uri) +{ + g_return_if_fail(uri!=NULL); + + mod_uri_load_internal(uri, + FALSE); /* base_reporting */ +} + +void mod_uri_load_base_reporting(GnomeVFSURI *uri) +{ + g_return_if_fail(uri!=NULL); + + mod_uri_load_internal(uri, + TRUE); /* base_reporting */ }