summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/init/fs/misc.c15
-rw-r--r--src/kernel/arch/i386/driver/fsroot.c4
-rw-r--r--src/kernel/arch/i386/driver/ps2.c8
-rw-r--r--src/kernel/arch/i386/driver/serial.c10
-rw-r--r--src/kernel/proc.c4
-rw-r--r--src/kernel/syscalls.c2
-rw-r--r--src/kernel/vfs/request.c36
-rw-r--r--src/kernel/vfs/request.h2
-rw-r--r--src/shared/syscalls.h1
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