aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/include/sys/syscall.h1
-rw-r--r--sys/include/sys/vfs.h1
-rw-r--r--sys/kern/kern_syscall.c1
-rw-r--r--sys/kern/vfs_syscalls.c83
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;
+}