DevPtsFS.cpp 4.3 KB

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