X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fblob_table.c;h=c94635f105b57add5fc422cf6017da9c57944bbb;hb=d8af927e5d02cbcfc45cd1a3568b31c9814ec6f5;hp=84835b5a7a03b6ca2d5a7774c55f98c025a2bad2;hpb=c8973198f13d77027bf601b5ec206baca2e7fa34;p=wimlib diff --git a/src/blob_table.c b/src/blob_table.c index 84835b5a..c94635f1 100644 --- a/src/blob_table.c +++ b/src/blob_table.c @@ -105,8 +105,7 @@ new_blob_descriptor(void) if (blob == NULL) return NULL; - blob->refcnt = 1; - + /* blob->refcnt = 0 */ /* blob->blob_location = BLOB_NONEXISTENT */ BUILD_BUG_ON(BLOB_NONEXISTENT != 0); @@ -263,10 +262,21 @@ finalize_blob(struct blob_descriptor *blob) void blob_decrement_refcnt(struct blob_descriptor *blob, struct blob_table *table) { - if (unlikely(blob->refcnt == 0)) /* See comment above */ + blob_subtract_refcnt(blob, table, 1); +} + +void +blob_subtract_refcnt(struct blob_descriptor *blob, struct blob_table *table, + u32 count) +{ + if (unlikely(blob->refcnt < count)) { + blob->refcnt = 0; /* See comment above */ return; + } + + blob->refcnt -= count; - if (--blob->refcnt != 0) + if (blob->refcnt != 0) return; if (blob->unhashed) { @@ -728,7 +738,6 @@ assign_blob_to_solid_resource(const struct wim_reshdr *reshdr, /* XXX: This linear search will be slow in the degenerate case where the * number of solid resources in the run is huge. */ blob->size = reshdr->size_in_wim; - blob->flags = reshdr->flags; for (size_t i = 0; i < num_rdescs; i++) { if (offset + blob->size <= rdescs[i]->uncompressed_size) { blob->offset_in_res = offset; @@ -1004,7 +1013,6 @@ read_blob_table(WIMStruct *wim) cur_blob->offset_in_res = 0; cur_blob->size = reshdr.uncompressed_size; - cur_blob->flags = reshdr.flags; blob_set_is_located_in_wim_resource(cur_blob, rdesc); } @@ -1024,6 +1032,8 @@ read_blob_table(WIMStruct *wim) if (reshdr.flags & WIM_RESHDR_FLAG_METADATA) { + cur_blob->is_metadata = 1; + /* Blob table entry for a metadata resource. */ /* Metadata entries with no references must be ignored. @@ -1145,9 +1155,9 @@ write_blob_descriptor(struct blob_descriptor_disk *disk_entry, } /* Note: the list of blob descriptors must be sorted so that all entries for the - * same solid resource are consecutive. In addition, blob descriptors with - * WIM_RESHDR_FLAG_METADATA set must be in the same order as the indices of the - * underlying images. */ + * same solid resource are consecutive. In addition, blob descriptors for + * metadata resources must be in the same order as the indices of the underlying + * images. */ int write_blob_table_from_blob_list(struct list_head *blob_list, struct filedes *out_fd, @@ -1229,7 +1239,7 @@ write_blob_table_from_blob_list(struct list_head *blob_list, * compressed blob table, MS software cannot. */ ret = write_wim_resource_from_buffer(table_buf, table_size, - WIM_RESHDR_FLAG_METADATA, + true, out_fd, WIMLIB_COMPRESSION_TYPE_NONE, 0, @@ -1255,7 +1265,6 @@ new_blob_from_data_buffer(const void *buffer, size_t size, if (existing_blob) { wimlib_assert(existing_blob->size == size); blob = existing_blob; - blob->refcnt++; } else { void *buffer_copy; blob = new_blob_descriptor(); @@ -1275,6 +1284,36 @@ new_blob_from_data_buffer(const void *buffer, size_t size, return blob; } +struct blob_descriptor * +after_blob_hashed(struct blob_descriptor *blob, + struct blob_descriptor **back_ptr, + struct blob_table *blob_table) +{ + struct blob_descriptor *duplicate_blob; + + list_del(&blob->unhashed_list); + blob->unhashed = 0; + + /* Look for a duplicate blob */ + duplicate_blob = lookup_blob(blob_table, blob->hash); + if (duplicate_blob) { + /* We have a duplicate blob. Transfer the reference counts from + * this blob to the duplicate and update the reference to this + * blob (from a stream) to point to the duplicate. The caller + * is responsible for freeing @blob if needed. */ + wimlib_assert(duplicate_blob->size == blob->size); + duplicate_blob->refcnt += blob->refcnt; + blob->refcnt = 0; + *back_ptr = duplicate_blob; + return duplicate_blob; + } else { + /* No duplicate blob, so we need to insert this blob into the + * blob table and treat it as a hashed blob. */ + blob_table_insert(blob_table, blob); + return blob; + } +} + /* * Calculate the SHA-1 message digest of a blob and move its descriptor from the * list of unhashed blobs to the blob table, possibly joining it with an @@ -1295,42 +1334,16 @@ int hash_unhashed_blob(struct blob_descriptor *blob, struct blob_table *blob_table, struct blob_descriptor **blob_ret) { - int ret; - struct blob_descriptor *duplicate_blob; struct blob_descriptor **back_ptr; + int ret; - wimlib_assert(blob->unhashed); - - /* back_ptr must be saved because @back_inode and @back_stream_id are in - * union with the SHA-1 message digest and will no longer be valid once - * the SHA-1 has been calculated. */ back_ptr = retrieve_pointer_to_unhashed_blob(blob); ret = sha1_blob(blob); if (ret) return ret; - list_del(&blob->unhashed_list); - blob->unhashed = 0; - - /* Look for a duplicate blob */ - duplicate_blob = lookup_blob(blob_table, blob->hash); - if (duplicate_blob) { - /* We have a duplicate blob. Transfer the reference counts from - * this blob to the duplicate and update the reference to this - * blob (from an stream) to point to the duplicate. The caller - * is responsible for freeing @blob if needed. */ - wimlib_assert(duplicate_blob->size == blob->size); - duplicate_blob->refcnt += blob->refcnt; - blob->refcnt = 0; - *back_ptr = duplicate_blob; - blob = duplicate_blob; - } else { - /* No duplicate blob, so we need to insert this blob into the - * blob table and treat it as a hashed blob. */ - blob_table_insert(blob_table, blob); - } - *blob_ret = blob; + *blob_ret = after_blob_hashed(blob, back_ptr, blob_table); return 0; } @@ -1342,8 +1355,10 @@ blob_to_wimlib_resource_entry(const struct blob_descriptor *blob, wentry->uncompressed_size = blob->size; if (blob->blob_location == BLOB_IN_WIM) { + unsigned res_flags = blob->rdesc->flags; + wentry->part_number = blob->rdesc->wim->hdr.part_number; - if (blob->flags & WIM_RESHDR_FLAG_SOLID) { + if (res_flags & WIM_RESHDR_FLAG_SOLID) { wentry->offset = blob->offset_in_res; } else { wentry->compressed_size = blob->rdesc->size_in_wim; @@ -1352,14 +1367,15 @@ blob_to_wimlib_resource_entry(const struct blob_descriptor *blob, wentry->raw_resource_offset_in_wim = blob->rdesc->offset_in_wim; wentry->raw_resource_compressed_size = blob->rdesc->size_in_wim; wentry->raw_resource_uncompressed_size = blob->rdesc->uncompressed_size; + + wentry->is_compressed = (res_flags & WIM_RESHDR_FLAG_COMPRESSED) != 0; + wentry->is_free = (res_flags & WIM_RESHDR_FLAG_FREE) != 0; + wentry->is_spanned = (res_flags & WIM_RESHDR_FLAG_SPANNED) != 0; + wentry->packed = (res_flags & WIM_RESHDR_FLAG_SOLID) != 0; } copy_hash(wentry->sha1_hash, blob->hash); wentry->reference_count = blob->refcnt; - wentry->is_compressed = (blob->flags & WIM_RESHDR_FLAG_COMPRESSED) != 0; - wentry->is_metadata = (blob->flags & WIM_RESHDR_FLAG_METADATA) != 0; - wentry->is_free = (blob->flags & WIM_RESHDR_FLAG_FREE) != 0; - wentry->is_spanned = (blob->flags & WIM_RESHDR_FLAG_SPANNED) != 0; - wentry->packed = (blob->flags & WIM_RESHDR_FLAG_SOLID) != 0; + wentry->is_metadata = blob->is_metadata; } struct iterate_blob_context {