1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
#ifndef DEF_FATFS_CLASS_H
#define DEF_FATFS_CLASS_H
#include <VFS/FileSystem.proto.h>
#include <VFS/Part.ns.h>
#include <VFS/BlockCache.class.h>
struct fat_extBS_32_t { //Extended boot sector for FAT32
unsigned int table_size_32;
unsigned short extended_flags;
unsigned short fat_version;
unsigned int root_cluster;
unsigned short fat_info;
unsigned short backup_BS_sector;
unsigned char reserved_0[12];
unsigned char drive_number;
unsigned char reserved_1;
unsigned char boot_signature;
unsigned int volume_id;
unsigned char volume_label[11];
unsigned char fat_type_label[8];
}__attribute__((packed));
struct fat_extBS_16_t { //Extended boot sector for FAT12 and FAT16
unsigned char bios_drive_num;
unsigned char reserved1;
unsigned char boot_signature;
unsigned int volume_id;
unsigned char volume_label[11];
unsigned char fat_type_label[8];
}__attribute__((packed));
struct fat_BS_t { //Boot sector
unsigned char bootjmp[3];
unsigned char oem_name[8];
unsigned short bytes_per_sector;
unsigned char sectors_per_cluster;
unsigned short reserved_sector_count;
unsigned char table_count;
unsigned short root_entry_count;
unsigned short total_sectors_16;
unsigned char media_type;
unsigned short table_size_16;
unsigned short sectors_per_track;
unsigned short head_side_count;
unsigned int hidden_sector_count;
unsigned int total_sectors_32;
union {
fat_extBS_32_t extBS_32;
fat_extBS_16_t extBS_16;
};
}__attribute__((packed));
struct fat_date_t {
u16int year : 7;
u16int month : 4;
u16int day : 5;
}__attribute__((packed));
struct fat_time_t {
u16int hour : 5;
u16int minutes : 6;
u16int seconds : 5;
}__attribute__((packed));
struct fat_dir_entry_t {
char name[8];
char extension[3];
u8int attributes;
u8int reserved;
u8int createtenthsofseconds;
fat_time_t created_time;
fat_date_t created_date;
fat_date_t accessed_date;
u16int first_clust_high; //always 0 on FAT12/16
fat_time_t modified_time;
fat_date_t modified_date;
u16int first_clust_low;
u32int size;
}__attribute__((packed));
#define FA_READONLY 0x01
#define FA_HIDDEN 0x02
#define FA_SYSTEM 0x04
#define FA_VOLUMEID 0x08
#define FA_DIRECTORY 0x10
#define FA_ARCHIVE 0x20
#define FA_LFN 0x0F
class FATFS : public FileSystem {
private:
fat_BS_t m_bs;
bool m_readOnly;
u32int m_fatSize; //Size of one FAT, in sectors
u32int m_totalSectors; //Total sectors used by the FAT
u32int m_rootDirSectors; //Sectors used by the root directory
u32int m_firstDataSector; //First data sector, start of cluster 2
u32int m_countOfClusters; //Count of usable clusters, EXCLUDING the ones used by the root directory
u32int m_clusterSize; //size of a cluster in bytes
u32int m_fatType; //12, 16 or 32
Partition* m_part;
BlockCache<Partition> m_fatCache;
u32int nextCluster(u32int cluster); //Get the next cluster number in the chain (0 = EOF)
bool readCluster(u32int cluster, u8int* data); //Read the content of a cluster to a buffer
~FATFS() {}
FATFS(Partition* p) : m_part(p), m_fatCache(p) {}
public:
static FileSystem* mount(Partition* p, DirectoryNode* mountpoint, bool readwrite = false);
bool unmount();
bool setName(FSNode* node, String name);
bool setPermissions(FSNode* node, u32int permissions);
bool setUid(FSNode* node, u32int uid);
bool setGid(FSNode* node, u32int gid);
bool setParent(FSNode* node, FSNode* parent);
u32int read(FileNode* file, u64int position, u32int max_length, u8int *data);
bool write(FileNode* file, u64int position, u32int length, u8int *data);
bool truncate(FileNode* file);
bool loadContents(DirectoryNode* dir);
FileNode* createFile(DirectoryNode* parent, String name);
DirectoryNode* createDirectory(DirectoryNode* parent, String name);
bool remove(DirectoryNode* parent, FSNode* node);
Partition* getPart() { return m_part; }
};
#endif
|