123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- /*
- * Copyright (c) 2022, Undefine <undefine@undefine.pl>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #pragma once
- #include <AK/OwnPtr.h>
- #include <AK/RefPtr.h>
- #include <AK/Types.h>
- #include <Kernel/FileSystem/BlockBasedFileSystem.h>
- #include <Kernel/FileSystem/Inode.h>
- #include <Kernel/KBuffer.h>
- namespace Kernel {
- struct [[gnu::packed]] FAT32BootRecord {
- u8 boot_jump[3];
- char oem_identifier[8];
- u16 bytes_per_sector;
- u8 sectors_per_cluster;
- u16 reserved_sector_count;
- u8 fat_count;
- u16 root_directory_entry_count;
- u16 unused1;
- u8 media_descriptor_type;
- u16 unused2;
- u16 sectors_per_track;
- u16 head_count;
- u32 hidden_sector_count;
- u32 sector_count;
- u32 sectors_per_fat;
- u16 flags;
- u16 fat_version;
- u32 root_directory_cluster;
- u16 fs_info_sector;
- u16 backup_boot_sector;
- u8 unused3[12];
- u8 drive_number;
- u8 unused4;
- u8 signature;
- u32 volume_id;
- char volume_label_string[11];
- char system_identifier_string[8];
- };
- static_assert(sizeof(FAT32BootRecord) == 90);
- enum class FATAttributes : u8 {
- ReadOnly = 0x01,
- Hidden = 0x02,
- System = 0x04,
- VolumeID = 0x08,
- Directory = 0x10,
- Archive = 0x20,
- LongFileName = 0x0F
- };
- AK_ENUM_BITWISE_OPERATORS(FATAttributes);
- union FATPackedTime {
- u16 value;
- struct {
- u16 second : 5;
- u16 minute : 6;
- u16 hour : 5;
- };
- };
- static_assert(sizeof(FATPackedTime) == 2);
- union FATPackedDate {
- u16 value;
- struct {
- u16 day : 5;
- u16 month : 4;
- u16 year : 7;
- };
- };
- static_assert(sizeof(FATPackedDate) == 2);
- struct [[gnu::packed]] FATEntry {
- char filename[8];
- char extension[3];
- FATAttributes attributes;
- u8 unused1;
- u8 creation_time_seconds;
- FATPackedTime creation_time;
- FATPackedDate creation_date;
- FATPackedDate last_accessed_date;
- u16 first_cluster_high;
- FATPackedTime modification_time;
- FATPackedDate modification_date;
- u16 first_cluster_low;
- u32 file_size;
- };
- static_assert(sizeof(FATEntry) == 32);
- struct [[gnu::packed]] FATLongFileNameEntry {
- u8 entry_index;
- u16 characters1[5];
- FATAttributes attributes;
- u8 entry_type;
- u8 checksum;
- u16 characters2[6];
- u16 zero;
- u16 characters3[2];
- };
- static_assert(sizeof(FATLongFileNameEntry) == 32);
- class FATInode;
- class FATFS final : public BlockBasedFileSystem {
- friend FATInode;
- public:
- static ErrorOr<NonnullLockRefPtr<FileSystem>> try_create(OpenFileDescription&);
- virtual ~FATFS() override = default;
- virtual StringView class_name() const override { return "FATFS"sv; }
- virtual Inode& root_inode() override;
- private:
- virtual ErrorOr<void> initialize_while_locked() override;
- virtual bool is_initialized_while_locked() override;
- // FIXME: This is not a proper way to clear last mount of a FAT filesystem,
- // but for now we simply have no other way to properly do it.
- virtual ErrorOr<void> prepare_to_clear_last_mount() override { return {}; }
- FATFS(OpenFileDescription&);
- static constexpr u8 signature_1 = 0x28;
- static constexpr u8 signature_2 = 0x29;
- static constexpr u32 first_data_cluster = 2;
- FAT32BootRecord const* boot_record() const { return reinterpret_cast<FAT32BootRecord const*>(m_boot_record->data()); };
- BlockBasedFileSystem::BlockIndex first_block_of_cluster(u32 cluster) const;
- OwnPtr<KBuffer> m_boot_record;
- LockRefPtr<FATInode> m_root_inode;
- u32 m_first_data_sector;
- };
- class FATInode final : public Inode {
- friend FATFS;
- public:
- virtual ~FATInode() override = default;
- static ErrorOr<NonnullLockRefPtr<FATInode>> create(FATFS&, FATEntry, Vector<FATLongFileNameEntry> const& = {});
- FATFS& fs() { return static_cast<FATFS&>(Inode::fs()); }
- FATFS const& fs() const { return static_cast<FATFS const&>(Inode::fs()); }
- private:
- FATInode(FATFS&, FATEntry, NonnullOwnPtr<KString> filename);
- static constexpr u32 no_more_clusters = 0x0FFFFFF8;
- static constexpr u32 cluster_number_mask = 0x0FFFFFFF;
- static constexpr u8 end_entry_byte = 0x00;
- static constexpr u8 unused_entry_byte = 0xE5;
- static constexpr u8 lfn_entry_text_termination = 0xFF;
- static constexpr u16 first_fat_year = 1980;
- static constexpr u8 normal_filename_length = 8;
- static constexpr u8 normal_extension_length = 3;
- static ErrorOr<NonnullOwnPtr<KString>> compute_filename(FATEntry&, Vector<FATLongFileNameEntry> const& = {});
- static StringView byte_terminated_string(StringView, u8);
- static time_t fat_date_time(FATPackedDate date, FATPackedTime time);
- ErrorOr<Vector<BlockBasedFileSystem::BlockIndex>> compute_block_list();
- ErrorOr<NonnullOwnPtr<KBuffer>> read_block_list();
- ErrorOr<LockRefPtr<FATInode>> traverse(Function<ErrorOr<bool>(LockRefPtr<FATInode>)> callback);
- u32 first_cluster() const;
- // ^Inode
- virtual ErrorOr<size_t> write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& data, OpenFileDescription*) override;
- virtual ErrorOr<size_t> read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override;
- virtual InodeMetadata metadata() const override;
- virtual ErrorOr<void> traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const override;
- virtual ErrorOr<NonnullLockRefPtr<Inode>> lookup(StringView name) override;
- virtual ErrorOr<NonnullLockRefPtr<Inode>> create_child(StringView name, mode_t, dev_t, UserID, GroupID) override;
- virtual ErrorOr<void> add_child(Inode&, StringView name, mode_t) override;
- virtual ErrorOr<void> remove_child(StringView name) override;
- virtual ErrorOr<void> chmod(mode_t) override;
- virtual ErrorOr<void> chown(UserID, GroupID) override;
- virtual ErrorOr<void> flush_metadata() override;
- Vector<BlockBasedFileSystem::BlockIndex> m_block_list;
- FATEntry m_entry;
- NonnullOwnPtr<KString> m_filename;
- InodeMetadata m_metadata;
- };
- }
|