aboutsummaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/include/process.h8
-rw-r--r--src/kernel/user/process.c32
-rw-r--r--src/kernel/user/syscall.c220
3 files changed, 257 insertions, 3 deletions
diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h
index 5d9c3bf..07cc14e 100644
--- a/src/kernel/include/process.h
+++ b/src/kernel/include/process.h
@@ -18,7 +18,6 @@
#include <mmap.h>
-
#define USERSTACK_ADDR 0xB8000000
#define USERSTACK_SIZE 0x00020000 // 32 KB
@@ -29,6 +28,8 @@ typedef struct process {
btree_t *regions_idx;
hashtbl_t *filesystems;
+ hashtbl_t *files;
+ int next_fd;
thread_t *thread;
@@ -47,7 +48,10 @@ bool start_process(process_t *p, proc_entry_t entry); // maps a region for user
bool proc_add_fs(process_t *p, fs_t *fs, const char* name);
fs_t *proc_find_fs(process_t *p, const char* name);
-bool proc_rm_fs(process_t *p, const char* name);
+void proc_rm_fs(process_t *p, const char* name);
+int proc_add_fd(process_t *p, fs_handle_t *f); // on error returns 0, nonzero other<ise
+fs_handle_t *proc_read_fd(process_t *p, int fd);
+void proc_close_fd(process_t *p, int fd);
bool mmap(process_t *proc, void* addr, size_t size, int mode); // create empty zone
bool mmap_file(process_t *proc, fs_handle_t *h, size_t offset, void* addr, size_t size, int mode);
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) {