Add WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN
authorEric Biggers <ebiggers3@gmail.com>
Fri, 16 Aug 2013 02:11:04 +0000 (21:11 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Fri, 16 Aug 2013 02:11:04 +0000 (21:11 -0500)
include/wimlib.h
include/wimlib/header.h
programs/imagex.c
src/extract.c
src/header.c

index 0c14941..340a963 100644 (file)
@@ -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,
index 637a4fe..efca274 100644 (file)
                            ((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.  */
index 977f21b..90b53dd 100644 (file)
@@ -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);
                }
index a8864af..d4efc24 100644 (file)
@@ -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)
index 906d8e7..13b098d 100644 (file)
 #  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.
  *