+ if (config_file) {
+ /* Read and parse capture configuration file. */
+ size_t config_len;
+
+ config_str = file_get_text_contents(config_file, &config_len);
+ if (!config_str) {
+ ret = -1;
+ goto out_free_capture_sources;
+ }
+
+ config = alloca(sizeof(*config));
+ ret = parse_capture_config(&config_str, config_len, config);
+ if (ret)
+ goto out_free_config;
+ } else {
+ /* No capture configuration file specified; use default
+ * configuration for capturing Windows operating systems. */
+ config = NULL;
+ add_image_flags |= WIMLIB_ADD_FLAG_WINCONFIG;
+ }
+
+ /* Open the existing WIM, or create a new one. */
+ if (cmd == CMD_APPEND)
+ ret = wimlib_open_wim(wimfile, open_flags, &wim,
+ imagex_progress_func);
+ else
+ ret = wimlib_create_new_wim(compression_type, &wim);
+ if (ret)
+ goto out_free_config;
+
+#ifndef __WIN32__
+ /* Detect if source is regular file or block device and set NTFS volume
+ * capture mode. */
+ if (!source_list) {
+ struct stat stbuf;
+
+ if (tstat(source, &stbuf) == 0) {
+ if (S_ISBLK(stbuf.st_mode) || S_ISREG(stbuf.st_mode)) {
+ imagex_printf(T("Capturing WIM image from NTFS "
+ "filesystem on \"%"TS"\"\n"), source);
+ add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_NTFS;
+ }
+ } else {
+ if (errno != ENOENT) {
+ imagex_error_with_errno(T("Failed to stat "
+ "\"%"TS"\""), source);
+ ret = -1;
+ goto out_free_wim;
+ }
+ }
+ }
+#endif
+
+ /* If the user did not specify an image name, and the basename of the
+ * source already exists as an image name in the WIM file, append a
+ * suffix to make it unique. */
+ if (cmd == CMD_APPEND && name_defaulted) {
+ unsigned long conflict_idx;
+ tchar *name_end = tstrchr(name, T('\0'));
+ for (conflict_idx = 1;
+ wimlib_image_name_in_use(wim, name);
+ conflict_idx++)
+ {
+ tsprintf(name_end, T(" (%lu)"), conflict_idx);
+ }
+ }
+
+ /* If capturing a delta WIM, reference resources from the base WIMs
+ * before adding the new image. */
+ if (base_wimfiles.num_strings) {
+ base_wims = calloc(base_wimfiles.num_strings,
+ sizeof(base_wims[0]));
+ if (base_wims == NULL) {
+ imagex_error(T("Out of memory!"));
+ ret = -1;
+ goto out_free_wim;
+ }
+
+ 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_wims,
+ base_wimfiles.num_strings, 0);
+ if (ret)
+ 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_wims = NULL;
+ }
+
+ /* If capturing or appending as an update of an existing (template) image,
+ * open the WIM if needed and parse the image index. */
+ if (template_image_name_or_num) {
+
+
+ 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_wims;
+ }
+
+ template_image = wimlib_resolve_image(template_wim,
+ template_image_name_or_num);
+
+ if (template_image_name_or_num[0] == T('-')) {
+ tchar *tmp;
+ unsigned long n;
+ struct wimlib_wim_info info;
+
+ wimlib_get_wim_info(template_wim, &info);
+ n = tstrtoul(template_image_name_or_num + 1, &tmp, 10);
+ if (n >= 1 && n <= info.image_count &&
+ *tmp == T('\0') &&
+ tmp != template_image_name_or_num + 1)
+ {
+ template_image = info.image_count - (n - 1);
+ }
+ }
+ ret = verify_image_exists_and_is_single(template_image,
+ template_image_name_or_num,
+ template_wimfile);
+ if (ret)
+ goto out_free_template_wim;
+ } else {
+ template_wim = NULL;
+ }
+
+ ret = wimlib_add_image_multisource(wim,
+ capture_sources,
+ num_sources,
+ name,
+ config,
+ add_image_flags,
+ imagex_progress_func);
+ if (ret)
+ goto out_free_template_wim;
+
+ if (desc || flags_element || template_image_name_or_num) {
+ /* User provided <DESCRIPTION> or <FLAGS> element, or an image
+ * on which the added one is to be based has been specified with
+ * --update-of. Get the index of the image we just
+ * added, then use it to call the appropriate functions. */
+ struct wimlib_wim_info info;
+
+ wimlib_get_wim_info(wim, &info);
+
+ if (desc) {
+ ret = wimlib_set_image_descripton(wim,
+ info.image_count,
+ desc);
+ if (ret)
+ goto out_free_template_wim;
+ }
+
+ if (flags_element) {
+ ret = wimlib_set_image_flags(wim, info.image_count,
+ flags_element);
+ if (ret)
+ goto out_free_template_wim;
+ }
+
+ /* Reference template image if the user provided one. */
+ if (template_image_name_or_num) {
+ imagex_printf(T("Using image %d "
+ "from \"%"TS"\" as template\n"),
+ template_image, template_wimfile);
+ ret = wimlib_reference_template_image(wim,
+ info.image_count,
+ template_wim,
+ template_image,
+ 0, NULL);
+ if (ret)
+ goto out_free_template_wim;
+ }
+ }
+
+ /* Write the new WIM or overwrite the existing WIM with the new image
+ * appended. */
+ if (cmd == CMD_APPEND) {
+ ret = wimlib_overwrite(wim, write_flags, num_threads,
+ imagex_progress_func);
+ } else if (wimfile) {
+ ret = wimlib_write(wim, wimfile, WIMLIB_ALL_IMAGES,
+ write_flags, num_threads,
+ imagex_progress_func);
+ } else {
+ ret = wimlib_write_to_fd(wim, wim_fd, WIMLIB_ALL_IMAGES,
+ write_flags, num_threads,
+ imagex_progress_func);
+ }
+out_free_template_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_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:
+ if (config) {
+ free(config->exclusion_pats.pats);
+ free(config->exclusion_exception_pats.pats);
+ free(config_str);
+ }
+out_free_capture_sources:
+ if (capture_sources_malloced)
+ free(capture_sources);
+out_free_source_list_contents:
+ free(source_list_contents);
+out_free_base_wimfiles:
+ string_set_destroy(&base_wimfiles);