]> wimlib.net Git - wimlib/blobdiff - src/lookup_table.c
Cache compression format in 'struct wim_resource_spec'
[wimlib] / src / lookup_table.c
index 0538dd050c9c4e991ae74be48f596e7aa3233043..815d576fe551177200b8b781c3a69621d7210530 100644 (file)
@@ -212,6 +212,43 @@ free_lookup_table(struct wim_lookup_table *table)
        }
 }
 
+static void
+lookup_table_insert_raw(struct wim_lookup_table *table,
+                       struct wim_lookup_table_entry *lte)
+{
+       size_t i = lte->hash_short % table->capacity;
+
+       hlist_add_head(&lte->hash_list, &table->array[i]);
+}
+
+static void
+enlarge_lookup_table(struct wim_lookup_table *table)
+{
+       size_t old_capacity, new_capacity;
+       struct hlist_head *old_array, *new_array;
+       struct wim_lookup_table_entry *lte;
+       struct hlist_node *cur, *tmp;
+       size_t i;
+
+       old_capacity = table->capacity;
+       new_capacity = old_capacity * 2;
+       new_array = CALLOC(new_capacity, sizeof(struct hlist_head));
+       if (new_array == NULL)
+               return;
+       old_array = table->array;
+       table->array = new_array;
+       table->capacity = new_capacity;
+
+       for (i = 0; i < old_capacity; i++) {
+               hlist_for_each_entry_safe(lte, cur, tmp, &old_array[i], hash_list) {
+                       hlist_del(&lte->hash_list);
+                       lookup_table_insert_raw(table, lte);
+               }
+       }
+       FREE(old_array);
+}
+
+
 /*
  * Inserts an entry into the lookup table.
  *
@@ -222,11 +259,9 @@ void
 lookup_table_insert(struct wim_lookup_table *table,
                    struct wim_lookup_table_entry *lte)
 {
-       size_t i = lte->hash_short % table->capacity;
-       hlist_add_head(&lte->hash_list, &table->array[i]);
-
-       /* XXX Make the table grow when too many entries have been inserted. */
-       table->num_entries++;
+       lookup_table_insert_raw(table, lte);
+       if (++table->num_entries > table->capacity)
+               enlarge_lookup_table(table);
 }
 
 static void
@@ -288,7 +323,6 @@ 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)
                                return ret;
@@ -578,11 +612,14 @@ read_wim_lookup_table(WIMStruct *wim)
                      reshdr.size_in_wim, reshdr.uncompressed_size,
                      reshdr.offset_in_wim, reshdr.flags);
 
+               if (wim->hdr.wim_version == WIM_VERSION_DEFAULT)
+                       reshdr.flags &= ~WIM_RESHDR_FLAG_PACKED_STREAMS;
+
                cur_entry = new_lookup_table_entry();
                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);
@@ -602,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;
                        }
                }
 
@@ -619,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
@@ -638,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) &&
@@ -665,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,
@@ -686,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);
@@ -727,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) {
@@ -781,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) {
@@ -804,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);
@@ -831,8 +884,7 @@ write_wim_lookup_table_from_stream_list(struct list_head *stream_list,
                                        struct filedes *out_fd,
                                        u16 part_number,
                                        struct wim_reshdr *out_reshdr,
-                                       int write_resource_flags,
-                                       struct wimlib_lzx_context **comp_ctx)
+                                       int write_resource_flags)
 {
        size_t table_size;
        struct wim_lookup_table_entry *lte;
@@ -912,8 +964,7 @@ write_wim_lookup_table_from_stream_list(struct list_head *stream_list,
                                             0,
                                             out_reshdr,
                                             NULL,
-                                            write_resource_flags,
-                                            comp_ctx);
+                                            write_resource_flags);
        FREE(table_buf);
        DEBUG("ret=%d", ret);
        return ret;
@@ -1139,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)