github.com/afumu/libc@v0.0.6/musl/src/stat/fstatat.c (about) 1 #define _BSD_SOURCE 2 #include <sys/stat.h> 3 #include <string.h> 4 #include <fcntl.h> 5 #include <errno.h> 6 #include <stdint.h> 7 #include <sys/sysmacros.h> 8 #include "syscall.h" 9 #include "kstat.h" 10 11 struct statx { 12 uint32_t stx_mask; 13 uint32_t stx_blksize; 14 uint64_t stx_attributes; 15 uint32_t stx_nlink; 16 uint32_t stx_uid; 17 uint32_t stx_gid; 18 uint16_t stx_mode; 19 uint16_t pad1; 20 uint64_t stx_ino; 21 uint64_t stx_size; 22 uint64_t stx_blocks; 23 uint64_t stx_attributes_mask; 24 struct { 25 int64_t tv_sec; 26 uint32_t tv_nsec; 27 int32_t pad; 28 } stx_atime, stx_btime, stx_ctime, stx_mtime; 29 uint32_t stx_rdev_major; 30 uint32_t stx_rdev_minor; 31 uint32_t stx_dev_major; 32 uint32_t stx_dev_minor; 33 uint64_t spare[14]; 34 }; 35 36 static int fstatat_statx(int fd, const char *restrict path, struct stat *restrict st, int flag) 37 { 38 struct statx stx; 39 40 int ret = __syscall(SYS_statx, fd, path, flag, 0x7ff, &stx); 41 if (ret) return ret; 42 43 *st = (struct stat){ 44 .st_dev = makedev(stx.stx_dev_major, stx.stx_dev_minor), 45 .st_ino = stx.stx_ino, 46 .st_mode = stx.stx_mode, 47 .st_nlink = stx.stx_nlink, 48 .st_uid = stx.stx_uid, 49 .st_gid = stx.stx_gid, 50 .st_rdev = makedev(stx.stx_rdev_major, stx.stx_rdev_minor), 51 .st_size = stx.stx_size, 52 .st_blksize = stx.stx_blksize, 53 .st_blocks = stx.stx_blocks, 54 .st_atim.tv_sec = stx.stx_atime.tv_sec, 55 .st_atim.tv_nsec = stx.stx_atime.tv_nsec, 56 .st_mtim.tv_sec = stx.stx_mtime.tv_sec, 57 .st_mtim.tv_nsec = stx.stx_mtime.tv_nsec, 58 .st_ctim.tv_sec = stx.stx_ctime.tv_sec, 59 .st_ctim.tv_nsec = stx.stx_ctime.tv_nsec, 60 #if _REDIR_TIME64 61 .__st_atim32.tv_sec = stx.stx_atime.tv_sec, 62 .__st_atim32.tv_nsec = stx.stx_atime.tv_nsec, 63 .__st_mtim32.tv_sec = stx.stx_mtime.tv_sec, 64 .__st_mtim32.tv_nsec = stx.stx_mtime.tv_nsec, 65 .__st_ctim32.tv_sec = stx.stx_ctime.tv_sec, 66 .__st_ctim32.tv_nsec = stx.stx_ctime.tv_nsec, 67 #endif 68 }; 69 return 0; 70 } 71 72 static int fstatat_kstat(int fd, const char *restrict path, struct stat *restrict st, int flag) 73 { 74 int ret; 75 struct kstat kst; 76 77 if (flag==AT_EMPTY_PATH && fd>=0 && !*path) { 78 ret = __syscall(SYS_fstat, fd, &kst); 79 if (ret==-EBADF && __syscall(SYS_fcntl, fd, F_GETFD)>=0) { 80 ret = __syscall(SYS_fstatat, fd, path, &kst, flag); 81 if (ret==-EINVAL) { 82 char buf[15+3*sizeof(int)]; 83 __procfdname(buf, fd); 84 #ifdef SYS_stat 85 ret = __syscall(SYS_stat, buf, &kst); 86 #else 87 ret = __syscall(SYS_fstatat, AT_FDCWD, buf, &kst, 0); 88 #endif 89 } 90 } 91 } 92 #ifdef SYS_lstat 93 else if ((fd == AT_FDCWD || *path=='/') && flag==AT_SYMLINK_NOFOLLOW) 94 ret = __syscall(SYS_lstat, path, &kst); 95 #endif 96 #ifdef SYS_stat 97 else if ((fd == AT_FDCWD || *path=='/') && !flag) 98 ret = __syscall(SYS_stat, path, &kst); 99 #endif 100 else ret = __syscall(SYS_fstatat, fd, path, &kst, flag); 101 102 if (ret) return ret; 103 104 *st = (struct stat){ 105 .st_dev = kst.st_dev, 106 .st_ino = kst.st_ino, 107 .st_mode = kst.st_mode, 108 .st_nlink = kst.st_nlink, 109 .st_uid = kst.st_uid, 110 .st_gid = kst.st_gid, 111 .st_rdev = kst.st_rdev, 112 .st_size = kst.st_size, 113 .st_blksize = kst.st_blksize, 114 .st_blocks = kst.st_blocks, 115 .st_atim.tv_sec = kst.st_atime_sec, 116 .st_atim.tv_nsec = kst.st_atime_nsec, 117 .st_mtim.tv_sec = kst.st_mtime_sec, 118 .st_mtim.tv_nsec = kst.st_mtime_nsec, 119 .st_ctim.tv_sec = kst.st_ctime_sec, 120 .st_ctim.tv_nsec = kst.st_ctime_nsec, 121 #if _REDIR_TIME64 122 .__st_atim32.tv_sec = kst.st_atime_sec, 123 .__st_atim32.tv_nsec = kst.st_atime_nsec, 124 .__st_mtim32.tv_sec = kst.st_mtime_sec, 125 .__st_mtim32.tv_nsec = kst.st_mtime_nsec, 126 .__st_ctim32.tv_sec = kst.st_ctime_sec, 127 .__st_ctim32.tv_nsec = kst.st_ctime_nsec, 128 #endif 129 }; 130 131 return 0; 132 } 133 134 int fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag) 135 { 136 int ret; 137 if (sizeof((struct kstat){0}.st_atime_sec) < sizeof(time_t)) { 138 ret = fstatat_statx(fd, path, st, flag); 139 if (ret!=-ENOSYS) return __syscall_ret(ret); 140 } 141 ret = fstatat_kstat(fd, path, st, flag); 142 return __syscall_ret(ret); 143 } 144 145 #if !_REDIR_TIME64 146 weak_alias(fstatat, fstatat64); 147 #endif