From e9edee7206645adcd48b91aae6ef4734f2e98254 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Tue, 26 Mar 2024 18:18:33 -0400 Subject: kernel: Add initial open() implementation Signed-off-by: Ian Moffett --- sys/include/sys/filedesc.h | 7 ++++++ sys/include/sys/syscall.h | 1 + sys/kern/kern_filedesc.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++ sys/kern/kern_syscall.c | 1 + 4 files changed, 71 insertions(+) (limited to 'sys') diff --git a/sys/include/sys/filedesc.h b/sys/include/sys/filedesc.h index 49d8d52..6eb500e 100644 --- a/sys/include/sys/filedesc.h +++ b/sys/include/sys/filedesc.h @@ -35,6 +35,10 @@ #include #include +#define O_RDONLY 0x00000 +#define O_WRONLY 0x00001 +#define O_RDWR 0x00002 + struct proc; struct filedesc { @@ -50,7 +54,10 @@ int fd_alloc(struct proc *td, struct filedesc **fd_out); struct filedesc *fd_from_fdnum(const struct proc *td, int fdno); void fd_close_fdnum(struct proc *td, int fdno); ssize_t write(int fd, const void *buf, size_t count); +int open(const char *pathname, int oflag); + uint64_t sys_write(struct syscall_args *args); +uint64_t sys_open(struct syscall_args *args); #endif #endif diff --git a/sys/include/sys/syscall.h b/sys/include/sys/syscall.h index e75b193..0f066e5 100644 --- a/sys/include/sys/syscall.h +++ b/sys/include/sys/syscall.h @@ -39,6 +39,7 @@ enum { SYS_exit = 1, SYS_write, + SYS_open, __MAX_SYSCALLS }; diff --git a/sys/kern/kern_filedesc.c b/sys/kern/kern_filedesc.c index 72d294d..c429125 100644 --- a/sys/kern/kern_filedesc.c +++ b/sys/kern/kern_filedesc.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -258,6 +259,44 @@ cleanup: return ret; } +/* + * Open a file and return a file descriptor. + * + * @pathname: File path. + * @oflag: Flags. + */ +int +open(const char *pathname, int oflag) +{ + struct vnode *vp; + struct filedesc *fd; + int status; + + /* + * Attempt to create a vnode and allocate a + * file descriptor + */ + if ((status = vfs_path_to_node(pathname, &vp)) != 0) { + return status; + } + if ((status = fd_alloc(this_td(), &fd)) != 0) { + return status; + } + + /* + * TODO: Handle more flags... For now we only support + * O_RDONLY, so deny other flags. + */ + if ((oflag & ~O_RDONLY) != 0){ + fd_close_fdnum(this_td(), fd->fdno); + return -EACCES; + } + + fd->vnode = vp; + fd->is_dir = (vp->type == VDIR); + return fd->fdno; +} + /* * arg0: int fd * arg1: const void *buf @@ -268,3 +307,26 @@ sys_write(struct syscall_args *args) { return write(args->arg0, (void *)args->arg1, args->arg2); } + +/* + * arg0: const char *pathname + * arg1: int oflag + */ +uint64_t +sys_open(struct syscall_args *args) +{ + char *pathbuf = dynalloc(sizeof(char) * PATH_MAX); + int ret; + + if (pathbuf == NULL) { + return -ENOMEM; + } + + if (copyinstr(args->arg0, pathbuf, PATH_MAX) != 0) { + invalid_uaddr(args->arg0); + } + + ret = open(pathbuf, args->arg1); + dynfree(pathbuf); + return ret; +} diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c index 2659448..dc37274 100644 --- a/sys/kern/kern_syscall.c +++ b/sys/kern/kern_syscall.c @@ -43,4 +43,5 @@ sys_exit(struct syscall_args *args) uint64_t(*g_syscall_table[__MAX_SYSCALLS])(struct syscall_args *args) = { sys_exit, sys_write, + sys_open, }; -- cgit v1.2.3