aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/user/syscall.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/user/syscall.c')
-rw-r--r--src/kernel/user/syscall.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/src/kernel/user/syscall.c b/src/kernel/user/syscall.c
index ca5a65c..eee65d6 100644
--- a/src/kernel/user/syscall.c
+++ b/src/kernel/user/syscall.c
@@ -57,6 +57,14 @@ static uint32_t mmap_sc(sc_args_t args) {
return mmap(current_process(), (void*)args.a, args.b, args.c);
}
+static uint32_t mmap_file_sc(sc_args_t args) {
+ int fd = args.a;
+ fs_handle_t *h = proc_read_fd(current_process(), fd);
+ if (h == 0) return false;
+
+ return mmap_file(current_process(), h, args.b, (void*)args.c, args.d, args.e);
+}
+
static uint32_t mchmap_sc(sc_args_t args) {
return mchmap(current_process(), (void*)args.a, args.b);
}
@@ -65,6 +73,203 @@ static uint32_t munmap_sc(sc_args_t args) {
return munmap(current_process(), (void*)args.a);
}
+static uint32_t create_sc(sc_args_t args) {
+ bool ret = false;
+
+ char* fn = sc_copy_string(args.a, args.b);
+ if (fn == 0) goto end_create;
+
+ char* sep = strchr(fn, ':');
+ if (sep == 0) goto end_create;
+
+ *sep = 0;
+ char* file = sep + 1;
+
+ fs_t *fs = proc_find_fs(current_process(), fn);
+ if (fs == 0) goto end_create;
+
+ ret = fs_create(fs, file, args.c);
+
+end_create:
+ if (fn) free(fn);
+ return ret;
+}
+
+static uint32_t delete_sc(sc_args_t args) {
+ bool ret = false;
+
+ char* fn = sc_copy_string(args.a, args.b);
+ if (fn == 0) goto end_del;
+
+ char* sep = strchr(fn, ':');
+ if (sep == 0) goto end_del;
+
+ *sep = 0;
+ char* file = sep + 1;
+
+ fs_t *fs = proc_find_fs(current_process(), fn);
+ if (fs == 0) goto end_del;
+
+ ret = fs_delete(fs, file);
+
+end_del:
+ if (fn) free(fn);
+ return ret;
+}
+
+static uint32_t move_sc(sc_args_t args) {
+ bool ret = false;
+
+ char *fn_a = sc_copy_string(args.a, args.b),
+ *fn_b = sc_copy_string(args.c, args.d);
+ if (fn_a == 0 || fn_b == 0) goto end_move;
+
+ char* sep_a = strchr(fn_a, ':');
+ if (sep_a == 0) goto end_move;
+ *sep_a = 0;
+
+ char* sep_b = strchr(fn_b, ':');
+ if (sep_b == 0) goto end_move;
+ *sep_b = 0;
+
+ if (strcmp(fn_a, fn_b) != 0) goto end_move; // can only move within same FS
+
+ char *file_a = sep_a + 1, *file_b = sep_b + 1;
+
+ fs_t *fs = proc_find_fs(current_process(), fn_a);
+ if (fs == 0) goto end_move;
+
+ ret = fs_move(fs, file_a, file_b);
+
+end_move:
+ if (fn_a) free(fn_a);
+ if (fn_b) free(fn_b);
+ return ret;
+}
+
+static uint32_t stat_sc(sc_args_t args) {
+ bool ret = false;
+
+ char* fn = sc_copy_string(args.a, args.b);
+ if (fn == 0) goto end_stat;
+
+ char* sep = strchr(fn, ':');
+ if (sep == 0) goto end_stat;
+
+ *sep = 0;
+ char* file = sep + 1;
+
+ fs_t *fs = proc_find_fs(current_process(), fn);
+ if (fs == 0) goto end_stat;
+
+ probe_for_write((stat_t*)args.c, sizeof(stat_t));
+ ret = fs_stat(fs, file, (stat_t*)args.c);
+
+end_stat:
+ if (fn) free(fn);
+ return ret;
+}
+
+static uint32_t ioctl_sc(sc_args_t args) {
+ int ret = -1;
+
+ char* fn = sc_copy_string(args.a, args.b);
+ if (fn == 0) goto end_ioctl;
+
+ char* sep = strchr(fn, ':');
+ if (sep == 0) goto end_ioctl;
+
+ *sep = 0;
+ char* file = sep + 1;
+
+ fs_t *fs = proc_find_fs(current_process(), fn);
+ if (fs == 0) goto end_ioctl;
+
+ void* data = (void*)args.d;
+ if (data >= (void*)K_HIGHHALF_ADDR) goto end_ioctl;
+ ret = fs_ioctl(fs, file, args.c, data);
+
+end_ioctl:
+ if (fn) free(fn);
+ return ret;
+}
+
+static uint32_t open_sc(sc_args_t args) {
+ int ret = 0;
+
+ char* fn = sc_copy_string(args.a, args.b);
+ if (fn == 0) goto end_open;
+
+ char* sep = strchr(fn, ':');
+ if (sep == 0) goto end_open;
+
+ *sep = 0;
+ char* file = sep + 1;
+
+ fs_t *fs = proc_find_fs(current_process(), fn);
+ if (fs == 0) goto end_open;
+
+ fs_handle_t *h = fs_open(fs, file, args.c);
+ if (h == 0) goto end_open;
+
+ ret = proc_add_fd(current_process(), h);
+ if (ret == 0) unref_file(h);
+
+end_open:
+ if (fn) free(fn);
+ return ret;
+}
+
+static uint32_t close_sc(sc_args_t args) {
+ proc_close_fd(current_process(), args.a);
+ return 0;
+}
+
+static uint32_t read_sc(sc_args_t args) {
+ fs_handle_t *h = proc_read_fd(current_process(), args.a);
+ if (h == 0) return 0;
+
+ char* data = (char*)args.d;
+ size_t len = args.c;
+ probe_for_write(data, len);
+ return file_read(h, args.b, len, data);
+}
+
+static uint32_t write_sc(sc_args_t args) {
+ fs_handle_t *h = proc_read_fd(current_process(), args.a);
+ if (h == 0) return 0;
+
+ char* data = (char*)args.d;
+ size_t len = args.c;
+ probe_for_read(data, len);
+ return file_write(h, args.b, len, data);
+}
+
+static uint32_t readdir_sc(sc_args_t args) {
+ fs_handle_t *h = proc_read_fd(current_process(), args.a);
+ if (h == 0) return false;
+
+ dirent_t *o = (dirent_t*)args.b;
+ probe_for_write(o, sizeof(dirent_t));
+ return file_readdir(h, o);
+}
+
+static uint32_t stat_open_sc(sc_args_t args) {
+ fs_handle_t *h = proc_read_fd(current_process(), args.a);
+ if (h == 0) return false;
+
+ stat_t *o = (stat_t*)args.b;
+ probe_for_write(o, sizeof(stat_t));
+ return file_stat(h, o);
+}
+
+static uint32_t get_mode_sc(sc_args_t args) {
+ fs_handle_t *h = proc_read_fd(current_process(), args.a);
+ if (h == 0) return 0;
+
+ return file_get_mode(h);
+}
+
// ====================== //
// SYSCALLS SETUP ROUTINE //
// ====================== //
@@ -75,8 +280,23 @@ void setup_syscalls() {
sc_handlers[SC_DBG_PRINT] = dbg_print_sc;
sc_handlers[SC_MMAP] = mmap_sc;
+ sc_handlers[SC_MMAP_FILE] = mmap_file_sc;
sc_handlers[SC_MCHMAP] = mchmap_sc;
sc_handlers[SC_MUNMAP] = munmap_sc;
+
+ sc_handlers[SC_CREATE] = create_sc;
+ sc_handlers[SC_DELETE] = delete_sc;
+ sc_handlers[SC_MOVE] = move_sc;
+ sc_handlers[SC_STAT] = stat_sc;
+ sc_handlers[SC_IOCTL] = ioctl_sc;
+
+ sc_handlers[SC_OPEN] = open_sc;
+ sc_handlers[SC_CLOSE] = close_sc;
+ sc_handlers[SC_READ] = read_sc;
+ sc_handlers[SC_WRITE] = write_sc;
+ sc_handlers[SC_READDIR] = readdir_sc;
+ sc_handlers[SC_STAT_OPEN] = stat_open_sc;
+ sc_handlers[SC_GET_MODE] = get_mode_sc;
}
void syscall_handler(registers_t *regs) {