diff --git a/kernel/include/sys/Syscall.h b/kernel/include/sys/Syscall.h index 2859fcd6..c1a71a52 100644 --- a/kernel/include/sys/Syscall.h +++ b/kernel/include/sys/Syscall.h @@ -22,6 +22,9 @@ #define SYS_fork 17 #define SYS_waitpid 18 #define SYS_access 19 +#define SYS_fstat 20 + +struct stat; namespace Syscall { @@ -47,4 +50,5 @@ void sys_clock(Context* context); void sys_mkdir(Context* context, const char* filename); void sys_fork(Context* context); void sys_waitpid(Context* context, long pid, int* wstatus, int options); -void sys_access(Context* context, const char* path, int amode); \ No newline at end of file +void sys_access(Context* context, const char* path, int amode); +void sys_fstat(Context* context, int fd, struct stat* buf); diff --git a/kernel/src/sys/Syscall.cpp b/kernel/src/sys/Syscall.cpp index 2a236e93..3c44c500 100644 --- a/kernel/src/sys/Syscall.cpp +++ b/kernel/src/sys/Syscall.cpp @@ -31,7 +31,8 @@ void Syscall::entry(Context* context) case SYS_fork: sys_fork(context); break; case SYS_waitpid: sys_waitpid(context, (long)context->rdi, (int*)context->rsi, (int)context->rdx); break; case SYS_access: sys_access(context, (const char*)context->rdi, (int)context->rsi); break; + case SYS_fstat: sys_fstat(context, (int)context->rdi, (struct stat*)context->rsi); break; default: context->rax = -ENOSYS; break; } VMM::exit_syscall_context(); -} \ No newline at end of file +} diff --git a/kernel/src/sys/stat.cpp b/kernel/src/sys/stat.cpp new file mode 100644 index 00000000..b386f607 --- /dev/null +++ b/kernel/src/sys/stat.cpp @@ -0,0 +1,44 @@ +#include "fs/VFS.h" +#include "interrupts/Context.h" +#include "std/errno.h" +#include "sys/UserMemory.h" +#include "thread/Scheduler.h" + +typedef unsigned long off_t; +typedef unsigned short mode_t; +typedef unsigned long ino_t; + +struct stat // FIXME: This struct is quite stubbed out. +{ + ino_t st_ino; + mode_t st_mode; + off_t st_size; +}; + +void sys_fstat(Context* context, int fd, struct stat* buf) +{ + Task* current_task = Scheduler::current_task(); + if (fd < 0 || fd >= TASK_MAX_FDS) + { + context->rax = -EBADF; + return; + } + Descriptor& file = current_task->files[fd]; + if (!file.is_open()) + { + context->rax = -EBADF; + return; + } + 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; + } + 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; +} \ No newline at end of file diff --git a/libs/libc/include/luna/vfs.h b/libs/libc/include/luna/vfs.h new file mode 100644 index 00000000..3cc260a9 --- /dev/null +++ b/libs/libc/include/luna/vfs.h @@ -0,0 +1,8 @@ +#ifndef _LUNA_VFS_H +#define _LUNA_VFS_H + +#define __VFS_FILE 0x0 +#define __VFS_DIRECTORY 0x1 +#define __VFS_DEVICE 0x2 + +#endif \ No newline at end of file diff --git a/libs/libc/include/sys/stat.h b/libs/libc/include/sys/stat.h index c7813d10..324a91b4 100644 --- a/libs/libc/include/sys/stat.h +++ b/libs/libc/include/sys/stat.h @@ -1,8 +1,18 @@ #ifndef _SYS_STAT_H #define _SYS_STAT_H +#include #include +struct stat // FIXME: This struct is quite stubbed out. +{ + ino_t st_ino; + mode_t st_mode; + off_t st_size; +}; + +#define S_ISDIR(mode) (((mode)&0xf) == __VFS_DIRECTORY) + #ifdef __cplusplus extern "C" { @@ -11,6 +21,9 @@ extern "C" /* Creates a new directory at the path pathname. FIXME: For now, mode is ignored. */ int mkdir(const char* pathname, mode_t mode); + /* Returns information about the file pointed to by fd in buf. */ + int fstat(int fd, struct stat* buf); + #ifdef __cplusplus } #endif diff --git a/libs/libc/include/sys/syscall.h b/libs/libc/include/sys/syscall.h index 2fa9b98e..5f00f903 100644 --- a/libs/libc/include/sys/syscall.h +++ b/libs/libc/include/sys/syscall.h @@ -21,5 +21,6 @@ #define SYS_fork 17 #define SYS_waitpid 18 #define SYS_access 19 +#define SYS_fstat 20 #endif \ No newline at end of file diff --git a/libs/libc/src/sys/stat.cpp b/libs/libc/src/sys/stat.cpp index 9249739d..53b572f0 100644 --- a/libs/libc/src/sys/stat.cpp +++ b/libs/libc/src/sys/stat.cpp @@ -8,4 +8,9 @@ extern "C" { return (int)syscall(SYS_mkdir, pathname); } + + int fstat(int fd, struct stat* buf) + { + return (int)syscall(SYS_fstat, fd, buf); + } } \ No newline at end of file diff --git a/libs/libc/src/syscall.cpp b/libs/libc/src/syscall.cpp index f8af3eee..0f7a363b 100644 --- a/libs/libc/src/syscall.cpp +++ b/libs/libc/src/syscall.cpp @@ -23,6 +23,7 @@ extern "C" long syscall(long number, ...) case SYS_sleep: result = __luna_syscall1(number, va_arg(ap, arg)); break; case SYS_munmap: case SYS_access: + case SYS_fstat: case SYS_open: { arg arg0 = va_arg(ap, arg); arg arg1 = va_arg(ap, arg);