DevPtsFS.cpp 4.6 KB

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