summaryrefslogtreecommitdiff
path: root/src/init/driver/tmpfs.c
diff options
context:
space:
mode:
authordzwdz2022-06-29 23:07:21 +0200
committerdzwdz2022-06-29 23:07:21 +0200
commitbf4f2bb63ed01026b1078f5f7ebfc005bb4bf6d3 (patch)
tree4b1abbcff1db9589709470918b3e75a73ed30341 /src/init/driver/tmpfs.c
parentbf4cbc830d78774ac00d9501c45e8b84d0ae9ae7 (diff)
init/fs: tmpfs driver with support for creating new files
Diffstat (limited to 'src/init/driver/tmpfs.c')
-rw-r--r--src/init/driver/tmpfs.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/init/driver/tmpfs.c b/src/init/driver/tmpfs.c
new file mode 100644
index 0000000..17b5b9b
--- /dev/null
+++ b/src/init/driver/tmpfs.c
@@ -0,0 +1,92 @@
+#include <init/malloc.h>
+#include <shared/mem.h>
+#include <shared/syscalls.h>
+#include <stddef.h>
+
+struct node {
+ const char *name;
+ size_t len;
+ struct node *next;
+};
+
+struct node *root = NULL;
+
+static struct node *lookup(const char *path, size_t len) {
+ for (struct node *iter = root; iter; iter = iter->next) {
+ if (iter->len == len && !memcmp(path, iter->name, len))
+ return iter;
+ }
+ return NULL;
+}
+
+static int tmpfs_open(const char *path, struct fs_wait_response *res) {
+ if (res->len == 0) return -1;
+ path++;
+ res->len--;
+
+ if (res->len == 0) return 0; /* root */
+
+ // no directory support (yet)
+ if (memchr(path, '/', res->len)) return -1;
+
+ if (res->flags & OPEN_CREATE) {
+ if (lookup(path, res->len)) return -1; /* already exists */
+ struct node *new = malloc(sizeof *new);
+ char *namebuf = malloc(res->len);
+ memcpy(namebuf, path, res->len);
+ new->name = namebuf;
+ new->len = res->len;
+ new->next = root;
+ root = new;
+ return 1;
+ }
+
+ return lookup(path, res->len) != 0 ? 1 : -1;
+}
+
+void tmpfs_drv(void) {
+ // TODO replace all the static allocations in drivers with mallocs
+ static char buf[512];
+ struct fs_wait_response res;
+ while (!_syscall_fs_wait(buf, sizeof buf, &res)) {
+ switch (res.op) {
+ case VFSOP_OPEN:
+ _syscall_fs_respond(NULL, tmpfs_open(buf, &res));
+ break;
+
+ case VFSOP_READ:
+ if (res.id != 0) {
+ // rw unimplemented
+ _syscall_fs_respond(NULL, -1);
+ break;
+ }
+ size_t buf_pos = 0;
+ size_t to_skip = res.offset;
+
+ for (struct node *iter = root; iter; iter = iter->next) {
+ if (iter->len <= to_skip) {
+ to_skip -= iter->len;
+ continue;
+ }
+
+ if (iter->len + buf_pos - to_skip >= sizeof(buf)) {
+ memcpy(buf + buf_pos, iter->name + to_skip, sizeof(buf) - buf_pos - to_skip);
+ buf_pos = sizeof(buf);
+ break;
+ }
+ memcpy(buf + buf_pos, iter->name + to_skip, iter->len - to_skip);
+ buf_pos += iter->len - to_skip;
+ buf[buf_pos++] = '\0';
+ to_skip = 0;
+ }
+ _syscall_fs_respond(buf, buf_pos);
+ break;
+
+ default:
+ _syscall_fs_respond(NULL, -1);
+ break;
+ }
+ }
+
+ _syscall_exit(1);
+}