From: Lennart Poettering Date: Tue, 19 Aug 2025 19:14:19 +0000 (+0200) Subject: copy: make copy_tree_at_full()'s 'to' parameter optional X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=69332065e204ad8516d19b8197e78c715873d54d;p=thirdparty%2Fsystemd.git copy: make copy_tree_at_full()'s 'to' parameter optional 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. --- diff --git a/src/shared/copy.c b/src/shared/copy.c index baed8b06961..054a01e86b9 100644 --- a/src/shared/copy.c +++ b/src/shared/copy.c @@ -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)