summaryrefslogtreecommitdiff
path: root/src/sys
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys')
-rw-r--r--src/sys/fs/tmpfs.c115
-rw-r--r--src/sys/include/compat/unix/syscall.h8
-rw-r--r--src/sys/include/os/filedesc.h10
-rw-r--r--src/sys/include/os/vnode.h21
-rw-r--r--src/sys/include/sys/seek.h37
-rw-r--r--src/sys/include/sys/syscall.h1
-rw-r--r--src/sys/os/os_filedes.c53
-rw-r--r--src/sys/os/vfs_subr.c20
8 files changed, 263 insertions, 2 deletions
diff --git a/src/sys/fs/tmpfs.c b/src/sys/fs/tmpfs.c
index 4a5c607..af1537f 100644
--- a/src/sys/fs/tmpfs.c
+++ b/src/sys/fs/tmpfs.c
@@ -47,6 +47,7 @@ struct tmpfs_node {
char name[TMPFS_NAMEMAX];
char *data;
size_t len;
+ size_t real_len;
int ref;
TAILQ_ENTRY(tmpfs_node) link;
};
@@ -93,6 +94,7 @@ tmpfs_new(const char *name, struct tmpfs_node **np_res)
return -ENOMEM;
}
+ np->real_len = 0;
np->len = TMPFS_INIT_SIZE;
np->ref = 1;
memset(np->data, 0, TMPFS_INIT_SIZE);
@@ -232,6 +234,114 @@ tmpfs_mount(struct fs_info *fip, struct mount_args *margs)
return 0;
}
+/*
+ * Write to the filesystem
+ */
+static ssize_t
+tmpfs_write(struct vop_rw_data *data)
+{
+ struct vnode *vp;
+ struct tmpfs_node *np;
+ char *dest;
+ void *p;
+ size_t node_len, len;
+ size_t overflow_window;
+
+ if (data == NULL) {
+ return -EINVAL;
+ }
+
+ if ((vp = data->vp) == NULL) {
+ return -EIO;
+ }
+
+ /* We need the vnode for lengths */
+ if ((np = vp->data) == NULL) {
+ return -EIO;
+ }
+
+ /*
+ * Check if there is going to be any overflows
+ * and if so, get the overflow window and expand
+ * the buffer by it.
+ */
+ len = data->len;
+ if ((len + data->off) > np->len) {
+ overflow_window = (len + data->off) - np->len;
+ np->len += overflow_window + 1;
+
+ p = np->data;
+ np->data = krealloc(np->data, np->len);
+ if (np->data == NULL) {
+ np->data = p;
+ return -ENOMEM;
+ }
+ }
+
+ np->real_len += len;
+ node_len = np->len;
+ dest = np->data + data->off;
+ memcpy(dest, data->data, len);
+ return len;
+}
+
+static ssize_t
+tmpfs_read(struct vop_rw_data *data)
+{
+ struct vnode *vp;
+ struct tmpfs_node *np;
+ size_t len;
+ char *dest, *src;
+
+ if (data == NULL) {
+ return -1;
+ }
+
+ if ((vp = data->vp) == NULL) {
+ return -EIO;
+ }
+
+ if ((np = vp->data) == NULL) {
+ return -EIO;
+ }
+
+ /* Return EOF if the offset is too far */
+ len = data->len;
+ if (data->off >= np->real_len) {
+ return 0; /* EOF */
+ }
+
+ /* Is there any data to read? */
+ if ((len + data->off) > np->len) {
+ len = np->len;
+ }
+ if (len == 0) {
+ return 0;
+ }
+
+ dest = data->data;
+ src = np->data + data->off;
+ memcpy(dest, src, len);
+ return len;
+}
+
+static int
+tmpfs_getattr(struct vnode *vp, struct vattr *res)
+{
+ struct tmpfs_node *np;
+
+ if (vp == NULL || res == NULL) {
+ return -EINVAL;
+ }
+
+ if ((np = vp->data) == NULL) {
+ return -EIO;
+ }
+
+ res->size = np->real_len;
+ return 0;
+}
+
static int
tmpfs_reclaim(struct vnode *vp, int flags)
{
@@ -241,7 +351,10 @@ tmpfs_reclaim(struct vnode *vp, int flags)
static struct vop tmpfs_vops = {
.lookup = tmpfs_lookup,
.create = tmpfs_create,
- .reclaim = tmpfs_reclaim
+ .reclaim = tmpfs_reclaim,
+ .write = tmpfs_write,
+ .read = tmpfs_read,
+ .getattr = tmpfs_getattr
};
struct vfsops g_tmpfs_vfsops = {
diff --git a/src/sys/include/compat/unix/syscall.h b/src/sys/include/compat/unix/syscall.h
index a031872..42dc4c0 100644
--- a/src/sys/include/compat/unix/syscall.h
+++ b/src/sys/include/compat/unix/syscall.h
@@ -73,6 +73,11 @@ scret_t sys_read(struct syscall_args *scargs);
*/
scret_t sys_close(struct syscall_args *scargs);
+/*
+ * Seek a file descriptor
+ */
+scret_t sys_lseek(struct syscall_args *scargs);
+
#ifdef _NEED_UNIX_SCTAB
scret_t(*g_unix_sctab[])(struct syscall_args *) = {
[SYS_none] = NULL,
@@ -89,7 +94,8 @@ scret_t(*g_unix_sctab[])(struct syscall_args *) = {
[SYS_waitpid] = sys_waitpid,
[SYS_dmsio] = sys_dmsio,
[SYS_read] = sys_read,
- [SYS_close] = sys_close
+ [SYS_close] = sys_close,
+ [SYS_lseek] = sys_lseek
};
#endif /* !_NEED_UNIX_SCTAB */
diff --git a/src/sys/include/os/filedesc.h b/src/sys/include/os/filedesc.h
index a6a2ac5..b773de9 100644
--- a/src/sys/include/os/filedesc.h
+++ b/src/sys/include/os/filedesc.h
@@ -30,6 +30,7 @@
#ifndef _OS_FILEDESC_H_
#define _OS_FILEDESC_H_ 1
+#include <sys/seek.h>
#include <sys/types.h>
#include <os/vnode.h>
@@ -117,4 +118,13 @@ ssize_t write(int fd, const void *buf, size_t count);
*/
ssize_t read(int fd, void *buf, size_t count);
+/*
+ * Reposition the file offset of a file
+ *
+ * @fd: File descriptor to reposition
+ * @offset: Offset to move `fd' to
+ * @whence: How it should be repositioned
+ */
+off_t lseek(int fd, off_t offset, int whence);
+
#endif /* !_OS_FILEDESC_H_ */
diff --git a/src/sys/include/os/vnode.h b/src/sys/include/os/vnode.h
index 628ba68..77cadb2 100644
--- a/src/sys/include/os/vnode.h
+++ b/src/sys/include/os/vnode.h
@@ -94,10 +94,20 @@ struct vop_create_args {
};
/*
+ * Represents attributes of a vnode
+ *
+ * @size: File size in bytes
+ */
+struct vattr {
+ size_t size;
+};
+
+/*
* Represents operations that can be performed on
* a specific vnode. These are implemented as callbacks
*/
struct vop {
+ int(*getattr)(struct vnode *vp, struct vattr *res);
int(*lookup)(struct vop_lookup_args *args);
int(*reclaim)(struct vnode *vp, int flags);
int(*create)(struct vop_create_args *args);
@@ -200,4 +210,15 @@ int vop_reclaim(struct vnode *vp, int flags);
*/
int vop_create(struct vnode *vp, struct nameidata *ndp);
+/*
+ * Get the attributes of a file
+ *
+ * @vp: Vnode of file to get attributes of
+ * @res: Result of file to get attr of
+ *
+ * Returns zero on success, otherwise a less than
+ * zero value on failure
+ */
+int vop_getattr(struct vnode *vp, struct vattr *res);
+
#endif /* !_OS_VNODE_H_ */
diff --git a/src/sys/include/sys/seek.h b/src/sys/include/sys/seek.h
new file mode 100644
index 0000000..1edc50b
--- /dev/null
+++ b/src/sys/include/sys/seek.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and L5 engineers
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_SEEK_H_
+#define _SYS_SEEK_H_ 1
+
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+#endif /* !_SYS_SEEK_H_ */
diff --git a/src/sys/include/sys/syscall.h b/src/sys/include/sys/syscall.h
index 77b7505..c97d5ea 100644
--- a/src/sys/include/sys/syscall.h
+++ b/src/sys/include/sys/syscall.h
@@ -58,6 +58,7 @@
#define SYS_dmsio 0x0D /* DMS I/O */
#define SYS_read 0x0E /* read a file descriptor */
#define SYS_close 0x0F /* close a file */
+#define SYS_lseek 0x10 /* seek to end of file */
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 ca56fc3..36748a6 100644
--- a/src/sys/os/os_filedes.c
+++ b/src/sys/os/os_filedes.c
@@ -359,6 +359,44 @@ read(int fd, void *buf, size_t count)
return retval;
}
+off_t
+lseek(int fd, off_t offset, int whence)
+{
+ struct filedesc *fdp;
+ struct proc *self = proc_self();
+ struct vattr attr;
+ int error;
+
+ if (fd < 0) {
+ return -EBADF;
+ }
+
+ fdp = fd_get(self, fd);
+ if (fdp == NULL) {
+ return -EBADF;
+ }
+
+ /* Could not get vnode attributes */
+ error = vop_getattr(fdp->vp, &attr);
+ if (error < 0) {
+ return 0;
+ }
+
+ switch (whence) {
+ case SEEK_SET:
+ fdp->off = offset;
+ break;
+ case SEEK_CUR:
+ fdp->off += offset;
+ break;
+ case SEEK_END:
+ fdp->off = attr.size;
+ break;
+ }
+
+ return fdp->off;
+}
+
/*
* ARG0: Path
* ARG1: Mode
@@ -378,3 +416,18 @@ sys_open(struct syscall_args *scargs)
return fd_open(pathbuf, mode);
}
+
+/*
+ * ARG0: Fd
+ * ARG1: Offset
+ * ARG2: Whence
+ */
+scret_t
+sys_lseek(struct syscall_args *scargs)
+{
+ int fd = SCARG(scargs, int, 0);
+ off_t off = SCARG(scargs, off_t, 1);
+ int whence = SCARG(scargs, int, 2);
+
+ return lseek(fd, off, whence);
+}
diff --git a/src/sys/os/vfs_subr.c b/src/sys/os/vfs_subr.c
index adfcffb..2ae18af 100644
--- a/src/sys/os/vfs_subr.c
+++ b/src/sys/os/vfs_subr.c
@@ -246,3 +246,23 @@ vop_create(struct vnode *vp, struct nameidata *ndp)
args.ndp = ndp;
return vops->create(&args);
}
+
+int
+vop_getattr(struct vnode *vp, struct vattr *res)
+{
+ struct vop *vops;
+
+ if (vp == NULL || res == NULL) {
+ return -EINVAL;
+ }
+
+ if ((vops = vp->vops) == NULL) {
+ return -EIO;
+ }
+
+ if (vops->getattr == NULL) {
+ return -EIO;
+ }
+
+ return vops->getattr(vp, res);
+}