X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=programs%2Fimagex.c;h=be4b910eb024c55bd8917c27b265eda56c3456f0;hb=41ae41d4dbe9a5c8413304b5e9ae02eec76d69b1;hp=767b67240c6fc448a008454a2d4b7df7b598a9d8;hpb=b348831df3fcf7d8eb66d35e4d0cf8434e788473;p=wimlib diff --git a/programs/imagex.c b/programs/imagex.c index 767b6724..be4b910e 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -125,6 +125,7 @@ enum { IMAGEX_COMPRESS_OPTION, IMAGEX_CONFIG_OPTION, IMAGEX_DEBUG_OPTION, + IMAGEX_DELTA_FROM_OPTION, IMAGEX_DEREFERENCE_OPTION, IMAGEX_DEST_DIR_OPTION, IMAGEX_EXTRACT_XML_OPTION, @@ -146,6 +147,7 @@ enum { IMAGEX_RECOMPRESS_OPTION, IMAGEX_RECURSIVE_OPTION, IMAGEX_REF_OPTION, + IMAGEX_RESUME_OPTION, IMAGEX_RPFIX_OPTION, IMAGEX_SOFT_OPTION, IMAGEX_SOURCE_LIST_OPTION, @@ -173,6 +175,9 @@ static const struct option apply_options[] = { {T("rpfix"), no_argument, NULL, IMAGEX_RPFIX_OPTION}, {T("norpfix"), no_argument, NULL, IMAGEX_NORPFIX_OPTION}, {T("include-invalid-names"), no_argument, NULL, IMAGEX_INCLUDE_INVALID_NAMES_OPTION}, + + /* --resume is undocumented for now as it needs improvement. */ + {T("resume"), no_argument, NULL, IMAGEX_RESUME_OPTION}, {NULL, 0, NULL, 0}, }; @@ -197,6 +202,7 @@ static const struct option capture_or_append_options[] = { {T("norpfix"), no_argument, NULL, IMAGEX_NORPFIX_OPTION}, {T("pipable"), no_argument, NULL, IMAGEX_PIPABLE_OPTION}, {T("not-pipable"), no_argument, NULL, IMAGEX_NOT_PIPABLE_OPTION}, + {T("delta-from"), required_argument, NULL, IMAGEX_DELTA_FROM_OPTION}, {NULL, 0, NULL, 0}, }; @@ -417,29 +423,6 @@ file_get_size(const tchar *filename) return (off_t)-1; } -tchar pat_ntfs_log[] = T("/$ntfs.log"); -tchar pat_hiberfil_sys[] = T("/hiberfil.sys"); -tchar pat_pagefile_sys[] = T("/pagefile.sys"); -tchar pat_system_volume_information[] = T("/System Volume Information"); -tchar pat_recycler[] = T("/RECYCLER"); -tchar pat_windows_csc[] = T("/Windows/CSC"); - -tchar *default_pats[] = { - pat_ntfs_log, - pat_hiberfil_sys, - pat_pagefile_sys, - pat_system_volume_information, - pat_recycler, - pat_windows_csc, -}; - -static struct wimlib_capture_config default_capture_config = { - .exclusion_pats = { - .num_pats = sizeof(default_pats) / sizeof(default_pats[0]), - .pats = default_pats, - }, -}; - enum { PARSE_STRING_SUCCESS = 0, PARSE_STRING_FAILURE = 1, @@ -1030,10 +1013,18 @@ imagex_progress_func(enum wimlib_progress_msg msg, } break; case WIMLIB_PROGRESS_MSG_SCAN_DENTRY: - if (info->scan.excluded) - imagex_printf(T("Excluding \"%"TS"\" from capture\n"), info->scan.cur_path); - else + switch (info->scan.status) { + case WIMLIB_SCAN_DENTRY_OK: imagex_printf(T("Scanning \"%"TS"\"\n"), info->scan.cur_path); + break; + case WIMLIB_SCAN_DENTRY_EXCLUDED: + imagex_printf(T("Excluding \"%"TS"\" from capture\n"), info->scan.cur_path); + break; + case WIMLIB_SCAN_DENTRY_UNSUPPORTED: + imagex_printf(T("WARNING: Excluding unsupported file or directory\n" + " \"%"TS"\" from capture\n"), info->scan.cur_path); + break; + } break; case WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY: unit_shift = get_unit(info->integrity.total_bytes, &unit_name); @@ -1098,6 +1089,11 @@ 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_SPWM_PART_BEGIN: + imagex_printf(T("\nReading split pipable WIM part %u of %u\n"), + info->extract.part_number, + info->extract.total_parts); + break; case WIMLIB_PROGRESS_MSG_APPLY_TIMESTAMPS: if (info->extract.extract_root_wim_source_path[0] == T('\0')) imagex_printf(T("Setting timestamps on all extracted files...\n")); @@ -1125,7 +1121,7 @@ imagex_progress_func(enum wimlib_progress_msg msg, break; case WIMLIB_PROGRESS_MSG_SPLIT_END_PART: if (info->split.completed_bytes == info->split.total_bytes) { - imagex_printf(T("Finished writing part %u of %u WIM parts\n"), + imagex_printf(T("Finished writing split WIM part %u of %u\n"), info->split.cur_part_number, info->split.total_parts); } @@ -1254,15 +1250,15 @@ update_command_add_option(int op, const tchar *option, switch (op) { case WIMLIB_UPDATE_OP_ADD: if (!tstrcmp(option, T("--verbose"))) - cmd->add.add_flags |= WIMLIB_ADD_IMAGE_FLAG_VERBOSE; + cmd->add.add_flags |= WIMLIB_ADD_FLAG_VERBOSE; else if (!tstrcmp(option, T("--unix-data"))) - cmd->add.add_flags |= WIMLIB_ADD_IMAGE_FLAG_UNIX_DATA; + cmd->add.add_flags |= WIMLIB_ADD_FLAG_UNIX_DATA; else if (!tstrcmp(option, T("--no-acls")) || !tstrcmp(option, T("--noacls"))) - cmd->add.add_flags |= WIMLIB_ADD_IMAGE_FLAG_NO_ACLS; + cmd->add.add_flags |= WIMLIB_ADD_FLAG_NO_ACLS; else if (!tstrcmp(option, T("--strict-acls"))) - cmd->add.add_flags |= WIMLIB_ADD_IMAGE_FLAG_STRICT_ACLS; + cmd->add.add_flags |= WIMLIB_ADD_FLAG_STRICT_ACLS; else if (!tstrcmp(option, T("--dereference"))) - cmd->add.add_flags |= WIMLIB_ADD_IMAGE_FLAG_DEREFERENCE; + cmd->add.add_flags |= WIMLIB_ADD_FLAG_DEREFERENCE; else recognized = false; break; @@ -1496,6 +1492,9 @@ imagex_apply(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_RESUME_OPTION: + extract_flags |= WIMLIB_EXTRACT_FLAG_RESUME; + break; default: goto out_usage; } @@ -1619,7 +1618,8 @@ 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; + int add_image_flags = WIMLIB_ADD_IMAGE_FLAG_EXCLUDE_VERBOSE | + WIMLIB_ADD_IMAGE_FLAG_WINCONFIG; int write_flags = 0; int compression_type = WIMLIB_COMPRESSION_TYPE_LZX; const tchar *wimfile; @@ -1627,6 +1627,8 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) const tchar *name; const tchar *desc; const tchar *flags_element = NULL; + const tchar *template_image_name_or_num = NULL; + int template_image; WIMStruct *wim; int ret; unsigned num_threads = 0; @@ -1660,6 +1662,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; break; case IMAGEX_COMPRESS_OPTION: compression_type = get_compression_type(optarg); @@ -1707,6 +1710,14 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) case IMAGEX_NOT_PIPABLE_OPTION: write_flags |= WIMLIB_WRITE_FLAG_NOT_PIPABLE; break; + case IMAGEX_DELTA_FROM_OPTION: + if (cmd == CMD_CAPTURE) { + imagex_error(T("--delta-from=IMAGE is only " + "valid for append.")); + goto out_usage; + } + template_image_name_or_num = optarg; + break; default: goto out_usage; } @@ -1721,6 +1732,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) wimfile = argv[1]; if (!tstrcmp(wimfile, T("-"))) { + /* Writing captured WIM to standard output. */ #if 0 if (!(write_flags & WIMLIB_WRITE_FLAG_PIPABLE)) { imagex_error("Can't write a non-pipable WIM to " @@ -1740,6 +1752,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) wim_fd = STDOUT_FILENO; wimfile = NULL; imagex_info_file = stderr; + set_fd_to_binary_mode(wim_fd); } if (argc >= 3) { @@ -1808,7 +1821,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) if (ret) goto out_free_config; } else { - config = &default_capture_config; + config = NULL; } if (cmd == CMD_APPEND) @@ -1853,6 +1866,30 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) tsprintf(name_end, T(" (%lu)"), conflict_idx); } } + + if (template_image_name_or_num) { + template_image = wimlib_resolve_image(wim, template_image_name_or_num); + if (template_image_name_or_num[0] == T('-')) { + tchar *tmp; + unsigned long n; + struct wimlib_wim_info info; + + wimlib_get_wim_info(wim, &info); + n = tstrtoul(template_image_name_or_num + 1, &tmp, 10); + if (n >= 1 && n <= info.image_count && + *tmp == T('\0') && + tmp != template_image_name_or_num + 1) + { + template_image = info.image_count - (n - 1); + } + } + ret = verify_image_exists_and_is_single(template_image, + template_image_name_or_num, + wimfile); + if (ret) + goto out_wimlib_free; + } + ret = wimlib_add_image_multisource(wim, capture_sources, num_sources, @@ -1863,10 +1900,11 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) if (ret) goto out_wimlib_free; - if (desc || flags_element) { - /* User provided or element. Get the - * index of the image we just added, then use it to call the - * appropriate functions. */ + 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 + * --delta-from=IMAGE. Get the index of the image we just + * added, then use it to call the appropriate functions. */ struct wimlib_wim_info info; wimlib_get_wim_info(wim, &info); @@ -1885,6 +1923,15 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) if (ret) goto out_wimlib_free; } + + if (template_image_name_or_num) { + ret = wimlib_reference_template_image(wim, + info.image_count, + template_image, + 0, NULL); + if (ret) + goto out_wimlib_free; + } } /* Write the new WIM or overwrite the existing WIM with the new image @@ -1904,7 +1951,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) out_wimlib_free: wimlib_free(wim); out_free_config: - if (config != &default_capture_config) { + if (config) { free(config->exclusion_pats.pats); free(config->exclusion_exception_pats.pats); free(config_str); @@ -2179,6 +2226,7 @@ imagex_export(int argc, tchar **argv, int cmd) dest_wimfile = NULL; dest_wim_fd = STDOUT_FILENO; imagex_info_file = stderr; + set_fd_to_binary_mode(dest_wim_fd); } errno = ENOENT; if (dest_wimfile != NULL && tstat(dest_wimfile, &stbuf) == 0) { @@ -3201,7 +3249,8 @@ imagex_update(int argc, tchar **argv, int cmd) int open_flags = WIMLIB_OPEN_FLAG_WRITE_ACCESS; int write_flags = 0; int update_flags = WIMLIB_UPDATE_FLAG_SEND_PROGRESS; - int default_add_flags = WIMLIB_ADD_IMAGE_FLAG_EXCLUDE_VERBOSE; + int default_add_flags = WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE | + WIMLIB_ADD_FLAG_WINCONFIG; int default_delete_flags = 0; unsigned num_threads = 0; int c; @@ -3254,24 +3303,25 @@ imagex_update(int argc, tchar **argv, int cmd) /* Global add option */ case IMAGEX_CONFIG_OPTION: + default_add_flags &= ~WIMLIB_ADD_FLAG_WINCONFIG; config_file = optarg; break; /* Default add options */ case IMAGEX_VERBOSE_OPTION: - default_add_flags |= WIMLIB_ADD_IMAGE_FLAG_VERBOSE; + default_add_flags |= WIMLIB_ADD_FLAG_VERBOSE; break; case IMAGEX_DEREFERENCE_OPTION: - default_add_flags |= WIMLIB_ADD_IMAGE_FLAG_DEREFERENCE; + default_add_flags |= WIMLIB_ADD_FLAG_DEREFERENCE; break; case IMAGEX_UNIX_DATA_OPTION: - default_add_flags |= WIMLIB_ADD_IMAGE_FLAG_UNIX_DATA; + default_add_flags |= WIMLIB_ADD_FLAG_UNIX_DATA; break; case IMAGEX_NO_ACLS_OPTION: - default_add_flags |= WIMLIB_ADD_IMAGE_FLAG_NO_ACLS; + default_add_flags |= WIMLIB_ADD_FLAG_NO_ACLS; break; case IMAGEX_STRICT_ACLS_OPTION: - default_add_flags |= WIMLIB_ADD_IMAGE_FLAG_STRICT_ACLS; + default_add_flags |= WIMLIB_ADD_FLAG_STRICT_ACLS; break; default: goto out_usage; @@ -3325,7 +3375,7 @@ imagex_update(int argc, tchar **argv, int cmd) if (ret) goto out_free_config; } else { - config = &default_capture_config; + config = NULL; } /* Read update commands from standard input, or the command string if @@ -3355,13 +3405,11 @@ imagex_update(int argc, tchar **argv, int cmd) } /* Set default flags and capture config on the update commands */ - bool have_add_command = false; for (size_t i = 0; i < num_cmds; i++) { switch (cmds[i].op) { case WIMLIB_UPDATE_OP_ADD: cmds[i].add.add_flags |= default_add_flags; cmds[i].add.config = config; - have_add_command = true; break; case WIMLIB_UPDATE_OP_DELETE: cmds[i].delete.delete_flags |= default_delete_flags; @@ -3385,7 +3433,7 @@ out_free_cmds: out_free_cmd_file_contents: free(cmd_file_contents); out_free_config: - if (config != &default_capture_config) { + if (config) { free(config->exclusion_pats.pats); free(config->exclusion_exception_pats.pats); free(config_str); @@ -3441,7 +3489,7 @@ T( " [--dereference] [--config=FILE] [--threads=NUM_THREADS]\n" " [--rebuild] [--unix-data] [--source-list] [--no-acls]\n" " [--strict-acls] [--rpfix] [--norpfix] [--pipable]\n" -" [--not-pipable]\n" +" [--not-pipable] [--delta-from=IMAGE]\n" ), [CMD_APPLY] = T( @@ -3458,8 +3506,7 @@ T( " [--nocheck] [--compress=TYPE] [--flags EDITION_ID]\n" " [--verbose] [--dereference] [--config=FILE]\n" " [--threads=NUM_THREADS] [--unix-data] [--source-list]\n" -" [--no-acls] [--strict-acls] [--rpfix] [--norpfix]\n" -" [--pipable] [--not-pipable]\n" +" [--no-acls] [--strict-acls] [--norpfix] [--pipable]\n" ), [CMD_DELETE] = T( @@ -3534,24 +3581,25 @@ T( }; static const tchar *invocation_name; -static bool using_cmd_from_invocation_name = false; +static int invocation_cmd = CMD_NONE; static const tchar *get_cmd_string(int cmd, bool nospace) { - - if (using_cmd_from_invocation_name || cmd == CMD_NONE) { - return invocation_name; + static tchar buf[50]; + if (cmd == CMD_NONE) { + tsprintf(buf, T("%"TS), T(IMAGEX_PROGNAME)); + } else if (invocation_cmd != CMD_NONE) { + tsprintf(buf, T("wim%"TS), imagex_commands[cmd].name); } else { const tchar *format; - static tchar buf[50]; if (nospace) format = T("%"TS"-%"TS""); else format = T("%"TS" %"TS""); tsprintf(buf, format, invocation_name, imagex_commands[cmd].name); - return buf; } + return buf; } static void @@ -3692,7 +3740,7 @@ main(int argc, char **argv) if (!tstrcmp(invocation_name + 3, imagex_commands[i].name)) { - using_cmd_from_invocation_name = true; + invocation_cmd = i; cmd = i; break; }