/* * Copyright (c) 2019-2020, Sergey Bugaev * Copyright (c) 2021, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include namespace Kernel { static InodeIndex pty_index_to_inode_index(unsigned pty_index) { return pty_index + 2; } // NOTE: This constructor is used for the root inode only. DevPtsFSInode::DevPtsFSInode(DevPtsFS& fs) : Inode(fs, 1) { } DevPtsFSInode::DevPtsFSInode(DevPtsFS& fs, InodeIndex index, SlavePTY& pty) : Inode(fs, index) , m_pty(pty) { } DevPtsFSInode::~DevPtsFSInode() = default; ErrorOr DevPtsFSInode::read_bytes_locked(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const { VERIFY_NOT_REACHED(); } ErrorOr DevPtsFSInode::write_bytes_locked(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*) { 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; } ErrorOr DevPtsFSInode::traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)> callback) const { if (identifier().index() > 1) return ENOTDIR; TRY(callback({ "."sv, identifier(), to_underlying(RAMBackedFileType::Directory) })); TRY(callback({ ".."sv, identifier(), to_underlying(RAMBackedFileType::Directory) })); return SlavePTY::all_instances().with([&](auto& list) -> ErrorOr { StringBuilder builder; for (SlavePTY& slave_pty : list) { builder.clear(); TRY(builder.try_appendff("{}", slave_pty.index())); // NOTE: We represent directory entries with DT_CHR as all // inodes in this filesystem are assumed to be char devices. TRY(callback({ builder.string_view(), { fsid(), pty_index_to_inode_index(slave_pty.index()) }, to_underlying(RAMBackedFileType::Character) })); } return {}; }); } ErrorOr> DevPtsFSInode::lookup(StringView name) { VERIFY(identifier().index() == 1); if (name == "." || name == "..") return *this; auto pty_index = name.to_number(); if (!pty_index.has_value()) return ENOENT; return SlavePTY::all_instances().with([&](auto& list) -> ErrorOr> { for (SlavePTY& slave_pty : list) { if (slave_pty.index() != pty_index.value()) continue; return fs().get_inode({ fsid(), pty_index_to_inode_index(pty_index.value()) }); } return ENOENT; }); } ErrorOr DevPtsFSInode::flush_metadata() { return {}; } ErrorOr DevPtsFSInode::add_child(Inode&, StringView, mode_t) { return EROFS; } ErrorOr> DevPtsFSInode::create_child(StringView, mode_t, dev_t, UserID, GroupID) { return EROFS; } ErrorOr DevPtsFSInode::remove_child(StringView) { return EROFS; } ErrorOr DevPtsFSInode::replace_child(StringView, Inode&) { return EROFS; } ErrorOr DevPtsFSInode::chmod(mode_t) { return EROFS; } ErrorOr DevPtsFSInode::chown(UserID, GroupID) { return EROFS; } }