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 5f7a183..4532a6c 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 4f9e9f7..82a6b2d 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 dd274ca..bd2a063 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 2902a61..7d33eb8 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 bfa0c85..6370f03 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 78de61a..dad230f 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 a2ae93c..db35ba6 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 d3380ca..7df50e7 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 7efc542..37b9a06 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 6a3406a..5c231e3 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 71b32ce..6054d36 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 4b75eda..06c5045 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 fc56663..201132a 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 f2794fe..67b840c 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 a5564b4..7f2b914 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 6a07c44..3fc9451 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;