summaryrefslogtreecommitdiff
path: root/src/user
diff options
context:
space:
mode:
authordzwdz2022-08-11 21:16:15 +0200
committerdzwdz2022-08-11 21:16:15 +0200
commit12aee8d9c127a85105b3e8f24cbcebc61c2db3e4 (patch)
tree627cefddb41a26f5e7c4ea7fb2537db8e9faf5f4 /src/user
parent9438c2fdaf4e75c9218a5fde84f121a7a0abb457 (diff)
vfs: support for removing files
Diffstat (limited to 'src/user')
-rw-r--r--src/user/app/shell/builtins.c36
-rw-r--r--src/user/app/tmpfs/tmpfs.c48
-rw-r--r--src/user/lib/syscall.c4
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);
}