DevPtsFS.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. RefPtr<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. auto inode = adopt_ref(*new DevPtsFSInode(const_cast<DevPtsFS&>(*this), inode_id.index(), static_cast<SlavePTY*>(device)));
  55. inode->m_metadata.inode = inode_id;
  56. inode->m_metadata.size = 0;
  57. inode->m_metadata.uid = device->uid();
  58. inode->m_metadata.gid = device->gid();
  59. inode->m_metadata.mode = 0020600;
  60. inode->m_metadata.major_device = device->major();
  61. inode->m_metadata.minor_device = device->minor();
  62. inode->m_metadata.mtime = mepoch;
  63. return inode;
  64. }
  65. DevPtsFSInode::DevPtsFSInode(DevPtsFS& fs, InodeIndex index, SlavePTY* pty)
  66. : Inode(fs, index)
  67. {
  68. if (pty)
  69. m_pty = *pty;
  70. }
  71. DevPtsFSInode::~DevPtsFSInode()
  72. {
  73. }
  74. KResultOr<size_t> DevPtsFSInode::read_bytes(off_t, size_t, UserOrKernelBuffer&, FileDescription*) const
  75. {
  76. VERIFY_NOT_REACHED();
  77. }
  78. KResultOr<size_t> DevPtsFSInode::write_bytes(off_t, size_t, const UserOrKernelBuffer&, FileDescription*)
  79. {
  80. VERIFY_NOT_REACHED();
  81. }
  82. InodeMetadata DevPtsFSInode::metadata() const
  83. {
  84. if (auto pty = m_pty.strong_ref()) {
  85. auto metadata = m_metadata;
  86. metadata.mtime = pty->time_of_last_write();
  87. return metadata;
  88. }
  89. return m_metadata;
  90. }
  91. KResult DevPtsFSInode::traverse_as_directory(Function<bool(FileSystem::DirectoryEntryView const&)> callback) const
  92. {
  93. if (identifier().index() > 1)
  94. return ENOTDIR;
  95. callback({ ".", identifier(), 0 });
  96. callback({ "..", identifier(), 0 });
  97. SlavePTY::all_instances().with([&](auto& list) {
  98. for (SlavePTY& slave_pty : list) {
  99. StringBuilder builder;
  100. builder.appendff("{}", slave_pty.index());
  101. callback({ builder.string_view(), { fsid(), pty_index_to_inode_index(slave_pty.index()) }, 0 });
  102. }
  103. });
  104. return KSuccess;
  105. }
  106. KResultOr<NonnullRefPtr<Inode>> DevPtsFSInode::lookup(StringView name)
  107. {
  108. VERIFY(identifier().index() == 1);
  109. if (name == "." || name == "..")
  110. return *this;
  111. auto pty_index = name.to_uint();
  112. if (!pty_index.has_value())
  113. return ENOENT;
  114. return SlavePTY::all_instances().with([&](auto& list) -> KResultOr<NonnullRefPtr<Inode>> {
  115. for (SlavePTY& slave_pty : list) {
  116. if (slave_pty.index() != pty_index.value())
  117. continue;
  118. auto inode = fs().get_inode({ fsid(), pty_index_to_inode_index(pty_index.value()) });
  119. if (!inode)
  120. return ENOENT;
  121. return inode.release_nonnull();
  122. }
  123. return ENOENT;
  124. });
  125. }
  126. void DevPtsFSInode::flush_metadata()
  127. {
  128. }
  129. KResult DevPtsFSInode::add_child(Inode&, const StringView&, mode_t)
  130. {
  131. return EROFS;
  132. }
  133. KResultOr<NonnullRefPtr<Inode>> DevPtsFSInode::create_child(StringView, mode_t, dev_t, UserID, GroupID)
  134. {
  135. return EROFS;
  136. }
  137. KResult DevPtsFSInode::remove_child(const StringView&)
  138. {
  139. return EROFS;
  140. }
  141. KResult DevPtsFSInode::chmod(mode_t)
  142. {
  143. return EROFS;
  144. }
  145. KResult DevPtsFSInode::chown(UserID, GroupID)
  146. {
  147. return EROFS;
  148. }
  149. }