summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authordzwdz2022-10-02 19:25:17 +0200
committerdzwdz2022-10-02 19:25:17 +0200
commit710e9b2b5c16f74f66420c66d12455ad518d42c7 (patch)
tree82b88cc07ef3f122512354d649af68584bd4da4d /src/kernel
parent503d9ff758f8b83295830bdfc8c2ea56837d25e5 (diff)
syscall/open: add the full suite of READ/WRITE flags
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/handle.h3
-rw-r--r--src/kernel/syscalls.c34
-rw-r--r--src/kernel/vfs/request.c11
-rw-r--r--src/kernel/vfs/request.h2
4 files changed, 33 insertions, 17 deletions
diff --git a/src/kernel/handle.h b/src/kernel/handle.h
index 6b095e5..3c16061 100644
--- a/src/kernel/handle.h
+++ b/src/kernel/handle.h
@@ -19,7 +19,8 @@ struct handle {
enum handle_type type;
struct vfs_backend *backend; // HANDLE_FILE | HANDLE_FS_FRONT
void __user *file_id; // only applicable to HANDLE_FILE
- bool ro; /* currently only for HANDLE_FILE */
+ // TODO readable/writeable could be reused for pipes
+ bool readable, writeable; /* currently only for HANDLE_FILE */
struct vfs_request *req; /* HANDLE_FS_REQ */
struct {
struct process *queued;
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index aa3c28f..dc8f9df 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -83,7 +83,7 @@ handle_t _syscall_open(const char __user *path, long len, int flags) {
struct vfs_mount *mount;
char *path_buf = NULL;
- if (flags & ~(OPEN_CREATE | OPEN_RO)) SYSCALL_RETURN(-ENOSYS);
+ if (flags & ~(OPEN_RW | OPEN_CREATE)) SYSCALL_RETURN(-ENOSYS);
if (PATH_MAX < len)
SYSCALL_RETURN(-1);
@@ -184,11 +184,16 @@ static long simple_vfsop(
enum vfs_operation vfsop, handle_t hid, void __user *buf,
size_t len, long offset, int flags)
{
- assert(vfsop != VFSOP_OPEN && vfsop != VFSOP_CLOSE);
+ assert(vfsop == VFSOP_READ
+ || vfsop == VFSOP_WRITE
+ || vfsop == VFSOP_GETSIZE);
struct handle *h = process_handle_get(process_current, hid);
if (!h) SYSCALL_RETURN(-1);
if (h->type == HANDLE_FILE) {
- if (h->ro && !(vfsop == VFSOP_READ || vfsop == VFSOP_GETSIZE))
+ // 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,
@@ -235,19 +240,22 @@ long _syscall_getsize(handle_t hid) {
long _syscall_remove(handle_t hid) {
struct handle *h = process_handle_get(process_current, hid);
if (!h) SYSCALL_RETURN(-EBADF);
- if (!h->ro && h->type == HANDLE_FILE) {
- vfsreq_create((struct vfs_request) {
- .type = VFSOP_REMOVE,
- .id = h->file_id,
- .caller = process_current,
- .backend = h->backend,
- });
+ if (h->type != HANDLE_FILE) {
process_handle_close(process_current, hid);
- return -1; // dummy
- } else {
+ SYSCALL_RETURN(-ENOSYS);
+ }
+ if (!h->writeable) {
process_handle_close(process_current, hid);
- SYSCALL_RETURN(h->ro ? -EACCES : -ENOSYS);
+ SYSCALL_RETURN(-EACCES);
}
+ vfsreq_create((struct vfs_request) {
+ .type = VFSOP_REMOVE,
+ .id = h->file_id,
+ .caller = process_current,
+ .backend = h->backend,
+ });
+ process_handle_close(process_current, hid);
+ return -1; // dummy
}
long _syscall_close(handle_t hid) {
diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c
index 24d5dac..0a377d3 100644
--- a/src/kernel/vfs/request.c
+++ b/src/kernel/vfs/request.c
@@ -23,8 +23,12 @@ void vfsreq_create(struct vfs_request req_) {
memcpy(req, &req_, sizeof *req);
if (req->backend) req->backend->refcount++;
- if (req->type == VFSOP_OPEN && (req->flags & OPEN_RO))
- req->flags &= ~OPEN_CREATE;
+ if (req->type == VFSOP_OPEN && !(req->flags & OPEN_WRITE) && (req->flags & OPEN_CREATE)) {
+ vfsreq_finish_short(req, -EINVAL);
+ return;
+ }
+
+ // TODO if i add a handle field to vfs_request, check ->readable ->writeable here
if (req->backend && req->backend->potential_handlers) {
struct vfs_request **iter = &req->backend->queue;
@@ -47,7 +51,8 @@ void vfsreq_finish(struct vfs_request *req, char __user *stored, long ret,
h = handle_init(HANDLE_FILE);
h->backend = req->backend; req->backend->refcount++;
h->file_id = stored;
- h->ro = req->flags & OPEN_RO;
+ h->readable = OPEN_READABLE(req->flags);
+ h->writeable = OPEN_WRITEABLE(req->flags);
} else {
/* delegating - moving a handle to the caller */
assert(handler);
diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h
index 4e309b0..db707d0 100644
--- a/src/kernel/vfs/request.h
+++ b/src/kernel/vfs/request.h
@@ -42,6 +42,8 @@ struct vfs_request {
size_t len;
} output;
+ // TODO why doesn't this just have a reference to the handle?
+
void __user *id; // handle.file.id
long offset;
int flags;