- if (size == wim_resource_size(lte)) {
- /* Do SHA1 */
- struct extract_ctx ctx;
- ctx.extract_chunk = extract_chunk;
- ctx.extract_chunk_arg = extract_chunk_arg;
- sha1_init(&ctx.sha_ctx);
- ret = read_resource_prefix(lte, size,
- extract_chunk_sha1_wrapper,
- &ctx, 0);
- if (ret == 0) {
- u8 hash[SHA1_HASH_SIZE];
- sha1_final(hash, &ctx.sha_ctx);
- if (!hashes_equal(hash, lte->hash)) {
- #ifdef ENABLE_ERROR_MESSAGES
- ERROR_WITH_ERRNO("Invalid SHA1 message digest "
- "on the following WIM resource:");
- print_lookup_table_entry(lte, stderr);
- if (lte->resource_location == RESOURCE_IN_WIM)
- ERROR("The WIM file appears to be corrupt!");
- #endif
- ret = WIMLIB_ERR_INVALID_RESOURCE_HASH;
+ struct list_head *cur, *next;
+ struct blob_descriptor *blob;
+ struct hasher_context *hasher_ctx;
+ struct read_blob_list_callbacks *sink_cbs;
+
+ if (!(flags & BLOB_LIST_ALREADY_SORTED)) {
+ ret = sort_blob_list_by_sequential_order(blob_list, list_head_offset);
+ if (ret)
+ return ret;
+ }
+
+ if (flags & (VERIFY_BLOB_HASHES | COMPUTE_MISSING_BLOB_HASHES)) {
+ hasher_ctx = alloca(sizeof(*hasher_ctx));
+ *hasher_ctx = (struct hasher_context) {
+ .flags = flags,
+ .cbs = *cbs,
+ };
+ sink_cbs = alloca(sizeof(*sink_cbs));
+ *sink_cbs = (struct read_blob_list_callbacks) {
+ .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,
+ };
+ } else {
+ sink_cbs = (struct read_blob_list_callbacks*)cbs;
+ }
+
+ for (cur = blob_list->next, next = cur->next;
+ cur != blob_list;
+ cur = next, next = cur->next)
+ {
+ blob = (struct blob_descriptor*)((u8*)cur - list_head_offset);
+
+ if (blob->blob_location == BLOB_IN_WIM &&
+ blob->size != blob->rdesc->uncompressed_size)
+ {
+ struct blob_descriptor *blob_next, *blob_last;
+ struct list_head *next2;
+ u64 blob_count;
+
+ /* The next blob is a proper sub-sequence of a WIM
+ * resource. See if there are other blobs in the same
+ * resource that need to be read. Since
+ * sort_blob_list_by_sequential_order() sorted the blobs
+ * by offset in the WIM, this can be determined by
+ * simply scanning forward in the list. */
+
+ blob_last = blob;
+ blob_count = 1;
+ for (next2 = next;
+ next2 != blob_list
+ && (blob_next = (struct blob_descriptor*)
+ ((u8*)next2 - list_head_offset),
+ blob_next->blob_location == BLOB_IN_WIM
+ && blob_next->rdesc == blob->rdesc);
+ next2 = next2->next)
+ {
+ blob_last = blob_next;
+ blob_count++;
+ }
+ if (blob_count > 1) {
+ /* Reading multiple blobs combined into a single
+ * WIM resource. They are in the blob list,
+ * sorted by offset; @blob specifies the first
+ * blob in the resource that needs to be read
+ * and @blob_last specifies the last blob in the
+ * resource that needs to be read. */
+ next = next2;
+ ret = read_blobs_in_solid_resource(blob, blob_last,
+ blob_count,
+ list_head_offset,
+ sink_cbs);
+ if (ret)
+ return ret;
+ continue;