From 2d30935fdb17f9181c4f492f46845a5cea6cf672 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 11 Apr 2023 22:14:57 +0200 Subject: [PATCH] kernel: Give each thread a working directory --- kernel/src/fs/VFS.cpp | 16 +++++++++------- kernel/src/fs/VFS.h | 10 +++++++--- kernel/src/sys/exec.cpp | 4 ++++ kernel/src/sys/id.cpp | 2 +- kernel/src/sys/mkdir.cpp | 2 +- kernel/src/sys/mknod.cpp | 2 +- kernel/src/sys/open.cpp | 5 +++-- kernel/src/sys/stat.cpp | 2 +- kernel/src/thread/Thread.h | 4 ++++ 9 files changed, 31 insertions(+), 16 deletions(-) diff --git a/kernel/src/fs/VFS.cpp b/kernel/src/fs/VFS.cpp index 11a75a19..b8aa6ca8 100644 --- a/kernel/src/fs/VFS.cpp +++ b/kernel/src/fs/VFS.cpp @@ -13,13 +13,15 @@ namespace VFS return *root_fs->root_inode(); } - Result> resolve_path(const char* path, Credentials auth) + Result> resolve_path(const char* path, Credentials auth, SharedPtr working_directory) { auto parser = TRY(PathParser::create(path)); - SharedPtr current_inode = root_fs->root_inode(); + SharedPtr current_inode; - // FIXME: Properly handle relative paths. + if (parser.is_absolute() || !working_directory) current_inode = root_fs->root_inode(); + else + current_inode = working_directory; const char* section; while (parser.next().try_set_value(section)) @@ -31,12 +33,12 @@ namespace VFS return current_inode; } - Result> create_directory(const char* path, Credentials auth) + Result> create_directory(const char* path, Credentials auth, SharedPtr working_directory) { auto parser = TRY(PathParser::create(path)); auto parent_path = TRY(parser.dirname()); - auto parent_inode = TRY(resolve_path(parent_path.chars(), auth)); + auto parent_inode = TRY(resolve_path(parent_path.chars(), auth, working_directory)); if (!can_write(parent_inode, auth)) return err(EACCES); @@ -47,12 +49,12 @@ namespace VFS return parent_inode->create_subdirectory(child_name.chars()); } - Result> create_file(const char* path, Credentials auth) + Result> create_file(const char* path, Credentials auth, SharedPtr working_directory) { auto parser = TRY(PathParser::create(path)); auto parent_path = TRY(parser.dirname()); - auto parent_inode = TRY(resolve_path(parent_path.chars(), auth)); + auto parent_inode = TRY(resolve_path(parent_path.chars(), auth, working_directory)); if (!can_write(parent_inode, auth)) return err(EACCES); diff --git a/kernel/src/fs/VFS.h b/kernel/src/fs/VFS.h index 709b3dcd..e9d9231e 100644 --- a/kernel/src/fs/VFS.h +++ b/kernel/src/fs/VFS.h @@ -175,10 +175,14 @@ namespace VFS extern SharedPtr root_fs; - Result> resolve_path(const char* path, Credentials auth); + Result> resolve_path(const char* path, Credentials auth, + SharedPtr working_directory = {}); - Result> create_directory(const char* path, Credentials auth); - Result> create_file(const char* path, Credentials auth); + Result> create_directory(const char* path, Credentials auth, + SharedPtr working_directory = {}); + + Result> create_file(const char* path, Credentials auth, + SharedPtr working_directory = {}); bool can_execute(SharedPtr inode, Credentials auth); bool can_read(SharedPtr inode, Credentials auth); diff --git a/kernel/src/sys/exec.cpp b/kernel/src/sys/exec.cpp index eb351e34..c9d18ece 100644 --- a/kernel/src/sys/exec.cpp +++ b/kernel/src/sys/exec.cpp @@ -104,6 +104,8 @@ Result sys_fork(Registers* regs, SyscallArgs) memcpy(¤t->regs, regs, sizeof(*regs)); + auto current_directory_path = TRY(current->current_directory_path.clone()); + auto image = TRY(ThreadImage::clone_from_thread(current)); auto thread = TRY(new_thread()); @@ -114,6 +116,8 @@ Result sys_fork(Registers* regs, SyscallArgs) thread->fp_data.save(); thread->name = current->name; thread->auth = current->auth; + thread->current_directory = current->current_directory; + thread->current_directory_path = move(current_directory_path); for (int i = 0; i < FD_MAX; i++) { thread->fd_table[i] = current->fd_table[i]; } diff --git a/kernel/src/sys/id.cpp b/kernel/src/sys/id.cpp index ab4b2b82..5fe236b3 100644 --- a/kernel/src/sys/id.cpp +++ b/kernel/src/sys/id.cpp @@ -99,7 +99,7 @@ Result sys_chmod(Registers*, SyscallArgs args) Credentials& auth = Scheduler::current()->auth; - auto inode = TRY(VFS::resolve_path(path.chars(), auth)); + auto inode = TRY(VFS::resolve_path(path.chars(), auth, Scheduler::current()->current_directory)); if (auth.euid != 0 && auth.euid != inode->uid()) return err(EPERM); diff --git a/kernel/src/sys/mkdir.cpp b/kernel/src/sys/mkdir.cpp index 6144e3ee..dccdd3f6 100644 --- a/kernel/src/sys/mkdir.cpp +++ b/kernel/src/sys/mkdir.cpp @@ -13,7 +13,7 @@ Result sys_mkdir(Registers*, SyscallArgs args) kinfoln("mkdir: attempting to create %s", path.chars()); - auto inode = TRY(VFS::create_directory(path.chars(), current->auth)); + auto inode = TRY(VFS::create_directory(path.chars(), current->auth, current->current_directory)); inode->chmod(mode); inode->chown(current->auth.euid, current->auth.egid); diff --git a/kernel/src/sys/mknod.cpp b/kernel/src/sys/mknod.cpp index 55c4df11..a94e84e3 100644 --- a/kernel/src/sys/mknod.cpp +++ b/kernel/src/sys/mknod.cpp @@ -24,7 +24,7 @@ Result sys_mknod(Registers*, SyscallArgs args) auto dirname = TRY(parser.dirname()); auto basename = TRY(parser.basename()); - auto parent = TRY(VFS::resolve_path(dirname.chars(), current->auth)); + auto parent = TRY(VFS::resolve_path(dirname.chars(), current->auth, current->current_directory)); if (!VFS::can_write(parent, current->auth)) return err(EACCES); auto inode = TRY(parent->fs().create_device_inode(maj, min)); diff --git a/kernel/src/sys/open.cpp b/kernel/src/sys/open.cpp index c0d93550..54f545eb 100644 --- a/kernel/src/sys/open.cpp +++ b/kernel/src/sys/open.cpp @@ -25,12 +25,13 @@ Result sys_open(Registers*, SyscallArgs args) if ((flags & O_RDWR) == 0) { return err(EINVAL); } int error; - bool ok = VFS::resolve_path(path.chars(), current->auth).try_set_value_or_error(inode, error); + bool ok = + VFS::resolve_path(path.chars(), current->auth, current->current_directory).try_set_value_or_error(inode, error); if (!ok) { if (error == ENOENT && (flags & O_CREAT)) { - inode = TRY(VFS::create_file(path.chars(), current->auth)); + inode = TRY(VFS::create_file(path.chars(), current->auth, current->current_directory)); inode->chmod(mode); inode->chown(current->auth.euid, current->auth.egid); } diff --git a/kernel/src/sys/stat.cpp b/kernel/src/sys/stat.cpp index 782e1960..751043e3 100644 --- a/kernel/src/sys/stat.cpp +++ b/kernel/src/sys/stat.cpp @@ -42,7 +42,7 @@ Result sys_stat(Registers*, SyscallArgs args) Thread* current = Scheduler::current(); - auto inode = TRY(VFS::resolve_path(path.chars(), current->auth)); + auto inode = TRY(VFS::resolve_path(path.chars(), current->auth, current->current_directory)); return do_stat(inode, st); } diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index 441e214d..685736ae 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef ARCH_X86_64 #include "arch/x86_64/CPU.h" @@ -83,6 +84,9 @@ struct Thread : public LinkedListNode StaticString<128> name; + String current_directory_path = {}; + SharedPtr current_directory = {}; + PageDirectory* directory; bool is_idle()