mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 19:12:43 +00:00 
			
		
		
		
	DevPtsFS: Do not assume there is one of it
Unfortunately, that also means it can no longer inherit from SynthFS.
This commit is contained in:
		
							parent
							
								
									37cc80fb96
								
							
						
					
					
						commit
						66a0a12435
					
				
					 5 changed files with 188 additions and 45 deletions
				
			
		|  | @ -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) | ||||
| { | ||||
|     return "DevPtsFS"; | ||||
|     ASSERT(inode_index > 1); | ||||
|     return inode_index - 2; | ||||
| } | ||||
| 
 | ||||
| NonnullRefPtr<SynthFSInode> DevPtsFS::create_slave_pty_device_file(unsigned index) | ||||
| static unsigned pty_index_to_inode_index(unsigned pty_index) | ||||
| { | ||||
|     auto file = adopt(*new SynthFSInode(*this, generate_inode_index())); | ||||
|     file->m_name = String::number(index); | ||||
|     return pty_index + 2; | ||||
| } | ||||
| 
 | ||||
|     auto* device = VFS::the().get_device(11, index); | ||||
| 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) | ||||
| { | ||||
|     error = -EROFS; | ||||
|     return nullptr; | ||||
| } | ||||
| 
 | ||||
| RefPtr<Inode> DevPtsFS::get_inode(InodeIdentifier inode_id) const | ||||
| { | ||||
|     if (inode_id.index() == 1) | ||||
|         return m_root_inode; | ||||
| 
 | ||||
|     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); | ||||
| } | ||||
|  |  | |||
|  | @ -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"; } | ||||
| 
 | ||||
|     void register_slave_pty(SlavePTY&); | ||||
|     void unregister_slave_pty(SlavePTY&); | ||||
|     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; | ||||
| 
 | ||||
|     static void register_slave_pty(SlavePTY&); | ||||
|     static void unregister_slave_pty(SlavePTY&); | ||||
| 
 | ||||
| private: | ||||
|     DevPtsFS(); | ||||
| 
 | ||||
|     NonnullRefPtr<SynthFSInode> create_slave_pty_device_file(unsigned index); | ||||
| 
 | ||||
|     HashTable<SlavePTY*> m_slave_ptys; | ||||
|     RefPtr<DevPtsFSInode> m_root_inode; | ||||
| }; | ||||
| 
 | ||||
| class DevPtsFSInode final : public Inode { | ||||
|     friend class DevPtsFS; | ||||
| public: | ||||
|     virtual ~DevPtsFSInode() override; | ||||
| 
 | ||||
| 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; | ||||
| }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Sergey Bugaev
						Sergey Bugaev