+ wim_res_hdr_to_spec(&reshdr, wim, cur_rspec);
+
+ /* If this is a packed run, the current stream entry may
+ * specify a stream within the resource, and not the
+ * resource itself. Zero possibly irrelevant data until
+ * it is read for certain. (Note that the computation
+ * of 'back_to_back_pack' tests if 'size_in_wim' is
+ * nonzero to see if the resource info has been read;
+ * hence we need to set it to 0 here.) */
+ if (reshdr.flags & WIM_RESHDR_FLAG_PACKED_STREAMS) {
+ cur_rspec->size_in_wim = 0;
+ cur_rspec->uncompressed_size = 0;
+ cur_rspec->offset_in_wim = 0;
+ }
+
+ if (prev_entry)
+ lte_bind_wim_resource_spec(prev_entry, cur_rspec);
+ }
+
+ if ((reshdr.flags & WIM_RESHDR_FLAG_PACKED_STREAMS) &&
+ reshdr.uncompressed_size == WIM_PACK_MAGIC_NUMBER)
+ {
+ /* 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".
+ */
+
+ /* Uncompressed size of the resource pack is actually
+ * stored in the header of the resource itself. Read
+ * it, and also grab the chunk size and compression type
+ * (which are not necessarily the defaults from the WIM
+ * header). */
+ struct alt_chunk_table_header_disk hdr;
+
+ ret = full_pread(&wim->in_fd, &hdr,
+ sizeof(hdr), reshdr.offset_in_wim);
+ if (ret)
+ goto err;
+
+ cur_rspec->uncompressed_size = le64_to_cpu(hdr.res_usize);
+ cur_rspec->offset_in_wim = reshdr.offset_in_wim;
+ cur_rspec->size_in_wim = reshdr.size_in_wim;
+ cur_rspec->flags = reshdr.flags;
+
+ /* Compression format numbers must be the same as in
+ * WIMGAPI to be compatible here. */
+ BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_NONE != 0);
+ BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_LZX != 1);
+ BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_XPRESS != 2);
+ BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_LZMS != 3);
+ cur_rspec->compression_type = le32_to_cpu(hdr.compression_format);
+
+ cur_rspec->chunk_size = le32_to_cpu(hdr.chunk_size);
+
+ 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 pack with stream: "
+ "%"PRIu64" uncompressed bytes @ "
+ "resource offset %"PRIu64")",
+ reshdr.size_in_wim, reshdr.offset_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;