X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=programs%2Fimagex.c;h=a9bdab02e059454ceec778123940668f24322537;hp=6dcc62d3b63dbcb29704a95e443294a046bb760c;hb=150fd376ac944f0fdc22c0df7beaa8dbd076061c;hpb=1449ca7e974c27bec75cb6784873be3c0e6eb78a diff --git a/programs/imagex.c b/programs/imagex.c index 6dcc62d3..a9bdab02 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -3,7 +3,9 @@ * * Use wimlib to create, modify, extract, mount, unmount, or display information * about a WIM file - * + */ + +/* * Copyright (C) 2012 Eric Biggers * * This program is free software: you can redistribute it and/or modify @@ -29,6 +31,11 @@ #include #include +#ifdef WITH_NTFS_3G +#include +#include +#endif + #define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0])) #define swap(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); \ @@ -37,6 +44,7 @@ #define for_opt(c, opts) while ((c = getopt_long_only(argc, (char**)argv, "", \ opts, NULL)) != -1) + enum imagex_op_type { APPEND, APPLY, @@ -48,6 +56,7 @@ enum imagex_op_type { JOIN, MOUNT, MOUNTRW, + SPLIT, UNMOUNT, }; @@ -72,14 +81,14 @@ static const char *path_basename(const char *path) static const char *usage_strings[] = { [APPEND] = " imagex append DIRECTORY WIMFILE [\"IMAGE_NAME\"] [\"DESCRIPTION\"] [--boot]\n" -" [--check] [--config CONFIG_FILE] [--flags EDITIONID] [--verify]\n", +" [--check] [--flags EDITIONID] [--dereference]\n", [APPLY] = " imagex apply WIMFILE [IMAGE_NUM | IMAGE_NAME | all] DIRECTORY [--check]\n" -" [--verify] [--hardlink] [--symlink] [--verbose]\n", +" [--hardlink] [--symlink] [--verbose]\n", [CAPTURE] = " imagex capture DIRECTORY WIMFILE [\"IMAGE_NAME\"] [\"DESCRIPTION\"]\n" -" [--boot] [--check] [--compress[=TYPE]] [--config CONFIG_FILE]\n" -" [--flags \"EditionID\"] [--norpfix] [--verify] [--verbose]\n", +" l [--boot] [--check] [--compress[=TYPE]]\n" +" [--flags \"EditionID\"] [--verbose] [--dereference]\n", [DELETE] = " imagex delete WIMFILE (IMAGE_NUM | IMAGE_NAME | all) [--check]\n", [DIR] = @@ -87,19 +96,21 @@ static const char *usage_strings[] = { [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]]\n", +" [--boot] [--check] [--compress[=TYPE]]\n", [INFO] = " imagex info WIMFILE [IMAGE_NUM | IMAGE_NAME] [NEW_NAME]\n" -" [NEW_DESC] [--boot] [--check] [--header] [--lookup-table]\n" -" [--xml] [--extract-xml FILE] [--metadata]\n", +" [NEW_DESC] [--boot] [--check] [--header] [--lookup-table]\n" +" [--xml] [--extract-xml FILE] [--metadata]\n", [JOIN] = -" imagex join [--check] --output WIMFILE SPLIT_WIM...\n", +" imagex join [--check] WIMFILE SPLIT_WIM...\n", [MOUNT] = " imagex mount WIMFILE (IMAGE_NUM | IMAGE_NAME) DIRECTORY\n" -" [--check] [--debug]\n", +" [--check] [--debug] [--stream-interface=INTERFACE]\n", [MOUNTRW] = " imagex mountrw WIMFILE [IMAGE_NUM | IMAGE_NAME] DIRECTORY\n" -" [--check] [--debug]\n", +" [--check] [--debug] [--stream-interface=INTERFACE]\n", +[SPLIT] = +" imagex split WIMFILE SPLIT_WIMFILE PART_SIZE [--check]\n", [UNMOUNT] = " imagex unmount DIRECTORY [--commit] [--check]\n", }; @@ -113,14 +124,12 @@ static const struct option common_options[] = { static const struct option append_options[] = { {"boot", no_argument, NULL, 'b'}, {"check", no_argument, NULL, 'c'}, - {"config", required_argument, NULL, 'C'}, {"flags", required_argument, NULL, 'f'}, - {"verify", no_argument, NULL, 'V'}, + {"dereference", no_argument, NULL, 'L'}, {NULL, 0, NULL, 0}, }; static const struct option apply_options[] = { {"check", no_argument, NULL, 'c'}, - {"verify", no_argument, NULL, 'V'}, {"hardlink", no_argument, NULL, 'h'}, {"symlink", no_argument, NULL, 's'}, {"verbose", no_argument, NULL, 'v'}, @@ -130,11 +139,9 @@ static const struct option capture_options[] = { {"boot", no_argument, NULL, 'b'}, {"check", no_argument, NULL, 'c'}, {"compress", optional_argument, NULL, 'x'}, - {"config", required_argument, NULL, 'C'}, {"flags", required_argument, NULL, 'f'}, - {"norpfix", no_argument, NULL, 'n'}, - {"verify", no_argument, NULL, 'V'}, - {"verbose", no_argument, NULL, 'v'}, + {"verbose", no_argument, NULL,'v'}, + {"dereference", no_argument, NULL, 'L'}, {NULL, 0, NULL, 0}, }; static const struct option delete_options[] = { @@ -162,13 +169,18 @@ static const struct option info_options[] = { static const struct option join_options[] = { {"check", no_argument, NULL, 'c'}, - {"output", required_argument, NULL, 'o'}, {NULL, 0, NULL, 0}, }; static const struct option mount_options[] = { {"check", no_argument, NULL, 'c'}, {"debug", no_argument, NULL, 'd'}, + {"stream-interface", required_argument, NULL, 's'}, + {NULL, 0, NULL, 0}, +}; + +static const struct option split_options[] = { + {"check", no_argument, NULL, 'c'}, {NULL, 0, NULL, 0}, }; @@ -186,6 +198,19 @@ static void imagex_error(const char *format, ...) va_start(va, format); fputs("ERROR: ", stderr); vfprintf(stderr, format, va); + putc('\n', stderr); + va_end(va); +} + +/* Print formatted error message to stderr. */ +static void imagex_error_with_errno(const char *format, ...) +{ + int errno_save = errno; + va_list va; + va_start(va, format); + fputs("ERROR: ", stderr); + vfprintf(stderr, format, va); + fprintf(stderr, ": %s\n", strerror(errno_save)); va_end(va); } @@ -226,7 +251,7 @@ static void usage_all() static int verify_image_exists(int image) { if (image == WIM_NO_IMAGE) { - imagex_error("Not a valid image!\n"); + imagex_error("Not a valid image"); return WIMLIB_ERR_INVALID_IMAGE; } return 0; @@ -235,7 +260,7 @@ static int verify_image_exists(int image) static int verify_image_is_single(int image) { if (image == WIM_ALL_IMAGES) { - imagex_error("Cannot specify all images for this action!\n"); + imagex_error("Cannot specify all images for this action"); return WIMLIB_ERR_INVALID_IMAGE; } return 0; @@ -262,8 +287,7 @@ static int get_compression_type(const char *optarg) return WIM_COMPRESSION_TYPE_NONE; else { imagex_error("Invalid compression type `%s'! Must be " - "\"maximum\", \"fast\", or \"none\".\n", - optarg); + "\"maximum\", \"fast\", or \"none\".", optarg); return WIM_COMPRESSION_TYPE_INVALID; } } @@ -291,14 +315,11 @@ static int imagex_append(int argc, const char **argv) open_flags |= WIMLIB_OPEN_FLAG_CHECK_INTEGRITY; write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY; break; - case 'C': - /*config = optarg;*/ - break; case 'f': flags_element = optarg; break; - case 'V': - /* verify */ + case 'L': + add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_DEREFERENCE; break; default: usage(APPEND); @@ -334,9 +355,7 @@ done: static int imagex_apply(int argc, const char **argv) { int c; - int link_type = WIM_LINK_TYPE_NONE; int open_flags = WIMLIB_OPEN_FLAG_SHOW_PROGRESS; - bool verbose = false; int image; int num_images; WIMStruct *w; @@ -344,23 +363,21 @@ 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; for_opt(c, apply_options) { switch (c) { case 'c': open_flags |= WIMLIB_OPEN_FLAG_CHECK_INTEGRITY; break; - case 'V': - /* verify */ - break; case 'h': - link_type = WIM_LINK_TYPE_HARD; + extract_flags |= WIMLIB_EXTRACT_FLAG_HARDLINK; break; case 's': - link_type = WIM_LINK_TYPE_SYMBOLIC; + extract_flags |= WIMLIB_EXTRACT_FLAG_SYMLINK; break; case 'v': - verbose = true; + extract_flags |= WIMLIB_EXTRACT_FLAG_VERBOSE; break; default: usage(APPLY); @@ -385,28 +402,44 @@ static int imagex_apply(int argc, const char **argv) ret = wimlib_open_wim(wimfile, open_flags, &w); if (ret != 0) - return ret; + goto out; image = wimlib_resolve_image(w, image_num_or_name); ret = verify_image_exists(image); if (ret != 0) - goto done; + goto out; num_images = wimlib_get_num_images(w); if (argc == 2 && num_images != 1) { imagex_error("`%s' contains %d images; Please select one " - "(or all).\n", wimfile, num_images); + "(or all)", wimfile, num_images); usage(APPLY); ret = -1; - goto done; + goto out; } - ret = wimlib_set_output_dir(w, dir); - if (ret != 0) - goto done; - wimlib_set_verbose(w, verbose); - wimlib_set_link_type(w, link_type); - ret = wimlib_extract_image(w, image); -done: + +#ifdef WITH_NTFS_3G + struct stat stbuf; + + ret = stat(dir, &stbuf); + if (ret == 0) { + if (S_ISBLK(stbuf.st_mode) || S_ISREG(stbuf.st_mode)) { + const char *ntfs_device = dir; + printf("Applying image %d of `%s' to NTFS filesystem on `%s'\n", + image, wimfile, ntfs_device); + ret = wimlib_apply_image_to_ntfs_volume(w, image, + ntfs_device, + extract_flags); + goto out; + } + } else { + if (errno != -ENOENT) + imagex_error_with_errno("Failed to stat `%s'", dir); + } +#endif + + ret = wimlib_extract_image(w, image, dir, extract_flags); +out: wimlib_free(w); return ret; } @@ -419,8 +452,7 @@ static int imagex_capture(int argc, const char **argv) int add_image_flags = 0; int write_flags = WIMLIB_WRITE_FLAG_SHOW_PROGRESS; int compression_type = WIM_COMPRESSION_TYPE_NONE; - const char *flags_element = NULL; - bool verbose = false; + const char *flags_element = NULL; const char *dir; const char *wimfile; const char *name; @@ -441,20 +473,17 @@ static int imagex_capture(int argc, const char **argv) if (compression_type == WIM_COMPRESSION_TYPE_INVALID) return -1; break; - case 'C': - /*config = optarg;*/ - break; case 'f': flags_element = optarg; break; - case 'n': - /*norpfix = true;*/ - break; case 'v': - verbose = true; + add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_VERBOSE; + break; + case 'N': + add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_NTFS; break; - case 'V': - /*verify = true;*/ + case 'L': + add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_DEREFERENCE; break; default: usage(CAPTURE); @@ -477,18 +506,16 @@ static int imagex_capture(int argc, const char **argv) if (ret != 0) return ret; - wimlib_set_verbose(w, verbose); - ret = wimlib_add_image(w, dir, name, desc, flags_element, add_image_flags); if (ret != 0) { - imagex_error("Failed to add the image `%s'!\n", dir); + imagex_error("Failed to add the image `%s'", dir); goto done; } ret = wimlib_write(w, wimfile, WIM_ALL_IMAGES, write_flags); if (ret != 0) - imagex_error("Failed to write the WIM file `%s'!\n", wimfile); + imagex_error("Failed to write the WIM file `%s'", wimfile); done: wimlib_free(w); return ret; @@ -522,9 +549,9 @@ static int imagex_delete(int argc, const char **argv) if (argc != 2) { if (argc < 1) - imagex_error("Must specify a WIM file!\n"); + imagex_error("Must specify a WIM file"); if (argc < 2) - imagex_error("Must specify an image!\n"); + imagex_error("Must specify an image"); usage(DELETE); return -1; } @@ -543,15 +570,14 @@ static int imagex_delete(int argc, const char **argv) ret = wimlib_delete_image(w, image); if (ret != 0) { - imagex_error("Failed to delete image from `%s'!\n", - wimfile); + imagex_error("Failed to delete image from `%s'", wimfile); goto done; } ret = wimlib_overwrite(w, write_flags); if (ret != 0) { imagex_error("Failed to write the file `%s' with image " - "deleted!\n", wimfile); + "deleted", wimfile); } done: wimlib_free(w); @@ -569,12 +595,12 @@ static int imagex_dir(int argc, const char **argv) int part_number; if (argc < 2) { - imagex_error("Must specify a WIM file!\n"); + imagex_error("Must specify a WIM file"); usage(DIR); return -1; } if (argc > 3) { - imagex_error("Too many arguments!\n"); + imagex_error("Too many arguments"); usage(DIR); return -1; } @@ -586,9 +612,9 @@ static int imagex_dir(int argc, const char **argv) part_number = wimlib_get_part_number(w, NULL); if (part_number != 1) { - imagex_error("`%s' is part %d of a split WIM! Specify the first part " - "to see the files.\n", - wimfile, part_number); + imagex_error("`%s' is part %d of a split WIM! Specify the " + "first part to see the files", + wimfile, part_number); ret = WIMLIB_ERR_SPLIT_UNSUPPORTED; goto done; } @@ -604,7 +630,7 @@ static int imagex_dir(int argc, const char **argv) num_images = wimlib_get_num_images(w); if (num_images != 1) { imagex_error("The file `%s' contains %d images; Please " - "select one.\n", wimfile, num_images); + "select one.", wimfile, num_images); usage(DIR); ret = -1; goto done; @@ -682,7 +708,7 @@ static int imagex_export(int argc, const char **argv) wim_is_new = false; /* Destination file exists. */ if (!S_ISREG(stbuf.st_mode)) { - imagex_error("`%s' is not a regular file!\n", + imagex_error("`%s' is not a regular file", dest_wimfile); goto done; } @@ -693,8 +719,9 @@ static int imagex_export(int argc, const char **argv) if (compression_type_specified && compression_type != wimlib_get_compression_type(dest_w)) { imagex_error("Cannot specify a compression type that is " - "not the same as that used in the " - "destination WIM!\n"); + "not the same as that used in the " + "destination WIM"); + ret = -1; goto done; } compression_type = wimlib_get_compression_type(dest_w); @@ -706,7 +733,7 @@ static int imagex_export(int argc, const char **argv) if (ret != 0) goto done; } else { - imagex_error("Cannot stat file `%s': %m\n", + imagex_error_with_errno("Cannot stat file `%s'", dest_wimfile); goto done; } @@ -829,12 +856,12 @@ static int imagex_info(int argc, const char **argv) image = wimlib_resolve_image(w, image_num_or_name); if (image == WIM_NO_IMAGE && strcmp(image_num_or_name, "0") != 0) { - imagex_error("The image `%s' does not exist!\n", + imagex_error("The image `%s' does not exist", image_num_or_name); if (boot) imagex_error("If you would like to set the boot " - "index to 0, specify image \"0\" with " - "the --boot flag.\n"); + "index to 0, specify image \"0\" with " + "the --boot flag."); ret = WIMLIB_ERR_INVALID_IMAGE; goto done; } @@ -842,15 +869,15 @@ static int imagex_info(int argc, const char **argv) if (image == WIM_ALL_IMAGES && wimlib_get_num_images(w) > 1) { if (boot) { imagex_error("Cannot specify the --boot flag " - "without specifying a specific " - "image in a multi-image WIM!\n"); + "without specifying a specific " + "image in a multi-image WIM"); ret = WIMLIB_ERR_INVALID_IMAGE; goto done; } if (new_name) { imagex_error("Cannot specify the NEW_NAME " - "without specifying a specific " - "image in a multi-image WIM!\n"); + "without specifying a specific " + "image in a multi-image WIM"); ret = WIMLIB_ERR_INVALID_IMAGE; goto done; } @@ -861,8 +888,8 @@ static int imagex_info(int argc, const char **argv) if (!new_name && !boot) { if (image == WIM_NO_IMAGE) { - imagex_error("`%s' is not a valid image!\n", - image_num_or_name); + imagex_error("`%s' is not a valid image", + image_num_or_name); ret = WIMLIB_ERR_INVALID_IMAGE; goto done; } @@ -876,8 +903,8 @@ static int imagex_info(int argc, const char **argv) if (lookup_table) { if (total_parts != 1) { printf("Warning: Only showing the lookup table " - "for part %d of a %d-part WIM.\n", - part_number, total_parts); + "for part %d of a %d-part WIM.\n", + part_number, total_parts); } wimlib_print_lookup_table(w); } @@ -891,15 +918,16 @@ static int imagex_info(int argc, const char **argv) if (xml_out_file) { fp = fopen(xml_out_file, "wb"); if (!fp) { - imagex_error("Failed to open the file `%s' for " - "writing: %m\n", xml_out_file); + imagex_error_with_errno("Failed to open the " + "file `%s' for " + "writing ", + xml_out_file); goto done; } ret = wimlib_extract_xml_data(w, fp); if (fclose(fp) != 0) { - imagex_error("Failed to close the " - "file `%s': %m\n", - xml_out_file); + imagex_error("Failed to close the file `%s'", + xml_out_file); goto done; } @@ -913,8 +941,8 @@ static int imagex_info(int argc, const char **argv) if (metadata) { if (total_parts != 1 && part_number != 1) { imagex_error("Select part 1 of this %d-part WIM " - "to see the image metadata.\n", - total_parts); + "to see the image metadata", + total_parts); return WIMLIB_ERR_SPLIT_UNSUPPORTED; } ret = wimlib_print_metadata(w, image); @@ -923,7 +951,7 @@ static int imagex_info(int argc, const char **argv) } } else { if (total_parts != 1) { - imagex_error("Modifying a split WIM is not supported.\n"); + imagex_error("Modifying a split WIM is not supported."); return -1; } if (image == WIM_ALL_IMAGES) @@ -931,18 +959,18 @@ static int imagex_info(int argc, const char **argv) if (image == WIM_NO_IMAGE && new_name) { imagex_error("Cannot specify new_name (`%s') when " - "using image 0!\n"); + "using image 0", new_name); return -1; } if (boot) { if (image == wimlib_get_boot_idx(w)) { printf("Image %d is already marked as " - "bootable.\n", image); + "bootable.\n", image); boot = false; } else { - printf("Marking image %d as bootable.\n", - image); + printf("Marking image %d as bootable.\n", + image); wimlib_set_boot_idx(w, image); } } @@ -950,11 +978,11 @@ static int imagex_info(int argc, const char **argv) if (strcmp(wimlib_get_image_name(w, image), new_name) == 0) { printf("Image %d is already named \"%s\".\n", - image, new_name); + image, new_name); new_name = NULL; } else { - printf("Changing the name of image %d to \"%s\".\n", - image, new_name); + printf("Changing the name of image %d to " + "\"%s\".\n", image, new_name); ret = wimlib_set_image_name(w, image, new_name); if (ret != 0) goto done; @@ -965,11 +993,11 @@ static int imagex_info(int argc, const char **argv) old_desc = wimlib_get_image_description(w, image); if (old_desc && strcmp(old_desc, new_desc) == 0) { printf("The description of image %d is already " - "\"%s\".\n", image, new_desc); + "\"%s\".\n", image, new_desc); new_desc = NULL; } else { printf("Changing the description of image %d " - "to \"%s\".\n", image, new_desc); + "to \"%s\".\n", image, new_desc); ret = wimlib_set_image_descripton(w, image, new_desc); if (ret != 0) @@ -1002,18 +1030,13 @@ static int imagex_join(int argc, const char **argv) { int c; int flags = WIMLIB_OPEN_FLAG_SPLIT_OK | WIMLIB_OPEN_FLAG_SHOW_PROGRESS; - int image; - int ret; - const char *output_path = NULL; + const char *output_path; for_opt(c, join_options) { switch (c) { case 'c': flags |= WIMLIB_OPEN_FLAG_CHECK_INTEGRITY; break; - case 'o': - output_path = optarg; - break; default: goto err; } @@ -1022,15 +1045,12 @@ static int imagex_join(int argc, const char **argv) argv += optind; if (argc < 2) { - imagex_error("Must specify at least two split WIM " - "(.swm) parts to join!\n"); - goto err; - } - if (!output_path) { - imagex_error("Must specify output_path!\n"); + imagex_error("Must specify at least one split WIM (.swm) parts " + "to join"); goto err; } - return wimlib_join(argv, argc, output_path, flags); + output_path = argv[0]; + return wimlib_join(++argv, --argc, output_path, flags); err: usage(JOIN); return -1; @@ -1039,7 +1059,6 @@ err: /* Mounts an image using a FUSE mount. */ static int imagex_mount_rw_or_ro(int argc, const char **argv) { - bool ro; int c; int mount_flags = 0; int open_flags = WIMLIB_OPEN_FLAG_SHOW_PROGRESS; @@ -1060,17 +1079,26 @@ static int imagex_mount_rw_or_ro(int argc, const char **argv) case 'd': mount_flags |= WIMLIB_MOUNT_FLAG_DEBUG; break; + case 's': + if (strcasecmp(optarg, "none") == 0) + mount_flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE; + else if (strcasecmp(optarg, "xattr") == 0) + mount_flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR; + else if (strcasecmp(optarg, "windows") == 0) + mount_flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS; + else { + imagex_error("Unknown stream interface \"%s\"", optarg); + goto mount_usage; + } + break; default: - usage(ro ? MOUNT : MOUNTRW); - return -1; + goto mount_usage; } } argc -= optind; argv += optind; - if (argc != 2 && argc != 3) { - usage(ro ? MOUNT : MOUNTRW); - return -1; - } + if (argc != 2 && argc != 3) + goto mount_usage; wimfile = argv[0]; @@ -1083,8 +1111,9 @@ static int imagex_mount_rw_or_ro(int argc, const char **argv) num_images = wimlib_get_num_images(w); if (num_images != 1) { imagex_error("The file `%s' contains %d images; Please " - "select one.\n", wimfile, num_images); - usage(ro ? MOUNT : MOUNTRW); + "select one", wimfile, num_images); + usage((mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) + ? MOUNTRW : MOUNT); ret = WIMLIB_ERR_INVALID_IMAGE; goto done; } @@ -1100,13 +1129,45 @@ static int imagex_mount_rw_or_ro(int argc, const char **argv) ret = wimlib_mount(w, image, dir, mount_flags); if (ret != 0) { - imagex_error("Failed to mount image %d from `%s' on `%s'!\n", - image, wimfile, dir); + imagex_error("Failed to mount image %d from `%s' on `%s'", + image, wimfile, dir); } done: wimlib_free(w); return ret; +mount_usage: + usage((mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) + ? MOUNTRW : MOUNT); + return -1; +} + +/* Split a WIM into a spanned set */ +static int imagex_split(int argc, const char **argv) +{ + int c; + int flags = WIMLIB_OPEN_FLAG_SHOW_PROGRESS; + unsigned long part_size; + + for_opt(c, split_options) { + switch (c) { + case 'c': + flags |= WIMLIB_OPEN_FLAG_CHECK_INTEGRITY; + break; + default: + usage(SPLIT); + return -1; + } + } + argc -= optind; + argv += optind; + + if (argc != 3) { + usage(SPLIT); + return -1; + } + part_size = strtoul(argv[2], NULL, 10) * (1 << 20); + return wimlib_split(argv[0], argv[1], part_size, flags); } /* Unmounts an image. */ @@ -1138,7 +1199,7 @@ static int imagex_unmount(int argc, const char **argv) ret = wimlib_unmount(argv[0], unmount_flags); if (ret != 0) - imagex_error("Failed to unmount `%s'!\n", argv[0]); + imagex_error("Failed to unmount `%s'", argv[0]); return ret; } @@ -1159,6 +1220,7 @@ static struct imagex_command imagex_commands[] = { {"join", imagex_join, JOIN}, {"mount", imagex_mount_rw_or_ro, MOUNT}, {"mountrw", imagex_mount_rw_or_ro, MOUNTRW}, + {"split", imagex_split, SPLIT}, {"unmount", imagex_unmount, UNMOUNT}, }; @@ -1203,7 +1265,7 @@ int main(int argc, const char **argv) int ret; if (argc < 2) { - imagex_error("No command specified!\n"); + imagex_error("No command specified"); usage_all(); return 1; } @@ -1219,14 +1281,23 @@ int main(int argc, const char **argv) ret = cmd->func(argc, argv); if (ret > 0) { imagex_error("Exiting with error code %d:\n" - " %s.\n", ret, - wimlib_get_error_string(ret)); + " %s.", ret, + wimlib_get_error_string(ret)); + if (ret == WIMLIB_ERR_NTFS_3G) + imagex_error_with_errno("errno"); } return ret; } } - imagex_error("Unrecognized command: `%s'\n", argv[0]); + imagex_error("Unrecognized command: `%s'", argv[0]); usage_all(); return 1; } +/*#ifndef WITH_NTFS_3G*/ + /*ERROR("wimlib was not compiled with support for NTFS-3g, so we cannot extract");*/ + /*ERROR("a WIM to a NTFS filesystem while preserving NTFS-specific metadata.");*/ + /*ERROR("Please apply the WIM to a directory rather than a block device, ");*/ + /*ERROR("and without the NTFS flag; or compile in support for NTFS-3g.");*/ + /*return WIMLIB_ERR_UNSUPPORTED;*/ +/*#endif*/