]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fs-util: wire up XAT_FDROOT in xopenat_full() and access_fd()
authorLennart Poettering <lennart@poettering.net>
Mon, 8 Dec 2025 12:31:56 +0000 (13:31 +0100)
committerLennart Poettering <lennart@poettering.net>
Sat, 17 Jan 2026 11:37:33 +0000 (12:37 +0100)
src/basic/fs-util.c

index d668416ff8cdd03de6620d38e0f6200942e72dc0..d3712622f179a3a8ad03900e092fde699b0a5a3d 100644 (file)
@@ -713,10 +713,15 @@ char* unlink_and_free(char *p) {
 }
 
 int access_fd(int fd, int mode) {
-        assert(fd >= 0);
-
         /* Like access() but operates on an already open fd */
 
+        if (fd == AT_FDCWD)
+                return RET_NERRNO(access(".", mode));
+        if (fd == XAT_FDROOT)
+                return RET_NERRNO(access("/", mode));
+
+        assert(fd >= 0);
+
         if (faccessat(fd, "", mode, AT_EMPTY_PATH) >= 0)
                 return 0;
         if (errno != EINVAL)
@@ -1160,7 +1165,7 @@ int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_
         bool made_dir = false, made_file = false;
         int r;
 
-        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
+        assert(dir_fd >= 0 || IN_SET(dir_fd, AT_FDCWD, XAT_FDROOT));
 
         /* An inode cannot be both a directory and a regular file at the same time. */
         assert(!(FLAGS_SET(open_flags, O_DIRECTORY) && FLAGS_SET(xopen_flags, XO_REGULAR)));
@@ -1179,8 +1184,23 @@ int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_
          *   • if XO_REGULAR is specified will return an error if inode is not a regular file.
          *
          *   • If mode is specified as MODE_INVALID, we'll use 0755 for dirs, and 0644 for regular files.
+         *
+         *   • The dir fd can be passed as XAT_FDROOT, in which case any relative paths will be taken relative to the root fs.
          */
 
+        _cleanup_close_ int _dir_fd = -EBADF;
+        if (dir_fd == XAT_FDROOT) {
+                if (path_is_absolute(path))
+                        dir_fd = AT_FDCWD;
+                else {
+                        _dir_fd = open("/", O_CLOEXEC|O_DIRECTORY|O_RDONLY);
+                        if (_dir_fd < 0)
+                                return -errno;
+
+                        dir_fd = _dir_fd;
+                }
+        }
+
         if (mode == MODE_INVALID)
                 mode = (open_flags & O_DIRECTORY) ? 0755 : 0644;