mirror of https://git.musl-libc.org/git/musl
Browse Source
equivalent logic for fstat+O_PATH fallback and direct use of stat/lstat syscalls where appropriate is kept, now in the fstatat function. this change both improves functionality (now, fstatat forms equivalent to fstat/lstat/stat will work even on kernels too old to have the at functions) and localizes direct interfacing with the kernel stat structure to one file.master
4 changed files with 37 additions and 23 deletions
@ -1,9 +1,40 @@ |
|||
#define _BSD_SOURCE |
|||
#include <sys/stat.h> |
|||
#include <string.h> |
|||
#include <fcntl.h> |
|||
#include <errno.h> |
|||
#include "syscall.h" |
|||
|
|||
int fstatat(int fd, const char *restrict path, struct stat *restrict buf, int flag) |
|||
int fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag) |
|||
{ |
|||
return syscall(SYS_fstatat, fd, path, buf, flag); |
|||
int ret; |
|||
|
|||
if (flag==AT_EMPTY_PATH && fd>=0 && !*path) { |
|||
ret = __syscall(SYS_fstat, fd, st); |
|||
if (ret==-EBADF && __syscall(SYS_fcntl, fd, F_GETFD)>=0) { |
|||
ret = __syscall(SYS_fstatat, fd, path, st, flag); |
|||
if (ret==-EINVAL) { |
|||
char buf[15+3*sizeof(int)]; |
|||
__procfdname(buf, fd); |
|||
#ifdef SYS_stat |
|||
ret = __syscall(SYS_stat, buf, st); |
|||
#else |
|||
ret = __syscall(SYS_fstatat, AT_FDCWD, buf, st, 0); |
|||
#endif |
|||
} |
|||
} |
|||
} |
|||
#ifdef SYS_lstat |
|||
else if ((fd == AT_FDCWD || *path=='/') && flag==AT_SYMLINK_NOFOLLOW) |
|||
ret = __syscall(SYS_lstat, path, st); |
|||
#endif |
|||
#ifdef SYS_stat |
|||
else if ((fd == AT_FDCWD || *path=='/') && !flag) |
|||
ret = __syscall(SYS_stat, path, st); |
|||
#endif |
|||
else ret = __syscall(SYS_fstatat, fd, path, st, flag); |
|||
|
|||
return __syscall_ret(ret); |
|||
} |
|||
|
|||
weak_alias(fstatat, fstatat64); |
|||
|
|||
Loading…
Reference in new issue