mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 03:22:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			193 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #include <AK/Singleton.h>
 | |
| #include <AK/StringBuilder.h>
 | |
| #include <AK/StringView.h>
 | |
| #include <Kernel/FileSystem/DevPtsFS.h>
 | |
| #include <Kernel/FileSystem/VirtualFileSystem.h>
 | |
| #include <Kernel/TTY/SlavePTY.h>
 | |
| 
 | |
| namespace Kernel {
 | |
| 
 | |
| NonnullRefPtr<DevPtsFS> DevPtsFS::create()
 | |
| {
 | |
|     return adopt_ref(*new DevPtsFS);
 | |
| }
 | |
| 
 | |
| DevPtsFS::DevPtsFS()
 | |
| {
 | |
| }
 | |
| 
 | |
| DevPtsFS::~DevPtsFS()
 | |
| {
 | |
| }
 | |
| 
 | |
| static AK::Singleton<HashTable<unsigned>> s_ptys;
 | |
| 
 | |
| bool DevPtsFS::initialize()
 | |
| {
 | |
|     m_root_inode = adopt_ref(*new DevPtsFSInode(*this, 1, nullptr));
 | |
|     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;
 | |
| }
 | |
| 
 | |
| static unsigned inode_index_to_pty_index(InodeIndex inode_index)
 | |
| {
 | |
|     VERIFY(inode_index > 1);
 | |
|     return inode_index.value() - 2;
 | |
| }
 | |
| 
 | |
| static InodeIndex pty_index_to_inode_index(unsigned pty_index)
 | |
| {
 | |
|     return pty_index + 2;
 | |
| }
 | |
| 
 | |
| NonnullRefPtr<Inode> DevPtsFS::root_inode() const
 | |
| {
 | |
|     return *m_root_inode;
 | |
| }
 | |
| 
 | |
| 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 = Device::get_device(201, pty_index);
 | |
|     VERIFY(device);
 | |
| 
 | |
|     auto inode = adopt_ref(*new DevPtsFSInode(const_cast<DevPtsFS&>(*this), inode_id.index(), static_cast<SlavePTY*>(device)));
 | |
|     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 = 0020600;
 | |
|     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)
 | |
| {
 | |
|     s_ptys->set(slave_pty.index());
 | |
| }
 | |
| 
 | |
| void DevPtsFS::unregister_slave_pty(SlavePTY& slave_pty)
 | |
| {
 | |
|     s_ptys->remove(slave_pty.index());
 | |
| }
 | |
| 
 | |
| DevPtsFSInode::DevPtsFSInode(DevPtsFS& fs, InodeIndex index, SlavePTY* pty)
 | |
|     : Inode(fs, index)
 | |
| {
 | |
|     if (pty)
 | |
|         m_pty = *pty;
 | |
| }
 | |
| 
 | |
| DevPtsFSInode::~DevPtsFSInode()
 | |
| {
 | |
| }
 | |
| 
 | |
| KResultOr<size_t> DevPtsFSInode::read_bytes(off_t, size_t, UserOrKernelBuffer&, FileDescription*) const
 | |
| {
 | |
|     VERIFY_NOT_REACHED();
 | |
| }
 | |
| 
 | |
| KResultOr<size_t> DevPtsFSInode::write_bytes(off_t, size_t, const UserOrKernelBuffer&, FileDescription*)
 | |
| {
 | |
|     VERIFY_NOT_REACHED();
 | |
| }
 | |
| 
 | |
| InodeMetadata DevPtsFSInode::metadata() const
 | |
| {
 | |
|     if (auto pty = m_pty.strong_ref()) {
 | |
|         auto metadata = m_metadata;
 | |
|         metadata.mtime = pty->time_of_last_write();
 | |
|         return metadata;
 | |
|     }
 | |
|     return m_metadata;
 | |
| }
 | |
| 
 | |
| KResult DevPtsFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)> callback) const
 | |
| {
 | |
|     if (identifier().index() > 1)
 | |
|         return ENOTDIR;
 | |
| 
 | |
|     callback({ ".", identifier(), 0 });
 | |
|     callback({ "..", identifier(), 0 });
 | |
| 
 | |
|     for (unsigned pty_index : *s_ptys) {
 | |
|         String name = String::number(pty_index);
 | |
|         InodeIdentifier identifier = { fsid(), pty_index_to_inode_index(pty_index) };
 | |
|         callback({ name, identifier, 0 });
 | |
|     }
 | |
| 
 | |
|     return KSuccess;
 | |
| }
 | |
| 
 | |
| KResultOr<size_t> DevPtsFSInode::directory_entry_count() const
 | |
| {
 | |
|     VERIFY(identifier().index() == 1);
 | |
| 
 | |
|     return 2 + s_ptys->size();
 | |
| }
 | |
| 
 | |
| RefPtr<Inode> DevPtsFSInode::lookup(StringView name)
 | |
| {
 | |
|     VERIFY(identifier().index() == 1);
 | |
| 
 | |
|     if (name == "." || name == "..")
 | |
|         return this;
 | |
| 
 | |
|     auto& fs = static_cast<DevPtsFS&>(this->fs());
 | |
| 
 | |
|     auto pty_index = name.to_uint();
 | |
|     if (pty_index.has_value() && s_ptys->contains(pty_index.value())) {
 | |
|         return fs.get_inode({ fsid(), pty_index_to_inode_index(pty_index.value()) });
 | |
|     }
 | |
| 
 | |
|     return {};
 | |
| }
 | |
| 
 | |
| void DevPtsFSInode::flush_metadata()
 | |
| {
 | |
| }
 | |
| 
 | |
| KResult DevPtsFSInode::add_child(Inode&, const StringView&, mode_t)
 | |
| {
 | |
|     return EROFS;
 | |
| }
 | |
| 
 | |
| KResultOr<NonnullRefPtr<Inode>> DevPtsFSInode::create_child(const String&, mode_t, dev_t, uid_t, gid_t)
 | |
| {
 | |
|     return EROFS;
 | |
| }
 | |
| 
 | |
| KResult DevPtsFSInode::remove_child(const StringView&)
 | |
| {
 | |
|     return EROFS;
 | |
| }
 | |
| 
 | |
| KResult DevPtsFSInode::chmod(mode_t)
 | |
| {
 | |
|     return EROFS;
 | |
| }
 | |
| 
 | |
| KResult DevPtsFSInode::chown(uid_t, gid_t)
 | |
| {
 | |
|     return EROFS;
 | |
| }
 | |
| 
 | |
| }
 | 
