-static int extract_regular_file_linked(struct dentry *dentry,
- const char *output_path,
- struct apply_args *args,
- struct lookup_table_entry *lte)
-{
- /* This mode overrides the normal hard-link extraction and
- * instead either symlinks or hardlinks *all* identical files in
- * the WIM, even if they are in a different image (in the case
- * of a multi-image extraction) */
-
- if (args->extract_flags & WIMLIB_EXTRACT_FLAG_HARDLINK) {
- if (link(lte->extracted_file, output_path) != 0) {
- ERROR_WITH_ERRNO("Failed to hard link "
- "`%s' to `%s'",
- output_path, lte->extracted_file);
- return WIMLIB_ERR_LINK;
- }
- } else {
- int num_path_components;
- int num_output_dir_path_components;
- size_t extracted_file_len;
- char *p;
- const char *p2;
- size_t i;
-
- num_path_components =
- get_num_path_components(dentry->full_path_utf8) - 1;
- num_output_dir_path_components =
- get_num_path_components(args->target);
-
- if (args->extract_flags & WIMLIB_EXTRACT_FLAG_MULTI_IMAGE) {
- num_path_components++;
- num_output_dir_path_components--;
+int
+end_file_metadata_phase(struct apply_ctx *ctx)
+{
+ return end_file_phase(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_METADATA);
+}
+
+#define PWM_FOUND_WIM_HDR (-1)
+
+/* Read the header for a blob in a pipable WIM. If @pwm_hdr_ret is not NULL,
+ * also look for a pipable WIM header and return PWM_FOUND_WIM_HDR if found. */
+static int
+read_pwm_blob_header(WIMStruct *pwm, u8 hash_ret[SHA1_HASH_SIZE],
+ struct wim_reshdr *reshdr_ret,
+ struct wim_header_disk *pwm_hdr_ret)
+{
+ int ret;
+ struct pwm_blob_hdr blob_hdr;
+ u64 magic;
+
+ ret = full_read(&pwm->in_fd, &blob_hdr, sizeof(blob_hdr));
+ if (unlikely(ret))
+ goto read_error;
+
+ magic = le64_to_cpu(blob_hdr.magic);
+
+ if (magic == PWM_MAGIC && pwm_hdr_ret != NULL) {
+ memcpy(pwm_hdr_ret, &blob_hdr, sizeof(blob_hdr));
+ ret = full_read(&pwm->in_fd,
+ (u8 *)pwm_hdr_ret + sizeof(blob_hdr),
+ sizeof(*pwm_hdr_ret) - sizeof(blob_hdr));
+ if (unlikely(ret))
+ goto read_error;
+ return PWM_FOUND_WIM_HDR;
+ }
+
+ if (unlikely(magic != PWM_BLOB_MAGIC)) {
+ ERROR("Data read on pipe is invalid (expected blob header)");
+ return WIMLIB_ERR_INVALID_PIPABLE_WIM;
+ }
+
+ copy_hash(hash_ret, blob_hdr.hash);
+
+ reshdr_ret->size_in_wim = 0; /* Not available */
+ reshdr_ret->flags = le32_to_cpu(blob_hdr.flags);
+ reshdr_ret->offset_in_wim = pwm->in_fd.offset;
+ reshdr_ret->uncompressed_size = le64_to_cpu(blob_hdr.uncompressed_size);
+
+ if (unlikely(reshdr_ret->uncompressed_size == 0)) {
+ ERROR("Data read on pipe is invalid (resource is of 0 size)");
+ return WIMLIB_ERR_INVALID_PIPABLE_WIM;
+ }
+
+ return 0;
+
+read_error:
+ if (ret == WIMLIB_ERR_UNEXPECTED_END_OF_FILE)
+ ERROR("The pipe ended before all needed data was sent!");
+ else
+ ERROR_WITH_ERRNO("Error reading pipable WIM from pipe");
+ return ret;
+}
+
+static int
+read_blobs_from_pipe(struct apply_ctx *ctx, const struct read_blob_callbacks *cbs)
+{
+ int ret;
+ u8 hash[SHA1_HASH_SIZE];
+ struct wim_reshdr reshdr;
+ struct wim_header_disk pwm_hdr;
+ struct wim_resource_descriptor rdesc;
+ struct blob_descriptor *blob;
+
+ copy_guid(ctx->progress.extract.guid, ctx->wim->hdr.guid);
+ ctx->progress.extract.part_number = ctx->wim->hdr.part_number;
+ ctx->progress.extract.total_parts = ctx->wim->hdr.total_parts;
+ ret = extract_progress(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN);
+ if (ret)
+ return ret;
+
+ while (ctx->num_blobs_remaining) {
+
+ ret = read_pwm_blob_header(ctx->wim, hash, &reshdr, &pwm_hdr);
+
+ if (ret == PWM_FOUND_WIM_HDR) {
+ u16 part_number = le16_to_cpu(pwm_hdr.part_number);
+ u16 total_parts = le16_to_cpu(pwm_hdr.total_parts);
+
+ if (part_number == ctx->progress.extract.part_number &&
+ total_parts == ctx->progress.extract.total_parts &&
+ guids_equal(pwm_hdr.guid, ctx->progress.extract.guid))
+ continue;
+
+ copy_guid(ctx->progress.extract.guid, pwm_hdr.guid);
+ ctx->progress.extract.part_number = part_number;
+ ctx->progress.extract.total_parts = total_parts;
+ ret = extract_progress(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN);
+ if (ret)
+ return ret;
+
+ continue;