From: Lennart Poettering Date: Wed, 13 Mar 2024 16:48:04 +0000 (+0100) Subject: fs-util: move link_fd() from tmpfile-util.c into generic fs-util.c X-Git-Tag: v256-rc1~531^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b8e36f0642bd11dbec3fae927e0a73cc9e394ce;p=thirdparty%2Fsystemd.git fs-util: move link_fd() from tmpfile-util.c into generic fs-util.c It's a generically useful call, let's move it so that we can use it at more places. --- diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 5bc7d2f95be..999713d243b 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -1236,3 +1236,23 @@ int xopenat_lock_full( return TAKE_FD(fd); } + +int link_fd(int fd, int newdirfd, const char *newpath) { + int r; + + assert(fd >= 0); + assert(newdirfd >= 0 || newdirfd == AT_FDCWD); + assert(newpath); + + /* Try linking via /proc/self/fd/ first. */ + r = RET_NERRNO(linkat(AT_FDCWD, FORMAT_PROC_FD_PATH(fd), newdirfd, newpath, AT_SYMLINK_FOLLOW)); + if (r != -ENOENT) + return r; + + /* Fall back to symlinking via AT_EMPTY_PATH as fallback (this requires CAP_DAC_READ_SEARCH and a + * more recent kernel, but does not require /proc/ mounted) */ + if (proc_mounted() != 0) + return r; + + return RET_NERRNO(linkat(fd, "", newdirfd, newpath, AT_EMPTY_PATH)); +} diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 6a1e2e76d14..86fc6711586 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -146,3 +146,5 @@ int xopenat_lock_full(int dir_fd, const char *path, int open_flags, XOpenFlags x static inline int xopenat_lock(int dir_fd, const char *path, int open_flags, LockType locktype, int operation) { return xopenat_lock_full(dir_fd, path, open_flags, 0, 0, locktype, operation); } + +int link_fd(int fd, int newdirfd, const char *newpath); diff --git a/src/basic/tmpfile-util.c b/src/basic/tmpfile-util.c index e77ca942489..4cae5cbd0b7 100644 --- a/src/basic/tmpfile-util.c +++ b/src/basic/tmpfile-util.c @@ -330,26 +330,6 @@ int fopen_tmpfile_linkable(const char *target, int flags, char **ret_path, FILE return 0; } -static int link_fd(int fd, int newdirfd, const char *newpath) { - int r; - - assert(fd >= 0); - assert(newdirfd >= 0 || newdirfd == AT_FDCWD); - assert(newpath); - - /* Try symlinking via /proc/fd/ first. */ - r = RET_NERRNO(linkat(AT_FDCWD, FORMAT_PROC_FD_PATH(fd), newdirfd, newpath, AT_SYMLINK_FOLLOW)); - if (r != -ENOENT) - return r; - - /* Fall back to symlinking via AT_EMPTY_PATH as fallback (this requires CAP_DAC_READ_SEARCH and a - * more recent kernel, but does not require /proc/ mounted) */ - if (proc_mounted() != 0) - return r; - - return RET_NERRNO(linkat(fd, "", newdirfd, newpath, AT_EMPTY_PATH)); -} - int link_tmpfile_at(int fd, int dir_fd, const char *path, const char *target, LinkTmpfileFlags flags) { _cleanup_free_ char *tmp = NULL; int r;