DevPtsFS.cpp 4.2 KB

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