ProcFS.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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/FileBackedFileSystem.h>
  12. #include <Kernel/FileSystem/FileDescription.h>
  13. #include <Kernel/FileSystem/ProcFS.h>
  14. #include <Kernel/FileSystem/VirtualFileSystem.h>
  15. #include <Kernel/Heap/kmalloc.h>
  16. #include <Kernel/Sections.h>
  17. #include <LibC/errno_numbers.h>
  18. namespace Kernel {
  19. static AK::Singleton<ProcFSComponentsRegistrar> s_the;
  20. ProcFSComponentsRegistrar& ProcFSComponentsRegistrar::the()
  21. {
  22. return *s_the;
  23. }
  24. UNMAP_AFTER_INIT void ProcFSComponentsRegistrar::initialize()
  25. {
  26. VERIFY(!s_the.is_initialized());
  27. s_the.ensure_instance();
  28. }
  29. UNMAP_AFTER_INIT ProcFSComponentsRegistrar::ProcFSComponentsRegistrar()
  30. : m_root_folder(ProcFSRootFolder::must_create())
  31. {
  32. }
  33. const ProcFSBusDirectory& ProcFSComponentsRegistrar::buses_folder() const
  34. {
  35. return *m_root_folder->m_buses_folder;
  36. }
  37. void ProcFSComponentsRegistrar::register_new_bus_folder(ProcFSExposedFolder& new_bus_folder)
  38. {
  39. VERIFY(!m_root_folder->m_buses_folder.is_null());
  40. m_root_folder->m_buses_folder->m_components.append(new_bus_folder);
  41. }
  42. void ProcFSComponentsRegistrar::register_new_process(Process& new_process)
  43. {
  44. Locker locker(m_lock);
  45. m_root_folder->m_process_folders.append(ProcFSProcessFolder::create(new_process));
  46. }
  47. void ProcFSComponentsRegistrar::unregister_process(Process& deleted_process)
  48. {
  49. auto process_folder = m_root_folder->process_folder_for(deleted_process).release_nonnull();
  50. process_folder->prepare_for_deletion();
  51. process_folder->m_list_node.remove();
  52. dbgln_if(PROCFS_DEBUG, "ProcFSExposedFolder ref_count now: {}", process_folder->ref_count());
  53. // Note: Let's ensure we are the last holder of the ProcFSProcessFolder object before it can be deleted for good
  54. VERIFY(process_folder->ref_count() == 1);
  55. }
  56. RefPtr<ProcFS> ProcFS::create()
  57. {
  58. return adopt_ref_if_nonnull(new (nothrow) ProcFS);
  59. }
  60. ProcFS::~ProcFS()
  61. {
  62. }
  63. bool ProcFS::initialize()
  64. {
  65. return true;
  66. }
  67. NonnullRefPtr<Inode> ProcFS::root_inode() const
  68. {
  69. return *m_root_inode;
  70. }
  71. NonnullRefPtr<ProcFSInode> ProcFSInode::create(const ProcFS& fs, const ProcFSExposedComponent& component)
  72. {
  73. return adopt_ref(*new (nothrow) ProcFSInode(fs, component));
  74. }
  75. ProcFSInode::ProcFSInode(const ProcFS& fs, const ProcFSExposedComponent& component)
  76. : Inode(const_cast<ProcFS&>(fs), component.component_index())
  77. , m_associated_component(component)
  78. {
  79. }
  80. KResult ProcFSInode::attach(FileDescription& description)
  81. {
  82. return m_associated_component->refresh_data(description);
  83. }
  84. void ProcFSInode::did_seek(FileDescription& description, off_t new_offset)
  85. {
  86. if (new_offset != 0)
  87. return;
  88. auto result = m_associated_component->refresh_data(description);
  89. if (result.is_error()) {
  90. // Subsequent calls to read will return EIO!
  91. dbgln("ProcFS: Could not refresh contents: {}", result.error());
  92. }
  93. }
  94. ProcFSInode::~ProcFSInode()
  95. {
  96. }
  97. ProcFS::ProcFS()
  98. : m_root_inode(ProcFSComponentsRegistrar::the().root_folder().to_inode(*this))
  99. {
  100. }
  101. KResultOr<size_t> ProcFSInode::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription* fd) const
  102. {
  103. return m_associated_component->read_bytes(offset, count, buffer, fd);
  104. }
  105. StringView ProcFSInode::name() const
  106. {
  107. return m_associated_component->name();
  108. }
  109. KResult ProcFSInode::traverse_as_directory(Function<bool(FileSystem::DirectoryEntryView const&)>) const
  110. {
  111. VERIFY_NOT_REACHED();
  112. }
  113. RefPtr<Inode> ProcFSInode::lookup(StringView)
  114. {
  115. VERIFY_NOT_REACHED();
  116. }
  117. InodeMetadata ProcFSInode::metadata() const
  118. {
  119. Locker locker(m_lock);
  120. InodeMetadata metadata;
  121. metadata.inode = { fsid(), m_associated_component->component_index() };
  122. metadata.mode = m_associated_component->required_mode();
  123. metadata.uid = m_associated_component->owner_user();
  124. metadata.gid = m_associated_component->owner_group();
  125. metadata.size = m_associated_component->size();
  126. metadata.mtime = m_associated_component->modified_time();
  127. return metadata;
  128. }
  129. void ProcFSInode::flush_metadata()
  130. {
  131. }
  132. KResultOr<size_t> ProcFSInode::write_bytes(off_t offset, size_t count, const UserOrKernelBuffer& buffer, FileDescription* fd)
  133. {
  134. return m_associated_component->write_bytes(offset, count, buffer, fd);
  135. }
  136. KResultOr<NonnullRefPtr<Inode>> ProcFSInode::create_child(const String&, mode_t, dev_t, uid_t, gid_t)
  137. {
  138. return EROFS;
  139. }
  140. KResult ProcFSInode::add_child(Inode&, const StringView&, mode_t)
  141. {
  142. return EROFS;
  143. }
  144. KResult ProcFSInode::remove_child(const StringView&)
  145. {
  146. return EROFS;
  147. }
  148. KResultOr<size_t> ProcFSInode::directory_entry_count() const
  149. {
  150. VERIFY_NOT_REACHED();
  151. }
  152. KResult ProcFSInode::chmod(mode_t)
  153. {
  154. return EPERM;
  155. }
  156. KResult ProcFSInode::chown(uid_t, gid_t)
  157. {
  158. return EPERM;
  159. }
  160. KResult ProcFSInode::truncate(u64)
  161. {
  162. return EPERM;
  163. }
  164. NonnullRefPtr<ProcFSDirectoryInode> ProcFSDirectoryInode::create(const ProcFS& procfs, const ProcFSExposedComponent& component)
  165. {
  166. return adopt_ref(*new (nothrow) ProcFSDirectoryInode(procfs, component));
  167. }
  168. ProcFSDirectoryInode::ProcFSDirectoryInode(const ProcFS& fs, const ProcFSExposedComponent& component)
  169. : ProcFSInode(fs, component)
  170. , m_parent_fs(const_cast<ProcFS&>(fs))
  171. {
  172. }
  173. ProcFSDirectoryInode::~ProcFSDirectoryInode()
  174. {
  175. }
  176. InodeMetadata ProcFSDirectoryInode::metadata() const
  177. {
  178. Locker locker(m_lock);
  179. InodeMetadata metadata;
  180. metadata.inode = { fsid(), m_associated_component->component_index() };
  181. metadata.mode = S_IFDIR | m_associated_component->required_mode();
  182. metadata.uid = m_associated_component->owner_user();
  183. metadata.gid = m_associated_component->owner_group();
  184. metadata.size = 0;
  185. metadata.mtime = m_associated_component->modified_time();
  186. return metadata;
  187. }
  188. KResult ProcFSDirectoryInode::traverse_as_directory(Function<bool(FileSystem::DirectoryEntryView const&)> callback) const
  189. {
  190. Locker locker(m_parent_fs.m_lock);
  191. return m_associated_component->traverse_as_directory(m_parent_fs.fsid(), move(callback));
  192. }
  193. RefPtr<Inode> ProcFSDirectoryInode::lookup(StringView name)
  194. {
  195. Locker locker(m_parent_fs.m_lock);
  196. auto component = m_associated_component->lookup(name);
  197. if (!component)
  198. return {};
  199. return component->to_inode(m_parent_fs);
  200. }
  201. KResultOr<size_t> ProcFSDirectoryInode::directory_entry_count() const
  202. {
  203. Locker locker(m_lock);
  204. return m_associated_component->entries_count();
  205. }
  206. NonnullRefPtr<ProcFSLinkInode> ProcFSLinkInode::create(const ProcFS& procfs, const ProcFSExposedComponent& component)
  207. {
  208. return adopt_ref(*new (nothrow) ProcFSLinkInode(procfs, component));
  209. }
  210. ProcFSLinkInode::ProcFSLinkInode(const ProcFS& fs, const ProcFSExposedComponent& component)
  211. : ProcFSInode(fs, component)
  212. {
  213. }
  214. InodeMetadata ProcFSLinkInode::metadata() const
  215. {
  216. Locker locker(m_lock);
  217. InodeMetadata metadata;
  218. metadata.inode = { fsid(), m_associated_component->component_index() };
  219. metadata.mode = S_IFLNK | m_associated_component->required_mode();
  220. metadata.uid = m_associated_component->owner_user();
  221. metadata.gid = m_associated_component->owner_group();
  222. metadata.size = 0;
  223. metadata.mtime = m_associated_component->modified_time();
  224. return metadata;
  225. }
  226. }