DevFS.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /*
  2. * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
  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/DevFS.h>
  10. #include <Kernel/FileSystem/VirtualFileSystem.h>
  11. namespace Kernel {
  12. NonnullRefPtr<DevFS> DevFS::create()
  13. {
  14. return adopt_ref(*new DevFS);
  15. }
  16. DevFS::DevFS()
  17. : m_root_inode(adopt_ref(*new DevFSRootDirectoryInode(*this)))
  18. {
  19. LOCKER(m_lock);
  20. Device::for_each([&](Device& device) {
  21. // FIXME: Find a better way to not add MasterPTYs or SlavePTYs!
  22. if (device.is_master_pty() || (device.is_character_device() && device.major() == 201))
  23. return;
  24. notify_new_device(device);
  25. });
  26. }
  27. void DevFS::notify_new_device(Device& device)
  28. {
  29. LOCKER(m_lock);
  30. auto new_device_inode = adopt_ref(*new DevFSDeviceInode(*this, device));
  31. m_nodes.append(new_device_inode);
  32. m_root_inode->m_devices.append(new_device_inode);
  33. }
  34. size_t DevFS::allocate_inode_index()
  35. {
  36. LOCKER(m_lock);
  37. m_next_inode_index = m_next_inode_index.value() + 1;
  38. VERIFY(m_next_inode_index > 0);
  39. return 1 + m_next_inode_index.value();
  40. }
  41. void DevFS::notify_device_removal(Device&)
  42. {
  43. TODO();
  44. }
  45. DevFS::~DevFS()
  46. {
  47. }
  48. bool DevFS::initialize()
  49. {
  50. return true;
  51. }
  52. NonnullRefPtr<Inode> DevFS::root_inode() const
  53. {
  54. return *m_root_inode;
  55. }
  56. RefPtr<Inode> DevFS::get_inode(InodeIdentifier inode_id) const
  57. {
  58. LOCKER(m_lock);
  59. if (inode_id.index() == 1)
  60. return m_root_inode;
  61. for (auto& node : m_nodes) {
  62. if (inode_id.index() == node.index())
  63. return node;
  64. }
  65. return nullptr;
  66. }
  67. DevFSInode::DevFSInode(DevFS& fs)
  68. : Inode(fs, fs.allocate_inode_index())
  69. {
  70. }
  71. ssize_t DevFSInode::read_bytes(off_t, ssize_t, UserOrKernelBuffer&, FileDescription*) const
  72. {
  73. VERIFY_NOT_REACHED();
  74. }
  75. KResult DevFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const
  76. {
  77. VERIFY_NOT_REACHED();
  78. }
  79. RefPtr<Inode> DevFSInode::lookup(StringView)
  80. {
  81. VERIFY_NOT_REACHED();
  82. }
  83. void DevFSInode::flush_metadata()
  84. {
  85. }
  86. ssize_t DevFSInode::write_bytes(off_t, ssize_t, const UserOrKernelBuffer&, FileDescription*)
  87. {
  88. VERIFY_NOT_REACHED();
  89. }
  90. KResultOr<NonnullRefPtr<Inode>> DevFSInode::create_child(const String&, mode_t, dev_t, uid_t, gid_t)
  91. {
  92. return EROFS;
  93. }
  94. KResult DevFSInode::add_child(Inode&, const StringView&, mode_t)
  95. {
  96. return EROFS;
  97. }
  98. KResult DevFSInode::remove_child(const StringView&)
  99. {
  100. return EROFS;
  101. }
  102. KResultOr<size_t> DevFSInode::directory_entry_count() const
  103. {
  104. VERIFY_NOT_REACHED();
  105. }
  106. KResult DevFSInode::chmod(mode_t)
  107. {
  108. return EPERM;
  109. }
  110. KResult DevFSInode::chown(uid_t, gid_t)
  111. {
  112. return EPERM;
  113. }
  114. KResult DevFSInode::truncate(u64)
  115. {
  116. return EPERM;
  117. }
  118. String DevFSLinkInode::name() const
  119. {
  120. return m_name;
  121. }
  122. DevFSLinkInode::~DevFSLinkInode()
  123. {
  124. }
  125. DevFSLinkInode::DevFSLinkInode(DevFS& fs, String name)
  126. : DevFSInode(fs)
  127. , m_name(name)
  128. {
  129. }
  130. ssize_t DevFSLinkInode::read_bytes(off_t offset, ssize_t, UserOrKernelBuffer& buffer, FileDescription*) const
  131. {
  132. LOCKER(m_lock);
  133. VERIFY(offset == 0);
  134. VERIFY(!m_link.is_null());
  135. if (!buffer.write(((const u8*)m_link.substring_view(0).characters_without_null_termination()) + offset, m_link.length()))
  136. return -EFAULT;
  137. return m_link.length();
  138. }
  139. InodeMetadata DevFSLinkInode::metadata() const
  140. {
  141. LOCKER(m_lock);
  142. InodeMetadata metadata;
  143. metadata.inode = { fsid(), index() };
  144. metadata.mode = S_IFLNK | 0555;
  145. metadata.uid = 0;
  146. metadata.gid = 0;
  147. metadata.size = 0;
  148. metadata.mtime = mepoch;
  149. return metadata;
  150. }
  151. ssize_t DevFSLinkInode::write_bytes(off_t offset, ssize_t count, const UserOrKernelBuffer& buffer, FileDescription*)
  152. {
  153. LOCKER(m_lock);
  154. VERIFY(offset == 0);
  155. VERIFY(buffer.is_kernel_buffer());
  156. m_link = buffer.copy_into_string(count);
  157. return count;
  158. }
  159. DevFSDirectoryInode::DevFSDirectoryInode(DevFS& fs)
  160. : DevFSInode(fs)
  161. {
  162. }
  163. DevFSDirectoryInode::~DevFSDirectoryInode()
  164. {
  165. }
  166. InodeMetadata DevFSDirectoryInode::metadata() const
  167. {
  168. LOCKER(m_lock);
  169. InodeMetadata metadata;
  170. metadata.inode = { fsid(), 1 };
  171. metadata.mode = 0040555;
  172. metadata.uid = 0;
  173. metadata.gid = 0;
  174. metadata.size = 0;
  175. metadata.mtime = mepoch;
  176. return metadata;
  177. }
  178. KResult DevFSDirectoryInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const
  179. {
  180. LOCKER(m_lock);
  181. return EINVAL;
  182. }
  183. RefPtr<Inode> DevFSDirectoryInode::lookup(StringView)
  184. {
  185. LOCKER(m_lock);
  186. return nullptr;
  187. }
  188. KResultOr<size_t> DevFSDirectoryInode::directory_entry_count() const
  189. {
  190. LOCKER(m_lock);
  191. return m_devices.size();
  192. }
  193. DevFSRootDirectoryInode::DevFSRootDirectoryInode(DevFS& fs)
  194. : DevFSDirectoryInode(fs)
  195. , m_parent_fs(fs)
  196. {
  197. }
  198. KResult DevFSRootDirectoryInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)> callback) const
  199. {
  200. LOCKER(m_parent_fs.m_lock);
  201. callback({ ".", identifier(), 0 });
  202. callback({ "..", identifier(), 0 });
  203. for (auto& folder : m_subfolders) {
  204. InodeIdentifier identifier = { fsid(), folder.index() };
  205. callback({ folder.name(), identifier, 0 });
  206. }
  207. for (auto& link : m_links) {
  208. InodeIdentifier identifier = { fsid(), link.index() };
  209. callback({ link.name(), identifier, 0 });
  210. }
  211. for (auto& device_node : m_devices) {
  212. InodeIdentifier identifier = { fsid(), device_node.index() };
  213. callback({ device_node.name(), identifier, 0 });
  214. }
  215. return KSuccess;
  216. }
  217. RefPtr<Inode> DevFSRootDirectoryInode::lookup(StringView name)
  218. {
  219. LOCKER(m_parent_fs.m_lock);
  220. for (auto& subfolder : m_subfolders) {
  221. if (subfolder.name() == name)
  222. return subfolder;
  223. }
  224. for (auto& link : m_links) {
  225. if (link.name() == name)
  226. return link;
  227. }
  228. for (auto& device_node : m_devices) {
  229. if (device_node.name() == name) {
  230. return device_node;
  231. }
  232. }
  233. return nullptr;
  234. }
  235. KResultOr<NonnullRefPtr<Inode>> DevFSRootDirectoryInode::create_child(const String& name, mode_t mode, dev_t, uid_t, gid_t)
  236. {
  237. LOCKER(m_parent_fs.m_lock);
  238. InodeMetadata metadata;
  239. metadata.mode = mode;
  240. if (metadata.is_directory()) {
  241. for (auto& folder : m_subfolders) {
  242. if (folder.name() == name)
  243. return EEXIST;
  244. }
  245. if (name != "pts")
  246. return EROFS;
  247. auto new_directory_inode = adopt_ref(*new DevFSPtsDirectoryInode(m_parent_fs));
  248. m_subfolders.append(new_directory_inode);
  249. m_parent_fs.m_nodes.append(new_directory_inode);
  250. return KResult(KSuccess);
  251. }
  252. if (metadata.is_symlink()) {
  253. for (auto& link : m_links) {
  254. if (link.name() == name)
  255. return EEXIST;
  256. }
  257. auto new_link_inode = adopt_ref(*new DevFSLinkInode(m_parent_fs, name));
  258. m_links.append(new_link_inode);
  259. m_parent_fs.m_nodes.append(new_link_inode);
  260. return new_link_inode;
  261. }
  262. return EROFS;
  263. }
  264. DevFSRootDirectoryInode::~DevFSRootDirectoryInode()
  265. {
  266. }
  267. InodeMetadata DevFSRootDirectoryInode::metadata() const
  268. {
  269. LOCKER(m_parent_fs.m_lock);
  270. InodeMetadata metadata;
  271. metadata.inode = { fsid(), 1 };
  272. metadata.mode = 0040555;
  273. metadata.uid = 0;
  274. metadata.gid = 0;
  275. metadata.size = 0;
  276. metadata.mtime = mepoch;
  277. return metadata;
  278. }
  279. KResultOr<size_t> DevFSRootDirectoryInode::directory_entry_count() const
  280. {
  281. LOCKER(m_parent_fs.m_lock);
  282. return m_devices.size() + DevFSDirectoryInode::directory_entry_count().value();
  283. }
  284. DevFSDeviceInode::DevFSDeviceInode(DevFS& fs, const Device& device)
  285. : DevFSInode(fs)
  286. , m_attached_device(device)
  287. {
  288. }
  289. DevFSDeviceInode::~DevFSDeviceInode()
  290. {
  291. }
  292. KResult DevFSDeviceInode::chown(uid_t uid, gid_t gid)
  293. {
  294. LOCKER(m_lock);
  295. m_uid = uid;
  296. m_gid = gid;
  297. return KSuccess;
  298. }
  299. String DevFSDeviceInode::name() const
  300. {
  301. LOCKER(m_lock);
  302. if (m_cached_name.is_null() || m_cached_name.is_empty())
  303. const_cast<DevFSDeviceInode&>(*this).m_cached_name = m_attached_device->device_name();
  304. return m_cached_name;
  305. }
  306. ssize_t DevFSDeviceInode::read_bytes(off_t offset, ssize_t count, UserOrKernelBuffer& buffer, FileDescription* description) const
  307. {
  308. LOCKER(m_lock);
  309. VERIFY(!!description);
  310. if (!m_attached_device->can_read(*description, offset))
  311. return 0;
  312. auto nread = const_cast<Device&>(*m_attached_device).read(*description, offset, buffer, count);
  313. if (nread.is_error())
  314. return -EIO;
  315. return nread.value();
  316. }
  317. InodeMetadata DevFSDeviceInode::metadata() const
  318. {
  319. LOCKER(m_lock);
  320. InodeMetadata metadata;
  321. metadata.inode = { fsid(), index() };
  322. metadata.mode = (m_attached_device->is_block_device() ? S_IFBLK : S_IFCHR) | m_attached_device->required_mode();
  323. metadata.uid = m_uid;
  324. metadata.gid = m_gid;
  325. metadata.size = 0;
  326. metadata.mtime = mepoch;
  327. metadata.major_device = m_attached_device->major();
  328. metadata.minor_device = m_attached_device->minor();
  329. return metadata;
  330. }
  331. ssize_t DevFSDeviceInode::write_bytes(off_t offset, ssize_t count, const UserOrKernelBuffer& buffer, FileDescription* description)
  332. {
  333. LOCKER(m_lock);
  334. VERIFY(!!description);
  335. if (!m_attached_device->can_write(*description, offset))
  336. return 0;
  337. auto nread = const_cast<Device&>(*m_attached_device).write(*description, offset, buffer, count);
  338. if (nread.is_error())
  339. return -EIO;
  340. return nread.value();
  341. }
  342. DevFSPtsDirectoryInode::DevFSPtsDirectoryInode(DevFS& fs)
  343. : DevFSDirectoryInode(fs)
  344. {
  345. }
  346. KResult DevFSPtsDirectoryInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)> callback) const
  347. {
  348. LOCKER(m_lock);
  349. callback({ ".", identifier(), 0 });
  350. callback({ "..", identifier(), 0 });
  351. return KSuccess;
  352. }
  353. RefPtr<Inode> DevFSPtsDirectoryInode::lookup(StringView)
  354. {
  355. return nullptr;
  356. }
  357. DevFSPtsDirectoryInode::~DevFSPtsDirectoryInode()
  358. {
  359. }
  360. InodeMetadata DevFSPtsDirectoryInode::metadata() const
  361. {
  362. LOCKER(m_lock);
  363. InodeMetadata metadata;
  364. metadata.inode = { fsid(), index() };
  365. metadata.mode = 0040555;
  366. metadata.uid = 0;
  367. metadata.gid = 0;
  368. metadata.size = 0;
  369. metadata.mtime = mepoch;
  370. return metadata;
  371. }
  372. KResultOr<size_t> DevFSPtsDirectoryInode::directory_entry_count() const
  373. {
  374. return 0;
  375. }
  376. }