]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
copy: Add copy_file_at()
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 22 Dec 2022 13:27:26 +0000 (14:27 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 20 Feb 2023 11:44:18 +0000 (12:44 +0100)
src/shared/copy.c
src/shared/copy.h

index d15875739acb38f5e6210f4d49998fa89850b287..a1df3048baeed36e304475565cba22cce3e5d231 100644 (file)
@@ -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;
 }
index 22151ff83b07a012085ab7be2854412b676cd907..cb40a10f091fbe761dc289225c20c8e00aa419e5 100644 (file)
@@ -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);