DevPtsFS.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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. #include <Kernel/FileSystem/DevPtsFS.h>
  8. #include <Kernel/FileSystem/VirtualFileSystem.h>
  9. #include <Kernel/TTY/SlavePTY.h>
  10. namespace Kernel {
  11. NonnullRefPtr<DevPtsFS> DevPtsFS::create()
  12. {
  13. return adopt_ref(*new DevPtsFS);
  14. }
  15. DevPtsFS::DevPtsFS()
  16. {
  17. }
  18. DevPtsFS::~DevPtsFS()
  19. {
  20. }
  21. KResult DevPtsFS::initialize()
  22. {
  23. m_root_inode = adopt_ref_if_nonnull(new (nothrow) DevPtsFSInode(*this, 1, nullptr));
  24. if (!m_root_inode)
  25. return ENOMEM;
  26. m_root_inode->m_metadata.inode = { fsid(), 1 };
  27. m_root_inode->m_metadata.mode = 0040555;
  28. m_root_inode->m_metadata.uid = 0;
  29. m_root_inode->m_metadata.gid = 0;
  30. m_root_inode->m_metadata.size = 0;
  31. m_root_inode->m_metadata.mtime = mepoch;
  32. return KSuccess;
  33. }
  34. static unsigned inode_index_to_pty_index(InodeIndex inode_index)
  35. {
  36. VERIFY(inode_index > 1);
  37. return inode_index.value() - 2;
  38. }
  39. static InodeIndex pty_index_to_inode_index(unsigned pty_index)
  40. {
  41. return pty_index + 2;
  42. }
  43. Inode& DevPtsFS::root_inode()
  44. {
  45. return *m_root_inode;
  46. }
  47. KResultOr<NonnullRefPtr<Inode>> DevPtsFS::get_inode(InodeIdentifier inode_id) const
  48. {
  49. if (inode_id.index() == 1)
  50. return *m_root_inode;
  51. unsigned pty_index = inode_index_to_pty_index(inode_id.index());
  52. auto* device = Device::get_device(201, pty_index);
  53. VERIFY(device);
  54. // FIXME: Handle OOM
  55. auto inode = adopt_ref(*new DevPtsFSInode(const_cast<DevPtsFS&>(*this), inode_id.index(), static_cast<SlavePTY*>(device)));
  56. inode->m_metadata.inode = inode_id;
  57. inode->m_metadata.size = 0;
  58. inode->m_metadata.uid = device->uid();
  59. inode->m_metadata.gid = device->gid();
  60. inode->m_metadata.mode = 0020600;
  61. inode->m_metadata.major_device = device->major();
  62. inode->m_metadata.minor_device = device->minor();
  63. inode->m_metadata.mtime = mepoch;
  64. return inode;
  65. }
  66. DevPtsFSInode::DevPtsFSInode(DevPtsFS& fs, InodeIndex index, SlavePTY* pty)
  67. : Inode(fs, index)
  68. {
  69. if (pty)
  70. m_pty = *pty;
  71. }
  72. DevPtsFSInode::~DevPtsFSInode()
  73. {
  74. }
  75. KResultOr<size_t> DevPtsFSInode::read_bytes(off_t, size_t, UserOrKernelBuffer&, FileDescription*) const
  76. {
  77. VERIFY_NOT_REACHED();
  78. }
  79. KResultOr<size_t> DevPtsFSInode::write_bytes(off_t, size_t, const UserOrKernelBuffer&, FileDescription*)
  80. {
  81. VERIFY_NOT_REACHED();
  82. }
  83. InodeMetadata DevPtsFSInode::metadata() const
  84. {
  85. if (auto pty = m_pty.strong_ref()) {
  86. auto metadata = m_metadata;
  87. metadata.mtime = pty->time_of_last_write();
  88. return metadata;
  89. }
  90. return m_metadata;
  91. }
  92. KResult DevPtsFSInode::traverse_as_directory(Function<bool(FileSystem::DirectoryEntryView const&)> callback) const
  93. {
  94. if (identifier().index() > 1)
  95. return ENOTDIR;
  96. callback({ ".", identifier(), 0 });
  97. callback({ "..", identifier(), 0 });
  98. SlavePTY::all_instances().with([&](auto& list) {
  99. for (SlavePTY& slave_pty : list) {
  100. StringBuilder builder;
  101. builder.appendff("{}", slave_pty.index());
  102. callback({ builder.string_view(), { fsid(), pty_index_to_inode_index(slave_pty.index()) }, 0 });
  103. }
  104. });
  105. return KSuccess;
  106. }
  107. KResultOr<NonnullRefPtr<Inode>> DevPtsFSInode::lookup(StringView name)
  108. {
  109. VERIFY(identifier().index() == 1);
  110. if (name == "." || name == "..")
  111. return *this;
  112. auto pty_index = name.to_uint();
  113. if (!pty_index.has_value())
  114. return ENOENT;
  115. return SlavePTY::all_instances().with([&](auto& list) -> KResultOr<NonnullRefPtr<Inode>> {
  116. for (SlavePTY& slave_pty : list) {
  117. if (slave_pty.index() != pty_index.value())
  118. continue;
  119. return fs().get_inode({ fsid(), pty_index_to_inode_index(pty_index.value()) });
  120. }
  121. return ENOENT;
  122. });
  123. }
  124. void DevPtsFSInode::flush_metadata()
  125. {
  126. }
  127. KResult DevPtsFSInode::add_child(Inode&, const StringView&, mode_t)
  128. {
  129. return EROFS;
  130. }
  131. KResultOr<NonnullRefPtr<Inode>> DevPtsFSInode::create_child(StringView, mode_t, dev_t, UserID, GroupID)
  132. {
  133. return EROFS;
  134. }
  135. KResult DevPtsFSInode::remove_child(const StringView&)
  136. {
  137. return EROFS;
  138. }
  139. KResult DevPtsFSInode::chmod(mode_t)
  140. {
  141. return EROFS;
  142. }
  143. KResult DevPtsFSInode::chown(UserID, GroupID)
  144. {
  145. return EROFS;
  146. }
  147. }