SyntheticFileSystem.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #include "SyntheticFileSystem.h"
  2. #include "FileDescriptor.h"
  3. #include <LibC/errno_numbers.h>
  4. #include <AK/StdLibExtras.h>
  5. #ifndef SERENITY
  6. typedef int InterruptDisabler;
  7. #define ASSERT_INTERRUPTS_DISABLED()
  8. #endif
  9. //#define SYNTHFS_DEBUG
  10. RetainPtr<SynthFS> SynthFS::create()
  11. {
  12. return adopt(*new SynthFS);
  13. }
  14. SynthFS::SynthFS()
  15. {
  16. }
  17. SynthFS::~SynthFS()
  18. {
  19. }
  20. bool SynthFS::initialize()
  21. {
  22. // Add a File for the root directory.
  23. // FIXME: This needs work.
  24. auto root = adopt(*new SynthFSInode(*this, RootInodeIndex));
  25. root->m_parent = { id(), RootInodeIndex };
  26. root->m_metadata.mode = 0040555;
  27. root->m_metadata.uid = 0;
  28. root->m_metadata.gid = 0;
  29. root->m_metadata.size = 0;
  30. root->m_metadata.mtime = mepoch;
  31. m_inodes.set(RootInodeIndex, move(root));
  32. #ifndef SERENITY
  33. addFile(createTextFile("file", String("I'm a synthetic file!\n").toByteBuffer(), 0100644));
  34. addFile(createTextFile("message", String("Hey! This isn't my bottle!\n").toByteBuffer(), 0100644));
  35. addFile(createGeneratedFile("lunk", [] { return String("/home/andreas/file1").toByteBuffer(); }, 00120777));
  36. #endif
  37. return true;
  38. }
  39. RetainPtr<SynthFSInode> SynthFS::create_directory(String&& name)
  40. {
  41. auto file = adopt(*new SynthFSInode(*this, generate_inode_index()));
  42. file->m_name = move(name);
  43. file->m_metadata.size = 0;
  44. file->m_metadata.uid = 0;
  45. file->m_metadata.gid = 0;
  46. file->m_metadata.mode = 0040555;
  47. file->m_metadata.mtime = mepoch;
  48. return file;
  49. }
  50. RetainPtr<SynthFSInode> SynthFS::create_text_file(String&& name, ByteBuffer&& contents, Unix::mode_t mode)
  51. {
  52. auto file = adopt(*new SynthFSInode(*this, generate_inode_index()));
  53. file->m_data = contents;
  54. file->m_name = move(name);
  55. file->m_metadata.size = file->m_data.size();
  56. file->m_metadata.uid = 100;
  57. file->m_metadata.gid = 200;
  58. file->m_metadata.mode = mode;
  59. file->m_metadata.mtime = mepoch;
  60. return file;
  61. }
  62. RetainPtr<SynthFSInode> SynthFS::create_generated_file(String&& name, Function<ByteBuffer()>&& generator, Unix::mode_t mode)
  63. {
  64. auto file = adopt(*new SynthFSInode(*this, generate_inode_index()));
  65. file->m_generator = move(generator);
  66. file->m_name = move(name);
  67. file->m_metadata.size = 0;
  68. file->m_metadata.uid = 0;
  69. file->m_metadata.gid = 0;
  70. file->m_metadata.mode = mode;
  71. file->m_metadata.mtime = mepoch;
  72. return file;
  73. }
  74. InodeIdentifier SynthFS::add_file(RetainPtr<SynthFSInode>&& file, InodeIndex parent)
  75. {
  76. ASSERT_INTERRUPTS_DISABLED();
  77. ASSERT(file);
  78. auto it = m_inodes.find(parent);
  79. ASSERT(it != m_inodes.end());
  80. auto new_inode_id = file->identifier();
  81. file->m_metadata.inode = new_inode_id;
  82. file->m_parent = { id(), parent };
  83. (*it).value->m_children.append(file.ptr());
  84. m_inodes.set(new_inode_id.index(), move(file));
  85. return new_inode_id;
  86. }
  87. bool SynthFS::remove_file(InodeIndex inode)
  88. {
  89. ASSERT_INTERRUPTS_DISABLED();
  90. auto it = m_inodes.find(inode);
  91. if (it == m_inodes.end())
  92. return false;
  93. auto& file = *(*it).value;
  94. auto pit = m_inodes.find(file.m_parent.index());
  95. if (pit == m_inodes.end())
  96. return false;
  97. auto& parent = *(*pit).value;
  98. for (size_t i = 0; i < parent.m_children.size(); ++i) {
  99. if (parent.m_children[i]->m_metadata.inode.index() != inode) {
  100. continue;
  101. }
  102. parent.m_children.remove(i);
  103. break;
  104. }
  105. Vector<InodeIndex> indices_to_remove;
  106. indices_to_remove.ensureCapacity(file.m_children.size());
  107. for (auto& child : file.m_children)
  108. indices_to_remove.unchecked_append(child->m_metadata.inode.index());
  109. for (auto& index : indices_to_remove)
  110. remove_file(index);
  111. m_inodes.remove(inode);
  112. return true;
  113. }
  114. const char* SynthFS::class_name() const
  115. {
  116. return "synthfs";
  117. }
  118. InodeIdentifier SynthFS::root_inode() const
  119. {
  120. return { id(), 1 };
  121. }
  122. RetainPtr<Inode> SynthFS::create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t mode, unsigned size, int& error)
  123. {
  124. (void) parentInode;
  125. (void) name;
  126. (void) mode;
  127. (void) size;
  128. (void) error;
  129. kprintf("FIXME: Implement SyntheticFileSystem::create_inode().\n");
  130. return { };
  131. }
  132. RetainPtr<Inode> SynthFS::create_directory(InodeIdentifier, const String&, Unix::mode_t, int& error)
  133. {
  134. error = -EROFS;
  135. return nullptr;
  136. }
  137. auto SynthFS::generate_inode_index() -> InodeIndex
  138. {
  139. return m_next_inode_index++;
  140. }
  141. InodeIdentifier SynthFS::find_parent_of_inode(InodeIdentifier inode) const
  142. {
  143. auto it = m_inodes.find(inode.index());
  144. if (it == m_inodes.end())
  145. return { };
  146. return (*it).value->m_parent;
  147. }
  148. RetainPtr<Inode> SynthFS::get_inode(InodeIdentifier inode) const
  149. {
  150. auto it = m_inodes.find(inode.index());
  151. if (it == m_inodes.end())
  152. return { };
  153. return (*it).value;
  154. }
  155. SynthFSInode::SynthFSInode(SynthFS& fs, unsigned index)
  156. : Inode(fs, index)
  157. {
  158. m_metadata.inode = { fs.id(), index };
  159. }
  160. SynthFSInode::~SynthFSInode()
  161. {
  162. }
  163. void SynthFSInode::populate_metadata() const
  164. {
  165. // Already done when SynthFS created the file.
  166. }
  167. ssize_t SynthFSInode::read_bytes(Unix::off_t offset, size_t count, byte* buffer, FileDescriptor* descriptor)
  168. {
  169. #ifdef SYNTHFS_DEBUG
  170. kprintf("SynthFS: read_bytes %u\n", index());
  171. #endif
  172. ASSERT(offset >= 0);
  173. ASSERT(buffer);
  174. ByteBuffer generatedData;
  175. if (m_generator) {
  176. if (!descriptor) {
  177. generatedData = m_generator();
  178. } else {
  179. if (!descriptor->generator_cache())
  180. descriptor->generator_cache() = m_generator();
  181. generatedData = descriptor->generator_cache();
  182. }
  183. }
  184. auto* data = generatedData ? &generatedData : &m_data;
  185. ssize_t nread = min(static_cast<Unix::off_t>(data->size() - offset), static_cast<Unix::off_t>(count));
  186. memcpy(buffer, data->pointer() + offset, nread);
  187. if (nread == 0 && descriptor && descriptor->generator_cache())
  188. descriptor->generator_cache().clear();
  189. return nread;
  190. }
  191. bool SynthFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback)
  192. {
  193. InterruptDisabler disabler;
  194. #ifdef SYNTHFS_DEBUG
  195. kprintf("SynthFS: traverse_as_directory %u\n", index());
  196. #endif
  197. if (!m_metadata.isDirectory())
  198. return false;
  199. callback({ ".", 1, m_metadata.inode, 2 });
  200. callback({ "..", 2, m_parent, 2 });
  201. for (auto& child : m_children)
  202. callback({ child->m_name.characters(), child->m_name.length(), child->m_metadata.inode, child->m_metadata.isDirectory() ? (byte)2 : (byte)1 });
  203. return true;
  204. }
  205. InodeIdentifier SynthFSInode::lookup(const String& name)
  206. {
  207. ASSERT(is_directory());
  208. if (name == ".")
  209. return identifier();
  210. if (name == "..")
  211. return m_parent;
  212. for (auto& child : m_children) {
  213. if (child->m_name == name)
  214. return child->identifier();
  215. }
  216. return { };
  217. }
  218. String SynthFSInode::reverse_lookup(InodeIdentifier child_id)
  219. {
  220. ASSERT(is_directory());
  221. for (auto& child : m_children) {
  222. if (child->identifier() == child_id)
  223. return child->m_name;
  224. }
  225. return { };
  226. }
  227. void SynthFSInode::flush_metadata()
  228. {
  229. }
  230. bool SynthFSInode::write(const ByteBuffer&)
  231. {
  232. ASSERT_NOT_REACHED();
  233. return false;
  234. }
  235. bool SynthFSInode::add_child(InodeIdentifier child_id, const String& name, byte file_type, int& error)
  236. {
  237. (void) child_id;
  238. (void) name;
  239. (void) file_type;
  240. (void) error;
  241. ASSERT_NOT_REACHED();
  242. return false;
  243. }