diff options
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/handle.h | 6 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 34 | ||||
-rw-r--r-- | src/kernel/vfs/backend.h | 1 |
3 files changed, 41 insertions, 0 deletions
diff --git a/src/kernel/handle.h b/src/kernel/handle.h index 0bf0f33..4ec8e57 100644 --- a/src/kernel/handle.h +++ b/src/kernel/handle.h @@ -10,6 +10,9 @@ typedef int handle_t; // TODO duplicated in syscalls.h enum handle_type { HANDLE_EMPTY, HANDLE_FILE, + + HANDLE_FS_FRONT, + HANDLE_FS_BACK, }; struct handle { @@ -19,5 +22,8 @@ struct handle { struct vfs_backend *backend; int id; } file; + struct { + struct vfs_backend *backend; + } fs; }; }; diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 6b0f4a2..5d792ce 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -161,6 +161,38 @@ int _syscall_close(handle_t handle) { return -1; } +handle_t _syscall_fs_create(user_ptr back_user) { + handle_t front, back = 0; + struct vfs_backend *backend; + + front = process_find_handle(process_current); + if (front < 0) goto fail; + // the type needs to be set here so process_find_handle skips this handle + process_current->handles[front].type = HANDLE_FS_FRONT; + + back = process_find_handle(process_current); + if (back < 0) goto fail; + process_current->handles[back].type = HANDLE_FS_BACK; + + // copy the back handle to back_user + if (!virt_cpy(process_current->pages, back_user, + NULL, (uintptr_t)&back, sizeof(handle_t))) + goto fail; + + backend = kmalloc(sizeof(struct vfs_backend)); + backend->type = VFS_BACK_USER; + process_current->handles[front].fs.backend = backend; + process_current->handles[back ].fs.backend = backend; + + return front; +fail: + if (front >= 0) + process_current->handles[front].type = HANDLE_EMPTY; + if (back >= 0) + process_current->handles[back].type = HANDLE_EMPTY; + return -1; +} + int syscall_handler(int num, int a, int b, int c) { switch (num) { case _SYSCALL_EXIT: @@ -179,6 +211,8 @@ int syscall_handler(int num, int a, int b, int c) { return _syscall_write(a, b, c); case _SYSCALL_CLOSE: return _syscall_close(a); + case _SYSCALL_FS_CREATE: + return _syscall_fs_create(a); default: tty_const("unknown syscall "); panic(); diff --git a/src/kernel/vfs/backend.h b/src/kernel/vfs/backend.h index 6a8bee6..fe46db1 100644 --- a/src/kernel/vfs/backend.h +++ b/src/kernel/vfs/backend.h @@ -3,6 +3,7 @@ enum vfs_backend_type { VFS_BACK_ROOT, + VFS_BACK_USER, }; // describes something which can acts as an access function |