+/* Like write_wim_resource(), but the resource is specified by a buffer of
+ * uncompressed data rather a lookup table entry; also writes the SHA1 hash of
+ * the buffer to @hash. */
+static int write_wim_resource_from_buffer(const u8 *buf, u64 buf_size,
+ FILE *out_fp, int out_ctype,
+ struct resource_entry *out_res_entry,
+ u8 hash[SHA1_HASH_SIZE])
+{
+ /* Set up a temporary lookup table entry to provide to
+ * write_wim_resource(). */
+ struct lookup_table_entry lte;
+ int ret;
+ lte.resource_entry.flags = 0;
+ lte.resource_entry.original_size = buf_size;
+ lte.resource_entry.size = buf_size;
+ lte.resource_entry.offset = 0;
+ lte.resource_location = RESOURCE_IN_ATTACHED_BUFFER;
+ lte.attached_buffer = (u8*)buf;
+
+ zero_out_hash(lte.hash);
+ ret = write_wim_resource(<e, out_fp, out_ctype, out_res_entry, 0);
+ if (ret != 0)
+ return ret;
+ copy_hash(hash, lte.hash);
+ return 0;
+}
+
+/*
+ * Extracts the first @size bytes of the WIM resource specified by @lte to the
+ * open file descriptor @fd.
+ *
+ * Returns 0 on success; nonzero on failure.
+ */
+int extract_wim_resource_to_fd(const struct lookup_table_entry *lte, int fd,
+ u64 size)
+{
+ u64 bytes_remaining = size;
+ u8 buf[min(WIM_CHUNK_SIZE, bytes_remaining)];
+ u64 offset = 0;
+ int ret = 0;
+ u8 hash[SHA1_HASH_SIZE];
+
+ SHA_CTX ctx;
+ sha1_init(&ctx);
+
+ while (bytes_remaining) {
+ u64 to_read = min(bytes_remaining, WIM_CHUNK_SIZE);
+ ret = read_wim_resource(lte, buf, to_read, offset, 0);
+ if (ret != 0)
+ break;
+ sha1_update(&ctx, buf, to_read);
+ if (full_write(fd, buf, to_read) < to_read) {
+ ERROR_WITH_ERRNO("Error extracting WIM resource");
+ return WIMLIB_ERR_WRITE;
+ }
+ bytes_remaining -= to_read;
+ offset += to_read;
+ }
+ sha1_final(hash, &ctx);
+ if (!hashes_equal(hash, lte->hash)) {
+ ERROR("Invalid checksum on a WIM resource "
+ "(detected when extracting to external file)");
+ ERROR("The following WIM resource is invalid:");
+ print_lookup_table_entry(lte);
+ return WIMLIB_ERR_INVALID_RESOURCE_HASH;
+ }
+ return 0;
+}
+
+/*
+ * Extracts the WIM resource specified by @lte to the open file descriptor @fd.
+ *
+ * Returns 0 on success; nonzero on failure.
+ */
+int extract_full_wim_resource_to_fd(const struct lookup_table_entry *lte, int fd)
+{
+ return extract_wim_resource_to_fd(lte, fd, wim_resource_size(lte));
+}
+
+/*
+ * Copies the file resource specified by the lookup table entry @lte from the
+ * input WIM to the output WIM that has its FILE * given by
+ * ((WIMStruct*)wim)->out_fp.
+ *
+ * The output_resource_entry, out_refcnt, and part_number fields of @lte are
+ * updated.
+ *
+ * Metadata resources are not copied (they are handled elsewhere for joining and
+ * splitting).
+ */
+int copy_resource(struct lookup_table_entry *lte, void *wim)
+{
+ WIMStruct *w = wim;
+ int ret;
+
+ if ((lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) &&
+ !w->write_metadata)
+ return 0;
+
+ ret = write_wim_resource(lte, w->out_fp,
+ wim_resource_compression_type(lte),
+ <e->output_resource_entry, 0);
+ if (ret != 0)
+ return ret;
+ lte->out_refcnt = lte->refcnt;
+ lte->part_number = w->hdr.part_number;
+ return 0;
+}
+
+/*