summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordzwdz2022-06-29 21:52:15 +0200
committerdzwdz2022-06-29 21:52:15 +0200
commitbf4cbc830d78774ac00d9501c45e8b84d0ae9ae7 (patch)
treef302f92badf74dade9e724e37f85d1ee2dd99833 /src
parent43de6a4d8ead1e609828ef34ad1957d34c94ee6a (diff)
kernel/vfs: add the OPEN_CREATE flag
Diffstat (limited to 'src')
-rw-r--r--src/init/driver/ansiterm.c6
-rw-r--r--src/init/driver/ps2.c6
-rw-r--r--src/init/fs/misc.c11
-rw-r--r--src/init/main.c12
-rw-r--r--src/init/shell.c15
-rw-r--r--src/init/stdlib.c4
-rw-r--r--src/init/stdlib.h2
-rw-r--r--src/init/syscalls.c4
-rw-r--r--src/init/tar.c4
-rw-r--r--src/init/tests/main.c4
-rw-r--r--src/kernel/arch/i386/driver/fsroot.c2
-rw-r--r--src/kernel/arch/i386/driver/ps2.c5
-rw-r--r--src/kernel/arch/i386/driver/serial.c5
-rw-r--r--src/kernel/syscalls.c5
-rw-r--r--src/kernel/vfs/request.c1
-rw-r--r--src/kernel/vfs/request.h1
-rw-r--r--src/shared/syscalls.h4
17 files changed, 63 insertions, 28 deletions
diff --git a/src/init/driver/ansiterm.c b/src/init/driver/ansiterm.c
index 01ad984..60aad72 100644
--- a/src/init/driver/ansiterm.c
+++ b/src/init/driver/ansiterm.c
@@ -56,7 +56,7 @@ static void in_char(char c) {
}
void ansiterm_drv(void) {
- vga_fd = _syscall_open("/vga", 4);
+ vga_fd = _syscall_open("/vga", 4, 0);
_syscall_read(vga_fd, vga, sizeof vga, 0);
// find first empty line
@@ -78,6 +78,10 @@ void ansiterm_drv(void) {
while (!_syscall_fs_wait(buf, sizeof buf, &res)) {
switch (res.op) {
case VFSOP_OPEN:
+ if (res.flags & OPEN_CREATE) {
+ _syscall_fs_respond(NULL, -1);
+ break;
+ }
// TODO check path
_syscall_fs_respond(NULL, 1);
break;
diff --git a/src/init/driver/ps2.c b/src/init/driver/ps2.c
index b2d42e5..0c6d548 100644
--- a/src/init/driver/ps2.c
+++ b/src/init/driver/ps2.c
@@ -51,6 +51,10 @@ static void main_loop(void) {
while (!_syscall_fs_wait(buf, sizeof buf, &res)) {
switch (res.op) {
case VFSOP_OPEN:
+ if (res.flags & OPEN_CREATE) {
+ _syscall_fs_respond(NULL, -1);
+ break;
+ }
_syscall_fs_respond(NULL, 1);
break;
@@ -74,7 +78,7 @@ static void main_loop(void) {
}
void ps2_drv(void) {
- fd = _syscall_open("/ps2", 4);
+ fd = _syscall_open("/ps2", 4, 0);
if (fd < 0) _syscall_exit(1);
main_loop();
diff --git a/src/init/fs/misc.c b/src/init/fs/misc.c
index f4965d5..914cfb2 100644
--- a/src/init/fs/misc.c
+++ b/src/init/fs/misc.c
@@ -105,10 +105,10 @@ void fs_passthru(const char *prefix) {
memcpy(tmp, buf, res.len);
memcpy(buf, prefix, prefix_len);
memcpy(buf + prefix_len, tmp, res.len);
- ret = _syscall_open(buf, res.len + prefix_len);
+ ret = _syscall_open(buf, res.len + prefix_len, res.flags);
} else ret = -1;
} else {
- ret = _syscall_open(buf, res.len);
+ ret = _syscall_open(buf, res.len, res.flags);
}
_syscall_fs_respond(NULL, ret);
break;
@@ -147,7 +147,7 @@ void fs_dir_inject(const char *path) {
}
if (hid < 0) _syscall_fs_respond(NULL, -2); // we ran out of handles
- ret = _syscall_open(buf, res.len); /* errors handled in inject handler */
+ ret = _syscall_open(buf, res.len, res.flags); /* errors handled in inject handler */
handles[hid].delegate = ret;
handles[hid].inject = NULL;
handles[hid].taken = true;
@@ -155,9 +155,12 @@ void fs_dir_inject(const char *path) {
if (buf[res.len - 1] == '/' &&
res.len < path_len && !memcmp(path, buf, res.len)) {
handles[hid].inject = path + res.len;
+
+ /* if we're making up the opened directory, disallow create */
+ if (ret < 0 && (res.flags & OPEN_CREATE)) hid = ret;
} else {
/* not injecting, don't allow opening nonexistent stuff */
- if (ret < 0) _syscall_fs_respond(NULL, ret);
+ if (ret < 0) hid = ret;
}
_syscall_fs_respond(NULL, hid);
break;
diff --git a/src/init/main.c b/src/init/main.c
index 998db9c..198bd88 100644
--- a/src/init/main.c
+++ b/src/init/main.c
@@ -19,7 +19,7 @@ int main(void) {
// allocate bss
_syscall_memflag(&_bss_start, &_bss_end - &_bss_start, MEMFLAG_PRESENT);
- file_open(&__stdout, "/com1");
+ file_open(&__stdout, "/com1", 0);
printf("preinit\n");
MOUNT("/init/", tar_driver(&_initrd));
@@ -48,7 +48,7 @@ int main(void) {
}
if (!_syscall_fork(0, NULL)) {
- if (file_open(&__stdout, "/com1") < 0 || file_open(&__stdin, "/com1") < 0)
+ if (file_open(&__stdout, "/com1", 0) < 0 || file_open(&__stdin, "/com1", 0) < 0)
_syscall_exit(1);
shell_loop();
@@ -57,10 +57,10 @@ int main(void) {
if (!_syscall_fork(0, NULL)) {
- if (file_open(&__stdout, "/vga_tty") < 0)
+ if (file_open(&__stdout, "/vga_tty", 0) < 0)
_syscall_exit(1);
- if (file_open(&__stdin, "/keyboard") < 0) {
+ if (file_open(&__stdin, "/keyboard", 0) < 0) {
printf("couldn't open /keyboard\n");
_syscall_exit(1);
}
@@ -71,8 +71,8 @@ int main(void) {
// try to find any working output
- if (file_open(&__stdout, "/com1") < 0)
- file_open(&__stdout, "/vga_tty");
+ if (file_open(&__stdout, "/com1", 0) < 0)
+ file_open(&__stdout, "/vga_tty", 0);
_syscall_await();
printf("init: quitting\n");
diff --git a/src/init/shell.c b/src/init/shell.c
index 105231e..edcd480 100644
--- a/src/init/shell.c
+++ b/src/init/shell.c
@@ -63,7 +63,7 @@ static void cmd_cat_ls(const char *args, bool ls) {
}
}
- if (file_open(&file, buf) < 0) {
+ if (file_open(&file, buf, 0) < 0) {
printf("couldn't open.\n");
return;
}
@@ -85,7 +85,7 @@ static void cmd_hexdump(const char *args) {
static uint8_t buf[512];
int fd, len;
- fd = _syscall_open(args, strlen(args));
+ fd = _syscall_open(args, strlen(args), 0);
if (fd < 0) {
printf("couldn't open.\n");
return;
@@ -113,6 +113,15 @@ static void cmd_hexdump(const char *args) {
_syscall_close(fd);
}
+static void cmd_touch(const char *args) {
+ int fd = _syscall_open(args, strlen(args), OPEN_CREATE);
+ if (fd < 0) {
+ printf("couldn't create file.\n");
+ return;
+ }
+ _syscall_close(fd);
+}
+
void shell_loop(void) {
static char cmd[256];
int level = 0;
@@ -140,6 +149,8 @@ void shell_loop(void) {
cmd_cat_ls(files[i], false);
printf("\n");
}
+ } else if (!strcmp(cmd, "touch")) {
+ cmd_touch(args);
} else if (!strcmp(cmd, "shadow")) {
_syscall_mount(-1, args, strlen(args));
} else if (!strcmp(cmd, "exit")) {
diff --git a/src/init/stdlib.c b/src/init/stdlib.c
index f59635e..9b7a329 100644
--- a/src/init/stdlib.c
+++ b/src/init/stdlib.c
@@ -18,10 +18,10 @@ int printf(const char *fmt, ...) {
return ret;
}
-int file_open(libc_file *f, const char *path) {
+int file_open(libc_file *f, const char *path, int flags) {
f->pos = 0;
f->eof = false;
- f->fd = _syscall_open(path, strlen(path));
+ f->fd = _syscall_open(path, strlen(path), flags);
if (f->fd < 0) return f->fd;
return 0;
}
diff --git a/src/init/stdlib.h b/src/init/stdlib.h
index b1709e0..3dc1c81 100644
--- a/src/init/stdlib.h
+++ b/src/init/stdlib.h
@@ -11,7 +11,7 @@ typedef struct {
int pos;
bool eof;
} libc_file;
-int file_open(libc_file*, const char *path); // TODO return a libc_file*
+int file_open(libc_file*, const char *path, int flags); // TODO return a libc_file*
int file_read(libc_file*, char *buf, size_t len);
int file_write(libc_file*, const char *buf, size_t len);
void file_close(libc_file*);
diff --git a/src/init/syscalls.c b/src/init/syscalls.c
index 7c3664c..e48043f 100644
--- a/src/init/syscalls.c
+++ b/src/init/syscalls.c
@@ -18,8 +18,8 @@ int _syscall_fork(int flags, handle_t __user *fs_front) {
return _syscall(_SYSCALL_FORK, flags, (int)fs_front, 0, 0);
}
-handle_t _syscall_open(const char __user *path, int len) {
- return _syscall(_SYSCALL_OPEN, (int)path, len, 0, 0);
+handle_t _syscall_open(const char __user *path, int len, int flags) {
+ return _syscall(_SYSCALL_OPEN, (int)path, len, flags, 0);
}
int _syscall_mount(handle_t h, const char __user *path, int len) {
diff --git a/src/init/tar.c b/src/init/tar.c
index c289edc..ce8c066 100644
--- a/src/init/tar.c
+++ b/src/init/tar.c
@@ -21,6 +21,10 @@ void tar_driver(void *base) {
while (!_syscall_fs_wait(buf, BUF_SIZE, &res)) {
switch (res.op) {
case VFSOP_OPEN:
+ if (res.flags & OPEN_CREATE) {
+ _syscall_fs_respond(NULL, -1);
+ break;
+ }
_syscall_fs_respond(NULL, tar_open(buf, res.len, base, ~0));
break;
diff --git a/src/init/tests/main.c b/src/init/tests/main.c
index d895289..1260a35 100644
--- a/src/init/tests/main.c
+++ b/src/init/tests/main.c
@@ -74,7 +74,7 @@ static void test_interrupted_fs(void) {
_syscall_exit(0);
} else { /* parent */
_syscall_mount(h, "/", 1);
- int ret = _syscall_open("/", 1);
+ int ret = _syscall_open("/", 1, 0);
// the handler quits while handling that call - but this syscall should return anyways
_syscall_exit(ret < 0 ? 0 : -1);
}
@@ -86,7 +86,7 @@ static void test_orphaned_fs(void) {
_syscall_exit(0);
} else { /* parent */
_syscall_mount(h, "/", 1);
- int ret = _syscall_open("/", 1);
+ int ret = _syscall_open("/", 1, 0);
// no handler will ever be available to handle this call - the syscall should instantly return
_syscall_exit(ret < 0 ? 0 : -1);
}
diff --git a/src/kernel/arch/i386/driver/fsroot.c b/src/kernel/arch/i386/driver/fsroot.c
index e6e53cd..4207541 100644
--- a/src/kernel/arch/i386/driver/fsroot.c
+++ b/src/kernel/arch/i386/driver/fsroot.c
@@ -47,6 +47,8 @@ static int handle(struct vfs_request *req) {
assert(req->caller);
switch (req->type) {
case VFSOP_OPEN:
+ if (req->flags & OPEN_CREATE) return -1;
+
if (exacteq(req, "/")) return HANDLE_ROOT;
if (exacteq(req, "/vga")) return HANDLE_VGA;
diff --git a/src/kernel/arch/i386/driver/ps2.c b/src/kernel/arch/i386/driver/ps2.c
index b7e82eb..e1e97c0 100644
--- a/src/kernel/arch/i386/driver/ps2.c
+++ b/src/kernel/arch/i386/driver/ps2.c
@@ -31,10 +31,11 @@ static void accept(struct vfs_request *req) {
// when you fix something here go also fix it in the COM1 driver
static uint8_t buf[32]; // pretty damn stupid
int ret;
+ bool valid;
switch (req->type) {
case VFSOP_OPEN:
- ret = req->input.len == 0 ? 0 : -1;
- vfsreq_finish(req, 0);
+ valid = req->input.len == 0 && !(req->flags & OPEN_CREATE);
+ vfsreq_finish(req, valid ? 0 : -1);
break;
case VFSOP_READ:
if (ring_size((void*)&backlog) == 0) {
diff --git a/src/kernel/arch/i386/driver/serial.c b/src/kernel/arch/i386/driver/serial.c
index cda016c..b776d0c 100644
--- a/src/kernel/arch/i386/driver/serial.c
+++ b/src/kernel/arch/i386/driver/serial.c
@@ -69,10 +69,11 @@ void serial_write(const char *buf, size_t len) {
static void accept(struct vfs_request *req) {
static char buf[32];
int ret;
+ bool valid;
switch (req->type) {
case VFSOP_OPEN:
- ret = req->input.len == 0 ? 0 : -1;
- vfsreq_finish(req, 0);
+ valid = req->input.len == 0 && !(req->flags & OPEN_CREATE);
+ vfsreq_finish(req, valid ? 0 : -1);
break;
case VFSOP_READ:
if (ring_size((void*)&backlog) == 0) {
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index 0d18af8..7040f6b 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -79,7 +79,7 @@ int _syscall_fork(int flags, handle_t __user *fs_front) {
SYSCALL_RETURN(1);
}
-handle_t _syscall_open(const char __user *path, int len) {
+handle_t _syscall_open(const char __user *path, int len, int flags) {
struct vfs_mount *mount;
char *path_buf = NULL;
@@ -114,6 +114,7 @@ handle_t _syscall_open(const char __user *path, int len) {
},
.caller = process_current,
.backend = mount->backend,
+ .flags = flags,
});
return -1; // dummy
fail:
@@ -300,7 +301,7 @@ int _syscall(int num, int a, int b, int c, int d) {
_syscall_fork(a, (userptr_t)b);
break;
case _SYSCALL_OPEN:
- _syscall_open((userptr_t)a, b);
+ _syscall_open((userptr_t)a, b, c);
break;
case _SYSCALL_MOUNT:
_syscall_mount(a, (userptr_t)b, c);
diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c
index 30c0e77..4ee5986 100644
--- a/src/kernel/vfs/request.c
+++ b/src/kernel/vfs/request.c
@@ -113,6 +113,7 @@ void vfs_backend_user_accept(struct vfs_request *req) {
res.capacity = req->output.len;
res.id = req->id;
res.offset = req->offset;
+ res.flags = req->flags;
res.op = req->type;
if (!virt_cpy_to(handler->pages,
diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h
index e034bc6..cad0981 100644
--- a/src/kernel/vfs/request.h
+++ b/src/kernel/vfs/request.h
@@ -49,6 +49,7 @@ struct vfs_request {
int id; // handle.file.id
int offset;
+ int flags;
struct process *caller;
struct vfs_backend *backend;
diff --git a/src/shared/syscalls.h b/src/shared/syscalls.h
index 5d98429..403d02c 100644
--- a/src/shared/syscalls.h
+++ b/src/shared/syscalls.h
@@ -4,6 +4,7 @@
#define FORK_NOREAP 1
#define FORK_NEWFS 2
+#define OPEN_CREATE 1
enum {
// idc about stable syscall numbers just yet
@@ -47,7 +48,7 @@ int _syscall_await(void);
*/
int _syscall_fork(int flags, handle_t __user *fs_front);
-handle_t _syscall_open(const char __user *path, int len);
+handle_t _syscall_open(const char __user *path, int len, int flags);
int _syscall_mount(handle_t h, const char __user *path, int len);
int _syscall_read(handle_t h, void __user *buf, size_t len, int offset);
@@ -60,6 +61,7 @@ struct fs_wait_response {
size_t capacity; // how much output can be accepted by the caller
int id; // file id (returned by the open handler, passed to other calls)
int offset;
+ int flags;
};
/** Blocks until an fs request is made.
* @return 0 if everything was successful */