+ ret = dentry_set_name_utf16le(filler,
+ cur_component_name,
+ cur_component_nbytes);
+ if (ret) {
+ free_dentry(filler);
+ return ret;
+ }
+ ret = journaled_link(j, filler, parent);
+ if (ret) {
+ free_dentry(filler);
+ return ret;
+ }
+ existing = filler;
+ }
+
+ /* Advance to next component */
+
+ cur_component_name = next_component_name;
+ end = cur_component_name + 1;
+ while (*end && *end != cpu_to_le16(WIM_PATH_SEPARATOR))
+ end++;
+
+ next_component_name = end;
+ if (*end) {
+ /* There will still be more components after this. */
+ do {
+ } while (*++next_component_name == cpu_to_le16(WIM_PATH_SEPARATOR));
+ wimlib_assert(*next_component_name); /* No trailing slashes */
+ } else {
+ /* This will be the last component */
+ next_component_name = end;
+ }
+ parent = existing;
+ cur_component_nbytes = (end - cur_component_name) * sizeof(utf16lechar);
+ existing = get_dentry_child_with_utf16le_name(
+ parent,
+ cur_component_name,
+ cur_component_nbytes,
+ WIMLIB_CASE_PLATFORM_DEFAULT);
+ }
+
+ /* Last component */
+ if (existing) {
+ return handle_conflict(branch, existing, j, add_flags,
+ progfunc, progctx);
+ } else {
+ return journaled_link(j, branch, parent);
+ }
+}
+
+/*
+ * Place the directory entry tree @branch at the path @target_tstr in the WIM
+ * image.
+ *
+ * @target_tstr cannot contain trailing slashes, and all path separators must be
+ * WIM_PATH_SEPARATOR.
+ *
+ * On success, @branch is committed to the journal @j.
+ * Otherwise @branch is freed.
+ *
+ * The relevant @add_flags are WIMLIB_ADD_FLAG_NO_REPLACE and
+ * WIMLIB_ADD_FLAG_VERBOSE.
+ */
+static int
+attach_branch(struct wim_dentry *branch, const tchar *target_tstr,
+ struct update_command_journal *j, int add_flags,
+ wimlib_progress_func_t progfunc, void *progctx)
+{
+ int ret;
+ const utf16lechar *target;
+
+ ret = 0;
+ if (unlikely(!branch))
+ goto out;
+
+ ret = tstr_get_utf16le(target_tstr, &target);
+ if (ret)
+ goto out_free_branch;
+
+ STATIC_ASSERT(WIM_PATH_SEPARATOR == OS_PREFERRED_PATH_SEPARATOR);
+ ret = dentry_set_name(branch, path_basename(target_tstr));
+ if (ret)
+ goto out_free_target;
+
+ ret = do_attach_branch(branch, target, j, add_flags, progfunc, progctx);
+ if (ret)
+ goto out_free_target;
+ /* branch was successfully committed to the journal */
+ branch = NULL;
+out_free_target:
+ tstr_put_utf16le(target);
+out_free_branch:
+ free_dentry_tree(branch, j->blob_table);
+out:
+ return ret;
+}
+
+static const char wincfg[] =
+"[ExclusionList]\n"
+"/$ntfs.log\n"
+"/hiberfil.sys\n"
+"/pagefile.sys\n"
+"/swapfile.sys\n"
+"/System Volume Information\n"
+"/RECYCLER\n"
+"/Windows/CSC\n";
+
+static const tchar *wimboot_cfgfile =
+ WIMLIB_WIM_PATH_SEPARATOR_STRING T("Windows")
+ WIMLIB_WIM_PATH_SEPARATOR_STRING T("System32")
+ WIMLIB_WIM_PATH_SEPARATOR_STRING T("WimBootCompress.ini");
+
+static int
+get_capture_config(const tchar *config_file, struct capture_config *config,
+ int add_flags, const tchar *fs_source_path)
+{
+ int ret;
+ tchar *tmp_config_file = NULL;
+
+ memset(config, 0, sizeof(*config));
+
+ /* For WIMBoot capture, check for default capture configuration file
+ * unless one was explicitly specified. */
+ if (!config_file && (add_flags & WIMLIB_ADD_FLAG_WIMBOOT)) {
+
+ /* XXX: Handle loading file correctly when in NTFS volume. */
+
+ size_t len = tstrlen(fs_source_path) +
+ tstrlen(wimboot_cfgfile);
+ tmp_config_file = MALLOC((len + 1) * sizeof(tchar));
+ struct stat st;
+
+ tsprintf(tmp_config_file, T("%"TS"%"TS),
+ fs_source_path, wimboot_cfgfile);
+ if (!tstat(tmp_config_file, &st)) {
+ config_file = tmp_config_file;
+ add_flags &= ~WIMLIB_ADD_FLAG_WINCONFIG;
+ } else {
+ WARNING("\"%"TS"\" does not exist.\n"
+ " Using default capture configuration!",
+ tmp_config_file);