- if ((flags & WIMLIB_RESOURCE_FLAG_RAW)
- || ctype == WIMLIB_COMPRESSION_TYPE_NONE)
- ret = read_uncompressed_resource(fp,
- lte->resource_entry.offset + offset,
- size, buf);
- else
- ret = read_compressed_resource(fp,
- lte->resource_entry.size,
- lte->resource_entry.original_size,
- lte->resource_entry.offset,
- ctype, size, offset, buf);
- #ifdef WITH_FUSE
- if (flags & WIMLIB_RESOURCE_FLAG_MULTITHREADED) {
- int ret2 = wim_release_fp(lte->wim, fp);
- if (ret == 0)
- ret = ret2;
- }
- #endif
- break;
- case RESOURCE_IN_STAGING_FILE:
- case RESOURCE_IN_FILE_ON_DISK:
- /* The resource is in some file on the external filesystem and
- * needs to be read uncompressed */
- wimlib_assert(lte->file_on_disk);
- wimlib_assert(<e->file_on_disk == <e->staging_file_name);
- /* Use existing file pointer if available; otherwise open one
- * temporarily */
- if (lte->file_on_disk_fp) {
- fp = lte->file_on_disk_fp;
- } else {
- fp = fopen(lte->file_on_disk, "rb");
- if (!fp) {
- ERROR_WITH_ERRNO("Failed to open the file "
- "`%s'", lte->file_on_disk);
- ret = WIMLIB_ERR_OPEN;
- break;
+ sha1_update(&ctx->sha_ctx, chunk, chunk_size);
+ return ctx->extract_chunk(chunk, chunk_size, ctx->extract_chunk_arg);
+}
+
+/* Extracts the first @size bytes of a WIM resource to somewhere. In the
+ * process, the SHA1 message digest of the resource is checked if the full
+ * resource is being extracted.
+ *
+ * @extract_chunk is a function that is called to extract each chunk of the
+ * resource. */
+int
+extract_wim_resource(const struct wim_lookup_table_entry *lte,
+ u64 size,
+ consume_data_callback_t extract_chunk,
+ void *extract_chunk_arg)
+{
+ int ret;
+ 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("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;