X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fwim.c;h=342281d382fed08bf7ed461bcf2c611fb90a912c;hp=9a20cc5756969e2642cc0ba7e01fd6b91756541f;hb=2af95e7dc313e9abaf571034c3e86f32503bf232;hpb=32844c59e618cfaf1999e81e32b5e18fcb13a5b9 diff --git a/src/wim.c b/src/wim.c index 9a20cc57..342281d3 100644 --- a/src/wim.c +++ b/src/wim.c @@ -32,11 +32,6 @@ #include #include -#ifdef WITH_NTFS_3G -# include -# include -#endif - #ifdef __WIN32__ # include "win32.h" #else @@ -70,7 +65,7 @@ static WIMStruct * new_wim_struct() { WIMStruct *w = CALLOC(1, sizeof(WIMStruct)); -#ifdef WITH_FUSE +#if defined(WITH_FUSE) || defined(ENABLE_MULTITHREADED_COMPRESSION) if (pthread_mutex_init(&w->fp_tab_mutex, NULL) != 0) { ERROR_WITH_ERRNO("Failed to initialize mutex"); FREE(w); @@ -199,15 +194,13 @@ select_wim_image(WIMStruct *w, int image) if (w->current_image != WIMLIB_NO_IMAGE) { imd = wim_get_current_image_metadata(w); if (!imd->modified) { + wimlib_assert(list_empty(&imd->unhashed_streams)); DEBUG("Freeing image %u", w->current_image); - destroy_image_metadata(imd, NULL); - imd->root_dentry = NULL; - imd->security_data = NULL; - INIT_HLIST_HEAD(&imd->inode_list); + destroy_image_metadata(imd, NULL, false); } } w->current_image = image; - imd = &w->image_metadata[image - 1]; + imd = wim_get_current_image_metadata(w); if (imd->root_dentry) { ret = 0; } else { @@ -375,17 +368,6 @@ wimlib_set_boot_idx(WIMStruct *w, int boot_idx) if (boot_idx < 0 || boot_idx > w->hdr.image_count) return WIMLIB_ERR_INVALID_IMAGE; w->hdr.boot_idx = boot_idx; - - if (boot_idx == 0) { - memset(&w->hdr.boot_metadata_res_entry, 0, - sizeof(struct resource_entry)); - } else { - memcpy(&w->hdr.boot_metadata_res_entry, - &w->image_metadata[ - boot_idx - 1].metadata_lte->resource_entry, - sizeof(struct resource_entry)); - } - return 0; } @@ -479,14 +461,9 @@ begin_read(WIMStruct *w, const tchar *in_wim_path, int open_flags, } if (w->hdr.image_count != 0 && w->hdr.part_number == 1) { - w->image_metadata = CALLOC(w->hdr.image_count, - sizeof(struct wim_image_metadata)); - - if (!w->image_metadata) { - ERROR("Failed to allocate memory for %u image metadata structures", - w->hdr.image_count); + w->image_metadata = new_image_metadata_array(w->hdr.image_count); + if (!w->image_metadata) return WIMLIB_ERR_NOMEM; - } } ret = read_lookup_table(w); @@ -539,12 +516,125 @@ wimlib_open_wim(const tchar *wim_file, int open_flags, void destroy_image_metadata(struct wim_image_metadata *imd, - struct wim_lookup_table *table) + struct wim_lookup_table *table, + bool free_metadata_lte) { free_dentry_tree(imd->root_dentry, table); + imd->root_dentry = NULL; free_security_data(imd->security_data); - if (table) + imd->security_data = NULL; + + if (free_metadata_lte) { free_lookup_table_entry(imd->metadata_lte); + imd->metadata_lte = NULL; + } + if (!table) { + struct wim_lookup_table_entry *lte, *tmp; + list_for_each_entry_safe(lte, tmp, &imd->unhashed_streams, unhashed_list) + free_lookup_table_entry(lte); + } + INIT_LIST_HEAD(&imd->unhashed_streams); + INIT_LIST_HEAD(&imd->inode_list); +#ifdef WITH_NTFS_3G + if (imd->ntfs_vol) { + do_ntfs_umount(imd->ntfs_vol); + imd->ntfs_vol = NULL; + } +#endif +} + +void +put_image_metadata(struct wim_image_metadata *imd, + struct wim_lookup_table *table) +{ + if (imd && --imd->refcnt == 0) { + destroy_image_metadata(imd, table, true); + FREE(imd); + } +} + +/* Appends the specified image metadata structure to the array of image metadata + * for a WIM, and increments the image count. */ +int +append_image_metadata(WIMStruct *w, struct wim_image_metadata *imd) +{ + struct wim_image_metadata **imd_array; + + DEBUG("Reallocating image metadata array for image_count = %u", + w->hdr.image_count + 1); + imd_array = REALLOC(w->image_metadata, + sizeof(w->image_metadata[0]) * (w->hdr.image_count + 1)); + + if (!imd_array) + return WIMLIB_ERR_NOMEM; + w->image_metadata = imd_array; + imd_array[w->hdr.image_count++] = imd; + return 0; +} + + +struct wim_image_metadata * +new_image_metadata() +{ + struct wim_image_metadata *imd; + + imd = CALLOC(1, sizeof(*imd)); + if (imd) { + imd->refcnt = 1; + INIT_LIST_HEAD(&imd->inode_list); + INIT_LIST_HEAD(&imd->unhashed_streams); + DEBUG("Created new image metadata (refcnt=1)"); + } else { + ERROR_WITH_ERRNO("Failed to allocate new image metadata structure"); + } + return imd; +} + +struct wim_image_metadata ** +new_image_metadata_array(unsigned num_images) +{ + struct wim_image_metadata **imd_array; + + DEBUG("Creating new image metadata array for %u images", + num_images); + + imd_array = CALLOC(num_images, sizeof(imd_array[0])); + + if (!imd_array) { + ERROR("Failed to allocate memory for %u image metadata structures", + num_images); + return NULL; + } + for (unsigned i = 0; i < num_images; i++) { + imd_array[i] = new_image_metadata(); + if (!imd_array[i]) { + for (unsigned j = 0; j < i; j++) + put_image_metadata(imd_array[j], NULL); + FREE(imd_array); + return NULL; + } + } + return imd_array; +} + +/* Checksum all streams that are unhashed (other than the metadata streams), + * merging them into the lookup table as needed. This is a no-op unless the + * library has previously used to add or mount an image using the same + * WIMStruct. */ +int +wim_checksum_unhashed_streams(WIMStruct *w) +{ + int ret; + for (int i = 0; i < w->hdr.image_count; i++) { + struct wim_lookup_table_entry *lte, *tmp; + struct wim_image_metadata *imd = w->image_metadata[i]; + image_for_each_unhashed_stream_safe(lte, tmp, imd) { + ret = hash_unhashed_stream(lte, w->lookup_table, NULL); + if (ret) + return ret; + } + } + return 0; } /* Frees the memory for the WIMStruct, including all internal memory; also @@ -577,18 +667,10 @@ wimlib_free(WIMStruct *w) FREE(w->xml_data); free_wim_info(w->wim_info); if (w->image_metadata) { - for (unsigned i = 0; i < w->hdr.image_count; i++) { - destroy_image_metadata(&w->image_metadata[i], NULL); - free_lookup_table_entry(w->image_metadata[i].metadata_lte); - } + for (unsigned i = 0; i < w->hdr.image_count; i++) + put_image_metadata(w->image_metadata[i], NULL); FREE(w->image_metadata); } -#ifdef WITH_NTFS_3G - if (w->ntfs_vol) { - DEBUG("Unmounting NTFS volume"); - ntfs_umount(w->ntfs_vol, FALSE); - } -#endif FREE(w); DEBUG("Freed WIMStruct"); } @@ -608,7 +690,7 @@ test_locale_ctype_utf8() #endif } -/* Get global memory allocations out of the way, +/* Get global memory allocations out of the way, * single-threaded programs like 'imagex'. */ WIMLIBAPI int wimlib_global_init()