X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=programs%2Fimagex.c;h=9b8af6e047d3caf16baaa544e9faefd4d55421f0;hp=2ba1a076795e326cbad4ceaa6103937e9b211c55;hb=5cdd60306facd14cc9dcc24471386451294ca73c;hpb=213d64619675a59db71fed619bf47c1870b0e2e2 diff --git a/programs/imagex.c b/programs/imagex.c index 2ba1a076..9b8af6e0 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -34,6 +34,7 @@ #include #include #include +#include #define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0])) @@ -52,6 +53,7 @@ enum imagex_op_type { JOIN, MOUNT, MOUNTRW, + OPTIMIZE, SPLIT, UNMOUNT, }; @@ -64,7 +66,7 @@ static const char *usage_strings[] = { "imagex append (DIRECTORY | NTFS_VOLUME) WIMFILE [IMAGE_NAME]\n" " [DESCRIPTION] [--boot] [--check] [--flags EDITION_ID]\n" " [--verbose] [--dereference] [--config=FILE]\n" -" [--threads=NUM_THREADS]\n", +" [--threads=NUM_THREADS] [--rebuild]\n", [APPLY] = "imagex apply WIMFILE [IMAGE_NUM | IMAGE_NAME | all]\n" " (DIRECTORY | NTFS_VOLUME) [--check] [--hardlink]\n" @@ -75,14 +77,14 @@ static const char *usage_strings[] = { " [--flags EDITION_ID] [--verbose] [--dereference]\n" " [--config=FILE] [--threads=NUM_THREADS]\n", [DELETE] = -"imagex delete WIMFILE (IMAGE_NUM | IMAGE_NAME | all) [--check]\n", +"imagex delete WIMFILE (IMAGE_NUM | IMAGE_NAME | all) [--check] [--soft]\n", [DIR] = "imagex dir WIMFILE (IMAGE_NUM | IMAGE_NAME | all)\n", [EXPORT] = "imagex export SRC_WIMFILE (SRC_IMAGE_NUM | SRC_IMAGE_NAME | all ) \n" " DEST_WIMFILE [DEST_IMAGE_NAME] [DEST_IMAGE_DESCRIPTION]\n" " [--boot] [--check] [--compress=TYPE] [--ref=\"GLOB\"]\n" -" [--threads=NUM_THREADS]\n", +" [--threads=NUM_THREADS] [--rebuild]\n", [INFO] = "imagex info WIMFILE [IMAGE_NUM | IMAGE_NAME] [NEW_NAME]\n" " [NEW_DESC] [--boot] [--check] [--header] [--lookup-table]\n" @@ -96,6 +98,8 @@ static const char *usage_strings[] = { [MOUNTRW] = "imagex mountrw WIMFILE [IMAGE_NUM | IMAGE_NAME] DIRECTORY\n" " [--check] [--debug] [--streams-interface=INTERFACE]\n", +[OPTIMIZE] = +"imagex optimize WIMFILE [--check] [--recompress]\n", [SPLIT] = "imagex split WIMFILE SPLIT_WIMFILE PART_SIZE_MB [--check]\n", [UNMOUNT] = @@ -125,10 +129,12 @@ static const struct option capture_or_append_options[] = { {"flags", required_argument, NULL, 'f'}, {"verbose", no_argument, NULL, 'v'}, {"threads", required_argument, NULL, 't'}, + {"rebuild", no_argument, NULL, 'R'}, {NULL, 0, NULL, 0}, }; static const struct option delete_options[] = { {"check", no_argument, NULL, 'c'}, + {"soft", no_argument, NULL, 's'}, {NULL, 0, NULL, 0}, }; @@ -138,6 +144,7 @@ static const struct option export_options[] = { {"compress", required_argument, NULL, 'x'}, {"ref", required_argument, NULL, 'r'}, {"threads", required_argument, NULL, 't'}, + {"rebuild", no_argument, NULL, 'R'}, {NULL, 0, NULL, 0}, }; @@ -165,6 +172,12 @@ static const struct option mount_options[] = { {NULL, 0, NULL, 0}, }; +static const struct option optimize_options[] = { + {"check", no_argument, NULL, 'c'}, + {"recompress", no_argument, NULL, 'r'}, + {NULL, 0, NULL, 0}, +}; + static const struct option split_options[] = { {"check", no_argument, NULL, 'c'}, {NULL, 0, NULL, 0}, @@ -250,6 +263,15 @@ static int get_compression_type(const char *optarg) } } +static off_t file_get_size(const char *filename) +{ + struct stat st; + if (stat(filename, &st) == 0) + return st.st_size; + else + return (off_t)-1; +} + static char *file_get_contents(const char *filename, size_t *len_ret) { struct stat stbuf; @@ -381,7 +403,8 @@ static int imagex_apply(int argc, const char **argv) const char *wimfile; const char *dir; const char *image_num_or_name; - int extract_flags = 0; + int extract_flags = WIMLIB_EXTRACT_FLAG_SEQUENTIAL | + WIMLIB_EXTRACT_FLAG_SHOW_PROGRESS; const char *swm_glob = NULL; WIMStruct **additional_swms = NULL; @@ -542,6 +565,9 @@ static int imagex_capture_or_append(int argc, const char **argv) if (num_threads == UINT_MAX) return -1; break; + case 'R': + write_flags |= WIMLIB_WRITE_FLAG_REBUILD; + break; default: usage(cmd); return -1; @@ -623,6 +649,8 @@ out_write: ret = wimlib_write(w, wimfile, WIM_ALL_IMAGES, write_flags, num_threads); } + if (ret == WIMLIB_ERR_REOPEN) + ret = 0; if (ret != 0) imagex_error("Failed to write the WIM file `%s'", wimfile); out: @@ -649,6 +677,9 @@ static int imagex_delete(int argc, const char **argv) open_flags |= WIMLIB_OPEN_FLAG_CHECK_INTEGRITY; write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY; break; + case 's': + write_flags |= WIMLIB_WRITE_FLAG_SOFT_DELETE; + break; default: usage(DELETE); return -1; @@ -689,6 +720,8 @@ static int imagex_delete(int argc, const char **argv) } ret = wimlib_overwrite(w, write_flags, 0); + if (ret == WIMLIB_ERR_REOPEN) + ret = 0; if (ret != 0) { imagex_error("Failed to write the file `%s' with image " "deleted", wimfile); @@ -797,6 +830,9 @@ static int imagex_export(int argc, const char **argv) if (num_threads == UINT_MAX) return -1; break; + case 'R': + write_flags |= WIMLIB_WRITE_FLAG_REBUILD; + break; default: usage(EXPORT); return -1; @@ -894,6 +930,8 @@ static int imagex_export(int argc, const char **argv) else ret = wimlib_overwrite(dest_w, write_flags, num_threads); out: + if (ret == WIMLIB_ERR_REOPEN) + ret = 0; wimlib_free(src_w); wimlib_free(dest_w); if (additional_swms) { @@ -1139,8 +1177,8 @@ static int imagex_info(int argc, const char **argv) } } - /* Only call wimlib_overwrite_xml_and_header() if something - * actually needs to be changed. */ + /* Only call wimlib_overwrite() if something actually needs to + * be changed. */ if (boot || new_name || new_desc || check != wimlib_has_integrity_table(w)) { @@ -1148,9 +1186,17 @@ static int imagex_info(int argc, const char **argv) if (ret != 0) return ret; - ret = wimlib_overwrite_xml_and_header(w, check ? - WIMLIB_WRITE_FLAG_CHECK_INTEGRITY | - WIMLIB_WRITE_FLAG_SHOW_PROGRESS : 0); + int write_flags; + if (check) { + write_flags = WIMLIB_WRITE_FLAG_CHECK_INTEGRITY | + WIMLIB_WRITE_FLAG_SHOW_PROGRESS; + } else { + write_flags = 0; + } + + ret = wimlib_overwrite(w, write_flags, 1); + if (ret == WIMLIB_ERR_REOPEN) + ret = 0; } else { printf("The file `%s' was not modified because nothing " "needed to be done.\n", wimfile); @@ -1158,7 +1204,7 @@ static int imagex_info(int argc, const char **argv) } } out: - /*wimlib_free(w);*/ + wimlib_free(w); return ret; } @@ -1306,6 +1352,74 @@ mount_usage: return -1; } +static int imagex_optimize(int argc, const char **argv) +{ + int c; + int open_flags = WIMLIB_OPEN_FLAG_SHOW_PROGRESS; + int write_flags = WIMLIB_WRITE_FLAG_REBUILD | + WIMLIB_WRITE_FLAG_SHOW_PROGRESS; + int ret; + WIMStruct *w; + const char *wimfile; + off_t old_size; + off_t new_size; + + for_opt(c, optimize_options) { + switch (c) { + case 'c': + open_flags |= WIMLIB_OPEN_FLAG_CHECK_INTEGRITY; + write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY; + break; + case 'r': + write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS; + break; + default: + usage(OPTIMIZE); + return -1; + } + } + argc -= optind; + argv += optind; + + if (argc != 1) { + usage(OPTIMIZE); + return -1; + } + + wimfile = argv[0]; + + ret = wimlib_open_wim(wimfile, open_flags, &w); + if (ret != 0) + return ret; + + old_size = file_get_size(argv[0]); + printf("`%s' original size: ", wimfile); + if (old_size == -1) + puts("Unknown"); + else + printf("%"PRIu64" KiB\n", old_size >> 10); + + ret = wimlib_overwrite(w, write_flags, 0); + + new_size = file_get_size(argv[0]); + printf("`%s' optimized size: ", wimfile); + if (new_size == -1) + puts("Unknown"); + else + printf("%"PRIu64" KiB\n", new_size >> 10); + + fputs("Space saved: ", stdout); + if (new_size != -1 && old_size != -1) { + printf("%lld KiB\n", + ((long long)old_size - (long long)new_size) >> 10); + } else { + puts("Unknown"); + } + + wimlib_free(w); + return ret; +} + /* Split a WIM into a spanned set */ static int imagex_split(int argc, const char **argv) { @@ -1394,6 +1508,7 @@ static const struct imagex_command imagex_commands[] = { {"join", imagex_join, JOIN}, {"mount", imagex_mount_rw_or_ro, MOUNT}, {"mountrw", imagex_mount_rw_or_ro, MOUNTRW}, + {"optimize",imagex_optimize, OPTIMIZE}, {"split", imagex_split, SPLIT}, {"unmount", imagex_unmount, UNMOUNT}, }; @@ -1459,7 +1574,7 @@ static void usage_all() { puts("IMAGEX: Usage:"); for (int i = 0; i < ARRAY_LEN(usage_strings); i++) - fputs(usage_strings[i], stdout); + printf(" %s", usage_strings[i]); static const char *extra = " imagex --help\n" " imagex --version\n"