summaryrefslogtreecommitdiffstats
path: root/src/stat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/stat.c')
-rw-r--r--src/stat.c53
1 files changed, 25 insertions, 28 deletions
diff --git a/src/stat.c b/src/stat.c
index 2f2743b..5a10a99 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -1,10 +1,10 @@
// Copyright © Tavian Barnes <tavianator@tavianator.com>
// SPDX-License-Identifier: 0BSD
+#include "prelude.h"
#include "stat.h"
#include "atomic.h"
#include "bfstd.h"
-#include "config.h"
#include "diag.h"
#include "sanity.h"
#include <errno.h>
@@ -13,7 +13,7 @@
#include <sys/stat.h>
#include <sys/types.h>
-#if BFS_USE_STATX && !BFS_HAS_LIBC_STATX
+#if BFS_USE_STATX && !BFS_HAS_STATX
# include <linux/stat.h>
# include <sys/syscall.h>
# include <unistd.h>
@@ -62,7 +62,7 @@ int bfs_fstatat_flags(enum bfs_stat_flags flags) {
ret |= AT_SYMLINK_NOFOLLOW;
}
-#if defined(AT_NO_AUTOMOUNT) && (!__GNU__ || __GLIBC_PREREQ(2, 35))
+#ifdef AT_NO_AUTOMOUNT
ret |= AT_NO_AUTOMOUNT;
#endif
@@ -99,23 +99,26 @@ void bfs_stat_convert(struct bfs_stat *dest, const struct stat *src) {
dest->rdev = src->st_rdev;
dest->mask |= BFS_STAT_RDEV;
-#if BSD
+#if BFS_HAS_ST_FLAGS
dest->attrs = src->st_flags;
dest->mask |= BFS_STAT_ATTRS;
#endif
- dest->atime = src->st_atim;
+ dest->atime = ST_ATIM(*src);
dest->mask |= BFS_STAT_ATIME;
- dest->ctime = src->st_ctim;
+ dest->ctime = ST_CTIM(*src);
dest->mask |= BFS_STAT_CTIME;
- dest->mtime = src->st_mtim;
+ dest->mtime = ST_MTIM(*src);
dest->mask |= BFS_STAT_MTIME;
-#if __APPLE__ || __FreeBSD__ || __NetBSD__
+#if BFS_HAS_ST_BIRTHTIM
dest->btime = src->st_birthtim;
dest->mask |= BFS_STAT_BTIME;
+#elif BFS_HAS_ST_BIRTHTIMESPEC
+ dest->btime = src->st_birthtimespec;
+ dest->mask |= BFS_STAT_BTIME;
#endif
}
@@ -137,7 +140,7 @@ static int bfs_stat_impl(int at_fd, const char *at_path, int at_flags, struct bf
* Wrapper for the statx() system call, which had no glibc wrapper prior to 2.28.
*/
static int bfs_statx(int at_fd, const char *at_path, int at_flags, unsigned int mask, struct statx *buf) {
-#if BFS_HAS_LIBC_STATX
+#if BFS_HAS_STATX
int ret = statx(at_fd, at_path, at_flags, mask, buf);
#else
int ret = syscall(SYS_statx, at_fd, at_path, at_flags, mask, buf);
@@ -294,27 +297,21 @@ int bfs_stat(int at_fd, const char *at_path, enum bfs_stat_flags flags, struct b
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
-#if defined(AT_EMPTY_PATH) && !__GNU__
- 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, buf);
- if (ret != 0 && errno == EINVAL) {
- store(&has_at_ep, false, relaxed);
- } else {
- return ret;
- }
- }
-#endif
-
- struct stat statbuf;
- if (fstat(at_fd, &statbuf) == 0) {
- bfs_stat_convert(buf, &statbuf);
- return 0;
- } else {
+#if BFS_USE_STATX
+ // If we have statx(), use it with AT_EMPTY_PATH for its extra features
+ at_flags |= AT_EMPTY_PATH;
+ return bfs_stat_explicit(at_fd, "", at_flags, buf);
+#else
+ // Otherwise, just use fstat() rather than fstatat(at_fd, ""), to save
+ // the kernel the trouble of copying in the empty string
+ struct stat sb;
+ if (fstat(at_fd, &sb) != 0) {
return -1;
}
+
+ bfs_stat_convert(buf, &sb);
+ return 0;
+#endif
}
const struct timespec *bfs_stat_time(const struct bfs_stat *buf, enum bfs_stat_field field) {