From 599ef07b89aa31c089398922ef65804f47f44b55 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Mon, 22 Jul 2024 14:31:35 -0400 Subject: kernel: vfs_syscalls: Add sys_read() Signed-off-by: Ian Moffett --- sys/include/sys/syscall.h | 1 + sys/include/sys/vfs.h | 1 + sys/kern/kern_syscall.c | 1 + sys/kern/vfs_syscalls.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) (limited to 'sys') diff --git a/sys/include/sys/syscall.h b/sys/include/sys/syscall.h index e4a72f2..9aa96e7 100644 --- a/sys/include/sys/syscall.h +++ b/sys/include/sys/syscall.h @@ -38,6 +38,7 @@ #define SYS_none 0 #define SYS_exit 1 #define SYS_open 2 +#define SYS_read 3 #if defined(_KERNEL) /* Syscall return value and arg type */ diff --git a/sys/include/sys/vfs.h b/sys/include/sys/vfs.h index 16c7795..52d35f3 100644 --- a/sys/include/sys/vfs.h +++ b/sys/include/sys/vfs.h @@ -36,6 +36,7 @@ #if defined(_KERNEL) scret_t sys_open(struct syscall_args *scargs); +scret_t sys_read(struct syscall_args *scargs); #endif /* _KERNEL */ #endif /* !_SYS_VFS_H_ */ diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c index 2c81d2c..416a8ec 100644 --- a/sys/kern/kern_syscall.c +++ b/sys/kern/kern_syscall.c @@ -36,6 +36,7 @@ scret_t(*g_sctab[])(struct syscall_args *) = { NULL, /* SYS_none */ sys_exit, /* SYS_exit */ sys_open, /* SYS_open */ + sys_read, /* SYS_read */ }; const size_t MAX_SYSCALLS = NELEM(g_sctab); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index c2ae580..371c1a5 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,24 @@ #include #include +/* + * Fetch a file descriptor from a file descriptor + * number. + * + * @fdno: File descriptor to fetch + */ +static struct filedesc * +fd_get(int fdno) +{ + struct proc *td = this_td(); + + if (fdno < 0 || fdno > PROC_MAX_FILEDES) { + return NULL; + } + + return td->fds[fdno]; +} + /* * Allocate a file descriptor. * @@ -118,3 +137,67 @@ sys_open(struct syscall_args *scargs) filedes->vp = nd.vp; return filedes->fdno; } + +/* + * arg0: fd + * arg1: buf + * arg2: count + */ +scret_t +sys_read(struct syscall_args *scargs) +{ + int fd; + char *buf, *kbuf = NULL; + size_t count; + struct filedesc *filedes; + struct sio_txn sio; + scret_t retval = 0; + + fd = scargs->arg0; + buf = (char *)scargs->arg1; + count = scargs->arg2; + + if (count > SSIZE_MAX) { + retval = -EINVAL; + goto done; + } + + filedes = fd_get(fd); + kbuf = dynalloc(count); + + if (kbuf == NULL) { + retval = -ENOMEM; + goto done; + } + + if (filedes == NULL) { + retval = -EBADF; + goto done; + } + + if (filedes->is_dir) { + retval = -EISDIR; + goto done; + } + + sio.len = count; + sio.buf = kbuf; + sio.offset = filedes->offset; + + if ((count = vfs_vop_read(filedes->vp, &sio)) < 0) { + retval = -EIO; + goto done; + } + + if (copyout(kbuf, buf, count) < 0) { + retval = -EFAULT; + goto done; + } + + retval = count; +done: + if (kbuf != NULL) { + dynfree(kbuf); + } + return retval; +} -- cgit v1.2.3