X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=programs%2Fimagex.c;h=d567371ae1227a549a0f4233aab14de458a1a071;hp=6dd8bdbb03df7b4f9b125cc9e9c328dd227a5839;hb=0a72460f9274f11689986f6b79ea42e512dd9213;hpb=4dd45340f9fe3a533e0f1a9d6b79f8118e45ca2a diff --git a/programs/imagex.c b/programs/imagex.c index 6dd8bdbb..d567371a 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -124,6 +124,7 @@ enum { CMD_UNMOUNT, #endif CMD_UPDATE, + CMD_VERIFY, CMD_MAX, }; @@ -404,6 +405,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))) @@ -1153,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); @@ -1167,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"), @@ -1234,6 +1264,25 @@ imagex_progress_func(enum wimlib_progress_msg msg, } } break; + case WIMLIB_PROGRESS_MSG_BEGIN_VERIFY_IMAGE: + imagex_printf(T("Verifying metadata for image %"PRIu32" of %"PRIu32"\n"), + info->verify_image.current_image, + info->verify_image.total_images); + break; + case WIMLIB_PROGRESS_MSG_VERIFY_STREAMS: + percent_done = TO_PERCENT(info->verify_streams.completed_bytes, + info->verify_streams.total_bytes); + unit_shift = get_unit(info->verify_streams.total_bytes, &unit_name); + imagex_printf(T("\rVerifying streams: " + "%"PRIu64" %"TS" of %"PRIu64" %"TS" (%u%%) done"), + info->verify_streams.completed_bytes >> unit_shift, + unit_name, + info->verify_streams.total_bytes >> unit_shift, + unit_name, + percent_done); + if (info->verify_streams.completed_bytes == info->verify_streams.total_bytes) + imagex_printf(T("\n")); + break; default: break; } @@ -1664,10 +1713,10 @@ 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; @@ -1707,7 +1756,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) 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; @@ -1718,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); @@ -1750,7 +1799,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) 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. */ @@ -1764,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; @@ -1818,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; @@ -1839,7 +1888,7 @@ 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) { @@ -1958,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 { @@ -1974,7 +2026,7 @@ 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) @@ -2001,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) { @@ -2041,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; @@ -2117,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; @@ -3959,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; @@ -3986,6 +4115,7 @@ static const struct imagex_command imagex_commands[] = { [CMD_UNMOUNT] = {T("unmount"), imagex_unmount}, #endif [CMD_UPDATE] = {T("update"), imagex_update}, + [CMD_VERIFY] = {T("verify"), imagex_verify}, }; #ifdef __WIN32__ @@ -4105,6 +4235,10 @@ T( " [--command=STRING] [--wimboot-config=FILE]\n" " [< CMDFILE]\n" ), +[CMD_VERIFY] = +T( +" %"TS" WIMFILE [--ref=\"GLOB\"]\n" +), }; static const tchar *invocation_name; @@ -4114,7 +4248,7 @@ static const tchar *get_cmd_string(int cmd, bool nospace) { static tchar buf[50]; if (cmd == CMD_NONE) { - tsprintf(buf, T("%"TS), T(IMAGEX_PROGNAME)); + return T("wimlib-imagex"); } else if (invocation_cmd != CMD_NONE) { tsprintf(buf, T("wim%"TS), imagex_commands[cmd].name); } else { @@ -4134,7 +4268,7 @@ version(void) { static const tchar *s = T( -IMAGEX_PROGNAME " (distributed with " PACKAGE " " PACKAGE_VERSION ")\n" +"wimlib-imagex (distributed with " PACKAGE " " PACKAGE_VERSION ")\n" "Copyright (C) 2012, 2013, 2014 Eric Biggers\n" "License GPLv3+; GNU GPL version 3 or later .\n" "This is free software: you are free to change and redistribute it.\n" @@ -4285,7 +4419,7 @@ main(int argc, char **argv) /* Allow being invoked as wimCOMMAND (e.g. wimapply). */ cmd = CMD_NONE; if (!tstrncmp(invocation_name, T("wim"), 3) && - tstrcmp(invocation_name, T(IMAGEX_PROGNAME))) { + tstrcmp(invocation_name, T("wimlib-imagex"))) { for (int i = 0; i < CMD_MAX; i++) { if (!tstrcmp(invocation_name + 3, imagex_commands[i].name))