summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDuncan Bellamy <dunk@denkimushi.com>2022-08-31 20:07:34 +0100
committerRich Felker <dalias@aerifal.cx>2024-02-24 12:27:09 -0500
commitb817541f1cfd38e4b81257b3215e276ea9d0fc61 (patch)
tree5e759b89743e278e0d152c8cee2f006026d74089 /src
parentd0ed307e6f79476bda12e531f7d30378a6167b65 (diff)
downloadmusl-b817541f1cfd38e4b81257b3215e276ea9d0fc61.tar.gz
add statx interface using syscall, fallback to fstatat
Diffstat (limited to 'src')
-rw-r--r--src/linux/statx.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/linux/statx.c b/src/linux/statx.c
new file mode 100644
index 00000000..4616bff4
--- /dev/null
+++ b/src/linux/statx.c
@@ -0,0 +1,42 @@
+#define _GNU_SOURCE
+#include <sys/stat.h>
+#include <string.h>
+#include <syscall.h>
+#include <sys/sysmacros.h>
+#include <errno.h>
+
+int statx(int dirfd, const char *restrict path, int flags, unsigned mask, struct statx *restrict stx)
+{
+ int ret = __syscall(SYS_statx, dirfd, path, flags, mask, stx);
+
+#ifndef SYS_fstatat
+ return __syscall_ret(ret);
+#endif
+
+ if (ret != -ENOSYS) return __syscall_ret(ret);
+
+ struct stat st;
+ ret = fstatat(dirfd, path, &st, flags);
+ if (ret) return ret;
+
+ stx->stx_dev_major = major(st.st_dev);
+ stx->stx_dev_minor = minor(st.st_dev);
+ stx->stx_ino = st.st_ino;
+ stx->stx_mode = st.st_mode;
+ stx->stx_nlink = st.st_nlink;
+ stx->stx_uid = st.st_uid;
+ stx->stx_gid = st.st_gid;
+ stx->stx_size = st.st_size;
+ stx->stx_blksize = st.st_blksize;
+ stx->stx_blocks = st.st_blocks;
+ stx->stx_atime.tv_sec = st.st_atim.tv_sec;
+ stx->stx_atime.tv_nsec = st.st_atim.tv_nsec;
+ stx->stx_mtime.tv_sec = st.st_mtim.tv_sec;
+ stx->stx_mtime.tv_nsec = st.st_mtim.tv_nsec;
+ stx->stx_ctime.tv_sec = st.st_ctim.tv_sec;
+ stx->stx_ctime.tv_nsec = st.st_ctim.tv_nsec;
+ stx->stx_btime = (struct statx_timestamp){.tv_sec=0, .tv_nsec=0};
+ stx->stx_mask = STATX_BASIC_STATS;
+
+ return 0;
+}