struct stat st;
int r;
- assert(fd >= 0 || fd == AT_FDCWD);
+ assert(fd >= 0 || IN_SET(fd, AT_FDCWD, XAT_FDROOT));
assert(!isempty(path) || !follow);
assert(verify_func);
+ _cleanup_free_ char *p = NULL;
+ if (fd == XAT_FDROOT) {
+ fd = AT_FDCWD;
+
+ if (isempty(path))
+ path = "/";
+ else if (!path_is_absolute(path)) {
+ p = strjoin("/", path);
+ if (!p)
+ return -ENOMEM;
+
+ path = p;
+ }
+ }
+
if (fstatat(fd, strempty(path), &st,
(isempty(path) ? AT_EMPTY_PATH : 0) | (follow ? 0 : AT_SYMLINK_NOFOLLOW)) < 0)
return -errno;
}
int fd_verify_regular(int fd) {
- assert(fd >= 0);
- return verify_regular_at(fd, NULL, false);
+ if (IN_SET(fd, AT_FDCWD, XAT_FDROOT))
+ return -EISDIR;
+
+ return verify_regular_at(fd, /* path= */ NULL, /* follow= */ false);
}
int stat_verify_directory(const struct stat *st) {
}
int fd_verify_directory(int fd) {
- assert(fd >= 0);
+ if (IN_SET(fd, AT_FDCWD, XAT_FDROOT))
+ return 0;
+
return verify_stat_at(fd, NULL, false, stat_verify_directory, true);
}
}
int fd_verify_linked(int fd) {
- assert(fd >= 0);
+
+ if (fd == XAT_FDROOT)
+ return 0;
+
return verify_stat_at(fd, NULL, false, stat_verify_linked, true);
}
return null_or_empty(&st);
}
-int fd_is_read_only_fs(int fd) {
- struct statfs st;
+static int xfstatfs(int fd, struct statfs *ret) {
+ assert(ret);
+
+ if (fd == AT_FDCWD)
+ return RET_NERRNO(statfs(".", ret));
+ if (fd == XAT_FDROOT)
+ return RET_NERRNO(statfs("/", ret));
assert(fd >= 0);
+ return RET_NERRNO(fstatfs(fd, ret));
+}
- if (fstatfs(fd, &st) < 0)
- return -errno;
+int fd_is_read_only_fs(int fd) {
+ int r;
+
+ struct statfs st;
+ r = xfstatfs(fd, &st);
+ if (r < 0)
+ return r;
if (st.f_flags & ST_RDONLY)
return true;
- if (is_network_fs(&st)) {
+ if (is_network_fs(&st))
/* On NFS, fstatfs() might not reflect whether we can actually write to the remote share.
* Let's try again with access(W_OK) which is more reliable, at least sometimes. */
- if (access_fd(fd, W_OK) == -EROFS)
- return true;
- }
+ return access_fd(fd, W_OK) == -EROFS;
return false;
}
}
int is_fs_type_at(int dir_fd, const char *path, statfs_f_type_t magic_value) {
- struct statfs s;
int r;
+ struct statfs s;
r = xstatfsat(dir_fd, path, &s);
if (r < 0)
return r;
}
int fd_is_temporary_fs(int fd) {
- struct statfs s;
+ int r;
- if (fstatfs(fd, &s) < 0)
- return -errno;
+ struct statfs s;
+ r = xfstatfs(fd, &s);
+ if (r < 0)
+ return r;
return is_temporary_fs(&s);
}
int fd_is_network_fs(int fd) {
- struct statfs s;
+ int r;
- if (fstatfs(fd, &s) < 0)
- return -errno;
+ struct statfs s;
+ r = xfstatfs(fd, &s);
+ if (r < 0)
+ return r;
return is_network_fs(&s);
}
int xstatfsat(int dir_fd, const char *path, struct statfs *ret) {
_cleanup_close_ int fd = -EBADF;
- assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
+ assert(dir_fd >= 0 || IN_SET(dir_fd, AT_FDCWD, XAT_FDROOT));
assert(ret);
if (!isempty(path)) {
dir_fd = fd;
}
- return RET_NERRNO(fstatfs(dir_fd, ret));
+ return RET_NERRNO(xfstatfs(dir_fd, ret));
}
usec_t statx_timestamp_load(const struct statx_timestamp *ts) {