Serenity Operating System
at hosted 213 lines 5.5 kB view raw
1/* 2 * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <AK/StringBuilder.h> 28#include <AK/StringView.h> 29#include <Kernel/FileSystem/DevPtsFS.h> 30#include <Kernel/FileSystem/VirtualFileSystem.h> 31#include <Kernel/TTY/SlavePTY.h> 32 33namespace Kernel { 34 35NonnullRefPtr<DevPtsFS> DevPtsFS::create() 36{ 37 return adopt(*new DevPtsFS); 38} 39 40DevPtsFS::DevPtsFS() 41{ 42} 43 44DevPtsFS::~DevPtsFS() 45{ 46} 47 48static HashTable<unsigned>* ptys; 49 50bool DevPtsFS::initialize() 51{ 52 if (ptys == nullptr) { 53 ptys = new HashTable<unsigned>(); 54 } 55 56 m_root_inode = adopt(*new DevPtsFSInode(*this, 1)); 57 m_root_inode->m_metadata.inode = { fsid(), 1 }; 58 m_root_inode->m_metadata.mode = 0040555; 59 m_root_inode->m_metadata.uid = 0; 60 m_root_inode->m_metadata.gid = 0; 61 m_root_inode->m_metadata.size = 0; 62 m_root_inode->m_metadata.mtime = mepoch; 63 64 return true; 65} 66 67static unsigned inode_index_to_pty_index(unsigned inode_index) 68{ 69 ASSERT(inode_index > 1); 70 return inode_index - 2; 71} 72 73static unsigned pty_index_to_inode_index(unsigned pty_index) 74{ 75 return pty_index + 2; 76} 77 78InodeIdentifier DevPtsFS::root_inode() const 79{ 80 return { fsid(), 1 }; 81} 82 83KResultOr<NonnullRefPtr<Inode>> DevPtsFS::create_inode(InodeIdentifier, const String&, mode_t, off_t, dev_t, uid_t, gid_t) 84{ 85 return KResult(-EROFS); 86} 87 88KResult DevPtsFS::create_directory(InodeIdentifier, const String&, mode_t, uid_t, gid_t) 89{ 90 return KResult(-EROFS); 91} 92 93RefPtr<Inode> DevPtsFS::get_inode(InodeIdentifier inode_id) const 94{ 95 if (inode_id.index() == 1) 96 return m_root_inode; 97 98 unsigned pty_index = inode_index_to_pty_index(inode_id.index()); 99 auto* device = Device::get_device(201, pty_index); 100 ASSERT(device); 101 102 auto inode = adopt(*new DevPtsFSInode(const_cast<DevPtsFS&>(*this), inode_id.index())); 103 inode->m_metadata.inode = inode_id; 104 inode->m_metadata.size = 0; 105 inode->m_metadata.uid = device->uid(); 106 inode->m_metadata.gid = device->gid(); 107 inode->m_metadata.mode = 0020600; 108 inode->m_metadata.major_device = device->major(); 109 inode->m_metadata.minor_device = device->minor(); 110 inode->m_metadata.mtime = mepoch; 111 112 return inode; 113} 114 115void DevPtsFS::register_slave_pty(SlavePTY& slave_pty) 116{ 117 ptys->set(slave_pty.index()); 118} 119 120void DevPtsFS::unregister_slave_pty(SlavePTY& slave_pty) 121{ 122 ptys->remove(slave_pty.index()); 123} 124 125DevPtsFSInode::DevPtsFSInode(DevPtsFS& fs, unsigned index) 126 : Inode(fs, index) 127{ 128} 129 130DevPtsFSInode::~DevPtsFSInode() 131{ 132} 133 134ssize_t DevPtsFSInode::read_bytes(off_t, ssize_t, u8*, FileDescription*) const 135{ 136 ASSERT_NOT_REACHED(); 137} 138 139ssize_t DevPtsFSInode::write_bytes(off_t, ssize_t, const u8*, FileDescription*) 140{ 141 ASSERT_NOT_REACHED(); 142} 143 144InodeMetadata DevPtsFSInode::metadata() const 145{ 146 return m_metadata; 147} 148 149bool DevPtsFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const 150{ 151 if (identifier().index() > 1) 152 return false; 153 154 callback({ ".", 1, identifier(), 0 }); 155 callback({ "..", 2, identifier(), 0 }); 156 157 for (unsigned pty_index : *ptys) { 158 String name = String::number(pty_index); 159 InodeIdentifier identifier = { fsid(), pty_index_to_inode_index(pty_index) }; 160 callback({ name.characters(), name.length(), identifier, 0 }); 161 } 162 163 return true; 164} 165 166size_t DevPtsFSInode::directory_entry_count() const 167{ 168 ASSERT(identifier().index() == 1); 169 170 return 2 + ptys->size(); 171} 172 173RefPtr<Inode> DevPtsFSInode::lookup(StringView name) 174{ 175 ASSERT(identifier().index() == 1); 176 177 if (name == "." || name == "..") 178 return fs().get_inode(identifier()); 179 180 bool ok; 181 unsigned pty_index = name.to_uint(ok); 182 if (ok && ptys->contains(pty_index)) { 183 return fs().get_inode({ fsid(), pty_index_to_inode_index(pty_index) }); 184 } 185 186 return {}; 187} 188 189void DevPtsFSInode::flush_metadata() 190{ 191} 192 193KResult DevPtsFSInode::add_child(InodeIdentifier, const StringView&, mode_t) 194{ 195 return KResult(-EROFS); 196} 197 198KResult DevPtsFSInode::remove_child(const StringView&) 199{ 200 return KResult(-EROFS); 201} 202 203KResult DevPtsFSInode::chmod(mode_t) 204{ 205 return KResult(-EPERM); 206} 207 208KResult DevPtsFSInode::chown(uid_t, gid_t) 209{ 210 return KResult(-EPERM); 211} 212 213}