diff options
author | Ian Moffett <ian@osmora.org> | 2024-07-22 14:31:35 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2024-07-22 14:31:35 -0400 |
commit | 599ef07b89aa31c089398922ef65804f47f44b55 (patch) | |
tree | 595a84a66d105f049c82c545d35a7e08868b7e17 /sys | |
parent | 0393c8b5c2e229e022dcb63a8cd171ac10a23081 (diff) |
kernel: vfs_syscalls: Add sys_read()
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys')
-rw-r--r-- | sys/include/sys/syscall.h | 1 | ||||
-rw-r--r-- | sys/include/sys/vfs.h | 1 | ||||
-rw-r--r-- | sys/kern/kern_syscall.c | 1 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 83 |
4 files changed, 86 insertions, 0 deletions
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 <sys/types.h> #include <sys/systm.h> #include <sys/errno.h> +#include <sys/sio.h> #include <sys/filedesc.h> #include <sys/namei.h> #include <sys/proc.h> @@ -42,6 +43,24 @@ #include <string.h> /* + * 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. * * @fd_out: Pointer to allocated file descriptor output. @@ -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; +} |