From eab48e05226c4eab9a66ad99c51da3babb2d678c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 14 Aug 2016 10:03:18 -0700 Subject: [PATCH] wimcapture, wimappend: semantics updates - wimcapture refuses to overwrite existing archive without confirmation - wimappend automatically creates archive if needed --- NEWS | 7 ++ doc/man1/wimlib-imagex-capture.1 | 55 ++++++++------- programs/imagex.c | 115 +++++++++++++++++++++++-------- tests/test_utils.sh | 2 +- 4 files changed, 124 insertions(+), 55 deletions(-) diff --git a/NEWS b/NEWS index 88522aac..a09484db 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,11 @@ Version 1.10.0-BETA: + 'wimcapture' now requires confirmation before overwriting an existing + archive. Scripts that relied on the old behavior will need to add the + '--force' option, or delete the existing archive first. + + 'wimappend' will now create the WIM archive if it doesn't yet exist + (thereby acting like 'wimcapture' in that scenario). + The LZX compression ratio has been slightly improved. The default mode, LZX level 50, is now almost as good as the old LZX level 100, while being nearly the same speed as before. diff --git a/doc/man1/wimlib-imagex-capture.1 b/doc/man1/wimlib-imagex-capture.1 index 3b0db0ad..87ba9140 100644 --- a/doc/man1/wimlib-imagex-capture.1 +++ b/doc/man1/wimlib-imagex-capture.1 @@ -8,18 +8,20 @@ wimlib-imagex-capture, wimlib-imagex-append \- Create or append a WIM image \fBwimlib-imagex append\fR \fISOURCE\fR \fIWIMFILE\fR [\fIIMAGE_NAME\fR \ [\fIIMAGE_DESCRIPTION\fR]] [\fIOPTION\fR...] .SH DESCRIPTION -The \fBwimlib-imagex capture\fR and \fBwimlib-imagex append\fR commands -create a Windows Imaging (WIM) image from a directory tree. The -\fBwimlib-imagex capture\fR command creates a new WIM file containing the -captured image, while the \fBwimlib-imagex append\fR command appends the -captured image to an existing WIM file. -These commands are also available as simply \fBwimcapture\fR and \fBwimappend\fR -if the appropriate hard links or batch files are installed. +The \fBwimlib-imagex capture\fR and \fBwimlib-imagex append\fR commands create a +Windows Imaging (WIM) image from a directory tree. If \fIWIMFILE\fR does not +yet exist, then the two commands are equivalent, and both create a new WIM +archive and save the image to it. Otherwise, \fBwimlib-imagex capture\fR will, +with confirmation, overwrite the existing WIM archive with a new one; whereas +\fBwimlib-imagex append\fR will append the new WIM image to the existing WIM +archive. These commands are also available as simply \fBwimcapture\fR and +\fBwimappend\fR if the appropriate hard links or batch files are installed. .PP Background information: A WIM image is an independent directory tree in a WIM -file. A WIM file may contain any number of separate images. WIM files are -single-instancing with regards to file data, so a file is stored only one time -in the entire WIM, regardless of how many images the file appears in. +archive (or "WIM file") A WIM archive may contain any number of separate +images. WIM archives are single-instancing with regards to file data, so a +file's data is stored only one time in the entire archive, regardless of how +many images the file appears in. .PP \fISOURCE\fR specifies the location of the files to create the new WIM image from. If \fISOURCE\fR is a directory, the WIM image is captured from that @@ -41,9 +43,9 @@ name already exists in \fIWIMFILE\fR, a unique suffix is added. Otherwise, \fIIMAGE_DESCRIPTION\fR is not specified, no description is given to the new image. .PP -As a special case, if \fIWIMFILE\fR is "-", the \fB--pipable\fR option is -assumed and the WIM file is written to standard output in a special pipable -format. See the documentation for \fB--pipable\fR for more details. +If \fIWIMFILE\fR is "-", the \fB--pipable\fR option is assumed and the WIM file +is written to standard output in a special pipable format. See the +documentation for \fB--pipable\fR for more details. .SH DIRECTORY CAPTURE (UNIX) This section documents how \fBwimlib-imagex\fR captures files from a directory tree on UNIX-like systems. See \fBDIRECTORY CAPTURE (WINDOWS)\fR for @@ -181,18 +183,19 @@ problems archiving such files consider using the \fBNTFS VOLUME CAPTURE (UNIX)\fR mode from Linux. .SH OPTIONS .TP 6 +\fB--force\fR +With \fBwimlib-imagex capture\fR, always overwrite the existing WIM archive; do +not prompt. +.TP \fB--boot\fR Specifies that the new image is to be made the bootable image of the WIM archive. .TP \fB--check\fR -For \fBwimlib-imagex append\fR, before performing the append operation, -check the integrity of \fIWIMFILE\fR if an integrity table is present. -Furthermore, include an integrity table in the new WIM file -(\fBwimlib-imagex capture\fR) or the modified WIM file (\fBwimlib-imagex -append\fR). If this option is not specified, no integrity table is included in -a WIM file created with \fBwimlib-imagex capture\fR, while a WIM file -updated with \fBwimlib-imagex append\fR will be written with an integrity -table if and only if one was present before. +For \fBwimlib-imagex append\fR, before performing the append operation, check +the integrity of \fIWIMFILE\fR if an integrity table is present. Furthermore, +include an integrity table in the new or modified WIM archive. If this option +is not specified, then an integrity table will be included only when appending +to an archive that already had an integrity table. .TP \fB--compress\fR=\fITYPE\fR[:\fILEVEL\fR] Specifies the compression format for the new WIM file. \fITYPE\fR may be @@ -395,8 +398,8 @@ point inside the directory tree being captured will be adjusted to be absolute relative to the root of the directory tree being captured. When disabled (\fB--norpfix\fR), absolute symbolic links will be captured exactly as is. .IP "" -The default behavior for \fBwimlib-imagex capture\fR is equivalent to -\fB--rpfix\fR. The default behavior for \fBwimlib-imagex append\fR will be +The default behavior for creating a new WIM archive is equivalent to +\fB--rpfix\fR. The default behavior for appending to an existing WIM archive \fB--rpfix\fR if reparse point fixups have previously been done on \fIWIMFILE\fR, otherwise \fB--norpfix\fR. .IP "" @@ -482,9 +485,9 @@ WIMs. The main disadvantages are that appending is (currently) less efficient (\fB--rebuild\fR is always implied), and also they aren't compatible with Microsoft's software. .IP "" -\fBwimlib-imagex capture\fR and \fBwimlib-imagex append\fR can both -write a pipable WIM directly to standard output; this is done automatically if -\fIWIMFILE\fR is specified as "-". (In that case, \fB--pipable\fR is assumed.) +\fBwimlib-imagex capture\fR can write a pipable WIM directly to standard output; +this is done automatically if \fIWIMFILE\fR is specified as "-". (In that case, +\fB--pipable\fR is assumed.) .TP \fB--not-pipable\fR Ensure the resulting WIM is in the normal, non-pipable WIM format. This is the diff --git a/programs/imagex.c b/programs/imagex.c index 1eb8489b..79bf5aa0 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -220,6 +220,7 @@ static const struct option apply_options[] = { }; static const struct option capture_or_append_options[] = { + {T("force"), no_argument, NULL, IMAGEX_FORCE_OPTION}, {T("boot"), no_argument, NULL, IMAGEX_BOOT_OPTION}, {T("check"), no_argument, NULL, IMAGEX_CHECK_OPTION}, {T("no-check"), no_argument, NULL, IMAGEX_NOCHECK_OPTION}, @@ -1825,10 +1826,58 @@ out_usage: goto out_free_refglobs; } -/* Create a WIM image from a directory tree, NTFS volume, or multiple files or - * directory trees. 'wimlib-imagex capture': create a new WIM file containing - * the desired image. 'wimlib-imagex append': add a new image to an existing - * WIM file. */ +static int +handle_wimfile_argument(const tchar *wimfile, bool force, int *cmd_p) +{ + struct stat st; + + if (stat(wimfile, &st) == 0) { + /* WIM file already exists. If invoked as 'wimcapture', make + * sure the user is certain about overwriting it. */ + if (*cmd_p == CMD_CAPTURE && !force) { + if (isatty(STDIN_FILENO)) { + /* Interactive */ + tprintf( +"You invoked 'wimcapture' to create a new WIM archive at the following path:\n" +"\t%"TS"\n" +"However, this file already exists. 'wimcapture' can overwrite this file, which\n" +"will cause this existing file to be permanently lost. If you actually want to\n" +"add an image to an existing WIM archive rather than creating a brand new WIM\n" +"archive, then you should cancel this operation and use 'wimappend' instead of\n" +"'wimcapture'. It is also possible to use the '--force' option to suppress this\n" +"prompt, making 'wimcapture' always overwrite existing files.\n" +"\n" +"Proceed with overwrite (y/n)? ", wimfile); + if (getchar() != 'y') + return -1; + } else { + /* Noninteractive */ + imagex_error("\"%"TS"\" already exists. " + "Refusing to overwrite " + "without --force option.", + wimfile); + return -1; + } + } + } else if (errno == ENOENT) { + /* WIM file does not yet exist. Act like 'wimcapture', even if + * invoked as 'wimappend'. */ + *cmd_p = CMD_CAPTURE; + } else { + imagex_error_with_errno(T("Error accessing \"%"TS"\""), + wimfile); + return -1; + } + + return 0; +} + +/* + * Create a WIM image from a directory tree, NTFS volume, or multiple files or + * directory trees. 'wimcapture' creates a new WIM archive to hold the new + * image. 'wimappend' appends to the existing WIM archive if there is one, + * otherwise (since wimlib v1.10.0) it creates a new one just like 'wimcapture'. + */ static int imagex_capture_or_append(int argc, tchar **argv, int cmd) { @@ -1847,6 +1896,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) int wim_fd; const tchar *name; STRING_LIST(image_properties); + bool force = false; WIMStruct *wim; STRING_LIST(base_wimfiles); @@ -1986,11 +2036,6 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) } break; case IMAGEX_DELTA_FROM_OPTION: - if (cmd != CMD_CAPTURE) { - imagex_error(T("'--delta-from' is only " - "valid for capture!")); - goto out_usage; - } ret = string_list_append(&base_wimfiles, optarg); if (ret) goto out; @@ -2000,16 +2045,14 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) add_flags |= WIMLIB_ADD_FLAG_WIMBOOT; break; case IMAGEX_UNSAFE_COMPACT_OPTION: - if (cmd != CMD_APPEND) { - imagex_error(T("'--unsafe-compact' is only " - "valid for append!")); - goto out_err; - } write_flags |= WIMLIB_WRITE_FLAG_UNSAFE_COMPACT; break; case IMAGEX_SNAPSHOT_OPTION: add_flags |= WIMLIB_ADD_FLAG_SNAPSHOT; break; + case IMAGEX_FORCE_OPTION: + force = true; + break; default: goto out_usage; } @@ -2044,26 +2087,42 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) if (!tstrcmp(wimfile, T("-"))) { /* Writing captured WIM to standard output. */ - #if 0 - if (!(write_flags & WIMLIB_WRITE_FLAG_PIPABLE)) { - imagex_error("Can't write a non-pipable WIM to " - "standard output! Specify --pipable\n" - " if you want to create a pipable WIM " - "(but read the docs first)."); - goto out_err; - } - #else write_flags |= WIMLIB_WRITE_FLAG_PIPABLE; - #endif if (cmd == CMD_APPEND) { - imagex_error(T("Using standard output for append does " - "not make sense.")); + imagex_error(T("To write a WIM archive to standard " + "output, you must use 'wimcapture', " + "not 'wimappend'.")); goto out_err; } wim_fd = STDOUT_FILENO; wimfile = NULL; imagex_info_file = stderr; set_fd_to_binary_mode(wim_fd); + } else { + ret = handle_wimfile_argument(wimfile, force, &cmd); + if (ret) + goto out; + } + + if ((write_flags & WIMLIB_WRITE_FLAG_SKIP_EXTERNAL_WIMS) && + cmd != CMD_CAPTURE) + { + imagex_error(T( + "'--delta-from' is only valid when creating a new WIM archive. Use\n" +" 'wimcapture' (or 'wimlib-imagex capture') if you want to force creation\n" +" of a new WIM archive.")); + goto out_err; + } + + if ((write_flags & WIMLIB_WRITE_FLAG_UNSAFE_COMPACT) && + cmd != CMD_APPEND) + { + imagex_error(T( + "'--unsafe-compact' is only valid when appending to an existing WIM\n" +" archive. If you want to append to an existing WIM archive, use\n" +" 'wimappend' (or 'wimlib-imagex append') and pass it the path to an\n" +" existing WIM archive.")); + goto out_err; } /* If template image was specified using --update-of=IMAGE rather @@ -2091,7 +2150,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) "'--update-of' must specify " "WIMFILE:IMAGE!")); } - goto out_usage; + goto out_err; } } @@ -4398,7 +4457,7 @@ T( [CMD_CAPTURE] = T( " %"TS" " SOURCE_STR " WIMFILE [IMAGE_NAME [IMAGE_DESC]]\n" -" [--compress=TYPE] [--boot] [--check] [--nocheck]\n" +" [--force] [--compress=TYPE] [--boot] [--check] [--nocheck]\n" " [--config=FILE] [--threads=NUM_THREADS]\n" " [--no-acls] [--strict-acls] [--rpfix] [--norpfix]\n" " [--update-of=[WIMFILE:]IMAGE] [--delta-from=WIMFILE]\n" diff --git a/tests/test_utils.sh b/tests/test_utils.sh index 5ebd2b13..d6f51453 100644 --- a/tests/test_utils.sh +++ b/tests/test_utils.sh @@ -48,7 +48,7 @@ wimapply() wimcapture() { - wimlib_imagex capture "$@" > /dev/null + wimlib_imagex capture "$@" --force > /dev/null } wimdelete() -- 2.43.0