From 4011d97c445ef525472ffe89ba4ab5d63e35b169 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 27 Jul 2014 22:02:28 -0500 Subject: [PATCH] Add 'wimlib-imagex verify' command --- Makefile.am | 4 +- NEWS | 4 ++ configure.ac | 1 + doc/man1/imagex-optimize.1.in | 3 +- doc/man1/imagex-verify.1.in | 55 ++++++++++++++++++ programs/imagex.c | 106 ++++++++++++++++++++++++++++++++++ 6 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 doc/man1/imagex-verify.1.in diff --git a/Makefile.am b/Makefile.am index beaedc4b..0d3d0f04 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 2198d08a..752f9def 100644 --- 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. diff --git a/configure.ac b/configure.ac index c9737fbf..4c22938e 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/doc/man1/imagex-optimize.1.in b/doc/man1/imagex-optimize.1.in index 67894196..2d296c72 100644 --- a/doc/man1/imagex-optimize.1.in +++ b/doc/man1/imagex-optimize.1.in @@ -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 index 00000000..5b21cf17 --- /dev/null +++ b/doc/man1/imagex-verify.1.in @@ -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) diff --git a/programs/imagex.c b/programs/imagex.c index 6dd8bdbb..60b533c3 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -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; -- 2.43.0