X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fwim.c;h=25b5c3367d9e2bd7421b6889a2234f22333756a4;hp=67b840cea209dcf68b0281164e2ff77fc75766a1;hb=394c5bd3292c0f3168416c0a5f25989e557b3cfc;hpb=f8698b9c814a62a117982701b9551f699553b2a4 diff --git a/src/wim.c b/src/wim.c index 67b840ce..25b5c336 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 @@ -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 { @@ -255,7 +248,7 @@ WIMLIBAPI int wimlib_resolve_image(WIMStruct *w, const tchar *image_name_or_num) { tchar *p; - int image; + long image; int i; if (!image_name_or_num || !*image_name_or_num) @@ -271,8 +264,8 @@ wimlib_resolve_image(WIMStruct *w, const tchar *image_name_or_num) return image; } else { for (i = 1; i <= w->hdr.image_count; i++) { - if (tstrcmp(image_name_or_num, - wimlib_get_image_name(w, i)) == 0) + if (!tstrcmp(image_name_or_num, + wimlib_get_image_name(w, i))) return i; } return WIMLIB_NO_IMAGE; @@ -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,127 @@ 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; + list_for_each_entry_safe(lte, tmp, + &w->image_metadata[i]->unhashed_streams, + unhashed_list) + { + 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 +669,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"); } @@ -596,15 +680,19 @@ wimlib_free(WIMStruct *w) static bool test_locale_ctype_utf8() { +#ifdef __WIN32__ + return false; +#else char *ctype = nl_langinfo(CODESET); return (!strstr(ctype, "UTF-8") || !strstr(ctype, "UTF8") || !strstr(ctype, "utf8") || !strstr(ctype, "utf-8")); +#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()