summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/include/sys/filedesc.h7
-rw-r--r--sys/include/sys/syscall.h1
-rw-r--r--sys/kern/kern_filedesc.c62
-rw-r--r--sys/kern/kern_syscall.c1
4 files changed, 71 insertions, 0 deletions
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 <sys/syscall.h>
#include <sys/types.h>
+#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 <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,
};