]> wimlib.net Git - wimlib/blobdiff - src/lookup_table.c
Cache compression format in 'struct wim_resource_spec'
[wimlib] / src / lookup_table.c
index 357d64387e995867e23b97057a29501567b39075..815d576fe551177200b8b781c3a69621d7210530 100644 (file)
@@ -619,7 +619,7 @@ read_wim_lookup_table(WIMStruct *wim)
                if (cur_entry == NULL) {
                        ERROR("Not enough memory to read lookup table!");
                        ret = WIMLIB_ERR_NOMEM;
-                       goto out_free_lookup_table;
+                       goto err;
                }
 
                part_number = le16_to_cpu(disk_entry->part_number);
@@ -639,7 +639,7 @@ read_wim_lookup_table(WIMStruct *wim)
                        if (reshdr.uncompressed_size != reshdr.size_in_wim) {
                                ERROR("Invalid resource entry!");
                                ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
-                               goto out_free_cur_entry;
+                               goto err;
                        }
                }
 
@@ -656,17 +656,18 @@ read_wim_lookup_table(WIMStruct *wim)
                         * resource.  */
                        struct wim_lookup_table_entry *prev_entry = NULL;
 
-                       if (back_to_back_pack) {
+                       if (back_to_back_pack &&
+                           !list_empty(&cur_rspec->stream_list))
+                       {
                                prev_entry = list_entry(cur_rspec->stream_list.prev,
                                                        struct wim_lookup_table_entry,
                                                        rspec_node);
                                lte_unbind_wim_resource_spec(prev_entry);
-                               cur_rspec->uncompressed_size -= prev_entry->size;
                        }
                        if (cur_rspec != NULL) {
                                ret = validate_resource(cur_rspec);
                                if (ret)
-                                       goto out_free_cur_entry;
+                                       goto err;
                        }
 
                        /* Allocate the resource specification and initialize it
@@ -675,24 +676,12 @@ read_wim_lookup_table(WIMStruct *wim)
                        if (cur_rspec == NULL) {
                                ERROR("Not enough memory to read lookup table!");
                                ret = WIMLIB_ERR_NOMEM;
-                               goto out_free_cur_entry;
+                               goto err;
                        }
                        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) {
+                       if (prev_entry)
                                lte_bind_wim_resource_spec(prev_entry, cur_rspec);
-                               cur_rspec->uncompressed_size = prev_entry->size;
-                       }
                }
 
                if ((reshdr.flags & WIM_RESHDR_FLAG_PACKED_STREAMS) &&
@@ -702,11 +691,36 @@ read_wim_lookup_table(WIMStruct *wim)
                         * 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".  */
+                        * 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,
@@ -723,10 +737,10 @@ read_wim_lookup_table(WIMStruct *wim)
 
                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")",
+                       DEBUG("Continuing pack 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);
@@ -764,7 +778,7 @@ read_wim_lookup_table(WIMStruct *wim)
                                        print_lookup_table_entry(cur_entry, stderr);
                                }
                                ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
-                               goto out_free_cur_entry;
+                               goto err;
                        }
 
                        if (wim->hdr.part_number != 1) {
@@ -818,12 +832,13 @@ read_wim_lookup_table(WIMStruct *wim)
                 * its SHA1 message digest.  */
                lookup_table_insert(table, cur_entry);
        }
+       cur_entry = NULL;
 
        /* Validate the last resource.  */
        if (cur_rspec != NULL) {
                ret = validate_resource(cur_rspec);
                if (ret)
-                       goto out_free_lookup_table;
+                       goto err;
        }
 
        if (wim->hdr.part_number == 1 && wim->current_image != wim->hdr.image_count) {
@@ -841,9 +856,10 @@ read_wim_lookup_table(WIMStruct *wim)
        ret = 0;
        goto out_free_buf;
 
-out_free_cur_entry:
-       FREE(cur_entry);
-out_free_lookup_table:
+err:
+       if (cur_rspec && list_empty(&cur_rspec->stream_list))
+               FREE(cur_rspec);
+       free_lookup_table_entry(cur_entry);
        free_lookup_table(table);
 out_free_buf:
        FREE(buf);
@@ -1174,7 +1190,7 @@ wim_pathname_to_stream(WIMStruct *wim,
                }
        }
 
-       dentry = get_dentry(wim, path);
+       dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
        if (p)
                *p = T(':');
        if (!dentry)