From: Eric Biggers Date: Fri, 11 Oct 2013 15:38:45 +0000 (-0500) Subject: wimcapture: Allow specifying `--delta-from' multiple times X-Git-Tag: v1.5.1~1 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=c5bfd142ec8316173720f0f3dfcb23a744743214 wimcapture: Allow specifying `--delta-from' multiple times --- diff --git a/NEWS b/NEWS index 0481f75d..cbef7b54 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,9 @@ Version 1.5.1: with empty DACLs when the NTFS-3g apply mode is being used with NTFS-3g 2013.1.13 or earlier. + `wimlib-imagex capture' can now accept the '--delta-from' option + multiple times. + Version 1.5.0: Added support for "pipable" WIMs. Pipable WIMs allow capturing images to standard output and applying images from standard input, but they are diff --git a/doc/imagex-capture.1.in b/doc/imagex-capture.1.in index 305de55f..18d07ed6 100644 --- a/doc/imagex-capture.1.in +++ b/doc/imagex-capture.1.in @@ -404,11 +404,11 @@ appear not to have been modified since they were archived in the existing performance and does not change the resulting WIM image. .IP "" As shown, the full syntax for the argument to this option is to specify the WIM -file, a colon, and the image; for example, "--update-of mywim.wim:1". -However, the WIM file and colon may be omitted, in which case the WIM file will -default to the WIM file being appended to for append operations, or the WIM file -from which a delta is being taken (with \fB--delta-from\fR, if specified) for -capture operations. +file, a colon, and the image; for example, "--update-of mywim.wim:1". However, +the WIM file and colon may be omitted, in which case the WIM file will default +to the WIM file being appended to for append operations, or the WIM file from +which a delta is being taken (only if \fB--delta-from\fR is specified exactly +once) for capture operations. .TP \fB--delta-from\fR=\fIWIMFILE\fR For \fB@IMAGEX_PROGNAME@ capture\fR only: capture the new WIM as a "delta" from @@ -417,12 +417,16 @@ WIM are omitted if they are already present in the \fIWIMFILE\fR on which the delta is being based. The new WIM will still contain a full copy of the image metadata, but this is typically only a small fraction of a WIM's total size. .IP "" +This option can be specified multiple times, in which case the resulting delta +WIM will only contain streams not present in any of the specified base +\fIWIMFILE\fRs. +.IP "" To operate on the resulting delta WIM using other commands such as \fB@IMAGEX_PROGNAME@ apply\fR, you must specify the delta WIM as the WIM file to -operate on, but also reference the base WIM using the \fB--ref\fR option. +operate on, but also reference the base WIM(s) using the \fB--ref\fR option. Beware: to retain the proper functioning of the delta WIM, you can only add, not -delete, files and images to the base WIM following the capture of a delta from -it. +delete, files and images to the base WIM(s) following the capture of a delta +from it. .IP "" \fB--delta-from\fR may be combined with \fB--update-of\fR to increase the speed of capturing a delta WIM. @@ -456,13 +460,13 @@ modified. Note: unlike "pipable" WIMs (created with the \fB--pipable\fR option), "delta" WIMs (created with the \fB--delta-from\fR option) are compatible with Microsoft's software. You can use the /ref option of imagex.exe to reference -the base WIM, similar to above. +the base WIM(s), similar to above. .IP "" Additional note: \fB@IMAGEX_PROGNAME@\fR is generalized enough that you can in fact combine \fB--pipable\fR and \fB--delta-from\fR to create pipable delta -WIMs. In such cases, the base WIM must be captured as pipable as well as the -delta WIM, and when applying an image, the base WIM must be sent over the pipe -after the delta WIM. +WIMs. In such cases, the base WIM(s) must be captured as pipable as well as the +delta WIM, and when applying an image, the base WIM(s) must be sent over the +pipe after the delta WIM. .SH NOTES \fB@IMAGEX_PROGNAME@ append\fR does not support appending an image to a split WIM. .PP diff --git a/programs/imagex.c b/programs/imagex.c index fc932857..628205a0 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -482,7 +482,7 @@ do_resource_not_found_warning(const tchar *wimfile, } } else { imagex_error(T("If this is a delta WIM, use the --ref argument " - "to specify the WIM on which it is based.")); + "to specify the WIM(s) on which it is based.")); } } @@ -1647,8 +1647,9 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) const tchar *flags_element = NULL; WIMStruct *wim; - WIMStruct *base_wim; - const tchar *base_wimfile = NULL; + STRING_SET(base_wimfiles); + WIMStruct **base_wims; + WIMStruct *template_wim; const tchar *template_wimfile = NULL; const tchar *template_image_name_or_num = NULL; @@ -1759,12 +1760,9 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) "valid for capture!")); goto out_usage; } - if (base_wimfile) { - imagex_error(T("'--delta-from' can only be " - "specified one time!")); - goto out_err; - } - base_wimfile = optarg; + ret = string_set_append(&base_wimfiles, optarg); + if (ret) + goto out_free_base_wimfiles; write_flags |= WIMLIB_WRITE_FLAG_SKIP_EXTERNAL_WIMS; break; default: @@ -1807,9 +1805,10 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) /* If template image was specified using --update-of=IMAGE rather * than --update-of=WIMFILE:IMAGE, set the default WIMFILE. */ if (template_image_name_or_num && !template_wimfile) { - if (base_wimfile) { - /* Capturing delta WIM: default to base WIM. */ - template_wimfile = base_wimfile; + if (base_wimfiles.num_strings == 1) { + /* Capturing delta WIM based on single WIM: default to + * base WIM. */ + template_wimfile = base_wimfiles.strings[0]; } else if (cmd == CMD_APPEND) { /* Appending to WIM: default to WIM being appended to. */ @@ -1817,9 +1816,17 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) } else { /* Capturing a normal (non-delta) WIM, so the WIM file * *must* be explicitly specified. */ - imagex_error(T("For capture of non-delta WIM, " - "'--update-of' must specify " - "WIMFILE:IMAGE!")); + if (base_wimfiles.num_strings > 1) { + imagex_error(T("For capture of delta WIM " + "based on multiple existing " + "WIMs,\n" + " '--update-of' must " + "specify WIMFILE:IMAGE!")); + } else { + imagex_error(T("For capture of non-delta WIM, " + "'--update-of' must specify " + "WIMFILE:IMAGE!")); + } goto out_usage; } } @@ -1942,22 +1949,41 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) } } - /* If capturing a delta WIM, reference resources from the base WIM + /* If capturing a delta WIM, reference resources from the base WIMs * before adding the new image. */ - if (base_wimfile) { - ret = wimlib_open_wim(base_wimfile, open_flags, - &base_wim, imagex_progress_func); - if (ret) + if (base_wimfiles.num_strings) { + base_wims = calloc(base_wimfiles.num_strings, + sizeof(base_wims[0])); + if (base_wims == NULL) { + imagex_error("Out of memory!"); + ret = -1; goto out_free_wim; + } - imagex_printf(T("Capturing delta WIM based on \"%"TS"\"\n"), - base_wimfile); + for (size_t i = 0; i < base_wimfiles.num_strings; i++) { + ret = wimlib_open_wim(base_wimfiles.strings[i], + open_flags, &base_wims[i], + imagex_progress_func); + if (ret) + goto out_free_base_wims; + + } - ret = wimlib_reference_resources(wim, &base_wim, 1, 0); + ret = wimlib_reference_resources(wim, base_wims, + base_wimfiles.num_strings, 0); if (ret) - goto out_free_base_wim; + goto out_free_base_wims; + + if (base_wimfiles.num_strings == 1) { + imagex_printf(T("Capturing delta WIM based on \"%"TS"\"\n"), + base_wimfiles.strings[0]); + } else { + imagex_printf(T("Capturing delta WIM based on %u WIMs\n"), + base_wimfiles.num_strings); + } + } else { - base_wim = NULL; + base_wims = NULL; } /* If capturing or appending as an update of an existing (template) image, @@ -1965,15 +1991,16 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) if (template_image_name_or_num) { - if (template_wimfile == base_wimfile) { - template_wim = base_wim; + if (base_wimfiles.num_strings == 1 && + template_wimfile == base_wimfiles.strings[0]) { + template_wim = base_wims[0]; } else if (template_wimfile == wimfile) { template_wim = wim; } else { ret = wimlib_open_wim(template_wimfile, open_flags, &template_wim, imagex_progress_func); if (ret) - goto out_free_base_wim; + goto out_free_base_wims; } template_image = wimlib_resolve_image(template_wim, @@ -2066,11 +2093,14 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd) imagex_progress_func); } out_free_template_wim: - /* template_wim may alias base_wim or wim. */ - if (template_wim != base_wim && template_wim != wim) + /* template_wim may alias base_wims[0] or wim. */ + if ((base_wimfiles.num_strings != 1 || template_wim != base_wims[0]) && + template_wim != wim) wimlib_free(template_wim); -out_free_base_wim: - wimlib_free(base_wim); +out_free_base_wims: + for (size_t i = 0; i < base_wimfiles.num_strings; i++) + wimlib_free(base_wims[i]); + free(base_wims); out_free_wim: wimlib_free(wim); out_free_config: @@ -2084,14 +2114,15 @@ out_free_capture_sources: free(capture_sources); out_free_source_list_contents: free(source_list_contents); -out: +out_free_base_wimfiles: + string_set_destroy(&base_wimfiles); return ret; out_usage: usage(cmd, stderr); out_err: ret = -1; - goto out; + goto out_free_base_wimfiles; } /* Remove image(s) from a WIM. */