summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordzwdz2021-08-25 14:49:58 +0200
committerdzwdz2021-08-25 14:49:58 +0200
commit0da663e05c93f2791d7166ece8d69a1be06a7924 (patch)
tree05dd2c16b04a3fd2e6ecf491da217b2686d8ec35
parentab5150478dd14c1c5b28ca50b36b35e8224df54b (diff)
implement open() for FD_SPECIAL_TTY (`/tty`)
-rw-r--r--src/init/main.c1
-rw-r--r--src/kernel/fd.c10
-rw-r--r--src/kernel/fd.h7
-rw-r--r--src/kernel/syscalls.c26
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) {