summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/kernel/syscalls.c95
1 files changed, 54 insertions, 41 deletions
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index 0b22770..0730620 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -164,13 +164,7 @@ hid_t _sys_dup(hid_t from, hid_t to, int flags) {
SYSCALL_RETURN(hs_dup(proc_cur->hs, from, to, flags));
}
-static long simple_vfsop(
- enum vfs_op vfsop, hid_t hid, void __user *buf,
- size_t len, long offset, int flags)
-{
- assert(vfsop == VFSOP_READ
- || vfsop == VFSOP_WRITE
- || vfsop == VFSOP_GETSIZE);
+long _sys_read(hid_t hid, void __user *buf, size_t len, long offset) {
Handle *h = hs_get(proc_cur->hs, hid);
if (!h) {
SYSCALL_RETURN(-EBADF);
@@ -178,56 +172,75 @@ static long simple_vfsop(
if (h->type != HANDLE_FILE && h->type != HANDLE_PIPE) {
SYSCALL_RETURN(-ENOSYS);
}
-
- // TODO those checks really need some comprehensive tests
- if (vfsop == VFSOP_READ && !h->readable)
- SYSCALL_RETURN(-EACCES);
- if (vfsop == VFSOP_WRITE && !h->writeable)
+ if (!h->readable) {
SYSCALL_RETURN(-EACCES);
-
+ }
if (h->type == HANDLE_FILE) {
- VfsReq req = (VfsReq){
- .type = vfsop,
+ vfsreq_dispatchcopy((VfsReq) {
+ .type = VFSOP_READ,
.backend = h->backend,
.id = h->file_id,
.caller = proc_cur,
.offset = offset,
- .flags = flags,
- };
- if (vfsop == VFSOP_READ) {
- req.out = buf;
- req.outlen = len;
- }
- if (vfsop == VFSOP_WRITE) {
- req.uin = buf;
- req.uinlen = len;
- }
- vfsreq_dispatchcopy(req);
- } else if (h->type == HANDLE_PIPE) {
- if (vfsop == VFSOP_READ || vfsop == VFSOP_WRITE) {
- /* already checked if this is the correct pipe end */
- pipe_joinqueue(h, proc_cur, buf, len);
- } else SYSCALL_RETURN(-ENOSYS);
- } else {
- panic_invalid_state();
+ .out = buf,
+ .outlen = len,
+ });
+ } else { /* h->type == HANDLE_PIPE */
+ /* we already know this is the correct pipe end as it's readable */
+ pipe_joinqueue(h, proc_cur, buf, len);
}
return 0;
}
-long _sys_read(hid_t hid, void __user *buf, size_t len, long offset) {
- simple_vfsop(VFSOP_READ, hid, buf, len, offset, 0);
- return 0;
-}
-
long _sys_write(hid_t hid, const void __user *buf, size_t len, long offset, int flags) {
- if (flags & ~(WRITE_TRUNCATE))
+ Handle *h = hs_get(proc_cur->hs, hid);
+ if (flags & ~(WRITE_TRUNCATE)) {
SYSCALL_RETURN(-ENOSYS);
- simple_vfsop(VFSOP_WRITE, hid, (userptr_t)buf, len, offset, flags);
+ }
+ if (!h) {
+ SYSCALL_RETURN(-EBADF);
+ }
+ if (h->type != HANDLE_FILE && h->type != HANDLE_PIPE) {
+ SYSCALL_RETURN(-ENOSYS);
+ }
+ if (!h->writeable) {
+ SYSCALL_RETURN(-EACCES);
+ }
+ if (h->type == HANDLE_FILE) {
+ vfsreq_dispatchcopy((VfsReq) {
+ .type = VFSOP_WRITE,
+ .backend = h->backend,
+ .id = h->file_id,
+ .caller = proc_cur,
+ .offset = offset,
+ .flags = flags,
+ .uin = (void __user*)buf, // TODO why isn't this const
+ .uinlen = len,
+ });
+ } else { /* h->type == HANDLE_PIPE */
+ /* we already know this is the correct pipe end as it's writeable */
+ pipe_joinqueue(h, proc_cur, (void __user*)buf, len);
+ }
return 0;
}
long _sys_getsize(hid_t hid) {
- simple_vfsop(VFSOP_GETSIZE, hid, NULL, 0, 0, 0);
+ Handle *h = hs_get(proc_cur->hs, hid);
+ if (!h) {
+ SYSCALL_RETURN(-EBADF);
+ }
+ if (h->type != HANDLE_FILE) {
+ SYSCALL_RETURN(-ENOSYS);
+ }
+ if (!h->readable && !h->writeable) { /* is this even possible? */
+ SYSCALL_RETURN(-EACCES);
+ }
+ vfsreq_dispatchcopy((VfsReq) {
+ .type = VFSOP_GETSIZE,
+ .backend = h->backend,
+ .id = h->file_id,
+ .caller = proc_cur,
+ });
return 0;
}