diff options
Diffstat (limited to 'src/user')
-rw-r--r-- | src/user/app/shell/builtins.c | 36 | ||||
-rw-r--r-- | src/user/app/tmpfs/tmpfs.c | 48 | ||||
-rw-r--r-- | src/user/lib/syscall.c | 4 |
3 files changed, 84 insertions, 4 deletions
diff --git a/src/user/app/shell/builtins.c b/src/user/app/shell/builtins.c index efc427d..6611002 100644 --- a/src/user/app/shell/builtins.c +++ b/src/user/app/shell/builtins.c @@ -1,5 +1,6 @@ #include "builtins.h" #include "shell.h" +#include <camellia/path.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -135,6 +136,40 @@ static void cmd_ls(int argc, char **argv) { } } +static void cmd_rm(int argc, char **argv) { + if (argc < 2) { + eprintf("no arguments"); + return; + } + const size_t buflen = PATH_MAX; + char *buf = malloc(buflen); + for (int i = 1; i < argc; i++) { + handle_t h; + long ret; + size_t abslen; + char *path = argv[i]; + if (*path == '\0') { + eprintf("ignoring empty argument"); + continue; + } + abslen = absolutepath(buf, path, buflen); + if (!abslen) { + eprintf("invalid path %s", path); + continue; + } + h = _syscall_open(buf, abslen - 1, 0); + if (h < 0) { + eprintf("couldn't open %s (err %u)", path, -h); + continue; + } + ret = _syscall_remove(h); + if (ret < 0) { + eprintf("couldn't remove %s (err %u)", path, -ret); + continue; + } + } +} + static void cmd_sleep(int argc, char **argv) { if (argc < 2) { eprintf("no arguments"); @@ -177,6 +212,7 @@ struct builtin builtins[] = { {"getsize", cmd_getsize}, {"hexdump", cmd_hexdump}, {"ls", cmd_ls}, + {"rm", cmd_rm}, {"sleep", cmd_sleep}, {"touch", cmd_touch}, {"whitelist", cmd_whitelist}, diff --git a/src/user/app/tmpfs/tmpfs.c b/src/user/app/tmpfs/tmpfs.c index 2594813..9bc3d6c 100644 --- a/src/user/app/tmpfs/tmpfs.c +++ b/src/user/app/tmpfs/tmpfs.c @@ -1,5 +1,6 @@ #include <camellia/fsutil.h> #include <camellia/syscalls.h> +#include <errno.h> #include <shared/mem.h> #include <stdbool.h> #include <stddef.h> @@ -11,12 +12,16 @@ struct node { const char *name; bool directory; size_t namelen; - struct node *sibling, *child; char *buf; size_t size, capacity; + size_t open; /* amount of open handles */ + + struct node *sibling, *child; + /* each node except special_root has exacly one sibling or child reference to it + * on remove(), it gets replaced with *sibling. */ + struct node **ref; }; -struct node *root = NULL; static struct node special_root = { .directory = true, .size = 0, @@ -57,17 +62,41 @@ static struct node *tmpfs_open(const char *path, struct fs_wait_response *res) { node->name = namebuf; node->directory = slash; node->namelen = seglen; - node->sibling = parent->child; - parent->child = node; + + if (parent->child) { + parent->child->ref = &node->sibling; + *parent->child->ref = parent->child; + } + node->ref = &parent->child; + *node->ref = node; } else { return NULL; } } segpos += seglen; } + node->open++; return node; } +static void handle_down(struct node *node) { + node->open--; + if (!node->ref && node != &special_root && node->open == 0) { + free(node->buf); + free(node); + } +} + +static long remove_node(struct node *node) { + if (node == &special_root) return -1; + if (!node->ref) return -1; + if (node->child) return -ENOTEMPTY; + *node->ref = node->sibling; + node->ref = NULL; + handle_down(node); + return 0; +} + int main(void) { const size_t buflen = 4096; char *buf = malloc(buflen); @@ -144,6 +173,17 @@ int main(void) { } break; + case VFSOP_REMOVE: + ptr = (void*)res.id; + _syscall_fs_respond(NULL, remove_node(ptr), 0); + break; + + case VFSOP_CLOSE: + ptr = (void*)res.id; + handle_down(ptr); + _syscall_fs_respond(NULL, -1, 0); + break; + default: _syscall_fs_respond(NULL, -1, 0); break; diff --git a/src/user/lib/syscall.c b/src/user/lib/syscall.c index e22f718..1635636 100644 --- a/src/user/lib/syscall.c +++ b/src/user/lib/syscall.c @@ -42,6 +42,10 @@ long _syscall_getsize(handle_t h) { return _syscall(_SYSCALL_GETSIZE, (long)h, 0, 0, 0, 0); } +long _syscall_remove(handle_t h) { + return _syscall(_SYSCALL_REMOVE, (long)h, 0, 0, 0, 0); +} + long _syscall_close(handle_t h) { return _syscall(_SYSCALL_CLOSE, (long)h, 0, 0, 0, 0); } |