mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-15 20:33:10 +00:00
Kernel: Split the FATFileSystem.{cpp,h} files into smaller components
This commit is contained in:
parent
5e6101dd3e
commit
e882b2ed05
|
@ -111,7 +111,8 @@ set(KERNEL_SOURCES
|
||||||
FileSystem/Custody.cpp
|
FileSystem/Custody.cpp
|
||||||
FileSystem/DevPtsFS.cpp
|
FileSystem/DevPtsFS.cpp
|
||||||
FileSystem/Ext2FileSystem.cpp
|
FileSystem/Ext2FileSystem.cpp
|
||||||
FileSystem/FATFileSystem.cpp
|
FileSystem/FATFS/FileSystem.cpp
|
||||||
|
FileSystem/FATFS/Inode.cpp
|
||||||
FileSystem/FIFO.cpp
|
FileSystem/FIFO.cpp
|
||||||
FileSystem/File.cpp
|
FileSystem/File.cpp
|
||||||
FileSystem/FileBackedFileSystem.cpp
|
FileSystem/FileBackedFileSystem.cpp
|
||||||
|
|
106
Kernel/FileSystem/FATFS/Definitions.h
Normal file
106
Kernel/FileSystem/FATFS/Definitions.h
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Undefine <undefine@undefine.pl>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/EnumBits.h>
|
||||||
|
#include <AK/Types.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);
|
||||||
|
|
||||||
|
}
|
94
Kernel/FileSystem/FATFS/FileSystem.cpp
Normal file
94
Kernel/FileSystem/FATFS/FileSystem.cpp
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Undefine <undefine@undefine.pl>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Kernel/Debug.h>
|
||||||
|
#include <Kernel/FileSystem/FATFS/FileSystem.h>
|
||||||
|
#include <Kernel/FileSystem/FATFS/Inode.h>
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
|
||||||
|
ErrorOr<NonnullLockRefPtr<FileSystem>> FATFS::try_create(OpenFileDescription& file_description)
|
||||||
|
{
|
||||||
|
return TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) FATFS(file_description)));
|
||||||
|
}
|
||||||
|
|
||||||
|
FATFS::FATFS(OpenFileDescription& file_description)
|
||||||
|
: BlockBasedFileSystem(file_description)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FATFS::is_initialized_while_locked()
|
||||||
|
{
|
||||||
|
VERIFY(m_lock.is_locked());
|
||||||
|
return !m_root_inode.is_null();
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> FATFS::initialize_while_locked()
|
||||||
|
{
|
||||||
|
VERIFY(m_lock.is_locked());
|
||||||
|
VERIFY(!is_initialized_while_locked());
|
||||||
|
|
||||||
|
m_boot_record = TRY(KBuffer::try_create_with_size("FATFS: Boot Record"sv, m_logical_block_size));
|
||||||
|
auto boot_record_buffer = UserOrKernelBuffer::for_kernel_buffer(m_boot_record->data());
|
||||||
|
TRY(raw_read(0, boot_record_buffer));
|
||||||
|
|
||||||
|
if constexpr (FAT_DEBUG) {
|
||||||
|
dbgln("FATFS: oem_identifier: {}", boot_record()->oem_identifier);
|
||||||
|
dbgln("FATFS: bytes_per_sector: {}", boot_record()->bytes_per_sector);
|
||||||
|
dbgln("FATFS: sectors_per_cluster: {}", boot_record()->sectors_per_cluster);
|
||||||
|
dbgln("FATFS: reserved_sector_count: {}", boot_record()->reserved_sector_count);
|
||||||
|
dbgln("FATFS: fat_count: {}", boot_record()->fat_count);
|
||||||
|
dbgln("FATFS: root_directory_entry_count: {}", boot_record()->root_directory_entry_count);
|
||||||
|
dbgln("FATFS: media_descriptor_type: {}", boot_record()->media_descriptor_type);
|
||||||
|
dbgln("FATFS: sectors_per_track: {}", boot_record()->sectors_per_track);
|
||||||
|
dbgln("FATFS: head_count: {}", boot_record()->head_count);
|
||||||
|
dbgln("FATFS: hidden_sector_count: {}", boot_record()->hidden_sector_count);
|
||||||
|
dbgln("FATFS: sector_count: {}", boot_record()->sector_count);
|
||||||
|
dbgln("FATFS: sectors_per_fat: {}", boot_record()->sectors_per_fat);
|
||||||
|
dbgln("FATFS: flags: {}", boot_record()->flags);
|
||||||
|
dbgln("FATFS: fat_version: {}", boot_record()->fat_version);
|
||||||
|
dbgln("FATFS: root_directory_cluster: {}", boot_record()->root_directory_cluster);
|
||||||
|
dbgln("FATFS: fs_info_sector: {}", boot_record()->fs_info_sector);
|
||||||
|
dbgln("FATFS: backup_boot_sector: {}", boot_record()->backup_boot_sector);
|
||||||
|
dbgln("FATFS: drive_number: {}", boot_record()->drive_number);
|
||||||
|
dbgln("FATFS: volume_id: {}", boot_record()->volume_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (boot_record()->signature != signature_1 && boot_record()->signature != signature_2) {
|
||||||
|
dbgln("FATFS: Invalid signature");
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_logical_block_size = boot_record()->bytes_per_sector;
|
||||||
|
set_block_size(m_logical_block_size);
|
||||||
|
|
||||||
|
u32 root_directory_sectors = ((boot_record()->root_directory_entry_count * sizeof(FATEntry)) + (m_logical_block_size - 1)) / m_logical_block_size;
|
||||||
|
m_first_data_sector = boot_record()->reserved_sector_count + (boot_record()->fat_count * boot_record()->sectors_per_fat) + root_directory_sectors;
|
||||||
|
|
||||||
|
TRY(BlockBasedFileSystem::initialize_while_locked());
|
||||||
|
|
||||||
|
FATEntry root_entry {};
|
||||||
|
|
||||||
|
root_entry.first_cluster_low = boot_record()->root_directory_cluster & 0xFFFF;
|
||||||
|
root_entry.first_cluster_high = boot_record()->root_directory_cluster >> 16;
|
||||||
|
|
||||||
|
root_entry.attributes = FATAttributes::Directory;
|
||||||
|
m_root_inode = TRY(FATInode::create(*this, root_entry));
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Inode& FATFS::root_inode()
|
||||||
|
{
|
||||||
|
return *m_root_inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockBasedFileSystem::BlockIndex FATFS::first_block_of_cluster(u32 cluster) const
|
||||||
|
{
|
||||||
|
return ((cluster - first_data_cluster) * boot_record()->sectors_per_cluster) + m_first_data_sector;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
53
Kernel/FileSystem/FATFS/FileSystem.h
Normal file
53
Kernel/FileSystem/FATFS/FileSystem.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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/FATFS/Definitions.h>
|
||||||
|
#include <Kernel/FileSystem/Inode.h>
|
||||||
|
#include <Kernel/Forward.h>
|
||||||
|
#include <Kernel/KBuffer.h>
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -6,93 +6,11 @@
|
||||||
|
|
||||||
#include <AK/Time.h>
|
#include <AK/Time.h>
|
||||||
#include <Kernel/Debug.h>
|
#include <Kernel/Debug.h>
|
||||||
#include <Kernel/Devices/BlockDevice.h>
|
#include <Kernel/FileSystem/FATFS/Inode.h>
|
||||||
#include <Kernel/FileSystem/FATFileSystem.h>
|
#include <Kernel/KBufferBuilder.h>
|
||||||
#include <Kernel/Memory/Region.h>
|
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
ErrorOr<NonnullLockRefPtr<FileSystem>> FATFS::try_create(OpenFileDescription& file_description)
|
|
||||||
{
|
|
||||||
return TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) FATFS(file_description)));
|
|
||||||
}
|
|
||||||
|
|
||||||
FATFS::FATFS(OpenFileDescription& file_description)
|
|
||||||
: BlockBasedFileSystem(file_description)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FATFS::is_initialized_while_locked()
|
|
||||||
{
|
|
||||||
VERIFY(m_lock.is_locked());
|
|
||||||
return !m_root_inode.is_null();
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorOr<void> FATFS::initialize_while_locked()
|
|
||||||
{
|
|
||||||
VERIFY(m_lock.is_locked());
|
|
||||||
VERIFY(!is_initialized_while_locked());
|
|
||||||
|
|
||||||
m_boot_record = TRY(KBuffer::try_create_with_size("FATFS: Boot Record"sv, m_logical_block_size));
|
|
||||||
auto boot_record_buffer = UserOrKernelBuffer::for_kernel_buffer(m_boot_record->data());
|
|
||||||
TRY(raw_read(0, boot_record_buffer));
|
|
||||||
|
|
||||||
if constexpr (FAT_DEBUG) {
|
|
||||||
dbgln("FATFS: oem_identifier: {}", boot_record()->oem_identifier);
|
|
||||||
dbgln("FATFS: bytes_per_sector: {}", boot_record()->bytes_per_sector);
|
|
||||||
dbgln("FATFS: sectors_per_cluster: {}", boot_record()->sectors_per_cluster);
|
|
||||||
dbgln("FATFS: reserved_sector_count: {}", boot_record()->reserved_sector_count);
|
|
||||||
dbgln("FATFS: fat_count: {}", boot_record()->fat_count);
|
|
||||||
dbgln("FATFS: root_directory_entry_count: {}", boot_record()->root_directory_entry_count);
|
|
||||||
dbgln("FATFS: media_descriptor_type: {}", boot_record()->media_descriptor_type);
|
|
||||||
dbgln("FATFS: sectors_per_track: {}", boot_record()->sectors_per_track);
|
|
||||||
dbgln("FATFS: head_count: {}", boot_record()->head_count);
|
|
||||||
dbgln("FATFS: hidden_sector_count: {}", boot_record()->hidden_sector_count);
|
|
||||||
dbgln("FATFS: sector_count: {}", boot_record()->sector_count);
|
|
||||||
dbgln("FATFS: sectors_per_fat: {}", boot_record()->sectors_per_fat);
|
|
||||||
dbgln("FATFS: flags: {}", boot_record()->flags);
|
|
||||||
dbgln("FATFS: fat_version: {}", boot_record()->fat_version);
|
|
||||||
dbgln("FATFS: root_directory_cluster: {}", boot_record()->root_directory_cluster);
|
|
||||||
dbgln("FATFS: fs_info_sector: {}", boot_record()->fs_info_sector);
|
|
||||||
dbgln("FATFS: backup_boot_sector: {}", boot_record()->backup_boot_sector);
|
|
||||||
dbgln("FATFS: drive_number: {}", boot_record()->drive_number);
|
|
||||||
dbgln("FATFS: volume_id: {}", boot_record()->volume_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (boot_record()->signature != signature_1 && boot_record()->signature != signature_2) {
|
|
||||||
dbgln("FATFS: Invalid signature");
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_logical_block_size = boot_record()->bytes_per_sector;
|
|
||||||
set_block_size(m_logical_block_size);
|
|
||||||
|
|
||||||
u32 root_directory_sectors = ((boot_record()->root_directory_entry_count * sizeof(FATEntry)) + (m_logical_block_size - 1)) / m_logical_block_size;
|
|
||||||
m_first_data_sector = boot_record()->reserved_sector_count + (boot_record()->fat_count * boot_record()->sectors_per_fat) + root_directory_sectors;
|
|
||||||
|
|
||||||
TRY(BlockBasedFileSystem::initialize_while_locked());
|
|
||||||
|
|
||||||
FATEntry root_entry {};
|
|
||||||
|
|
||||||
root_entry.first_cluster_low = boot_record()->root_directory_cluster & 0xFFFF;
|
|
||||||
root_entry.first_cluster_high = boot_record()->root_directory_cluster >> 16;
|
|
||||||
|
|
||||||
root_entry.attributes = FATAttributes::Directory;
|
|
||||||
m_root_inode = TRY(FATInode::create(*this, root_entry));
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Inode& FATFS::root_inode()
|
|
||||||
{
|
|
||||||
return *m_root_inode;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockBasedFileSystem::BlockIndex FATFS::first_block_of_cluster(u32 cluster) const
|
|
||||||
{
|
|
||||||
return ((cluster - first_data_cluster) * boot_record()->sectors_per_cluster) + m_first_data_sector;
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorOr<NonnullLockRefPtr<FATInode>> FATInode::create(FATFS& fs, FATEntry entry, Vector<FATLongFileNameEntry> const& lfn_entries)
|
ErrorOr<NonnullLockRefPtr<FATInode>> FATInode::create(FATFS& fs, FATEntry entry, Vector<FATLongFileNameEntry> const& lfn_entries)
|
||||||
{
|
{
|
||||||
auto filename = TRY(compute_filename(entry, lfn_entries));
|
auto filename = TRY(compute_filename(entry, lfn_entries));
|
75
Kernel/FileSystem/FATFS/Inode.h
Normal file
75
Kernel/FileSystem/FATFS/Inode.h
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Undefine <undefine@undefine.pl>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/OwnPtr.h>
|
||||||
|
#include <AK/RefPtr.h>
|
||||||
|
#include <Kernel/FileSystem/FATFS/Definitions.h>
|
||||||
|
#include <Kernel/FileSystem/FATFS/FileSystem.h>
|
||||||
|
#include <Kernel/FileSystem/Inode.h>
|
||||||
|
#include <Kernel/KBuffer.h>
|
||||||
|
#include <Kernel/KString.h>
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -1,201 +0,0 @@
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -20,6 +20,7 @@ class Device;
|
||||||
class DiskCache;
|
class DiskCache;
|
||||||
class DoubleBuffer;
|
class DoubleBuffer;
|
||||||
class File;
|
class File;
|
||||||
|
class FATInode;
|
||||||
class OpenFileDescription;
|
class OpenFileDescription;
|
||||||
class DisplayConnector;
|
class DisplayConnector;
|
||||||
class FileSystem;
|
class FileSystem;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <Kernel/FileSystem/Custody.h>
|
#include <Kernel/FileSystem/Custody.h>
|
||||||
#include <Kernel/FileSystem/DevPtsFS.h>
|
#include <Kernel/FileSystem/DevPtsFS.h>
|
||||||
#include <Kernel/FileSystem/Ext2FileSystem.h>
|
#include <Kernel/FileSystem/Ext2FileSystem.h>
|
||||||
#include <Kernel/FileSystem/FATFileSystem.h>
|
#include <Kernel/FileSystem/FATFS/FileSystem.h>
|
||||||
#include <Kernel/FileSystem/ISO9660FileSystem.h>
|
#include <Kernel/FileSystem/ISO9660FileSystem.h>
|
||||||
#include <Kernel/FileSystem/Plan9FileSystem.h>
|
#include <Kernel/FileSystem/Plan9FileSystem.h>
|
||||||
#include <Kernel/FileSystem/ProcFS.h>
|
#include <Kernel/FileSystem/ProcFS.h>
|
||||||
|
|
Loading…
Reference in a new issue