summaryrefslogtreecommitdiffstats
path: root/src/stat.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2022-05-12 14:25:19 -0400
committerTavian Barnes <tavianator@tavianator.com>2022-05-12 14:25:19 -0400
commit2c67e0676ed27055cb622a9da9508defbafc2488 (patch)
treee3930cf41376d9210f10ee8c4c2f51d9bde64592 /src/stat.c
parentf8eaf398c667ab4455bb480fcbece7240aeeb9f3 (diff)
downloadbfs-2c67e0676ed27055cb622a9da9508defbafc2488.tar.xz
stat: Keep statx()-specific flags separate
Previously, if statx() was unsupported at runtime, we could end up passing AT_STATX_DONT_SYNC to fstatat() which doesn't expect it.
Diffstat (limited to 'src/stat.c')
-rw-r--r--src/stat.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/src/stat.c b/src/stat.c
index 0326ba2..c3ee1ad 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -268,12 +268,12 @@ static int bfs_statx_impl(int at_fd, const char *at_path, int at_flags, struct b
/**
* Calls the stat() implementation with explicit flags.
*/
-static int bfs_stat_explicit(int at_fd, const char *at_path, int at_flags, struct bfs_stat *buf) {
+static int bfs_stat_explicit(int at_fd, const char *at_path, int at_flags, int x_flags, struct bfs_stat *buf) {
#if BFS_STATX
static bool has_statx = true;
if (has_statx) {
- int ret = bfs_statx_impl(at_fd, at_path, at_flags, buf);
+ int ret = bfs_statx_impl(at_fd, at_path, at_flags | x_flags, buf);
// EPERM is commonly returned in a seccomp() sandbox that does
// not allow statx()
if (ret != 0 && (errno == ENOSYS || errno == EPERM)) {
@@ -290,15 +290,15 @@ static int bfs_stat_explicit(int at_fd, const char *at_path, int at_flags, struc
/**
* Implements the BFS_STAT_TRYFOLLOW retry logic.
*/
-static int bfs_stat_tryfollow(int at_fd, const char *at_path, int at_flags, enum bfs_stat_flags bfs_flags, struct bfs_stat *buf) {
- int ret = bfs_stat_explicit(at_fd, at_path, at_flags, buf);
+static int bfs_stat_tryfollow(int at_fd, const char *at_path, int at_flags, int x_flags, enum bfs_stat_flags bfs_flags, struct bfs_stat *buf) {
+ int ret = bfs_stat_explicit(at_fd, at_path, at_flags, x_flags, buf);
if (ret != 0
&& (bfs_flags & (BFS_STAT_NOFOLLOW | BFS_STAT_TRYFOLLOW)) == BFS_STAT_TRYFOLLOW
&& is_nonexistence_error(errno))
{
at_flags |= AT_SYMLINK_NOFOLLOW;
- ret = bfs_stat_explicit(at_fd, at_path, at_flags, buf);
+ ret = bfs_stat_explicit(at_fd, at_path, at_flags, x_flags, buf);
}
return ret;
@@ -310,14 +310,15 @@ int bfs_stat(int at_fd, const char *at_path, enum bfs_stat_flags flags, struct b
at_flags |= AT_SYMLINK_NOFOLLOW;
}
+ int x_flags = 0;
#ifdef AT_STATX_DONT_SYNC
if (flags & BFS_STAT_NOSYNC) {
- at_flags |= AT_STATX_DONT_SYNC;
+ x_flags |= AT_STATX_DONT_SYNC;
}
#endif
if (at_path) {
- return bfs_stat_tryfollow(at_fd, at_path, at_flags, flags, buf);
+ return bfs_stat_tryfollow(at_fd, at_path, at_flags, x_flags, flags, buf);
}
// Check __GNU__ to work around https://lists.gnu.org/archive/html/bug-hurd/2021-12/msg00001.html
@@ -325,7 +326,7 @@ int bfs_stat(int at_fd, const char *at_path, enum bfs_stat_flags flags, struct b
static bool has_at_ep = true;
if (has_at_ep) {
at_flags |= AT_EMPTY_PATH;
- int ret = bfs_stat_explicit(at_fd, "", at_flags, buf);
+ int ret = bfs_stat_explicit(at_fd, "", at_flags, x_flags, buf);
if (ret != 0 && errno == EINVAL) {
has_at_ep = false;
} else {