X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fblob_table.c;h=1509a835489dcb8daed0389e82b4b193bc5d13e9;hp=dd5bbd7e7e14c41877becc1afaaaac627a2573f0;hb=3a0b45be3635a632f3acd97b170dead2de29e8a8;hpb=c24f1c029572b67c7023aa06a7c24a46cf938367 diff --git a/src/blob_table.c b/src/blob_table.c index dd5bbd7e..1509a835 100644 --- a/src/blob_table.c +++ b/src/blob_table.c @@ -162,15 +162,24 @@ out_free: return NULL; } -static void +/* Release a blob descriptor from its location, if any, and set its new location + * to BLOB_NONEXISTENT. */ +void blob_release_location(struct blob_descriptor *blob) { switch (blob->blob_location) { - case BLOB_IN_WIM: + case BLOB_IN_WIM: { + struct wim_resource_descriptor *rdesc = blob->rdesc; + list_del(&blob->rdesc_node); - if (list_empty(&blob->rdesc->blob_list)) - FREE(blob->rdesc); + if (list_empty(&rdesc->blob_list)) { + wimlib_assert(rdesc->wim->refcnt > 0); + if (--rdesc->wim->refcnt == 0) + finalize_wim_struct(rdesc->wim); + FREE(rdesc); + } break; + } case BLOB_IN_FILE_ON_DISK: #ifdef __WIN32__ case BLOB_IN_WINNT_FILE_ON_DISK: @@ -193,6 +202,7 @@ blob_release_location(struct blob_descriptor *blob) break; #endif } + blob->blob_location = BLOB_NONEXISTENT; } void @@ -403,7 +413,12 @@ cmp_blobs_by_sequential_order(const void *p1, const void *p2) v = (int)blob1->blob_location - (int)blob2->blob_location; - /* Different locations? */ + /* Different locations? Note: "unsafe compaction mode" requires that + * blobs in WIMs sort before all others. For the logic here to ensure + * this, BLOB_IN_WIM must have the lowest value among all defined + * blob_locations. Statically verify that the enum values haven't + * changed. */ + STATIC_ASSERT(BLOB_NONEXISTENT == 0 && BLOB_IN_WIM == 1); if (v) return v; @@ -412,22 +427,39 @@ cmp_blobs_by_sequential_order(const void *p1, const void *p2) wim1 = blob1->rdesc->wim; wim2 = blob2->rdesc->wim; - /* Different (possibly split) WIMs? */ + /* Different WIM files? */ if (wim1 != wim2) { + + /* Resources from the WIM file currently being compacted + * (if any) must always sort first. */ + v = (int)wim2->being_compacted - (int)wim1->being_compacted; + if (v) + return v; + + /* Different split WIMs? */ v = cmp_guids(wim1->hdr.guid, wim2->hdr.guid); if (v) return v; + + /* Different part numbers in the same split WIM? */ + v = (int)wim1->hdr.part_number - (int)wim2->hdr.part_number; + if (v) + return v; + + /* Probably two WIMStructs for the same on-disk file. + * Just sort by pointer. */ + return wim1 < wim2 ? -1 : 1; } - /* Different part numbers in the same WIM? */ - v = (int)wim1->hdr.part_number - (int)wim2->hdr.part_number; - if (v) - return v; + /* Same WIM file */ + /* Sort by increasing resource offset */ if (blob1->rdesc->offset_in_wim != blob2->rdesc->offset_in_wim) return cmp_u64(blob1->rdesc->offset_in_wim, blob2->rdesc->offset_in_wim); + /* The blobs are in the same solid resource. Sort by increasing + * offset in the resource. */ return cmp_u64(blob1->offset_in_res, blob2->offset_in_res); case BLOB_IN_FILE_ON_DISK: @@ -685,6 +717,8 @@ load_solid_info(WIMStruct *wim, if (ret) goto out_free_rdescs; + wim->refcnt += num_rdescs; + *rdescs_ret = rdescs; *num_rdescs_ret = num_rdescs; return 0; @@ -725,9 +759,12 @@ static void free_solid_rdescs(struct wim_resource_descriptor **rdescs, size_t num_rdescs) { if (rdescs) { - for (size_t i = 0; i < num_rdescs; i++) - if (list_empty(&rdescs[i]->blob_list)) + for (size_t i = 0; i < num_rdescs; i++) { + if (list_empty(&rdescs[i]->blob_list)) { + rdescs[i]->wim->refcnt--; FREE(rdescs[i]); + } + } FREE(rdescs); } } @@ -959,6 +996,7 @@ read_blob_table(WIMStruct *wim) goto oom; wim_reshdr_to_desc_and_blob(&reshdr, wim, rdesc, cur_blob); + wim->refcnt++; } /* cur_blob is now a blob bound to a resource. */