diff options
author | dzwdz | 2022-06-29 23:07:21 +0200 |
---|---|---|
committer | dzwdz | 2022-06-29 23:07:21 +0200 |
commit | bf4f2bb63ed01026b1078f5f7ebfc005bb4bf6d3 (patch) | |
tree | 4b1abbcff1db9589709470918b3e75a73ed30341 /src/init/driver/tmpfs.c | |
parent | bf4cbc830d78774ac00d9501c45e8b84d0ae9ae7 (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.c | 92 |
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); +} |