FATFileSystem.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Copyright (c) 2022, Undefine <undefine@undefine.pl>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/OwnPtr.h>
  8. #include <AK/RefPtr.h>
  9. #include <AK/Types.h>
  10. #include <Kernel/FileSystem/BlockBasedFileSystem.h>
  11. #include <Kernel/FileSystem/Inode.h>
  12. #include <Kernel/KBuffer.h>
  13. namespace Kernel {
  14. struct [[gnu::packed]] FAT32BootRecord {
  15. u8 boot_jump[3];
  16. char oem_identifier[8];
  17. u16 bytes_per_sector;
  18. u8 sectors_per_cluster;
  19. u16 reserved_sector_count;
  20. u8 fat_count;
  21. u16 root_directory_entry_count;
  22. u16 unused1;
  23. u8 media_descriptor_type;
  24. u16 unused2;
  25. u16 sectors_per_track;
  26. u16 head_count;
  27. u32 hidden_sector_count;
  28. u32 sector_count;
  29. u32 sectors_per_fat;
  30. u16 flags;
  31. u16 fat_version;
  32. u32 root_directory_cluster;
  33. u16 fs_info_sector;
  34. u16 backup_boot_sector;
  35. u8 unused3[12];
  36. u8 drive_number;
  37. u8 unused4;
  38. u8 signature;
  39. u32 volume_id;
  40. char volume_label_string[11];
  41. char system_identifier_string[8];
  42. };
  43. static_assert(sizeof(FAT32BootRecord) == 90);
  44. enum class FATAttributes : u8 {
  45. ReadOnly = 0x01,
  46. Hidden = 0x02,
  47. System = 0x04,
  48. VolumeID = 0x08,
  49. Directory = 0x10,
  50. Archive = 0x20,
  51. LongFileName = 0x0F
  52. };
  53. AK_ENUM_BITWISE_OPERATORS(FATAttributes);
  54. union FATPackedTime {
  55. u16 value;
  56. struct {
  57. u16 second : 5;
  58. u16 minute : 6;
  59. u16 hour : 5;
  60. };
  61. };
  62. static_assert(sizeof(FATPackedTime) == 2);
  63. union FATPackedDate {
  64. u16 value;
  65. struct {
  66. u16 day : 5;
  67. u16 month : 4;
  68. u16 year : 7;
  69. };
  70. };
  71. static_assert(sizeof(FATPackedDate) == 2);
  72. struct [[gnu::packed]] FATEntry {
  73. char filename[8];
  74. char extension[3];
  75. FATAttributes attributes;
  76. u8 unused1;
  77. u8 creation_time_seconds;
  78. FATPackedTime creation_time;
  79. FATPackedDate creation_date;
  80. FATPackedDate last_accessed_date;
  81. u16 first_cluster_high;
  82. FATPackedTime modification_time;
  83. FATPackedDate modification_date;
  84. u16 first_cluster_low;
  85. u32 file_size;
  86. };
  87. static_assert(sizeof(FATEntry) == 32);
  88. struct [[gnu::packed]] FATLongFileNameEntry {
  89. u8 entry_index;
  90. u16 characters1[5];
  91. FATAttributes attributes;
  92. u8 entry_type;
  93. u8 checksum;
  94. u16 characters2[6];
  95. u16 zero;
  96. u16 characters3[2];
  97. };
  98. static_assert(sizeof(FATLongFileNameEntry) == 32);
  99. class FATInode;
  100. class FATFS final : public BlockBasedFileSystem {
  101. friend FATInode;
  102. public:
  103. static ErrorOr<NonnullLockRefPtr<FileSystem>> try_create(OpenFileDescription&);
  104. virtual ~FATFS() override = default;
  105. virtual StringView class_name() const override { return "FATFS"sv; }
  106. virtual Inode& root_inode() override;
  107. private:
  108. virtual ErrorOr<void> initialize_while_locked() override;
  109. virtual bool is_initialized_while_locked() override;
  110. // FIXME: This is not a proper way to clear last mount of a FAT filesystem,
  111. // but for now we simply have no other way to properly do it.
  112. virtual ErrorOr<void> prepare_to_clear_last_mount() override { return {}; }
  113. FATFS(OpenFileDescription&);
  114. static constexpr u8 signature_1 = 0x28;
  115. static constexpr u8 signature_2 = 0x29;
  116. static constexpr u32 first_data_cluster = 2;
  117. FAT32BootRecord const* boot_record() const { return reinterpret_cast<FAT32BootRecord const*>(m_boot_record->data()); };
  118. BlockBasedFileSystem::BlockIndex first_block_of_cluster(u32 cluster) const;
  119. OwnPtr<KBuffer> m_boot_record;
  120. LockRefPtr<FATInode> m_root_inode;
  121. u32 m_first_data_sector;
  122. };
  123. class FATInode final : public Inode {
  124. friend FATFS;
  125. public:
  126. virtual ~FATInode() override = default;
  127. static ErrorOr<NonnullLockRefPtr<FATInode>> create(FATFS&, FATEntry, Vector<FATLongFileNameEntry> const& = {});
  128. FATFS& fs() { return static_cast<FATFS&>(Inode::fs()); }
  129. FATFS const& fs() const { return static_cast<FATFS const&>(Inode::fs()); }
  130. private:
  131. FATInode(FATFS&, FATEntry, NonnullOwnPtr<KString> filename);
  132. static constexpr u32 no_more_clusters = 0x0FFFFFF8;
  133. static constexpr u32 cluster_number_mask = 0x0FFFFFFF;
  134. static constexpr u8 end_entry_byte = 0x00;
  135. static constexpr u8 unused_entry_byte = 0xE5;
  136. static constexpr u8 lfn_entry_text_termination = 0xFF;
  137. static constexpr u16 first_fat_year = 1980;
  138. static constexpr u8 normal_filename_length = 8;
  139. static constexpr u8 normal_extension_length = 3;
  140. static ErrorOr<NonnullOwnPtr<KString>> compute_filename(FATEntry&, Vector<FATLongFileNameEntry> const& = {});
  141. static StringView byte_terminated_string(StringView, u8);
  142. static time_t fat_date_time(FATPackedDate date, FATPackedTime time);
  143. ErrorOr<Vector<BlockBasedFileSystem::BlockIndex>> compute_block_list();
  144. ErrorOr<NonnullOwnPtr<KBuffer>> read_block_list();
  145. ErrorOr<LockRefPtr<FATInode>> traverse(Function<ErrorOr<bool>(LockRefPtr<FATInode>)> callback);
  146. u32 first_cluster() const;
  147. // ^Inode
  148. virtual ErrorOr<size_t> write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& data, OpenFileDescription*) override;
  149. virtual ErrorOr<size_t> read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override;
  150. virtual InodeMetadata metadata() const override;
  151. virtual ErrorOr<void> traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const override;
  152. virtual ErrorOr<NonnullLockRefPtr<Inode>> lookup(StringView name) override;
  153. virtual ErrorOr<NonnullLockRefPtr<Inode>> create_child(StringView name, mode_t, dev_t, UserID, GroupID) override;
  154. virtual ErrorOr<void> add_child(Inode&, StringView name, mode_t) override;
  155. virtual ErrorOr<void> remove_child(StringView name) override;
  156. virtual ErrorOr<void> chmod(mode_t) override;
  157. virtual ErrorOr<void> chown(UserID, GroupID) override;
  158. virtual ErrorOr<void> flush_metadata() override;
  159. Vector<BlockBasedFileSystem::BlockIndex> m_block_list;
  160. FATEntry m_entry;
  161. NonnullOwnPtr<KString> m_filename;
  162. InodeMetadata m_metadata;
  163. };
  164. }