From: Daan De Meyer Date: Thu, 1 Jun 2023 11:42:39 +0000 (+0200) Subject: copy: Merge copy_directory() and copy_directory_fd() into copy_directory_at() X-Git-Tag: v254-rc1~269^2~13 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f9f70e062da2557a1127dbd584c7dfae7defe149;p=thirdparty%2Fsystemd.git copy: Merge copy_directory() and copy_directory_fd() into copy_directory_at() Let's merge these two into a single function that can handle both variants and more. --- diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c index 5c742497d5c..25bdd68cd20 100644 --- a/src/dissect/dissect.c +++ b/src/dissect/dissect.c @@ -1286,7 +1286,7 @@ static int action_list_or_mtree_or_copy(DissectedImage *m, LoopDevice *d) { } /* Try to copy as directory? */ - r = copy_directory_fd(source_fd, arg_target, COPY_REFLINK|COPY_MERGE_EMPTY|COPY_SIGINT|COPY_HARDLINKS); + r = copy_directory_at(source_fd, NULL, AT_FDCWD, arg_target, COPY_REFLINK|COPY_MERGE_EMPTY|COPY_SIGINT|COPY_HARDLINKS); if (r >= 0) return 0; if (r != -ENOTDIR) diff --git a/src/import/import-fs.c b/src/import/import-fs.c index d81dd13ffde..221febea19c 100644 --- a/src/import/import-fs.c +++ b/src/import/import-fs.c @@ -206,9 +206,9 @@ static int import_fs(int argc, char *argv[], void *userdata) { progress_bytes, &progress); else - r = copy_directory_fd_full( - fd, - dest, + r = copy_directory_at_full( + fd, NULL, + AT_FDCWD, dest, COPY_REFLINK| COPY_SAME_MOUNT| COPY_HARDLINKS| diff --git a/src/shared/btrfs-util.c b/src/shared/btrfs-util.c index 16295a58237..03f9c0d0e69 100644 --- a/src/shared/btrfs-util.c +++ b/src/shared/btrfs-util.c @@ -1561,8 +1561,9 @@ int btrfs_subvol_snapshot_fd_full( } else if (r < 0) return r; - r = copy_directory_fd_full( - old_fd, new_path, + r = copy_directory_at_full( + old_fd, NULL, + AT_FDCWD, new_path, COPY_MERGE_EMPTY| COPY_REFLINK| COPY_SAME_MOUNT| diff --git a/src/shared/copy.c b/src/shared/copy.c index 14b9b61d8a2..3216607ef8f 100644 --- a/src/shared/copy.c +++ b/src/shared/copy.c @@ -1208,61 +1208,22 @@ int copy_tree_at_full( return 0; } -static int sync_dir_by_flags(const char *path, CopyFlags copy_flags) { +static int sync_dir_by_flags(int dir_fd, const char *path, CopyFlags copy_flags) { + assert(dir_fd >= 0 || dir_fd == AT_FDCWD); + assert(path); if (copy_flags & COPY_SYNCFS) - return syncfs_path(AT_FDCWD, path); + return syncfs_path(dir_fd, path); if (copy_flags & COPY_FSYNC_FULL) - return fsync_parent_at(AT_FDCWD, path); + return fsync_parent_at(dir_fd, path); return 0; } -int copy_directory_fd_full( - int dirfd, - const char *to, - CopyFlags copy_flags, - copy_progress_path_t progress_path, - copy_progress_bytes_t progress_bytes, - void *userdata) { - - struct stat st; - int r; - - assert(dirfd >= 0); - assert(to); - - if (fstat(dirfd, &st) < 0) - return -errno; - - r = stat_verify_directory(&st); - if (r < 0) - return r; - - r = fd_copy_directory( - dirfd, NULL, - &st, - AT_FDCWD, to, - st.st_dev, - COPY_DEPTH_MAX, - UID_INVALID, GID_INVALID, - copy_flags, - NULL, NULL, NULL, - progress_path, - progress_bytes, - userdata); - if (r < 0) - return r; - - r = sync_dir_by_flags(to, copy_flags); - if (r < 0) - return r; - - return 0; -} - -int copy_directory_full( +int copy_directory_at_full( + int dir_fdf, const char *from, + int dir_fdt, const char *to, CopyFlags copy_flags, copy_progress_path_t progress_path, @@ -1272,10 +1233,11 @@ int copy_directory_full( struct stat st; int r; - assert(from); + assert(dir_fdf >= 0 || dir_fdf == AT_FDCWD); + assert(dir_fdt >= 0 || dir_fdt == AT_FDCWD); assert(to); - if (lstat(from, &st) < 0) + if (fstatat(dir_fdf, strempty(from), &st, AT_SYMLINK_NOFOLLOW|(isempty(from) ? AT_EMPTY_PATH : 0)) < 0) return -errno; r = stat_verify_directory(&st); @@ -1283,9 +1245,9 @@ int copy_directory_full( return r; r = fd_copy_directory( - AT_FDCWD, from, + dir_fdf, from, &st, - AT_FDCWD, to, + dir_fdt, to, st.st_dev, COPY_DEPTH_MAX, UID_INVALID, GID_INVALID, @@ -1297,7 +1259,7 @@ int copy_directory_full( if (r < 0) return r; - r = sync_dir_by_flags(to, copy_flags); + r = sync_dir_by_flags(dir_fdt, to, copy_flags); if (r < 0) return r; diff --git a/src/shared/copy.h b/src/shared/copy.h index c4482eba7e1..9a0df9f4f53 100644 --- a/src/shared/copy.h +++ b/src/shared/copy.h @@ -82,14 +82,9 @@ static inline int copy_tree(const char *from, const char *to, uid_t override_uid return copy_tree_at_full(AT_FDCWD, from, AT_FDCWD, to, override_uid, override_gid, copy_flags, denylist, NULL, NULL, NULL); } -int copy_directory_fd_full(int dirfd, const char *to, CopyFlags copy_flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata); -static inline int copy_directory_fd(int dirfd, const char *to, CopyFlags copy_flags) { - return copy_directory_fd_full(dirfd, to, copy_flags, NULL, NULL, NULL); -} - -int copy_directory_full(const char *from, const char *to, CopyFlags copy_flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata); -static inline int copy_directory(const char *from, const char *to, CopyFlags copy_flags) { - return copy_directory_full(from, to, copy_flags, NULL, NULL, NULL); +int copy_directory_at_full(int dir_fdf, const char *from, int dir_fdt, const char *to, CopyFlags copy_flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata); +static inline int copy_directory_at(int dir_fdf, const char *from, int dir_fdt, const char *to, CopyFlags copy_flags) { + return copy_directory_at_full(dir_fdf, from, dir_fdt, to, copy_flags, NULL, NULL, NULL); } int copy_bytes_full(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags, void **ret_remains, size_t *ret_remains_size, copy_progress_bytes_t progress, void *userdata); diff --git a/src/test/test-execute.c b/src/test/test-execute.c index a07c837e3f5..a63afa873b9 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -1299,7 +1299,7 @@ static int prepare_ns(const char *process_name) { /* Copy unit files to make them accessible even when unprivileged. */ assert_se(get_testdata_dir("test-execute/", &unit_dir) >= 0); - assert_se(copy_directory(unit_dir, PRIVATE_UNIT_DIR, COPY_MERGE_EMPTY) >= 0); + assert_se(copy_directory_at(AT_FDCWD, unit_dir, AT_FDCWD, PRIVATE_UNIT_DIR, COPY_MERGE_EMPTY) >= 0); /* Prepare credstore like tmpfiles.d/credstore.conf for LoadCredential= tests. */ FOREACH_STRING(p, "/run/credstore", "/run/credstore.encrypted") {