]> wimlib.net Git - wimlib/blobdiff - src/update_image.c
wincfg: Add swapfile.sys
[wimlib] / src / update_image.c
index 70038d42d0e605bbea400ef9a9406bf2779a88b2..c088c831786f18e7920c2667cb66f55b067a5169 100644 (file)
@@ -328,15 +328,13 @@ static int
 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;
@@ -356,21 +354,18 @@ journaled_link(struct update_command_journal *j,
 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)
@@ -458,21 +453,33 @@ rollback_update(struct update_command_journal *j)
        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);
 }
 
@@ -715,6 +722,7 @@ static const char wincfg[] =
 "/$ntfs.log\n"
 "/hiberfil.sys\n"
 "/pagefile.sys\n"
+"/swapfile.sys\n"
 "/System Volume Information\n"
 "/RECYCLER\n"
 "/Windows/CSC\n";
@@ -808,8 +816,8 @@ execute_add_command(struct update_command_journal *j,
 
        memset(&params, 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) {
@@ -817,11 +825,8 @@ execute_add_command(struct update_command_journal *j,
                        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);
@@ -842,10 +847,7 @@ execute_add_command(struct update_command_journal *j,
        if (progress_func)
                progress_func(WIMLIB_PROGRESS_MSG_SCAN_BEGIN, &params.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, &params);
        if (ret)
@@ -854,7 +856,7 @@ execute_add_command(struct update_command_journal *j,
        if (progress_func)
                progress_func(WIMLIB_PROGRESS_MSG_SCAN_END, &params.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);
@@ -869,7 +871,7 @@ execute_add_command(struct update_command_journal *j,
                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;
@@ -949,6 +951,19 @@ free_dentry_full_path(struct wim_dentry *dentry, void *_ignore)
        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.
@@ -1003,29 +1018,29 @@ rename_wim_path(WIMStruct *wim, const tchar *from, const tchar *to,
                        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);
        }
@@ -1059,6 +1074,9 @@ execute_rename_command(struct update_command_journal *j,
                        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:
@@ -1232,20 +1250,19 @@ check_add_command(struct wimlib_update_command *cmd,
                          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;
@@ -1354,9 +1371,7 @@ free_update_commands(struct wimlib_update_command *cmds, size_t num_cmds)
                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);
@@ -1387,18 +1402,12 @@ copy_update_commands(const struct wimlib_update_command *cmds,
                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: