summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-02-22 02:18:33 -0500
committerIan Moffett <ian@osmora.org>2025-02-22 02:20:12 -0500
commitd68537c1ca22d58f1c219d970d5aa462df9e0c6b (patch)
tree375e9f1a9feb249f39754a8df38f5fdfe4430b85 /sys/kern
parent2f7f296f8e7eae3944bc34e9dfe51a262b7f7149 (diff)
kernel: vfs: Add support for write()
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_descrip.c50
-rw-r--r--sys/kern/kern_syscall.c1
-rw-r--r--sys/kern/vfs_subr.c13
-rw-r--r--sys/kern/vfs_syscalls.c12
4 files changed, 69 insertions, 7 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index d1ed044..201db3e 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -31,6 +31,7 @@
#include <sys/errno.h>
#include <sys/proc.h>
#include <sys/limits.h>
+#include <sys/fcntl.h>
#include <sys/namei.h>
#include <sys/filedesc.h>
#include <sys/systm.h>
@@ -135,15 +136,16 @@ fd_close(unsigned int fd)
}
/*
- * Read bytes from a file using a file
+ * Read/write bytes to/from a file using a file
* descriptor number.
*
* @fd: File descriptor number.
- * @buf: Buffer to read into.
+ * @buf: Buffer with data to read/write
* @count: Number of bytes to read.
+ * @write: Set to 1 for writes
*/
-int
-fd_read(unsigned int fd, void *buf, size_t count)
+static int
+fd_rw(unsigned int fd, void *buf, size_t count, uint8_t write)
{
char *kbuf = NULL;
struct filedesc *filedes;
@@ -173,13 +175,34 @@ fd_read(unsigned int fd, void *buf, size_t count)
goto done;
}
+ /* Check if this violates the file seal */
+ if (!ISSET(filedes->flags, O_ALLOW_WR) && write) {
+ return -EPERM;
+ } else if (ISSET(O_RDONLY, filedes->flags) && write) {
+ return -EPERM;
+ }
+
sio.len = count;
sio.buf = kbuf;
sio.offset = filedes->offset;
- if ((count = vfs_vop_read(filedes->vp, &sio)) < 0) {
- retval = -EIO;
- goto done;
+ if (write) {
+ /* Copy in user buffer */
+ if (copyin(buf, kbuf, count) < 0) {
+ retval = -EFAULT;
+ goto done;
+ }
+
+ /* Call VFS write hook */
+ if ((count = vfs_vop_write(filedes->vp, &sio)) < 0) {
+ retval = -EIO;
+ goto done;
+ }
+ } else {
+ if ((count = vfs_vop_read(filedes->vp, &sio)) < 0) {
+ retval = -EIO;
+ goto done;
+ }
}
if (copyout(kbuf, buf, count) < 0) {
@@ -195,6 +218,18 @@ done:
return retval;
}
+int
+fd_read(unsigned int fd, void *buf, size_t count)
+{
+ return fd_rw(fd, buf, count, 0);
+}
+
+int
+fd_write(unsigned int fd, void *buf, size_t count)
+{
+ return fd_rw(fd, buf, count, 1);
+}
+
/*
* Open a file and get a file descriptor
* number.
@@ -224,6 +259,7 @@ fd_open(const char *pathname, int flags)
}
filedes->vp = nd.vp;
+ filedes->flags = flags;
return filedes->fdno;
}
diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c
index 1d961a7..986d82a 100644
--- a/sys/kern/kern_syscall.c
+++ b/sys/kern/kern_syscall.c
@@ -41,6 +41,7 @@ scret_t(*g_sctab[])(struct syscall_args *) = {
sys_close, /* SYS_close */
sys_stat, /* SYS_stat */
sys_sysctl, /* SYS_sysctl */
+ sys_write, /* SYS_write */
};
const size_t MAX_SYSCALLS = NELEM(g_sctab);
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index f67bcfe..da0a4f9 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -167,6 +167,19 @@ vfs_vop_read(struct vnode *vp, struct sio_txn *sio)
}
int
+vfs_vop_write(struct vnode *vp, struct sio_txn *sio)
+{
+ const struct vops *vops = vp->vops;
+
+ if (vops == NULL)
+ return -EIO;
+ if (vops->write == NULL)
+ return -EIO;
+
+ return vops->write(vp, sio);
+}
+
+int
vfs_vop_getattr(struct vnode *vp, struct vop_getattr_args *args)
{
const struct vops *vops = vp->vops;
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index fa613c2..6f2d683 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -129,6 +129,18 @@ sys_read(struct syscall_args *scargs)
}
/*
+ * arg0: fd
+ * arg1: buf
+ * arg2: count
+ */
+scret_t
+sys_write(struct syscall_args *scargs)
+{
+ return fd_write(scargs->arg0, (void *)scargs->arg1,
+ scargs->arg2);
+}
+
+/*
* arg0: path
* arg1: buf
*/