diff options
author | Daan De Meyer <daan.j.demeyer@gmail.com> | 2023-03-21 20:52:17 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-21 20:52:17 +0100 |
commit | f3e03bd04e21c00cd251bf69a346d0ae505b6494 (patch) | |
tree | 02f3011b471e941b3cea6014b078ed8bbc368af4 /src | |
parent | 42db4a8db704592866ccc96c4a068b1537b1dde8 (diff) | |
parent | d294857ea6d874e29eda7c14e3fc2de0d4869909 (diff) | |
download | systemd-f3e03bd04e21c00cd251bf69a346d0ae505b6494.tar.gz |
Merge pull request #26828 from DaanDeMeyer/tmpfile-at
tmpfile-util: Add open_tmpfile_linkable_at() and link_tmpfile_at()
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/fs-util.c | 17 | ||||
-rw-r--r-- | src/basic/fs-util.h | 5 | ||||
-rw-r--r-- | src/basic/tmpfile-util.c | 21 | ||||
-rw-r--r-- | src/basic/tmpfile-util.h | 11 |
4 files changed, 38 insertions, 16 deletions
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 7f1f90f4e9..19ada73af5 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -781,12 +781,23 @@ int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) { return 0; } -int open_parent(const char *path, int flags, mode_t mode) { +int open_parent_at(int dir_fd, const char *path, int flags, mode_t mode) { _cleanup_free_ char *parent = NULL; int r; + assert(dir_fd >= 0 || dir_fd == AT_FDCWD); + assert(path); + r = path_extract_directory(path, &parent); - if (r < 0) + if (r == -EDESTADDRREQ) { + parent = strdup("."); + if (!parent) + return -ENOMEM; + } else if (r == -EADDRNOTAVAIL) { + parent = strdup(path); + if (!parent) + return -ENOMEM; + } else if (r < 0) return r; /* Let's insist on O_DIRECTORY since the parent of a file or directory is a directory. Except if we open an @@ -797,7 +808,7 @@ int open_parent(const char *path, int flags, mode_t mode) { else if (!FLAGS_SET(flags, O_TMPFILE)) flags |= O_DIRECTORY|O_RDONLY; - return RET_NERRNO(open(parent, flags, mode)); + return RET_NERRNO(openat(dir_fd, parent, flags, mode)); } int conservative_renameat( diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index b66dda01b4..d08e224aa1 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -113,7 +113,10 @@ typedef enum UnlinkDeallocateFlags { int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags); -int open_parent(const char *path, int flags, mode_t mode); +int open_parent_at(int dir_fd, const char *path, int flags, mode_t mode); +static inline int open_parent(const char *path, int flags, mode_t mode) { + return open_parent_at(AT_FDCWD, path, flags, mode); +} int conservative_renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath); static inline int conservative_rename(const char *oldpath, const char *newpath) { diff --git a/src/basic/tmpfile-util.c b/src/basic/tmpfile-util.c index 379d81d5c8..d44464dd7b 100644 --- a/src/basic/tmpfile-util.c +++ b/src/basic/tmpfile-util.c @@ -272,7 +272,7 @@ int open_tmpfile_unlinkable(const char *directory, int flags) { return fd; } -int open_tmpfile_linkable(const char *target, int flags, char **ret_path) { +int open_tmpfile_linkable_at(int dir_fd, const char *target, int flags, char **ret_path) { _cleanup_free_ char *tmp = NULL; int r, fd; @@ -286,7 +286,7 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path) { * which case "ret_path" will be returned as NULL. If not possible the temporary path name used is returned in * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */ - fd = open_parent(target, O_TMPFILE|flags, 0640); + fd = open_parent_at(dir_fd, target, O_TMPFILE|flags, 0640); if (fd >= 0) { *ret_path = NULL; return fd; @@ -298,7 +298,7 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path) { if (r < 0) return r; - fd = open(tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0640); + fd = openat(dir_fd, tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0640); if (fd < 0) return -errno; @@ -349,11 +349,12 @@ static int link_fd(int fd, int newdirfd, const char *newpath) { return RET_NERRNO(linkat(fd, "", newdirfd, newpath, AT_EMPTY_PATH)); } -int link_tmpfile(int fd, const char *path, const char *target, bool replace) { +int link_tmpfile_at(int fd, int dir_fd, const char *path, const char *target, bool replace) { _cleanup_free_ char *tmp = NULL; int r; assert(fd >= 0); + assert(dir_fd >= 0 || dir_fd == AT_FDCWD); assert(target); /* Moves a temporary file created with open_tmpfile() above into its final place. If "path" is NULL @@ -362,12 +363,12 @@ int link_tmpfile(int fd, const char *path, const char *target, bool replace) { if (path) { if (replace) - return RET_NERRNO(rename(path, target)); + return RET_NERRNO(renameat(dir_fd, path, dir_fd, target)); - return rename_noreplace(AT_FDCWD, path, AT_FDCWD, target); + return rename_noreplace(dir_fd, path, dir_fd, target); } - r = link_fd(fd, AT_FDCWD, target); + r = link_fd(fd, dir_fd, target); if (r != -EEXIST || !replace) return r; @@ -381,12 +382,12 @@ int link_tmpfile(int fd, const char *path, const char *target, bool replace) { if (r < 0) return r; - if (link_fd(fd, AT_FDCWD, tmp) < 0) + if (link_fd(fd, dir_fd, tmp) < 0) return -EEXIST; /* propagate original error */ - r = RET_NERRNO(rename(tmp, target)); + r = RET_NERRNO(renameat(dir_fd, tmp, dir_fd, target)); if (r < 0) { - (void) unlink(tmp); + (void) unlinkat(dir_fd, tmp, 0); return r; } diff --git a/src/basic/tmpfile-util.h b/src/basic/tmpfile-util.h index 4665dafb24..f48ce10e68 100644 --- a/src/basic/tmpfile-util.h +++ b/src/basic/tmpfile-util.h @@ -2,6 +2,7 @@ #pragma once #include <fcntl.h> +#include <stdbool.h> #include <stdio.h> int fopen_temporary_at(int dir_fd, const char *path, FILE **ret_file, char **ret_path); @@ -22,10 +23,16 @@ int tempfn_random(const char *p, const char *extra, char **ret); int tempfn_random_child(const char *p, const char *extra, char **ret); int open_tmpfile_unlinkable(const char *directory, int flags); -int open_tmpfile_linkable(const char *target, int flags, char **ret_path); +int open_tmpfile_linkable_at(int dir_fd, const char *target, int flags, char **ret_path); +static inline int open_tmpfile_linkable(const char *target, int flags, char **ret_path) { + return open_tmpfile_linkable_at(AT_FDCWD, target, flags, ret_path); +} int fopen_tmpfile_linkable(const char *target, int flags, char **ret_path, FILE **ret_file); -int link_tmpfile(int fd, const char *path, const char *target, bool replace); +int link_tmpfile_at(int fd, int dir_fd, const char *path, const char *target, bool replace); +static inline int link_tmpfile(int fd, const char *path, const char *target, bool replace) { + return link_tmpfile_at(fd, AT_FDCWD, path, target, replace); +} int flink_tmpfile(FILE *f, const char *path, const char *target, bool replace); int mkdtemp_malloc(const char *template, char **ret); |