diff options
author | Ian Moffett <ian@osmora.org> | 2025-10-15 13:01:39 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-10-15 13:01:39 -0400 |
commit | b9e8dbfd957337ff064c4cb8bb5bd7b23ac88b8d (patch) | |
tree | 888d6e5c69a0178c4b00e11c80fdd96c22dfa53a | |
parent | 9970641f0ee8c80be660e2b49e63f6ed4e3b8859 (diff) |
kern: Add SYS_read system call for file I/O
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r-- | src/sys/compat/unix/os/os_filedesc.c | 33 | ||||
-rw-r--r-- | src/sys/include/compat/unix/syscall.h | 8 | ||||
-rw-r--r-- | src/sys/include/os/filedesc.h | 12 | ||||
-rw-r--r-- | src/sys/include/sys/syscall.h | 1 | ||||
-rw-r--r-- | src/sys/os/os_filedes.c | 34 |
5 files changed, 87 insertions, 1 deletions
diff --git a/src/sys/compat/unix/os/os_filedesc.c b/src/sys/compat/unix/os/os_filedesc.c index 48ea6be..673701f 100644 --- a/src/sys/compat/unix/os/os_filedesc.c +++ b/src/sys/compat/unix/os/os_filedesc.c @@ -33,6 +33,7 @@ #include <sys/mount.h> #include <sys/errno.h> #include <sys/types.h> +#include <os/kalloc.h> #include <os/systm.h> #include <os/filedesc.h> #include <compat/unix/syscall.h> @@ -105,3 +106,35 @@ sys_mount(struct syscall_args *scargs) args.fstype = fstype; return kmount(&args, u_mountflags); } + +/* + * ARG0: fd + * ARG1: buf[] + * ARG2: count + */ +scret_t +sys_read(struct syscall_args *scargs) +{ + int fd = SCARG(scargs, int, 0); + char *u_buf = SCARG(scargs, char *, 1); + size_t count = SCARG(scargs, size_t, 2); + char *kbuf; + ssize_t retval; + int error; + + /* Do we have enough memory to fulfill this */ + kbuf = kalloc(count); + if (kbuf == NULL) { + return -ENOMEM; + } + + retval = read(fd, kbuf, count); + if (retval < 0) { + kfree(kbuf); + return retval; + } + + error = copyout(kbuf, u_buf, count); + kfree(kbuf); + return (error == 0) ? retval : error; +} diff --git a/src/sys/include/compat/unix/syscall.h b/src/sys/include/compat/unix/syscall.h index 8b7e7d7..be351e8 100644 --- a/src/sys/include/compat/unix/syscall.h +++ b/src/sys/include/compat/unix/syscall.h @@ -63,6 +63,11 @@ scret_t sys_query(struct syscall_args *scargs); */ scret_t sys_open(struct syscall_args *scargs); +/* + * Read a file + */ +scret_t sys_read(struct syscall_args *scargs); + #ifdef _NEED_UNIX_SCTAB scret_t(*g_unix_sctab[])(struct syscall_args *) = { [SYS_none] = NULL, @@ -77,7 +82,8 @@ scret_t(*g_unix_sctab[])(struct syscall_args *) = { [SYS_getargv] = sys_getargv, [SYS_reboot] = sys_reboot, [SYS_waitpid] = sys_waitpid, - [SYS_dmsio] = sys_dmsio + [SYS_dmsio] = sys_dmsio, + [SYS_read] = sys_read }; #endif /* !_NEED_UNIX_SCTAB */ diff --git a/src/sys/include/os/filedesc.h b/src/sys/include/os/filedesc.h index 0023526..8cdf161 100644 --- a/src/sys/include/os/filedesc.h +++ b/src/sys/include/os/filedesc.h @@ -93,4 +93,16 @@ int fd_open(const char *path, mode_t mode); */ ssize_t write(int fd, const void *buf, size_t count); +/* + * Read a file descriptor + * + * @fd: File descriptor to read from + * @buf: Buffer to read into + * @count: Number of bytes to read + * + * Returns the number of bytes read on success, otherwise a less + * than zero value on error. + */ +ssize_t read(int fd, void *buf, size_t count); + #endif /* !_OS_FILEDESC_H_ */ diff --git a/src/sys/include/sys/syscall.h b/src/sys/include/sys/syscall.h index 2ff6087..1138029 100644 --- a/src/sys/include/sys/syscall.h +++ b/src/sys/include/sys/syscall.h @@ -56,6 +56,7 @@ #define SYS_reboot 0x0B /* reboot the system */ #define SYS_waitpid 0x0C /* wait for child to exit */ #define SYS_dmsio 0x0D /* DMS I/O */ +#define SYS_read 0x0E /* read a file descriptor */ typedef __ssize_t scret_t; typedef __ssize_t scarg_t; diff --git a/src/sys/os/os_filedes.c b/src/sys/os/os_filedes.c index 5789427..9ba0c63 100644 --- a/src/sys/os/os_filedes.c +++ b/src/sys/os/os_filedes.c @@ -273,6 +273,40 @@ write(int fd, const void *buf, size_t count) return count; } +ssize_t +read(int fd, void *buf, size_t count) +{ + struct proc *self = proc_self(); + struct filedesc *fdp; + int error; + + if (buf == NULL) { + return -EINVAL; + } + + /* Must be valid */ + error = proc_check_addr(self, (uintptr_t)buf, count); + if (error < 0) { + return error; + } + + /* We need the actual descriptor */ + if ((fdp = fd_get(self, fd)) == NULL) { + return -EBADF; + } + + /* Can we read from it? */ + if (fdp->mode == O_WRONLY) { + return -EPERM; + } + + if (fdp->vp == NULL) { + return -EIO; + } + + return vop_read(fdp->vp, buf, count); +} + /* * ARG0: Path * ARG1: Mode |