diff options
-rw-r--r-- | Kernel/FileSystem/DevPtsFS.cpp | 172 | ||||
-rw-r--r-- | Kernel/FileSystem/DevPtsFS.h | 46 | ||||
-rw-r--r-- | Kernel/TTY/SlavePTY.cpp | 4 | ||||
-rw-r--r-- | Kernel/TTY/SlavePTY.h | 4 | ||||
-rw-r--r-- | Kernel/init.cpp | 5 |
5 files changed, 187 insertions, 44 deletions
diff --git a/Kernel/FileSystem/DevPtsFS.cpp b/Kernel/FileSystem/DevPtsFS.cpp index 73c0282651..cb7203d83b 100644 --- a/Kernel/FileSystem/DevPtsFS.cpp +++ b/Kernel/FileSystem/DevPtsFS.cpp @@ -3,14 +3,6 @@ #include <Kernel/FileSystem/VirtualFileSystem.h> #include <Kernel/TTY/SlavePTY.h> -static DevPtsFS* s_the; - -DevPtsFS& DevPtsFS::the() -{ - ASSERT(s_the); - return *s_the; -} - NonnullRefPtr<DevPtsFS> DevPtsFS::create() { return adopt(*new DevPtsFS); @@ -18,49 +10,175 @@ NonnullRefPtr<DevPtsFS> DevPtsFS::create() DevPtsFS::DevPtsFS() { - s_the = this; } DevPtsFS::~DevPtsFS() { } +static HashTable<unsigned>* ptys; + bool DevPtsFS::initialize() { - SynthFS::initialize(); + if (ptys == nullptr) { + ptys = new HashTable<unsigned>(); + } + + m_root_inode = adopt(*new DevPtsFSInode(*this, 1)); + m_root_inode->m_metadata.inode = { fsid(), 1 }; + m_root_inode->m_metadata.mode = 0040555; + m_root_inode->m_metadata.uid = 0; + m_root_inode->m_metadata.gid = 0; + m_root_inode->m_metadata.size = 0; + m_root_inode->m_metadata.mtime = mepoch; + return true; } -const char* DevPtsFS::class_name() const +static unsigned inode_index_to_pty_index(unsigned inode_index) +{ + ASSERT(inode_index > 1); + return inode_index - 2; +} + +static unsigned pty_index_to_inode_index(unsigned pty_index) +{ + return pty_index + 2; +} + +InodeIdentifier DevPtsFS::root_inode() const +{ + return { fsid(), 1 }; +} + +RefPtr<Inode> DevPtsFS::create_inode(InodeIdentifier, const String&, mode_t, off_t, dev_t, int& error) +{ + error = -EROFS; + return nullptr; +} + +RefPtr<Inode> DevPtsFS::create_directory(InodeIdentifier, const String&, mode_t, int& error) { - return "DevPtsFS"; + error = -EROFS; + return nullptr; } -NonnullRefPtr<SynthFSInode> DevPtsFS::create_slave_pty_device_file(unsigned index) +RefPtr<Inode> DevPtsFS::get_inode(InodeIdentifier inode_id) const { - auto file = adopt(*new SynthFSInode(*this, generate_inode_index())); - file->m_name = String::number(index); + if (inode_id.index() == 1) + return m_root_inode; - auto* device = VFS::the().get_device(11, index); + unsigned pty_index = inode_index_to_pty_index(inode_id.index()); + auto* device = VFS::the().get_device(11, pty_index); ASSERT(device); - file->m_metadata.size = 0; - file->m_metadata.uid = device->uid(); - file->m_metadata.gid = device->gid(); - file->m_metadata.mode = 0020644; - file->m_metadata.major_device = device->major(); - file->m_metadata.minor_device = device->minor(); - file->m_metadata.mtime = mepoch; - return file; + auto inode = adopt(*new DevPtsFSInode(const_cast<DevPtsFS&>(*this), inode_id.index())); + inode->m_metadata.inode = inode_id; + inode->m_metadata.size = 0; + inode->m_metadata.uid = device->uid(); + inode->m_metadata.gid = device->gid(); + inode->m_metadata.mode = 0020644; + inode->m_metadata.major_device = device->major(); + inode->m_metadata.minor_device = device->minor(); + inode->m_metadata.mtime = mepoch; + + return inode; } void DevPtsFS::register_slave_pty(SlavePTY& slave_pty) { - auto inode_id = add_file(create_slave_pty_device_file(slave_pty.index())); - slave_pty.set_devpts_inode_id(inode_id); + ptys->set(slave_pty.index()); } void DevPtsFS::unregister_slave_pty(SlavePTY& slave_pty) { - remove_file(slave_pty.devpts_inode_id().index()); + ptys->remove(slave_pty.index()); +} + +DevPtsFSInode::DevPtsFSInode(DevPtsFS& fs, unsigned index) + : Inode(fs, index) +{ +} + +DevPtsFSInode::~DevPtsFSInode() +{ +} + +ssize_t DevPtsFSInode::read_bytes(off_t, ssize_t, u8*, FileDescription*) const +{ + ASSERT_NOT_REACHED(); +} + +ssize_t DevPtsFSInode::write_bytes(off_t, ssize_t, const u8*, FileDescription*) +{ + ASSERT_NOT_REACHED(); +} + +InodeMetadata DevPtsFSInode::metadata() const +{ + return m_metadata; +} + +bool DevPtsFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const +{ + if (identifier().index() > 1) + return false; + + callback({ ".", 1, identifier(), 0 }); + callback({ "..", 2, identifier(), 0 }); + + for (unsigned pty_index : *ptys) { + String name = String::number(pty_index); + InodeIdentifier identifier = { fsid(), pty_index_to_inode_index(pty_index) }; + callback({ name.characters(), name.length(), identifier, 0 }); + } + + return true; +} + +size_t DevPtsFSInode::directory_entry_count() const +{ + ASSERT(identifier().index() == 1); + + return 2 + ptys->size(); +} + +InodeIdentifier DevPtsFSInode::lookup(StringView name) +{ + ASSERT(identifier().index() == 1); + + if (name == "." || name == "..") + return identifier(); + + bool ok; + unsigned pty_index = name.to_uint(ok); + if (ok && ptys->contains(pty_index)) { + return { fsid(), pty_index_to_inode_index(pty_index) }; + } + + return {}; +} + +void DevPtsFSInode::flush_metadata() +{ +} + +KResult DevPtsFSInode::add_child(InodeIdentifier, const StringView&, mode_t) +{ + return KResult(-EROFS); +} + +KResult DevPtsFSInode::remove_child(const StringView&) +{ + return KResult(-EROFS); +} + +KResult DevPtsFSInode::chmod(mode_t) +{ + return KResult(-EPERM); +} + +KResult DevPtsFSInode::chown(uid_t, gid_t) +{ + return KResult(-EPERM); } diff --git a/Kernel/FileSystem/DevPtsFS.h b/Kernel/FileSystem/DevPtsFS.h index c834b82156..2dae6c137e 100644 --- a/Kernel/FileSystem/DevPtsFS.h +++ b/Kernel/FileSystem/DevPtsFS.h @@ -1,28 +1,54 @@ #pragma once #include <AK/Types.h> -#include <Kernel/FileSystem/SyntheticFileSystem.h> +#include <Kernel/FileSystem/FileSystem.h> +#include <Kernel/FileSystem/Inode.h> -class Process; class SlavePTY; +class DevPtsFSInode; -class DevPtsFS final : public SynthFS { +class DevPtsFS final : public FS { public: - static DevPtsFS& the(); - virtual ~DevPtsFS() override; static NonnullRefPtr<DevPtsFS> create(); virtual bool initialize() override; - virtual const char* class_name() const override; + virtual const char* class_name() const override { return "DevPtsFS"; } + + virtual InodeIdentifier root_inode() const override; + virtual RefPtr<Inode> create_inode(InodeIdentifier parentInode, const String& name, mode_t, off_t size, dev_t, int& error) override; + virtual RefPtr<Inode> create_directory(InodeIdentifier parentInode, const String& name, mode_t, int& error) override; + virtual RefPtr<Inode> get_inode(InodeIdentifier) const override; - void register_slave_pty(SlavePTY&); - void unregister_slave_pty(SlavePTY&); + static void register_slave_pty(SlavePTY&); + static void unregister_slave_pty(SlavePTY&); private: DevPtsFS(); - NonnullRefPtr<SynthFSInode> create_slave_pty_device_file(unsigned index); + RefPtr<DevPtsFSInode> m_root_inode; +}; + +class DevPtsFSInode final : public Inode { + friend class DevPtsFS; +public: + virtual ~DevPtsFSInode() override; - HashTable<SlavePTY*> m_slave_ptys; +private: + DevPtsFSInode(DevPtsFS&, unsigned index); + + // ^Inode + virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override; + virtual InodeMetadata metadata() const override; + virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override; + virtual InodeIdentifier lookup(StringView name) override; + virtual void flush_metadata() override; + virtual ssize_t write_bytes(off_t, ssize_t, const u8* buffer, FileDescription*) override; + virtual KResult add_child(InodeIdentifier child_id, const StringView& name, mode_t) override; + virtual KResult remove_child(const StringView& name) override; + virtual size_t directory_entry_count() const override; + virtual KResult chmod(mode_t) override; + virtual KResult chown(uid_t, gid_t) override; + + InodeMetadata m_metadata; }; diff --git a/Kernel/TTY/SlavePTY.cpp b/Kernel/TTY/SlavePTY.cpp index 5f227b50da..129eb00e07 100644 --- a/Kernel/TTY/SlavePTY.cpp +++ b/Kernel/TTY/SlavePTY.cpp @@ -13,7 +13,7 @@ SlavePTY::SlavePTY(MasterPTY& master, unsigned index) m_tty_name = String::format("/dev/pts/%u", m_index); set_uid(current->process().uid()); set_gid(current->process().gid()); - DevPtsFS::the().register_slave_pty(*this); + DevPtsFS::register_slave_pty(*this); set_size(80, 25); } @@ -22,7 +22,7 @@ SlavePTY::~SlavePTY() #ifdef SLAVEPTY_DEBUG dbgprintf("~SlavePTY(%u)\n", m_index); #endif - DevPtsFS::the().unregister_slave_pty(*this); + DevPtsFS::unregister_slave_pty(*this); } String SlavePTY::tty_name() const diff --git a/Kernel/TTY/SlavePTY.h b/Kernel/TTY/SlavePTY.h index 5cb0b7ed80..9bf1c5f9cc 100644 --- a/Kernel/TTY/SlavePTY.h +++ b/Kernel/TTY/SlavePTY.h @@ -12,9 +12,6 @@ public: void on_master_write(const u8*, ssize_t); unsigned index() const { return m_index; } - InodeIdentifier devpts_inode_id() const { return m_devpts_inode_id; } - void set_devpts_inode_id(InodeIdentifier inode_id) { m_devpts_inode_id = inode_id; } - private: // ^TTY virtual String tty_name() const override; @@ -32,6 +29,5 @@ private: RefPtr<MasterPTY> m_master; unsigned m_index; - InodeIdentifier m_devpts_inode_id; String m_tty_name; }; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index b8bc868b7a..650cbb8992 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -122,7 +122,10 @@ VFS* vfs; auto procfs = ProcFS::create(); procfs->initialize(); vfs->mount(procfs, "/proc"); - vfs->mount(DevPtsFS::the(), "/dev/pts"); + + auto devptsfs = DevPtsFS::create(); + devptsfs->initialize(); + vfs->mount(devptsfs, "/dev/pts"); auto tmpfs = TmpFS::create(); if (!tmpfs->initialize()) |