summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2024-01-16 12:32:38 -0500
committerTavian Barnes <tavianator@tavianator.com>2024-01-18 20:07:40 -0500
commitcb45babbeff337df9e0d96a251db2b9b325f9d18 (patch)
tree519bffc379afd423c1f5e70c9d584f797ff8bb36 /src
parent3fa8f1a22ad120322bbc68823ca9759d8939b131 (diff)
downloadbfs-cb45babbeff337df9e0d96a251db2b9b325f9d18.tar.xz
stat: Expose bfs_{fstatat,statx}_flags()
Diffstat (limited to 'src')
-rw-r--r--src/stat.c58
-rw-r--r--src/stat.h10
2 files changed, 47 insertions, 21 deletions
diff --git a/src/stat.c b/src/stat.c
index 8da1466..4e7e7e2 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -57,6 +57,20 @@ const char *bfs_stat_field_name(enum bfs_stat_field field) {
return "???";
}
+int bfs_fstatat_flags(enum bfs_stat_flags flags) {
+ int ret = 0;
+
+ if (flags & BFS_STAT_NOFOLLOW) {
+ ret |= AT_SYMLINK_NOFOLLOW;
+ }
+
+#if defined(AT_NO_AUTOMOUNT) && (!__GNU__ || __GLIBC_PREREQ(2, 35))
+ ret |= AT_NO_AUTOMOUNT;
+#endif
+
+ return ret;
+}
+
void bfs_stat_convert(struct bfs_stat *dest, const struct stat *src) {
dest->mask = 0;
@@ -139,6 +153,16 @@ static int bfs_statx(int at_fd, const char *at_path, int at_flags, unsigned int
return ret;
}
+int bfs_statx_flags(enum bfs_stat_flags flags) {
+ int ret = bfs_fstatat_flags(flags);
+
+ if (flags & BFS_STAT_NOSYNC) {
+ ret |= AT_STATX_DONT_SYNC;
+ }
+
+ return ret;
+}
+
int bfs_statx_convert(struct bfs_stat *dest, const struct statx *src) {
// Callers shouldn't have to check anything except the times
const unsigned int guaranteed = STATX_BASIC_STATS & ~(STATX_ATIME | STATX_CTIME | STATX_MTIME);
@@ -226,12 +250,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, int x_flags, struct bfs_stat *buf) {
+static int bfs_stat_explicit(int at_fd, const char *at_path, int at_flags, struct bfs_stat *buf) {
#if BFS_USE_STATX
static atomic bool has_statx = true;
if (load(&has_statx, relaxed)) {
- int ret = bfs_statx_impl(at_fd, at_path, at_flags | x_flags, buf);
+ int ret = bfs_statx_impl(at_fd, at_path, at_flags, buf);
// EPERM is commonly returned in a seccomp() sandbox that does
// not allow statx()
if (ret != 0 && (errno == ENOSYS || errno == EPERM)) {
@@ -240,6 +264,8 @@ static int bfs_stat_explicit(int at_fd, const char *at_path, int at_flags, int x
return ret;
}
}
+
+ at_flags &= ~AT_STATX_DONT_SYNC;
#endif
return bfs_stat_impl(at_fd, at_path, at_flags, buf);
@@ -248,39 +274,29 @@ static int bfs_stat_explicit(int at_fd, const char *at_path, int at_flags, int x
/**
* Implements the BFS_STAT_TRYFOLLOW retry logic.
*/
-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);
+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);
if (ret != 0
&& (bfs_flags & (BFS_STAT_NOFOLLOW | BFS_STAT_TRYFOLLOW)) == BFS_STAT_TRYFOLLOW
&& errno_is_like(ENOENT))
{
at_flags |= AT_SYMLINK_NOFOLLOW;
- ret = bfs_stat_explicit(at_fd, at_path, at_flags, x_flags, buf);
+ ret = bfs_stat_explicit(at_fd, at_path, at_flags, buf);
}
return ret;
}
int bfs_stat(int at_fd, const char *at_path, enum bfs_stat_flags flags, struct bfs_stat *buf) {
- int at_flags = 0;
- if (flags & BFS_STAT_NOFOLLOW) {
- at_flags |= AT_SYMLINK_NOFOLLOW;
- }
-
-#if defined(AT_NO_AUTOMOUNT) && (!__GNU__ || __GLIBC_PREREQ(2, 35))
- at_flags |= AT_NO_AUTOMOUNT;
-#endif
-
- int x_flags = 0;
-#ifdef AT_STATX_DONT_SYNC
- if (flags & BFS_STAT_NOSYNC) {
- x_flags |= AT_STATX_DONT_SYNC;
- }
+#if BFS_USE_STATX
+ int at_flags = bfs_statx_flags(flags);
+#else
+ int at_flags = bfs_fstatat_flags(flags);
#endif
if (at_path) {
- return bfs_stat_tryfollow(at_fd, at_path, at_flags, x_flags, flags, buf);
+ return bfs_stat_tryfollow(at_fd, at_path, at_flags, flags, buf);
}
// Check __GNU__ to work around https://lists.gnu.org/archive/html/bug-hurd/2021-12/msg00001.html
@@ -288,7 +304,7 @@ int bfs_stat(int at_fd, const char *at_path, enum bfs_stat_flags flags, struct b
static atomic bool has_at_ep = true;
if (load(&has_at_ep, relaxed)) {
at_flags |= AT_EMPTY_PATH;
- int ret = bfs_stat_explicit(at_fd, "", at_flags, x_flags, buf);
+ int ret = bfs_stat_explicit(at_fd, "", at_flags, buf);
if (ret != 0 && errno == EINVAL) {
store(&has_at_ep, false, relaxed);
} else {
diff --git a/src/stat.h b/src/stat.h
index 68a5c13..17b7fe1 100644
--- a/src/stat.h
+++ b/src/stat.h
@@ -138,12 +138,22 @@ struct bfs_stat {
int bfs_stat(int at_fd, const char *at_path, enum bfs_stat_flags flags, struct bfs_stat *buf);
/**
+ * Convert bfs_stat_flags to fstatat() flags.
+ */
+int bfs_fstatat_flags(enum bfs_stat_flags flags);
+
+/**
* Convert struct stat to struct bfs_stat.
*/
void bfs_stat_convert(struct bfs_stat *dest, const struct stat *src);
#if BFS_USE_STATX
/**
+ * Convert bfs_stat_flags to statx() flags.
+ */
+int bfs_statx_flags(enum bfs_stat_flags flags);
+
+/**
* Convert struct statx to struct bfs_stat.
*/
int bfs_statx_convert(struct bfs_stat *dest, const struct statx *src);