X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=programs%2Fimagex.c;h=d41964a22ba384b9bd514b3c7209c8eae8546df9;hp=7bb553700541015cf42dca2efbc22385b085a889;hb=5d1e60d65eed94e7d2acae5dc4e9e95563e571ab;hpb=d8ebcfcc7ea9ecb5b474df79bb853b191b35c587 diff --git a/programs/imagex.c b/programs/imagex.c index 7bb55370..d41964a2 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -80,23 +80,27 @@ static const char *path_basename(const char *path) static const char *usage_strings[] = { [APPEND] = -" imagex append DIRECTORY WIMFILE [\"IMAGE_NAME\"] [\"DESCRIPTION\"] [--boot]\n" -" [--check] [--flags EDITIONID] [--dereference]\n", +" imagex append (DIRECTORY | NTFS_VOLUME) WIMFILE [\"IMAGE_NAME\"]\n" +" [\"DESCRIPTION\"] [--boot] [--check] [--flags EDITIONID]\n" +" [--verbose] [--dereference] [--config=FILE]\n", [APPLY] = -" imagex apply WIMFILE [IMAGE_NUM | IMAGE_NAME | all] DIRECTORY [--check]\n" -" [--hardlink] [--symlink] [--verbose]\n", +" imagex apply WIMFILE [IMAGE_NUM | IMAGE_NAME | all]\n" +" (DIRECTORY | NTFS_VOLUME) [--check] [--hardlink]\n" +" [--symlink] [--verbose]\n", [CAPTURE] = -" imagex capture DIRECTORY WIMFILE [\"IMAGE_NAME\"] [\"DESCRIPTION\"]\n" -" l [--boot] [--check] [--compress[=TYPE]]\n" -" [--flags \"EditionID\"] [--verbose] [--dereference]\n", +" imagex capture (DIRECTORY | NTFS_VOLUME) WIMFILE [\"IMAGE_NAME\"]\n" +" [\"DESCRIPTION\"] [--boot] [--check] [--compress=TYPE]\n" +" [--flags \"EditionID\"] [--verbose] [--dereference]\n" +" [--config=FILE]\n", [DELETE] = " imagex delete WIMFILE (IMAGE_NUM | IMAGE_NAME | all) [--check]\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]]\n", +" DEST_WIMFILE [\"DEST_IMAGE_NAME\"]\n" +" [\"DEST_IMAGE_DESCRIPTION\"] [--boot] [--check]\n" +" [--compress=TYPE]\n", [INFO] = " imagex info WIMFILE [IMAGE_NUM | IMAGE_NAME] [NEW_NAME]\n" " [NEW_DESC] [--boot] [--check] [--header] [--lookup-table]\n" @@ -105,12 +109,12 @@ static const char *usage_strings[] = { " imagex join [--check] WIMFILE SPLIT_WIM...\n", [MOUNT] = " imagex mount WIMFILE (IMAGE_NUM | IMAGE_NAME) DIRECTORY\n" -" [--check] [--debug] [--stream-interface=INTERFACE]\n", +" [--check] [--debug] [--streams-interface=INTERFACE]\n", [MOUNTRW] = " imagex mountrw WIMFILE [IMAGE_NUM | IMAGE_NAME] DIRECTORY\n" -" [--check] [--debug] [--stream-interface=INTERFACE]\n", +" [--check] [--debug] [--streams-interface=INTERFACE]\n", [SPLIT] = -" imagex split WIMFILE SPLIT_WIMFILE PART_SIZE [--check]\n", +" imagex split WIMFILE SPLIT_WIMFILE PART_SIZE_MB [--check]\n", [UNMOUNT] = " imagex unmount DIRECTORY [--commit] [--check]\n", }; @@ -122,10 +126,12 @@ static const struct option common_options[] = { }; static const struct option append_options[] = { - {"boot", no_argument, NULL, 'b'}, - {"check", no_argument, NULL, 'c'}, - {"flags", required_argument, NULL, 'f'}, - {"dereference", no_argument, NULL, 'L'}, + {"boot", no_argument, NULL, 'b'}, + {"check", no_argument, NULL, 'c'}, + {"config", required_argument, NULL, 'C'}, + {"dereference", no_argument, NULL, 'L'}, + {"flags", required_argument, NULL, 'f'}, + {"verbose", no_argument, NULL, 'v'}, {NULL, 0, NULL, 0}, }; static const struct option apply_options[] = { @@ -133,18 +139,16 @@ static const struct option apply_options[] = { {"hardlink", no_argument, NULL, 'h'}, {"symlink", no_argument, NULL, 's'}, {"verbose", no_argument, NULL, 'v'}, - {"ntfs", no_argument, NULL, 'N'}, - {"mkntfs-args", required_argument, NULL, 'm'}, {NULL, 0, NULL, 0}, }; static const struct option capture_options[] = { - {"boot", no_argument, NULL, 'b'}, - {"check", no_argument, NULL, 'c'}, - {"compress", optional_argument, NULL, 'x'}, - {"flags", required_argument, NULL, 'f'}, - {"verbose", no_argument, NULL,'v'}, - {"ntfs", no_argument, NULL, 'N'}, - {"dereference", no_argument, NULL, 'L'}, + {"boot", no_argument, NULL, 'b'}, + {"check", no_argument, NULL, 'c'}, + {"compress", required_argument, NULL, 'x'}, + {"config", required_argument, NULL, 'C'}, + {"dereference", no_argument, NULL, 'L'}, + {"flags", required_argument, NULL, 'f'}, + {"verbose", no_argument, NULL, 'v'}, {NULL, 0, NULL, 0}, }; static const struct option delete_options[] = { @@ -153,20 +157,20 @@ static const struct option delete_options[] = { }; static const struct option export_options[] = { - {"boot", no_argument, NULL, 'b'}, - {"check", no_argument , NULL, 'c'}, - {"compress", optional_argument, NULL, 'x'}, + {"boot", no_argument, NULL, 'b'}, + {"check", no_argument, NULL, 'c'}, + {"compress", required_argument, NULL, 'x'}, {NULL, 0, NULL, 0}, }; static const struct option info_options[] = { {"boot", no_argument, NULL, 'b'}, {"check", no_argument, NULL, 'c'}, + {"extract-xml", required_argument, NULL, 'X'}, {"header", no_argument, NULL, 'h'}, {"lookup-table", no_argument, NULL, 'l'}, - {"xml", no_argument, NULL, 'x'}, - {"extract-xml", required_argument, NULL, 'X'}, {"metadata", no_argument, NULL, 'm'}, + {"xml", no_argument, NULL, 'x'}, {NULL, 0, NULL, 0}, }; @@ -178,7 +182,7 @@ static const struct option join_options[] = { static const struct option mount_options[] = { {"check", no_argument, NULL, 'c'}, {"debug", no_argument, NULL, 'd'}, - {"stream-interface", required_argument, NULL, 's'}, + {"streams-interface", required_argument, NULL, 's'}, {NULL, 0, NULL, 0}, }; @@ -280,8 +284,6 @@ static int verify_image_exists_and_is_single(int image) static int get_compression_type(const char *optarg) { - if (!optarg) - return WIM_COMPRESSION_TYPE_LZX; if (strcasecmp(optarg, "maximum") == 0 || strcasecmp(optarg, "lzx") == 0) return WIM_COMPRESSION_TYPE_LZX; else if (strcasecmp(optarg, "fast") == 0 || strcasecmp(optarg, "xpress") == 0) @@ -295,6 +297,45 @@ static int get_compression_type(const char *optarg) } } +static const char *file_get_contents(const char *filename, size_t *len_ret) +{ + struct stat stbuf; + char *buf; + size_t len; + FILE *fp; + + if (stat(filename, &stbuf) != 0) { + imagex_error_with_errno("Failed to stat the file `%s'", filename); + return NULL; + } + len = stbuf.st_size; + + fp = fopen(filename, "rb"); + if (!fp) { + imagex_error_with_errno("Failed to open the file `%s'", filename); + return NULL; + } + + buf = malloc(len); + if (!buf) { + imagex_error("Failed to allocate buffer of %zu bytes to hold " + "contents of file `%s'", len, filename); + goto out_fclose; + } + if (fread(buf, 1, len, fp) != len) { + imagex_error_with_errno("Failed to read %lu bytes from the " + "file `%s'", len, filename); + goto out_free_buf; + } + *len_ret = len; + return buf; +out_free_buf: + free(buf); +out_fclose: + fclose(fp); + return NULL; +} + static int imagex_append(int argc, const char **argv) { int c; @@ -306,8 +347,12 @@ static int imagex_append(int argc, const char **argv) const char *wimfile; const char *name; const char *desc; + const char *config_file = NULL; + const char *config_str = NULL; + size_t config_len = 0; WIMStruct *w; int ret; + int cur_image; for_opt(c, append_options) { switch (c) { @@ -318,12 +363,18 @@ 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_file = optarg; + break; case 'f': flags_element = optarg; break; case 'L': add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_DEREFERENCE; break; + case 'v': + add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_VERBOSE; + break; default: usage(APPEND); return -1; @@ -340,16 +391,56 @@ static int imagex_append(int argc, const char **argv) name = (argc >= 3) ? argv[2] : path_basename(dir); desc = (argc >= 4) ? argv[3] : NULL; + if (config_file) { + config_str = file_get_contents(config_file, &config_len); + if (!config_str) + return -1; + } + ret = wimlib_open_wim(wimfile, open_flags, &w); if (ret != 0) return ret; - ret = wimlib_add_image(w, dir, name, desc, - flags_element, add_image_flags); +#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("Capturing WIM image NTFS filesystem on `%s'\n", + ntfs_device); + ret = wimlib_add_image_from_ntfs_volume(w, ntfs_device, + name, + config_str, + config_len, + add_image_flags); + goto out_write; + } + } else { + if (errno != -ENOENT) + imagex_error_with_errno("Failed to stat `%s'", dir); + } +#endif + ret = wimlib_add_image(w, dir, name, config_str, config_len, + add_image_flags); + +out_write: if (ret != 0) - goto done; + goto out; + cur_image = wimlib_get_num_images(w); + if (desc) { + ret = wimlib_set_image_descripton(w, cur_image, desc); + if (ret != 0) + goto out; + } + if (flags_element) { + ret = wimlib_set_image_flags(w, cur_image, flags_element); + if (ret != 0) + goto out; + } ret = wimlib_overwrite(w, write_flags); -done: +out: wimlib_free(w); return ret; } @@ -366,7 +457,6 @@ static int imagex_apply(int argc, const char **argv) const char *wimfile; const char *dir; const char *image_num_or_name; - const char *mkntfs_args = ""; int extract_flags = 0; for_opt(c, apply_options) { @@ -383,12 +473,6 @@ static int imagex_apply(int argc, const char **argv) case 'v': extract_flags |= WIMLIB_EXTRACT_FLAG_VERBOSE; break; - case 'N': - extract_flags |= WIMLIB_EXTRACT_FLAG_NTFS; - break; - case 'm': - mkntfs_args = optarg; - break; default: usage(APPLY); return -1; @@ -410,73 +494,14 @@ static int imagex_apply(int argc, const char **argv) dir = argv[2]; } -#ifdef WITH_NTFS_3G - char tmpdir[strlen(dir) + 50]; - tmpdir[0] = '\0'; - - /* Check to see if a block device file was specified. If so, - * create a NTFS filesystem on it. */ - struct stat stbuf; - - ret = stat(dir, &stbuf); - if (ret != 0) - imagex_error_with_errno("Failed to stat `%s'", dir); - if (S_ISBLK(stbuf.st_mode) || S_ISREG(stbuf.st_mode)) { - extract_flags |= WIMLIB_EXTRACT_FLAG_NTFS; - - const char *dev = dir; - printf("Making NTFS filesystem on `%s'\n", dev); - - char mkntfs_cmdline[sizeof("mkntfs ") + strlen(mkntfs_args) + - sizeof(" ") + strlen(dev)]; - sprintf(mkntfs_cmdline, "mkntfs %s %s", mkntfs_args, dev); - puts(mkntfs_cmdline); - ret = system(mkntfs_cmdline); - if (ret == -1) { - imagex_error_with_errno("Failed to execute the " - "`mkntfs' program"); - return -1; - } else if (ret > 0) { - imagex_error("`mkntfs' exited with failure status"); - imagex_error("Note: You can pass additional arguments " - "to `mkntfs' using the --mkntfs-args " - "argument"); - return -1; - } - sprintf(tmpdir, "/tmp/imagex-%d-ntfsmount-%s-XXXXXX", - getpid(), dev); - dir = mkdtemp(tmpdir); - if (!dir) { - imagex_error_with_errno("Failed to create " - "temporary directory " - "`%s'", tmpdir); - } - char ntfs_3g_cmdline[sizeof("ntfs-3g ") + strlen(dev) + - sizeof(" ") + strlen(dir)]; - sprintf(ntfs_3g_cmdline, "ntfs-3g %s %s", dev, dir); - puts(ntfs_3g_cmdline); - ret = system(ntfs_3g_cmdline); - if (ret == -1) { - imagex_error_with_errno("Failed to execute the " - "`ntfs-3g' program"); - ret = -1; - goto out_rm_tmpdir; - } else if (ret > 0) { - imagex_error("`ntfs-3g' exited with failure status"); - ret = -1; - goto out_rm_tmpdir; - } - } -#endif - ret = wimlib_open_wim(wimfile, open_flags, &w); if (ret != 0) - goto done; + 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) { @@ -484,46 +509,32 @@ static int imagex_apply(int argc, const char **argv) "(or all)", wimfile, num_images); usage(APPLY); ret = -1; - goto done; + goto out; } - ret = wimlib_extract_image(w, image, dir, extract_flags); -done: - wimlib_free(w); -#ifdef WITH_NTFS_3G -out_rm_tmpdir: - if (tmpdir[0] != '\0') { - /* Unmount and remove the NTFS-3g mounted directory */ - - int pid = fork(); - int status; - if (pid == -1) { - imagex_error_with_errno("Failed to fork()"); - return -1; - } - if (pid == 0) { - execlp("fusermount", "fusermount", "-u", dir, NULL); - imagex_error_with_errno("Failed to execute `fusermount'"); - return -1; - } - if (waitpid(pid, &status, 0) == -1) { - imagex_error_with_errno("Failed to wait for " - "fusermount process to " - "terminate"); - return -1; - } +#ifdef WITH_NTFS_3G + struct stat stbuf; - if (status != 0) { - imagex_error("fusermount exited with status %d", - status); - return -1; - } - if (rmdir(tmpdir) != 0) { - imagex_error_with_errno("Failed to remove temporary " - "directory `%s'", tmpdir); + 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; } @@ -534,13 +545,17 @@ static int imagex_capture(int argc, const char **argv) int c; int add_image_flags = 0; int write_flags = WIMLIB_WRITE_FLAG_SHOW_PROGRESS; - int compression_type = WIM_COMPRESSION_TYPE_NONE; + int compression_type = WIM_COMPRESSION_TYPE_XPRESS; const char *flags_element = NULL; const char *dir; const char *wimfile; const char *name; const char *desc; + const char *config_file = NULL; + const char *config_str = NULL; + size_t config_len = 0; WIMStruct *w; + int cur_image; int ret; for_opt(c, capture_options) { @@ -551,6 +566,9 @@ static int imagex_capture(int argc, const char **argv) case 'c': write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY; break; + case 'C': + config_file = optarg; + break; case 'x': compression_type = get_compression_type(optarg); if (compression_type == WIM_COMPRESSION_TYPE_INVALID) @@ -561,9 +579,7 @@ static int imagex_capture(int argc, const char **argv) break; case 'v': add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_VERBOSE; - break; - case 'N': - add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_NTFS; + write_flags |= WIMLIB_WRITE_FLAG_VERBOSE; break; case 'L': add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_DEREFERENCE; @@ -585,21 +601,61 @@ static int imagex_capture(int argc, const char **argv) name = (argc >= 3) ? argv[2] : dir; desc = (argc >= 4) ? argv[3] : NULL; + if (config_file) { + config_str = file_get_contents(config_file, &config_len); + if (!config_str) + return -1; + } + ret = wimlib_create_new_wim(compression_type, &w); if (ret != 0) return ret; - ret = wimlib_add_image(w, dir, name, desc, flags_element, - add_image_flags); +#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("Capturing WIM image NTFS filesystem on `%s'\n", + ntfs_device); + ret = wimlib_add_image_from_ntfs_volume(w, ntfs_device, + name, + config_str, + config_len, + add_image_flags); + goto out_write; + } + } else { + if (errno != -ENOENT) + imagex_error_with_errno("Failed to stat `%s'", dir); + } +#endif + ret = wimlib_add_image(w, dir, name, config_str, + config_len, add_image_flags); + +out_write: if (ret != 0) { imagex_error("Failed to add the image `%s'", dir); - goto done; + goto out; + } + cur_image = wimlib_get_num_images(w); + if (desc) { + ret = wimlib_set_image_descripton(w, cur_image, desc); + if (ret != 0) + goto out; + } + if (flags_element) { + ret = wimlib_set_image_flags(w, cur_image, flags_element); + if (ret != 0) + goto out; } ret = wimlib_write(w, wimfile, WIM_ALL_IMAGES, write_flags); if (ret != 0) imagex_error("Failed to write the WIM file `%s'", wimfile); -done: +out: wimlib_free(w); return ret; } @@ -735,7 +791,7 @@ static int imagex_export(int argc, const char **argv) int open_flags = WIMLIB_OPEN_FLAG_SHOW_PROGRESS; int export_flags = 0; int write_flags = WIMLIB_WRITE_FLAG_SHOW_PROGRESS; - int compression_type = WIM_COMPRESSION_TYPE_NONE; + int compression_type = WIM_COMPRESSION_TYPE_XPRESS; bool compression_type_specified = false; const char *src_wimfile; const char *src_image_num_or_name; @@ -790,7 +846,7 @@ static int imagex_export(int argc, const char **argv) if (stat(dest_wimfile, &stbuf) == 0) { wim_is_new = false; /* Destination file exists. */ - if (!S_ISREG(stbuf.st_mode)) { + if (!S_ISREG(stbuf.st_mode) && !S_ISLNK(stbuf.st_mode)) { imagex_error("`%s' is not a regular file", dest_wimfile); goto done;