DevPtsFS.cpp 4.3 KB

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