Serenity Operating System
1/*
2 * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
3 * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#include <Kernel/Devices/DeviceManagement.h>
9#include <Kernel/FileSystem/DevPtsFS/Inode.h>
10
11namespace Kernel {
12
13static InodeIndex pty_index_to_inode_index(unsigned pty_index)
14{
15 return pty_index + 2;
16}
17
18DevPtsFSInode::DevPtsFSInode(DevPtsFS& fs, InodeIndex index, SlavePTY* pty)
19 : Inode(fs, index)
20{
21 if (pty)
22 m_pty = *pty;
23}
24
25DevPtsFSInode::~DevPtsFSInode() = default;
26
27ErrorOr<size_t> DevPtsFSInode::read_bytes_locked(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const
28{
29 VERIFY_NOT_REACHED();
30}
31
32ErrorOr<size_t> DevPtsFSInode::write_bytes_locked(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*)
33{
34 VERIFY_NOT_REACHED();
35}
36
37InodeMetadata DevPtsFSInode::metadata() const
38{
39 if (auto pty = m_pty.strong_ref()) {
40 auto metadata = m_metadata;
41 metadata.mtime = Time::from_timespec({ pty->time_of_last_write(), 0 });
42 return metadata;
43 }
44 return m_metadata;
45}
46
47ErrorOr<void> DevPtsFSInode::traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
48{
49 if (identifier().index() > 1)
50 return ENOTDIR;
51
52 TRY(callback({ "."sv, identifier(), 0 }));
53 TRY(callback({ ".."sv, identifier(), 0 }));
54
55 return SlavePTY::all_instances().with([&](auto& list) -> ErrorOr<void> {
56 StringBuilder builder;
57 for (SlavePTY& slave_pty : list) {
58 builder.clear();
59 TRY(builder.try_appendff("{}", slave_pty.index()));
60 TRY(callback({ builder.string_view(), { fsid(), pty_index_to_inode_index(slave_pty.index()) }, 0 }));
61 }
62 return {};
63 });
64}
65
66ErrorOr<NonnullRefPtr<Inode>> DevPtsFSInode::lookup(StringView name)
67{
68 VERIFY(identifier().index() == 1);
69
70 if (name == "." || name == "..")
71 return *this;
72
73 auto pty_index = name.to_uint();
74 if (!pty_index.has_value())
75 return ENOENT;
76
77 return SlavePTY::all_instances().with([&](auto& list) -> ErrorOr<NonnullRefPtr<Inode>> {
78 for (SlavePTY& slave_pty : list) {
79 if (slave_pty.index() != pty_index.value())
80 continue;
81 return fs().get_inode({ fsid(), pty_index_to_inode_index(pty_index.value()) });
82 }
83 return ENOENT;
84 });
85}
86
87ErrorOr<void> DevPtsFSInode::flush_metadata()
88{
89 return {};
90}
91
92ErrorOr<void> DevPtsFSInode::add_child(Inode&, StringView, mode_t)
93{
94 return EROFS;
95}
96
97ErrorOr<NonnullRefPtr<Inode>> DevPtsFSInode::create_child(StringView, mode_t, dev_t, UserID, GroupID)
98{
99 return EROFS;
100}
101
102ErrorOr<void> DevPtsFSInode::remove_child(StringView)
103{
104 return EROFS;
105}
106
107ErrorOr<void> DevPtsFSInode::replace_child(StringView, Inode&)
108{
109 return EROFS;
110}
111
112ErrorOr<void> DevPtsFSInode::chmod(mode_t)
113{
114 return EROFS;
115}
116
117ErrorOr<void> DevPtsFSInode::chown(UserID, GroupID)
118{
119 return EROFS;
120}
121
122}