# define _wimlib_deprecated
#endif
+#define WIMLIB_GUID_LEN 16
+
/**
* Specifies the compression type of a WIM file.
*/
* 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
* 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. */
* 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 {
* 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:
* 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,
((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. */
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"));
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);
}
/* 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;
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;
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))
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;
* 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;
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)
# include <stdlib.h>
#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.
*