diff options
-rw-r--r-- | src/init/fs/misc.c | 15 | ||||
-rw-r--r-- | src/kernel/arch/i386/driver/fsroot.c | 4 | ||||
-rw-r--r-- | src/kernel/arch/i386/driver/ps2.c | 8 | ||||
-rw-r--r-- | src/kernel/arch/i386/driver/serial.c | 10 | ||||
-rw-r--r-- | src/kernel/proc.c | 4 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 2 | ||||
-rw-r--r-- | src/kernel/vfs/request.c | 36 | ||||
-rw-r--r-- | src/kernel/vfs/request.h | 2 | ||||
-rw-r--r-- | src/shared/syscalls.h | 1 |
9 files changed, 48 insertions, 34 deletions
diff --git a/src/init/fs/misc.c b/src/init/fs/misc.c index 7f0c1fb..b394c26 100644 --- a/src/init/fs/misc.c +++ b/src/init/fs/misc.c @@ -111,11 +111,11 @@ void fs_passthru(const char *prefix) { } else { ret = _syscall_open(buf, res.len, res.flags); } - _syscall_fs_respond(NULL, ret, 0); + _syscall_fs_respond(NULL, ret, FSR_DELEGATE); break; default: - fs_respond_delegate(&res, res.id, buf); + _syscall_fs_respond(NULL, -1, 0); break; } } @@ -139,11 +139,11 @@ void fs_whitelist(const char **list) { break; } } - _syscall_fs_respond(NULL, allow ? _syscall_open(buf, res.len, res.flags) : -1, 0); + _syscall_fs_respond(NULL, allow ? _syscall_open(buf, res.len, res.flags) : -1, FSR_DELEGATE); break; default: - fs_respond_delegate(&res, res.id, buf); + _syscall_fs_respond(NULL, -1, 0); break; } } @@ -183,15 +183,18 @@ void fs_dir_inject(const char *path) { if (buf[res.len - 1] == '/' && res.len < path_len && !memcmp(path, buf, res.len)) { + /* we're injecting */ handles[hid].inject = path + res.len; /* if we're making up the opened directory, disallow create */ if (ret < 0 && (res.flags & OPEN_CREATE)) hid = ret; + _syscall_fs_respond(NULL, hid, 0); } else { /* not injecting, don't allow opening nonexistent stuff */ - if (ret < 0) hid = ret; + + handles[hid].taken = false; + _syscall_fs_respond(NULL, ret, FSR_DELEGATE); } - _syscall_fs_respond(NULL, hid, 0); break; case VFSOP_CLOSE: diff --git a/src/kernel/arch/i386/driver/fsroot.c b/src/kernel/arch/i386/driver/fsroot.c index bea89cd..10cf3bc 100644 --- a/src/kernel/arch/i386/driver/fsroot.c +++ b/src/kernel/arch/i386/driver/fsroot.c @@ -134,9 +134,9 @@ static int handle(struct vfs_request *req) { static void accept(struct vfs_request *req) { if (req->caller) { - vfsreq_finish(req, handle(req)); + vfsreq_finish(req, handle(req), 0, NULL); } else { - vfsreq_finish(req, -1); + vfsreq_finish(req, -1, 0, NULL); } } diff --git a/src/kernel/arch/i386/driver/ps2.c b/src/kernel/arch/i386/driver/ps2.c index e1e97c0..36c1b92 100644 --- a/src/kernel/arch/i386/driver/ps2.c +++ b/src/kernel/arch/i386/driver/ps2.c @@ -35,7 +35,7 @@ static void accept(struct vfs_request *req) { switch (req->type) { case VFSOP_OPEN: valid = req->input.len == 0 && !(req->flags & OPEN_CREATE); - vfsreq_finish(req, valid ? 0 : -1); + vfsreq_finish(req, valid ? 0 : -1, 0, NULL); break; case VFSOP_READ: if (ring_size((void*)&backlog) == 0) { @@ -45,13 +45,13 @@ static void accept(struct vfs_request *req) { ret = clamp(0, req->output.len, sizeof buf); ret = ring_get((void*)&backlog, buf, ret); virt_cpy_to(req->caller->pages, req->output.buf, buf, ret); - vfsreq_finish(req, ret); + vfsreq_finish(req, ret, 0, NULL); } else { - vfsreq_finish(req, -1); + vfsreq_finish(req, -1, 0, NULL); } break; default: - vfsreq_finish(req, -1); + vfsreq_finish(req, -1, 0, NULL); break; } } diff --git a/src/kernel/arch/i386/driver/serial.c b/src/kernel/arch/i386/driver/serial.c index b776d0c..a5285e4 100644 --- a/src/kernel/arch/i386/driver/serial.c +++ b/src/kernel/arch/i386/driver/serial.c @@ -73,7 +73,7 @@ static void accept(struct vfs_request *req) { switch (req->type) { case VFSOP_OPEN: valid = req->input.len == 0 && !(req->flags & OPEN_CREATE); - vfsreq_finish(req, valid ? 0 : -1); + vfsreq_finish(req, valid ? 0 : -1, 0, NULL); break; case VFSOP_READ: if (ring_size((void*)&backlog) == 0) { @@ -83,9 +83,9 @@ static void accept(struct vfs_request *req) { ret = clamp(0, req->output.len, sizeof buf); ret = ring_get((void*)&backlog, buf, ret); virt_cpy_to(req->caller->pages, req->output.buf, buf, ret); - vfsreq_finish(req, ret); + vfsreq_finish(req, ret, 0, NULL); } else { - vfsreq_finish(req, -1); + vfsreq_finish(req, -1, 0, NULL); } break; case VFSOP_WRITE: @@ -97,10 +97,10 @@ static void accept(struct vfs_request *req) { serial_write(iter.frag, iter.frag_len); ret = iter.prior; } else ret = -1; - vfsreq_finish(req, ret); + vfsreq_finish(req, ret, 0, NULL); break; default: - vfsreq_finish(req, -1); + vfsreq_finish(req, -1, 0, NULL); break; } } diff --git a/src/kernel/proc.c b/src/kernel/proc.c index 717af11..331e019 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -86,7 +86,7 @@ struct process *process_fork(struct process *parent, int flags) { void process_kill(struct process *p, int ret) { if (p->state != PS_DEAD) { if (p->handled_req) { - vfsreq_finish(p->handled_req, -1); + vfsreq_finish(p->handled_req, -1, 0, NULL); p->handled_req = NULL; } @@ -99,7 +99,7 @@ void process_kill(struct process *p, int ret) { struct vfs_request *q = p->controlled->queue; while (q) { struct vfs_request *q2 = q->queue_next; - vfsreq_finish(q, -1); + vfsreq_finish(q, -1, 0, NULL); q = q2; } p->controlled->queue = NULL; diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index d703b52..cb26b70 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -261,7 +261,7 @@ int _syscall_fs_respond(char __user *buf, int ret, int flags) { } process_current->handled_req = NULL; - vfsreq_finish(req, ret); + vfsreq_finish(req, ret, flags, process_current); SYSCALL_RETURN(0); } diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index 4ee5986..1729ca1 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -19,7 +19,7 @@ void vfsreq_create(struct vfs_request req_) { } if (!req->backend || !req->backend->potential_handlers) - vfsreq_finish(req, -1); + vfsreq_finish(req, -1, 0, NULL); struct vfs_request **iter = &req->backend->queue; while (*iter != NULL) // find free spot in queue @@ -29,27 +29,37 @@ void vfsreq_create(struct vfs_request req_) { vfs_backend_tryaccept(req->backend); } -void vfsreq_finish(struct vfs_request *req, int ret) { +void vfsreq_finish(struct vfs_request *req, int ret, int flags, struct process *handler) { if (req->type == VFSOP_OPEN && ret >= 0) { - // open() calls need special handling - // we need to wrap the id returned by the VFS in a handle passed to - // the client - if (req->caller) { - handle_t handle = process_find_free_handle(req->caller, 0); - if (handle < 0) - panic_invalid_state(); // we check for free handles before the open() call + // TODO write tests for caller getting killed while opening a file + if (!req->caller) panic_unimplemented(); + handle_t handle = process_find_free_handle(req->caller, 0); + if (handle < 0) + panic_invalid_state(); // we check for free handles before the open() call + + if (!(flags & FSR_DELEGATE)) { + /* default behavior - create a new handle for the file, wrap the id */ struct handle *backing = handle_init(HANDLE_FILE); backing->backend = req->backend; req->backend->refcount++; + // TODO file ids can only be 31bit long, so they can't be pointers backing->file_id = ret; req->caller->handles[handle] = backing; - ret = handle; } else { - // caller got killed - // TODO write tests & implement - panic_unimplemented(); + /* delegating - moving a handle to the caller */ + assert(handler); + + struct handle *h = handler->handles[ret]; + if (!h) { + kprintf("tried delegating an invalid handle\n"); + handle = -1; // return error + } else { + req->caller->handles[handle] = h; + handler->handles[ret] = NULL; + } } + ret = handle; } if (req->input.kern) diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h index cad0981..35173ca 100644 --- a/src/kernel/vfs/request.h +++ b/src/kernel/vfs/request.h @@ -59,7 +59,7 @@ struct vfs_request { /** Assigns the vfs_request to the caller, and dispatches the call */ void vfsreq_create(struct vfs_request); -void vfsreq_finish(struct vfs_request *, int ret); +void vfsreq_finish(struct vfs_request*, int ret, int flags, struct process *handler); /** Try to accept an enqueued request */ void vfs_backend_tryaccept(struct vfs_backend *); diff --git a/src/shared/syscalls.h b/src/shared/syscalls.h index bd26b43..b9be23d 100644 --- a/src/shared/syscalls.h +++ b/src/shared/syscalls.h @@ -5,6 +5,7 @@ #define FORK_NOREAP 1 #define FORK_NEWFS 2 #define OPEN_CREATE 1 +#define FSR_DELEGATE 1 enum { // idc about stable syscall numbers just yet |