diff options
Diffstat (limited to 'src/init')
-rw-r--r-- | src/init/fs/misc.c | 71 | ||||
-rw-r--r-- | src/init/fs/misc.h | 2 | ||||
-rw-r--r-- | src/init/main.c | 4 |
3 files changed, 77 insertions, 0 deletions
diff --git a/src/init/fs/misc.c b/src/init/fs/misc.c index 8c8967c..d2e2614 100644 --- a/src/init/fs/misc.c +++ b/src/init/fs/misc.c @@ -101,3 +101,74 @@ void fs_passthru(const char *prefix) { } _syscall_exit(0); } + + +void fs_dir_inject(const char *path) { + struct fs_dir_handle { + int delegate; + const char *inject; + }; + + const int path_len = strlen(path); + struct fs_wait_response res; + struct fs_dir_handle handles[16]; // TODO hardcoded FD_MAX - use malloc instead + int handle_next = 0; + int buf_size = 64; + char buf[ 64]; + int ret; + + while (!_syscall_fs_wait(buf, buf_size, &res)) { + switch (res.op) { + case VFSOP_OPEN: + if (handle_next > 15) _syscall_fs_respond(NULL, -2); // we ran out of handles, which is entirely our fault. + + ret = _syscall_open(buf, res.len); /* errors handled in inject handler */ + handles[handle_next].delegate = ret; + handles[handle_next].inject = NULL; + + if (buf[res.len - 1] == '/' && + res.len < path_len && !memcmp(path, buf, res.len)) { + handles[handle_next].inject = path + res.len; + } else { + /* not injecting, don't allow opening nonexistent stuff */ + if (ret < 0) _syscall_fs_respond(NULL, ret); + } + _syscall_fs_respond(NULL, handle_next++); + break; + + case VFSOP_READ: + if (handles[res.id].inject) { + // TODO check offset + struct fs_dir_handle h = handles[res.id]; + + int out_len = 0; + while (h.inject[out_len] != '/') out_len++; // TODO ensure trailing slash + memcpy(buf, h.inject, out_len); + buf[out_len++] = '\0'; + + if (h.delegate >= 0) { + int to_read = res.capacity < buf_size ? res.capacity : buf_size; + to_read -= out_len; + ret = _syscall_read(h.delegate, buf + out_len, to_read, 0); + if (ret > 0) out_len += ret; + // TODO deduplicate entries + } + + _syscall_fs_respond(buf, out_len); + break; + } + + /* fallthrough */ + + default: { + struct fs_dir_handle h = handles[res.id]; + if (h.delegate < 0) + _syscall_fs_respond(NULL, -1); + else + fs_respond_delegate(&res, h.delegate); + break; + } + } + } + _syscall_exit(0); +} diff --git a/src/init/fs/misc.h b/src/init/fs/misc.h index 33e98f5..8e31844 100644 --- a/src/init/fs/misc.h +++ b/src/init/fs/misc.h @@ -4,3 +4,5 @@ bool fork2_n_mount(const char *path); void fs_passthru(const char *prefix); + +void fs_dir_inject(const char *path); diff --git a/src/init/main.c b/src/init/main.c index d19b1e5..b723c7b 100644 --- a/src/init/main.c +++ b/src/init/main.c @@ -51,4 +51,8 @@ void fs_prep(void) { if (!fork2_n_mount("/3nd")) fs_passthru("/init"); + + if (!fork2_n_mount("/")) + fs_dir_inject("/test/dir/"); + } |