From: Eric Biggers Date: Sun, 24 Mar 2013 06:38:21 +0000 (-0500) Subject: Modify treatment of metadata entries X-Git-Tag: v1.3.2~14 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=f8698b9c814a62a117982701b9551f699553b2a4 Modify treatment of metadata entries Image order is actually determined by the order of metadata entries in the on-disk lookup table, not order of metadata resources in the WIM. However, do not insert the metadata entries into the actual lookup hash table, as they are treated specially. --- diff --git a/src/add_image.c b/src/add_image.c index 5f7a183c..4532a6cc 100644 --- a/src/add_image.c +++ b/src/add_image.c @@ -80,8 +80,6 @@ add_new_dentry_tree(WIMStruct *w, struct wim_dentry *root_dentry, goto err_free_imd; metadata_lte->resource_entry.flags = WIM_RESHDR_FLAG_METADATA; - random_hash(metadata_lte->hash); - lookup_table_insert(w->lookup_table, metadata_lte); new_imd = &imd[w->hdr.image_count]; diff --git a/src/dentry.c b/src/dentry.c index 4f9e9f7a..82a6b2d3 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -638,7 +638,7 @@ print_dentry(struct wim_dentry *dentry, void *lookup_table) hash = inode_stream_hash(inode, 0); if (hash) { tprintf(T("Hash = 0x")); - print_hash(hash); + print_hash(hash, stdout); tputchar(T('\n')); tputchar(T('\n')); } @@ -652,7 +652,7 @@ print_dentry(struct wim_dentry *dentry, void *lookup_table) hash = inode_stream_hash(inode, i + 1); if (hash) { tprintf(T("Hash = 0x")); - print_hash(hash); + print_hash(hash, stdout); tputchar(T('\n')); } print_lookup_table_entry(inode_stream_lte(inode, i + 1, lookup_table), diff --git a/src/header.c b/src/header.c index dd274ca0..bd2a0631 100644 --- a/src/header.c +++ b/src/header.c @@ -270,7 +270,7 @@ wimlib_print_header(const WIMStruct *w) tprintf(T("Chunk Size = %u\n"), WIM_CHUNK_SIZE); tfputs (T("GUID = "), stdout); - print_byte_field(hdr->guid, WIM_GID_LEN); + print_byte_field(hdr->guid, WIM_GID_LEN, stdout); tputchar(T('\n')); tprintf(T("Part Number = %hu\n"), w->hdr.part_number); tprintf(T("Total Parts = %hu\n"), w->hdr.total_parts); diff --git a/src/join.c b/src/join.c index 2902a61c..7d33eb89 100644 --- a/src/join.c +++ b/src/join.c @@ -114,9 +114,7 @@ join_wims(WIMStruct **swms, unsigned num_swms, progress_func(WIMLIB_PROGRESS_MSG_JOIN_STREAMS, &progress); } - /* Write the resources (streams and metadata resources) from each SWM - * part */ - swms[0]->write_metadata = true; + /* Write the non-metadata resources from each SWM part */ for (i = 0; i < num_swms; i++) { swms[i]->fp = tfopen(swms[i]->filename, T("rb")); if (!swms[i]->fp) { @@ -129,8 +127,11 @@ join_wims(WIMStruct **swms, unsigned num_swms, ret = for_lookup_table_entry(swms[i]->lookup_table, copy_resource, swms[i]); swms[i]->out_fp = NULL; - fclose(swms[i]->fp); - swms[i]->fp = NULL; + + if (i != 0) { + fclose(swms[i]->fp); + swms[i]->fp = NULL; + } if (ret != 0) return ret; @@ -142,14 +143,27 @@ join_wims(WIMStruct **swms, unsigned num_swms, } } + /* Write metadata resources from the first SWM part */ + swms[0]->out_fp = joined_wim->out_fp; + ret = for_image(swms[0], WIMLIB_ALL_IMAGES, write_metadata_resource); + swms[0]->out_fp = NULL; + fclose(swms[0]->fp); + swms[0]->fp = NULL; + + if (ret) + return ret; + + /* Write lookup table, XML data, and optional integrity table */ joined_wim->hdr.image_count = swms[0]->hdr.image_count; for (i = 0; i < num_swms; i++) lookup_table_join(joined_wim->lookup_table, swms[i]->lookup_table); free_wim_info(joined_wim->wim_info); joined_wim->wim_info = swms[0]->wim_info; + joined_wim->image_metadata = swms[0]->image_metadata; ret = finish_write(joined_wim, WIMLIB_ALL_IMAGES, write_flags, progress_func); joined_wim->wim_info = NULL; + joined_wim->image_metadata = NULL; return ret; } diff --git a/src/lookup_table.c b/src/lookup_table.c index bfa0c858..6370f038 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -264,6 +264,7 @@ for_lookup_table_entry(struct wim_lookup_table *table, hlist_for_each_entry_safe(lte, pos, tmp, &table->array[i], hash_list) { + wimlib_assert2(!(lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA)); ret = visitor(lte, arg); if (ret != 0) return ret; @@ -275,6 +276,10 @@ for_lookup_table_entry(struct wim_lookup_table *table, /* * Reads the lookup table from a WIM file. + * + * Saves lookup table entries for non-metadata streams in a hash table, and + * saves the metadata entry for each image in a special per-image location (the + * image_metadata array). */ int read_lookup_table(WIMStruct *w) @@ -283,7 +288,7 @@ read_lookup_table(WIMStruct *w) u8 buf[WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE]; int ret; struct wim_lookup_table *table; - struct wim_lookup_table_entry *cur_entry = NULL, *duplicate_entry; + struct wim_lookup_table_entry *cur_entry, *duplicate_entry; if (resource_is_compressed(&w->hdr.lookup_table_res_entry)) { ERROR("Didn't expect a compressed lookup table!"); @@ -309,6 +314,7 @@ read_lookup_table(WIMStruct *w) if (!table) return WIMLIB_ERR_NOMEM; + w->current_image = 0; while (num_entries--) { const u8 *p; @@ -320,16 +326,16 @@ read_lookup_table(WIMStruct *w) "table"); } ret = WIMLIB_ERR_READ; - goto out; + goto out_free_lookup_table; } cur_entry = new_lookup_table_entry(); if (!cur_entry) { ret = WIMLIB_ERR_NOMEM; - goto out; + goto out_free_lookup_table; } + cur_entry->wim = w; cur_entry->resource_location = RESOURCE_IN_WIM; - p = get_resource_entry(buf, &cur_entry->resource_entry); p = get_u16(p, &cur_entry->part_number); p = get_u32(p, &cur_entry->refcnt); @@ -350,27 +356,6 @@ read_lookup_table(WIMStruct *w) goto out_free_cur_entry; } - /* Ordinarily, no two streams should share the same SHA1 message - * digest. However, this constraint can be broken for metadata - * resources--- two identical images will have the same metadata - * resource, but their lookup table entries are not shared. */ - duplicate_entry = __lookup_resource(table, cur_entry->hash); - if (duplicate_entry - && !((duplicate_entry->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) - && cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_METADATA)) - { - #ifdef ENABLE_ERROR_MESSAGES - ERROR("The WIM lookup table contains two entries with the " - "same SHA1 message digest!"); - ERROR("The first entry is:"); - print_lookup_table_entry(duplicate_entry, stderr); - ERROR("The second entry is:"); - print_lookup_table_entry(cur_entry, stderr); - #endif - ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; - goto out_free_cur_entry; - } - if (!(cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) && (cur_entry->resource_entry.size != cur_entry->resource_entry.original_size)) @@ -384,26 +369,84 @@ read_lookup_table(WIMStruct *w) ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; goto out_free_cur_entry; } - if ((cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) - && cur_entry->refcnt != 1) - { - #ifdef ENABLE_ERROR_MESSAGES - ERROR("Found metadata resource with refcnt != 1:"); - print_lookup_table_entry(cur_entry, stderr); - #endif - ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; - goto out_free_cur_entry; + + if (cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) { + /* Lookup table entry for a metadata resource */ + if (cur_entry->refcnt != 1) { + #ifdef ENABLE_ERROR_MESSAGES + ERROR("Found metadata resource with refcnt != 1:"); + print_lookup_table_entry(cur_entry, stderr); + #endif + ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; + goto out_free_cur_entry; + } + + if (w->hdr.part_number != 1) { + ERROR("Found a metadata resource in a " + "non-first part of the split WIM!"); + ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; + goto out_free_cur_entry; + } + if (w->current_image == w->hdr.image_count) { + ERROR("The WIM header says there are %u images " + "in the WIM, but we found more metadata " + "resources than this", w->hdr.image_count); + ret = WIMLIB_ERR_IMAGE_COUNT; + goto out_free_cur_entry; + } + + /* Notice very carefully: We are assigning the metadata + * resources in the exact order mirrored by their lookup + * table entries on disk, which is the behavior of + * Microsoft's software. In particular, this overrides + * the actual locations of the metadata resources + * themselves in the WIM file as well as any information + * written in the XML data. */ + DEBUG("Found metadata resource for image %u at " + "offset %"PRIu64".", + w->current_image + 1, + cur_entry->resource_entry.offset); + w->image_metadata[ + w->current_image++].metadata_lte = cur_entry; + } else { + /* Lookup table entry for a stream that is not a + * metadata resource */ + duplicate_entry = __lookup_resource(table, cur_entry->hash); + if (duplicate_entry) { + #ifdef ENABLE_ERROR_MESSAGES + ERROR("The WIM lookup table contains two entries with the " + "same SHA1 message digest!"); + ERROR("The first entry is:"); + print_lookup_table_entry(duplicate_entry, stderr); + ERROR("The second entry is:"); + print_lookup_table_entry(cur_entry, stderr); + #endif + ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; + goto out_free_cur_entry; + } + lookup_table_insert(table, cur_entry); } - lookup_table_insert(table, cur_entry); + } + if (w->hdr.part_number == 1 && + w->current_image != w->hdr.image_count) + { + ERROR("The WIM header says there are %u images " + "in the WIM, but we only found %d metadata " + "resources!", w->hdr.image_count, w->current_image); + ret = WIMLIB_ERR_IMAGE_COUNT; + goto out_free_lookup_table; } DEBUG("Done reading lookup table."); w->lookup_table = table; - return 0; + ret = 0; + goto out; out_free_cur_entry: FREE(cur_entry); -out: +out_free_lookup_table: free_lookup_table(table); +out: + w->current_image = 0; return ret; } @@ -412,13 +455,13 @@ out: * Writes a lookup table entry to the output file. */ int -write_lookup_table_entry(struct wim_lookup_table_entry *lte, void *__out) +write_lookup_table_entry(struct wim_lookup_table_entry *lte, void *_out) { FILE *out; u8 buf[WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE]; u8 *p; - out = __out; + out = _out; /* Don't write entries that have not had file resources or metadata * resources written for them. */ @@ -442,20 +485,39 @@ write_lookup_table_entry(struct wim_lookup_table_entry *lte, void *__out) return 0; } -/* Writes the lookup table to the output file. */ +/* Writes the WIM lookup table to the output file. */ int -write_lookup_table(struct wim_lookup_table *table, FILE *out, - struct resource_entry *out_res_entry) +write_lookup_table(WIMStruct *w, int image, struct resource_entry *out_res_entry) { + FILE *out = w->out_fp; off_t start_offset, end_offset; int ret; + int start_image, end_image; start_offset = ftello(out); if (start_offset == -1) return WIMLIB_ERR_WRITE; - ret = for_lookup_table_entry(table, write_lookup_table_entry, out); - if (ret != 0) + if (image == WIMLIB_ALL_IMAGES) { + start_image = 1; + end_image = w->hdr.image_count; + } else { + start_image = image; + end_image = image; + } + for (int i = start_image; i <= end_image; i++) { + struct wim_lookup_table_entry *metadata_lte; + + metadata_lte = w->image_metadata[i - 1].metadata_lte; + metadata_lte->out_refcnt = 1; + metadata_lte->output_resource_entry.flags |= WIM_RESHDR_FLAG_METADATA; + ret = write_lookup_table_entry(metadata_lte, out); + if (ret) + return ret; + } + + ret = for_lookup_table_entry(w->lookup_table, write_lookup_table_entry, out); + if (ret) return ret; end_offset = ftello(out); @@ -466,7 +528,6 @@ write_lookup_table(struct wim_lookup_table *table, FILE *out, out_res_entry->size = end_offset - start_offset; out_res_entry->original_size = end_offset - start_offset; out_res_entry->flags = WIM_RESHDR_FLAG_METADATA; - return 0; } @@ -515,7 +576,7 @@ print_lookup_table_entry(const struct wim_lookup_table_entry *lte, FILE *out) tfprintf(out, T("Reference Count = %u\n"), lte->refcnt); tfprintf(out, T("Hash = 0x")); - print_hash(lte->hash); + print_hash(lte->hash, out); tputc(T('\n'), out); tfprintf(out, T("Flags = ")); diff --git a/src/lookup_table.h b/src/lookup_table.h index 78de61a3..dad230f7 100644 --- a/src/lookup_table.h +++ b/src/lookup_table.h @@ -261,8 +261,8 @@ extern int read_lookup_table(WIMStruct *w); extern int -write_lookup_table(struct wim_lookup_table *table, FILE *out, - struct resource_entry *out_res_entry); +write_lookup_table(WIMStruct *w, int image, struct resource_entry *out_res_entry); + extern void free_lookup_table(struct wim_lookup_table *table); diff --git a/src/metadata_resource.c b/src/metadata_resource.c index a2ae93c6..db35ba64 100644 --- a/src/metadata_resource.c +++ b/src/metadata_resource.c @@ -236,9 +236,13 @@ write_metadata_resource(WIMStruct *w) u64 metadata_original_size; struct wim_security_data *sd; + wimlib_assert(w->out_fp != NULL); + wimlib_assert(w->current_image != WIMLIB_NO_IMAGE); + DEBUG("Writing metadata resource for image %d (offset = %"PRIu64")", w->current_image, ftello(w->out_fp)); + root = wim_root_dentry(w); sd = wim_security_data(w); @@ -292,22 +296,11 @@ write_metadata_resource(WIMStruct *w) if (ret != 0) goto out; - /* It's very likely the SHA1 message digest of the metadata resource - * changed, so re-insert the lookup table entry into the lookup table. - * - * We do not check for other lookup table entries having the same SHA1 - * message digest. It's possible for 2 absolutely identical images to - * be added, therefore causing 2 identical metadata resources to be in - * the WIM. However, in this case, it's expected for 2 separate lookup - * table entries to be created, even though this doesn't make a whole - * lot of sense since they will share the same SHA1 message digest. - * */ - lookup_table_unlink(w->lookup_table, lte); - lookup_table_insert(w->lookup_table, lte); + /* Note that although the SHA1 message digest of the metadata resource + * is very likely to have changed, the corresponding lookup table entry + * is not actually located in the hash table, so it need not be + * re-inserted in the hash table. */ lte->out_refcnt = 1; - - /* Make sure that the lookup table entry for this metadata resource is - * marked with the metadata flag. */ lte->output_resource_entry.flags |= WIM_RESHDR_FLAG_METADATA; out: /* All the data has been written to the new WIM; no need for the buffer diff --git a/src/resource.c b/src/resource.c index d3380caf..7df50e72 100644 --- a/src/resource.c +++ b/src/resource.c @@ -730,16 +730,12 @@ copy_resource(struct wim_lookup_table_entry *lte, void *wim) WIMStruct *w = wim; int ret; - if ((lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) && - !w->write_metadata) - return 0; - ret = write_wim_resource(lte, w->out_fp, wim_resource_compression_type(lte), <e->output_resource_entry, 0); - if (ret != 0) - return ret; - lte->out_refcnt = lte->refcnt; - lte->part_number = w->hdr.part_number; - return 0; + if (ret == 0) { + lte->out_refcnt = lte->refcnt; + lte->part_number = w->hdr.part_number; + } + return ret; } diff --git a/src/security.c b/src/security.c index 7efc542b..37b9a063 100644 --- a/src/security.c +++ b/src/security.c @@ -375,7 +375,7 @@ print_sid(const void *p, const tchar *type) tprintf(T(" Subauthority count = %u\n"), sid->sub_authority_count); tprintf(T(" Identifier authority = ")); print_byte_field(sid->identifier_authority, - sizeof(sid->identifier_authority)); + sizeof(sid->identifier_authority), stdout); tputchar(T('\n')); for (u8 i = 0; i < sid->sub_authority_count; i++) { tprintf(T(" Subauthority %u = %u\n"), diff --git a/src/sha1.h b/src/sha1.h index 6a3406a8..5c231e37 100644 --- a/src/sha1.h +++ b/src/sha1.h @@ -37,9 +37,9 @@ hashes_cmp(const u8 h1[SHA1_HASH_SIZE], } static inline void -print_hash(const u8 hash[SHA1_HASH_SIZE]) +print_hash(const u8 hash[SHA1_HASH_SIZE], FILE *out) { - print_byte_field(hash, SHA1_HASH_SIZE); + print_byte_field(hash, SHA1_HASH_SIZE, out); } static inline bool diff --git a/src/split.c b/src/split.c index 71b32cef..6054d368 100644 --- a/src/split.c +++ b/src/split.c @@ -119,7 +119,7 @@ copy_resource_to_swm(struct wim_lookup_table_entry *lte, void *__args) } args->size_remaining -= lte->resource_entry.size; args->progress.split.completed_bytes += lte->resource_entry.size; - list_add(<e->staging_list, &args->lte_list); + list_add_tail(<e->staging_list, &args->lte_list); return copy_resource(lte, w); } @@ -187,7 +187,6 @@ wimlib_split(WIMStruct *w, const tchar *swm_name, &args.progress); } - w->write_metadata = true; for (int i = 0; i < w->hdr.image_count; i++) { struct wim_lookup_table_entry *metadata_lte; metadata_lte = w->image_metadata[i].metadata_lte; @@ -196,9 +195,10 @@ wimlib_split(WIMStruct *w, const tchar *swm_name, goto out; args.size_remaining -= metadata_lte->resource_entry.size; args.progress.split.completed_bytes += metadata_lte->resource_entry.size; - list_add(&metadata_lte->staging_list, &args.lte_list); + /* Careful: The metadata lookup table entries must be added in + * order of the images. */ + list_add_tail(&metadata_lte->staging_list, &args.lte_list); } - w->write_metadata = false; ret = for_lookup_table_entry(w->lookup_table, copy_resource_to_swm, &args); diff --git a/src/util.h b/src/util.h index 4b75eda2..06c5045d 100644 --- a/src/util.h +++ b/src/util.h @@ -243,10 +243,10 @@ extern const tchar * path_stream_name(const tchar *path); static inline void -print_byte_field(const u8 field[], size_t len) +print_byte_field(const u8 field[], size_t len, FILE *out) { while (len--) - tprintf(T("%02hhx"), *field++); + tfprintf(out, T("%02hhx"), *field++); } static inline u32 diff --git a/src/verify.c b/src/verify.c index fc566633..201132ae 100644 --- a/src/verify.c +++ b/src/verify.c @@ -214,10 +214,11 @@ wim_run_full_verifications(WIMStruct *w) int ret; for_lookup_table_entry(w->lookup_table, lte_zero_real_refcnt, NULL); + + w->all_images_verified = 1; /* Set *before* image_run_full_verifications, + because of check in read_metadata_resource() */ ret = for_image(w, WIMLIB_ALL_IMAGES, image_run_full_verifications); if (ret == 0) { - w->all_images_verified = 1; - unsigned long num_ltes_with_bogus_refcnt = 0; for (int i = 0; i < w->hdr.image_count; i++) w->image_metadata[i].metadata_lte->real_refcnt++; @@ -229,6 +230,8 @@ wim_run_full_verifications(WIMStruct *w) " their reference counts fixed.", num_ltes_with_bogus_refcnt); } + } else { + w->all_images_verified = 0; } return ret; } diff --git a/src/wim.c b/src/wim.c index f2794fe8..67b840ce 100644 --- a/src/wim.c +++ b/src/wim.c @@ -115,49 +115,6 @@ for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *)) return 0; } -static int -sort_image_metadata_by_position(const void *p1, const void *p2) -{ - const struct wim_image_metadata *imd1 = p1; - const struct wim_image_metadata *imd2 = p2; - u64 offset1 = imd1->metadata_lte->resource_entry.offset; - u64 offset2 = imd2->metadata_lte->resource_entry.offset; - if (offset1 < offset2) - return -1; - else if (offset1 > offset2) - return 1; - else - return 0; -} - -/* - * If @lte points to a metadata resource, append it to the list of metadata - * resources in the WIMStruct. Otherwise, do nothing. - */ -static int -append_metadata_resource_entry(struct wim_lookup_table_entry *lte, void *wim_p) -{ - WIMStruct *w = wim_p; - int ret = 0; - - if (lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) { - if (w->current_image == w->hdr.image_count) { - ERROR("The WIM header says there are %u images in the WIM,\n" - " but we found more metadata resources than this", - w->hdr.image_count); - ret = WIMLIB_ERR_IMAGE_COUNT; - } else { - DEBUG("Found metadata resource for image %u at " - "offset %"PRIu64".", - w->current_image + 1, - lte->resource_entry.offset); - w->image_metadata[ - w->current_image++].metadata_lte = lte; - } - } - return ret; -} - /* Returns the compression type given in the flags of a WIM header. */ static int wim_hdr_flags_compression_type(int wim_hdr_flags) @@ -257,7 +214,7 @@ select_wim_image(WIMStruct *w, int image) #ifdef ENABLE_DEBUG DEBUG("Reading metadata resource specified by the following " "lookup table entry:"); - print_lookup_table_entry(imd->metadata_lte, stdout); + print_lookup_table_entry(imd->metadata_lte, stderr); #endif ret = read_metadata_resource(w, imd); if (ret) @@ -333,7 +290,7 @@ wimlib_print_wim_information(const WIMStruct *w) tputs(T("----------------")); tprintf(T("Path: %"TS"\n"), w->filename); tfputs(T("GUID: 0x"), stdout); - print_byte_field(hdr->guid, WIM_GID_LEN); + print_byte_field(hdr->guid, WIM_GID_LEN, stdout); tputchar(T('\n')); tprintf(T("Image Count: %d\n"), hdr->image_count); tprintf(T("Compression: %"TS"\n"), @@ -489,7 +446,7 @@ begin_read(WIMStruct *w, const tchar *in_wim_path, int open_flags, } ret = read_header(w->fp, &w->hdr, open_flags); - if (ret != 0) + if (ret) return ret; DEBUG("According to header, WIM contains %u images", w->hdr.image_count); @@ -521,11 +478,7 @@ begin_read(WIMStruct *w, const tchar *in_wim_path, int open_flags, } } - ret = read_lookup_table(w); - if (ret != 0) - return ret; - - if (w->hdr.image_count != 0) { + if (w->hdr.image_count != 0 && w->hdr.part_number == 1) { w->image_metadata = CALLOC(w->hdr.image_count, sizeof(struct wim_image_metadata)); @@ -535,41 +488,14 @@ begin_read(WIMStruct *w, const tchar *in_wim_path, int open_flags, return WIMLIB_ERR_NOMEM; } } - w->current_image = 0; - - DEBUG("Looking for metadata resources in the lookup table."); - /* Find the images in the WIM by searching the lookup table. */ - ret = for_lookup_table_entry(w->lookup_table, - append_metadata_resource_entry, w); - - if (ret != 0) + ret = read_lookup_table(w); + if (ret) return ret; - /* Make sure all the expected images were found. (We already have - * returned WIMLIB_ERR_IMAGE_COUNT if *extra* images were found) */ - if (w->current_image != w->hdr.image_count && - w->hdr.part_number == 1) - { - ERROR("Only found %d images in WIM, but expected %u", - w->current_image, w->hdr.image_count); - return WIMLIB_ERR_IMAGE_COUNT; - } - - /* Sort images by the position of their metadata resources. I'm - * assuming that is what determines the other of the images in the WIM - * file, rather than their order in the lookup table, which is random - * because of hashing. */ - qsort(w->image_metadata, w->current_image, - sizeof(struct wim_image_metadata), sort_image_metadata_by_position); - - w->current_image = WIMLIB_NO_IMAGE; - - /* Read the XML data. */ ret = read_xml_data(w->fp, &w->hdr.xml_res_entry, &w->xml_data, &w->wim_info); - - if (ret != 0) + if (ret) return ret; xml_num_images = wim_info_get_num_images(w->wim_info); @@ -617,13 +543,8 @@ destroy_image_metadata(struct wim_image_metadata *imd, { free_dentry_tree(imd->root_dentry, table); free_security_data(imd->security_data); - - /* Get rid of the lookup table entry for this image's metadata resource - * */ - if (table) { - lookup_table_unlink(table, imd->metadata_lte); + if (table) free_lookup_table_entry(imd->metadata_lte); - } } /* Frees the memory for the WIMStruct, including all internal memory; also @@ -656,8 +577,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++) + 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); + } FREE(w->image_metadata); } #ifdef WITH_NTFS_3G diff --git a/src/wimlib_internal.h b/src/wimlib_internal.h index a5564b48..7f2b914b 100644 --- a/src/wimlib_internal.h +++ b/src/wimlib_internal.h @@ -300,11 +300,9 @@ struct WIMStruct { /* The header of the WIM file. */ struct wim_header hdr; - /* Temporary fields */ - union { - bool write_metadata; - void *private; - }; + /* Temporary field */ + void *private; + #ifdef WITH_NTFS_3G struct _ntfs_volume *ntfs_vol; #endif diff --git a/src/write.c b/src/write.c index 6a07c44e..3fc9451d 100644 --- a/src/write.c +++ b/src/write.c @@ -1440,24 +1440,29 @@ lte_overwrite_prepare(struct wim_lookup_table_entry *lte, void *arg) lte->out_refcnt = lte->refcnt; memcpy(<e->output_resource_entry, <e->resource_entry, sizeof(struct resource_entry)); - if (!(lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA)) { - wimlib_assert(lte->resource_location != RESOURCE_NONEXISTENT); + if (!(lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA)) if (lte->resource_location != RESOURCE_IN_WIM || lte->wim != args->wim) list_add(<e->staging_list, args->stream_list); - } return 0; } static int -wim_find_new_streams(WIMStruct *wim, off_t end_offset, - struct list_head *stream_list) +wim_prepare_streams(WIMStruct *wim, off_t end_offset, + struct list_head *stream_list) { struct lte_overwrite_prepare_args args = { .wim = wim, .end_offset = end_offset, .stream_list = stream_list, }; + int ret; + for (int i = 0; i < wim->hdr.image_count; i++) { + ret = lte_overwrite_prepare(wim->image_metadata[i].metadata_lte, + &args); + if (ret) + return ret; + } return for_lookup_table_entry(wim->lookup_table, lte_overwrite_prepare, &args); } @@ -1553,7 +1558,7 @@ finish_write(WIMStruct *w, int image, int write_flags, memcpy(&hdr, &w->hdr, sizeof(struct wim_header)); if (!(write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE)) { - ret = write_lookup_table(w->lookup_table, out, &hdr.lookup_table_res_entry); + ret = write_lookup_table(w, image, &hdr.lookup_table_res_entry); if (ret != 0) goto out; } @@ -1902,7 +1907,7 @@ overwrite_wim_inplace(WIMStruct *w, int write_flags, WIMLIB_WRITE_FLAG_CHECKPOINT_AFTER_XML; } INIT_LIST_HEAD(&stream_list); - ret = wim_find_new_streams(w, old_wim_end, &stream_list); + ret = wim_prepare_streams(w, old_wim_end, &stream_list); if (ret != 0) return ret;