-
Notifications
You must be signed in to change notification settings - Fork 0
/
fat.h
207 lines (180 loc) · 5.8 KB
/
fat.h
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#pragma once
#include <optional>
#include <stdint.h>
#include <string>
#include <vector>
namespace cs5250 {
static inline constexpr char UnicodeToAscii(uint16_t unicode) {
if (unicode >= 0x20 && unicode <= 0x7e) {
return static_cast<char>(unicode);
}
return '?';
}
struct Extended16 {
uint8_t BS_DrvNum; /* offset 36 */
uint8_t BS_Reserved1; /* offset 37 */
uint8_t BS_BootSig; /* offset 38 */
uint8_t BS_VolID[4]; /* offset 39 */
uint8_t BS_VolLab[11]; /* offset 43 */
char BS_FilSysType[8]; /* offset 54 */
uint8_t _[448];
} __attribute__((packed));
struct Extended32 {
uint32_t BPB_FATSz32; /* offset 36 */
uint16_t BPB_ExtFlags; /* offset 40 */
uint8_t BPB_FSVer[2]; /* offset 42 */
uint32_t BPB_RootClus; /* offset 44 */
uint16_t BPB_FSInfo; /* offset 48 */
uint16_t BPB_BkBootSec; /* offset 50 */
uint8_t BPB_Reserved[12]; /* offset 52 */
uint8_t BS_DrvNum; /* offset 64 */
uint8_t BS_Reserved1; /* offset 65 */
uint8_t BS_BootSig; /* offset 66 */
uint8_t BS_VolID[4]; /* offset 67 */
uint8_t BS_VolLab[11]; /* offset 71 */
uint8_t BS_FilSysType[8]; /* offset 82 */
uint8_t _[420];
} __attribute__((packed));
struct BPB {
uint8_t BS_jmpBoot[3]; /* offset 0 */
uint8_t BS_OEMName[8]; /* offset 3 */
uint16_t BPB_BytsPerSec; /* offset 11 */
uint8_t BPB_SecPerClus; /* offset 13 */
uint16_t BPB_RsvdSecCnt; /* offset 14 */
uint8_t BPB_NumFATs; /* offset 16 */
uint16_t BPB_RootEntCnt; /* offset 17 */
uint16_t BPB_TotSec16; /* offset 19 */
uint8_t BPB_Media; /* offset 21 */
uint16_t BPB_FATSz16; /* offset 22 */
uint16_t BPB_SecPerTrk; /* offset 24 */
uint16_t BPB_NumHeads; /* offset 26 */
uint32_t BPB_HiddSec; /* offset 28 */
uint32_t BPB_TotSec32; /* offset 32 */
union {
// Extended BPB structure for FAT12 and FAT16 volumes
Extended16 fat16;
// Extended BPB structure for FAT32 volumes
Extended32 fat32;
};
uint16_t Signature_word; /* offset 510 */
} __attribute__((packed));
static_assert(sizeof(BPB) == 512, "BPB size is not 512 bytes");
/*
* File System Information (FSInfo) Structure
* RTFM: Section 5
*/
struct FSInfo {
uint32_t FSI_LeadSig; /* offset 0 */
uint8_t FSI_Reserved1[480]; /* offset 4 */
uint32_t FSI_StrucSig; /* offset 484 */
uint32_t FSI_Free_Count; /* offset 488 */
uint32_t FSI_Nxt_Free; /* offset 492 */
uint8_t FSI_Reserved2[12]; /* offset 496 */
uint32_t FSI_TrailSig; /* offset 508 */
} __attribute__((packed));
struct FATDirectory {
struct ShortName {
uint8_t name[8];
uint8_t ext[3];
} __attribute__((packed));
enum class Attr : uint8_t {
ReadOnly = 0x01,
Hidden = 0x02,
System = 0x04,
VolumeID = 0x08,
Directory = 0x10,
Archive = 0x20,
LongName = ReadOnly | Hidden | System | VolumeID,
LongNameMask =
ReadOnly | Hidden | System | VolumeID | Directory | Archive,
};
ShortName DIR_Name;
uint8_t DIR_Attr;
uint8_t DIR_NTRes;
uint8_t DIR_CrtTimeTenth;
uint16_t DIR_CrtTime;
uint16_t DIR_CrtDate;
uint16_t DIR_LstAccDate;
uint16_t DIR_FstClusHI;
uint16_t DIR_WrtTime;
uint16_t DIR_WrtDate;
uint16_t DIR_FstClusLO;
uint32_t DIR_FileSize;
public:
static const std::string AttributeTypeToString(Attr attr) {
switch (attr) {
case Attr::ReadOnly:
return "Read Only";
case Attr::Hidden:
return "Hidden";
case Attr::System:
return "System";
case Attr::VolumeID:
return "Volume ID";
case Attr::Directory:
return "Directory";
case Attr::Archive:
return "Archive";
case Attr::LongName:
return "Long Name";
default:
return "Unknown";
}
}
} __attribute__((packed));
struct LongNameDirectory {
struct UnicodeChar {
uint8_t low;
uint8_t high;
public:
UnicodeChar() : low(0), high(0) {}
UnicodeChar(uint8_t low, uint8_t high) : low(low), high(high) {}
UnicodeChar(uint8_t low) : low(low), high(0) {}
} __attribute__((packed));
template <size_t N> struct Name {
UnicodeChar values[N];
} __attribute__((packed));
template <size_t N>
static const std::pair<std::string, bool> GetName(const Name<N> &name) {
std::string str = "";
for (size_t i = 0; i < N; ++i) {
if (name.values[i].low == 0)
return {str, true};
str += UnicodeToAscii(
reinterpret_cast<const uint16_t &>(name.values[i]));
}
return {str, false};
}
uint8_t LDIR_Ord;
Name<5> LDIR_Name1;
uint8_t LDIR_Attr;
uint8_t LDIR_Type;
uint8_t LDIR_Chksum;
Name<6> LDIR_Name2;
uint16_t LDIR_FstClusLO;
Name<2> LDIR_Name3;
} __attribute__((packed));
static_assert(sizeof(LongNameDirectory) == 32);
static_assert(sizeof(FATDirectory) == 32);
static_assert(sizeof(FSInfo) == 512);
struct SimpleStruct {
std::string name;
uint32_t first_cluster;
bool is_dir;
uint32_t size;
std::optional<std::vector<const LongNameDirectory *>> long_name_entries;
operator std::string() const { return name; }
bool operator==(const SimpleStruct &other) const {
return name == other.name && first_cluster == other.first_cluster &&
is_dir == other.is_dir;
}
};
} // namespace cs5250
// define hash for LsStruct
namespace std {
template <> struct hash<cs5250::SimpleStruct> {
std::size_t operator()(const cs5250::SimpleStruct &k) const {
return std::hash<uint32_t>{}(k.first_cluster);
}
};
} // namespace std