stat-util: write up XAT_FDROOT in stat-util.[ch]
This commit is contained in:
+58
-22
@@ -31,10 +31,25 @@ static int verify_stat_at(
|
||||
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;
|
||||
@@ -66,8 +81,10 @@ int verify_regular_at(int fd, const char *path, bool follow) {
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -83,7 +100,9 @@ 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);
|
||||
}
|
||||
|
||||
@@ -127,7 +146,10 @@ int stat_verify_linked(const struct stat *st) {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -223,23 +245,33 @@ int null_or_empty_path_with_root(const char *fn, const char *root) {
|
||||
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;
|
||||
}
|
||||
@@ -364,9 +396,9 @@ bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -383,19 +415,23 @@ bool is_network_fs(const struct statfs *s) {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -489,7 +525,7 @@ bool statx_mount_same(const struct statx *a, const struct statx *b) {
|
||||
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)) {
|
||||
@@ -499,7 +535,7 @@ int xstatfsat(int dir_fd, const char *path, struct statfs *ret) {
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user