diff --git a/kernel/include/sys/Syscall.h b/kernel/include/sys/Syscall.h index c09ab9b8..6014b9f5 100644 --- a/kernel/include/sys/Syscall.h +++ b/kernel/include/sys/Syscall.h @@ -25,6 +25,7 @@ #define SYS_fstat 20 #define SYS_pstat 21 #define SYS_getdents 22 +#define SYS_stat 23 struct stat; struct pstat; @@ -57,4 +58,5 @@ void sys_waitpid(Context* context, long pid, int* wstatus, int options); void sys_access(Context* context, const char* path, int amode); void sys_fstat(Context* context, int fd, struct stat* buf); void sys_pstat(Context* context, long pid, struct pstat* buf); -void sys_getdents(Context* context, int fd, struct luna_dirent* buf, size_t count); \ No newline at end of file +void sys_getdents(Context* context, int fd, struct luna_dirent* buf, size_t count); +void sys_stat(Context* context, const char* path, struct stat* buf); \ No newline at end of file diff --git a/kernel/src/sys/stat.cpp b/kernel/src/sys/stat.cpp index b386f607..66ab8ca1 100644 --- a/kernel/src/sys/stat.cpp +++ b/kernel/src/sys/stat.cpp @@ -1,6 +1,7 @@ #include "fs/VFS.h" #include "interrupts/Context.h" #include "std/errno.h" +#include "std/stdlib.h" #include "sys/UserMemory.h" #include "thread/Scheduler.h" @@ -15,6 +16,21 @@ struct stat // FIXME: This struct is quite stubbed out. off_t st_size; }; +void do_stat(Context* context, VFS::Node* node, struct stat* buf) +{ + struct stat* kstat = obtain_user_ref(buf); + if (!kstat) + { + context->rax = -EFAULT; // FIXME: The manual doesn't say fstat can return EFAULT, but it seems logical here... + return; + } + kstat->st_ino = node->inode; + kstat->st_mode = (mode_t)node->type; + kstat->st_size = node->length; + release_user_ref(kstat); + context->rax = 0; +} + void sys_fstat(Context* context, int fd, struct stat* buf) { Task* current_task = Scheduler::current_task(); @@ -29,16 +45,24 @@ void sys_fstat(Context* context, int fd, struct stat* buf) context->rax = -EBADF; return; } - struct stat* kstat = obtain_user_ref(buf); - if (!kstat) + VFS::Node* node = file.node(); + return do_stat(context, node, buf); +} + +void sys_stat(Context* context, const char* path, struct stat* buf) +{ + char* kpath = strdup_from_user(path); + if (!kpath) { - context->rax = -EFAULT; // FIXME: The manual doesn't say fstat can return EFAULT, but it seems logical here... + context->rax = -EFAULT; return; } - VFS::Node* node = file.node(); - kstat->st_ino = node->inode; - kstat->st_mode = (mode_t)node->type; - kstat->st_size = node->length; - release_user_ref(kstat); - context->rax = 0; + VFS::Node* node = VFS::resolve_path(kpath); + kfree(kpath); + if (!node) + { + context->rax = -ENOENT; + return; + } + return do_stat(context, node, buf); } \ No newline at end of file diff --git a/libs/libc/include/sys/stat.h b/libs/libc/include/sys/stat.h index b8501fc4..18d1ca47 100644 --- a/libs/libc/include/sys/stat.h +++ b/libs/libc/include/sys/stat.h @@ -25,6 +25,9 @@ extern "C" /* Returns information about the file pointed to by fd in buf. */ int fstat(int fd, struct stat* buf); + /* Returns information about the file pointed at path in buf. */ + int stat(const char* pathname, struct stat* buf); + #ifdef __cplusplus } #endif diff --git a/libs/libc/include/sys/syscall.h b/libs/libc/include/sys/syscall.h index 4aee2f03..1be6f6bc 100644 --- a/libs/libc/include/sys/syscall.h +++ b/libs/libc/include/sys/syscall.h @@ -24,5 +24,6 @@ #define SYS_fstat 20 #define SYS_pstat 21 #define SYS_getdents 22 +#define SYS_stat 23 #endif \ No newline at end of file diff --git a/libs/libc/src/sys/stat.cpp b/libs/libc/src/sys/stat.cpp index 53b572f0..387e6b71 100644 --- a/libs/libc/src/sys/stat.cpp +++ b/libs/libc/src/sys/stat.cpp @@ -13,4 +13,9 @@ extern "C" { return (int)syscall(SYS_fstat, fd, buf); } + + int stat(const char* path, struct stat* buf) + { + return (int)syscall(SYS_stat, path, buf); + } } \ No newline at end of file diff --git a/libs/libc/src/syscall.cpp b/libs/libc/src/syscall.cpp index 3fae82ff..cb40f378 100644 --- a/libs/libc/src/syscall.cpp +++ b/libs/libc/src/syscall.cpp @@ -24,6 +24,7 @@ extern "C" long syscall(long number, ...) case SYS_munmap: case SYS_access: case SYS_fstat: + case SYS_stat: case SYS_pstat: case SYS_open: { arg arg0 = va_arg(ap, arg);