mirror of
https://github.com/systemd/systemd.git
synced 2026-08-09 17:38:42 +00:00
fd-util: wire up XAT_FDROOT in various really basic fd-util.h calls
This commit is contained in:
@@ -572,10 +572,12 @@ bool fdname_is_valid(const char *s) {
|
||||
int fd_get_path(int fd, char **ret) {
|
||||
int r;
|
||||
|
||||
assert(fd >= 0 || fd == AT_FDCWD);
|
||||
assert(fd >= 0 || IN_SET(fd, AT_FDCWD, XAT_FDROOT));
|
||||
|
||||
if (fd == AT_FDCWD)
|
||||
return safe_getcwd(ret);
|
||||
if (fd == XAT_FDROOT)
|
||||
return strdup_to(ret, "/");
|
||||
|
||||
r = readlink_malloc(FORMAT_PROC_FD_PATH(fd), ret);
|
||||
if (r == -ENOENT)
|
||||
@@ -770,7 +772,7 @@ finish:
|
||||
}
|
||||
|
||||
int fd_reopen(int fd, int flags) {
|
||||
assert(fd >= 0 || fd == AT_FDCWD);
|
||||
assert(fd >= 0 || IN_SET(fd, AT_FDCWD, XAT_FDROOT));
|
||||
assert(!FLAGS_SET(flags, O_CREAT));
|
||||
|
||||
/* Reopens the specified fd with new flags. This is useful for convert an O_PATH fd into a regular one, or to
|
||||
@@ -782,6 +784,8 @@ int fd_reopen(int fd, int flags) {
|
||||
*
|
||||
* If AT_FDCWD is specified as file descriptor gets an fd to the current cwd.
|
||||
*
|
||||
* If XAT_FDROOT is specified as fd get an fd to the root directory.
|
||||
*
|
||||
* If the specified file descriptor refers to a symlink via O_PATH, then this function cannot be used
|
||||
* to follow that symlink. Because we cannot have non-O_PATH fds to symlinks reopening it without
|
||||
* O_PATH will always result in -ELOOP. Or in other words: if you have an O_PATH fd to a symlink you
|
||||
@@ -795,6 +799,9 @@ int fd_reopen(int fd, int flags) {
|
||||
* the same way as the non-O_DIRECTORY case. */
|
||||
return -ELOOP;
|
||||
|
||||
if (fd == XAT_FDROOT)
|
||||
return RET_NERRNO(open("/", flags | O_DIRECTORY));
|
||||
|
||||
if (FLAGS_SET(flags, O_DIRECTORY) || fd == AT_FDCWD)
|
||||
/* If we shall reopen the fd as directory we can just go via "." and thus bypass the whole
|
||||
* magic /proc/ directory, and make ourselves independent of that being mounted. */
|
||||
@@ -1025,19 +1032,36 @@ int fd_get_diskseq(int fd, uint64_t *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_literal_root(const char *p) {
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
/* Check if string consists of at least one '/', and possibly more, but nothing else */
|
||||
size_t n = strspn(p, "/");
|
||||
return n >= 1 && p[n] == 0;
|
||||
}
|
||||
|
||||
int path_is_root_at(int dir_fd, const char *path) {
|
||||
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
|
||||
assert(dir_fd >= 0 || IN_SET(dir_fd, AT_FDCWD, XAT_FDROOT));
|
||||
|
||||
if (dir_fd == XAT_FDROOT && isempty(path))
|
||||
return true;
|
||||
|
||||
if (IN_SET(dir_fd, XAT_FDROOT, AT_FDCWD) && is_literal_root(path))
|
||||
return true;
|
||||
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
if (!isempty(path)) {
|
||||
fd = openat(dir_fd, path, O_PATH|O_DIRECTORY|O_CLOEXEC);
|
||||
fd = xopenat(dir_fd, path, O_PATH|O_DIRECTORY|O_CLOEXEC);
|
||||
if (fd == -ENOTDIR)
|
||||
return false; /* the root dir must be a dir */
|
||||
if (fd < 0)
|
||||
return errno == ENOTDIR ? false : -errno;
|
||||
return fd;
|
||||
|
||||
dir_fd = fd;
|
||||
}
|
||||
|
||||
_cleanup_close_ int root_fd = openat(AT_FDCWD, "/", O_PATH|O_DIRECTORY|O_CLOEXEC);
|
||||
_cleanup_close_ int root_fd = open("/", O_PATH|O_DIRECTORY|O_CLOEXEC);
|
||||
if (root_fd < 0)
|
||||
return -errno;
|
||||
|
||||
@@ -1055,13 +1079,27 @@ int path_is_root_at(int dir_fd, const char *path) {
|
||||
int fds_are_same_mount(int fd1, int fd2) {
|
||||
struct statx sx1 = {}, sx2 = {}; /* explicitly initialize the struct to make msan silent. */
|
||||
|
||||
assert(fd1 >= 0);
|
||||
assert(fd2 >= 0);
|
||||
assert(fd1 >= 0 || IN_SET(fd1, AT_FDCWD, XAT_FDROOT));
|
||||
assert(fd2 >= 0 || IN_SET(fd2, AT_FDCWD, XAT_FDROOT));
|
||||
|
||||
if (statx(fd1, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx1) < 0)
|
||||
const char *fn1;
|
||||
if (fd1 == XAT_FDROOT) {
|
||||
fd1 = AT_FDCWD;
|
||||
fn1 = "/";
|
||||
} else
|
||||
fn1 = "";
|
||||
|
||||
if (statx(fd1, fn1, AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx1) < 0)
|
||||
return -errno;
|
||||
|
||||
if (statx(fd2, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx2) < 0)
|
||||
const char *fn2;
|
||||
if (fd2 == XAT_FDROOT) {
|
||||
fd2 = AT_FDCWD;
|
||||
fn2 = "/";
|
||||
} else
|
||||
fn2 = "";
|
||||
|
||||
if (statx(fd2, fn2, AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx2) < 0)
|
||||
return -errno;
|
||||
|
||||
return statx_inode_same(&sx1, &sx2) && statx_mount_same(&sx1, &sx2);
|
||||
|
||||
@@ -173,10 +173,10 @@ static inline int path_is_root(const char *path) {
|
||||
return path_is_root_at(AT_FDCWD, path);
|
||||
}
|
||||
static inline int dir_fd_is_root(int dir_fd) {
|
||||
return path_is_root_at(dir_fd, NULL);
|
||||
return dir_fd == XAT_FDROOT ? true : path_is_root_at(dir_fd, NULL);
|
||||
}
|
||||
static inline int dir_fd_is_root_or_cwd(int dir_fd) {
|
||||
return dir_fd == AT_FDCWD ? true : path_is_root_at(dir_fd, NULL);
|
||||
return IN_SET(dir_fd, AT_FDCWD, XAT_FDROOT) ? true : path_is_root_at(dir_fd, NULL);
|
||||
}
|
||||
|
||||
int fds_are_same_mount(int fd1, int fd2);
|
||||
|
||||
Reference in New Issue
Block a user