]> wimlib.net Git - wimlib/blobdiff - programs/imagex.c
Don't use the old ADD_IMAGE flag names
[wimlib] / programs / imagex.c
index 6351475f5178494656bd5f653d2432d8c918c588..19ef736124a58eac0a9d519cbac3d3da23e1bf5d 100644 (file)
@@ -46,6 +46,8 @@
 #  include <alloca.h>
 #endif
 
+#define WIMLIB_COMPRESSION_TYPE_INVALID (-1)
+
 #ifdef __WIN32__
 #  include "imagex-win32.h"
 #  define print_security_descriptor     win32_print_security_descriptor
@@ -122,6 +124,7 @@ enum {
        CMD_UNMOUNT,
 #endif
        CMD_UPDATE,
+       CMD_VERIFY,
        CMD_MAX,
 };
 
@@ -166,12 +169,9 @@ enum {
        IMAGEX_NO_ACLS_OPTION,
        IMAGEX_NO_ATTRIBUTES_OPTION,
        IMAGEX_NO_REPLACE_OPTION,
-       IMAGEX_NO_WILDCARDS_OPTION,
+       IMAGEX_NO_GLOBS_OPTION,
        IMAGEX_NULLGLOB_OPTION,
        IMAGEX_ONE_FILE_ONLY_OPTION,
-       IMAGEX_PACK_CHUNK_SIZE_OPTION,
-       IMAGEX_PACK_COMPRESS_OPTION,
-       IMAGEX_PACK_STREAMS_OPTION,
        IMAGEX_PATH_OPTION,
        IMAGEX_PIPABLE_OPTION,
        IMAGEX_PRESERVE_DIR_STRUCTURE_OPTION,
@@ -182,6 +182,9 @@ enum {
        IMAGEX_RESUME_OPTION,
        IMAGEX_RPFIX_OPTION,
        IMAGEX_SOFT_OPTION,
+       IMAGEX_SOLID_OPTION,
+       IMAGEX_SOLID_CHUNK_SIZE_OPTION,
+       IMAGEX_SOLID_COMPRESS_OPTION,
        IMAGEX_SOURCE_LIST_OPTION,
        IMAGEX_STAGING_DIR_OPTION,
        IMAGEX_STREAMS_INTERFACE_OPTION,
@@ -223,12 +226,12 @@ static const struct option capture_or_append_options[] = {
        {T("compress"),    required_argument, NULL, IMAGEX_COMPRESS_OPTION},
        {T("compress-slow"), no_argument,     NULL, IMAGEX_COMPRESS_SLOW_OPTION},
        {T("chunk-size"),  required_argument, NULL, IMAGEX_CHUNK_SIZE_OPTION},
-       {T("pack-chunk-size"), required_argument, NULL, IMAGEX_PACK_CHUNK_SIZE_OPTION},
-       {T("solid-chunk-size"),required_argument, NULL, IMAGEX_PACK_CHUNK_SIZE_OPTION},
-       {T("pack-compress"), required_argument, NULL, IMAGEX_PACK_COMPRESS_OPTION},
-       {T("solid-compress"),required_argument, NULL, IMAGEX_PACK_COMPRESS_OPTION},
-       {T("pack-streams"), no_argument,      NULL, IMAGEX_PACK_STREAMS_OPTION},
-       {T("solid"),       no_argument,      NULL, IMAGEX_PACK_STREAMS_OPTION},
+       {T("solid"),       no_argument,      NULL, IMAGEX_SOLID_OPTION},
+       {T("pack-streams"), no_argument,      NULL, IMAGEX_SOLID_OPTION},
+       {T("solid-compress"),required_argument, NULL, IMAGEX_SOLID_COMPRESS_OPTION},
+       {T("pack-compress"), required_argument, NULL, IMAGEX_SOLID_COMPRESS_OPTION},
+       {T("solid-chunk-size"),required_argument, NULL, IMAGEX_SOLID_CHUNK_SIZE_OPTION},
+       {T("pack-chunk-size"), required_argument, NULL, IMAGEX_SOLID_CHUNK_SIZE_OPTION},
        {T("config"),      required_argument, NULL, IMAGEX_CONFIG_OPTION},
        {T("dereference"), no_argument,       NULL, IMAGEX_DEREFERENCE_OPTION},
        {T("flags"),       required_argument, NULL, IMAGEX_FLAGS_OPTION},
@@ -269,14 +272,15 @@ static const struct option export_options[] = {
        {T("nocheck"),     no_argument,       NULL, IMAGEX_NOCHECK_OPTION},
        {T("no-check"),    no_argument,       NULL, IMAGEX_NOCHECK_OPTION},
        {T("compress"),    required_argument, NULL, IMAGEX_COMPRESS_OPTION},
+       {T("recompress"),  no_argument,       NULL, IMAGEX_RECOMPRESS_OPTION},
        {T("compress-slow"), no_argument,     NULL, IMAGEX_COMPRESS_SLOW_OPTION},
-       {T("pack-streams"),no_argument,       NULL, IMAGEX_PACK_STREAMS_OPTION},
-       {T("solid"),       no_argument,       NULL, IMAGEX_PACK_STREAMS_OPTION},
        {T("chunk-size"),  required_argument, NULL, IMAGEX_CHUNK_SIZE_OPTION},
-       {T("pack-chunk-size"), required_argument, NULL, IMAGEX_PACK_CHUNK_SIZE_OPTION},
-       {T("solid-chunk-size"),required_argument, NULL, IMAGEX_PACK_CHUNK_SIZE_OPTION},
-       {T("pack-compress"), required_argument, NULL, IMAGEX_PACK_COMPRESS_OPTION},
-       {T("solid-compress"),required_argument, NULL, IMAGEX_PACK_COMPRESS_OPTION},
+       {T("solid"),       no_argument,       NULL, IMAGEX_SOLID_OPTION},
+       {T("pack-streams"),no_argument,       NULL, IMAGEX_SOLID_OPTION},
+       {T("solid-compress"),required_argument, NULL, IMAGEX_SOLID_COMPRESS_OPTION},
+       {T("pack-compress"), required_argument, NULL, IMAGEX_SOLID_COMPRESS_OPTION},
+       {T("solid-chunk-size"),required_argument, NULL, IMAGEX_SOLID_CHUNK_SIZE_OPTION},
+       {T("pack-chunk-size"), required_argument, NULL, IMAGEX_SOLID_CHUNK_SIZE_OPTION},
        {T("ref"),         required_argument, NULL, IMAGEX_REF_OPTION},
        {T("threads"),     required_argument, NULL, IMAGEX_THREADS_OPTION},
        {T("rebuild"),     no_argument,       NULL, IMAGEX_REBUILD_OPTION},
@@ -298,7 +302,8 @@ static const struct option extract_options[] = {
        {T("dest-dir"),    required_argument, NULL, IMAGEX_DEST_DIR_OPTION},
        {T("to-stdout"),   no_argument,       NULL, IMAGEX_TO_STDOUT_OPTION},
        {T("include-invalid-names"), no_argument, NULL, IMAGEX_INCLUDE_INVALID_NAMES_OPTION},
-       {T("no-wildcards"), no_argument,      NULL, IMAGEX_NO_WILDCARDS_OPTION},
+       {T("no-wildcards"), no_argument,      NULL, IMAGEX_NO_GLOBS_OPTION},
+       {T("no-globs"),     no_argument,      NULL, IMAGEX_NO_GLOBS_OPTION},
        {T("nullglob"),     no_argument,      NULL, IMAGEX_NULLGLOB_OPTION},
        {T("preserve-dir-structure"), no_argument, NULL, IMAGEX_PRESERVE_DIR_STRUCTURE_OPTION},
        {T("wimboot"),     no_argument,       NULL, IMAGEX_WIMBOOT_OPTION},
@@ -341,14 +346,14 @@ static const struct option optimize_options[] = {
        {T("compress"),    required_argument, NULL, IMAGEX_COMPRESS_OPTION},
        {T("recompress"),  no_argument,       NULL, IMAGEX_RECOMPRESS_OPTION},
        {T("compress-slow"), no_argument,     NULL, IMAGEX_COMPRESS_SLOW_OPTION},
-       {T("recompress-slow"), no_argument,     NULL, IMAGEX_COMPRESS_SLOW_OPTION},
+       {T("recompress-slow"), no_argument,   NULL, IMAGEX_COMPRESS_SLOW_OPTION},
        {T("chunk-size"),  required_argument, NULL, IMAGEX_CHUNK_SIZE_OPTION},
-       {T("pack-chunk-size"), required_argument, NULL, IMAGEX_PACK_CHUNK_SIZE_OPTION},
-       {T("solid-chunk-size"),required_argument, NULL, IMAGEX_PACK_CHUNK_SIZE_OPTION},
-       {T("pack-compress"), required_argument, NULL, IMAGEX_PACK_COMPRESS_OPTION},
-       {T("solid-compress"),required_argument, NULL, IMAGEX_PACK_COMPRESS_OPTION},
-       {T("pack-streams"),no_argument,       NULL, IMAGEX_PACK_STREAMS_OPTION},
-       {T("solid"),       no_argument,       NULL, IMAGEX_PACK_STREAMS_OPTION},
+       {T("solid"),       no_argument,       NULL, IMAGEX_SOLID_OPTION},
+       {T("pack-streams"),no_argument,       NULL, IMAGEX_SOLID_OPTION},
+       {T("solid-compress"),required_argument, NULL, IMAGEX_SOLID_COMPRESS_OPTION},
+       {T("pack-compress"), required_argument, NULL, IMAGEX_SOLID_COMPRESS_OPTION},
+       {T("solid-chunk-size"),required_argument, NULL, IMAGEX_SOLID_CHUNK_SIZE_OPTION},
+       {T("pack-chunk-size"), required_argument, NULL, IMAGEX_SOLID_CHUNK_SIZE_OPTION},
        {T("threads"),     required_argument, NULL, IMAGEX_THREADS_OPTION},
        {T("pipable"),     no_argument,       NULL, IMAGEX_PIPABLE_OPTION},
        {T("not-pipable"), no_argument,       NULL, IMAGEX_NOT_PIPABLE_OPTION},
@@ -365,6 +370,7 @@ static const struct option unmount_options[] = {
        {T("check"),   no_argument, NULL, IMAGEX_CHECK_OPTION},
        {T("rebuild"), no_argument, NULL, IMAGEX_REBUILD_OPTION},
        {T("lazy"),    no_argument, NULL, IMAGEX_LAZY_OPTION},
+       {T("force"),    no_argument, NULL, IMAGEX_FORCE_OPTION},
        {T("new-image"), no_argument, NULL, IMAGEX_NEW_IMAGE_OPTION},
        {NULL, 0, NULL, 0},
 };
@@ -399,6 +405,13 @@ static const struct option update_options[] = {
        {NULL, 0, NULL, 0},
 };
 
+static const struct option verify_options[] = {
+       {T("ref"), required_argument, NULL, IMAGEX_REF_OPTION},
+       {T("nocheck"), no_argument, NULL, IMAGEX_NOCHECK_OPTION},
+
+       {NULL, 0, NULL, 0},
+};
+
 #if 0
 #      define _format_attribute(type, format_str, args_start) \
                        __attribute__((format(type, format_str, args_start)))
@@ -469,66 +482,74 @@ verify_image_exists_and_is_single(int image, const tchar *image_name,
        return ret;
 }
 
+static void
+print_available_compression_types(FILE *fp)
+{
+       static const tchar *s =
+       T(
+       "Available compression types:\n"
+       "\n"
+       "    none\n"
+       "    xpress (alias: \"fast\")\n"
+       "    lzx    (alias: \"maximum\") (default for capture)\n"
+       "    lzms   (alias: \"recovery\")\n"
+       "\n"
+       );
+       tfputs(s, fp);
+}
+
 /* Parse the argument to --compress */
 static int
-get_compression_type(const tchar *optarg)
+get_compression_type(tchar *optarg)
 {
+       int ctype;
+       unsigned int compression_level = 0;
+       tchar *plevel;
+
+       plevel = tstrchr(optarg, T(':'));
+       if (plevel) {
+               tchar *ptmp;
+               unsigned long ultmp;
+
+               *plevel++ = T('\0');
+               ultmp = tstrtoul(plevel, &ptmp, 10);
+               if (ultmp >= UINT_MAX || ultmp == 0 || *ptmp || ptmp == plevel) {
+                       imagex_error(T("Compression level must be a positive integer! "
+                                      "e.g. --compress=lzx:80"));
+                       return WIMLIB_COMPRESSION_TYPE_INVALID;
+               }
+               compression_level = ultmp;
+       }
+
        if (!tstrcasecmp(optarg, T("maximum")) ||
            !tstrcasecmp(optarg, T("lzx")) ||
            !tstrcasecmp(optarg, T("max")))
-               return WIMLIB_COMPRESSION_TYPE_LZX;
+               ctype = WIMLIB_COMPRESSION_TYPE_LZX;
        else if (!tstrcasecmp(optarg, T("fast")) || !tstrcasecmp(optarg, T("xpress")))
-               return WIMLIB_COMPRESSION_TYPE_XPRESS;
+               ctype = WIMLIB_COMPRESSION_TYPE_XPRESS;
        else if (!tstrcasecmp(optarg, T("recovery")) || !tstrcasecmp(optarg, T("lzms")))
-               return WIMLIB_COMPRESSION_TYPE_LZMS;
+               ctype = WIMLIB_COMPRESSION_TYPE_LZMS;
        else if (!tstrcasecmp(optarg, T("none")))
-               return WIMLIB_COMPRESSION_TYPE_NONE;
+               ctype = WIMLIB_COMPRESSION_TYPE_NONE;
        else {
-               imagex_error(T("Invalid compression type \"%"TS"\"! Must be "
-                            "\"maximum\", \"fast\", or \"none\"."), optarg);
+               imagex_error(T("Invalid compression type \"%"TS"\"!"), optarg);
+               print_available_compression_types(stderr);
                return WIMLIB_COMPRESSION_TYPE_INVALID;
        }
+
+       if (compression_level != 0)
+               wimlib_set_default_compression_level(ctype, compression_level);
+       return ctype;
 }
 
 static void
 set_compress_slow(void)
 {
-       static const struct wimlib_lzx_compressor_params lzx_slow_params = {
-               .hdr = {
-                       .size = sizeof(struct wimlib_lzx_compressor_params),
-               },
-               .algorithm = WIMLIB_LZX_ALGORITHM_SLOW,
-               .alg_params = {
-                       .slow = {
-                               .use_len2_matches = 1,
-                               .nice_match_length = 96,
-                               .num_optim_passes = 4,
-                               .max_search_depth = 100,
-                               .max_matches_per_pos = 10,
-                               .main_nostat_cost = 15,
-                               .len_nostat_cost = 15,
-                               .aligned_nostat_cost = 7,
-                       },
-               },
-       };
-
-       static const struct wimlib_lzms_compressor_params lzms_slow_params = {
-               .hdr = {
-                       .size = sizeof(struct wimlib_lzms_compressor_params),
-               },
-               .min_match_length = 2,
-               .max_match_length = UINT32_MAX,
-               .nice_match_length = 96,
-               .max_search_depth = 100,
-               .max_matches_per_pos = 10,
-               .optim_array_length = 1024,
-       };
-
-       wimlib_set_default_compressor_params(WIMLIB_COMPRESSION_TYPE_LZX,
-                                            &lzx_slow_params.hdr);
-
-       wimlib_set_default_compressor_params(WIMLIB_COMPRESSION_TYPE_LZMS,
-                                            &lzms_slow_params.hdr);
+#if 0
+       fprintf(stderr, "WARNING: the '--compress-slow' option is deprecated.\n"
+                       "         Use the '--compress=TYPE:LEVEL' option instead.\n");
+#endif
+       wimlib_set_default_compression_level(-1, 100);
 }
 
 struct string_set {
@@ -1078,24 +1099,13 @@ imagex_progress_func(enum wimlib_progress_msg msg,
                        imagex_printf(T("\nWARNING: Excluding unsupported file or directory\n"
                                        "         \"%"TS"\" from capture\n"), info->scan.cur_path);
                        break;
-               case WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK:
-                       imagex_printf(T("\nWARNING: Ignoring absolute symbolic link "
-                                       "with out-of-tree target:\n"
-                                       "           \"%"TS"\" => \"%"TS"\"\n"
-                                       "           (Use --norpfix to capture "
-                                       "absolute symbolic links as-is)\n"),
-                                       info->scan.cur_path, info->scan.symlink_target);
-                       break;
                case WIMLIB_SCAN_DENTRY_FIXED_SYMLINK:
                        /* Symlink fixups are enabled by default.  This is
                         * mainly intended for Windows, which for some reason
                         * uses absolute junctions (with drive letters!) in the
                         * default installation.  On UNIX-like systems, warn the
                         * user when fixing the target of an absolute symbolic
-                        * link, so they know to disable this if they want.
-                        * (Although, more likely they will get the warning
-                        * about an absolute symbolic link with an out-of-tree
-                        * target first.)  */
+                        * link, so they know to disable this if they want.  */
                #ifndef __WIN32__
                        imagex_printf(T("\nWARNING: Adjusted target of "
                                        "absolute symbolic link \"%"TS"\"\n"
@@ -1104,6 +1114,8 @@ imagex_progress_func(enum wimlib_progress_msg msg,
                                        info->scan.cur_path);
                #endif
                        break;
+               default:
+                       break;
                }
                break;
        case WIMLIB_PROGRESS_MSG_SCAN_END:
@@ -1149,6 +1161,17 @@ imagex_progress_func(enum wimlib_progress_msg msg,
                         T("NTFS volume") : T("directory")),
                        info->extract.target);
                break;
+       case WIMLIB_PROGRESS_MSG_EXTRACT_FILE_STRUCTURE:
+               if (info->extract.end_file_count >= 2000) {
+                       percent_done = TO_PERCENT(info->extract.current_file_count,
+                                                 info->extract.end_file_count);
+                       imagex_printf(T("\rCreating files: %"PRIu64" of %"PRIu64" (%u%%) done"),
+                                     info->extract.current_file_count,
+                                     info->extract.end_file_count, percent_done);
+                       if (info->extract.current_file_count == info->extract.end_file_count)
+                               imagex_printf(T("\n"));
+               }
+               break;
        case WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS:
                percent_done = TO_PERCENT(info->extract.completed_bytes,
                                          info->extract.total_bytes);
@@ -1163,6 +1186,17 @@ 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_METADATA:
+               if (info->extract.end_file_count >= 2000) {
+                       percent_done = TO_PERCENT(info->extract.current_file_count,
+                                                 info->extract.end_file_count);
+                       imagex_printf(T("\rApplying metadata to files: %"PRIu64" of %"PRIu64" (%u%%) done"),
+                                     info->extract.current_file_count,
+                                     info->extract.end_file_count, percent_done);
+                       if (info->extract.current_file_count == info->extract.end_file_count)
+                               imagex_printf(T("\n"));
+               }
+               break;
        case WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN:
                if (info->extract.total_parts != 1) {
                        imagex_printf(T("\nReading split pipable WIM part %u of %u\n"),
@@ -1216,6 +1250,39 @@ imagex_progress_func(enum wimlib_progress_msg msg,
                imagex_printf(T("\nExtracting \"%"TS"\" as normal file (not WIMBoot pointer)\n"),
                              info->wimboot_exclude.path_in_wim);
                break;
+       case WIMLIB_PROGRESS_MSG_UNMOUNT_BEGIN:
+               if (info->unmount.mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
+                       if (info->unmount.unmount_flags & WIMLIB_UNMOUNT_FLAG_COMMIT) {
+                               imagex_printf(T("Committing changes to %"TS" (image %d)\n"),
+                                             info->unmount.mounted_wim,
+                                             info->unmount.mounted_image);
+                       } else {
+                               imagex_printf(T("Discarding changes to %"TS" (image %d)\n"),
+                                             info->unmount.mounted_wim,
+                                             info->unmount.mounted_image);
+                               imagex_printf(T("\t(Use --commit to keep changes.)\n"));
+                       }
+               }
+               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;
        }
@@ -1646,15 +1713,15 @@ static int
 imagex_capture_or_append(int argc, tchar **argv, int cmd)
 {
        int c;
-       int open_flags = WIMLIB_OPEN_FLAG_WRITE_ACCESS;
-       int add_image_flags = WIMLIB_ADD_IMAGE_FLAG_EXCLUDE_VERBOSE |
-                             WIMLIB_ADD_IMAGE_FLAG_WINCONFIG |
-                             WIMLIB_ADD_IMAGE_FLAG_VERBOSE;
+       int open_flags = 0;
+       int add_flags = WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE |
+                       WIMLIB_ADD_FLAG_WINCONFIG |
+                       WIMLIB_ADD_FLAG_VERBOSE;
        int write_flags = 0;
        int compression_type = WIMLIB_COMPRESSION_TYPE_INVALID;
        uint32_t chunk_size = UINT32_MAX;
-       uint32_t pack_chunk_size = UINT32_MAX;
-       int pack_ctype = WIMLIB_COMPRESSION_TYPE_INVALID;
+       uint32_t solid_chunk_size = UINT32_MAX;
+       int solid_ctype = WIMLIB_COMPRESSION_TYPE_INVALID;
        const tchar *wimfile;
        int wim_fd;
        const tchar *name;
@@ -1685,12 +1752,11 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
        struct wimlib_capture_source *capture_sources;
        size_t num_sources;
        bool name_defaulted;
-       bool compress_slow = false;
 
        for_opt(c, capture_or_append_options) {
                switch (c) {
                case IMAGEX_BOOT_OPTION:
-                       add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_BOOT;
+                       add_flags |= WIMLIB_ADD_FLAG_BOOT;
                        break;
                case IMAGEX_CHECK_OPTION:
                        open_flags |= WIMLIB_OPEN_FLAG_CHECK_INTEGRITY;
@@ -1701,7 +1767,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
                        break;
                case IMAGEX_CONFIG_OPTION:
                        config_file = optarg;
-                       add_image_flags &= ~WIMLIB_ADD_IMAGE_FLAG_WINCONFIG;
+                       add_flags &= ~WIMLIB_ADD_FLAG_WINCONFIG;
                        break;
                case IMAGEX_COMPRESS_OPTION:
                        compression_type = get_compression_type(optarg);
@@ -1709,31 +1775,31 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
                                goto out_err;
                        break;
                case IMAGEX_COMPRESS_SLOW_OPTION:
-                       compress_slow = true;
+                       set_compress_slow();
                        break;
                case IMAGEX_CHUNK_SIZE_OPTION:
                        chunk_size = parse_chunk_size(optarg);
                        if (chunk_size == UINT32_MAX)
                                goto out_err;
                        break;
-               case IMAGEX_PACK_CHUNK_SIZE_OPTION:
-                       pack_chunk_size = parse_chunk_size(optarg);
-                       if (pack_chunk_size == UINT32_MAX)
+               case IMAGEX_SOLID_CHUNK_SIZE_OPTION:
+                       solid_chunk_size = parse_chunk_size(optarg);
+                       if (solid_chunk_size == UINT32_MAX)
                                goto out_err;
                        break;
-               case IMAGEX_PACK_COMPRESS_OPTION:
-                       pack_ctype = get_compression_type(optarg);
-                       if (pack_ctype == WIMLIB_COMPRESSION_TYPE_INVALID)
+               case IMAGEX_SOLID_COMPRESS_OPTION:
+                       solid_ctype = get_compression_type(optarg);
+                       if (solid_ctype == WIMLIB_COMPRESSION_TYPE_INVALID)
                                goto out_err;
                        break;
-               case IMAGEX_PACK_STREAMS_OPTION:
+               case IMAGEX_SOLID_OPTION:
                        write_flags |= WIMLIB_WRITE_FLAG_PACK_STREAMS;
                        break;
                case IMAGEX_FLAGS_OPTION:
                        flags_element = optarg;
                        break;
                case IMAGEX_DEREFERENCE_OPTION:
-                       add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_DEREFERENCE;
+                       add_flags |= WIMLIB_ADD_FLAG_DEREFERENCE;
                        break;
                case IMAGEX_VERBOSE_OPTION:
                        /* No longer does anything.  */
@@ -1747,22 +1813,22 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
                        write_flags |= WIMLIB_WRITE_FLAG_REBUILD;
                        break;
                case IMAGEX_UNIX_DATA_OPTION:
-                       add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_UNIX_DATA;
+                       add_flags |= WIMLIB_ADD_FLAG_UNIX_DATA;
                        break;
                case IMAGEX_SOURCE_LIST_OPTION:
                        source_list = true;
                        break;
                case IMAGEX_NO_ACLS_OPTION:
-                       add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_NO_ACLS;
+                       add_flags |= WIMLIB_ADD_FLAG_NO_ACLS;
                        break;
                case IMAGEX_STRICT_ACLS_OPTION:
-                       add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_STRICT_ACLS;
+                       add_flags |= WIMLIB_ADD_FLAG_STRICT_ACLS;
                        break;
                case IMAGEX_RPFIX_OPTION:
-                       add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_RPFIX;
+                       add_flags |= WIMLIB_ADD_FLAG_RPFIX;
                        break;
                case IMAGEX_NORPFIX_OPTION:
-                       add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_NORPFIX;
+                       add_flags |= WIMLIB_ADD_FLAG_NORPFIX;
                        break;
                case IMAGEX_PIPABLE_OPTION:
                        write_flags |= WIMLIB_WRITE_FLAG_PIPABLE;
@@ -1801,7 +1867,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
                        write_flags |= WIMLIB_WRITE_FLAG_SKIP_EXTERNAL_WIMS;
                        break;
                case IMAGEX_WIMBOOT_OPTION:
-                       add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_WIMBOOT;
+                       add_flags |= WIMLIB_ADD_FLAG_WIMBOOT;
                        break;
                default:
                        goto out_usage;
@@ -1822,33 +1888,19 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
        if (compression_type == WIMLIB_COMPRESSION_TYPE_INVALID) {
                /* No compression type specified.  Use the default.  */
 
-               if (add_image_flags & WIMLIB_ADD_IMAGE_FLAG_WIMBOOT) {
+               if (add_flags & WIMLIB_ADD_FLAG_WIMBOOT) {
                        /* With --wimboot, default to XPRESS compression.  */
                        compression_type = WIMLIB_COMPRESSION_TYPE_XPRESS;
                } else if (write_flags & WIMLIB_WRITE_FLAG_PACK_STREAMS) {
-                       /* With --pack-streams or --solid, default to LZMS
-                        * compression.  (However, this will not affect packed
-                        * resources!)  */
+                       /* With --solid, default to LZMS compression.  (However,
+                        * this will not affect solid blocks!)  */
                        compression_type = WIMLIB_COMPRESSION_TYPE_LZMS;
                } else {
-                       /* Otherwise, default to LZX compression in fast mode.
-                        */
+                       /* Otherwise, default to LZX compression.  */
                        compression_type = WIMLIB_COMPRESSION_TYPE_LZX;
-                       if (!compress_slow && pack_ctype != WIMLIB_COMPRESSION_TYPE_LZX) {
-                               struct wimlib_lzx_compressor_params params = {
-                                       .hdr.size = sizeof(params),
-                                       .algorithm = WIMLIB_LZX_ALGORITHM_FAST,
-                                       .use_defaults = 1,
-                               };
-                               wimlib_set_default_compressor_params(WIMLIB_COMPRESSION_TYPE_LZX,
-                                                                    &params.hdr);
-                       }
                }
        }
 
-       if (compress_slow)
-               set_compress_slow();
-
        if (!tstrcmp(wimfile, T("-"))) {
                /* Writing captured WIM to standard output.  */
        #if 0
@@ -1955,8 +2007,11 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
 
        /* Open the existing WIM, or create a new one.  */
        if (cmd == CMD_APPEND) {
-               ret = wimlib_open_wim_with_progress(wimfile, open_flags, &wim,
-                                                   imagex_progress_func, NULL);
+               ret = wimlib_open_wim_with_progress(wimfile,
+                                                   open_flags | WIMLIB_OPEN_FLAG_WRITE_ACCESS,
+                                                   &wim,
+                                                   imagex_progress_func,
+                                                   NULL);
                if (ret)
                        goto out_free_capture_sources;
        } else {
@@ -1971,19 +2026,19 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
                ret = wimlib_set_output_chunk_size(wim, chunk_size);
                if (ret)
                        goto out_free_wim;
-       } else if ((add_image_flags & WIMLIB_ADD_IMAGE_FLAG_WIMBOOT) &&
+       } else if ((add_flags & WIMLIB_ADD_FLAG_WIMBOOT) &&
                   compression_type == WIMLIB_COMPRESSION_TYPE_XPRESS) {
                ret = wimlib_set_output_chunk_size(wim, 4096);
                if (ret)
                        goto out_free_wim;
        }
-       if (pack_ctype != WIMLIB_COMPRESSION_TYPE_INVALID) {
-               ret = wimlib_set_output_pack_compression_type(wim, pack_ctype);
+       if (solid_ctype != WIMLIB_COMPRESSION_TYPE_INVALID) {
+               ret = wimlib_set_output_pack_compression_type(wim, solid_ctype);
                if (ret)
                        goto out_free_wim;
        }
-       if (pack_chunk_size != UINT32_MAX) {
-               ret = wimlib_set_output_pack_chunk_size(wim, pack_chunk_size);
+       if (solid_chunk_size != UINT32_MAX) {
+               ret = wimlib_set_output_pack_chunk_size(wim, solid_chunk_size);
                if (ret)
                        goto out_free_wim;
        }
@@ -1998,7 +2053,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
                        if (S_ISBLK(stbuf.st_mode) || S_ISREG(stbuf.st_mode)) {
                                imagex_printf(T("Capturing WIM image from NTFS "
                                          "filesystem on \"%"TS"\"\n"), source);
-                               add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_NTFS;
+                               add_flags |= WIMLIB_ADD_FLAG_NTFS;
                        }
                } else {
                        if (errno != ENOENT) {
@@ -2038,9 +2093,8 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
 
                for (size_t i = 0; i < base_wimfiles.num_strings; i++) {
                        ret = wimlib_open_wim_with_progress(
-                                   base_wimfiles.strings[i],
-                                   open_flags, &base_wims[i],
-                                   imagex_progress_func, NULL);
+                                   base_wimfiles.strings[i], open_flags,
+                                   &base_wims[i], imagex_progress_func, NULL);
                        if (ret)
                                goto out_free_base_wims;
 
@@ -2114,7 +2168,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
                                           num_sources,
                                           name,
                                           config_file,
-                                          add_image_flags);
+                                          add_flags);
        if (ret)
                goto out_free_template_wim;
 
@@ -2585,8 +2639,8 @@ imagex_export(int argc, tchar **argv, int cmd)
        STRING_SET(refglobs);
        unsigned num_threads = 0;
        uint32_t chunk_size = UINT32_MAX;
-       uint32_t pack_chunk_size = UINT32_MAX;
-       int pack_ctype = WIMLIB_COMPRESSION_TYPE_INVALID;
+       uint32_t solid_chunk_size = UINT32_MAX;
+       int solid_ctype = WIMLIB_COMPRESSION_TYPE_INVALID;
 
        for_opt(c, export_options) {
                switch (c) {
@@ -2606,10 +2660,13 @@ imagex_export(int argc, tchar **argv, int cmd)
                                goto out_err;
                        break;
                case IMAGEX_COMPRESS_SLOW_OPTION:
-                       write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
                        set_compress_slow();
+                       write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
                        break;
-               case IMAGEX_PACK_STREAMS_OPTION:
+               case IMAGEX_RECOMPRESS_OPTION:
+                       write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
+                       break;
+               case IMAGEX_SOLID_OPTION:
                        write_flags |= WIMLIB_WRITE_FLAG_PACK_STREAMS;
                        break;
                case IMAGEX_CHUNK_SIZE_OPTION:
@@ -2617,14 +2674,14 @@ imagex_export(int argc, tchar **argv, int cmd)
                        if (chunk_size == UINT32_MAX)
                                goto out_err;
                        break;
-               case IMAGEX_PACK_CHUNK_SIZE_OPTION:
-                       pack_chunk_size = parse_chunk_size(optarg);
-                       if (pack_chunk_size == UINT32_MAX)
+               case IMAGEX_SOLID_CHUNK_SIZE_OPTION:
+                       solid_chunk_size = parse_chunk_size(optarg);
+                       if (solid_chunk_size == UINT32_MAX)
                                goto out_err;
                        break;
-               case IMAGEX_PACK_COMPRESS_OPTION:
-                       pack_ctype = get_compression_type(optarg);
-                       if (pack_ctype == WIMLIB_COMPRESSION_TYPE_INVALID)
+               case IMAGEX_SOLID_COMPRESS_OPTION:
+                       solid_ctype = get_compression_type(optarg);
+                       if (solid_ctype == WIMLIB_COMPRESSION_TYPE_INVALID)
                                goto out_err;
                        break;
                case IMAGEX_REF_OPTION:
@@ -2742,8 +2799,8 @@ imagex_export(int argc, tchar **argv, int cmd)
 
                if (compression_type == WIMLIB_COMPRESSION_TYPE_INVALID) {
                        /* The user did not specify a compression type; default
-                        * to that of the source WIM, unless --pack-streams,
-                        * --solid, or --wimboot was specified.   */
+                        * to that of the source WIM, unless --solid or
+                        * --wimboot was specified.   */
 
                        if (write_flags & WIMLIB_WRITE_FLAG_PACK_STREAMS)
                                compression_type = WIMLIB_COMPRESSION_TYPE_LZMS;
@@ -2778,13 +2835,13 @@ imagex_export(int argc, tchar **argv, int cmd)
                if (ret)
                        goto out_free_dest_wim;
        }
-       if (pack_ctype != WIMLIB_COMPRESSION_TYPE_INVALID) {
-               ret = wimlib_set_output_pack_compression_type(dest_wim, pack_ctype);
+       if (solid_ctype != WIMLIB_COMPRESSION_TYPE_INVALID) {
+               ret = wimlib_set_output_pack_compression_type(dest_wim, solid_ctype);
                if (ret)
                        goto out_free_dest_wim;
        }
-       if (pack_chunk_size != UINT32_MAX) {
-               ret = wimlib_set_output_pack_chunk_size(dest_wim, pack_chunk_size);
+       if (solid_chunk_size != UINT32_MAX) {
+               ret = wimlib_set_output_pack_chunk_size(dest_wim, solid_chunk_size);
                if (ret)
                        goto out_free_dest_wim;
        }
@@ -2902,7 +2959,7 @@ imagex_extract(int argc, tchar **argv, int cmd)
                        extract_flags |= WIMLIB_EXTRACT_FLAG_REPLACE_INVALID_FILENAMES;
                        extract_flags |= WIMLIB_EXTRACT_FLAG_ALL_CASE_CONFLICTS;
                        break;
-               case IMAGEX_NO_WILDCARDS_OPTION:
+               case IMAGEX_NO_GLOBS_OPTION:
                        extract_flags &= ~WIMLIB_EXTRACT_FLAG_GLOB_PATHS;
                        break;
                case IMAGEX_NULLGLOB_OPTION:
@@ -2927,7 +2984,7 @@ imagex_extract(int argc, tchar **argv, int cmd)
        if (!(extract_flags & (WIMLIB_EXTRACT_FLAG_GLOB_PATHS |
                               WIMLIB_EXTRACT_FLAG_STRICT_GLOB)))
        {
-               imagex_error(T("Can't combine --no-wildcards and --nullglob!"));
+               imagex_error(T("Can't combine --no-globs and --nullglob!"));
                goto out_err;
        }
 
@@ -2989,6 +3046,15 @@ imagex_extract(int argc, tchar **argv, int cmd)
                if (!imagex_be_quiet)
                        imagex_printf(T("Done extracting files.\n"));
        } else if (ret == WIMLIB_ERR_PATH_DOES_NOT_EXIST) {
+               if ((extract_flags & (WIMLIB_EXTRACT_FLAG_STRICT_GLOB |
+                                     WIMLIB_EXTRACT_FLAG_GLOB_PATHS))
+                       == (WIMLIB_EXTRACT_FLAG_STRICT_GLOB |
+                           WIMLIB_EXTRACT_FLAG_GLOB_PATHS))
+               {
+                       tfprintf(stderr,
+                                T("Note: You can use the '--nullglob' "
+                                  "option to ignore missing files.\n"));
+               }
                tfprintf(stderr, T("Note: You can use `%"TS"' to see what "
                                   "files and directories\n"
                                   "      are in the WIM image.\n"),
@@ -3458,8 +3524,8 @@ imagex_optimize(int argc, tchar **argv, int cmd)
        int write_flags = WIMLIB_WRITE_FLAG_REBUILD;
        int compression_type = WIMLIB_COMPRESSION_TYPE_INVALID;
        uint32_t chunk_size = UINT32_MAX;
-       uint32_t pack_chunk_size = UINT32_MAX;
-       int pack_ctype = WIMLIB_COMPRESSION_TYPE_INVALID;
+       uint32_t solid_chunk_size = UINT32_MAX;
+       int solid_ctype = WIMLIB_COMPRESSION_TYPE_INVALID;
        int ret;
        WIMStruct *wim;
        const tchar *wimfile;
@@ -3482,29 +3548,29 @@ imagex_optimize(int argc, tchar **argv, int cmd)
                        if (compression_type == WIMLIB_COMPRESSION_TYPE_INVALID)
                                goto out_err;
                        break;
-               case IMAGEX_RECOMPRESS_OPTION:
+               case IMAGEX_COMPRESS_SLOW_OPTION:
+                       set_compress_slow();
                        write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
                        break;
-               case IMAGEX_COMPRESS_SLOW_OPTION:
+               case IMAGEX_RECOMPRESS_OPTION:
                        write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
-                       set_compress_slow();
                        break;
                case IMAGEX_CHUNK_SIZE_OPTION:
                        chunk_size = parse_chunk_size(optarg);
                        if (chunk_size == UINT32_MAX)
                                goto out_err;
                        break;
-               case IMAGEX_PACK_CHUNK_SIZE_OPTION:
-                       pack_chunk_size = parse_chunk_size(optarg);
-                       if (pack_chunk_size == UINT32_MAX)
+               case IMAGEX_SOLID_CHUNK_SIZE_OPTION:
+                       solid_chunk_size = parse_chunk_size(optarg);
+                       if (solid_chunk_size == UINT32_MAX)
                                goto out_err;
                        break;
-               case IMAGEX_PACK_COMPRESS_OPTION:
-                       pack_ctype = get_compression_type(optarg);
-                       if (pack_ctype == WIMLIB_COMPRESSION_TYPE_INVALID)
+               case IMAGEX_SOLID_COMPRESS_OPTION:
+                       solid_ctype = get_compression_type(optarg);
+                       if (solid_ctype == WIMLIB_COMPRESSION_TYPE_INVALID)
                                goto out_err;
                        break;
-               case IMAGEX_PACK_STREAMS_OPTION:
+               case IMAGEX_SOLID_OPTION:
                        write_flags |= WIMLIB_WRITE_FLAG_PACK_STREAMS;
                        write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
                        break;
@@ -3549,13 +3615,13 @@ imagex_optimize(int argc, tchar **argv, int cmd)
                if (ret)
                        goto out_wimlib_free;
        }
-       if (pack_ctype != WIMLIB_COMPRESSION_TYPE_INVALID) {
-               ret = wimlib_set_output_pack_compression_type(wim, pack_ctype);
+       if (solid_ctype != WIMLIB_COMPRESSION_TYPE_INVALID) {
+               ret = wimlib_set_output_pack_compression_type(wim, solid_ctype);
                if (ret)
                        goto out_wimlib_free;
        }
-       if (pack_chunk_size != UINT32_MAX) {
-               ret = wimlib_set_output_pack_chunk_size(wim, pack_chunk_size);
+       if (solid_chunk_size != UINT32_MAX) {
+               ret = wimlib_set_output_pack_chunk_size(wim, solid_chunk_size);
                if (ret)
                        goto out_wimlib_free;
        }
@@ -3673,7 +3739,14 @@ imagex_unmount(int argc, tchar **argv, int cmd)
                        unmount_flags |= WIMLIB_UNMOUNT_FLAG_REBUILD;
                        break;
                case IMAGEX_LAZY_OPTION:
-                       unmount_flags |= WIMLIB_UNMOUNT_FLAG_LAZY;
+               case IMAGEX_FORCE_OPTION:
+                       /* Now, unmount is lazy by default.  However, committing
+                        * the image will fail with
+                        * WIMLIB_ERR_MOUNTED_IMAGE_IS_BUSY if there are open
+                        * file descriptors on the WIM image.  The
+                        * WIMLIB_UNMOUNT_FLAG_FORCE option forces these file
+                        * descriptors to be closed.  */
+                       unmount_flags |= WIMLIB_UNMOUNT_FLAG_FORCE;
                        break;
                case IMAGEX_NEW_IMAGE_OPTION:
                        unmount_flags |= WIMLIB_UNMOUNT_FLAG_NEW_IMAGE;
@@ -3693,13 +3766,19 @@ imagex_unmount(int argc, tchar **argv, int cmd)
                                       "without --commit also specified!"));
                        goto out_err;
                }
-               imagex_printf(T("Committing changes as new image...\n"));
        }
 
        ret = wimlib_unmount_image_with_progress(argv[0], unmount_flags,
                                                 imagex_progress_func, NULL);
-       if (ret)
+       if (ret) {
                imagex_error(T("Failed to unmount \"%"TS"\""), argv[0]);
+               if (ret == WIMLIB_ERR_MOUNTED_IMAGE_IS_BUSY) {
+                       imagex_printf(T(
+                               "\tNote: Use --commit --force to force changes "
+                                       "to be committed, regardless\n"
+                               "\t      of open files.\n"));
+               }
+       }
 out:
        return ret;
 
@@ -3931,7 +4010,85 @@ 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;
+               case IMAGEX_NOCHECK_OPTION:
+                       open_flags &= ~WIMLIB_OPEN_FLAG_CHECK_INTEGRITY;
+                       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;
@@ -3958,64 +4115,80 @@ 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__
+
+   /* Can be a directory or source list file.  But source list file is probably
+    * a rare use case, so just say directory.  */
+#  define SOURCE_STR T("DIRECTORY")
+
+   /* Can only be a directory  */
+#  define TARGET_STR T("DIRECTORY")
+
+#else
+   /* Can be a directory, NTFS volume, or source list file. */
+#  define SOURCE_STR T("SOURCE")
+
+   /* Can be a directory or NTFS volume.  */
+#  define TARGET_STR T("TARGET")
+
+#endif
+
 static const tchar *usage_strings[] = {
 [CMD_APPEND] =
 T(
-"    %"TS" (DIRECTORY | NTFS_VOLUME) WIMFILE\n"
-"                    [IMAGE_NAME [IMAGE_DESCRIPTION]] [--boot] [--check]\n"
-"                    [--nocheck] [--flags EDITION_ID] [--dereference]\n"
-"                    [--config=FILE] [--threads=NUM_THREADS] [--source-list]\n"
-"                    [--no-acls] [--strict-acls] [--rpfix] [--norpfix]\n"
-"                    [--update-of=[WIMFILE:]IMAGE] [--wimboot]\n"
+"    %"TS" " SOURCE_STR " WIMFILE [IMAGE_NAME [IMAGE_DESC]]\n"
+"                    [--boot] [--check] [--nocheck] [--config=FILE]\n"
+"                    [--threads=NUM_THREADS] [--no-acls] [--strict-acls]\n"
+"                    [--rpfix] [--norpfix] [--update-of=[WIMFILE:]IMAGE]\n"
+"                    [--wimboot] [--unix-data] [--dereference]\n"
 ),
 [CMD_APPLY] =
 T(
-"    %"TS" WIMFILE [(IMAGE_NUM | IMAGE_NAME | all)]\n"
-"                    (DIRECTORY | NTFS_VOLUME) [--check] [--ref=\"GLOB\"]\n"
-"                    [--no-acls] [--strict-acls] [--no-attributes]\n"
-"                    [--rpfix] [--norpfix] [--include-invalid-names]\n"
-"                    [--wimboot] [--unix-data]\n"
+"    %"TS" WIMFILE [IMAGE] " TARGET_STR "\n"
+"                    [--check] [--ref=\"GLOB\"] [--no-acls] [--strict-acls]\n"
+"                    [--no-attributes] [--rpfix] [--norpfix]\n"
+"                    [--include-invalid-names] [--wimboot] [--unix-data]\n"
 ),
 [CMD_CAPTURE] =
 T(
-"    %"TS" (DIRECTORY | NTFS_VOLUME) WIMFILE\n"
-"                   [IMAGE_NAME [IMAGE_DESCRIPTION]] [--boot] [--check]\n"
-"                    [--nocheck] [--compress=TYPE] [--flags EDITION_ID]\n"
-"                    [--dereference] [--config=FILE] [--threads=NUM_THREADS]\n"
-"                    [--source-list] [--no-acls] [--strict-acls] [--rpfix]\n"
-"                    [--norpfix] [--update-of=[WIMFILE:]IMAGE]\n"
-"                    [--delta-from=WIMFILE] [--wimboot] [--unix-data]\n"
+"    %"TS" " SOURCE_STR " WIMFILE [IMAGE_NAME [IMAGE_DESC]]\n"
+"                    [--compress=TYPE] [--boot] [--check] [--nocheck]\n"
+"                    [--config=FILE] [--threads=NUM_THREADS]\n"
+"                    [--no-acls] [--strict-acls] [--rpfix] [--norpfix]\n"
+"                    [--update-of=[WIMFILE:]IMAGE] [--delta-from=WIMFILE]\n"
+"                    [--wimboot] [--unix-data] [--dereference] [--solid]\n"
 ),
 [CMD_DELETE] =
 T(
-"    %"TS" WIMFILE (IMAGE_NUM | IMAGE_NAME | all)\n"
-"                    [--check] [--soft]\n"
+"    %"TS" WIMFILE IMAGE [--check] [--soft]\n"
 ),
 [CMD_DIR] =
 T(
-"    %"TS" WIMFILE (IMAGE_NUM | IMAGE_NAME | all) [--path=PATH] [--detailed]\n"
+"    %"TS" WIMFILE IMAGE [--path=PATH] [--detailed]\n"
 ),
 [CMD_EXPORT] =
 T(
-"    %"TS" SRC_WIMFILE (SRC_IMAGE_NUM | SRC_IMAGE_NAME | all ) \n"
-"                    DEST_WIMFILE [DEST_IMAGE_NAME [DEST_IMAGE_DESCRIPTION]]\n"
+"    %"TS" SRC_WIMFILE SRC_IMAGE DEST_WIMFILE\n"
+"                        [DEST_IMAGE_NAME [DEST_IMAGE_DESC]]\n"
 "                    [--boot] [--check] [--nocheck] [--compress=TYPE]\n"
 "                    [--ref=\"GLOB\"] [--threads=NUM_THREADS] [--rebuild]\n"
+"                    [--wimboot]\n"
 ),
 [CMD_EXTRACT] =
 T(
-"    %"TS" WIMFILE (IMAGE_NUM | IMAGE_NAME) [(PATH | @LISTFILE)...]\n"
+"    %"TS" WIMFILE IMAGE [(PATH | @LISTFILE)...]\n"
 "                    [--check] [--ref=\"GLOB\"] [--dest-dir=CMD_DIR]\n"
 "                    [--to-stdout] [--no-acls] [--strict-acls]\n"
 "                    [--no-attributes] [--include-invalid-names]\n"
-"                    [--no-wildcards] [--nullglob] [--preserve-dir-structure]\n"
+"                    [--no-globs] [--nullglob] [--preserve-dir-structure]\n"
 ),
 [CMD_INFO] =
 T(
-"    %"TS" WIMFILE [(IMAGE_NUM | IMAGE_NAME) [NEW_NAME\n"
-"                    [NEW_DESC]]] [--boot] [--check] [--nocheck] [--xml]\n"
+"    %"TS" WIMFILE [IMAGE [NEW_NAME [NEW_DESC]]]\n"
+"                    [--boot] [--check] [--nocheck] [--xml]\n"
 "                    [--extract-xml FILE] [--header] [--lookup-table]\n"
 ),
 [CMD_JOIN] =
@@ -4025,22 +4198,23 @@ T(
 #if WIM_MOUNTING_SUPPORTED
 [CMD_MOUNT] =
 T(
-"    %"TS" WIMFILE [(IMAGE_NUM | IMAGE_NAME)] DIRECTORY\n"
+"    %"TS" WIMFILE [IMAGE] DIRECTORY\n"
 "                    [--check] [--streams-interface=INTERFACE]\n"
 "                    [--ref=\"GLOB\"] [--allow-other] [--unix-data]\n"
 ),
 [CMD_MOUNTRW] =
 T(
-"    %"TS" WIMFILE [(IMAGE_NUM | IMAGE_NAME)] DIRECTORY\n"
+"    %"TS" WIMFILE [IMAGE] DIRECTORY\n"
 "                    [--check] [--streams-interface=INTERFACE]\n"
 "                    [--staging-dir=CMD_DIR] [--allow-other] [--unix-data]\n"
 ),
 #endif
 [CMD_OPTIMIZE] =
 T(
-"    %"TS" WIMFILE [--check] [--nocheck] [--recompress]\n"
-"                    [--recompress-slow] [--compress=TYPE]\n"
-"                    [--threads=NUM_THREADS]\n"
+"    %"TS" WIMFILE\n"
+"                    [--recompress] [--compress=TYPE]\n"
+"                    [--threads=NUM_THREADS] [--check] [--nocheck]\n"
+"\n"
 ),
 [CMD_SPLIT] =
 T(
@@ -4049,16 +4223,21 @@ T(
 #if WIM_MOUNTING_SUPPORTED
 [CMD_UNMOUNT] =
 T(
-"    %"TS" DIRECTORY [--commit] [--check] [--rebuild] [--lazy]\n"
-"                    [--new-image]\n"
+"    %"TS" DIRECTORY\n"
+"                    [--commit] [--force] [--new-image] [--check] [--rebuild]\n"
 ),
 #endif
 [CMD_UPDATE] =
 T(
-"    %"TS" WIMFILE [IMAGE_NUM | IMAGE_NAME] [--check] [--rebuild]\n"
-"                    [--threads=NUM_THREADS] [DEFAULT_ADD_OPTIONS]\n"
-"                    [DEFAULT_DELETE_OPTIONS] [--command=STRING]\n"
-"                    [--wimboot-config=FILE| [< CMDFILE]\n"
+"    %"TS" WIMFILE [IMAGE]\n"
+"                    [--check] [--rebuild] [--threads=NUM_THREADS]\n"
+"                    [DEFAULT_ADD_OPTIONS] [DEFAULT_DELETE_OPTIONS]\n"
+"                    [--command=STRING] [--wimboot-config=FILE]\n"
+"                    [< CMDFILE]\n"
+),
+[CMD_VERIFY] =
+T(
+"    %"TS" WIMFILE [--ref=\"GLOB\"]\n"
 ),
 };
 
@@ -4136,10 +4315,10 @@ recommend_man_page(int cmd, FILE *fp)
 {
        const tchar *format_str;
 #ifdef __WIN32__
-       format_str = T("Uncommon options are not listed;\n"
+       format_str = T("Some uncommon options are not listed;\n"
                       "See %"TS".pdf in the doc directory for more details.\n");
 #else
-       format_str = T("Uncommon options are not listed;\n"
+       format_str = T("Some uncommon options are not listed;\n"
                       "Try `man %"TS"' for more details.\n");
 #endif
        tfprintf(fp, format_str, get_cmd_string(cmd, true));
@@ -4166,11 +4345,14 @@ usage_all(FILE *fp)
        T(
 "    %"TS" --help\n"
 "    %"TS" --version\n"
-"\n"
-"    The compression TYPE may be \"maximum\", \"fast\", or \"none\".\n"
 "\n"
        );
        tfprintf(fp, extra, invocation_name, invocation_name);
+       tfprintf(fp,
+                T("IMAGE can be the 1-based index or name of an image in the WIM file.\n"
+                  "For some commands IMAGE is optional if the WIM file only contains one image.\n"
+                  "For some commands IMAGE may be \"all\".\n"
+                  "\n"));
        recommend_man_page(CMD_NONE, fp);
 }