From: Daan De Meyer Date: Thu, 22 Dec 2022 13:27:26 +0000 (+0100) Subject: copy: Add copy_file_at() X-Git-Tag: v254-rc1~1231^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d9daf0d14443a995077744fb9b407094f0ca9302;p=thirdparty%2Fsystemd.git copy: Add copy_file_at() --- diff --git a/src/shared/copy.c b/src/shared/copy.c index d15875739ac..a1df3048bae 100644 --- a/src/shared/copy.c +++ b/src/shared/copy.c @@ -1329,8 +1329,10 @@ int copy_file_fd_full( return 0; } -int copy_file_full( +int copy_file_at_full( + int dir_fdf, const char *from, + int dir_fdt, const char *to, int flags, mode_t mode, @@ -1344,10 +1346,12 @@ int copy_file_full( struct stat st; int r; + assert(dir_fdf >= 0 || dir_fdf == AT_FDCWD); + assert(dir_fdt >= 0 || dir_fdt == AT_FDCWD); assert(from); assert(to); - fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY); + fdf = openat(dir_fdf, from, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fdf < 0) return -errno; @@ -1360,11 +1364,11 @@ int copy_file_full( WITH_UMASK(0000) { if (copy_flags & COPY_MAC_CREATE) { - r = mac_selinux_create_file_prepare(to, S_IFREG); + r = mac_selinux_create_file_prepare_at(dir_fdt, to, S_IFREG); if (r < 0) return r; } - fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, + fdt = openat(dir_fdt, to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode != MODE_INVALID ? mode : st.st_mode); if (copy_flags & COPY_MAC_CREATE) mac_selinux_create_file_clear(); @@ -1403,7 +1407,7 @@ int copy_file_full( goto fail; if (copy_flags & COPY_FSYNC_FULL) { - r = fsync_parent_at(AT_FDCWD, to); + r = fsync_parent_at(dir_fdt, to); if (r < 0) goto fail; } @@ -1413,7 +1417,7 @@ int copy_file_full( fail: /* Only unlink if we definitely are the ones who created the file */ if (FLAGS_SET(flags, O_EXCL)) - (void) unlink(to); + (void) unlinkat(dir_fdt, to, 0); return r; } diff --git a/src/shared/copy.h b/src/shared/copy.h index 22151ff83b0..cb40a10f091 100644 --- a/src/shared/copy.h +++ b/src/shared/copy.h @@ -38,9 +38,15 @@ static inline int copy_file_fd(const char *from, int to, CopyFlags copy_flags) { return copy_file_fd_full(from, to, copy_flags, NULL, NULL); } -int copy_file_full(const char *from, const char *to, int open_flags, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags, copy_progress_bytes_t progress, void *userdata); +int copy_file_at_full(int dir_fdf, const char *from, int dir_fdt, const char *to, int open_flags, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags, copy_progress_bytes_t progress, void *userdata); +static inline int copy_file_at(int dir_fdf, const char *from, int dir_fdt, const char *to, int open_flags, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags) { + return copy_file_at_full(dir_fdf, from, dir_fdt, to, open_flags, mode, chattr_flags, chattr_mask, copy_flags, NULL, NULL); +} +static inline int copy_file_full(const char *from, const char *to, int open_flags, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags, copy_progress_bytes_t progress, void *userdata) { + return copy_file_at_full(AT_FDCWD, from, AT_FDCWD, to, open_flags, mode, chattr_flags, chattr_mask, copy_flags, progress, userdata); +} static inline int copy_file(const char *from, const char *to, int open_flags, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags) { - return copy_file_full(from, to, open_flags, mode, chattr_flags, chattr_mask, copy_flags, NULL, NULL); + return copy_file_at(AT_FDCWD, from, AT_FDCWD, to, open_flags, mode, chattr_flags, chattr_mask, copy_flags); } int copy_file_atomic_full(const char *from, const char *to, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags, copy_progress_bytes_t progress, void *userdata);