ProcFS.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, Spencer Dixon <spencercdixon@gmail.com>
  4. * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #include <AK/Singleton.h>
  9. #include <Kernel/Debug.h>
  10. #include <Kernel/FileSystem/Custody.h>
  11. #include <Kernel/FileSystem/FileDescription.h>
  12. #include <Kernel/FileSystem/ProcFS.h>
  13. #include <Kernel/FileSystem/VirtualFileSystem.h>
  14. #include <Kernel/Heap/kmalloc.h>
  15. #include <Kernel/Sections.h>
  16. #include <LibC/errno_numbers.h>
  17. namespace Kernel {
  18. static AK::Singleton<ProcFSComponentRegistry> s_the;
  19. ProcFSComponentRegistry& ProcFSComponentRegistry::the()
  20. {
  21. return *s_the;
  22. }
  23. UNMAP_AFTER_INIT void ProcFSComponentRegistry::initialize()
  24. {
  25. VERIFY(!s_the.is_initialized());
  26. s_the.ensure_instance();
  27. }
  28. UNMAP_AFTER_INIT ProcFSComponentRegistry::ProcFSComponentRegistry()
  29. : m_root_directory(ProcFSRootDirectory::must_create())
  30. {
  31. }
  32. const ProcFSBusDirectory& ProcFSComponentRegistry::buses_directory() const
  33. {
  34. return *m_root_directory->m_buses_directory;
  35. }
  36. void ProcFSComponentRegistry::register_new_bus_directory(ProcFSExposedDirectory& new_bus_directory)
  37. {
  38. VERIFY(!m_root_directory->m_buses_directory.is_null());
  39. m_root_directory->m_buses_directory->m_components.append(new_bus_directory);
  40. }
  41. void ProcFSComponentRegistry::register_new_process(Process& new_process)
  42. {
  43. Locker locker(m_lock);
  44. m_root_directory->m_process_directories.append(ProcFSProcessDirectory::create(new_process));
  45. }
  46. void ProcFSComponentRegistry::unregister_process(Process& deleted_process)
  47. {
  48. auto process_directory = m_root_directory->process_directory_for(deleted_process).release_nonnull();
  49. process_directory->prepare_for_deletion();
  50. process_directory->m_list_node.remove();
  51. dbgln_if(PROCFS_DEBUG, "ProcFSExposedDirectory ref_count now: {}", process_directory->ref_count());
  52. }
  53. RefPtr<ProcFS> ProcFS::create()
  54. {
  55. return adopt_ref_if_nonnull(new (nothrow) ProcFS);
  56. }
  57. ProcFS::~ProcFS()
  58. {
  59. }
  60. bool ProcFS::initialize()
  61. {
  62. return true;
  63. }
  64. NonnullRefPtr<Inode> ProcFS::root_inode() const
  65. {
  66. return *m_root_inode;
  67. }
  68. NonnullRefPtr<ProcFSInode> ProcFSInode::create(const ProcFS& fs, const ProcFSExposedComponent& component)
  69. {
  70. return adopt_ref(*new (nothrow) ProcFSInode(fs, component));
  71. }
  72. ProcFSInode::ProcFSInode(const ProcFS& fs, const ProcFSExposedComponent& component)
  73. : Inode(const_cast<ProcFS&>(fs), component.component_index())
  74. , m_associated_component(component)
  75. {
  76. }
  77. KResult ProcFSInode::attach(FileDescription& description)
  78. {
  79. return m_associated_component->refresh_data(description);
  80. }
  81. void ProcFSInode::did_seek(FileDescription& description, off_t new_offset)
  82. {
  83. if (new_offset != 0)
  84. return;
  85. auto result = m_associated_component->refresh_data(description);
  86. if (result.is_error()) {
  87. // Subsequent calls to read will return EIO!
  88. dbgln("ProcFS: Could not refresh contents: {}", result.error());
  89. }
  90. }
  91. ProcFSInode::~ProcFSInode()
  92. {
  93. }
  94. ProcFS::ProcFS()
  95. : m_root_inode(ProcFSComponentRegistry::the().root_directory().to_inode(*this))
  96. {
  97. }
  98. KResultOr<size_t> ProcFSInode::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription* fd) const
  99. {
  100. return m_associated_component->read_bytes(offset, count, buffer, fd);
  101. }
  102. StringView ProcFSInode::name() const
  103. {
  104. return m_associated_component->name();
  105. }
  106. KResult ProcFSInode::traverse_as_directory(Function<bool(FileSystem::DirectoryEntryView const&)>) const
  107. {
  108. VERIFY_NOT_REACHED();
  109. }
  110. RefPtr<Inode> ProcFSInode::lookup(StringView)
  111. {
  112. VERIFY_NOT_REACHED();
  113. }
  114. InodeMetadata ProcFSInode::metadata() const
  115. {
  116. Locker locker(m_inode_lock);
  117. InodeMetadata metadata;
  118. metadata.inode = { fsid(), m_associated_component->component_index() };
  119. metadata.mode = m_associated_component->required_mode();
  120. metadata.uid = m_associated_component->owner_user();
  121. metadata.gid = m_associated_component->owner_group();
  122. metadata.size = m_associated_component->size();
  123. metadata.mtime = m_associated_component->modified_time();
  124. return metadata;
  125. }
  126. void ProcFSInode::flush_metadata()
  127. {
  128. }
  129. KResultOr<size_t> ProcFSInode::write_bytes(off_t offset, size_t count, const UserOrKernelBuffer& buffer, FileDescription* fd)
  130. {
  131. return m_associated_component->write_bytes(offset, count, buffer, fd);
  132. }
  133. KResultOr<NonnullRefPtr<Inode>> ProcFSInode::create_child(StringView, mode_t, dev_t, uid_t, gid_t)
  134. {
  135. return EROFS;
  136. }
  137. KResult ProcFSInode::add_child(Inode&, const StringView&, mode_t)
  138. {
  139. return EROFS;
  140. }
  141. KResult ProcFSInode::remove_child(const StringView&)
  142. {
  143. return EROFS;
  144. }
  145. KResult ProcFSInode::chmod(mode_t)
  146. {
  147. return EPERM;
  148. }
  149. KResult ProcFSInode::chown(uid_t, gid_t)
  150. {
  151. return EPERM;
  152. }
  153. KResult ProcFSInode::truncate(u64)
  154. {
  155. return EPERM;
  156. }
  157. NonnullRefPtr<ProcFSDirectoryInode> ProcFSDirectoryInode::create(const ProcFS& procfs, const ProcFSExposedComponent& component)
  158. {
  159. return adopt_ref(*new (nothrow) ProcFSDirectoryInode(procfs, component));
  160. }
  161. ProcFSDirectoryInode::ProcFSDirectoryInode(const ProcFS& fs, const ProcFSExposedComponent& component)
  162. : ProcFSInode(fs, component)
  163. , m_parent_fs(const_cast<ProcFS&>(fs))
  164. {
  165. }
  166. ProcFSDirectoryInode::~ProcFSDirectoryInode()
  167. {
  168. }
  169. InodeMetadata ProcFSDirectoryInode::metadata() const
  170. {
  171. Locker locker(m_inode_lock);
  172. InodeMetadata metadata;
  173. metadata.inode = { fsid(), m_associated_component->component_index() };
  174. metadata.mode = S_IFDIR | m_associated_component->required_mode();
  175. metadata.uid = m_associated_component->owner_user();
  176. metadata.gid = m_associated_component->owner_group();
  177. metadata.size = 0;
  178. metadata.mtime = m_associated_component->modified_time();
  179. return metadata;
  180. }
  181. KResult ProcFSDirectoryInode::traverse_as_directory(Function<bool(FileSystem::DirectoryEntryView const&)> callback) const
  182. {
  183. Locker locker(m_parent_fs.m_lock);
  184. return m_associated_component->traverse_as_directory(m_parent_fs.fsid(), move(callback));
  185. }
  186. RefPtr<Inode> ProcFSDirectoryInode::lookup(StringView name)
  187. {
  188. Locker locker(m_parent_fs.m_lock);
  189. auto component = m_associated_component->lookup(name);
  190. if (!component)
  191. return {};
  192. return component->to_inode(m_parent_fs);
  193. }
  194. NonnullRefPtr<ProcFSLinkInode> ProcFSLinkInode::create(const ProcFS& procfs, const ProcFSExposedComponent& component)
  195. {
  196. return adopt_ref(*new (nothrow) ProcFSLinkInode(procfs, component));
  197. }
  198. ProcFSLinkInode::ProcFSLinkInode(const ProcFS& fs, const ProcFSExposedComponent& component)
  199. : ProcFSInode(fs, component)
  200. {
  201. }
  202. InodeMetadata ProcFSLinkInode::metadata() const
  203. {
  204. Locker locker(m_inode_lock);
  205. InodeMetadata metadata;
  206. metadata.inode = { fsid(), m_associated_component->component_index() };
  207. metadata.mode = S_IFLNK | m_associated_component->required_mode();
  208. metadata.uid = m_associated_component->owner_user();
  209. metadata.gid = m_associated_component->owner_group();
  210. metadata.size = 0;
  211. metadata.mtime = m_associated_component->modified_time();
  212. return metadata;
  213. }
  214. }