diff options
author | Alex Auvolat <alex.auvolat@ens.fr> | 2015-02-19 18:25:29 +0100 |
---|---|---|
committer | Alex Auvolat <alex.auvolat@ens.fr> | 2015-02-19 18:25:29 +0100 |
commit | 277b329c5609b8172ad0c142117edfa9a08279da (patch) | |
tree | 23dc957e64e5b67e61072516bea30d650ffcefdd /src/kernel/user | |
parent | 408faed4df730384538aaa0e338ae8ea7abe400d (diff) | |
download | kogata-277b329c5609b8172ad0c142117edfa9a08279da.tar.gz kogata-277b329c5609b8172ad0c142117edfa9a08279da.zip |
Implement basic syscalls...
Diffstat (limited to 'src/kernel/user')
-rw-r--r-- | src/kernel/user/process.c | 32 | ||||
-rw-r--r-- | src/kernel/user/syscall.c | 220 |
2 files changed, 251 insertions, 1 deletions
diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c index 6cba0f7..3ee78a7 100644 --- a/src/kernel/user/process.c +++ b/src/kernel/user/process.c @@ -38,6 +38,9 @@ process_t *new_process(process_t *parent) { proc->filesystems = create_hashtbl(str_key_eq_fun, str_hash_fun, free_key); if (proc->filesystems == 0) goto error; + proc->files = create_hashtbl(id_key_eq_fun, id_hash_fun, 0); + if (proc->files == 0) goto error; + proc->regions_idx = create_btree(id_key_cmp_fun, 0); if (proc->regions_idx == 0) goto error; @@ -48,12 +51,14 @@ process_t *new_process(process_t *parent) { proc->thread = 0; proc->pid = (next_pid++); proc->parent = parent; + proc->next_fd = 1; return proc; error: if (proc && proc->regions_idx) delete_btree(proc->regions_idx); if (proc && proc->filesystems) delete_hashtbl(proc->filesystems); + if (proc && proc->files) delete_hashtbl(proc->files); if (proc) free(proc); return 0; } @@ -123,7 +128,32 @@ bool proc_add_fs(process_t *p, fs_t *fs, const char* name) { } fs_t *proc_find_fs(process_t *p, const char* name) { - return hashtbl_find(p->filesystems, name); + return (fs_t*)hashtbl_find(p->filesystems, name); +} + +void proc_remove_fs(process_t *p, const char* name) { + hashtbl_remove(p->filesystems, name); +} + +int proc_add_fd(process_t *p, fs_handle_t *f) { + int fd = p->next_fd++; + + bool add_ok = hashtbl_add(p->files, (void*)fd, f); + if (!add_ok) return 0; + + return fd; +} + +fs_handle_t *proc_read_fd(process_t *p, int fd) { + return (fs_handle_t*)hashtbl_find(p->files, (void*)fd); +} + +void proc_close_fd(process_t *p, int fd) { + fs_handle_t *x = proc_read_fd(p, fd); + if (x != 0) { + unref_file(x); + hashtbl_remove(p->files, (void*)fd); + } } // ============================= // 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) { |