Add 'wimlib-imagex verify' command
authorEric Biggers <ebiggers3@gmail.com>
Mon, 28 Jul 2014 03:02:28 +0000 (22:02 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Mon, 28 Jul 2014 03:13:02 +0000 (22:13 -0500)
Makefile.am
NEWS
configure.ac
doc/man1/imagex-optimize.1.in
doc/man1/imagex-verify.1.in [new file with mode: 0644]
programs/imagex.c

index beaedc4..0d3d0f0 100644 (file)
@@ -209,7 +209,8 @@ imagex_cmds =       append  \
                optimize\
                split   \
                unmount \
-               update
+               update  \
+               verify
 
 install-exec-hook:
        if [ "@IMAGEX_PROGNAME@" != imagex ]; then                          \
@@ -283,6 +284,7 @@ wimlib_manpages =                           \
        doc/man1/@IMAGEX_PROGNAME@-split.1              \
        doc/man1/@IMAGEX_PROGNAME@-unmount.1            \
        doc/man1/@IMAGEX_PROGNAME@-update.1             \
+       doc/man1/@IMAGEX_PROGNAME@-verify.1             \
        doc/man1/mkwinpeimg.1
 
 man1_MANS = $(wimlib_manpages)
diff --git a/NEWS b/NEWS
index 2198d08..752f9de 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -24,6 +24,8 @@ Version 1.7.1-BETA:
        "standard" names: '--solid', '--solid-compress', and
        '--solid-chunk-size', respectively.
 
+       Added 'verify' subcommand to 'wimlib-imagex'.
+
        The XPRESS compressor no longer supports chunks larger than 65536 bytes.
        There is little point in having larger chunks, since the LZ77 sliding
        window for XPRESS cannot be larger than 65536 bytes.  This change does
@@ -56,6 +58,8 @@ Version 1.7.1-BETA:
                error messages to be sent to, rather than the default of
                standard error.
 
+               New function: wimlib_verify_wim().
+
 Version 1.7.0:
        Improved compression, decompression, and extraction performance.
 
index c9737fb..4c22938 100644 (file)
@@ -40,6 +40,7 @@ AC_CONFIG_FILES([Makefile]
                [doc/man1/"$IMAGEX_PROGNAME"-split.1:doc/man1/imagex-split.1.in]
                [doc/man1/"$IMAGEX_PROGNAME"-unmount.1:doc/man1/imagex-unmount.1.in]
                [doc/man1/"$IMAGEX_PROGNAME"-update.1:doc/man1/imagex-update.1.in]
+               [doc/man1/"$IMAGEX_PROGNAME"-verify.1:doc/man1/imagex-verify.1.in]
                [doc/man1/mkwinpeimg.1])
 
 AC_CONFIG_FILES([programs/mkwinpeimg], [chmod +x programs/mkwinpeimg])
index 6789419..2d296c7 100644 (file)
@@ -33,7 +33,7 @@ better job than the program that wrote the original file.  A side effect of this
 is that every stream in the original WIM will be checksummed, so this can help
 verify that the WIM is intact (equivalent to applying all the images from it).
 .TP
-\fB--compress\fR=\fITYPE\fR[:\fILEVEL\fR
+\fB--compress\fR=\fITYPE\fR[:\fILEVEL\fR]
 Recompress the WIM file using the specified compression type, and optionally the
 specified compression level for that compression type.  This implies
 \fB--recompress\fR.
@@ -88,3 +88,4 @@ Rebuild the WIM in the non-pipable format.  (This is the default if
 .SH SEE ALSO
 .BR @IMAGEX_PROGNAME@ (1)
 .BR @IMAGEX_PROGNAME@-export (1)
+.BR @IMAGEX_PROGNAME@-verify (1)
diff --git a/doc/man1/imagex-verify.1.in b/doc/man1/imagex-verify.1.in
new file mode 100644 (file)
index 0000000..5b21cf1
--- /dev/null
@@ -0,0 +1,55 @@
+.TH WIMLIB-IMAGEX "1" "June 2014" "@IMAGEX_PROGNAME@ @VERSION@" "User Commands"
+.SH NAME
+@IMAGEX_PROGNAME@-verify \- Verify a WIM file
+.SH SYNOPSIS
+\fB@IMAGEX_PROGNAME@ verify\fR \fIWIMFILE\fR [\fIOPTION\fR...]
+.SH DESCRIPTION
+\fB@IMAGEX_PROGNAME@ verify\fR checks the validity of the specified WIM archive.
+This command is also available as simply \fBwimverify\fR if the appropriate hard
+link or batch file has been installed.
+.PP
+Specifically, this command performs the following verifications on the WIM
+archive:
+.IP \[bu] 4
+Verify that the WIM file can be successfully opened, which involves parsing the
+header, lookup table, and XML data.
+.IP \[bu]
+If the WIM archive contains an integrity table, verify the integrity of the
+entire WIM archive.  Otherwise, print a warning.
+.IP \[bu]
+Verify that the metadata for each image in the WIM archive can be successfully
+parsed.
+.IP \[bu]
+Verify that all files needed by each image are actually contained in the WIM
+archive or in one of the WIM archives referenced by the \fB--ref\fR option.
+.IP \[bu]
+Verify that all files contained in the WIM archive can be successfully
+decompressed, with matching cryptographic checksums.
+.SH OPTIONS
+.TP 6
+\fB--ref\fR="\fIGLOB\fR"
+File glob of additional WIMs or split WIM parts to reference resources from.
+This option can be specified multiple times.  Note: \fIGLOB\fR is listed in
+quotes because it is interpreted by \fB@IMAGEX_PROGNAME@\fR and may need to be
+quoted to protect against shell expansion.
+.SH NOTES
+This is a read-only command.  It will never modify the WIM file.
+.PP
+In the future, this command might do more thorough verifications than it does
+now.
+.SH EXAMPLES
+Verify the WIM file 'boot.wim':
+.RS
+.PP
+wimverify boot.wim
+.RE
+.PP
+Verify the split WIM file consisting of 'boot.swm', 'boot2.swm', 'boot3.swm', ...:
+.RS
+.PP
+wimverify boot.swm --ref="boot*.swm"
+.RE
+.PP
+.SH SEE ALSO
+.BR @IMAGEX_PROGNAME@ (1)
+.BR @IMAGEX_PROGNAME@-optimize (1)
index 6dd8bdb..60b533c 100644 (file)
@@ -124,6 +124,7 @@ enum {
        CMD_UNMOUNT,
 #endif
        CMD_UPDATE,
+       CMD_VERIFY,
        CMD_MAX,
 };
 
@@ -404,6 +405,12 @@ static const struct option update_options[] = {
        {NULL, 0, NULL, 0},
 };
 
+static const struct option verify_options[] = {
+       {T("ref"), required_argument, NULL, IMAGEX_REF_OPTION},
+
+       {NULL, 0, NULL, 0},
+};
+
 #if 0
 #      define _format_attribute(type, format_str, args_start) \
                        __attribute__((format(type, format_str, args_start)))
@@ -1234,6 +1241,25 @@ imagex_progress_func(enum wimlib_progress_msg msg,
                        }
                }
                break;
+       case WIMLIB_PROGRESS_MSG_BEGIN_VERIFY_IMAGE:
+               imagex_printf(T("Verifying metadata for image %"PRIu32" of %"PRIu32"\n"),
+                             info->verify_image.current_image,
+                             info->verify_image.total_images);
+               break;
+       case WIMLIB_PROGRESS_MSG_VERIFY_STREAMS:
+               percent_done = TO_PERCENT(info->verify_streams.completed_bytes,
+                                         info->verify_streams.total_bytes);
+               unit_shift = get_unit(info->verify_streams.total_bytes, &unit_name);
+               imagex_printf(T("\rVerifying streams: "
+                         "%"PRIu64" %"TS" of %"PRIu64" %"TS" (%u%%) done"),
+                       info->verify_streams.completed_bytes >> unit_shift,
+                       unit_name,
+                       info->verify_streams.total_bytes >> unit_shift,
+                       unit_name,
+                       percent_done);
+               if (info->verify_streams.completed_bytes == info->verify_streams.total_bytes)
+                       imagex_printf(T("\n"));
+               break;
        default:
                break;
        }
@@ -3959,7 +3985,82 @@ out_err:
        goto out_free_command_str;
 }
 
