summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/kernel/handle.h4
-rw-r--r--src/kernel/pipe.c18
-rw-r--r--src/kernel/pipe.h3
-rw-r--r--src/kernel/syscalls.c19
4 files changed, 19 insertions, 25 deletions
diff --git a/src/kernel/handle.h b/src/kernel/handle.h
index 3c16061..19d5953 100644
--- a/src/kernel/handle.h
+++ b/src/kernel/handle.h
@@ -19,12 +19,10 @@ struct handle {
enum handle_type type;
struct vfs_backend *backend; // HANDLE_FILE | HANDLE_FS_FRONT
void __user *file_id; // only applicable to HANDLE_FILE
- // TODO readable/writeable could be reused for pipes
- bool readable, writeable; /* currently only for HANDLE_FILE */
+ bool readable, writeable; /* HANDLE_FILE | HANDLE_PIPE */
struct vfs_request *req; /* HANDLE_FS_REQ */
struct {
struct process *queued;
- bool write_end;
struct handle *sister; // the other end, not included in refcount
} pipe;
diff --git a/src/kernel/pipe.c b/src/kernel/pipe.c
index bf775b8..d9dc8a7 100644
--- a/src/kernel/pipe.c
+++ b/src/kernel/pipe.c
@@ -5,14 +5,9 @@
static void pipe_trytransfer(struct handle *h);
-void pipe_joinqueue(struct handle *h, bool wants_write,
- struct process *proc, void __user *pbuf, size_t pbuflen)
-{
+void pipe_joinqueue(struct handle *h, struct process *proc, void __user *pbuf, size_t pbuflen) {
assert(h && h->type == HANDLE_PIPE);
- if (wants_write == h->pipe.write_end) {
- regs_savereturn(&proc->regs, -1);
- return;
- }
+ assert(h->readable ^ h->writeable);
if (!h->pipe.sister) {
regs_savereturn(&proc->regs, -1);
return;
@@ -37,21 +32,20 @@ static void pipe_trytransfer(struct handle *h) {
struct process *rdr, *wtr;
struct virt_cpy_error cpyerr;
int len;
- assert(h);
+ assert(h && h->type == HANDLE_PIPE);
+ assert(h->readable ^ h->writeable);
if (!h->pipe.sister) {
assert(!h->pipe.queued);
return;
}
- rdr = h->pipe.write_end ? h->pipe.sister->pipe.queued : h->pipe.queued;
- wtr = h->pipe.write_end ? h->pipe.queued : h->pipe.sister->pipe.queued;
-
+ rdr = h->readable ? h->pipe.queued : h->pipe.sister->pipe.queued;
+ wtr = h->writeable ? h->pipe.queued : h->pipe.sister->pipe.queued;
if (!(rdr && wtr)) return;
assert(rdr->state == PS_WAITS4PIPE);
assert(wtr->state == PS_WAITS4PIPE);
len = min(rdr->waits4pipe.len, wtr->waits4pipe.len);
-
virt_cpy(
rdr->pages, rdr->waits4pipe.buf,
wtr->pages, wtr->waits4pipe.buf,
diff --git a/src/kernel/pipe.h b/src/kernel/pipe.h
index 2a90738..bcdfb86 100644
--- a/src/kernel/pipe.h
+++ b/src/kernel/pipe.h
@@ -3,7 +3,6 @@
#include <stdbool.h>
/* eventually transitions to PS_RUNNING */
-void pipe_joinqueue(struct handle *h, bool wants_write,
- struct process *proc, void __user *pbuf, size_t pbuflen);
+void pipe_joinqueue(struct handle *h, struct process *proc, void __user *pbuf, size_t pbuflen);
void pipe_invalidate_end(struct handle *h);
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index 6800138..88e98c6 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -187,13 +187,14 @@ static long simple_vfsop(
|| vfsop == VFSOP_WRITE
|| vfsop == VFSOP_GETSIZE);
struct handle *h = process_handle_get(process_current, hid);
- if (!h) SYSCALL_RETURN(-1);
+ if (!h) SYSCALL_RETURN(-EBADF);
+ // TODO those checks really need some comprehensive tests
+ if (vfsop == VFSOP_READ && !h->readable)
+ SYSCALL_RETURN(-EACCES);
+ if (vfsop == VFSOP_WRITE && !h->writeable)
+ SYSCALL_RETURN(-EACCES);
+
if (h->type == HANDLE_FILE) {
- // TODO those checks really need some comprehensive tests
- if (!h->readable && vfsop == VFSOP_READ)
- SYSCALL_RETURN(-EACCES);
- if (!h->writeable && vfsop == VFSOP_WRITE)
- SYSCALL_RETURN(-EACCES);
struct vfs_request req = (struct vfs_request){
.type = vfsop,
.backend = h->backend,
@@ -213,7 +214,8 @@ static long simple_vfsop(
vfsreq_create(req);
} else if (h->type == HANDLE_PIPE) {
if (vfsop == VFSOP_READ || vfsop == VFSOP_WRITE) {
- pipe_joinqueue(h, vfsop == VFSOP_READ, process_current, buf, len);
+ /* already checked if this is the correct pipe end */
+ pipe_joinqueue(h, process_current, buf, len);
} else SYSCALL_RETURN(-ENOSYS);
} else SYSCALL_RETURN(-ENOSYS);
return 0;
@@ -353,9 +355,10 @@ long _syscall_pipe(handle_t __user user_ends[2], int flags) {
process_handle_close(process_current, ends[1]);
SYSCALL_RETURN(-EMFILE);
}
- wend->pipe.write_end = true;
wend->pipe.sister = rend;
rend->pipe.sister = wend;
+ wend->writeable = true;
+ rend->readable = true;
virt_cpy_to(process_current->pages, user_ends, ends, sizeof ends);
SYSCALL_RETURN(0);