]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
chase-symlinks: Add chase_symlinks_at_and_open() 26502/head
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Sun, 8 Jan 2023 17:24:38 +0000 (18:24 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 6 Mar 2023 12:53:01 +0000 (13:53 +0100)
src/basic/chase-symlinks.c
src/basic/chase-symlinks.h
src/test/test-fs-util.c

index 38fb582c88a432bd55284d009fa3deb0ae820a33..8a769e08e815f8c98608f20a6b97f49b6d9d7edb 100644 (file)
@@ -781,3 +781,38 @@ int chase_symlinks_and_unlink(
 
         return 0;
 }
+
+int chase_symlinks_at_and_open(
+                int dir_fd,
+                const char *path,
+                ChaseSymlinksFlags chase_flags,
+                int open_flags,
+                char **ret_path) {
+
+        _cleanup_close_ int path_fd = -EBADF;
+        _cleanup_free_ char *p = NULL;
+        int r;
+
+        if (chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))
+                return -EINVAL;
+
+        if (dir_fd == AT_FDCWD && !ret_path &&
+            (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0)
+                /* Shortcut this call if none of the special features of this call are requested */
+                return RET_NERRNO(openat(dir_fd, path, open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0)));
+
+        r = chase_symlinks_at(dir_fd, path, chase_flags, ret_path ? &p : NULL, &path_fd);
+        if (r < 0)
+                return r;
+        assert(path_fd >= 0);
+
+        r = fd_reopen(path_fd, open_flags);
+        if (r < 0)
+                return r;
+
+        if (ret_path)
+                *ret_path = TAKE_PTR(p);
+
+        return r;
+}
+
index 7308227c711334a3a205dfe1994092d993cb2caa..19acf9e4b56c9a812860d1d93042295d2c7e6118 100644 (file)
@@ -39,3 +39,4 @@ int chase_symlinks_and_fopen_unlocked(const char *path, const char *root, ChaseS
 int chase_symlinks_and_unlink(const char *path, const char *root, ChaseSymlinksFlags chase_flags, int unlink_flags, char **ret_path);
 
 int chase_symlinks_at(int dir_fd, const char *path, ChaseSymlinksFlags flags, char **ret_path, int *ret_fd);
+int chase_symlinks_at_and_open(int dir_fd, const char *path, ChaseSymlinksFlags chase_flags, int open_flags, char **ret_path);
index ef7f41885a9cfb2489bc32b68fca9e57947f8156..c009424a2bcc48dd54893284ea1327033f10d62f 100644 (file)
@@ -500,6 +500,12 @@ TEST(chase_symlinks_at) {
         result = mfree(result);
 
         assert_se(chase_symlinks_at(tfd, "i/../p", CHASE_MKDIR_0755, NULL, NULL) == -ENOENT);
+
+        /* Test chase_symlinks_at_and_open() */
+
+        fd = chase_symlinks_at_and_open(tfd, "o/p/e/n", CHASE_MKDIR_0755, O_CLOEXEC, NULL);
+        assert_se(fd >= 0);
+        fd = safe_close(fd);
 }
 
 TEST(unlink_noerrno) {