X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=programs%2Fimagex.c;h=9ea7edb019b520fbd2b5f465a96b69e93a02a277;hp=84f7b8e0ff7202c2d5757f6ced71710a1726307e;hb=b385fbfff5c985c0037dfc80ccbc3213e47718d5;hpb=d31b2fee211b1c31420bafe1c2379f6f89bd92fe diff --git a/programs/imagex.c b/programs/imagex.c index 84f7b8e0..9ea7edb0 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -160,6 +160,7 @@ enum { IMAGEX_FLAGS_OPTION, IMAGEX_FORCE_OPTION, IMAGEX_HEADER_OPTION, + IMAGEX_IMAGE_PROPERTY_OPTION, IMAGEX_INCLUDE_INVALID_NAMES_OPTION, IMAGEX_LAZY_OPTION, IMAGEX_METADATA_OPTION, @@ -183,6 +184,7 @@ enum { IMAGEX_REF_OPTION, IMAGEX_RESUME_OPTION, IMAGEX_RPFIX_OPTION, + IMAGEX_SNAPSHOT_OPTION, IMAGEX_SOFT_OPTION, IMAGEX_SOLID_CHUNK_SIZE_OPTION, IMAGEX_SOLID_COMPRESS_OPTION, @@ -194,6 +196,7 @@ enum { IMAGEX_THREADS_OPTION, IMAGEX_TO_STDOUT_OPTION, IMAGEX_UNIX_DATA_OPTION, + IMAGEX_UNSAFE_COMPACT_OPTION, IMAGEX_UPDATE_OF_OPTION, IMAGEX_VERBOSE_OPTION, IMAGEX_WIMBOOT_CONFIG_OPTION, @@ -239,6 +242,7 @@ static const struct option capture_or_append_options[] = { {T("config"), required_argument, NULL, IMAGEX_CONFIG_OPTION}, {T("dereference"), no_argument, NULL, IMAGEX_DEREFERENCE_OPTION}, {T("flags"), required_argument, NULL, IMAGEX_FLAGS_OPTION}, + {T("image-property"), required_argument, NULL, IMAGEX_IMAGE_PROPERTY_OPTION}, {T("verbose"), no_argument, NULL, IMAGEX_VERBOSE_OPTION}, {T("threads"), required_argument, NULL, IMAGEX_THREADS_OPTION}, {T("rebuild"), no_argument, NULL, IMAGEX_REBUILD_OPTION}, @@ -254,12 +258,15 @@ static const struct option capture_or_append_options[] = { {T("update-of"), required_argument, NULL, IMAGEX_UPDATE_OF_OPTION}, {T("delta-from"), required_argument, NULL, IMAGEX_DELTA_FROM_OPTION}, {T("wimboot"), no_argument, NULL, IMAGEX_WIMBOOT_OPTION}, + {T("unsafe-compact"), no_argument, NULL, IMAGEX_UNSAFE_COMPACT_OPTION}, + {T("snapshot"), no_argument, NULL, IMAGEX_SNAPSHOT_OPTION}, {NULL, 0, NULL, 0}, }; static const struct option delete_options[] = { {T("check"), no_argument, NULL, IMAGEX_CHECK_OPTION}, {T("soft"), no_argument, NULL, IMAGEX_SOFT_OPTION}, + {T("unsafe-compact"), no_argument, NULL, IMAGEX_UNSAFE_COMPACT_OPTION}, {NULL, 0, NULL, 0}, }; @@ -293,6 +300,7 @@ static const struct option export_options[] = { {T("pipable"), no_argument, NULL, IMAGEX_PIPABLE_OPTION}, {T("not-pipable"), no_argument, NULL, IMAGEX_NOT_PIPABLE_OPTION}, {T("wimboot"), no_argument, NULL, IMAGEX_WIMBOOT_OPTION}, + {T("unsafe-compact"), no_argument, NULL, IMAGEX_UNSAFE_COMPACT_OPTION}, {NULL, 0, NULL, 0}, }; @@ -328,6 +336,7 @@ static const struct option info_options[] = { {T("blobs"), no_argument, NULL, IMAGEX_BLOBS_OPTION}, {T("metadata"), no_argument, NULL, IMAGEX_METADATA_OPTION}, {T("xml"), no_argument, NULL, IMAGEX_XML_OPTION}, + {T("image-property"), required_argument, NULL, IMAGEX_IMAGE_PROPERTY_OPTION}, {NULL, 0, NULL, 0}, }; @@ -366,6 +375,7 @@ static const struct option optimize_options[] = { {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}, + {T("unsafe-compact"), no_argument, NULL, IMAGEX_UNSAFE_COMPACT_OPTION}, {NULL, 0, NULL, 0}, }; @@ -410,6 +420,7 @@ static const struct option update_options[] = { {T("no-acls"), no_argument, NULL, IMAGEX_NO_ACLS_OPTION}, {T("strict-acls"), no_argument, NULL, IMAGEX_STRICT_ACLS_OPTION}, {T("no-replace"), no_argument, NULL, IMAGEX_NO_REPLACE_OPTION}, + {T("unsafe-compact"), no_argument, NULL, IMAGEX_UNSAFE_COMPACT_OPTION}, {NULL, 0, NULL, 0}, }; @@ -507,9 +518,9 @@ print_available_compression_types(FILE *fp) tfputs(s, fp); } -/* Parse the argument to --compress */ +/* Parse the argument to --compress or --solid-compress */ static int -get_compression_type(tchar *optarg) +get_compression_type(tchar *optarg, bool solid) { int ctype; unsigned int compression_level = 0; @@ -532,15 +543,27 @@ get_compression_type(tchar *optarg) if (!tstrcasecmp(optarg, T("maximum")) || !tstrcasecmp(optarg, T("lzx")) || - !tstrcasecmp(optarg, T("max"))) + !tstrcasecmp(optarg, T("max"))) { ctype = WIMLIB_COMPRESSION_TYPE_LZX; - else if (!tstrcasecmp(optarg, T("fast")) || !tstrcasecmp(optarg, T("xpress"))) + } else if (!tstrcasecmp(optarg, T("fast")) || !tstrcasecmp(optarg, T("xpress"))) { ctype = WIMLIB_COMPRESSION_TYPE_XPRESS; - else if (!tstrcasecmp(optarg, T("recovery")) || !tstrcasecmp(optarg, T("lzms"))) + } else if (!tstrcasecmp(optarg, T("recovery"))) { + if (!solid) { + tfprintf(stderr, +T( +"Warning: use of '--compress=recovery' is discouraged because it behaves\n" +" differently from DISM. Instead, you typically want to use '--solid' to\n" +" create a solid LZMS-compressed WIM or \"ESD file\", similar to DISM's\n" +" /compress:recovery. But if you really want *non-solid* LZMS compression,\n" +" then you may suppress this warning by specifying '--compress=lzms' instead\n" +" of '--compress=recovery'.\n")); + } ctype = WIMLIB_COMPRESSION_TYPE_LZMS; - else if (!tstrcasecmp(optarg, T("none"))) + } else if (!tstrcasecmp(optarg, T("lzms"))) { + ctype = WIMLIB_COMPRESSION_TYPE_LZMS; + } else if (!tstrcasecmp(optarg, T("none"))) { ctype = WIMLIB_COMPRESSION_TYPE_NONE; - else { + } else { imagex_error(T("Invalid compression type \"%"TS"\"!"), optarg); print_available_compression_types(stderr); return WIMLIB_COMPRESSION_TYPE_INVALID; @@ -593,7 +616,7 @@ set_compress_slow(void) } struct string_set { - const tchar **strings; + tchar **strings; unsigned num_strings; unsigned num_alloc_strings; }; @@ -605,12 +628,12 @@ struct string_set { struct string_set _strings = STRING_SET_INITIALIZER static int -string_set_append(struct string_set *set, const tchar *glob) +string_set_append(struct string_set *set, tchar *glob) { unsigned num_alloc_strings = set->num_alloc_strings; if (set->num_strings == num_alloc_strings) { - const tchar **new_strings; + tchar **new_strings; num_alloc_strings += 4; new_strings = realloc(set->strings, @@ -635,12 +658,57 @@ string_set_destroy(struct string_set *set) static int wim_reference_globs(WIMStruct *wim, struct string_set *set, int open_flags) { - return wimlib_reference_resource_files(wim, set->strings, + return wimlib_reference_resource_files(wim, (const tchar **)set->strings, set->num_strings, WIMLIB_REF_FLAG_GLOB_ENABLE, open_flags); } +static int +append_image_property_argument(struct string_set *image_properties) +{ + if (!tstrchr(optarg, '=')) { + imagex_error(T("'--image-property' argument " + "must be in the form NAME=VALUE")); + return -1; + } + return string_set_append(image_properties, optarg); +} + +static int +apply_image_properties(struct string_set *image_properties, + WIMStruct *wim, int image, bool *any_changes_ret) +{ + bool any_changes = false; + for (unsigned i = 0; i < image_properties->num_strings; i++) { + tchar *name, *value; + const tchar *current_value; + int ret; + + name = image_properties->strings[i]; + value = tstrchr(name, '='); + *value++ = '\0'; + + current_value = wimlib_get_image_property(wim, image, name); + if (current_value && !tstrcmp(current_value, value)) { + imagex_printf(T("The %"TS" property of image %d " + "already has value \"%"TS"\".\n"), + name, image, value); + } else { + imagex_printf(T("Setting the %"TS" property of image " + "%d to \"%"TS"\".\n"), + name, image, value); + ret = wimlib_set_image_property(wim, image, name, value); + if (ret) + return ret; + any_changes = true; + } + } + if (any_changes_ret) + *any_changes_ret = any_changes; + return 0; +} + static void do_resource_not_found_warning(const tchar *wimfile, const struct wimlib_wim_info *info, @@ -1103,23 +1171,24 @@ imagex_progress_func(enum wimlib_progress_msg msg, switch (msg) { case WIMLIB_PROGRESS_MSG_WRITE_STREAMS: { - static bool first = true; - if (first) { - imagex_printf(T("Writing %"TS"-compressed data " - "using %u thread%"TS"\n"), - wimlib_get_compression_type_string( - info->write_streams.compression_type), - info->write_streams.num_threads, - (info->write_streams.num_threads == 1) ? T("") : T("s")); - first = false; + static bool started; + if (!started) { + if (info->write_streams.compression_type != WIMLIB_COMPRESSION_TYPE_NONE) { + imagex_printf(T("Using %"TS" compression " + "with %u thread%"TS"\n"), + wimlib_get_compression_type_string( + info->write_streams.compression_type), + info->write_streams.num_threads, + (info->write_streams.num_threads == 1) ? T("") : T("s")); + } + started = true; } } unit_shift = get_unit(info->write_streams.total_bytes, &unit_name); percent_done = TO_PERCENT(info->write_streams.completed_bytes, info->write_streams.total_bytes); - imagex_printf(T("\r%"PRIu64" %"TS" of %"PRIu64" %"TS" (uncompressed) " - "written (%u%% done)"), + imagex_printf(T("\rArchiving file data: %"PRIu64" %"TS" of %"PRIu64" %"TS" (%u%%) done"), info->write_streams.completed_bytes >> unit_shift, unit_name, info->write_streams.total_bytes >> unit_shift, @@ -1769,7 +1838,7 @@ imagex_apply(int argc, tchar **argv, int cmd) " make sure you have " "concatenated together all parts.")); } - } else if (ret == WIMLIB_ERR_METADATA_NOT_FOUND) { + } else if (ret == WIMLIB_ERR_METADATA_NOT_FOUND && wim) { do_metadata_not_found_warning(wimfile, &info); } out_wimlib_free: @@ -1804,8 +1873,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) const tchar *wimfile; int wim_fd; const tchar *name; - const tchar *desc; - const tchar *flags_element = NULL; + STRING_SET(image_properties); WIMStruct *wim; STRING_SET(base_wimfiles); @@ -1849,7 +1917,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) add_flags &= ~WIMLIB_ADD_FLAG_WINCONFIG; break; case IMAGEX_COMPRESS_OPTION: - compression_type = get_compression_type(optarg); + compression_type = get_compression_type(optarg, false); if (compression_type == WIMLIB_COMPRESSION_TYPE_INVALID) goto out_err; break; @@ -1867,7 +1935,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) goto out_err; break; case IMAGEX_SOLID_COMPRESS_OPTION: - solid_ctype = get_compression_type(optarg); + solid_ctype = get_compression_type(optarg, true); if (solid_ctype == WIMLIB_COMPRESSION_TYPE_INVALID) goto out_err; break; @@ -1877,8 +1945,18 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) case IMAGEX_NO_SOLID_SORT_OPTION: write_flags |= WIMLIB_WRITE_FLAG_NO_SOLID_SORT; break; - case IMAGEX_FLAGS_OPTION: - flags_element = optarg; + case IMAGEX_FLAGS_OPTION: { + tchar *p = alloca((6 + tstrlen(optarg) + 1) * sizeof(tchar)); + tsprintf(p, T("FLAGS=%"TS), optarg); + ret = string_set_append(&image_properties, p); + if (ret) + goto out; + break; + } + case IMAGEX_IMAGE_PROPERTY_OPTION: + ret = append_image_property_argument(&image_properties); + if (ret) + goto out; break; case IMAGEX_DEREFERENCE_OPTION: add_flags |= WIMLIB_ADD_FLAG_DEREFERENCE; @@ -1945,12 +2023,23 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) } ret = string_set_append(&base_wimfiles, optarg); if (ret) - goto out_free_base_wimfiles; + goto out; write_flags |= WIMLIB_WRITE_FLAG_SKIP_EXTERNAL_WIMS; break; case IMAGEX_WIMBOOT_OPTION: add_flags |= WIMLIB_ADD_FLAG_WIMBOOT; break; + case IMAGEX_UNSAFE_COMPACT_OPTION: + if (cmd != CMD_APPEND) { + imagex_error(T("'--unsafe-compact' is only " + "valid for append!")); + goto out_err; + } + write_flags |= WIMLIB_WRITE_FLAG_UNSAFE_COMPACT; + break; + case IMAGEX_SNAPSHOT_OPTION: + add_flags |= WIMLIB_ADD_FLAG_SNAPSHOT; + break; default: goto out_usage; } @@ -2051,11 +2140,15 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) name = tbasename(tstrcpy(source_copy, source)); name_defaulted = true; } - /* Image description defaults to NULL if not given. */ - if (argc >= 4) - desc = argv[3]; - else - desc = NULL; + + /* Image description (if given). */ + if (argc >= 4) { + tchar *p = alloca((12 + tstrlen(argv[3]) + 1) * sizeof(tchar)); + tsprintf(p, T("DESCRIPTION=%"TS), argv[3]); + ret = string_set_append(&image_properties, p); + if (ret) + goto out; + } if (source_list) { /* Set up capture sources in source list mode */ @@ -2108,11 +2201,21 @@ 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_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; + } else if ((add_flags & WIMLIB_ADD_FLAG_WIMBOOT)) { + + int ctype = compression_type; + + if (cmd == CMD_APPEND) { + struct wimlib_wim_info info; + wimlib_get_wim_info(wim, &info); + ctype = info.compression_type; + } + + if (ctype == WIMLIB_COMPRESSION_TYPE_XPRESS) { + ret = wimlib_set_output_chunk_size(wim, 4096); + if (ret) + goto out_free_wim; + } } if (solid_ctype != WIMLIB_COMPRESSION_TYPE_INVALID) { ret = wimlib_set_output_pack_compression_type(wim, solid_ctype); @@ -2254,29 +2357,18 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) if (ret) goto out_free_template_wim; - if (desc || flags_element || template_image_name_or_num) { - /* User provided or element, or an image - * on which the added one is to be based has been specified with - * --update-of. Get the index of the image we just - * added, then use it to call the appropriate functions. */ + if (image_properties.num_strings || template_image_name_or_num) { + /* User asked to set additional image properties, or an image on + * which the added one is to be based has been specified with + * --update-of. */ struct wimlib_wim_info info; wimlib_get_wim_info(wim, &info); - if (desc) { - ret = wimlib_set_image_descripton(wim, - info.image_count, - desc); - if (ret) - goto out_free_template_wim; - } - - if (flags_element) { - ret = wimlib_set_image_flags(wim, info.image_count, - flags_element); - if (ret) - goto out_free_template_wim; - } + ret = apply_image_properties(&image_properties, wim, + info.image_count, NULL); + if (ret) + goto out_free_template_wim; /* Reference template image if the user provided one. */ if (template_image_name_or_num) { @@ -2320,7 +2412,8 @@ out_free_capture_sources: free(capture_sources); out_free_source_list_contents: free(source_list_contents); -out_free_base_wimfiles: +out: + string_set_destroy(&image_properties); string_set_destroy(&base_wimfiles); return ret; @@ -2328,7 +2421,7 @@ out_usage: usage(cmd, stderr); out_err: ret = -1; - goto out_free_base_wimfiles; + goto out; } /* Remove image(s) from a WIM. */ @@ -2353,6 +2446,9 @@ imagex_delete(int argc, tchar **argv, int cmd) case IMAGEX_SOFT_OPTION: write_flags |= WIMLIB_WRITE_FLAG_SOFT_DELETE; break; + case IMAGEX_UNSAFE_COMPACT_OPTION: + write_flags |= WIMLIB_WRITE_FLAG_UNSAFE_COMPACT; + break; default: goto out_usage; } @@ -2783,7 +2879,7 @@ imagex_export(int argc, tchar **argv, int cmd) write_flags |= WIMLIB_WRITE_FLAG_NO_CHECK_INTEGRITY; break; case IMAGEX_COMPRESS_OPTION: - compression_type = get_compression_type(optarg); + compression_type = get_compression_type(optarg, false); if (compression_type == WIMLIB_COMPRESSION_TYPE_INVALID) goto out_err; break; @@ -2811,7 +2907,7 @@ imagex_export(int argc, tchar **argv, int cmd) goto out_err; break; case IMAGEX_SOLID_COMPRESS_OPTION: - solid_ctype = get_compression_type(optarg); + solid_ctype = get_compression_type(optarg, true); if (solid_ctype == WIMLIB_COMPRESSION_TYPE_INVALID) goto out_err; break; @@ -2837,6 +2933,9 @@ imagex_export(int argc, tchar **argv, int cmd) case IMAGEX_WIMBOOT_OPTION: export_flags |= WIMLIB_EXPORT_FLAG_WIMBOOT; break; + case IMAGEX_UNSAFE_COMPACT_OPTION: + write_flags |= WIMLIB_WRITE_FLAG_UNSAFE_COMPACT; + break; default: goto out_usage; } @@ -2926,6 +3025,13 @@ imagex_export(int argc, tchar **argv, int cmd) goto out_free_src_wim; } + if (write_flags & WIMLIB_WRITE_FLAG_UNSAFE_COMPACT) { + imagex_error(T("'--unsafe-compact' is only valid when " + "exporting to an existing WIM file!")); + ret = -1; + goto out_free_src_wim; + } + /* dest_wimfile is not an existing file, so create a new WIM. */ if (compression_type == WIMLIB_COMPRESSION_TYPE_INVALID) { @@ -3237,8 +3343,7 @@ imagex_info(int argc, tchar **argv, int cmd) const tchar *xml_out_file = NULL; const tchar *wimfile; const tchar *image_num_or_name; - const tchar *new_name; - const tchar *new_desc; + STRING_SET(image_properties); WIMStruct *wim; int image; int ret; @@ -3276,6 +3381,11 @@ imagex_info(int argc, tchar **argv, int cmd) imagex_error(T("The --metadata option has been removed. " "Use 'wimdir --detail' instead.")); goto out_err; + case IMAGEX_IMAGE_PROPERTY_OPTION: + ret = append_image_property_argument(&image_properties); + if (ret) + goto out; + break; default: goto out_usage; } @@ -3288,8 +3398,24 @@ imagex_info(int argc, tchar **argv, int cmd) wimfile = argv[0]; image_num_or_name = (argc >= 2) ? argv[1] : T("all"); - new_name = (argc >= 3) ? argv[2] : NULL; - new_desc = (argc >= 4) ? argv[3] : NULL; + + if (argc >= 3) { + /* NEW_NAME */ + tchar *p = alloca((5 + tstrlen(argv[2]) + 1) * sizeof(tchar)); + tsprintf(p, T("NAME=%"TS), argv[2]); + ret = string_set_append(&image_properties, p); + if (ret) + goto out; + } + + if (argc >= 4) { + /* NEW_DESC */ + tchar *p = alloca((12 + tstrlen(argv[3]) + 1) * sizeof(tchar)); + tsprintf(p, T("DESCRIPTION=%"TS), argv[3]); + ret = string_set_append(&image_properties, p); + if (ret) + goto out; + } if (check && nocheck) { imagex_error(T("Can't specify both --check and --nocheck")); @@ -3330,17 +3456,17 @@ imagex_info(int argc, tchar **argv, int cmd) "image in a multi-image WIM")); goto out_wimlib_free; } - if (new_name) { - imagex_error(T("Cannot specify the NEW_NAME " - "without specifying a specific " - "image in a multi-image WIM")); + if (image_properties.num_strings) { + imagex_error(T("Can't change image properties without " + "specifying a specific image in a " + "multi-image WIM")); goto out_wimlib_free; } } /* Operations that print information are separated from operations that * recreate the WIM file. */ - if (!new_name && !boot) { + if (!image_properties.num_strings && !boot) { /* Read-only operations */ @@ -3399,15 +3525,15 @@ imagex_info(int argc, tchar **argv, int cmd) ret = 0; } else { - /* Modification operations */ + bool any_property_changes; if (image == WIMLIB_ALL_IMAGES) image = 1; - if (image == WIMLIB_NO_IMAGE && new_name) { - imagex_error(T("Cannot specify new_name (\"%"TS"\") " - "when using image 0"), new_name); + if (image == WIMLIB_NO_IMAGE && image_properties.num_strings) { + imagex_error(T("Cannot change image properties " + "when using image 0")); ret = -1; goto out_wimlib_free; } @@ -3427,40 +3553,15 @@ imagex_info(int argc, tchar **argv, int cmd) goto out_wimlib_free; } } - if (new_name) { - if (!tstrcmp(wimlib_get_image_name(wim, image), new_name)) - { - imagex_printf(T("Image %d is already named \"%"TS"\".\n"), - image, new_name); - new_name = NULL; - } else { - imagex_printf(T("Changing the name of image %d to " - "\"%"TS"\".\n"), image, new_name); - ret = wimlib_set_image_name(wim, image, new_name); - if (ret) - goto out_wimlib_free; - } - } - if (new_desc) { - const tchar *old_desc; - old_desc = wimlib_get_image_description(wim, image); - if (old_desc && !tstrcmp(old_desc, new_desc)) { - imagex_printf(T("The description of image %d is already " - "\"%"TS"\".\n"), image, new_desc); - new_desc = NULL; - } else { - imagex_printf(T("Changing the description of image %d " - "to \"%"TS"\".\n"), image, new_desc); - ret = wimlib_set_image_descripton(wim, image, - new_desc); - if (ret) - goto out_wimlib_free; - } - } + + ret = apply_image_properties(&image_properties, wim, image, + &any_property_changes); + if (ret) + goto out_wimlib_free; /* Only call wimlib_overwrite() if something actually needs to * be changed. */ - if (boot || new_name || new_desc || + if (boot || any_property_changes || (check && !info.has_integrity_table) || (nocheck && info.has_integrity_table)) { @@ -3481,6 +3582,7 @@ imagex_info(int argc, tchar **argv, int cmd) out_wimlib_free: wimlib_free(wim); out: + string_set_destroy(&image_properties); return ret; out_usage: @@ -3691,7 +3793,7 @@ imagex_optimize(int argc, tchar **argv, int cmd) break; case IMAGEX_COMPRESS_OPTION: write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS; - compression_type = get_compression_type(optarg); + compression_type = get_compression_type(optarg, false); if (compression_type == WIMLIB_COMPRESSION_TYPE_INVALID) goto out_err; break; @@ -3713,7 +3815,7 @@ imagex_optimize(int argc, tchar **argv, int cmd) goto out_err; break; case IMAGEX_SOLID_COMPRESS_OPTION: - solid_ctype = get_compression_type(optarg); + solid_ctype = get_compression_type(optarg, true); if (solid_ctype == WIMLIB_COMPRESSION_TYPE_INVALID) goto out_err; break; @@ -3735,6 +3837,9 @@ imagex_optimize(int argc, tchar **argv, int cmd) case IMAGEX_NOT_PIPABLE_OPTION: write_flags |= WIMLIB_WRITE_FLAG_NOT_PIPABLE; break; + case IMAGEX_UNSAFE_COMPACT_OPTION: + write_flags |= WIMLIB_WRITE_FLAG_UNSAFE_COMPACT; + break; default: goto out_usage; } @@ -4032,6 +4137,9 @@ imagex_update(int argc, tchar **argv, int cmd) case IMAGEX_NO_REPLACE_OPTION: default_add_flags |= WIMLIB_ADD_FLAG_NO_REPLACE; break; + case IMAGEX_UNSAFE_COMPACT_OPTION: + write_flags |= WIMLIB_WRITE_FLAG_UNSAFE_COMPACT; + break; default: goto out_usage; } @@ -4293,7 +4401,7 @@ T( " [--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" +" [--wimboot] [--unix-data] [--dereference] [--snapshot]\n" ), [CMD_APPLY] = T( @@ -4311,6 +4419,7 @@ T( " [--no-acls] [--strict-acls] [--rpfix] [--norpfix]\n" " [--update-of=[WIMFILE:]IMAGE] [--delta-from=WIMFILE]\n" " [--wimboot] [--unix-data] [--dereference] [--solid]\n" +" [--snapshot]\n" ), [CMD_DELETE] = T( @@ -4341,6 +4450,7 @@ T( " %"TS" WIMFILE [IMAGE [NEW_NAME [NEW_DESC]]]\n" " [--boot] [--check] [--nocheck] [--xml]\n" " [--extract-xml FILE] [--header] [--blobs]\n" +" [--image-property NAME=VALUE]\n" ), [CMD_JOIN] = T(