Cache compression format in 'struct wim_resource_spec'
authorEric Biggers <ebiggers3@gmail.com>
Wed, 8 Jan 2014 01:10:22 +0000 (19:10 -0600)
committerEric Biggers <ebiggers3@gmail.com>
Wed, 8 Jan 2014 01:10:22 +0000 (19:10 -0600)
include/wimlib/resource.h
src/lookup_table.c
src/resource.c
src/write.c

index 488ea6a..38ce568 100644 (file)
@@ -52,6 +52,13 @@ struct wim_resource_spec {
 
        /* Temporary flag.  */
        u32 raw_copy_ok : 1;
+
+       /* Compression type of this resource.  */
+       u32 compression_type : 22;
+
+       /* Compression chunk size of this resource.  Irrelevant if the resource
+        * is uncompressed.  */
+       u32 chunk_size;
 };
 
 /* On-disk version of a WIM resource header.  */
index 6ff8381..815d576 100644 (file)
@@ -680,16 +680,6 @@ read_wim_lookup_table(WIMStruct *wim)
                        }
                        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.  */
-                       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);
                }
@@ -705,7 +695,10 @@ read_wim_lookup_table(WIMStruct *wim)
                         */
 
                        /* Uncompressed size of the resource pack is actually
-                        * stored in the header of the resource itself.  */
+                        * 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,
@@ -717,6 +710,17 @@ read_wim_lookup_table(WIMStruct *wim)
                        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,
index 6e47dff..116873f 100644 (file)
@@ -175,37 +175,21 @@ read_compressed_wim_resource(const struct wim_resource_spec * const rspec,
 
        /* Get the maximum size of uncompressed chunks in this resource, which
         * we require be a power of 2.  */
-       u32 chunk_size = 0;
        u64 cur_read_offset = rspec->offset_in_wim;
-       int ctype = WIMLIB_COMPRESSION_TYPE_NONE;
+       int ctype = rspec->compression_type;
+       u32 chunk_size = rspec->chunk_size;
        if (alt_chunk_table) {
                /* Alternate chunk table format.  Its header specifies the chunk
-                * size and compression format.  */
-               struct alt_chunk_table_header_disk hdr;
-
-               ret = full_pread(in_fd, &hdr, sizeof(hdr), cur_read_offset);
-               if (ret)
-                       goto read_error;
-               cur_read_offset += sizeof(hdr);
-
-               chunk_size = le32_to_cpu(hdr.chunk_size);
-               ctype = le32_to_cpu(hdr.compression_format);
-
-               /* Format numbers must be the same as in WIMGAPI to be
-                * compatible.  */
-               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);
-       } else {
-               /* "Normal" format: the maximum uncompressed chunk size and the
-                * compression format default to those of the WIM itself.  */
-               chunk_size = rspec->wim->chunk_size;
-               ctype = rspec->wim->compression_type;
+                * size and compression format.  Note: it could be read here;
+                * however, the relevant data was already loaded into @rspec by
+                * read_wim_lookup_table().  */
+               cur_read_offset += sizeof(struct alt_chunk_table_header_disk);
        }
+
        if (!is_power_of_2(chunk_size)) {
                ERROR("Invalid compressed resource: "
-                     "expected power-of-2 chunk size (got %u)", chunk_size);
+                     "expected power-of-2 chunk size (got %"PRIu32")",
+                     chunk_size);
                ret = WIMLIB_ERR_INVALID_CHUNK_SIZE;
                goto out_free_memory;
        }
@@ -1377,7 +1361,10 @@ sha1_stream(struct wim_lookup_table_entry *lte)
 }
 
 /* Convert a short WIM resource header to a stand-alone WIM resource
- * specification.  */
+ * specification.
+ *
+ * Note: for packed resources some fields still need to be overridden.
+ */
 void
 wim_res_hdr_to_spec(const struct wim_reshdr *reshdr, WIMStruct *wim,
                    struct wim_resource_spec *rspec)
@@ -1389,6 +1376,13 @@ wim_res_hdr_to_spec(const struct wim_reshdr *reshdr, WIMStruct *wim,
        INIT_LIST_HEAD(&rspec->stream_list);
        rspec->flags = reshdr->flags;
        rspec->is_pipable = wim_is_pipable(wim);
+       if (rspec->flags & WIM_RESHDR_FLAG_COMPRESSED) {
+               rspec->compression_type = wim->compression_type;
+               rspec->chunk_size = wim->chunk_size;
+       } else {
+               rspec->compression_type = WIMLIB_COMPRESSION_TYPE_NONE;
+               rspec->chunk_size = 0;
+       }
 }
 
 /* Convert a stand-alone resource specification to a WIM resource header.  */
index 3fd1d04..b8d86e8 100644 (file)
@@ -172,8 +172,8 @@ can_raw_copy(const struct wim_lookup_table_entry *lte,
        if (rspec->flags & WIM_RESHDR_FLAG_COMPRESSED) {
                /* Normal compressed resource: Must use same compression type
                 * and chunk size.  */
-               return (rspec->wim->compression_type == out_ctype &&
-                       rspec->wim->chunk_size == out_chunk_size);
+               return (rspec->compression_type == out_ctype &&
+                       rspec->chunk_size == out_chunk_size);
        }
 
        /* XXX: For compatibility, we can't allow multiple packed resources per