+/* Verify a WIM file.  */
+static int
+imagex_verify(int argc, tchar **argv, int cmd)
+{
+       int ret;
+       const tchar *wimfile;
+       WIMStruct *wim;
+       int open_flags = WIMLIB_OPEN_FLAG_CHECK_INTEGRITY;
+       int verify_flags = 0;
+       STRING_SET(refglobs);
+       int c;
+
+       for_opt(c, verify_options) {
+               switch (c) {
+               case IMAGEX_REF_OPTION:
+                       ret = string_set_append(&refglobs, optarg);
+                       if (ret)
+                               goto out_free_refglobs;
+                       break;
+               default:
+                       goto out_usage;
+               }
+       }
 
+       argv += optind;
+       argc -= optind;
+
+       if (argc != 1) {
+               if (argc == 0)
+                       imagex_error(T("Must specify a WIM file!"));
+               else
+                       imagex_error(T("At most one WIM file can be specified!"));
+               goto out_usage;
+       }
+
+       wimfile = argv[0];
+
+       ret = wimlib_open_wim_with_progress(wimfile,
+                                           open_flags,
+                                           &wim,
+                                           imagex_progress_func,
+                                           NULL);
+       if (ret)
+               goto out_free_refglobs;
+
+       ret = wim_reference_globs(wim, &refglobs, open_flags);
+       if (ret)
+               goto out_wimlib_free;
+
+       ret = wimlib_verify_wim(wim, verify_flags);
+       if (ret) {
+               tputc(T('\n'), stderr);
+               imagex_error(T("\"%"TS"\" failed verification!"),
+                            wimfile);
+               if (ret == WIMLIB_ERR_RESOURCE_NOT_FOUND &&
+                   refglobs.num_strings == 0)
+               {
+                       imagex_printf(T("Note: if this WIM file is not standalone, "
+                                       "use the --ref option to specify the other parts.\n"));
+               }
+       } else {
+               imagex_printf(T("\n\"%"TS"\" was successfully verified.\n"),
+                             wimfile);
+       }
+
+out_wimlib_free:
+       wimlib_free(wim);
+out_free_refglobs:
+       string_set_destroy(&refglobs);
+       return ret;
+
+out_usage:
+       usage(CMD_VERIFY, stderr);
+       ret = -1;
+       goto out_free_refglobs;
+}
 
 struct imagex_command {
        const tchar *name;
@@ -3986,6 +4087,7 @@ static const struct imagex_command imagex_commands[] = {
        [CMD_UNMOUNT]  = {T("unmount"),  imagex_unmount},
 #endif
        [CMD_UPDATE]   = {T("update"),   imagex_update},
+       [CMD_VERIFY]   = {T("verify"),   imagex_verify},
 };
 
 #ifdef __WIN32__
@@ -4105,6 +4207,10 @@ T(
 "                    [--command=STRING] [--wimboot-config=FILE]\n"
 "                    [< CMDFILE]\n"
 ),
+[CMD_VERIFY] =
+T(
+"    %"TS" WIMFILE [--ref=\"GLOB\"]\n"
+),
 };
 
 static const tchar *invocation_name;