FileSystem.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #include <AK/Assertions.h>
  2. #include <AK/HashMap.h>
  3. #include <LibC/errno_numbers.h>
  4. #include "FileSystem.h"
  5. static dword s_lastFileSystemID;
  6. static HashMap<dword, FS*>* s_fs_map;
  7. static HashTable<Inode*>* s_inode_set;
  8. static HashMap<dword, FS*>& all_fses()
  9. {
  10. if (!s_fs_map)
  11. s_fs_map = new HashMap<dword, FS*>();
  12. return *s_fs_map;
  13. }
  14. static HashTable<Inode*>& all_inodes()
  15. {
  16. if (!s_inode_set)
  17. s_inode_set = new HashTable<Inode*>();
  18. return *s_inode_set;
  19. }
  20. void FS::initialize_globals()
  21. {
  22. s_lastFileSystemID = 0;
  23. s_fs_map = nullptr;
  24. s_inode_set = nullptr;
  25. }
  26. FS::FS()
  27. : m_fsid(++s_lastFileSystemID)
  28. {
  29. all_fses().set(m_fsid, this);
  30. }
  31. FS::~FS()
  32. {
  33. all_fses().remove(m_fsid);
  34. }
  35. FS* FS::from_fsid(dword id)
  36. {
  37. auto it = all_fses().find(id);
  38. if (it != all_fses().end())
  39. return (*it).value;
  40. return nullptr;
  41. }
  42. ByteBuffer Inode::read_entire(FileDescriptor* descriptor)
  43. {
  44. return fs().read_entire_inode(identifier(), descriptor);
  45. /*
  46. size_t initial_size = metadata().size ? metadata().size : 4096;
  47. auto contents = ByteBuffer::create_uninitialized(initial_size);
  48. ssize_t nread;
  49. byte buffer[4096];
  50. byte* out = contents.pointer();
  51. Unix::off_t offset = 0;
  52. for (;;) {
  53. nread = read_bytes(offset, sizeof(buffer), buffer, descriptor);
  54. //kprintf("nread: %u, bufsiz: %u, initial_size: %u\n", nread, sizeof(buffer), initial_size);
  55. ASSERT(nread <= (ssize_t)sizeof(buffer));
  56. if (nread <= 0)
  57. break;
  58. memcpy(out, buffer, nread);
  59. out += nread;
  60. offset += nread;
  61. ASSERT(offset <= (ssize_t)initial_size); // FIXME: Support dynamically growing the buffer.
  62. }
  63. if (nread < 0) {
  64. kprintf("Inode::read_entire: ERROR: %d\n", nread);
  65. return nullptr;
  66. }
  67. contents.trim(offset);
  68. return contents;
  69. */
  70. }
  71. ByteBuffer FS::read_entire_inode(InodeIdentifier inode, FileDescriptor* handle) const
  72. {
  73. ASSERT(inode.fsid() == id());
  74. auto metadata = inode_metadata(inode);
  75. if (!metadata.isValid()) {
  76. kprintf("[fs] readInode: metadata lookup for inode %u failed\n", inode.index());
  77. return nullptr;
  78. }
  79. size_t initialSize = metadata.size ? metadata.size : 4096;
  80. auto contents = ByteBuffer::create_uninitialized(initialSize);
  81. ssize_t nread;
  82. byte buffer[4096];
  83. byte* out = contents.pointer();
  84. Unix::off_t offset = 0;
  85. for (;;) {
  86. nread = read_inode_bytes(inode, offset, sizeof(buffer), buffer, handle);
  87. //kprintf("nread: %u, bufsiz: %u, initialSize: %u\n", nread, sizeof(buffer), initialSize);
  88. ASSERT(nread <= (ssize_t)sizeof(buffer));
  89. if (nread <= 0)
  90. break;
  91. memcpy(out, buffer, nread);
  92. out += nread;
  93. offset += nread;
  94. ASSERT(offset <= (ssize_t)initialSize); // FIXME: Support dynamically growing the buffer.
  95. }
  96. if (nread < 0) {
  97. kprintf("[fs] readInode: ERROR: %d\n", nread);
  98. return nullptr;
  99. }
  100. contents.trim(offset);
  101. return contents;
  102. }
  103. FS::DirectoryEntry::DirectoryEntry(const char* n, InodeIdentifier i, byte ft)
  104. : name_length(strlen(n))
  105. , inode(i)
  106. , fileType(ft)
  107. {
  108. memcpy(name, n, name_length);
  109. name[name_length] = '\0';
  110. }
  111. FS::DirectoryEntry::DirectoryEntry(const char* n, size_t nl, InodeIdentifier i, byte ft)
  112. : name_length(nl)
  113. , inode(i)
  114. , fileType(ft)
  115. {
  116. memcpy(name, n, nl);
  117. name[nl] = '\0';
  118. }
  119. Inode::Inode(FS& fs, unsigned index)
  120. : m_fs(fs)
  121. , m_index(index)
  122. {
  123. all_inodes().set(this);
  124. }
  125. Inode::~Inode()
  126. {
  127. all_inodes().remove(this);
  128. }
  129. void Inode::will_be_destroyed()
  130. {
  131. if (m_metadata_dirty)
  132. flush_metadata();
  133. }
  134. int Inode::set_atime(Unix::time_t ts)
  135. {
  136. if (fs().is_readonly())
  137. return -EROFS;
  138. if (m_metadata.atime == ts)
  139. return 0;
  140. m_metadata.atime = ts;
  141. m_metadata_dirty = true;
  142. return 0;
  143. }
  144. int Inode::set_ctime(Unix::time_t ts)
  145. {
  146. if (fs().is_readonly())
  147. return -EROFS;
  148. if (m_metadata.ctime == ts)
  149. return 0;
  150. m_metadata.ctime = ts;
  151. m_metadata_dirty = true;
  152. return 0;
  153. }
  154. int Inode::set_mtime(Unix::time_t ts)
  155. {
  156. if (fs().is_readonly())
  157. return -EROFS;
  158. if (m_metadata.mtime == ts)
  159. return 0;
  160. m_metadata.mtime = ts;
  161. m_metadata_dirty = true;
  162. return 0;
  163. }
  164. void FS::sync()
  165. {
  166. for (auto* inode : all_inodes()) {
  167. if (inode->is_metadata_dirty())
  168. inode->flush_metadata();
  169. }
  170. }