FATFileSystem.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /*
  2. * Copyright (c) 2022, Undefine <undefine@undefine.pl>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Time.h>
  7. #include <Kernel/Debug.h>
  8. #include <Kernel/Devices/BlockDevice.h>
  9. #include <Kernel/FileSystem/FATFileSystem.h>
  10. #include <Kernel/Memory/Region.h>
  11. namespace Kernel {
  12. ErrorOr<NonnullLockRefPtr<FileSystem>> FATFS::try_create(OpenFileDescription& file_description)
  13. {
  14. return TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) FATFS(file_description)));
  15. }
  16. FATFS::FATFS(OpenFileDescription& file_description)
  17. : BlockBasedFileSystem(file_description)
  18. {
  19. }
  20. bool FATFS::is_initialized_while_locked()
  21. {
  22. VERIFY(m_lock.is_locked());
  23. return !m_root_inode.is_null();
  24. }
  25. ErrorOr<void> FATFS::initialize_while_locked()
  26. {
  27. VERIFY(m_lock.is_locked());
  28. VERIFY(!is_initialized_while_locked());
  29. m_boot_record = TRY(KBuffer::try_create_with_size("FATFS: Boot Record"sv, m_logical_block_size));
  30. auto boot_record_buffer = UserOrKernelBuffer::for_kernel_buffer(m_boot_record->data());
  31. TRY(raw_read(0, boot_record_buffer));
  32. if constexpr (FAT_DEBUG) {
  33. dbgln("FATFS: oem_identifier: {}", boot_record()->oem_identifier);
  34. dbgln("FATFS: bytes_per_sector: {}", boot_record()->bytes_per_sector);
  35. dbgln("FATFS: sectors_per_cluster: {}", boot_record()->sectors_per_cluster);
  36. dbgln("FATFS: reserved_sector_count: {}", boot_record()->reserved_sector_count);
  37. dbgln("FATFS: fat_count: {}", boot_record()->fat_count);
  38. dbgln("FATFS: root_directory_entry_count: {}", boot_record()->root_directory_entry_count);
  39. dbgln("FATFS: media_descriptor_type: {}", boot_record()->media_descriptor_type);
  40. dbgln("FATFS: sectors_per_track: {}", boot_record()->sectors_per_track);
  41. dbgln("FATFS: head_count: {}", boot_record()->head_count);
  42. dbgln("FATFS: hidden_sector_count: {}", boot_record()->hidden_sector_count);
  43. dbgln("FATFS: sector_count: {}", boot_record()->sector_count);
  44. dbgln("FATFS: sectors_per_fat: {}", boot_record()->sectors_per_fat);
  45. dbgln("FATFS: flags: {}", boot_record()->flags);
  46. dbgln("FATFS: fat_version: {}", boot_record()->fat_version);
  47. dbgln("FATFS: root_directory_cluster: {}", boot_record()->root_directory_cluster);
  48. dbgln("FATFS: fs_info_sector: {}", boot_record()->fs_info_sector);
  49. dbgln("FATFS: backup_boot_sector: {}", boot_record()->backup_boot_sector);
  50. dbgln("FATFS: drive_number: {}", boot_record()->drive_number);
  51. dbgln("FATFS: volume_id: {}", boot_record()->volume_id);
  52. }
  53. if (boot_record()->signature != signature_1 && boot_record()->signature != signature_2) {
  54. dbgln("FATFS: Invalid signature");
  55. return EINVAL;
  56. }
  57. m_logical_block_size = boot_record()->bytes_per_sector;
  58. set_block_size(m_logical_block_size);
  59. u32 root_directory_sectors = ((boot_record()->root_directory_entry_count * sizeof(FATEntry)) + (m_logical_block_size - 1)) / m_logical_block_size;
  60. m_first_data_sector = boot_record()->reserved_sector_count + (boot_record()->fat_count * boot_record()->sectors_per_fat) + root_directory_sectors;
  61. TRY(BlockBasedFileSystem::initialize_while_locked());
  62. FATEntry root_entry {};
  63. root_entry.first_cluster_low = boot_record()->root_directory_cluster & 0xFFFF;
  64. root_entry.first_cluster_high = boot_record()->root_directory_cluster >> 16;
  65. root_entry.attributes = FATAttributes::Directory;
  66. m_root_inode = TRY(FATInode::create(*this, root_entry));
  67. return {};
  68. }
  69. Inode& FATFS::root_inode()
  70. {
  71. return *m_root_inode;
  72. }
  73. BlockBasedFileSystem::BlockIndex FATFS::first_block_of_cluster(u32 cluster) const
  74. {
  75. return ((cluster - first_data_cluster) * boot_record()->sectors_per_cluster) + m_first_data_sector;
  76. }
  77. ErrorOr<NonnullLockRefPtr<FATInode>> FATInode::create(FATFS& fs, FATEntry entry, Vector<FATLongFileNameEntry> const& lfn_entries)
  78. {
  79. auto filename = TRY(compute_filename(entry, lfn_entries));
  80. return adopt_nonnull_lock_ref_or_enomem(new (nothrow) FATInode(fs, entry, move(filename)));
  81. }
  82. FATInode::FATInode(FATFS& fs, FATEntry entry, NonnullOwnPtr<KString> filename)
  83. : Inode(fs, first_cluster())
  84. , m_entry(entry)
  85. , m_filename(move(filename))
  86. {
  87. dbgln_if(FAT_DEBUG, "FATFS: Creating inode {} with filename \"{}\"", index(), m_filename);
  88. m_metadata = {
  89. .inode = identifier(),
  90. .size = m_entry.file_size,
  91. .mode = static_cast<mode_t>((has_flag(m_entry.attributes, FATAttributes::Directory) ? S_IFDIR : S_IFREG) | 0777),
  92. .uid = 0,
  93. .gid = 0,
  94. .link_count = 0,
  95. .atime = fat_date_time(m_entry.last_accessed_date, { 0 }),
  96. .ctime = fat_date_time(m_entry.creation_date, m_entry.creation_time),
  97. .mtime = fat_date_time(m_entry.modification_date, m_entry.modification_time),
  98. .dtime = 0,
  99. .block_count = 0,
  100. .block_size = 0,
  101. .major_device = 0,
  102. .minor_device = 0,
  103. };
  104. }
  105. ErrorOr<Vector<BlockBasedFileSystem::BlockIndex>> FATInode::compute_block_list()
  106. {
  107. VERIFY(m_inode_lock.is_locked());
  108. dbgln_if(FAT_DEBUG, "FATFS: computing block list for inode {}", index());
  109. u32 cluster = first_cluster();
  110. Vector<BlockBasedFileSystem::BlockIndex> block_list;
  111. auto fat_sector = TRY(KBuffer::try_create_with_size("FATFS: FAT read buffer"sv, fs().m_logical_block_size));
  112. auto fat_sector_buffer = UserOrKernelBuffer::for_kernel_buffer(fat_sector->data());
  113. while (cluster < no_more_clusters) {
  114. dbgln_if(FAT_DEBUG, "FATFS: Appending cluster {} to inode {}'s cluster chain", cluster, index());
  115. BlockBasedFileSystem::BlockIndex first_block = fs().first_block_of_cluster(cluster);
  116. for (u8 i = 0; i < fs().boot_record()->sectors_per_cluster; i++)
  117. block_list.append(BlockBasedFileSystem::BlockIndex { first_block.value() + i });
  118. u32 fat_offset = cluster * sizeof(u32);
  119. u32 fat_sector_index = fs().boot_record()->reserved_sector_count + (fat_offset / fs().m_logical_block_size);
  120. u32 entry_offset = fat_offset % fs().m_logical_block_size;
  121. TRY(fs().raw_read(fat_sector_index, fat_sector_buffer));
  122. cluster = *reinterpret_cast<u32*>(&fat_sector->data()[entry_offset]);
  123. cluster &= cluster_number_mask;
  124. }
  125. return block_list;
  126. }
  127. ErrorOr<NonnullOwnPtr<KBuffer>> FATInode::read_block_list()
  128. {
  129. VERIFY(m_inode_lock.is_locked());
  130. dbgln_if(FAT_DEBUG, "FATFS: reading block list for inode {} ({} blocks)", index(), m_block_list.size());
  131. if (m_block_list.is_empty())
  132. m_block_list = TRY(compute_block_list());
  133. auto builder = TRY(KBufferBuilder::try_create());
  134. u8 buffer[512];
  135. VERIFY(fs().m_logical_block_size <= sizeof(buffer));
  136. auto buf = UserOrKernelBuffer::for_kernel_buffer(buffer);
  137. for (BlockBasedFileSystem::BlockIndex block : m_block_list) {
  138. dbgln_if(FAT_DEBUG, "FATFS: reading block: {}", block);
  139. TRY(fs().raw_read(block, buf));
  140. TRY(builder.append((char const*)buffer, fs().m_logical_block_size));
  141. }
  142. auto blocks = builder.build();
  143. if (!blocks)
  144. return ENOMEM;
  145. return blocks.release_nonnull();
  146. }
  147. ErrorOr<LockRefPtr<FATInode>> FATInode::traverse(Function<ErrorOr<bool>(LockRefPtr<FATInode>)> callback)
  148. {
  149. VERIFY(has_flag(m_entry.attributes, FATAttributes::Directory));
  150. Vector<FATLongFileNameEntry> lfn_entries;
  151. auto blocks = TRY(read_block_list());
  152. for (u32 i = 0; i < blocks->size() / sizeof(FATEntry); i++) {
  153. auto* entry = reinterpret_cast<FATEntry*>(blocks->data() + i * sizeof(FATEntry));
  154. if (entry->filename[0] == end_entry_byte) {
  155. dbgln_if(FAT_DEBUG, "FATFS: Found end entry");
  156. return nullptr;
  157. } else if (static_cast<u8>(entry->filename[0]) == unused_entry_byte) {
  158. dbgln_if(FAT_DEBUG, "FATFS: Found unused entry");
  159. lfn_entries.clear();
  160. } else if (entry->attributes == FATAttributes::LongFileName) {
  161. dbgln_if(FAT_DEBUG, "FATFS: Found LFN entry");
  162. TRY(lfn_entries.try_append(*reinterpret_cast<FATLongFileNameEntry*>(entry)));
  163. } else {
  164. dbgln_if(FAT_DEBUG, "FATFS: Found 8.3 entry");
  165. lfn_entries.reverse();
  166. auto inode = TRY(FATInode::create(fs(), *entry, lfn_entries));
  167. if (TRY(callback(inode)))
  168. return inode;
  169. lfn_entries.clear();
  170. }
  171. }
  172. return EINVAL;
  173. }
  174. ErrorOr<NonnullOwnPtr<KString>> FATInode::compute_filename(FATEntry& entry, Vector<FATLongFileNameEntry> const& lfn_entries)
  175. {
  176. if (lfn_entries.is_empty()) {
  177. StringBuilder filename;
  178. filename.append(byte_terminated_string(StringView(entry.filename, normal_filename_length), ' '));
  179. if (entry.extension[0] != ' ') {
  180. filename.append('.');
  181. filename.append(byte_terminated_string(StringView(entry.extension, normal_extension_length), ' '));
  182. }
  183. return TRY(KString::try_create(filename.string_view()));
  184. } else {
  185. StringBuilder filename;
  186. for (auto& lfn_entry : lfn_entries) {
  187. filename.append(lfn_entry.characters1[0]);
  188. filename.append(lfn_entry.characters1[1]);
  189. filename.append(lfn_entry.characters1[2]);
  190. filename.append(lfn_entry.characters1[3]);
  191. filename.append(lfn_entry.characters1[4]);
  192. filename.append(lfn_entry.characters2[0]);
  193. filename.append(lfn_entry.characters2[1]);
  194. filename.append(lfn_entry.characters2[2]);
  195. filename.append(lfn_entry.characters2[3]);
  196. filename.append(lfn_entry.characters2[4]);
  197. filename.append(lfn_entry.characters2[5]);
  198. filename.append(lfn_entry.characters3[0]);
  199. filename.append(lfn_entry.characters3[1]);
  200. }
  201. return TRY(KString::try_create(byte_terminated_string(filename.string_view(), lfn_entry_text_termination)));
  202. }
  203. VERIFY_NOT_REACHED();
  204. }
  205. time_t FATInode::fat_date_time(FATPackedDate date, FATPackedTime time)
  206. {
  207. if (date.value == 0)
  208. return 0;
  209. return Time::from_timestamp(first_fat_year + date.year, date.month, date.day, time.hour, time.minute, time.second * 2, 0).to_seconds();
  210. }
  211. StringView FATInode::byte_terminated_string(StringView string, u8 fill_byte)
  212. {
  213. if (auto index = string.find_last_not(fill_byte); index.has_value())
  214. return string.substring_view(0, index.value());
  215. return string;
  216. }
  217. u32 FATInode::first_cluster() const
  218. {
  219. return (((u32)m_entry.first_cluster_high) << 16) | m_entry.first_cluster_low;
  220. }
  221. ErrorOr<size_t> FATInode::read_bytes_locked(off_t offset, size_t size, UserOrKernelBuffer& buffer, OpenFileDescription*) const
  222. {
  223. dbgln_if(FAT_DEBUG, "FATFS: Reading inode {}: size: {} offset: {}", identifier().index(), size, offset);
  224. // FIXME: Read only the needed blocks instead of the whole file
  225. auto blocks = TRY(const_cast<FATInode&>(*this).read_block_list());
  226. TRY(buffer.write(blocks->data() + offset, min(size, m_block_list.size() * fs().m_logical_block_size - offset)));
  227. return min(size, m_block_list.size() * fs().m_logical_block_size - offset);
  228. }
  229. InodeMetadata FATInode::metadata() const
  230. {
  231. return m_metadata;
  232. }
  233. ErrorOr<void> FATInode::traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
  234. {
  235. MutexLocker locker(m_inode_lock);
  236. VERIFY(has_flag(m_entry.attributes, FATAttributes::Directory));
  237. [[maybe_unused]] auto inode = TRY(const_cast<FATInode&>(*this).traverse([&callback](auto inode) -> ErrorOr<bool> {
  238. if (inode->m_filename->view() == "" || inode->m_filename->view() == "." || inode->m_filename->view() == "..")
  239. return false;
  240. TRY(callback({ inode->m_filename->view(), inode->identifier(), static_cast<u8>(inode->m_entry.attributes) }));
  241. return false;
  242. }));
  243. return {};
  244. }
  245. ErrorOr<NonnullLockRefPtr<Inode>> FATInode::lookup(StringView name)
  246. {
  247. MutexLocker locker(m_inode_lock);
  248. VERIFY(has_flag(m_entry.attributes, FATAttributes::Directory));
  249. auto inode = TRY(traverse([name](auto child) -> ErrorOr<bool> {
  250. return child->m_filename->view() == name;
  251. }));
  252. if (inode.is_null())
  253. return ENOENT;
  254. else
  255. return inode.release_nonnull();
  256. }
  257. ErrorOr<size_t> FATInode::write_bytes_locked(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*)
  258. {
  259. return EROFS;
  260. }
  261. ErrorOr<NonnullLockRefPtr<Inode>> FATInode::create_child(StringView, mode_t, dev_t, UserID, GroupID)
  262. {
  263. return EROFS;
  264. }
  265. ErrorOr<void> FATInode::add_child(Inode&, StringView, mode_t)
  266. {
  267. return EROFS;
  268. }
  269. ErrorOr<void> FATInode::remove_child(StringView)
  270. {
  271. return EROFS;
  272. }
  273. ErrorOr<void> FATInode::chmod(mode_t)
  274. {
  275. return EROFS;
  276. }
  277. ErrorOr<void> FATInode::chown(UserID, GroupID)
  278. {
  279. return EROFS;
  280. }
  281. ErrorOr<void> FATInode::flush_metadata()
  282. {
  283. return EROFS;
  284. }
  285. }