diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/kernel/arch/amd64/driver/fsroot.c | 2 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 27 | ||||
-rw-r--r-- | src/shared/include/camellia/errno.h | 1 | ||||
-rw-r--r-- | src/shared/include/camellia/syscalls.h | 2 | ||||
-rw-r--r-- | src/shared/include/camellia/types.h | 1 | ||||
-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 |
8 files changed, 115 insertions, 6 deletions
diff --git a/src/kernel/arch/amd64/driver/fsroot.c b/src/kernel/arch/amd64/driver/fsroot.c index 7856fba..3bbf2d1 100644 --- a/src/kernel/arch/amd64/driver/fsroot.c +++ b/src/kernel/arch/amd64/driver/fsroot.c @@ -25,7 +25,7 @@ static int handle(struct vfs_request *req) { // TODO getsize for the other kernel provided directories case VFSOP_GETSIZE: return sizeof dir; - default: return 0; + default: return -ENOSYS; } } diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 5dca49f..288aa1e 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -266,7 +266,7 @@ long _syscall_write(handle_t handle_num, const void __user *buf, size_t len, lon long _syscall_getsize(handle_t hid) { struct handle *h = process_handle_get(process_current, hid); if (!h) SYSCALL_RETURN(-1); - if (h->type != HANDLE_FILE) SYSCALL_RETURN(-2); + if (h->type != HANDLE_FILE) SYSCALL_RETURN(-ENOSYS); vfsreq_create((struct vfs_request) { .type = VFSOP_GETSIZE, .id = h->file_id, @@ -276,6 +276,28 @@ long _syscall_getsize(handle_t hid) { return -1; // dummy } +long _syscall_remove(handle_t hid) { + if (hid < 0 || hid >= HANDLE_MAX) return -1; + struct handle **hslot = &process_current->handles[hid]; + struct handle *h = *hslot; + if (!h) SYSCALL_RETURN(-1); + if (h->type == HANDLE_FILE) { + vfsreq_create((struct vfs_request) { + .type = VFSOP_REMOVE, + .id = h->file_id, + .caller = process_current, + .backend = h->backend, + }); + handle_close(*hslot); + *hslot = NULL; + return -1; // dummy + } else { + handle_close(*hslot); + *hslot = NULL; + SYSCALL_RETURN(-ENOSYS); + } +} + long _syscall_close(handle_t hid) { if (hid < 0 || hid >= HANDLE_MAX) return -1; struct handle **h = &process_current->handles[hid]; @@ -441,6 +463,9 @@ long _syscall(long num, long a, long b, long c, long d, long e) { case _SYSCALL_GETSIZE: _syscall_getsize(a); break; + case _SYSCALL_REMOVE: + _syscall_remove(a); + break; case _SYSCALL_CLOSE: _syscall_close(a); break; diff --git a/src/shared/include/camellia/errno.h b/src/shared/include/camellia/errno.h index 5a9e743..e352015 100644 --- a/src/shared/include/camellia/errno.h +++ b/src/shared/include/camellia/errno.h @@ -7,3 +7,4 @@ #define ERANGE 6 #define ENOMEM 7 #define ENOENT 8 +#define ENOTEMPTY 9 diff --git a/src/shared/include/camellia/syscalls.h b/src/shared/include/camellia/syscalls.h index ade75a5..b6c93fe 100644 --- a/src/shared/include/camellia/syscalls.h +++ b/src/shared/include/camellia/syscalls.h @@ -21,6 +21,7 @@ enum { _SYSCALL_READ, _SYSCALL_WRITE, _SYSCALL_GETSIZE, + _SYSCALL_REMOVE, _SYSCALL_CLOSE, _SYSCALL_FS_FORK2, @@ -65,6 +66,7 @@ handle_t _syscall_dup(handle_t from, handle_t to, int flags); long _syscall_read(handle_t h, void __user *buf, size_t len, long offset); long _syscall_write(handle_t h, const void __user *buf, size_t len, long offset, int flags); long _syscall_getsize(handle_t h); +long _syscall_remove(handle_t h); long _syscall_close(handle_t h); struct fs_wait_response { diff --git a/src/shared/include/camellia/types.h b/src/shared/include/camellia/types.h index cb17b3a..622d705 100644 --- a/src/shared/include/camellia/types.h +++ b/src/shared/include/camellia/types.h @@ -17,5 +17,6 @@ enum vfs_operation { VFSOP_READ, VFSOP_WRITE, VFSOP_GETSIZE, + VFSOP_REMOVE, VFSOP_CLOSE, }; 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); } |