Inode.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /*
  2. * Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/FileSystem/Plan9FS/Inode.h>
  7. #include <Kernel/Process.h>
  8. namespace Kernel {
  9. Plan9FSInode::Plan9FSInode(Plan9FS& fs, u32 fid)
  10. : Inode(fs, fid)
  11. {
  12. }
  13. ErrorOr<NonnullLockRefPtr<Plan9FSInode>> Plan9FSInode::try_create(Plan9FS& fs, u32 fid)
  14. {
  15. return adopt_nonnull_lock_ref_or_enomem(new (nothrow) Plan9FSInode(fs, fid));
  16. }
  17. Plan9FSInode::~Plan9FSInode()
  18. {
  19. Plan9FSMessage clunk_request { fs(), Plan9FSMessage::Type::Tclunk };
  20. clunk_request << fid();
  21. // FIXME: Should we observe this error somehow?
  22. [[maybe_unused]] auto rc = fs().post_message_and_explicitly_ignore_reply(clunk_request);
  23. }
  24. ErrorOr<void> Plan9FSInode::ensure_open_for_mode(int mode)
  25. {
  26. bool use_lopen = fs().m_remote_protocol_version >= Plan9FS::ProtocolVersion::v9P2000L;
  27. u32 l_mode = 0;
  28. u8 p9_mode = 0;
  29. {
  30. MutexLocker locker(m_inode_lock);
  31. // If it's already open in this mode, we're done.
  32. if ((m_open_mode & mode) == mode)
  33. return {};
  34. m_open_mode |= mode;
  35. if ((m_open_mode & O_RDWR) == O_RDWR) {
  36. l_mode |= 2;
  37. p9_mode |= 2;
  38. } else if (m_open_mode & O_WRONLY) {
  39. l_mode |= 1;
  40. p9_mode |= 1;
  41. } else if (m_open_mode & O_RDONLY) {
  42. // Leave the values at 0.
  43. }
  44. }
  45. if (use_lopen) {
  46. Plan9FSMessage message { fs(), Plan9FSMessage::Type::Tlopen };
  47. message << fid() << l_mode;
  48. return fs().post_message_and_wait_for_a_reply(message);
  49. }
  50. Plan9FSMessage message { fs(), Plan9FSMessage::Type::Topen };
  51. message << fid() << p9_mode;
  52. return fs().post_message_and_wait_for_a_reply(message);
  53. }
  54. ErrorOr<size_t> Plan9FSInode::read_bytes_locked(off_t offset, size_t size, UserOrKernelBuffer& buffer, OpenFileDescription*) const
  55. {
  56. TRY(const_cast<Plan9FSInode&>(*this).ensure_open_for_mode(O_RDONLY));
  57. size = fs().adjust_buffer_size(size);
  58. Plan9FSMessage message { fs(), Plan9FSMessage::Type::Treadlink };
  59. StringView data;
  60. // Try readlink first.
  61. bool readlink_succeeded = false;
  62. if (fs().m_remote_protocol_version >= Plan9FS::ProtocolVersion::v9P2000L && offset == 0) {
  63. message << fid();
  64. if (auto result = fs().post_message_and_wait_for_a_reply(message); !result.is_error()) {
  65. readlink_succeeded = true;
  66. message >> data;
  67. }
  68. }
  69. if (!readlink_succeeded) {
  70. message = Plan9FSMessage { fs(), Plan9FSMessage::Type::Tread };
  71. message << fid() << (u64)offset << (u32)size;
  72. TRY(fs().post_message_and_wait_for_a_reply(message));
  73. data = message.read_data();
  74. }
  75. // Guard against the server returning more data than requested.
  76. size_t nread = min(data.length(), size);
  77. TRY(buffer.write(data.characters_without_null_termination(), nread));
  78. return nread;
  79. }
  80. ErrorOr<void> Plan9FSInode::replace_child(StringView, Inode&)
  81. {
  82. // TODO
  83. return ENOTIMPL;
  84. }
  85. ErrorOr<size_t> Plan9FSInode::write_bytes_locked(off_t offset, size_t size, UserOrKernelBuffer const& data, OpenFileDescription*)
  86. {
  87. TRY(ensure_open_for_mode(O_WRONLY));
  88. size = fs().adjust_buffer_size(size);
  89. auto data_copy = TRY(data.try_copy_into_kstring(size)); // FIXME: this seems ugly
  90. Plan9FSMessage message { fs(), Plan9FSMessage::Type::Twrite };
  91. message << fid() << (u64)offset;
  92. message.append_data(data_copy->view());
  93. TRY(fs().post_message_and_wait_for_a_reply(message));
  94. u32 nwritten;
  95. message >> nwritten;
  96. return nwritten;
  97. }
  98. InodeMetadata Plan9FSInode::metadata() const
  99. {
  100. InodeMetadata metadata;
  101. metadata.inode = identifier();
  102. // 9P2000.L; TODO: 9P2000 & 9P2000.u
  103. Plan9FSMessage message { fs(), Plan9FSMessage::Type::Tgetattr };
  104. message << fid() << (u64)GetAttrMask::Basic;
  105. auto result = fs().post_message_and_wait_for_a_reply(message);
  106. if (result.is_error()) {
  107. // Just return blank metadata; hopefully that's enough to result in an
  108. // error at some upper layer. Ideally, there would be a way for
  109. // Inode::metadata() to return failure.
  110. return metadata;
  111. }
  112. u64 valid;
  113. Plan9FSQIdentifier qid;
  114. u32 mode;
  115. u32 uid;
  116. u32 gid;
  117. u64 nlink;
  118. u64 rdev;
  119. u64 size;
  120. u64 blksize;
  121. u64 blocks;
  122. message >> valid >> qid >> mode >> uid >> gid >> nlink >> rdev >> size >> blksize >> blocks;
  123. // TODO: times...
  124. if (valid & (u64)GetAttrMask::Mode)
  125. metadata.mode = mode;
  126. if (valid & (u64)GetAttrMask::NLink)
  127. metadata.link_count = nlink;
  128. #if 0
  129. // FIXME: Map UID/GID somehow? Or what do we do?
  130. if (valid & (u64)GetAttrMask::UID)
  131. metadata.uid = uid;
  132. if (valid & (u64)GetAttrMask::GID)
  133. metadata.uid = gid;
  134. // FIXME: What about device nodes?
  135. if (valid & (u64)GetAttrMask::RDev)
  136. metadata.encoded_device = 0; // TODO
  137. #endif
  138. if (valid & (u64)GetAttrMask::Size)
  139. metadata.size = size;
  140. if (valid & (u64)GetAttrMask::Blocks) {
  141. metadata.block_size = blksize;
  142. metadata.block_count = blocks;
  143. }
  144. return metadata;
  145. }
  146. ErrorOr<void> Plan9FSInode::flush_metadata()
  147. {
  148. // Do nothing.
  149. return {};
  150. }
  151. ErrorOr<void> Plan9FSInode::traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
  152. {
  153. // TODO: Should we synthesize "." and ".." here?
  154. if (fs().m_remote_protocol_version >= Plan9FS::ProtocolVersion::v9P2000L) {
  155. // Start by cloning the fid and opening it.
  156. auto clone_fid = fs().allocate_fid();
  157. {
  158. Plan9FSMessage clone_message { fs(), Plan9FSMessage::Type::Twalk };
  159. clone_message << fid() << clone_fid << (u16)0;
  160. TRY(fs().post_message_and_wait_for_a_reply(clone_message));
  161. Plan9FSMessage open_message { fs(), Plan9FSMessage::Type::Tlopen };
  162. open_message << clone_fid << (u32)0;
  163. auto result = fs().post_message_and_wait_for_a_reply(open_message);
  164. if (result.is_error()) {
  165. Plan9FSMessage close_message { fs(), Plan9FSMessage::Type::Tclunk };
  166. close_message << clone_fid;
  167. // FIXME: Should we observe this error?
  168. [[maybe_unused]] auto rc = fs().post_message_and_explicitly_ignore_reply(close_message);
  169. return result;
  170. }
  171. }
  172. u64 offset = 0;
  173. u32 count = fs().adjust_buffer_size(8 * MiB);
  174. ErrorOr<void> result;
  175. while (true) {
  176. Plan9FSMessage message { fs(), Plan9FSMessage::Type::Treaddir };
  177. message << clone_fid << offset << count;
  178. result = fs().post_message_and_wait_for_a_reply(message);
  179. if (result.is_error())
  180. break;
  181. StringView data = message.read_data();
  182. if (data.is_empty()) {
  183. // We've reached the end.
  184. break;
  185. }
  186. for (Plan9FSMessage::Decoder decoder { data }; decoder.has_more_data();) {
  187. Plan9FSQIdentifier qid;
  188. u8 type;
  189. StringView name;
  190. decoder >> qid >> offset >> type >> name;
  191. result = callback({ name, { fsid(), fs().allocate_fid() }, 0 });
  192. if (result.is_error())
  193. break;
  194. }
  195. if (result.is_error())
  196. break;
  197. }
  198. Plan9FSMessage close_message { fs(), Plan9FSMessage::Type::Tclunk };
  199. close_message << clone_fid;
  200. // FIXME: Should we observe this error?
  201. [[maybe_unused]] auto rc = fs().post_message_and_explicitly_ignore_reply(close_message);
  202. return result;
  203. }
  204. // TODO
  205. return ENOTIMPL;
  206. }
  207. ErrorOr<NonnullLockRefPtr<Inode>> Plan9FSInode::lookup(StringView name)
  208. {
  209. u32 newfid = fs().allocate_fid();
  210. Plan9FSMessage message { fs(), Plan9FSMessage::Type::Twalk };
  211. message << fid() << newfid << (u16)1 << name;
  212. TRY(fs().post_message_and_wait_for_a_reply(message));
  213. return TRY(Plan9FSInode::try_create(fs(), newfid));
  214. }
  215. ErrorOr<NonnullLockRefPtr<Inode>> Plan9FSInode::create_child(StringView, mode_t, dev_t, UserID, GroupID)
  216. {
  217. // TODO
  218. return ENOTIMPL;
  219. }
  220. ErrorOr<void> Plan9FSInode::add_child(Inode&, StringView, mode_t)
  221. {
  222. // TODO
  223. return ENOTIMPL;
  224. }
  225. ErrorOr<void> Plan9FSInode::remove_child(StringView)
  226. {
  227. // TODO
  228. return ENOTIMPL;
  229. }
  230. ErrorOr<void> Plan9FSInode::chmod(mode_t)
  231. {
  232. // TODO
  233. return ENOTIMPL;
  234. }
  235. ErrorOr<void> Plan9FSInode::chown(UserID, GroupID)
  236. {
  237. // TODO
  238. return ENOTIMPL;
  239. }
  240. ErrorOr<void> Plan9FSInode::truncate(u64 new_size)
  241. {
  242. if (fs().m_remote_protocol_version >= Plan9FS::ProtocolVersion::v9P2000L) {
  243. Plan9FSMessage message { fs(), Plan9FSMessage::Type::Tsetattr };
  244. SetAttrMask valid = SetAttrMask::Size;
  245. u32 mode = 0;
  246. u32 uid = 0;
  247. u32 gid = 0;
  248. u64 atime_sec = 0;
  249. u64 atime_nsec = 0;
  250. u64 mtime_sec = 0;
  251. u64 mtime_nsec = 0;
  252. message << fid() << (u64)valid << mode << uid << gid << new_size << atime_sec << atime_nsec << mtime_sec << mtime_nsec;
  253. return fs().post_message_and_wait_for_a_reply(message);
  254. }
  255. // TODO: wstat version
  256. return {};
  257. }
  258. }