]> wimlib.net Git - wimlib/commitdiff
Modify treatment of metadata entries
authorEric Biggers <ebiggers3@gmail.com>
Sun, 24 Mar 2013 06:38:21 +0000 (01:38 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 24 Mar 2013 06:38:21 +0000 (01:38 -0500)
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.

16 files changed:
src/add_image.c
src/dentry.c
src/header.c
src/join.c
src/lookup_table.c
src/lookup_table.h
src/metadata_resource.c
src/resource.c
src/security.c
src/sha1.h
src/split.c
src/util.h
src/verify.c
src/wim.c
src/wimlib_internal.h
src/write.c

index 5f7a183c9079885bb7b3b4f8b1eccd048c428e25..4532a6cc316da2f7de6134c8f2924442f67f014e 100644 (file)
@@ -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];
 
index 4f9e9f7a7aca69682eeb2c69f5fa4546bf3720aa..82a6b2d306778a8dde6e41e11318d82eca739c6e 100644 (file)
@@ -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),
index dd274ca025247f48885cd450c67caeb4621a3f21..bd2a0631ea31460eb57daef87af9c22c34d1ce0f 100644 (file)
@@ -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);
index 2902a61cae68c86acc5fb134f327a982b2cb3403..7d33eb895e54b7ee0945cf569f19ed7d6fd41ec0 100644 (file)
@@ -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;
 }
 
index bfa0c858c4ddea8a84842f630377fb94a3c5ddc7..6370f03873440edf83e634bc7264a0a5b1d4ca67 100644 (file)
@@ -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             = "));
index 78de61a3f523e06c1d9c6331644fba98d7d74a1b..dad230f7ad58ab3443ad66dbd207e758c9aee05c 100644 (file)
@@ -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);
 
index a2ae93c6111eaaba7e03369dd16e81058b63ce9f..db35ba649cfc15581fef8c9de2489f7e13607822 100644 (file)
@@ -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
index d3380caf66a7380fa9d9b7b5344539b9663f6d51..7df50e727ab7eeb1c240d0afbafe0a880a5ea4bd 100644 (file)
@@ -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),
                                 &lte->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;
 }
index 7efc542b1e1de80a58dde1b8cf688cc170798782..37b9a063cfe5bec6d4793fe2586a54427f5654fc 100644 (file)
@@ -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"),
index 6a3406a8e443fc4862ce7afc5c2351b17e0cd3ec..5c231e378ea6d02f82bbebcfaf5e2237b7d9e682 100644 (file)
@@ -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
index 71b32cefe95ed31f60283b409e9851f12dacc6cd..6054d368a7f8a706ec7d0977138dac22643c97e0 100644 (file)
@@ -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(&lte->staging_list, &args->lte_list);
+       list_add_tail(&lte->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);
index 4b75eda2c98001a515101d8a7e9c398250292925..06c5045d0318f620f0f7c5e46726ebe1d1c1bfa6 100644 (file)
@@ -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
index fc5666337b7e4c201f717f59d0ee8d06332dbf50..201132aec51f91cecd980b2a3d4773a88086d271 100644 (file)
@@ -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;
 }
index f2794fe86c61047b09a3ba6735b7c49828dbb81c..67b840cea209dcf68b0281164e2ff77fc75766a1 100644 (file)
--- 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
index a5564b488502e6891adf6671d4c2d3bb5ba52298..7f2b914bfc23d017d610de633b01725f23b9e3e0 100644 (file)
@@ -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
index 6a07c44ed3aeae03b20f0ad85e76a7481eff8354..3fc9451d0effab99d127ee7fcec704c43ff4f69f 100644 (file)
@@ -1440,24 +1440,29 @@ lte_overwrite_prepare(struct wim_lookup_table_entry *lte, void *arg)
        lte->out_refcnt = lte->refcnt;
        memcpy(&lte->output_resource_entry, &lte->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(&lte->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;