X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=programs%2Fimagex.c;h=c1d817b970490255eb9dfc303f80737b95fe5c50;hp=1a3cbbd5a05176975e22ea78764d7b8e43bdbeb6;hb=145a20679ef30eafd0defbed295127f27aca27e9;hpb=f69ae15310f292995d2f0838c91ee61b721c356c diff --git a/programs/imagex.c b/programs/imagex.c index 1a3cbbd5..c1d817b9 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -50,12 +50,16 @@ # include "imagex-win32.h" # define tbasename win32_wbasename # define tglob win32_wglob +# define OS_PREFERRED_PATH_SEPARATOR L'\\' +# define OS_PREFERRED_PATH_SEPARATOR_STRING L"\\" #else /* __WIN32__ */ # include # include # include # define tbasename basename # define tglob glob +# define OS_PREFERRED_PATH_SEPARATOR '/' +# define OS_PREFERRED_PATH_SEPARATOR_STRING "/" #endif /* !__WIN32 */ @@ -121,7 +125,7 @@ IMAGEX_PROGNAME" delete WIMFILE (IMAGE_NUM | IMAGE_NAME | all) [--check] [--soft ), [DIR] = T( -IMAGEX_PROGNAME" dir WIMFILE (IMAGE_NUM | IMAGE_NAME | all)\n" +IMAGEX_PROGNAME" dir WIMFILE (IMAGE_NUM | IMAGE_NAME | all) [--path=PATH]\n" ), [EXPORT] = T( @@ -217,6 +221,7 @@ enum { IMAGEX_METADATA_OPTION, IMAGEX_NORPFIX_OPTION, IMAGEX_NO_ACLS_OPTION, + IMAGEX_PATH_OPTION, IMAGEX_REBUILD_OPTION, IMAGEX_RECOMPRESS_OPTION, IMAGEX_RECURSIVE_OPTION, @@ -275,6 +280,11 @@ static const struct option delete_options[] = { {NULL, 0, NULL, 0}, }; +static const struct option dir_options[] = { + {T("path"), required_argument, NULL, IMAGEX_PATH_OPTION}, + {NULL, 0, NULL, 0}, +}; + static const struct option export_options[] = { {T("boot"), no_argument, NULL, IMAGEX_BOOT_OPTION}, {T("check"), no_argument, NULL, IMAGEX_CHECK_OPTION}, @@ -976,18 +986,6 @@ stdin_get_text_contents(size_t *num_tchars_ret) return translate_text_to_tstr(contents, num_bytes, num_tchars_ret); } -/* Return 0 if a path names a file to which the current user has write access; - * -1 otherwise (and print an error message). */ -static int -file_writable(const tchar *path) -{ - int ret; - ret = taccess(path, W_OK); - if (ret != 0) - imagex_error_with_errno(T("Can't modify \"%"TS"\""), path); - return ret; -} - #define TO_PERCENT(numerator, denominator) \ (((denominator) == 0) ? 0 : ((numerator) * 100 / (denominator))) @@ -1065,7 +1063,8 @@ imagex_progress_func(enum wimlib_progress_msg msg, case WIMLIB_PROGRESS_MSG_SCAN_BEGIN: tprintf(T("Scanning \"%"TS"\""), info->scan.source); if (*info->scan.wim_target_path) { - tprintf(T(" (loading as WIM path: \"/%"TS"\")...\n"), + tprintf(T(" (loading as WIM path: " + "\""WIMLIB_WIM_PATH_SEPARATOR_STRING"%"TS"\")...\n"), info->scan.wim_target_path); } else { tprintf(T(" (loading as root of WIM image)...\n")); @@ -1119,7 +1118,8 @@ imagex_progress_func(enum wimlib_progress_msg msg, info->extract.target); break; case WIMLIB_PROGRESS_MSG_EXTRACT_TREE_BEGIN: - tprintf(T("Extracting \"%"TS"\" from image %d (\"%"TS"\") " + tprintf(T("Extracting " + "\""WIMLIB_WIM_PATH_SEPARATOR_STRING"%"TS"\" from image %d (\"%"TS"\") " "in \"%"TS"\" to \"%"TS"\"\n"), info->extract.extract_root_wim_source_path, info->extract.image, @@ -1192,6 +1192,25 @@ imagex_progress_func(enum wimlib_progress_msg msg, info->split.cur_part_number); } break; + case WIMLIB_PROGRESS_MSG_UPDATE_END_COMMAND: + switch (info->update.command->op) { + case WIMLIB_UPDATE_OP_DELETE: + tprintf(T("Deleted WIM path " + "\""WIMLIB_WIM_PATH_SEPARATOR_STRING "%"TS"\"\n"), + info->update.command->delete.wim_path); + break; + case WIMLIB_UPDATE_OP_RENAME: + tprintf(T("Renamed WIM path " + "\""WIMLIB_WIM_PATH_SEPARATOR_STRING "%"TS"\" => " + "\""WIMLIB_WIM_PATH_SEPARATOR_STRING "%"TS"\"\n"), + info->update.command->rename.wim_source_path, + info->update.command->rename.wim_target_path); + break; + case WIMLIB_UPDATE_OP_ADD: + default: + break; + } + break; default: break; } @@ -1631,7 +1650,7 @@ static int imagex_capture_or_append(int argc, tchar **argv) { int c; - int open_flags = 0; + int open_flags = WIMLIB_OPEN_FLAG_WRITE_ACCESS; int add_image_flags = WIMLIB_ADD_IMAGE_FLAG_EXCLUDE_VERBOSE; int write_flags = 0; int compression_type = WIMLIB_COMPRESSION_TYPE_XPRESS; @@ -1864,8 +1883,6 @@ imagex_capture_or_append(int argc, tchar **argv) ret = wimlib_write(w, wimfile, WIMLIB_ALL_IMAGES, write_flags, num_threads, imagex_progress_func); } - if (ret == WIMLIB_ERR_REOPEN) - ret = 0; if (ret != 0) imagex_error(T("Failed to write the WIM file \"%"TS"\""), wimfile); @@ -1894,7 +1911,7 @@ static int imagex_delete(int argc, tchar **argv) { int c; - int open_flags = 0; + int open_flags = WIMLIB_OPEN_FLAG_WRITE_ACCESS; int write_flags = 0; const tchar *wimfile; const tchar *image_num_or_name; @@ -1930,10 +1947,6 @@ imagex_delete(int argc, tchar **argv) wimfile = argv[0]; image_num_or_name = argv[1]; - ret = file_writable(wimfile); - if (ret != 0) - return ret; - ret = wimlib_open_wim(wimfile, open_flags, &w, imagex_progress_func); if (ret != 0) @@ -1952,8 +1965,6 @@ imagex_delete(int argc, tchar **argv) } ret = wimlib_overwrite(w, write_flags, 0, imagex_progress_func); - if (ret == WIMLIB_ERR_REOPEN) - ret = 0; if (ret != 0) { imagex_error(T("Failed to write the file \"%"TS"\" with image " "deleted"), wimfile); @@ -1963,56 +1974,80 @@ out: return ret; } +static int +print_full_path(const struct wimlib_wim_dentry *wdentry, void *_ignore) +{ + int ret = tprintf(T("%"TS"\n"), wdentry->full_path); + return (ret >= 0) ? 0 : -1; +} + /* Print the files contained in an image(s) in a WIM file. */ static int imagex_dir(int argc, tchar **argv) { const tchar *wimfile; - WIMStruct *w; + WIMStruct *wim = NULL; int image; int ret; - int num_images; + const tchar *path = T(""); + int c; - if (argc < 2) { + for_opt(c, dir_options) { + switch (c) { + case IMAGEX_PATH_OPTION: + path = optarg; + break; + default: + goto out_usage; + } + } + argc -= optind; + argv += optind; + + if (argc < 1) { imagex_error(T("Must specify a WIM file")); - usage(DIR); - return -1; + goto out_usage; } - if (argc > 3) { + if (argc > 2) { imagex_error(T("Too many arguments")); - usage(DIR); - return -1; + goto out_usage; } - wimfile = argv[1]; - ret = wimlib_open_wim(wimfile, WIMLIB_OPEN_FLAG_SPLIT_OK, &w, + wimfile = argv[0]; + ret = wimlib_open_wim(wimfile, WIMLIB_OPEN_FLAG_SPLIT_OK, &wim, imagex_progress_func); - if (ret != 0) - return ret; + if (ret) + goto out; - if (argc == 3) { - image = wimlib_resolve_image(w, argv[2]); - ret = verify_image_exists(image, argv[2], wimfile); - if (ret != 0) - goto out; + if (argc == 2) { + image = wimlib_resolve_image(wim, argv[1]); + ret = verify_image_exists(image, argv[1], wimfile); + if (ret) + goto out_wimlib_free; } else { /* Image was not specified. If the WIM only contains one image, * choose that one; otherwise, print an error. */ - num_images = wimlib_get_num_images(w); + int num_images = wimlib_get_num_images(wim); if (num_images != 1) { imagex_error(T("\"%"TS"\" contains %d images; Please " "select one."), wimfile, num_images); - usage(DIR); - ret = -1; - goto out; + wimlib_free(wim); + goto out_usage; } image = 1; } - ret = wimlib_print_files(w, image); + ret = wimlib_iterate_dir_tree(wim, image, path, + WIMLIB_ITERATE_DIR_TREE_FLAG_RECURSIVE, + print_full_path, NULL); +out_wimlib_free: + wimlib_free(wim); out: - wimlib_free(w); return ret; +out_usage: + usage(DIR); + ret = -1; + goto out; } /* Exports one, or all, images from a WIM file to a new WIM file or an existing @@ -2105,12 +2140,8 @@ imagex_export(int argc, tchar **argv) ret = -1; goto out; } - ret = wimlib_open_wim(dest_wimfile, open_flags, &dest_w, - imagex_progress_func); - if (ret != 0) - goto out; - - ret = file_writable(dest_wimfile); + ret = wimlib_open_wim(dest_wimfile, open_flags | WIMLIB_OPEN_FLAG_WRITE_ACCESS, + &dest_w, imagex_progress_func); if (ret != 0) goto out; @@ -2169,8 +2200,6 @@ imagex_export(int argc, tchar **argv) ret = wimlib_overwrite(dest_w, write_flags, num_threads, imagex_progress_func); out: - if (ret == WIMLIB_ERR_REOPEN) - ret = 0; wimlib_free(src_w); wimlib_free(dest_w); if (additional_swms) { @@ -2233,8 +2262,8 @@ prepare_extract_commands(tchar **paths, unsigned num_paths, free_extract_commands(cmds, num_cmds, dest_dir); return NULL; } - tsprintf(cmds[i].fs_dest_path, T("%"TS"/%"TS), dest_dir, - tbasename(paths[i])); + tsprintf(cmds[i].fs_dest_path, T("%"TS""OS_PREFERRED_PATH_SEPARATOR_STRING"%"TS), + dest_dir, tbasename(paths[i])); } } *num_cmds_ret = num_cmds; @@ -2566,11 +2595,7 @@ imagex_info(int argc, tchar **argv) } else { /* Modification operations */ - if (total_parts != 1) { - imagex_error(T("Modifying a split WIM is not supported.")); - ret = -1; - goto out; - } + if (image == WIMLIB_ALL_IMAGES) image = 1; @@ -2589,7 +2614,9 @@ imagex_info(int argc, tchar **argv) } else { tprintf(T("Marking image %d as bootable.\n"), image); - wimlib_set_boot_idx(w, image); + ret = wimlib_set_boot_idx(w, image); + if (ret) + goto out; } } if (new_name) { @@ -2628,21 +2655,12 @@ imagex_info(int argc, tchar **argv) if (boot || new_name || new_desc || (check && !wimlib_has_integrity_table(w))) { - int write_flags; - - ret = file_writable(wimfile); - if (ret != 0) - goto out; + int write_flags = 0; if (check) - write_flags = WIMLIB_WRITE_FLAG_CHECK_INTEGRITY; - else - write_flags = 0; - + write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY; ret = wimlib_overwrite(w, write_flags, 1, imagex_progress_func); - if (ret == WIMLIB_ERR_REOPEN) - ret = 0; } else { tprintf(T("The file \"%"TS"\" was not modified because nothing " "needed to be done.\n"), wimfile); @@ -2711,8 +2729,10 @@ imagex_mount_rw_or_ro(int argc, tchar **argv) unsigned num_additional_swms = 0; const tchar *staging_dir = NULL; - if (!tstrcmp(argv[0], T("mountrw"))) + if (!tstrcmp(argv[0], T("mountrw"))) { mount_flags |= WIMLIB_MOUNT_FLAG_READWRITE; + open_flags |= WIMLIB_OPEN_FLAG_WRITE_ACCESS; + } for_opt(c, mount_options) { switch (c) { @@ -2791,12 +2811,6 @@ imagex_mount_rw_or_ro(int argc, tchar **argv) goto out; } - if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) { - ret = file_writable(wimfile); - if (ret != 0) - goto out; - } - ret = wimlib_mount_image(w, image, dir, mount_flags, additional_swms, num_additional_swms, staging_dir); if (ret != 0) { @@ -2824,7 +2838,7 @@ static int imagex_optimize(int argc, tchar **argv) { int c; - int open_flags = 0; + int open_flags = WIMLIB_OPEN_FLAG_WRITE_ACCESS; int write_flags = WIMLIB_WRITE_FLAG_REBUILD; int ret; WIMStruct *w; @@ -2862,10 +2876,6 @@ imagex_optimize(int argc, tchar **argv) wimfile = argv[0]; - ret = file_writable(wimfile); - if (ret) - return ret; - ret = wimlib_open_wim(wimfile, open_flags, &w, imagex_progress_func); if (ret) @@ -2999,9 +3009,9 @@ imagex_update(int argc, tchar **argv) int image; WIMStruct *wim; int ret; - int open_flags = 0; + int open_flags = WIMLIB_OPEN_FLAG_WRITE_ACCESS; int write_flags = 0; - int update_flags = 0; + int update_flags = WIMLIB_UPDATE_FLAG_SEND_PROGRESS; int default_add_flags = WIMLIB_ADD_IMAGE_FLAG_EXCLUDE_VERBOSE; int default_delete_flags = 0; unsigned num_threads = 0; @@ -3090,10 +3100,6 @@ imagex_update(int argc, tchar **argv) goto out_usage; wimfile = argv[0]; - ret = file_writable(wimfile); - if (ret) - goto out; - ret = wimlib_open_wim(wimfile, open_flags, &wim, imagex_progress_func); if (ret) goto out; @@ -3163,11 +3169,13 @@ imagex_update(int argc, tchar **argv) } /* 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; @@ -3178,7 +3186,8 @@ imagex_update(int argc, tchar **argv) } #ifdef __WIN32__ - win32_acquire_capture_privileges(); + if (have_add_command) + win32_acquire_capture_privileges(); #endif /* Execute the update commands */ @@ -3192,7 +3201,8 @@ imagex_update(int argc, tchar **argv) imagex_progress_func); out_release_privs: #ifdef __WIN32__ - win32_release_capture_privileges(); + if (have_add_command) + win32_release_capture_privileges(); #endif free(cmds); out_free_cmd_file_contents: