exFAT uses tree structure to describe relationship between files and directories. The root of the directory tree is defined by directory located at RootDirectoryCluster. Subdirectories are single-linked to there parents. There is no special (.) and (..) directories pointing to itself and to parent like in FAT16/FAT32.
Each directory consists of a series of directory entries. Directory entries are classified as critical/benign and primary/secondary as follows:
Critical entries are required while benign entries are optional. Primary directory entries correspond to the entries in file system and describe main characteristics. Secondary directory entries extend the metadata associated with a primary directory entry end follow it. A group of primary/secondary entries make up a directory entry set describing a file or directory. The first directory entry in the set is a primary directory entry. All subsequent entries, if any, must be secondary directory entries.
Each directory entry derives from Generica Directory Entry template. Size of directory entry is 32 bytes.
Offset | Size | Description | Comments |
---|---|---|---|
0 (0x00) | 1 | EntryType (see below) | |
1 (0x01) | 19 | CustomDefined | |
20 (0x14) | 4 | FirstCluster | 0 – no cluster allocation 2..ClusterCount+1 – cluster index |
24 (0x18) | 8 | DataLength | In bytes |
Bits | Size | Description | Comments |
0-4 | 5 | Code | |
5 | 1 | Importance | 0 – Critical entry, 1 – Benign entry |
6 | 1 | Category | 0 – Primary entry, 1 – Secondary entry |
7 | 1 | In use status | 0 – Not in use, 1 – In use |
EntryType can have the following values:
Offset | Size | Description | Comments |
---|---|---|---|
0 (0x00) | 1 | EntryType | |
1 (0x01) | 1 | SecondaryCount | Number of secondary entries which immediately follow this primary entry and together comprise a directory entry set. Valid value is 0..255 |
2 (0x02) | 2 | SetChecksum | Checksum of all directory entries in the given set excluding this field. See EntrySetCheckSum(). |
4 (0x04) | 2 | GeneralPrimaryFlags (see below) | |
6 (0x06) | 14 | CustomDefined | |
20 (0x14) | 4 | FirstCluster | |
24 (0x18) | 8 | DataLength |
Bits | Size | Description | Comments |
---|---|---|---|
0 | 1 | AllocationPossible | 0-not possible (FirstCluster and DataLength undefined), 1-possible |
1 | 1 | NoFatChain | 0-FAT cluster chain is valid 1-FAT cluster chain is not used (contiguous data) |
2 | 14 | CustomDefined |
All critical primary directory entries are located in root directory (except file directory entries). Benign primary directory enries are optional. If one benign primary entry is not recognized, all directory entry set is ignored.
// data points to directory entry set in memory UINT16 EntrySetChecksum(const unsigned char data[], int secondaryCount) { UINT16 checksum = 0; int bytes = (secondaryCount + 1) * 32; for (int i = 0; i < bytes; i++) { if (i == 2 || i == 3) continue; checksum = (checksum << 15) | (checksum >> 1) + data[i]; } return checksum; }