summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaan De Meyer <daan.j.demeyer@gmail.com>2023-03-21 20:52:17 +0100
committerGitHub <noreply@github.com>2023-03-21 20:52:17 +0100
commitf3e03bd04e21c00cd251bf69a346d0ae505b6494 (patch)
tree02f3011b471e941b3cea6014b078ed8bbc368af4 /src
parent42db4a8db704592866ccc96c4a068b1537b1dde8 (diff)
parentd294857ea6d874e29eda7c14e3fc2de0d4869909 (diff)
downloadsystemd-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.c17
-rw-r--r--src/basic/fs-util.h5
-rw-r--r--src/basic/tmpfile-util.c21
-rw-r--r--src/basic/tmpfile-util.h11
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);