aboutsummaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-03-26 18:18:33 -0400
committerIan Moffett <ian@osmora.org>2024-03-26 18:21:59 -0400
commite9edee7206645adcd48b91aae6ef4734f2e98254 (patch)
tree21c3088a527e4325f181ff5bddaafdf897e209e6 /sys/kern
parent4048b75fd22d5e7506681cc81feeed8930d5915d (diff)
kernel: Add initial open() implementation
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_filedesc.c62
-rw-r--r--sys/kern/kern_syscall.c1
2 files changed, 63 insertions, 0 deletions
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 <sys/errno.h>
#include <sys/system.h>
#include <sys/syslog.h>
+#include <sys/vfs.h>
#include <sys/vnode.h>
#include <vm/dynalloc.h>
#include <dev/vcons/vcons.h>
@@ -259,6 +260,44 @@ cleanup:
}
/*
+ * 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
* arg2: count
@@ -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,
};