summaryrefslogtreecommitdiff
path: root/src/kernel/vfs/request.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/vfs/request.c')
-rw-r--r--src/kernel/vfs/request.c36
1 files changed, 23 insertions, 13 deletions
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)