From: Eric Biggers Date: Fri, 16 Aug 2013 02:11:04 +0000 (-0500) Subject: Add WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN X-Git-Tag: v1.5.0~66 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=ca1be480fd209d8c24e19350e440c01832310a2d;hp=e08e0d6d920e1f3f154270efc4849d51efd65593 Add WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN --- diff --git a/include/wimlib.h b/include/wimlib.h index 0c14941e..340a9631 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -218,6 +218,8 @@ typedef char wimlib_tchar; # define _wimlib_deprecated #endif +#define WIMLIB_GUID_LEN 16 + /** * Specifies the compression type of a WIM file. */ @@ -260,8 +262,9 @@ enum wimlib_progress_msg { * info will point to ::wimlib_progress_info.extract. */ WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS, - /** Reserved. */ - WIMLIB_PROGRESS_MSG_EXTRACT_RESERVED, + /** Starting to read a new part of a split pipable WIM over the pipe. + * @a info will point to ::wimlib_progress_info.extract. */ + WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN, /** All the WIM files and directories have been extracted, and * timestamps are about to be applied. @a info will point to @@ -469,6 +472,19 @@ union wimlib_progress_info { * being extracted. Will be the empty string when extracting a * full image. */ const wimlib_tchar *extract_root_wim_source_path; + + /** Currently only used for + * ::WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN. */ + + unsigned part_number; + + /** Currently only used for + * ::WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN. */ + unsigned total_parts; + + /** Currently only used for + * ::WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN. */ + uint8_t guid[WIMLIB_GUID_LEN]; } extract; /** Valid on messages ::WIMLIB_PROGRESS_MSG_RENAME. */ @@ -646,8 +662,6 @@ struct wimlib_capture_config { * reparse-point fixups by default when capturing or applying WIM images. */ #define WIMLIB_CHANGE_RPFIX_FLAG 0x00000008 -#define WIMLIB_GUID_LEN 16 - /** General information about a WIM file. */ struct wimlib_wim_info { @@ -1902,7 +1916,9 @@ wimlib_extract_image(WIMStruct *wim, int image, * in this mode; also, ::WIMLIB_EXTRACT_FLAG_TO_STDOUT is invalid and will * result in ::WIMLIB_ERR_INVALID_PARAM being returned. * @param progress_func - * Same as the corresponding parameter to wimlib_extract_image(). + * Same as the corresponding parameter to wimlib_extract_image(), except + * ::WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN messages will also be + * received. * * @return 0 on success; nonzero on error. The possible error codes include * those returned by wimlib_extract_image() as well as the following: @@ -2814,23 +2830,27 @@ wimlib_set_print_errors(bool show_messages); * the WIM may be larger than this size, and the WIM file format provides * no way to split up file resources among multiple WIMs. * @param write_flags - * ::WIMLIB_WRITE_FLAG_CHECK_INTEGRITY if integrity tables are to be - * included in the split WIM parts. + * Bitwise OR of relevant flags prefixed with @c WIMLIB_WRITE_FLAG. These + * flags will be used to write each split WIM part. Specify 0 here to get + * the default behavior. * @param progress_func * If non-NULL, a function that will be called periodically with the - * progress of the current operation. + * progress of the current operation + * (::WIMLIB_PROGRESS_MSG_SPLIT_BEGIN_PART and + * ::WIMLIB_PROGRESS_MSG_SPLIT_END_PART). * * @return 0 on success; nonzero on error. This function may return any value * returned by wimlib_write() as well as the following error codes: * * @retval ::WIMLIB_ERR_SPLIT_UNSUPPORTED - * @a wim is not part 1 of a stand-alone WIM. + * @a wim was not part 1 of a stand-alone WIM. * @retval ::WIMLIB_ERR_INVALID_PARAM - * @a swm_name was @c NULL, or @a part_size was 0. + * @a swm_name was not a nonempty string, or @a part_size was 0. * * Note: the WIM's uncompressed and compressed resources are not checksummed * when they are copied from the joined WIM to the split WIM parts, nor are - * compressed resources re-compressed. + * compressed resources re-compressed (unless explicitly requested with + * ::WIMLIB_WRITE_FLAG_RECOMPRESS). */ extern int wimlib_split(WIMStruct *wim, diff --git a/include/wimlib/header.h b/include/wimlib/header.h index 637a4fef..efca2749 100644 --- a/include/wimlib/header.h +++ b/include/wimlib/header.h @@ -44,6 +44,70 @@ ((u64)'\0' << 48) | \ ((u64)'\0' << 54)) +/* On-disk format of the WIM header. */ +struct wim_header_disk { + + /* Magic characters "MSWIM\0\0\0" */ + le64 magic; + + /* Size of the WIM header, in bytes; WIM_HEADER_DISK_SIZE expected + * (currently the only supported value). */ + u32 hdr_size; + + /* Version of the WIM file; WIM_VERSION expected (currently the only + * supported value). */ + u32 wim_version; + + /* Flags for the WIM file (WIM_HDR_FLAG_*) */ + u32 wim_flags; + + /* Uncompressed chunk size of resources in the WIM. 0 if the WIM is + * uncompressed. If compressed, WIM_CHUNK_SIZE is expected (currently + * the only supported value). */ + u32 chunk_size; + + /* Globally unique identifier for the WIM file. Basically a bunch of + * random bytes. */ + u8 guid[WIM_GID_LEN]; + + /* Number of this WIM part in the split WIM file, indexed from 1, or 1 + * if the WIM is not split. */ + u16 part_number; + + /* Total number of parts of the split WIM file, or 1 if the WIM is not + * split. */ + u16 total_parts; + + /* Number of images in the WIM. */ + u32 image_count; + + /* Location and size of the WIM's lookup table. */ + struct resource_entry_disk lookup_table_res_entry; + + /* Location and size of the WIM's XML data. */ + struct resource_entry_disk xml_data_res_entry; + + /* Location and size of metadata resource for the bootable image of the + * WIM, or all zeroes if no image is bootable. */ + struct resource_entry_disk boot_metadata_res_entry; + + /* 1-based index of the bootable image of the WIM, or 0 if no image is + * bootable. */ + u32 boot_idx; + + /* Location and size of the WIM's integrity table, or all zeroes if the + * WIM has no integrity table. + * + * Note the integrity_table_res_entry here is 4-byte aligned even though + * it would ordinarily be 8-byte aligned--- hence, the _packed_attribute + * on the `struct wim_header_disk' is essential. */ + struct resource_entry_disk integrity_table_res_entry; + + /* Unused bytes. */ + u8 unused[60]; +} _packed_attribute; + + /* Header at the very beginning of the WIM file. This is the in-memory * representation and does not include all fields; see `struct wim_header_disk' * for the on-disk structure. */ diff --git a/programs/imagex.c b/programs/imagex.c index 977f21be..90b53dd6 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -1100,6 +1100,11 @@ imagex_progress_func(enum wimlib_progress_msg msg, if (info->extract.completed_bytes >= info->extract.total_bytes) imagex_printf(T("\n")); break; + case WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN: + imagex_printf(T("\nReading split pipable WIM part %u of %u\n"), + info->extract.part_number, + info->extract.total_parts); + break; case WIMLIB_PROGRESS_MSG_APPLY_TIMESTAMPS: if (info->extract.extract_root_wim_source_path[0] == T('\0')) imagex_printf(T("Setting timestamps on all extracted files...\n")); @@ -1127,7 +1132,7 @@ imagex_progress_func(enum wimlib_progress_msg msg, break; case WIMLIB_PROGRESS_MSG_SPLIT_END_PART: if (info->split.completed_bytes == info->split.total_bytes) { - imagex_printf(T("Finished writing part %u of %u WIM parts\n"), + imagex_printf(T("Finished writing split WIM part %u of %u\n"), info->split.cur_part_number, info->split.total_parts); } diff --git a/src/extract.c b/src/extract.c index a8864af0..d4efc24e 100644 --- a/src/extract.c +++ b/src/extract.c @@ -1269,32 +1269,38 @@ extract_stream_list(struct apply_ctx *ctx) /* Read the header from a stream in a pipable WIM. */ static int read_pwm_stream_header(WIMStruct *pwm, struct wim_lookup_table_entry *lte, - int flags) + int flags, struct wim_header_disk *hdr_ret) { - struct pwm_stream_hdr stream_hdr; + union { + struct pwm_stream_hdr stream_hdr; + struct wim_header_disk pwm_hdr; + } buf; int ret; - ret = full_read(&pwm->in_fd, &stream_hdr, sizeof(stream_hdr)); + ret = full_read(&pwm->in_fd, &buf.stream_hdr, sizeof(buf.stream_hdr)); if (ret) goto read_error; - if ((flags & PWM_ALLOW_WIM_HDR) && stream_hdr.magic == PWM_MAGIC) { - u8 buf[WIM_HEADER_DISK_SIZE - sizeof(stream_hdr)]; - ret = full_read(&pwm->in_fd, buf, sizeof(buf)); + if ((flags & PWM_ALLOW_WIM_HDR) && buf.stream_hdr.magic == PWM_MAGIC) { + BUILD_BUG_ON(sizeof(buf.pwm_hdr) < sizeof(buf.stream_hdr)); + ret = full_read(&pwm->in_fd, &buf.stream_hdr + 1, + sizeof(buf.pwm_hdr) - sizeof(buf.stream_hdr)); + if (ret) goto read_error; lte->resource_location = RESOURCE_NONEXISTENT; + memcpy(hdr_ret, &buf.pwm_hdr, sizeof(buf.pwm_hdr)); return 0; } - if (stream_hdr.magic != PWM_STREAM_MAGIC) { + if (buf.stream_hdr.magic != PWM_STREAM_MAGIC) { ERROR("Data read on pipe is invalid (expected stream header)."); return WIMLIB_ERR_INVALID_PIPABLE_WIM; } - lte->resource_entry.original_size = le64_to_cpu(stream_hdr.uncompressed_size); - copy_hash(lte->hash, stream_hdr.hash); - lte->resource_entry.flags = le32_to_cpu(stream_hdr.flags); + lte->resource_entry.original_size = le64_to_cpu(buf.stream_hdr.uncompressed_size); + copy_hash(lte->hash, buf.stream_hdr.hash); + lte->resource_entry.flags = le32_to_cpu(buf.stream_hdr.flags); lte->resource_entry.offset = pwm->in_fd.offset; lte->resource_location = RESOURCE_IN_WIM; lte->wim = pwm; @@ -1330,6 +1336,7 @@ extract_streams_from_pipe(struct apply_ctx *ctx) struct wim_lookup_table_entry *found_lte; struct wim_lookup_table_entry *needed_lte; struct wim_lookup_table *lookup_table; + struct wim_header_disk pwm_hdr; int ret; int pwm_flags; @@ -1342,8 +1349,15 @@ extract_streams_from_pipe(struct apply_ctx *ctx) pwm_flags = PWM_ALLOW_WIM_HDR; if ((ctx->extract_flags & WIMLIB_EXTRACT_FLAG_RESUME)) pwm_flags |= PWM_SILENT_EOF; + memcpy(ctx->progress.extract.guid, ctx->wim->hdr.guid, WIM_GID_LEN); + ctx->progress.extract.part_number = ctx->wim->hdr.part_number; + ctx->progress.extract.total_parts = ctx->wim->hdr.total_parts; + if (ctx->progress_func) + ctx->progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN, + &ctx->progress); while (ctx->num_streams_remaining) { - ret = read_pwm_stream_header(ctx->wim, found_lte, pwm_flags); + ret = read_pwm_stream_header(ctx->wim, found_lte, pwm_flags, + &pwm_hdr); if (ret) { if (ret == WIMLIB_ERR_UNEXPECTED_END_OF_FILE && (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_RESUME)) @@ -1373,6 +1387,26 @@ extract_streams_from_pipe(struct apply_ctx *ctx) ret = skip_pwm_stream(found_lte); if (ret) goto out_free_found_lte; + } else { + 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 || + memcmp(pwm_hdr.guid, ctx->progress.extract.guid, + WIM_GID_LEN)) + { + ctx->progress.extract.part_number = part_number; + ctx->progress.extract.total_parts = total_parts; + memcpy(ctx->progress.extract.guid, + pwm_hdr.guid, WIM_GID_LEN); + if (ctx->progress_func) { + ctx->progress_func( + WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN, + &ctx->progress); + } + + } } } ret = 0; @@ -2660,7 +2694,7 @@ wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name, * WIMs.) */ { struct wim_lookup_table_entry xml_lte; - ret = read_pwm_stream_header(pwm, &xml_lte, 0); + ret = read_pwm_stream_header(pwm, &xml_lte, 0, NULL); if (ret) goto out_wimlib_free; @@ -2720,7 +2754,7 @@ wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name, goto out_wimlib_free; } - ret = read_pwm_stream_header(pwm, metadata_lte, 0); + ret = read_pwm_stream_header(pwm, metadata_lte, 0, NULL); imd = pwm->image_metadata[i - 1]; imd->metadata_lte = metadata_lte; if (ret) diff --git a/src/header.c b/src/header.c index 906d8e75..13b098dc 100644 --- a/src/header.c +++ b/src/header.c @@ -45,69 +45,6 @@ # include #endif -/* On-disk format of the WIM header. */ -struct wim_header_disk { - - /* Magic characters "MSWIM\0\0\0" */ - le64 magic; - - /* Size of the WIM header, in bytes; WIM_HEADER_DISK_SIZE expected - * (currently the only supported value). */ - u32 hdr_size; - - /* Version of the WIM file; WIM_VERSION expected (currently the only - * supported value). */ - u32 wim_version; - - /* Flags for the WIM file (WIM_HDR_FLAG_*) */ - u32 wim_flags; - - /* Uncompressed chunk size of resources in the WIM. 0 if the WIM is - * uncompressed. If compressed, WIM_CHUNK_SIZE is expected (currently - * the only supported value). */ - u32 chunk_size; - - /* Globally unique identifier for the WIM file. Basically a bunch of - * random bytes. */ - u8 guid[WIM_GID_LEN]; - - /* Number of this WIM part in the split WIM file, indexed from 1, or 1 - * if the WIM is not split. */ - u16 part_number; - - /* Total number of parts of the split WIM file, or 1 if the WIM is not - * split. */ - u16 total_parts; - - /* Number of images in the WIM. */ - u32 image_count; - - /* Location and size of the WIM's lookup table. */ - struct resource_entry_disk lookup_table_res_entry; - - /* Location and size of the WIM's XML data. */ - struct resource_entry_disk xml_data_res_entry; - - /* Location and size of metadata resource for the bootable image of the - * WIM, or all zeroes if no image is bootable. */ - struct resource_entry_disk boot_metadata_res_entry; - - /* 1-based index of the bootable image of the WIM, or 0 if no image is - * bootable. */ - u32 boot_idx; - - /* Location and size of the WIM's integrity table, or all zeroes if the - * WIM has no integrity table. - * - * Note the integrity_table_res_entry here is 4-byte aligned even though - * it would ordinarily be 8-byte aligned--- hence, the _packed_attribute - * on the `struct wim_header_disk' is essential. */ - struct resource_entry_disk integrity_table_res_entry; - - /* Unused bytes. */ - u8 unused[60]; -} _packed_attribute; - /* * Reads the header from a WIM file. *