aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex.auvolat@ens.fr>2015-03-07 17:23:44 +0100
committerAlex Auvolat <alex.auvolat@ens.fr>2015-03-07 17:23:44 +0100
commitcb6cef08023bee0feeaa60a84d19bc52745bb2e4 (patch)
treed3496821926f438b1e7580234e29c57a617e270e
parent639ec6dd97a3d27fd249fa0509f0f8ebfd1f4c91 (diff)
downloadkogata-cb6cef08023bee0feeaa60a84d19bc52745bb2e4.tar.gz
kogata-cb6cef08023bee0feeaa60a84d19bc52745bb2e4.zip
Implement some missing syscalls.
-rw-r--r--src/common/include/syscallproto.h7
-rw-r--r--src/kernel/include/process.h3
-rw-r--r--src/kernel/user/process.c33
-rw-r--r--src/kernel/user/syscall.c193
-rw-r--r--src/lib/include/syscall.h1
-rw-r--r--src/lib/libkogata/syscall.c14
6 files changed, 227 insertions, 24 deletions
diff --git a/src/common/include/syscallproto.h b/src/common/include/syscallproto.h
index 518cdb4..4cfd9ae 100644
--- a/src/common/include/syscallproto.h
+++ b/src/common/include/syscallproto.h
@@ -37,7 +37,8 @@
#define SC_NEW_PROC 50 // args: nothing ?
#define SC_BIND_FS 51 // args: pid, new_name, new_name_strlen, fs_name, fs_name_strlen -- bind FS to child process
#define SC_BIND_SUBFS 52 // args: sc_subfs_args_t -- subfs & bind to child process
-#define SC_BIND_FD 53 // args: pid, new_fd, local_fd -- copy a file descriptor to child process
+#define SC_BIND_MAKE_FS 53 // args: sc_make_fs_args_t
+#define SC_BIND_FD 54 // args: pid, new_fd, local_fd -- copy a file descriptor to child process
#define SC_PROC_EXEC 55 // args: pid, exec_name, exec_name_strlen -- execute binary in process
#define SC_PROC_STATUS 56 // args: pid, proc_status_t*
#define SC_PROC_KILL 57 // args: pid, proc_status_t* -- inconditionnally kill child process
@@ -56,6 +57,8 @@ typedef struct {
const char* opts;
size_t opts_strlen;
+
+ int bind_to_pid; // zero = bind to current proc
} sc_make_fs_args_t;
typedef struct {
@@ -70,7 +73,7 @@ typedef struct {
int ok_modes;
- int bind_to_pid; // used only for SC_BIND_SUBFS
+ int bind_to_pid; // 0 = bind to current proc
} sc_subfs_args_t;
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h
index def3397..8dfa274 100644
--- a/src/kernel/include/process.h
+++ b/src/kernel/include/process.h
@@ -86,7 +86,7 @@ void process_thread_deleted(thread_t *t); // called by threading code when a th
process_t *process_find_child(process_t *p, int pid);
void process_get_status(process_t *p, proc_status_t *st);
void process_wait(process_t *p, proc_status_t *st, bool block); // waits for exit and frees process_t structure
-void process_wait_any_child(process_t *p, bool block);
+void process_wait_any_child(process_t *p, proc_status_t *st, bool block);
// ---- Process FS namespace & FD set
@@ -94,6 +94,7 @@ bool proc_add_fs(process_t *p, fs_t *fs, const char* name);
fs_t *proc_find_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
+bool proc_add_fd_as(process_t *p, fs_handle_t *f, int fd);
fs_handle_t *proc_read_fd(process_t *p, int fd);
void proc_close_fd(process_t *p, int fd);
diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c
index 0a757b4..973e9d8 100644
--- a/src/kernel/user/process.c
+++ b/src/kernel/user/process.c
@@ -267,6 +267,28 @@ void process_thread_deleted(thread_t *t) {
process_exit(p, PS_FINISHED, 0);
}
+// =========================== //
+// PROCESS CHILDREN MANAGEMENT //
+// =========================== //
+
+process_t *process_find_child(process_t *p, int pid) {
+ process_t *ret = 0;
+
+ mutex_lock(&p->lock);
+
+ for (process_t *it = p->children; it != 0; it = it->next_child) {
+ if (it->pid == pid) {
+ ret = it;
+ break;
+ }
+ }
+
+ mutex_unlock(&p->lock);
+
+ return ret;
+
+}
+
// ================================== //
// MANAGING FILESYSTEMS FOR PROCESSES //
@@ -289,7 +311,7 @@ fs_t *proc_find_fs(process_t *p, const char* name) {
return (fs_t*)hashtbl_find(p->filesystems, name);
}
-void proc_remove_fs(process_t *p, const char* name) {
+void proc_rm_fs(process_t *p, const char* name) {
fs_t *fs = proc_find_fs(p, name);
if (fs) {
unref_fs(fs);
@@ -306,6 +328,15 @@ int proc_add_fd(process_t *p, fs_handle_t *f) {
return fd;
}
+bool proc_add_fd_as(process_t *p, fs_handle_t *f, int fd) {
+ if (hashtbl_find(p->files, (void*)fd) != 0) return false;
+
+ if (fd >= p->next_fd) p->next_fd = fd + 1;
+
+ bool add_ok = hashtbl_add(p->files, (void*)fd, f);
+ return add_ok;
+}
+
fs_handle_t *proc_read_fd(process_t *p, int fd) {
return (fs_handle_t*)hashtbl_find(p->files, (void*)fd);
}
diff --git a/src/kernel/user/syscall.c b/src/kernel/user/syscall.c
index 73b3341..fe9b4fe 100644
--- a/src/kernel/user/syscall.c
+++ b/src/kernel/user/syscall.c
@@ -12,8 +12,7 @@ typedef uint32_t (*syscall_handler_t)(sc_args_t);
static syscall_handler_t sc_handlers[SC_MAX] = { 0 };
-static char* sc_copy_string(uint32_t s, uint32_t slen) {
- const char* addr = (const char*)s;
+static char* sc_copy_string(const char* addr, size_t slen) {
probe_for_read(addr, slen);
char* buf = malloc(slen+1);
@@ -25,6 +24,10 @@ static char* sc_copy_string(uint32_t s, uint32_t slen) {
return buf;
}
+static char* sc_copy_string_x(uint32_t s, uint32_t slen) {
+ return sc_copy_string((const char*)s, slen);
+}
+
// ==================== //
// THE SYSCALLS CODE !! //
// ==================== //
@@ -50,7 +53,7 @@ static uint32_t usleep_sc(sc_args_t args) {
}
static uint32_t dbg_print_sc(sc_args_t args) {
- char* msg = sc_copy_string(args.a, args.b);
+ char* msg = sc_copy_string_x(args.a, args.b);
if (msg == 0) return -1;
dbg_print(msg);
@@ -86,7 +89,7 @@ static uint32_t munmap_sc(sc_args_t args) {
static uint32_t create_sc(sc_args_t args) {
bool ret = false;
- char* fn = sc_copy_string(args.a, args.b);
+ char* fn = sc_copy_string_x(args.a, args.b);
if (fn == 0) goto end_create;
char* sep = strchr(fn, ':');
@@ -108,7 +111,7 @@ end_create:
static uint32_t delete_sc(sc_args_t args) {
bool ret = false;
- char* fn = sc_copy_string(args.a, args.b);
+ char* fn = sc_copy_string_x(args.a, args.b);
if (fn == 0) goto end_del;
char* sep = strchr(fn, ':');
@@ -130,8 +133,8 @@ end_del:
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);
+ char *fn_a = sc_copy_string_x(args.a, args.b),
+ *fn_b = sc_copy_string_x(args.c, args.d);
if (fn_a == 0 || fn_b == 0) goto end_move;
char* sep_a = strchr(fn_a, ':');
@@ -160,7 +163,7 @@ end_move:
static uint32_t stat_sc(sc_args_t args) {
bool ret = false;
- char* fn = sc_copy_string(args.a, args.b);
+ char* fn = sc_copy_string_x(args.a, args.b);
if (fn == 0) goto end_stat;
char* sep = strchr(fn, ':');
@@ -185,7 +188,7 @@ end_stat:
static uint32_t open_sc(sc_args_t args) {
int ret = 0;
- char* fn = sc_copy_string(args.a, args.b);
+ char* fn = sc_copy_string_x(args.a, args.b);
if (fn == 0) goto end_open;
char* sep = strchr(fn, ':');
@@ -270,37 +273,186 @@ static uint32_t get_mode_sc(sc_args_t args) {
// ---- Managing file systems
static uint32_t make_fs_sc(sc_args_t args) {
- return -1; // TODO
+ sc_make_fs_args_t *a = (sc_make_fs_args_t*)args.a;
+ probe_for_read(a, sizeof(sc_make_fs_args_t));
+
+ bool ok = false;
+
+ char* driver = 0;
+ char* fs_name = 0;
+ char* opts = 0;
+ fs_t *the_fs = 0;
+
+ process_t *p;
+ if (a->bind_to_pid == 0) {
+ p = current_process();
+ } else {
+ p = process_find_child(current_process(), a->bind_to_pid);
+ if (p == 0) goto end_mk_fs;
+ }
+
+ fs_handle_t *source = 0;
+ if (a->source_fd != 0) {
+ source = proc_read_fd(current_process(), a->source_fd);
+ if (!source) goto end_mk_fs;
+ }
+
+ driver = sc_copy_string(a->driver, a->driver_strlen);
+ if (!driver) goto end_mk_fs;
+
+ fs_name = sc_copy_string(a->fs_name, a->fs_name_strlen);
+ if (!fs_name) goto end_mk_fs;
+
+ opts = sc_copy_string(a->opts, a->opts_strlen);
+ if (!opts) goto end_mk_fs;
+
+ the_fs = make_fs(driver, source, opts);
+ if (!the_fs) goto end_mk_fs;
+
+ ok = proc_add_fs(p, the_fs, fs_name);
+
+end_mk_fs:
+ if (driver) free(driver);
+ if (fs_name) free(fs_name);
+ if (opts) free(opts);
+ if (the_fs && !ok) unref_fs(the_fs);
+ return ok;
}
static uint32_t fs_add_src_sc(sc_args_t args) {
- return -1; //TODO
+ bool ok = false;
+
+ char* opts = 0;
+ char* fs_name = 0;
+
+ fs_name = sc_copy_string_x(args.a, args.b);
+ if (fs_name == 0) goto end_add_src;
+
+ opts = sc_copy_string_x(args.d, args.e);
+ if (opts == 0) goto end_add_src;
+
+ fs_t *fs = proc_find_fs(current_process(), fs_name);
+ if (fs == 0) goto end_add_src;
+
+ fs_handle_t *src = proc_read_fd(current_process(), args.c);
+ if (src == 0) goto end_add_src;
+
+ ok = fs_add_source(fs, src, opts);
+
+end_add_src:
+ if (fs_name) free(fs_name);
+ if (opts) free(opts);
+ return ok;
}
static uint32_t fs_subfs_sc(sc_args_t args) {
- return -1; //TODO
+ sc_subfs_args_t *a = (sc_subfs_args_t*)args.a;
+ probe_for_read(a, sizeof(sc_subfs_args_t));
+
+ bool ok = false;
+
+ char* new_name = 0;
+ char* from_fs = 0;
+ char* root = 0;
+ fs_t* new_fs = 0;
+
+ process_t *p;
+ if (a->bind_to_pid == 0) {
+ p = current_process();
+ } else {
+ p = process_find_child(current_process(), a->bind_to_pid);
+ if (p == 0) goto end_subfs;
+ }
+
+ new_name = sc_copy_string(a->new_name, a->new_name_strlen);
+ if (!new_name) goto end_subfs;
+
+ from_fs = sc_copy_string(a->from_fs, a->from_fs_strlen);
+ if (!from_fs) goto end_subfs;
+
+ root = sc_copy_string(a->root, a->root_strlen);
+ if (!root) goto end_subfs;
+
+ fs_t *orig_fs = proc_find_fs(current_process(), from_fs);
+ if (!orig_fs) goto end_subfs;
+
+ new_fs = fs_subfs(orig_fs, root, a->ok_modes);
+ if (!new_fs) goto end_subfs;
+
+ ok = proc_add_fs(p, new_fs, new_name);
+
+end_subfs:
+ if (new_name) free(new_name);
+ if (from_fs) free(from_fs);
+ if (root) free(root);
+ if (new_fs && !ok) unref_fs(new_fs);
+ return ok;
}
static uint32_t rm_fs_sc(sc_args_t args) {
- return -1; //TODO
+ char* fs_name = sc_copy_string_x(args.a, args.b);
+ if (fs_name == 0) return false;
+
+ proc_rm_fs(current_process(), fs_name);
+ free(fs_name);
+ return true;
}
// ---- Spawning new processes & giving them ressources
static uint32_t new_proc_sc(sc_args_t args) {
- return -1; //TODO
+ process_t *new_proc = new_process(current_process());
+ if (new_proc == 0) return 0;
+
+ return new_proc->pid;
}
static uint32_t bind_fs_sc(sc_args_t args) {
- return -1; //TODO
-}
+ bool ok = false;
-static uint32_t bind_subfs_sc(sc_args_t args) {
- return -1; //TODO
+ char* old_name = 0;
+ char* new_name = 0;
+ fs_t* fs = 0;
+
+ process_t *p = process_find_child(current_process(), args.a);
+ if (p == 0) goto end_bind_fs;
+
+ new_name = sc_copy_string_x(args.b, args.c);
+ if (!new_name) goto end_bind_fs;
+
+ old_name = sc_copy_string_x(args.d, args.e);
+ if (!old_name) goto end_bind_fs;
+
+ fs = proc_find_fs(current_process(), old_name);
+ if (!fs) goto end_bind_fs;
+
+ ref_fs(fs);
+ ok = proc_add_fs(p, fs, new_name);
+
+end_bind_fs:
+ if (old_name) free(old_name);
+ if (new_name) free(new_name);
+ if (fs && !ok) unref_fs(fs);
+ return ok;
}
static uint32_t bind_fd_sc(sc_args_t args) {
- return -1; //TODO
+ bool ok = false;
+
+ fs_handle_t *h = 0;
+
+ process_t *p = process_find_child(current_process(), args.a);
+ if (p == 0) goto end_bind_fd;
+
+ h = proc_read_fd(current_process(), args.c);
+ if (h == 0) goto end_bind_fd;
+
+ ref_file(h);
+ ok = proc_add_fd_as(p, h, args.b);
+
+end_bind_fd:
+ if (h && !ok) unref_file(h);
+ return ok;
}
static uint32_t proc_exec_sc(sc_args_t args) {
@@ -355,7 +507,8 @@ void setup_syscall_table() {
sc_handlers[SC_NEW_PROC] = new_proc_sc;
sc_handlers[SC_BIND_FS] = bind_fs_sc;
- sc_handlers[SC_BIND_SUBFS] = bind_subfs_sc;
+ sc_handlers[SC_BIND_SUBFS] = fs_subfs_sc; // no bind_subfs_sc;
+ sc_handlers[SC_BIND_MAKE_FS] = make_fs_sc; // no bind_make_fs_sc;
sc_handlers[SC_BIND_FD] = bind_fd_sc;
sc_handlers[SC_PROC_EXEC] = proc_exec_sc;
sc_handlers[SC_PROC_STATUS] = proc_status_sc;
diff --git a/src/lib/include/syscall.h b/src/lib/include/syscall.h
index ddc0e18..b94c7fd 100644
--- a/src/lib/include/syscall.h
+++ b/src/lib/include/syscall.h
@@ -45,6 +45,7 @@ void fs_remove(const char* name);
pid_t new_proc();
bool bind_fs(pid_t pid, const char* new_name, const char* fs);
bool bind_subfs(pid_t pid, const char* new_name, const char* fs, const char* root, int ok_modes);
+bool bind_make_fs(pid_t pid, const char* name, const char* driver, fd_t source, const char* options);
bool bind_fd(pid_t pid, fd_t new_fd, fd_t fd);
bool proc_exec(pid_t pid, const char* file);
bool proc_status(pid_t pid, proc_status_t *s);
diff --git a/src/lib/libkogata/syscall.c b/src/lib/libkogata/syscall.c
index 4b31ab3..37b2a1a 100644
--- a/src/lib/libkogata/syscall.c
+++ b/src/lib/libkogata/syscall.c
@@ -99,6 +99,7 @@ bool make_fs(const char* name, const char* driver, fd_t source, const char* opti
.source_fd = source,
.opts = options,
.opts_strlen = strlen(options),
+ .bind_to_pid = 0,
};
return call(SC_MAKE_FS, (uint32_t)&args, 0, 0, 0, 0);
}
@@ -141,6 +142,19 @@ bool bind_subfs(pid_t pid, const char* new_name, const char* orig_fs, const char
};
return call(SC_BIND_SUBFS, (uint32_t)&args, 0, 0, 0, 0);
}
+bool bind_make_fs(pid_t pid, const char* name, const char* driver, fd_t source, const char* options) {
+ sc_make_fs_args_t args = {
+ .driver = driver,
+ .driver_strlen = strlen(driver),
+ .fs_name = name,
+ .fs_name_strlen = strlen(name),
+ .source_fd = source,
+ .opts = options,
+ .opts_strlen = strlen(options),
+ .bind_to_pid = pid,
+ };
+ return call(SC_BIND_MAKE_FS, (uint32_t)&args, 0, 0, 0, 0);
+}
bool bind_fd(pid_t pid, fd_t new_fd, fd_t fd) {
return call(SC_BIND_FD, new_fd, fd, 0, 0, 0);
}