]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
copy: make copy_tree_at_full()'s 'to' parameter optional
authorLennart Poettering <lennart@poettering.net>
Tue, 19 Aug 2025 19:14:19 +0000 (21:14 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 21 Oct 2025 21:09:50 +0000 (23:09 +0200)
Sometimes it's quite useful to pin a source dir via an fd, as well as a
target dir the same way, and then ask copy_tree_at_full() to copy the
contents from one to the other. Make this possible, by allowing 'to' be
NULL. (Previously, it had to be non-NULL, i.e. the function would always
create a new dir, no matter what.)

Note that we only support that for dir inodes.

src/shared/copy.c

index baed8b06961a1bf8b39659a87fcc0227fe931403..054a01e86b9a0b2684647f87c606c7a69429d870 100644 (file)
@@ -657,7 +657,10 @@ static int hardlink_context_setup(
                         return -errno;
         }
 
-        r = tempfn_random_child(to, "hardlink", &c->subdir);
+        if (to)
+                r = tempfn_random_child(to, "hardlink", &c->subdir);
+        else
+                r = tempfn_random("hardlink", /* extra= */ NULL, &c->subdir);
         if (r < 0)
                 return r;
 
@@ -1127,7 +1130,6 @@ static int fd_copy_directory(
         int r;
 
         assert(st);
-        assert(to);
 
         if (depth_left == 0)
                 return -ENAMETOOLONG;
@@ -1345,6 +1347,10 @@ static int fd_copy_tree_generic(
                                          override_gid, copy_flags, denylist, subvolumes, hardlink_context,
                                          display_path, progress_path, progress_bytes, userdata);
 
+        /* Only if we are copying a directory we are fine if the target dir is referenced by fd only */
+        if (!to)
+                return -ENOTDIR;
+
         DenyType t = PTR_TO_INT(hashmap_get(denylist, st));
         if (t == DENY_INODE) {
                 log_debug("%s is in the denylist, ignoring", from ?: "file to copy");
@@ -1382,7 +1388,6 @@ int copy_tree_at_full(
         struct stat st;
         int r;
 
-        assert(to);
         assert(!FLAGS_SET(copy_flags, COPY_LOCK_BSD));
 
         if (fstatat(fdf, strempty(from), &st, AT_SYMLINK_NOFOLLOW | (isempty(from) ? AT_EMPTY_PATH : 0)) < 0)