diff options
Diffstat (limited to 'src/stat')
-rw-r--r-- | src/stat/__xstat.c | 7 | ||||
-rw-r--r-- | src/stat/fchmodat.c | 19 | ||||
-rw-r--r-- | src/stat/fstat.c | 18 | ||||
-rw-r--r-- | src/stat/fstatat.c | 151 | ||||
-rw-r--r-- | src/stat/lstat.c | 9 | ||||
-rw-r--r-- | src/stat/stat.c | 9 | ||||
-rw-r--r-- | src/stat/statvfs.c | 6 | ||||
-rw-r--r-- | src/stat/utimensat.c | 43 |
8 files changed, 203 insertions, 59 deletions
diff --git a/src/stat/__xstat.c b/src/stat/__xstat.c index f6303430..b4560df7 100644 --- a/src/stat/__xstat.c +++ b/src/stat/__xstat.c @@ -1,5 +1,7 @@ #include <sys/stat.h> +#if !_REDIR_TIME64 + int __fxstat(int ver, int fd, struct stat *buf) { return fstat(fd, buf); @@ -20,10 +22,7 @@ int __xstat(int ver, const char *path, struct stat *buf) return stat(path, buf); } -weak_alias(__fxstat, __fxstat64); -weak_alias(__fxstatat, __fxstatat64); -weak_alias(__lxstat, __lxstat64); -weak_alias(__xstat, __xstat64); +#endif int __xmknod(int ver, const char *path, mode_t mode, dev_t *dev) { diff --git a/src/stat/fchmodat.c b/src/stat/fchmodat.c index be61bdf3..92c9d1b0 100644 --- a/src/stat/fchmodat.c +++ b/src/stat/fchmodat.c @@ -5,17 +5,20 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag) { - if (!flag) return syscall(SYS_fchmodat, fd, path, mode, flag); + if (!flag) return syscall(SYS_fchmodat, fd, path, mode); + + int ret = __syscall(SYS_fchmodat2, fd, path, mode, flag); + if (ret != -ENOSYS) return __syscall_ret(ret); if (flag != AT_SYMLINK_NOFOLLOW) return __syscall_ret(-EINVAL); struct stat st; - int ret, fd2; + int fd2; char proc[15+3*sizeof(int)]; - if ((ret = __syscall(SYS_fstatat, fd, path, &st, flag))) - return __syscall_ret(ret); + if (fstatat(fd, path, &st, flag)) + return -1; if (S_ISLNK(st.st_mode)) return __syscall_ret(-EOPNOTSUPP); @@ -26,12 +29,12 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag) } __procfdname(proc, fd2); - ret = __syscall(SYS_fstatat, AT_FDCWD, proc, &st, 0); + ret = stat(proc, &st); if (!ret) { - if (S_ISLNK(st.st_mode)) ret = -EOPNOTSUPP; - else ret = __syscall(SYS_fchmodat, AT_FDCWD, proc, mode); + if (S_ISLNK(st.st_mode)) ret = __syscall_ret(-EOPNOTSUPP); + else ret = syscall(SYS_fchmodat, AT_FDCWD, proc, mode); } __syscall(SYS_close, fd2); - return __syscall_ret(ret); + return ret; } diff --git a/src/stat/fstat.c b/src/stat/fstat.c index 4f13f4f0..fd28b8ac 100644 --- a/src/stat/fstat.c +++ b/src/stat/fstat.c @@ -1,21 +1,13 @@ +#define _BSD_SOURCE #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #include "syscall.h" -int fstat(int fd, struct stat *st) +int __fstat(int fd, struct stat *st) { - int ret = __syscall(SYS_fstat, fd, st); - if (ret != -EBADF || __syscall(SYS_fcntl, fd, F_GETFD) < 0) - return __syscall_ret(ret); - - char buf[15+3*sizeof(int)]; - __procfdname(buf, fd); -#ifdef SYS_stat - return syscall(SYS_stat, buf, st); -#else - return syscall(SYS_fstatat, AT_FDCWD, buf, st, 0); -#endif + if (fd<0) return __syscall_ret(-EBADF); + return __fstatat(fd, "", st, AT_EMPTY_PATH); } -weak_alias(fstat, fstat64); +weak_alias(__fstat, fstat); diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c index 582db442..9eed063b 100644 --- a/src/stat/fstatat.c +++ b/src/stat/fstatat.c @@ -1,9 +1,154 @@ +#define _BSD_SOURCE #include <sys/stat.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <stdint.h> +#include <sys/sysmacros.h> #include "syscall.h" -int fstatat(int fd, const char *restrict path, struct stat *restrict buf, int flag) +struct statx { + uint32_t stx_mask; + uint32_t stx_blksize; + uint64_t stx_attributes; + uint32_t stx_nlink; + uint32_t stx_uid; + uint32_t stx_gid; + uint16_t stx_mode; + uint16_t pad1; + uint64_t stx_ino; + uint64_t stx_size; + uint64_t stx_blocks; + uint64_t stx_attributes_mask; + struct { + int64_t tv_sec; + uint32_t tv_nsec; + int32_t pad; + } stx_atime, stx_btime, stx_ctime, stx_mtime; + uint32_t stx_rdev_major; + uint32_t stx_rdev_minor; + uint32_t stx_dev_major; + uint32_t stx_dev_minor; + uint64_t spare[14]; +}; + +static int fstatat_statx(int fd, const char *restrict path, struct stat *restrict st, int flag) +{ + struct statx stx; + + flag |= AT_NO_AUTOMOUNT; + int ret = __syscall(SYS_statx, fd, path, flag, 0x7ff, &stx); + if (ret) return ret; + + *st = (struct stat){ + .st_dev = makedev(stx.stx_dev_major, stx.stx_dev_minor), + .st_ino = stx.stx_ino, + .st_mode = stx.stx_mode, + .st_nlink = stx.stx_nlink, + .st_uid = stx.stx_uid, + .st_gid = stx.stx_gid, + .st_rdev = makedev(stx.stx_rdev_major, stx.stx_rdev_minor), + .st_size = stx.stx_size, + .st_blksize = stx.stx_blksize, + .st_blocks = stx.stx_blocks, + .st_atim.tv_sec = stx.stx_atime.tv_sec, + .st_atim.tv_nsec = stx.stx_atime.tv_nsec, + .st_mtim.tv_sec = stx.stx_mtime.tv_sec, + .st_mtim.tv_nsec = stx.stx_mtime.tv_nsec, + .st_ctim.tv_sec = stx.stx_ctime.tv_sec, + .st_ctim.tv_nsec = stx.stx_ctime.tv_nsec, +#if _REDIR_TIME64 + .__st_atim32.tv_sec = stx.stx_atime.tv_sec, + .__st_atim32.tv_nsec = stx.stx_atime.tv_nsec, + .__st_mtim32.tv_sec = stx.stx_mtime.tv_sec, + .__st_mtim32.tv_nsec = stx.stx_mtime.tv_nsec, + .__st_ctim32.tv_sec = stx.stx_ctime.tv_sec, + .__st_ctim32.tv_nsec = stx.stx_ctime.tv_nsec, +#endif + }; + return 0; +} + +#ifdef SYS_fstatat + +#include "kstat.h" + +static int fstatat_kstat(int fd, const char *restrict path, struct stat *restrict st, int flag) +{ + int ret; + struct kstat kst; + + if (flag==AT_EMPTY_PATH && fd>=0 && !*path) { + ret = __syscall(SYS_fstat, fd, &kst); + if (ret==-EBADF && __syscall(SYS_fcntl, fd, F_GETFD)>=0) { + ret = __syscall(SYS_fstatat, fd, path, &kst, flag); + if (ret==-EINVAL) { + char buf[15+3*sizeof(int)]; + __procfdname(buf, fd); +#ifdef SYS_stat + ret = __syscall(SYS_stat, buf, &kst); +#else + ret = __syscall(SYS_fstatat, AT_FDCWD, buf, &kst, 0); +#endif + } + } + } +#ifdef SYS_lstat + else if ((fd == AT_FDCWD || *path=='/') && flag==AT_SYMLINK_NOFOLLOW) + ret = __syscall(SYS_lstat, path, &kst); +#endif +#ifdef SYS_stat + else if ((fd == AT_FDCWD || *path=='/') && !flag) + ret = __syscall(SYS_stat, path, &kst); +#endif + else ret = __syscall(SYS_fstatat, fd, path, &kst, flag); + + if (ret) return ret; + + *st = (struct stat){ + .st_dev = kst.st_dev, + .st_ino = kst.st_ino, + .st_mode = kst.st_mode, + .st_nlink = kst.st_nlink, + .st_uid = kst.st_uid, + .st_gid = kst.st_gid, + .st_rdev = kst.st_rdev, + .st_size = kst.st_size, + .st_blksize = kst.st_blksize, + .st_blocks = kst.st_blocks, + .st_atim.tv_sec = kst.st_atime_sec, + .st_atim.tv_nsec = kst.st_atime_nsec, + .st_mtim.tv_sec = kst.st_mtime_sec, + .st_mtim.tv_nsec = kst.st_mtime_nsec, + .st_ctim.tv_sec = kst.st_ctime_sec, + .st_ctim.tv_nsec = kst.st_ctime_nsec, +#if _REDIR_TIME64 + .__st_atim32.tv_sec = kst.st_atime_sec, + .__st_atim32.tv_nsec = kst.st_atime_nsec, + .__st_mtim32.tv_sec = kst.st_mtime_sec, + .__st_mtim32.tv_nsec = kst.st_mtime_nsec, + .__st_ctim32.tv_sec = kst.st_ctime_sec, + .__st_ctim32.tv_nsec = kst.st_ctime_nsec, +#endif + }; + + return 0; +} +#endif + +int __fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag) { - return syscall(SYS_fstatat, fd, path, buf, flag); + int ret; +#ifdef SYS_fstatat + if (sizeof((struct kstat){0}.st_atime_sec) < sizeof(time_t)) { + ret = fstatat_statx(fd, path, st, flag); + if (ret!=-ENOSYS) return __syscall_ret(ret); + } + ret = fstatat_kstat(fd, path, st, flag); +#else + ret = fstatat_statx(fd, path, st, flag); +#endif + return __syscall_ret(ret); } -weak_alias(fstatat, fstatat64); +weak_alias(__fstatat, fstatat); diff --git a/src/stat/lstat.c b/src/stat/lstat.c index 5b89f290..6822fcae 100644 --- a/src/stat/lstat.c +++ b/src/stat/lstat.c @@ -1,14 +1,7 @@ #include <sys/stat.h> #include <fcntl.h> -#include "syscall.h" int lstat(const char *restrict path, struct stat *restrict buf) { -#ifdef SYS_lstat - return syscall(SYS_lstat, path, buf); -#else - return syscall(SYS_fstatat, AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW); -#endif + return fstatat(AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW); } - -weak_alias(lstat, lstat64); diff --git a/src/stat/stat.c b/src/stat/stat.c index 0bec9d6f..23570e7a 100644 --- a/src/stat/stat.c +++ b/src/stat/stat.c @@ -1,14 +1,7 @@ #include <sys/stat.h> #include <fcntl.h> -#include "syscall.h" int stat(const char *restrict path, struct stat *restrict buf) { -#ifdef SYS_stat - return syscall(SYS_stat, path, buf); -#else - return syscall(SYS_fstatat, AT_FDCWD, path, buf, 0); -#endif + return fstatat(AT_FDCWD, path, buf, 0); } - -weak_alias(stat, stat64); diff --git a/src/stat/statvfs.c b/src/stat/statvfs.c index f65d1b54..bc12da8b 100644 --- a/src/stat/statvfs.c +++ b/src/stat/statvfs.c @@ -39,6 +39,7 @@ static void fixup(struct statvfs *out, const struct statfs *in) out->f_fsid = in->f_fsid.__val[0]; out->f_flag = in->f_flags; out->f_namemax = in->f_namelen; + out->f_type = in->f_type; } int statvfs(const char *restrict path, struct statvfs *restrict buf) @@ -56,8 +57,3 @@ int fstatvfs(int fd, struct statvfs *buf) fixup(buf, &kbuf); return 0; } - -weak_alias(statvfs, statvfs64); -weak_alias(statfs, statfs64); -weak_alias(fstatvfs, fstatvfs64); -weak_alias(fstatfs, fstatfs64); diff --git a/src/stat/utimensat.c b/src/stat/utimensat.c index 159c8be3..730723a9 100644 --- a/src/stat/utimensat.c +++ b/src/stat/utimensat.c @@ -4,28 +4,51 @@ #include <errno.h> #include "syscall.h" +#define IS32BIT(x) !((x)+0x80000000ULL>>32) +#define NS_SPECIAL(ns) ((ns)==UTIME_NOW || (ns)==UTIME_OMIT) + int utimensat(int fd, const char *path, const struct timespec times[2], int flags) { - int r = __syscall(SYS_utimensat, fd, path, times, flags); + int r; + if (times && times[0].tv_nsec==UTIME_NOW && times[1].tv_nsec==UTIME_NOW) + times = 0; +#ifdef SYS_utimensat_time64 + r = -ENOSYS; + time_t s0=0, s1=0; + long ns0=0, ns1=0; + if (times) { + ns0 = times[0].tv_nsec; + ns1 = times[1].tv_nsec; + if (!NS_SPECIAL(ns0)) s0 = times[0].tv_sec; + if (!NS_SPECIAL(ns1)) s1 = times[1].tv_sec; + } + if (SYS_utimensat == SYS_utimensat_time64 || !IS32BIT(s0) || !IS32BIT(s1)) + r = __syscall(SYS_utimensat_time64, fd, path, times ? + ((long long[]){s0, ns0, s1, ns1}) : 0, flags); + if (SYS_utimensat == SYS_utimensat_time64 || r!=-ENOSYS) + return __syscall_ret(r); + if (!IS32BIT(s0) || !IS32BIT(s1)) + return __syscall_ret(-ENOTSUP); + r = __syscall(SYS_utimensat, fd, path, + times ? ((long[]){s0, ns0, s1, ns1}) : 0, flags); +#else + r = __syscall(SYS_utimensat, fd, path, times, flags); +#endif + #ifdef SYS_futimesat if (r != -ENOSYS || flags) return __syscall_ret(r); - struct timeval *tv = 0, tmp[2]; + long *tv=0, tmp[4]; if (times) { int i; tv = tmp; for (i=0; i<2; i++) { if (times[i].tv_nsec >= 1000000000ULL) { - if (times[i].tv_nsec == UTIME_NOW && - times[1-i].tv_nsec == UTIME_NOW) { - tv = 0; - break; - } - if (times[i].tv_nsec == UTIME_OMIT) + if (NS_SPECIAL(times[i].tv_nsec)) return __syscall_ret(-ENOSYS); return __syscall_ret(-EINVAL); } - tmp[i].tv_sec = times[i].tv_sec; - tmp[i].tv_usec = times[i].tv_nsec / 1000; + tmp[2*i+0] = times[i].tv_sec; + tmp[2*i+1] = times[i].tv_nsec / 1000; } } |