summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/init/main.c6
-rw-r--r--src/init/syscalls.c4
-rw-r--r--src/kernel/syscalls.c31
-rw-r--r--src/shared/syscalls.h8
4 files changed, 25 insertions, 24 deletions
diff --git a/src/init/main.c b/src/init/main.c
index 5df6bb3..795e2ac 100644
--- a/src/init/main.c
+++ b/src/init/main.c
@@ -32,10 +32,8 @@ int main(void) {
}
void fs_prep(void) {
- handle_t front;
- front = _syscall_fs_create();
-
- if (!_syscall_fork()) {
+ handle_t front = _syscall_fs_fork2();
+ if (!front) {
tar_driver(&_initrd);
_syscall_exit(1);
}
diff --git a/src/init/syscalls.c b/src/init/syscalls.c
index e14dfe8..b535cae 100644
--- a/src/init/syscalls.c
+++ b/src/init/syscalls.c
@@ -34,8 +34,8 @@ int _syscall_close(handle_t handle) {
return _syscall(_SYSCALL_CLOSE, handle, 0, 0, 0);
}
-handle_t _syscall_fs_create(void) {
- return _syscall(_SYSCALL_FS_CREATE, 0, 0, 0, 0);
+handle_t _syscall_fs_fork2(void) {
+ return _syscall(_SYSCALL_FS_FORK2, 0, 0, 0, 0);
}
int _syscall_fs_wait(char __user *buf, int max_len, struct fs_wait_response __user *res) {
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index d5c2c8f..5cee090 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -165,29 +165,34 @@ int _syscall_close(handle_t handle) {
return -1;
}
-handle_t _syscall_fs_create(void) {
- handle_t front = 0;
+handle_t _syscall_fs_fork2(void) {
struct vfs_backend *backend;
+ struct process *child;
+ handle_t front;
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
+ if (front < 0) return -1;
process_current->handles[front].type = HANDLE_FS_FRONT;
+ /* so this can't return 0 in the parent or it will make it think that it's
+ * the child. i could make fork()s return -1 in the child but that's weird.
+ *
+ * also there's this whole thing with handling errors here properly and
+ * errno
+ * TODO figure this out */
+ if (front == 0) panic_unimplemented();
+
backend = kmalloc(sizeof *backend); // TODO never freed
backend->type = VFS_BACK_USER;
backend->handler = NULL;
backend->queue = NULL;
- process_current->handles[front].fs.backend = backend;
-
- process_current->controlled = backend;
+ child = process_fork(process_current);
+ child->controlled = backend;
+ regs_savereturn(&child->regs, 0);
+ process_current->handles[front].fs.backend = backend;
return front;
-fail:
- if (front >= 0)
- process_current->handles[front].type = HANDLE_EMPTY;
- return -1;
}
int _syscall_fs_wait(char __user *buf, int max_len, struct fs_wait_response __user *res) {
@@ -269,8 +274,8 @@ int _syscall(int num, int a, int b, int c, int d) {
return _syscall_write(a, (userptr_t)b, c, d);
case _SYSCALL_CLOSE:
return _syscall_close(a);
- case _SYSCALL_FS_CREATE:
- return _syscall_fs_create();
+ case _SYSCALL_FS_FORK2:
+ return _syscall_fs_fork2();
case _SYSCALL_FS_WAIT:
return _syscall_fs_wait((userptr_t)a, b, (userptr_t)c);
case _SYSCALL_FS_RESPOND:
diff --git a/src/shared/syscalls.h b/src/shared/syscalls.h
index 1779dc8..f136ed2 100644
--- a/src/shared/syscalls.h
+++ b/src/shared/syscalls.h
@@ -15,7 +15,7 @@ enum {
_SYSCALL_WRITE,
_SYSCALL_CLOSE,
- _SYSCALL_FS_CREATE,
+ _SYSCALL_FS_FORK2,
_SYSCALL_FS_WAIT,
_SYSCALL_FS_RESPOND,
@@ -47,10 +47,8 @@ int _syscall_read(handle_t, char __user *buf, int len, int offset);
int _syscall_write(handle_t, const char __user *buf, int len, int offset);
int _syscall_close(handle_t);
-/** Creates a pair of front/back filesystem handles.
- * @param back a pointer to a handle_t which will store the back pointer
- */
-handle_t _syscall_fs_create(void);
+handle_t _syscall_fs_fork2(void);
+
struct fs_wait_response {
int len; // how much was put in *buf
int id; // file id (returned by the open handler, passed to other calls)