diff options
author | dzwdz | 2021-08-25 14:49:58 +0200 |
---|---|---|
committer | dzwdz | 2021-08-25 14:49:58 +0200 |
commit | 0da663e05c93f2791d7166ece8d69a1be06a7924 (patch) | |
tree | 05dd2c16b04a3fd2e6ecf491da217b2686d8ec35 | |
parent | ab5150478dd14c1c5b28ca50b36b35e8224df54b (diff) |
implement open() for FD_SPECIAL_TTY (`/tty`)
-rw-r--r-- | src/init/main.c | 1 | ||||
-rw-r--r-- | src/kernel/fd.c | 10 | ||||
-rw-r--r-- | src/kernel/fd.h | 7 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 26 |
4 files changed, 42 insertions, 2 deletions
diff --git a/src/init/main.c b/src/init/main.c index c08cf21..0e74e93 100644 --- a/src/init/main.c +++ b/src/init/main.c @@ -30,6 +30,7 @@ int main(void) { fd = _syscall_fs_open( multipageify("/tty"), sizeof("/tty") - 1); + // TODO don't dispatch /ttywhatever to the tty driver if (fd < 0) { _syscall_exit("couldn't open tty", diff --git a/src/kernel/fd.c b/src/kernel/fd.c index 810cdb7..e875061 100644 --- a/src/kernel/fd.c +++ b/src/kernel/fd.c @@ -24,6 +24,16 @@ static int fdop_special_tty(struct fdop_args *args) { case FDOP_MOUNT: return 0; // no special action needed + case FDOP_OPEN: + /* don't allow anything after the mount point + * this is a file, not a directory + * for example: open("/tty") is allowed. open("/tty/smth") isn't */ + if (args->open.len == 0) { + args->open.target->type = FD_SPECIAL_TTY; + return 0; + } + return -1; + case FDOP_READ: return -1; // input not implemented yet diff --git a/src/kernel/fd.h b/src/kernel/fd.h index bcc9902..c7c5182 100644 --- a/src/kernel/fd.h +++ b/src/kernel/fd.h @@ -18,6 +18,8 @@ struct fd { enum fdop { // describes the operations which can be done on file descriptors FDOP_MOUNT, // also closes the original fd + FDOP_OPEN, // when the file descriptor is mounted, open a file relative to it + FDOP_READ, FDOP_WRITE, FDOP_CLOSE, @@ -30,6 +32,11 @@ struct fdop_args { struct { // FDOP_MOUNT struct mount *target; } mnt; + struct { // FDOP_OPEN + struct fd *target; + const char *path; // relative to the mount point + size_t len; + } open; struct { // FDOP_READ, FDOP_WRITE user_ptr ptr; size_t len; diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 737484d..1c0a687 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -70,9 +70,17 @@ fd_t _syscall_fs_open(const user_ptr path, int len) { struct virt_iter iter; struct vfs_mount *mount = process_current->mount; static char buffer[PATH_MAX]; // holds the path + int fd, res; if (len > PATH_MAX) return -1; + // find the first free fd + for (fd = 0; fd < FD_MAX; fd++) { + if (process_current->fds[fd].type == FD_EMPTY) + break; + } + if (fd == FD_MAX) return -1; + // copy the path to the kernel virt_iter_new(&iter, path, len, process_current->pages, true, false); while (virt_iter_next(&iter)) @@ -90,14 +98,28 @@ fd_t _syscall_fs_open(const user_ptr path, int len) { break; } - tty_write(buffer, len); + tty_write(buffer + mount->prefix_len, len - mount->prefix_len); tty_const(" from mount "); if (mount) tty_write(mount->prefix, mount->prefix_len); else tty_const("[none]"); - return -1; + if (!mount) return -1; + + res = fdop_dispatch((struct fdop_args){ + .type = FDOP_OPEN, + .fd = &mount->fd, + .open = { + .target = &process_current->fds[fd], + .path = &buffer[mount->prefix_len], + .len = len - mount->prefix_len, + } + }); + if (res < 0) + return res; + else + return fd; } int _syscall_fd_mount(fd_t fd, const user_ptr path, int len) { |