#include "fs/VFS.h" #include "Log.h" #include "thread/Thread.h" #include #include namespace VFS { SharedPtr root_fs; Inode& root_inode() { return *root_fs->root_inode(); } Result> resolve_path(const char* path, Credentials auth) { auto parser = TRY(PathParser::create(path)); SharedPtr current_inode = root_fs->root_inode(); // FIXME: Properly handle relative paths. const char* section; while (parser.next().try_set_value(section)) { if (!can_execute(current_inode, auth)) return err(EACCES); current_inode = TRY(current_inode->find(section)); } return current_inode; } Result> create_directory(const char* path, Credentials auth) { auto parser = TRY(PathParser::create(path)); auto parent_path = TRY(parser.dirname()); auto parent_inode = TRY(resolve_path(parent_path.chars(), auth)); if (!can_write(parent_inode, auth)) return err(EACCES); auto child_name = TRY(parser.basename()); // kdbgln("vfs: creating directory '%s' in parent '%s'", child_name.chars(), parent_path.chars()); return parent_inode->create_subdirectory(child_name.chars()); } Result> create_file(const char* path, Credentials auth) { auto parser = TRY(PathParser::create(path)); auto parent_path = TRY(parser.dirname()); auto parent_inode = TRY(resolve_path(parent_path.chars(), auth)); if (!can_write(parent_inode, auth)) return err(EACCES); auto child_name = TRY(parser.basename()); // kdbgln("vfs: creating file '%s' in parent '%s'", child_name.chars(), parent_path.chars()); return parent_inode->create_file(child_name.chars()); } bool can_execute(SharedPtr inode, Credentials auth) { if (inode->uid() == auth.euid) { return inode->mode() & S_IXUSR; } if (inode->gid() == auth.egid) { return inode->mode() & S_IXGRP; } return inode->mode() & S_IXOTH; } bool can_write(SharedPtr inode, Credentials auth) { if (inode->uid() == auth.euid) { return inode->mode() & S_IWUSR; } if (inode->gid() == auth.egid) { return inode->mode() & S_IWGRP; } return inode->mode() & S_IWOTH; } bool can_read(SharedPtr inode, Credentials auth) { if (inode->uid() == auth.euid) { return inode->mode() & S_IRUSR; } if (inode->gid() == auth.egid) { return inode->mode() & S_IRGRP; } return inode->mode() & S_IROTH; } }