]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fs-util: add access_fd() which is like access() but for fds
authorLennart Poettering <lennart@poettering.net>
Thu, 16 Nov 2017 17:56:25 +0000 (18:56 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 17 Nov 2017 10:12:33 +0000 (11:12 +0100)
Linux doesn't have faccess(), hence let's emulate it. Linux has access()
and faccessat() but neither allows checking the access rights of an fd
passed in directly.

src/basic/fs-util.c
src/basic/fs-util.h
src/test/test-fs-util.c

index 946f779a329b1b583b22459c4defcf88aee7f3c5..ff8b4e8747dc4c54cd02a26e515dcd83d211c157 100644 (file)
@@ -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;
+}
index d3342d5cdaadff288c4911c2e214a15ca96d395a..9849522f5af1000870a7a738e5fe07748327dacd 100644 (file)
@@ -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);
index a5871a25b061636dbcdde043e49c4a7f6625d5d0..e8fe2b3ff11cfdc62a9a075ca89c19ff671f8911 100644 (file)
@@ -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;
 }