+ return ret;
+
+ ret = read_blob_prefix(blob, blob->size, cbs->consume_chunk,
+ cbs->consume_chunk_ctx);
+
+ return (*cbs->end_blob)(blob, ret, cbs->end_blob_ctx);
+}
+
+/* Read the full data of the specified blob, passing the data into the specified
+ * callbacks (all of which are optional) and either checking or computing the
+ * SHA-1 message digest of the blob. */
+static int
+read_full_blob_with_sha1(struct blob_descriptor *blob,
+ const struct read_blob_list_callbacks *cbs)
+{
+ struct hasher_context hasher_ctx = {
+ .flags = VERIFY_BLOB_HASHES | COMPUTE_MISSING_BLOB_HASHES,
+ .cbs = *cbs,
+ };
+ struct read_blob_list_callbacks hasher_cbs = {
+ .begin_blob = hasher_begin_blob,
+ .begin_blob_ctx = &hasher_ctx,
+ .consume_chunk = hasher_consume_chunk,
+ .consume_chunk_ctx = &hasher_ctx,
+ .end_blob = hasher_end_blob,
+ .end_blob_ctx = &hasher_ctx,
+ };
+ return read_full_blob_with_cbs(blob, &hasher_cbs);
+}
+
+static int
+read_blobs_in_solid_resource(struct blob_descriptor *first_blob,
+ struct blob_descriptor *last_blob,
+ u64 blob_count,
+ size_t list_head_offset,
+ const struct read_blob_list_callbacks *sink_cbs)
+{
+ struct data_range *ranges;
+ bool ranges_malloced;
+ struct blob_descriptor *cur_blob;
+ size_t i;
+ int ret;
+ u64 ranges_alloc_size;
+
+ DEBUG("Reading %"PRIu64" blobs combined in same WIM resource",
+ blob_count);
+
+ /* Setup data ranges array (one range per blob to read); this way
+ * read_compressed_wim_resource() does not need to be aware of blobs.
+ */
+
+ ranges_alloc_size = blob_count * sizeof(ranges[0]);
+
+ if (unlikely((size_t)ranges_alloc_size != ranges_alloc_size)) {
+ ERROR("Too many blobs in one resource!");
+ return WIMLIB_ERR_NOMEM;
+ }
+ if (likely(ranges_alloc_size <= STACK_MAX)) {
+ ranges = alloca(ranges_alloc_size);
+ ranges_malloced = false;
+ } else {
+ ranges = MALLOC(ranges_alloc_size);
+ if (ranges == NULL) {
+ ERROR("Too many blobs in one resource!");
+ return WIMLIB_ERR_NOMEM;
+ }
+ ranges_malloced = true;
+ }
+
+ for (i = 0, cur_blob = first_blob;
+ i < blob_count;
+ i++, cur_blob = next_blob(cur_blob, list_head_offset))
+ {
+ ranges[i].offset = cur_blob->offset_in_res;
+ ranges[i].size = cur_blob->size;
+ }
+
+ struct blobifier_context blobifier_ctx = {
+ .cbs = *sink_cbs,
+ .cur_blob = first_blob,
+ .next_blob = next_blob(first_blob, list_head_offset),
+ .cur_blob_offset = 0,
+ .final_blob = last_blob,
+ .list_head_offset = list_head_offset,
+ };
+
+ ret = read_compressed_wim_resource(first_blob->rdesc,
+ ranges,
+ blob_count,
+ blobifier_cb,
+ &blobifier_ctx);
+
+ if (ranges_malloced)
+ FREE(ranges);
+
+ if (ret) {
+ if (blobifier_ctx.cur_blob_offset != 0) {
+ ret = (*blobifier_ctx.cbs.end_blob)
+ (blobifier_ctx.cur_blob,
+ ret,
+ blobifier_ctx.cbs.end_blob_ctx);
+ }
+ }