X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=programs%2Fimagex.c;h=f8ffc7c1bce4190868f4aa88a79b852a792dfdec;hp=0a1f77b045c0633260a75153700356ecb8697a00;hb=5d52d8c322857646dec623cedc35796dc135e2b9;hpb=bae9a26f52c209a0c8931eefb2e3150e4b6ac749 diff --git a/programs/imagex.c b/programs/imagex.c index 0a1f77b0..f8ffc7c1 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -104,6 +104,7 @@ IMAGEX_PROGNAME" apply WIMFILE [IMAGE_NUM | IMAGE_NAME | all]\n" " (DIRECTORY | NTFS_VOLUME) [--check] [--hardlink]\n" " [--symlink] [--verbose] [--ref=\"GLOB\"] [--unix-data]\n" " [--no-acls] [--strict-acls] [--rpfix] [--norpfix]\n" +" [--including-invalid-names]\n" ), [CAPTURE] = T( @@ -134,6 +135,7 @@ T( IMAGEX_PROGNAME" extract WIMFILE (IMAGE_NUM | IMAGE_NAME) [PATH...]\n" " [--check] [--ref=\"GLOB\"] [--verbose] [--unix-data]\n" " [--no-acls] [--strict-acls] [--to-stdout] [--dest-dir=DIR]\n" +" [--including-invalid-names]\n" ), [INFO] = T( @@ -174,7 +176,7 @@ IMAGEX_PROGNAME" unmount DIRECTORY [--commit] [--check] [--rebuild] [--lazy]\n" T( IMAGEX_PROGNAME" update WIMFILE [IMAGE_NUM | IMAGE_NAME] [--check] [--rebuild]\n" " [--threads=NUM_THREADS] [DEFAULT_ADD_OPTIONS]\n" -" [DEFAULT_DELETE_OPTIONS] < CMDFILE\n" +" [DEFAULT_DELETE_OPTIONS] [--command=STRING] [< CMDFILE]\n" ), }; @@ -197,6 +199,7 @@ enum { IMAGEX_ALLOW_OTHER_OPTION, IMAGEX_BOOT_OPTION, IMAGEX_CHECK_OPTION, + IMAGEX_COMMAND_OPTION, IMAGEX_COMMIT_OPTION, IMAGEX_COMPRESS_OPTION, IMAGEX_CONFIG_OPTION, @@ -208,6 +211,7 @@ enum { IMAGEX_FORCE_OPTION, IMAGEX_HARDLINK_OPTION, IMAGEX_HEADER_OPTION, + IMAGEX_INCLUDING_INVALID_NAMES_OPTION, IMAGEX_LAZY_OPTION, IMAGEX_LOOKUP_TABLE_OPTION, IMAGEX_METADATA_OPTION, @@ -243,6 +247,7 @@ static const struct option apply_options[] = { {T("strict-acls"), no_argument, NULL, IMAGEX_STRICT_ACLS_OPTION}, {T("rpfix"), no_argument, NULL, IMAGEX_RPFIX_OPTION}, {T("norpfix"), no_argument, NULL, IMAGEX_NORPFIX_OPTION}, + {T("including-invalid-names"), no_argument, NULL, IMAGEX_INCLUDING_INVALID_NAMES_OPTION}, {NULL, 0, NULL, 0}, }; static const struct option capture_or_append_options[] = { @@ -290,6 +295,7 @@ static const struct option extract_options[] = { {T("strict-acls"), no_argument, NULL, IMAGEX_STRICT_ACLS_OPTION}, {T("dest-dir"), required_argument, NULL, IMAGEX_DEST_DIR_OPTION}, {T("to-stdout"), no_argument, NULL, IMAGEX_TO_STDOUT_OPTION}, + {T("including-invalid-names"), no_argument, NULL, IMAGEX_INCLUDING_INVALID_NAMES_OPTION}, {NULL, 0, NULL, 0}, }; @@ -348,6 +354,7 @@ static const struct option update_options[] = { {T("threads"), required_argument, NULL, IMAGEX_THREADS_OPTION}, {T("check"), no_argument, NULL, IMAGEX_CHECK_OPTION}, {T("rebuild"), no_argument, NULL, IMAGEX_REBUILD_OPTION}, + {T("command"), required_argument, NULL, IMAGEX_COMMAND_OPTION}, /* Default delete options */ {T("force"), no_argument, NULL, IMAGEX_FORCE_OPTION}, @@ -363,6 +370,7 @@ static const struct option update_options[] = { {T("noacls"), no_argument, NULL, IMAGEX_NO_ACLS_OPTION}, {T("no-acls"), no_argument, NULL, IMAGEX_NO_ACLS_OPTION}, {T("strict-acls"), no_argument, NULL, IMAGEX_STRICT_ACLS_OPTION}, + {NULL, 0, NULL, 0}, }; @@ -999,16 +1007,41 @@ get_data_type(int ctype) return NULL; } +#define GIBIBYTE_MIN_NBYTES 10000000000ULL +#define MEBIBYTE_MIN_NBYTES 10000000ULL +#define KIBIBYTE_MIN_NBYTES 10000ULL + +static unsigned +get_unit(uint64_t total_bytes, const tchar **name_ret) +{ + if (total_bytes >= GIBIBYTE_MIN_NBYTES) { + *name_ret = T("GiB"); + return 30; + } else if (total_bytes >= MEBIBYTE_MIN_NBYTES) { + *name_ret = T("MiB"); + return 20; + } else if (total_bytes >= KIBIBYTE_MIN_NBYTES) { + *name_ret = T("KiB"); + return 10; + } else { + *name_ret = T("bytes"); + return 0; + } +} + /* Progress callback function passed to various wimlib functions. */ static int imagex_progress_func(enum wimlib_progress_msg msg, const union wimlib_progress_info *info) { unsigned percent_done; + unsigned unit_shift; + const tchar *unit_name; if (imagex_be_quiet) return 0; switch (msg) { case WIMLIB_PROGRESS_MSG_WRITE_STREAMS: + 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); if (info->write_streams.completed_streams == 0) { @@ -1019,10 +1052,12 @@ imagex_progress_func(enum wimlib_progress_msg msg, data_type, info->write_streams.num_threads, (info->write_streams.num_threads == 1) ? T("") : T("s")); } - tprintf(T("\r%"PRIu64" MiB of %"PRIu64" MiB (uncompressed) " + tprintf(T("\r%"PRIu64" %"TS" of %"PRIu64" %"TS" (uncompressed) " "written (%u%% done)"), - info->write_streams.completed_bytes >> 20, - info->write_streams.total_bytes >> 20, + info->write_streams.completed_bytes >> unit_shift, + unit_name, + info->write_streams.total_bytes >> unit_shift, + unit_name, percent_done); if (info->write_streams.completed_bytes >= info->write_streams.total_bytes) tputchar(T('\n')); @@ -1045,24 +1080,30 @@ imagex_progress_func(enum wimlib_progress_msg msg, /*case WIMLIB_PROGRESS_MSG_SCAN_END:*/ /*break;*/ case WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY: + unit_shift = get_unit(info->integrity.total_bytes, &unit_name); percent_done = TO_PERCENT(info->integrity.completed_bytes, info->integrity.total_bytes); - tprintf(T("\rVerifying integrity of \"%"TS"\": %"PRIu64" MiB " - "of %"PRIu64" MiB (%u%%) done"), + tprintf(T("\rVerifying integrity of \"%"TS"\": %"PRIu64" "TS" " + "of %"PRIu64" "TS" (%u%%) done"), info->integrity.filename, - info->integrity.completed_bytes >> 20, - info->integrity.total_bytes >> 20, + info->integrity.completed_bytes >> unit_shift, + unit_name, + info->integrity.total_bytes >> unit_shift, + unit_name, percent_done); if (info->integrity.completed_bytes == info->integrity.total_bytes) tputchar(T('\n')); break; case WIMLIB_PROGRESS_MSG_CALC_INTEGRITY: + unit_shift = get_unit(info->integrity.total_bytes, &unit_name); percent_done = TO_PERCENT(info->integrity.completed_bytes, info->integrity.total_bytes); - tprintf(T("\rCalculating integrity table for WIM: %"PRIu64" MiB " - "of %"PRIu64" MiB (%u%%) done"), - info->integrity.completed_bytes >> 20, - info->integrity.total_bytes >> 20, + tprintf(T("\rCalculating integrity table for WIM: %"PRIu64" %"TS" " + "of %"PRIu64" %"TS" (%u%%) done"), + info->integrity.completed_bytes >> unit_shift, + unit_name, + info->integrity.total_bytes >> unit_shift, + unit_name, percent_done); if (info->integrity.completed_bytes == info->integrity.total_bytes) tputchar(T('\n')); @@ -1093,10 +1134,13 @@ imagex_progress_func(enum wimlib_progress_msg msg, case WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS: percent_done = TO_PERCENT(info->extract.completed_bytes, info->extract.total_bytes); + unit_shift = get_unit(info->extract.total_bytes, &unit_name); tprintf(T("\rExtracting files: " - "%"PRIu64" MiB of %"PRIu64" MiB (%u%%) done"), - info->extract.completed_bytes >> 20, - info->extract.total_bytes >> 20, + "%"PRIu64" %"TS" of %"PRIu64" %"TS" (%u%%) done"), + info->extract.completed_bytes >> unit_shift, + unit_name, + info->extract.total_bytes >> unit_shift, + unit_name, percent_done); if (info->extract.completed_bytes >= info->extract.total_bytes) tputchar(T('\n')); @@ -1117,23 +1161,29 @@ imagex_progress_func(enum wimlib_progress_msg msg, case WIMLIB_PROGRESS_MSG_JOIN_STREAMS: percent_done = TO_PERCENT(info->join.completed_bytes, info->join.total_bytes); + unit_shift = get_unit(info->join.total_bytes, &unit_name); tprintf(T("Writing resources from part %u of %u: " - "%"PRIu64 " MiB of %"PRIu64" MiB (%u%%) written\n"), + "%"PRIu64 " %"TS" of %"PRIu64" %"TS" (%u%%) written\n"), (info->join.completed_parts == info->join.total_parts) ? info->join.completed_parts : info->join.completed_parts + 1, info->join.total_parts, - info->join.completed_bytes >> 20, - info->join.total_bytes >> 20, + info->join.completed_bytes >> unit_shift, + unit_name, + info->join.total_bytes >> unit_shift, + unit_name, percent_done); break; case WIMLIB_PROGRESS_MSG_SPLIT_BEGIN_PART: percent_done = TO_PERCENT(info->split.completed_bytes, info->split.total_bytes); - tprintf(T("Writing \"%"TS"\": %"PRIu64" MiB of " - "%"PRIu64" MiB (%u%%) written\n"), + unit_shift = get_unit(info->split.total_bytes, &unit_name); + tprintf(T("Writing \"%"TS"\": %"PRIu64" %"TS" of " + "%"PRIu64" %"TS" (%u%%) written\n"), info->split.part_name, - info->split.completed_bytes >> 20, - info->split.total_bytes >> 20, + info->split.completed_bytes >> unit_shift, + unit_name, + info->split.total_bytes >> unit_shift, + unit_name, percent_done); break; case WIMLIB_PROGRESS_MSG_SPLIT_END_PART: @@ -1486,6 +1536,10 @@ imagex_apply(int argc, tchar **argv) case IMAGEX_RPFIX_OPTION: extract_flags |= WIMLIB_EXTRACT_FLAG_RPFIX; break; + case IMAGEX_INCLUDING_INVALID_NAMES_OPTION: + extract_flags |= WIMLIB_EXTRACT_FLAG_REPLACE_INVALID_FILENAMES; + extract_flags |= WIMLIB_EXTRACT_FLAG_ALL_CASE_CONFLICTS; + break; default: usage(APPLY); return -1; @@ -2217,6 +2271,10 @@ imagex_extract(int argc, tchar **argv) extract_flags |= WIMLIB_EXTRACT_FLAG_TO_STDOUT; imagex_be_quiet = true; break; + case IMAGEX_INCLUDING_INVALID_NAMES_OPTION: + extract_flags |= WIMLIB_EXTRACT_FLAG_REPLACE_INVALID_FILENAMES; + extract_flags |= WIMLIB_EXTRACT_FLAG_ALL_CASE_CONFLICTS; + break; default: goto out_usage; } @@ -2930,11 +2988,12 @@ imagex_update(int argc, tchar **argv) int default_delete_flags = 0; unsigned num_threads = 0; int c; - tchar *cmd_file_contents; + tchar *cmd_file_contents = NULL; size_t cmd_file_nchars; struct wimlib_update_command *cmds; size_t num_cmds; int num_images; + tchar *command_str = NULL; const tchar *config_file = NULL; tchar *config_str; @@ -2957,7 +3016,22 @@ imagex_update(int argc, tchar **argv) case IMAGEX_REBUILD_OPTION: write_flags |= WIMLIB_WRITE_FLAG_REBUILD; break; - + case IMAGEX_COMMAND_OPTION: + if (command_str) { + imagex_error(T("--command may only be specified " + "one time. Please provide\n" + " the update commands " + "on standard input instead.")); + ret = -1; + goto out; + } + command_str = tstrdup(optarg); + if (!command_str) { + imagex_error(T("Out of memory!")); + ret = -1; + goto out; + } + break; /* Default delete options */ case IMAGEX_FORCE_OPTION: default_delete_flags |= WIMLIB_DELETE_FLAG_FORCE; @@ -3045,20 +3119,26 @@ imagex_update(int argc, tchar **argv) config = &default_capture_config; } - /* Read update commands from standard input */ - if (isatty(STDIN_FILENO)) { - tputs(T("Reading update commands from standard input...")); - recommend_man_page(T("update")); - } - cmd_file_contents = stdin_get_text_contents(&cmd_file_nchars); - if (!cmd_file_contents) { - ret = -1; - goto out_free_config; - } + /* Read update commands from standard input, or the command string if + * specified. */ + if (command_str) { + cmds = parse_update_command_file(&command_str, tstrlen(command_str), + &num_cmds); + } else { + if (isatty(STDIN_FILENO)) { + tputs(T("Reading update commands from standard input...")); + recommend_man_page(T("update")); + } + cmd_file_contents = stdin_get_text_contents(&cmd_file_nchars); + if (!cmd_file_contents) { + ret = -1; + goto out_free_config; + } - /* Parse the update commands */ - cmds = parse_update_command_file(&cmd_file_contents, cmd_file_nchars, - &num_cmds); + /* Parse the update commands */ + cmds = parse_update_command_file(&cmd_file_contents, cmd_file_nchars, + &num_cmds); + } if (!cmds) { ret = -1; goto out_free_cmd_file_contents; @@ -3079,15 +3159,23 @@ imagex_update(int argc, tchar **argv) } } +#ifdef __WIN32__ + win32_acquire_capture_privileges(); +#endif + /* Execute the update commands */ ret = wimlib_update_image(wim, image, cmds, num_cmds, update_flags, imagex_progress_func); if (ret) - goto out_free_cmds; + goto out_release_privs; /* Overwrite the updated WIM */ ret = wimlib_overwrite(wim, write_flags, num_threads, imagex_progress_func); +out_release_privs: +#ifdef __WIN32__ + win32_release_capture_privileges(); +#endif out_free_cmds: free(cmds); out_free_cmd_file_contents: @@ -3101,6 +3189,7 @@ out_free_config: out_wimlib_free: wimlib_free(wim); out: + free(command_str); return ret; out_usage: usage(UPDATE);