journaled_link(struct update_command_journal *j,
struct wim_dentry *subject, struct wim_dentry *parent)
{
- struct update_primitive prim = {
- .type = LINK_DENTRY,
- .link = {
- .subject = subject,
- .parent = parent,
- },
- };
+ struct update_primitive prim;
int ret;
+ prim.type = LINK_DENTRY;
+ prim.link.subject = subject;
+ prim.link.parent = parent;
+
ret = record_update_primitive(j, prim);
if (ret)
return ret;
static int
journaled_unlink(struct update_command_journal *j, struct wim_dentry *subject)
{
- int ret;
struct wim_dentry *parent;
+ struct update_primitive prim;
+ int ret;
if (dentry_is_root(subject))
parent = NULL;
else
parent = subject->parent;
- struct update_primitive prim = {
- .type = UNLINK_DENTRY,
- .link = {
- .subject = subject,
- .parent = parent,
- },
- };
+ prim.type = UNLINK_DENTRY;
+ prim.link.subject = subject;
+ prim.link.parent = parent;
ret = record_update_primitive(j, prim);
if (ret)
free_update_command_journal(j);
}
+/*
+ * Set the name of @branch for placing it at @target in the WIM image. This
+ * assumes that @target is in "canonical form", as produced by
+ * canonicalize_wim_path().
+ *
+ * Note: for the root target this produces the empty name.
+ */
static int
set_branch_name(struct wim_dentry *branch, const utf16lechar *target)
{
const utf16lechar *p;
+ /* Find end of string. (We can assume it contains at least one
+ * character, the leading slash.) */
+ wimlib_assert(target[0] == cpu_to_le16(WIM_PATH_SEPARATOR));
p = target;
- while (*p)
+ do {
p++;
+ } while (*p);
- /* No trailing slashes allowed */
- wimlib_assert(p == target || *(p - 1) != cpu_to_le16(WIM_PATH_SEPARATOR));
-
- while (p > target && *(p - 1) != cpu_to_le16(WIM_PATH_SEPARATOR))
+ while (*(p - 1) != cpu_to_le16(WIM_PATH_SEPARATOR))
p--;
+
+ /* We're assuming no trailing slashes. */
+ wimlib_assert(*p || p == &target[1]);
+
return dentry_set_name_utf16le(branch, p);
}
"/$ntfs.log\n"
"/hiberfil.sys\n"
"/pagefile.sys\n"
+"/swapfile.sys\n"
"/System Volume Information\n"
"/RECYCLER\n"
"/Windows/CSC\n";
/* Use Windows default. */
if (config_file)
return WIMLIB_ERR_INVALID_PARAM;
- ret = do_read_capture_config_file(T("wincfg"), wincfg,
- sizeof(wincfg) - 1, config);
+ ret = read_capture_config(T("wincfg"), wincfg,
+ sizeof(wincfg) - 1, config);
} else if (config_file) {
/* Use the specified configuration file. */
- ret = do_read_capture_config_file(config_file, NULL, 0, config);
+ ret = read_capture_config(config_file, NULL, 0, config);
} else {
/* ... Or don't use any configuration file at all. No files
* will be excluded from capture, all files will be compressed,
memset(¶ms, 0, sizeof(params));
+#ifdef WITH_NTFS_3G
if (add_flags & WIMLIB_ADD_FLAG_NTFS) {
- #ifdef WITH_NTFS_3G
capture_tree = build_dentry_tree_ntfs;
extra_arg = &ntfs_vol;
if (wim_get_current_image_metadata(wim)->ntfs_vol != NULL) {
ret = WIMLIB_ERR_INVALID_PARAM;
goto out;
}
- #else
- ret = WIMLIB_ERR_INVALID_PARAM;
- goto out;
- #endif
}
+#endif
ret = get_capture_config(config_file, &config,
add_flags, fs_source_path);
if (progress_func)
progress_func(WIMLIB_PROGRESS_MSG_SCAN_BEGIN, ¶ms.progress);
- config.prefix = fs_source_path;
- config.prefix_num_tchars = tstrlen(fs_source_path);
-
- if (wim_target_path[0] == T('\0'))
+ if (WIMLIB_IS_WIM_ROOT_PATH(wim_target_path))
params.add_flags |= WIMLIB_ADD_FLAG_ROOT;
ret = (*capture_tree)(&branch, fs_source_path, ¶ms);
if (ret)
if (progress_func)
progress_func(WIMLIB_PROGRESS_MSG_SCAN_END, ¶ms.progress);
- if (wim_target_path[0] == T('\0') &&
+ if (WIMLIB_IS_WIM_ROOT_PATH(wim_target_path) &&
branch && !dentry_is_directory(branch))
{
ERROR("\"%"TS"\" is not a directory!", fs_source_path);
goto out_cleanup_after_capture;
if (config_file && (add_flags & WIMLIB_ADD_FLAG_WIMBOOT) &&
- wim_target_path[0] == T('\0'))
+ WIMLIB_IS_WIM_ROOT_PATH(wim_target_path))
{
params.add_flags = 0;
params.progress_func = NULL;
return 0;
}
+/* Is @d1 a (possibly nonproper) ancestor of @d2? */
+static bool
+is_ancestor(struct wim_dentry *d1, struct wim_dentry *d2)
+{
+ for (;;) {
+ if (d2 == d1)
+ return true;
+ if (dentry_is_root(d2))
+ return false;
+ d2 = d2->parent;
+ }
+}
+
/* Rename a file or directory in the WIM.
*
* This returns a -errno value.
return -ENOTDIR;
}
+ /* @src can't be an ancestor of @dst. Otherwise we're unlinking @src
+ * from the tree and creating a loop... */
+ if (is_ancestor(src, parent_of_dst))
+ return -EBUSY;
+
if (j) {
+ if (dst)
+ if (journaled_unlink(j, dst))
+ return -ENOMEM;
+ if (journaled_unlink(j, src))
+ return -ENOMEM;
if (journaled_change_name(j, src, path_basename(to)))
return -ENOMEM;
+ if (journaled_link(j, src, parent_of_dst))
+ return -ENOMEM;
} else {
ret = dentry_set_name(src, path_basename(to));
if (ret)
return -ENOMEM;
- }
- if (dst) {
- if (j) {
- if (journaled_unlink(j, dst))
- return -ENOMEM;
- } else {
+ if (dst) {
unlink_dentry(dst);
free_dentry_tree(dst, wim->lookup_table);
}
- }
- if (j) {
- if (journaled_unlink(j, src))
- return -ENOMEM;
- if (journaled_link(j, src, parent_of_dst))
- return -ENOMEM;
- } else {
unlink_dentry(src);
dentry_add_child(parent_of_dst, src);
}
ret = WIMLIB_ERR_NOTDIR;
break;
case ENOTEMPTY:
+ case EBUSY:
+ /* XXX: EBUSY is returned when the rename would create a
+ * loop. It maybe should have its own error code. */
ret = WIMLIB_ERR_NOTEMPTY;
break;
case EISDIR:
WIMLIB_ADD_FLAG_NO_REPLACE))
return WIMLIB_ERR_INVALID_PARAM;
- /* Are we adding the entire image or not? An empty wim_target_path
- * indicates that the tree we're adding is to be placed in the root of
- * the image. We consider this to be capturing the entire image,
- * although it could potentially be an overlay on an existing root as
- * well. */
- bool is_entire_image = cmd->add.wim_target_path[0] == T('\0');
+ bool is_entire_image = WIMLIB_IS_WIM_ROOT_PATH(cmd->add.wim_target_path);
-#ifdef __WIN32__
- /* Check for flags not supported on Windows */
+#ifndef WITH_NTFS_3G
if (add_flags & WIMLIB_ADD_FLAG_NTFS) {
- ERROR("wimlib was compiled without support for NTFS-3g, so");
- ERROR("we cannot capture a WIM image directly from a NTFS volume");
+ ERROR("wimlib was compiled without support for NTFS-3g, so\n"
+ " we cannot capture a WIM image directly "
+ "from an NTFS volume");
return WIMLIB_ERR_UNSUPPORTED;
}
+#endif
+
+#ifdef __WIN32__
+ /* Check for flags not supported on Windows */
if (add_flags & WIMLIB_ADD_FLAG_UNIX_DATA) {
ERROR("Capturing UNIX-specific data is not supported on Windows");
return WIMLIB_ERR_UNSUPPORTED;
for (size_t i = 0; i < num_cmds; i++) {
switch (cmds[i].op) {
case WIMLIB_UPDATE_OP_ADD:
- FREE(cmds[i].add.fs_source_path);
FREE(cmds[i].add.wim_target_path);
- FREE(cmds[i].add.config_file);
break;
case WIMLIB_UPDATE_OP_DELETE:
FREE(cmds[i].delete_.wim_path);
cmds_copy[i].op = cmds[i].op;
switch (cmds[i].op) {
case WIMLIB_UPDATE_OP_ADD:
- cmds_copy[i].add.fs_source_path =
- canonicalize_fs_path(cmds[i].add.fs_source_path);
+ cmds_copy[i].add.fs_source_path = cmds[i].add.fs_source_path;
cmds_copy[i].add.wim_target_path =
canonicalize_wim_path(cmds[i].add.wim_target_path);
- if (!cmds_copy[i].add.fs_source_path ||
- !cmds_copy[i].add.wim_target_path)
+ if (!cmds_copy[i].add.wim_target_path)
goto oom;
- if (cmds[i].add.config_file) {
- cmds_copy[i].add.config_file = TSTRDUP(cmds[i].add.config_file);
- if (!cmds_copy[i].add.config_file)
- goto oom;
- }
+ cmds_copy[i].add.config_file = cmds[i].add.config_file;
cmds_copy[i].add.add_flags = cmds[i].add.add_flags;
break;
case WIMLIB_UPDATE_OP_DELETE: