diff --git a/kernel/include/kernel/Device.h b/kernel/include/kernel/Device.h index 15e804fc..b67bd956 100644 --- a/kernel/include/kernel/Device.h +++ b/kernel/include/kernel/Device.h @@ -16,7 +16,8 @@ namespace Kernel { BlockDevice, CharacterDevice, - DeviceController + DeviceController, + Partition, }; Device(); @@ -24,6 +25,8 @@ namespace Kernel virtual DeviceType device_type() const = 0; virtual void update() {} + virtual InodeType inode_type() const override { return InodeType::Device; } + virtual timespec atime() const override { return m_create_time; } virtual timespec mtime() const override { return m_create_time; } virtual timespec ctime() const override { return m_create_time; } @@ -58,6 +61,8 @@ namespace Kernel virtual BAN::RefPtr root_inode() override { return this; } + virtual InodeType inode_type() const override { return InodeType::Device; } + virtual BAN::StringView name() const override { return "device-manager"; } virtual BAN::ErrorOr> read_directory_inode(BAN::StringView) override; diff --git a/kernel/include/kernel/FS/Ext2.h b/kernel/include/kernel/FS/Ext2.h index 89614482..a0606317 100644 --- a/kernel/include/kernel/FS/Ext2.h +++ b/kernel/include/kernel/FS/Ext2.h @@ -137,6 +137,8 @@ namespace Kernel virtual dev_t dev() const override { return 0; } virtual dev_t rdev() const override { return 0; } + virtual InodeType inode_type() const override { return InodeType::Ext2; } + virtual BAN::StringView name() const override { return m_name; } virtual BAN::ErrorOr read(size_t, void*, size_t) override; diff --git a/kernel/include/kernel/FS/Inode.h b/kernel/include/kernel/FS/Inode.h index f32a2d55..eb2e23f3 100644 --- a/kernel/include/kernel/FS/Inode.h +++ b/kernel/include/kernel/FS/Inode.h @@ -48,6 +48,12 @@ namespace Kernel mode_t mode; }; + enum class InodeType + { + Device, + Ext2, + }; + public: virtual ~Inode() {} @@ -67,6 +73,8 @@ namespace Kernel virtual dev_t dev() const = 0; virtual dev_t rdev() const = 0; + virtual InodeType inode_type() const = 0; + virtual BAN::StringView name() const = 0; virtual BAN::ErrorOr> read_directory_inode(BAN::StringView) { if (!mode().ifdir()) return BAN::Error::from_errno(ENOTDIR); ASSERT_NOT_REACHED(); } diff --git a/kernel/include/kernel/FS/VirtualFileSystem.h b/kernel/include/kernel/FS/VirtualFileSystem.h index da11cbf4..c701fe55 100644 --- a/kernel/include/kernel/FS/VirtualFileSystem.h +++ b/kernel/include/kernel/FS/VirtualFileSystem.h @@ -18,7 +18,7 @@ namespace Kernel virtual BAN::RefPtr root_inode() override { return m_root_fs->root_inode(); } - BAN::ErrorOr mount(FileSystem*, BAN::StringView); + BAN::ErrorOr mount(BAN::StringView, BAN::StringView); struct File { @@ -27,6 +27,10 @@ namespace Kernel }; BAN::ErrorOr file_from_absolute_path(BAN::StringView); + private: + VirtualFileSystem() = default; + BAN::ErrorOr mount(FileSystem*, BAN::StringView); + struct MountPoint { File host; @@ -34,9 +38,6 @@ namespace Kernel }; MountPoint* mount_point_for_inode(BAN::RefPtr); - private: - VirtualFileSystem() = default; - private: FileSystem* m_root_fs = nullptr; BAN::Vector m_mount_points; diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 047b92bf..ccb1e245 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -37,6 +37,8 @@ namespace Kernel BAN::ErrorOr fstat(int, stat*); BAN::ErrorOr stat(BAN::StringView, stat*); + BAN::ErrorOr mount(BAN::StringView, BAN::StringView); + BAN::ErrorOr> read_directory_entries(int); BAN::String working_directory() const; diff --git a/kernel/include/kernel/Storage/StorageDevice.h b/kernel/include/kernel/Storage/StorageDevice.h index 6547be12..70fa31d1 100644 --- a/kernel/include/kernel/Storage/StorageDevice.h +++ b/kernel/include/kernel/Storage/StorageDevice.h @@ -42,6 +42,8 @@ namespace Kernel char m_label[36 * 4 + 1]; public: + virtual DeviceType device_type() const override { return DeviceType::Partition; } + virtual ino_t ino() const override { return m_index; } virtual Mode mode() const override { return { Mode::IFBLK | Mode::IRUSR | Mode::IRGRP }; } virtual nlink_t nlink() const override { return 1; } diff --git a/kernel/kernel/FS/VirtualFileSystem.cpp b/kernel/kernel/FS/VirtualFileSystem.cpp index 6cf5ec9b..6cc69e2a 100644 --- a/kernel/kernel/FS/VirtualFileSystem.cpp +++ b/kernel/kernel/FS/VirtualFileSystem.cpp @@ -35,6 +35,18 @@ namespace Kernel return *s_instance; } + BAN::ErrorOr VirtualFileSystem::mount(BAN::StringView partition, BAN::StringView target) + { + auto partition_file = TRY(file_from_absolute_path(partition)); + if (partition_file.inode->inode_type() != Inode::InodeType::Device) + return BAN::Error::from_c_string("Not a partition"); + Device* device = (Device*)partition_file.inode.ptr(); + if (device->device_type() != Device::DeviceType::Partition) + return BAN::Error::from_c_string("Not a partition"); + auto* file_system = TRY(Ext2FS::create(*(Partition*)device)); + return mount(file_system, target); + } + BAN::ErrorOr VirtualFileSystem::mount(FileSystem* file_system, BAN::StringView path) { auto file = TRY(file_from_absolute_path(path)); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 01023071..9cbcff94 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -97,6 +97,13 @@ namespace Kernel return {}; } + BAN::ErrorOr Process::mount(BAN::StringView partition, BAN::StringView path) + { + LockGuard _(m_lock); + TRY(VirtualFileSystem::get().mount(partition, path)); + return {}; + } + BAN::ErrorOr Process::fstat(int fd, struct stat* out) { LockGuard _(m_lock); diff --git a/kernel/kernel/Shell.cpp b/kernel/kernel/Shell.cpp index be840156..965b85e1 100644 --- a/kernel/kernel/Shell.cpp +++ b/kernel/kernel/Shell.cpp @@ -508,6 +508,12 @@ argument_done: TTY_PRINTLN("{} {} {}", crc32, total_read, arguments[i]); } } + else if (arguments.front() == "mount") + { + if (arguments.size() != 3) + return BAN::Error::from_c_string("usage: 'mount partition directory'"); + TRY(Process::current()->mount(arguments[1], arguments[2])); + } else if (arguments.front() == "loadfont") { if (arguments.size() != 2)