summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordzwdz2022-08-08 13:12:41 +0200
committerdzwdz2022-08-08 13:12:41 +0200
commitc7af8418c9a2222cde5ab3a6953b31803d0a8ef1 (patch)
treece9b5f19cfd292eb4e70086cb061527f29a68bba /src
parent1252bdeaf795629ac34161bc59a263e998483247 (diff)
user: union filesystems
Diffstat (limited to 'src')
-rw-r--r--src/user/app/init/init.c4
-rw-r--r--src/user/app/shell/builtins.c2
-rw-r--r--src/user/lib/fs/misc.c65
-rw-r--r--src/user/lib/fs/misc.h1
4 files changed, 71 insertions, 1 deletions
diff --git a/src/user/app/init/init.c b/src/user/app/init/init.c
index f011ca5..c788cb6 100644
--- a/src/user/app/init/init.c
+++ b/src/user/app/init/init.c
@@ -39,6 +39,10 @@ int main(void) {
const char *argv[] = {"/bin/vterm", NULL};
execv(argv[0], (void*)argv);
}
+ MOUNT_AT("/union/") {
+ const char *list[] = {"/tmp/", "/init/", NULL};
+ fs_union(list);
+ }
if (fork()) {
/* used to trigger a kernel bug
diff --git a/src/user/app/shell/builtins.c b/src/user/app/shell/builtins.c
index 2562c18..0f06482 100644
--- a/src/user/app/shell/builtins.c
+++ b/src/user/app/shell/builtins.c
@@ -125,7 +125,7 @@ static void cmd_ls(int argc, char **argv) {
return;
}
for (;;) {
- int len = fread(buf, 1, sizeof buf, file);
+ int len = fread(buf, 1, buflen, file);
if (len <= 0) break;
for (int i = 0; i < len; i++)
if (buf[i] == '\0') buf[i] = '\n';
diff --git a/src/user/lib/fs/misc.c b/src/user/lib/fs/misc.c
index 1fb5c3b..54f54fd 100644
--- a/src/user/lib/fs/misc.c
+++ b/src/user/lib/fs/misc.c
@@ -135,6 +135,71 @@ void fs_whitelist(const char **list) {
exit(0);
}
+void fs_union(const char **list) {
+ struct fs_wait_response res;
+
+ /* the buffer is split into two halves:
+ * the second one is filled out with the path by fs_wait
+ * the first one is used for the prepended paths */
+ const size_t buflen = 1024;
+ const size_t prelen = 512;
+ const size_t postlen = buflen - prelen;
+ char *pre = malloc(buflen);
+ char *post = pre + prelen;
+ long ret;
+ struct dirbuild db;
+ if (!pre) exit(1);
+
+ while (!_syscall_fs_wait(post, postlen, &res)) {
+ switch (res.op) {
+ case VFSOP_OPEN:
+ if (res.len == 1) { /* root directory */
+ _syscall_fs_respond(NULL, 0, 0);
+ break;
+ }
+
+ ret = -1;
+ for (size_t i = 0; ret < 0 && list[i]; i++) {
+ const char *prefix = list[i];
+ size_t prefixlen = strlen(prefix); // TODO cache
+ if (prefixlen > prelen) continue;
+ char *path = post - prefixlen;
+ memcpy(path, prefix, prefixlen);
+
+ ret = _syscall_open(path, prefixlen + res.len, res.flags);
+
+ post[res.len] = '\0';
+ }
+ if (ret < 0) ret = -1;
+ _syscall_fs_respond(NULL, ret, FSR_DELEGATE);
+ break;
+
+ case VFSOP_READ:
+ if (res.capacity > buflen)
+ res.capacity = buflen;
+ bool end = false;
+ dir_start(&db, res.offset, pre, res.capacity);
+ for (size_t i = 0; !end && list[i]; i++) {
+ const char *prefix = list[i];
+ size_t prefixlen = strlen(prefix);
+ // TODO only open the directories once
+ // TODO ensure trailing slash
+ handle_t h = _syscall_open(prefix, prefixlen, 0);
+ if (h < 0) continue;
+ end = end || dir_append_from(&db, h);
+ _syscall_close(h);
+ }
+ _syscall_fs_respond(pre, dir_finish(&db), 0);
+ break;
+
+ default:
+ _syscall_fs_respond(NULL, -1, 0);
+ break;
+ }
+ }
+ exit(0);
+}
+
void fs_dir_inject(const char *path) {
struct fs_dir_handle {
diff --git a/src/user/lib/fs/misc.h b/src/user/lib/fs/misc.h
index 1a9c555..8fe6834 100644
--- a/src/user/lib/fs/misc.h
+++ b/src/user/lib/fs/misc.h
@@ -8,6 +8,7 @@ bool fork2_n_mount(const char *path);
void fs_passthru(const char *prefix);
void fs_whitelist(const char **list);
+void fs_union(const char **list);
void fs_dir_inject(const char *path);