+ /* Found the specification for the packed resource.
+ * Transfer the values to the `struct
+ * wim_resource_spec', and discard the current stream
+ * since this lookup table entry did not, in fact,
+ * correspond to a "stream". */
+
+ cur_rspec->offset_in_wim = reshdr.offset_in_wim;
+ cur_rspec->size_in_wim = reshdr.size_in_wim;
+ cur_rspec->flags = reshdr.flags;
+ DEBUG("Full pack is %"PRIu64" compressed bytes "
+ "at file offset %"PRIu64" (flags 0x%02x)",
+ cur_rspec->size_in_wim,
+ cur_rspec->offset_in_wim,
+ cur_rspec->flags);
+ free_lookup_table_entry(cur_entry);
+ continue;
+ }
+
+ if (is_zero_hash(cur_entry->hash)) {
+ free_lookup_table_entry(cur_entry);
+ continue;
+ }
+
+ if (reshdr.flags & WIM_RESHDR_FLAG_PACKED_STREAMS) {
+ /* Continuing the pack with another stream. */
+ DEBUG("Continuing packed run with stream: "
+ "%"PRIu64" uncompressed bytes @ resource offset %"PRIu64")",
+ reshdr.size_in_wim, reshdr.offset_in_wim);
+ cur_rspec->uncompressed_size += reshdr.size_in_wim;
+ }
+
+ lte_bind_wim_resource_spec(cur_entry, cur_rspec);
+ if (reshdr.flags & WIM_RESHDR_FLAG_PACKED_STREAMS) {
+ /* In packed runs, the offset field is used for
+ * in-resource offset, not the in-WIM offset, and the
+ * size field is used for the uncompressed size, not the
+ * compressed size. */
+ cur_entry->offset_in_res = reshdr.offset_in_wim;
+ cur_entry->size = reshdr.size_in_wim;
+ cur_entry->flags = reshdr.flags;
+ } else {
+ /* Normal case: The stream corresponds one-to-one with
+ * the resource entry. */
+ cur_entry->offset_in_res = 0;
+ cur_entry->size = reshdr.uncompressed_size;
+ cur_entry->flags = reshdr.flags;
+ cur_rspec = NULL;
+ }
+
+ if (cur_entry->flags & WIM_RESHDR_FLAG_METADATA) {
+ /* Lookup table entry for a metadata resource */
+
+ /* Metadata entries with no references must be ignored;
+ * see for example the WinPE WIMs from the WAIK v2.1.
+ * */
+ if (cur_entry->refcnt == 0) {
+ free_lookup_table_entry(cur_entry);
+ continue;
+ }
+
+ if (cur_entry->refcnt != 1) {
+ if (wimlib_print_errors) {
+ ERROR("Found metadata resource with refcnt != 1:");
+ print_lookup_table_entry(cur_entry, stderr);
+ }
+ ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
+ goto out_free_cur_entry;
+ }
+
+ if (wim->hdr.part_number != 1) {
+ WARNING("Ignoring metadata resource found in a "
+ "non-first part of the split WIM");
+ free_lookup_table_entry(cur_entry);
+ continue;
+ }
+ if (wim->current_image == wim->hdr.image_count) {
+ WARNING("The WIM header says there are %u images "
+ "in the WIM, but we found more metadata "
+ "resources than this (ignoring the extra)",
+ wim->hdr.image_count);
+ free_lookup_table_entry(cur_entry);
+ continue;
+ }
+
+ /* 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".",
+ wim->current_image + 1,
+ cur_entry->rspec->offset_in_wim);
+ wim->image_metadata[
+ wim->current_image++]->metadata_lte = cur_entry;
+ continue;
+ }
+
+ /* Lookup table entry for a stream that is not a metadata
+ * resource. */
+ duplicate_entry = lookup_resource(table, cur_entry->hash);
+ if (duplicate_entry) {
+ if (wimlib_print_errors) {
+ WARNING("The WIM lookup table contains two entries with the "
+ "same SHA1 message digest!");
+ WARNING("The first entry is:");
+ print_lookup_table_entry(duplicate_entry, stderr);
+ WARNING("The second entry is:");
+ print_lookup_table_entry(cur_entry, stderr);
+ }
+ free_lookup_table_entry(cur_entry);
+ continue;