diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index c543b7eb..648af54d 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -128,9 +128,9 @@ namespace Kernel return ret.value(); } - long sys_stat(const char* path, struct stat* buf, int flags) + long sys_fstat(int fd, struct stat* buf) { - auto ret = Process::current().stat(path, buf, flags); + auto ret = Process::current().fstat(fd, buf); if (ret.is_error()) return -ret.error().get_error_code(); return 0; @@ -217,8 +217,8 @@ namespace Kernel case SYS_WAIT: ret = sys_wait((pid_t)arg1, (int*)arg2, (int)arg3); break; - case SYS_STAT: - ret = sys_stat((const char*)arg1, (struct stat*)arg2, (int)arg3); + case SYS_FSTAT: + ret = sys_fstat((int)arg1, (struct stat*)arg2); break; case SYS_SETENVP: ret = sys_setenvp((char**)arg1); diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h index ecee3d14..5fc7c9a9 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -22,7 +22,7 @@ __BEGIN_DECLS #define SYS_EXEC 15 #define SYS_REALLOC 16 #define SYS_WAIT 17 -#define SYS_STAT 18 +#define SYS_FSTAT 18 #define SYS_SETENVP 19 #define SYS_READ_DIR_ENTRIES 20 diff --git a/libc/sys/stat.cpp b/libc/sys/stat.cpp index 4996e8f7..c224ba06 100644 --- a/libc/sys/stat.cpp +++ b/libc/sys/stat.cpp @@ -1,14 +1,46 @@ +#include #include #include #include #include +int fstat(int fildes, struct stat* buf) +{ + return syscall(SYS_FSTAT, fildes, buf); +} + +int fstatat(int fd, const char* __restrict path, struct stat* __restrict buf, int flag) +{ + if (flag & ~AT_SYMLINK_NOFOLLOW) + { + errno = EINVAL; + return -1; + } + + int target = openat(fd, path, (flag & AT_SYMLINK_NOFOLLOW) ? O_NOFOLLOW : 0); + if (target == -1) + return -1; + int ret = fstat(target, buf); + close(target); + return ret; +} + int lstat(const char* __restrict path, struct stat* __restrict buf) { - return syscall(SYS_STAT, path, buf, O_RDONLY | O_NOFOLLOW); + int fd = open(path, O_SEARCH | O_NOFOLLOW); + if (fd == -1) + return -1; + int ret = fstat(fd, buf); + close(fd); + return ret; } int stat(const char* __restrict path, struct stat* __restrict buf) { - return syscall(SYS_STAT, path, buf, O_RDONLY); + int fd = open(path, O_SEARCH); + if (fd == -1) + return -1; + int ret = fstat(fd, buf); + close(fd); + return ret; } diff --git a/libc/unistd.cpp b/libc/unistd.cpp index 5fba2fec..5ee00978 100644 --- a/libc/unistd.cpp +++ b/libc/unistd.cpp @@ -149,12 +149,11 @@ long syscall(long syscall, ...) ret = Kernel::syscall(SYS_WAIT, pid, (uintptr_t)stat_loc, options); break; } - case SYS_STAT: + case SYS_FSTAT: { - const char* path = va_arg(args, const char*); + int fd = va_arg(args, int); struct stat* buf = va_arg(args, struct stat*); - int flags = va_arg(args, int); - ret = Kernel::syscall(SYS_STAT, (uintptr_t)path, (uintptr_t)buf, flags); + ret = Kernel::syscall(SYS_FSTAT, (uintptr_t)fd, (uintptr_t)buf); break; } case SYS_SETENVP: