diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 946f779a32..ff8b4e8747 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -104,7 +104,6 @@ int rmdir_parents(const char *path, const char *stop) { return 0; } - int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { struct stat buf; int ret; @@ -809,3 +808,18 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return exists; } + +int access_fd(int fd, int mode) { + char p[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1]; + int r; + + /* Like access() but operates on an already open fd */ + + xsprintf(p, "/proc/self/fd/%i", fd); + + r = access(p, mode); + if (r < 0) + r = -errno; + + return r; +} diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index d3342d5cda..9849522f5a 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -98,3 +98,5 @@ static inline void unlink_and_free(char *p) { free(p); } DEFINE_TRIVIAL_CLEANUP_FUNC(char*, unlink_and_free); + +int access_fd(int fd, int mode); diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index a5871a25b0..e8fe2b3ff1 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -315,6 +315,32 @@ static void test_dot_or_dot_dot(void) { assert_se(!dot_or_dot_dot("..foo")); } +static void test_access_fd(void) { + _cleanup_(rmdir_and_freep) char *p = NULL; + _cleanup_close_ int fd = -1; + + assert_se(mkdtemp_malloc("/tmp/access-fd.XXXXXX", &p) >= 0); + + fd = open(p, O_RDONLY|O_DIRECTORY|O_CLOEXEC); + assert_se(fd >= 0); + + assert_se(access_fd(fd, R_OK) >= 0); + assert_se(access_fd(fd, F_OK) >= 0); + assert_se(access_fd(fd, W_OK) >= 0); + + assert_se(fchmod(fd, 0000) >= 0); + + assert_se(access_fd(fd, F_OK) >= 0); + + if (geteuid() == 0) { + assert_se(access_fd(fd, R_OK) >= 0); + assert_se(access_fd(fd, W_OK) >= 0); + } else { + assert_se(access_fd(fd, R_OK) == -EACCES); + assert_se(access_fd(fd, W_OK) == -EACCES); + } +} + int main(int argc, char *argv[]) { test_unlink_noerrno(); test_get_files_in_directory(); @@ -322,6 +348,7 @@ int main(int argc, char *argv[]) { test_var_tmp(); test_chase_symlinks(); test_dot_or_dot_dot(); + test_access_fd(); return 0; }