DevFS.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /*
  2. * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <AK/Singleton.h>
  27. #include <AK/StringBuilder.h>
  28. #include <AK/StringView.h>
  29. #include <Kernel/FileSystem/DevFS.h>
  30. #include <Kernel/FileSystem/VirtualFileSystem.h>
  31. namespace Kernel {
  32. NonnullRefPtr<DevFS> DevFS::create()
  33. {
  34. return adopt(*new DevFS);
  35. }
  36. DevFS::DevFS()
  37. : m_root_inode(adopt(*new DevFSRootDirectoryInode(*this)))
  38. {
  39. LOCKER(m_lock);
  40. Device::for_each([&](Device& device) {
  41. // FIXME: Find a better way to not add MasterPTYs or SlavePTYs!
  42. if (device.is_master_pty() || (device.is_character_device() && device.major() == 201))
  43. return;
  44. notify_new_device(device);
  45. });
  46. }
  47. void DevFS::notify_new_device(Device& device)
  48. {
  49. LOCKER(m_lock);
  50. auto new_device_inode = adopt(*new DevFSDeviceInode(*this, device));
  51. m_nodes.append(new_device_inode);
  52. m_root_inode->m_devices.append(new_device_inode);
  53. }
  54. size_t DevFS::allocate_inode_index()
  55. {
  56. LOCKER(m_lock);
  57. m_next_inode_index = m_next_inode_index.value() + 1;
  58. VERIFY(m_next_inode_index > 0);
  59. return 1 + m_next_inode_index.value();
  60. }
  61. void DevFS::notify_device_removal(Device&)
  62. {
  63. TODO();
  64. }
  65. DevFS::~DevFS()
  66. {
  67. }
  68. bool DevFS::initialize()
  69. {
  70. return true;
  71. }
  72. NonnullRefPtr<Inode> DevFS::root_inode() const
  73. {
  74. return *m_root_inode;
  75. }
  76. RefPtr<Inode> DevFS::get_inode(InodeIdentifier inode_id) const
  77. {
  78. LOCKER(m_lock);
  79. if (inode_id.index() == 1)
  80. return m_root_inode;
  81. for (auto& node : m_nodes) {
  82. if (inode_id.index() == node.index())
  83. return node;
  84. }
  85. return nullptr;
  86. }
  87. DevFSInode::DevFSInode(DevFS& fs)
  88. : Inode(fs, fs.allocate_inode_index())
  89. {
  90. }
  91. ssize_t DevFSInode::read_bytes(off_t, ssize_t, UserOrKernelBuffer&, FileDescription*) const
  92. {
  93. VERIFY_NOT_REACHED();
  94. }
  95. KResult DevFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const
  96. {
  97. VERIFY_NOT_REACHED();
  98. }
  99. RefPtr<Inode> DevFSInode::lookup(StringView)
  100. {
  101. VERIFY_NOT_REACHED();
  102. }
  103. void DevFSInode::flush_metadata()
  104. {
  105. }
  106. ssize_t DevFSInode::write_bytes(off_t, ssize_t, const UserOrKernelBuffer&, FileDescription*)
  107. {
  108. VERIFY_NOT_REACHED();
  109. }
  110. KResultOr<NonnullRefPtr<Inode>> DevFSInode::create_child(const String&, mode_t, dev_t, uid_t, gid_t)
  111. {
  112. return EROFS;
  113. }
  114. KResult DevFSInode::add_child(Inode&, const StringView&, mode_t)
  115. {
  116. return EROFS;
  117. }
  118. KResult DevFSInode::remove_child(const StringView&)
  119. {
  120. return EROFS;
  121. }
  122. KResultOr<size_t> DevFSInode::directory_entry_count() const
  123. {
  124. VERIFY_NOT_REACHED();
  125. }
  126. KResult DevFSInode::chmod(mode_t)
  127. {
  128. return EPERM;
  129. }
  130. KResult DevFSInode::chown(uid_t, gid_t)
  131. {
  132. return EPERM;
  133. }
  134. KResult DevFSInode::truncate(u64)
  135. {
  136. return EPERM;
  137. }
  138. String DevFSLinkInode::name() const
  139. {
  140. return m_name;
  141. }
  142. DevFSLinkInode::~DevFSLinkInode()
  143. {
  144. }
  145. DevFSLinkInode::DevFSLinkInode(DevFS& fs, String name)
  146. : DevFSInode(fs)
  147. , m_name(name)
  148. {
  149. }
  150. ssize_t DevFSLinkInode::read_bytes(off_t offset, ssize_t, UserOrKernelBuffer& buffer, FileDescription*) const
  151. {
  152. LOCKER(m_lock);
  153. VERIFY(offset == 0);
  154. VERIFY(!m_link.is_null());
  155. if (!buffer.write(((const u8*)m_link.substring_view(0).characters_without_null_termination()) + offset, m_link.length()))
  156. return -EFAULT;
  157. return m_link.length();
  158. }
  159. InodeMetadata DevFSLinkInode::metadata() const
  160. {
  161. LOCKER(m_lock);
  162. InodeMetadata metadata;
  163. metadata.inode = { fsid(), index() };
  164. metadata.mode = S_IFLNK | 0555;
  165. metadata.uid = 0;
  166. metadata.gid = 0;
  167. metadata.size = 0;
  168. metadata.mtime = mepoch;
  169. return metadata;
  170. }
  171. ssize_t DevFSLinkInode::write_bytes(off_t offset, ssize_t count, const UserOrKernelBuffer& buffer, FileDescription*)
  172. {
  173. LOCKER(m_lock);
  174. VERIFY(offset == 0);
  175. VERIFY(buffer.is_kernel_buffer());
  176. m_link = buffer.copy_into_string(count);
  177. return count;
  178. }
  179. DevFSDirectoryInode::DevFSDirectoryInode(DevFS& fs)
  180. : DevFSInode(fs)
  181. {
  182. }
  183. DevFSDirectoryInode::~DevFSDirectoryInode()
  184. {
  185. }
  186. InodeMetadata DevFSDirectoryInode::metadata() const
  187. {
  188. LOCKER(m_lock);
  189. InodeMetadata metadata;
  190. metadata.inode = { fsid(), 1 };
  191. metadata.mode = 0040555;
  192. metadata.uid = 0;
  193. metadata.gid = 0;
  194. metadata.size = 0;
  195. metadata.mtime = mepoch;
  196. return metadata;
  197. }
  198. KResult DevFSDirectoryInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const
  199. {
  200. LOCKER(m_lock);
  201. return EINVAL;
  202. }
  203. RefPtr<Inode> DevFSDirectoryInode::lookup(StringView)
  204. {
  205. LOCKER(m_lock);
  206. return nullptr;
  207. }
  208. KResultOr<size_t> DevFSDirectoryInode::directory_entry_count() const
  209. {
  210. LOCKER(m_lock);
  211. return m_devices.size();
  212. }
  213. DevFSRootDirectoryInode::DevFSRootDirectoryInode(DevFS& fs)
  214. : DevFSDirectoryInode(fs)
  215. , m_parent_fs(fs)
  216. {
  217. }
  218. KResult DevFSRootDirectoryInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)> callback) const
  219. {
  220. LOCKER(m_parent_fs.m_lock);
  221. callback({ ".", identifier(), 0 });
  222. callback({ "..", identifier(), 0 });
  223. for (auto& folder : m_subfolders) {
  224. InodeIdentifier identifier = { fsid(), folder.index() };
  225. callback({ folder.name(), identifier, 0 });
  226. }
  227. for (auto& link : m_links) {
  228. InodeIdentifier identifier = { fsid(), link.index() };
  229. callback({ link.name(), identifier, 0 });
  230. }
  231. for (auto& device_node : m_devices) {
  232. InodeIdentifier identifier = { fsid(), device_node.index() };
  233. callback({ device_node.name(), identifier, 0 });
  234. }
  235. return KSuccess;
  236. }
  237. RefPtr<Inode> DevFSRootDirectoryInode::lookup(StringView name)
  238. {
  239. LOCKER(m_parent_fs.m_lock);
  240. for (auto& subfolder : m_subfolders) {
  241. if (subfolder.name() == name)
  242. return subfolder;
  243. }
  244. for (auto& link : m_links) {
  245. if (link.name() == name)
  246. return link;
  247. }
  248. for (auto& device_node : m_devices) {
  249. if (device_node.name() == name) {
  250. return device_node;
  251. }
  252. }
  253. return nullptr;
  254. }
  255. KResultOr<NonnullRefPtr<Inode>> DevFSRootDirectoryInode::create_child(const String& name, mode_t mode, dev_t, uid_t, gid_t)
  256. {
  257. LOCKER(m_parent_fs.m_lock);
  258. InodeMetadata metadata;
  259. metadata.mode = mode;
  260. if (metadata.is_directory()) {
  261. for (auto& folder : m_subfolders) {
  262. if (folder.name() == name)
  263. return EEXIST;
  264. }
  265. if (name != "pts")
  266. return EROFS;
  267. auto new_directory_inode = adopt(*new DevFSPtsDirectoryInode(m_parent_fs));
  268. m_subfolders.append(new_directory_inode);
  269. m_parent_fs.m_nodes.append(new_directory_inode);
  270. return KResult(KSuccess);
  271. }
  272. if (metadata.is_symlink()) {
  273. for (auto& link : m_links) {
  274. if (link.name() == name)
  275. return EEXIST;
  276. }
  277. auto new_link_inode = adopt(*new DevFSLinkInode(m_parent_fs, name));
  278. m_links.append(new_link_inode);
  279. m_parent_fs.m_nodes.append(new_link_inode);
  280. return new_link_inode;
  281. }
  282. return EROFS;
  283. }
  284. DevFSRootDirectoryInode::~DevFSRootDirectoryInode()
  285. {
  286. }
  287. InodeMetadata DevFSRootDirectoryInode::metadata() const
  288. {
  289. LOCKER(m_parent_fs.m_lock);
  290. InodeMetadata metadata;
  291. metadata.inode = { fsid(), 1 };
  292. metadata.mode = 0040555;
  293. metadata.uid = 0;
  294. metadata.gid = 0;
  295. metadata.size = 0;
  296. metadata.mtime = mepoch;
  297. return metadata;
  298. }
  299. KResultOr<size_t> DevFSRootDirectoryInode::directory_entry_count() const
  300. {
  301. LOCKER(m_parent_fs.m_lock);
  302. return m_devices.size() + DevFSDirectoryInode::directory_entry_count().value();
  303. }
  304. DevFSDeviceInode::DevFSDeviceInode(DevFS& fs, const Device& device)
  305. : DevFSInode(fs)
  306. , m_attached_device(device)
  307. {
  308. }
  309. DevFSDeviceInode::~DevFSDeviceInode()
  310. {
  311. }
  312. KResult DevFSDeviceInode::chown(uid_t uid, gid_t gid)
  313. {
  314. LOCKER(m_lock);
  315. m_uid = uid;
  316. m_gid = gid;
  317. return KSuccess;
  318. }
  319. String DevFSDeviceInode::name() const
  320. {
  321. LOCKER(m_lock);
  322. if (m_cached_name.is_null() || m_cached_name.is_empty())
  323. const_cast<DevFSDeviceInode&>(*this).m_cached_name = m_attached_device->device_name();
  324. return m_cached_name;
  325. }
  326. ssize_t DevFSDeviceInode::read_bytes(off_t offset, ssize_t count, UserOrKernelBuffer& buffer, FileDescription* description) const
  327. {
  328. LOCKER(m_lock);
  329. VERIFY(!!description);
  330. if (!m_attached_device->can_read(*description, offset))
  331. return -EIO;
  332. auto nread = const_cast<Device&>(*m_attached_device).read(*description, offset, buffer, count);
  333. if (nread.is_error())
  334. return -EIO;
  335. return nread.value();
  336. }
  337. InodeMetadata DevFSDeviceInode::metadata() const
  338. {
  339. LOCKER(m_lock);
  340. InodeMetadata metadata;
  341. metadata.inode = { fsid(), index() };
  342. metadata.mode = (m_attached_device->is_block_device() ? S_IFBLK : S_IFCHR) | m_attached_device->required_mode();
  343. metadata.uid = m_uid;
  344. metadata.gid = m_gid;
  345. metadata.size = 0;
  346. metadata.mtime = mepoch;
  347. metadata.major_device = m_attached_device->major();
  348. metadata.minor_device = m_attached_device->minor();
  349. return metadata;
  350. }
  351. ssize_t DevFSDeviceInode::write_bytes(off_t offset, ssize_t count, const UserOrKernelBuffer& buffer, FileDescription* description)
  352. {
  353. LOCKER(m_lock);
  354. VERIFY(!!description);
  355. if (!m_attached_device->can_write(*description, offset))
  356. return -EIO;
  357. auto nread = const_cast<Device&>(*m_attached_device).write(*description, offset, buffer, count);
  358. if (nread.is_error())
  359. return -EIO;
  360. return nread.value();
  361. }
  362. DevFSPtsDirectoryInode::DevFSPtsDirectoryInode(DevFS& fs)
  363. : DevFSDirectoryInode(fs)
  364. {
  365. }
  366. KResult DevFSPtsDirectoryInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)> callback) const
  367. {
  368. LOCKER(m_lock);
  369. callback({ ".", identifier(), 0 });
  370. callback({ "..", identifier(), 0 });
  371. return KSuccess;
  372. }
  373. RefPtr<Inode> DevFSPtsDirectoryInode::lookup(StringView)
  374. {
  375. return nullptr;
  376. }
  377. DevFSPtsDirectoryInode::~DevFSPtsDirectoryInode()
  378. {
  379. }
  380. InodeMetadata DevFSPtsDirectoryInode::metadata() const
  381. {
  382. LOCKER(m_lock);
  383. InodeMetadata metadata;
  384. metadata.inode = { fsid(), index() };
  385. metadata.mode = 0040555;
  386. metadata.uid = 0;
  387. metadata.gid = 0;
  388. metadata.size = 0;
  389. metadata.mtime = mepoch;
  390. return metadata;
  391. }
  392. KResultOr<size_t> DevFSPtsDirectoryInode::directory_entry_count() const
  393. {
  394. return 0;
  395. }
  396. }