Last Updated: 2023-06-26 09:26:12 Monday
-- TOC --
exFAT文件系统,extensible File Allocation Table,是FAT系列文件系统,FAT32的后续。exFAT突破了4G文件大小的限制,专利2019年到期,Linux和Mac上读写exFAT分区都没问题。
The exFAT file system is the successor to FAT32 in the FAT family of file systems.
exFAT (Extensible File Allocation Table) is a file system introduced by Microsoft in 2006 and
optimized for flash memory
such as USB flash drives and SD cards. exFAT was proprietary until 28 August 2019. 专利到期,大家就都支持了!exFAT标准:https://learn.microsoft.com/en-us/windows/win32/fileio/exfat-specification
exFAT文件系统的设计目标:
simplicity
of FAT-based file systems. Two of the strengths of FAT-based file systems are their relative simplicity and ease of implementation. In the spirit of its predecessors, implementers should find exFAT relatively simple and easy to implement. (简单好用就是王道)very large
files and storage devices. The exFAT file system uses 64 bits to describe file size
, thereby enabling applications which depend on very large files. The exFAT file system also allows for clusters as large as 32MB, effectively enabling very large storage devices.extensibility
for future innovation. The exFAT file system incorporates extensibility into its design, enabling the file system to keep pace with innovations in storage and changes in usage.struct exfat_bpb
{
uint8_t jmp_boot[3];
uint8_t oem_name[8];
uint8_t mbz[53];
uint64_t num_hidden_sectors;
uint64_t num_total_sectors;
uint32_t num_reserved_sectors;
uint32_t sectors_per_fat;
uint32_t cluster_offset;
uint32_t cluster_count;
uint32_t root_cluster;
uint32_t num_serial;
uint16_t fs_revision;
uint16_t volume_flags;
uint8_t bytes_per_sector_shift;
uint8_t sectors_per_cluster_shift;
uint8_t num_fats;
uint8_t num_ph_drive;
uint8_t PercentInUse;
uint8_t reserved[7];
} GRUB_PACKED;
在U盘上创建一个exFAT分区(用mkfs.exfat命令,默认参数):
Device Start End Sectors Size Type
...
/dev/sdc2 2099200 60086271 57987072 27.7G Linux filesystem
BPB引导扇区内容如下:
$ sudo xxd -a -u -l 512 /dev/sdc2
00000000: EB76 9045 5846 4154 2020 2000 0000 0000 .v.EXFAT .....
00000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
00000040: 0008 2000 0000 0000 00D0 7403 0000 0000 .. .......t.....
00000050: 0008 0000 C01B 0000 0028 0000 A0D2 0D00 .........(......
00000060: 0700 0000 5AE8 837D 0001 0000 0906 0180 ....Z..}........
00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
000001f0: 0000 0000 0000 0000 0000 0000 0000 55AA ..............U.
uint8_t jmp_boot[3]
,3字节,可忽略,其值与FAT32有所不同uint8_t oem_name[8]
,8字节,uint8_t mbz[53]
,53字节,全0,MustBeZero。前64字节,只有个name可以看看。uint64_t num_hidden_sectors
,8字节,分区前面的hidden section数量,0x0000 0000 0020 0800
,即2099200,标准中写为PartitionOffset。uint64_t num_total_sectors
,8字节,分区的total section数量,0x0000 0000 0374 D000
,即57987072,标准中写为VolumeLength。(微软喜欢用Volume这个词,它就是Partition)uint32_t num_reserved_sectors
,4字节,保留扇区数,0x0000 0800
,即2048,标准中写为FatOffset。uint32_t sectors_per_fat
,4字节,FAT表扇区数,0x0000 1BC0
,即7104,标准中写为FatLength。uint32_t cluster_offset
,4字节,第1个cluster的偏移扇区数,0x0000 2800
,即10240uint32_t cluster_count
,4字节,cluster数量,0x000D D2A0
,即905888uint32_t root_cluster
,4字节,root cluster,0x0000 0007
,即7uint32_t num_serial
,4字节,序列号,0x7D83 E85A
uint16_t fs_revision
,2字节,版本号,0x0100
,1.0uint16_t volume_flags
,2字节,flags,见下uint8_t bytes_per_sector_shift
,1字节,用左移位数表示每扇区字节数,0x09
,即9,1<<9=512
uint8_t sectors_per_cluster_shift
,1字节,用左移位数表示每cluster的扇区数,0x06
,即6,1<<6=64
,每cluster有64扇区,每cluster的size为32768Bytes,32KBuint8_t num_fats
,1字节,FAT表的数量,0x01
,即1,1个FAT表uint8_t num_ph_drive
,1字节,物理驱动器号,0x80
uint8_t reserved[8]
,最后保留8字节,用于未来扩展。标准中这个区域的第1个字节,被用作PercentInUse。做几道小学数学题:
>>> (57987072-10240)/64
905888.0
>>> 10240-2048-7104
1088
>>> 2048+7104+1088+905888*64
57987072
在FAT表末尾到第1个cluster之间,还有1088个扇区闲置?!
MustBeZero
这段全0,就像一个保护字段,类似PMBR的效果。
The MustBeZero field shall directly correspond with the range of bytes the packed BIOS parameter block consumes on FAT12/16/32 volumes.
The valid value for this field is 0, which helps to prevent FAT12/16/32 implementations from mistakenly mounting an exFAT volume.
Volume Flags
这16个bit,标准目前只定了前4个:
TexFAT
的实现,才需要考虑切换FAT表。Boot Checksum
checksum的作用是,代码需要首先通过checksum确认Boot Region的内容是可靠的。
The Main and Backup Boot Checksums each contain a repeating pattern of the four-byte checksum of the contents of all other sub-regions in their respective Boot regions. The checksum calculation shall not include the VolumeFlags and PercentInUse fields in their respective Boot Sector. The repeating pattern of the four-byte checksum fills its respective Boot Checksum sub-region from the beginning to the end of the sub-region.
checksum算法:
#include <stdio.h>
#include <stdlib.h>
int main() {
unsigned int cks = 0;
FILE *fdev = fopen("/dev/sdc2", "rb");
if(!fdev){
printf("fopen failed.\n");
return 1;
}
unsigned char *p11s = malloc(512*11);
fread(p11s, 512, 11, fdev);
fclose(fdev);
for(int i=0; i<512*11; ++i){
if((i==106) || (i==107) || (i==112))
continue;
cks = ((cks&1)?0x80000000:0) + (cks>>1) + p11s[i];
}
free(p11s);
printf("0x%X\n", cks);
return 0;
}
sudo执行,输出0x7859FD56
。exFAT文件系统定义的checksum,为什么要在一个sector内不断重复呢:
$ sudo xxd -a -u -s$((512*11)) -l 512 /dev/sdc2
00001600: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001610: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001620: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001630: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001640: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001650: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001660: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001670: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001680: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001690: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
000016a0: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
000016b0: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
000016c0: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
000016d0: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
000016e0: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
000016f0: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001700: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001710: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001720: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001730: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001740: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001750: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001760: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001770: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001780: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
00001790: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
000017a0: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
000017b0: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
000017c0: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
000017d0: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
000017e0: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
000017f0: 56FD 5978 56FD 5978 56FD 5978 56FD 5978 V.YxV.YxV.YxV.Yx
exFAT文件系统对分区的划分,与FAT32完全一样。
Main Boot Region | FAT Region | Data Region
Main Boot Region占用前12个扇区,结构如下描述:
Sub-region Name | Offset (sector) | Size (sectors) | Comments |
---|---|---|---|
Main Boot Sector | 0 | 1 | BPB |
Main Extended Boot Sectors | 1 | 8 | 一般都是全0,但每个sector最后两个byte均为0x55AA |
Main OEM Parameters | 9 | 1 | 标准定义的很复杂,但我的U盘告诉我,全FF |
Main Reserved | 10 | 1 | 全0 |
Main Boot Checksum | 11 | 1 | 4字节的校验,在整个sector重复128遍,如何计算校验,见下 |
紧接着的后面12个sector,是前12个sector的backup!
exFAT文件系统最多2个FAT表,在Flags中指定了那个是Active的。用mkfs.exfat格式化,默认就1个FAT。exFAT的FAT表与FAT32一样。
A FAT shall describe cluster chains in the Cluster Heap. A cluster chain is a series of clusters which provides space for recording the contents of files, directories, and other file system structures.
A FAT represents a cluster chain as a singly-linked list of cluster indices
. With the exception of the first two entries, every entry in a FAT represents exactly one cluster.
每4字节表示一个cluster,前2个entry有点特殊,按照标准,值是固定的,如下:
$ sudo xxd -a -u -s$((512*2048)) -l512 /dev/sdc2
00100000: F8FF FFFF FFFF FFFF 0300 0000 0400 0000 ................
00100010: 0500 0000 FFFF FFFF FFFF FFFF FFFF FFFF ................
00100020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
001001f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
2 and ClusterCount + 1, inclusively
, which points to the next FatEntry in the given cluster chain; the given FatEntry shall not point to any FatEntry which precedes it in the given cluster chain。我理解这句话的意思是,这个cluster chain是递增的。FFFFFFF7h
, which marks the given FatEntry's corresponding cluster as bad
。FFFFFFFFh
, which marks the given FatEntry's corresponding cluster as the last cluster
of a cluster chain; this is the only valid value for the last FatEntry of any given cluster chain发现问题了吗?exFAT的FAT表,没有定义如何表示空闲cluster。
这一段就是一块块的cluster,历史原因,cluster的编号从2开始
,因此最后一个cluster的index是ClusterCount+1(实际计算偏移时,要减2)。前面解析root cluster编号是7,我们从7号cluster开始,offset为7-2=5
。
首先要搞懂Directory Entry这个多变的数据结构。
Directory Entry结构以32字节
为单位,除了文件和文件夹,Allocation Bitmap,Volume Label,Up-case Table等都使用这个Entry来定位。
这32个字节被粗分为4个部分:
struct generic_directory_entry{
uint8_t EntryType;
uint8_t CustomDefined[19];
uint32_t FirstCluster;
uint64_t DataLength;
};
第1个字节很关键,EntryType,详细定义看标准,下面简述:
0x00
,表示end-of-directory,表示从这里开始,后面就没有Entry了。[0x01 -- 0x7F]
,表示unused-directory-entry。[0x81 -- 0xFF]
,regular directory entry。EntryType这8个bit,被分成了4个部分:
entry sets
。主要EntryType:
EntryType=0x81
,表示Allocation Bitmap Directory EntryEntryType=0x82
,表示Up-case Table Directory EntryEntryType=0x83
,表示Volume Label Directory EntryEntryType=0x85
,表示File Directory EntryEntryType=0xC0
,表示Stream Extension Directory EntryEntryType=0xC1
,表示File Name Directory Entrystruct generic_primary_directory_entry{
uint8_t EntryType;
uint8_t SecondaryCount;
uint16_t SetChecksum;
uint16_t GeneralPrimaryFlags;
uint8_t CustomDefined[14];
uint32_t FirstCluster;
uint64_t DataLength;
};
struct generic_second_directory_entry{
uint8_t EntryType;
uint8_t GeneralSecondaryFlags;
uint8_t CustomDefined[18];
uint32_t FirstCluster;
uint64_t DataLength;
};
exFAT文件系统与FAT32显著不一样的地方,就是这个Allocation Bitmap。这是一块独立的区域,很可能会占用好几个cluster空间,专门用来记录cluster的占用情况。而FAT32文件系统,使用FAT表来记录,全0表示空闲。
In an exFAT volume, an Allocation Bitmap maintains the record of the allocation state of all clusters. This is a significant difference from exFAT's predecessors (FAT12, FAT16, and FAT32), in which a FAT maintained a record of the allocation state of all clusters in the Cluster Heap.
32字节的定义如下:
struct directory_entry{
uint8_t EntryType = 0x81;
uint8_t BitmapFlag;
uint8_t reserved[18];
uint32_t FirstCluster;
uint64_t DataLength;
};
BitmapFlag也只有第1个bit被用到:
先看看7号root cluster的内容:
$ sudo xxd -a -u -s$((512*10240+32768*(7-2))) -l512 /dev/sdc2
00528000: 8300 0000 0000 0000 0000 0000 0000 0000 ................
00528010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00528020: 8100 0000 0000 0000 0000 0000 0000 0000 ................
00528030: 0000 0000 0200 0000 54BA 0100 0000 0000 ........T.......
00528040: 8200 0000 0DD3 19E6 0000 0000 0000 0000 ................
00528050: 0000 0000 0600 0000 CC16 0000 0000 0000 ................
00528060: 0502 6F8D 2000 0000 8A33 C956 8A33 C956 ..o. ....3.V.3.V
00528070: 8A33 C956 7F7F 8080 8000 0000 0000 0000 .3.V............
00528080: 4001 0009 7501 0000 0000 0000 0000 0000 @...u...........
00528090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
005280a0: 4100 2E00 6400 6400 6400 6400 2E00 7300 A...d.d.d.d...s.
005280b0: 7700 7000 0000 0000 0000 0000 0000 0000 w.p.............
005280c0: 8502 77EC 2000 6F00 8C33 C956 8C33 C956 ..w. .o..3.V.3.V
005280d0: A233 C956 C1C1 8080 8000 0000 0000 0000 .3.V............
005280e0: C003 0004 2D28 0000 0B00 0000 0000 0000 ....-(..........
005280f0: 0000 0000 0900 0000 0B00 0000 0000 0000 ................
00528100: C100 6400 6400 6400 6400 0000 0000 0000 ..d.d.d.d.......
00528110: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00528120: 8502 1792 2000 0000 7632 C956 7632 C956 .... ...v2.Vv2.V
00528130: 7632 C956 4040 8080 8000 0000 0000 0000 v2.V@@..........
00528140: C001 0003 2BF8 0000 0000 0000 0000 0000 ....+...........
00528150: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00528160: C100 6300 6300 6300 0000 0000 0000 0000 ..c.c.c.........
00528170: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
005281f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
肉眼可见,第2个Entry,就是Allocation Bitmap:
00528020: 8100 0000 0000 0000 0000 0000 0000 0000 ................
00528030: 0000 0000 0200 0000 54BA 0100 0000 0000 ........T.......
>>> 905888/8
113236.0
>>> 905888/8/(1024*32)
3.4556884765625
一共需要4个cluster来存放Allocation Bitmap,现在看一下FAT表:
00100000: F8FF FFFF FFFF FFFF 0300 0000 0400 0000 ................
00100010: 0500 0000 FFFF FFFF FFFF FFFF FFFF FFFF ................
00100020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
即2,3,4,5号cluster被占用,5号cluster是最后一个,因此FAT表对应的值为全F。
最后看一下Allocation Bitmap里面的值:
$ sudo xxd -a -u -s$((512*10240+32768*(2-2))) -l512 /dev/sdc2
00500000: BF00 0000 0000 0000 0000 0000 0000 0000 ................
00500010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
005001f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
第1个字节为0xBF
,即0b1011 1111
前面解析出来的root cluster是7号,2,3,4,5用allocation bitmap,中间的6号是干什么?它叫做Up-case Table。
00528040: 8200 0000 0DD3 19E6 0000 0000 0000 0000 ................
00528050: 0000 0000 0600 0000 CC16 0000 0000 0000 ................
exFAT对于文件名的处理,大小写不敏感,但是保留大小写信息(跟FAT32一样)。实现方式就是这个up-case表,filename存放的值有两个含义:
比如a
,在filename存放0061
,同时将0061
当做up-case table的index,查到0041
,即大写A
。如此简单。
struct directory_entry{
uint8_t EntryType = 0x82; // Up-case Table
uint8_t reserved1[3];
uint32_t TableChecksum;
uint8_t reserved2[12];
uint32_t FirstCluster;
uint64_t DataLength;
};
关于checksum,推荐的表内容,请见标准。
这个方法有效的一个前提:这个世界上的所有语言,所有的存在大小写符号,数量并不多!
00528000: 8300 0000 0000 0000 0000 0000 0000 0000 ................
00528010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
struct directory_entry{
uint8_t EntryType = 0x83;
uint8_t CharacterCount;
uint8_t VolumeLabel[22];
uint8_t Reserved2[8];
};
CharacterCount
,[0 -- 11]
,表示unicode string的长度。开始分析具体目录和文件的存储方式。
$ ll /mnt/u2
total 64K
drwxr-xr-x. 2 xinlin xinlin 32K Jun 10 10:19 .
drwxr-xr-x. 1 root root 12 Jun 9 13:52 ..
-rwxr-xr-x. 1 xinlin xinlin 0 Jun 9 14:19 ccc
-rwxr-xr-x. 1 xinlin xinlin 11 Jun 9 14:28 dddd
...
005280c0: 8502 77EC 2000 6F00 8C33 C956 8C33 C956 ..w. .o..3.V.3.V
005280d0: A233 C956 C1C1 8080 8000 0000 0000 0000 .3.V............
005280e0: C003 0004 2D28 0000 0B00 0000 0000 0000 ....-(..........
005280f0: 0000 0000 0900 0000 0B00 0000 0000 0000 ................
00528100: C100 6400 6400 6400 6400 0000 0000 0000 ..d.d.d.d.......
00528110: 0000 0000 0000 0000 0000 0000 0000 0000 ................
dddd这个文件,对应3个entry,术语叫做Entry Set
。
struct directory_entry{
uint8_t EntryType = 0x85;
uint8_t SecondaryCount;
uint16_t SetChecksum;
uint16_t FileAttributes;
uint16_t Reserved1;
uint32_t CreateTimestamp;
uint32_t LastModifiedTimestamp;
uint32_t LastAccessedTimestamp;
uint8_t Create10msIncrement;
uint8_t LastModified10msIncrement;
uint8_t CreateUtcOffset;
uint8_t LastModifiedUtcOffset;
uint8_t LastAccessedUtcOffset;
uint8_t Reserved2[7];
};
SecondaryCount
,secondary directory entry的数量,此例为0x02
,即后面有两块secondary entry。SetChecksum
,校验整个entry set。FileAttributes
,属性,16个bit的解释:其它全是各种时间。比FAT32多的是UTC offset。32bit的Timestamp如何解析,参考标准。
Stream Extension Entry
struct directory_entry{
uint8_t EntryType = 0xC0; // Stream Extension
uint8_t GeneralSecondaryFlags;
uint8_t Reserved1;
uint8_t NameLength;
uint16_t NameHash;
uint16_t Reserved2;
uint64_t ValidDataLength;
uint32_t Reserved3;
uint32_t FirstCluster;
uint64_t DataLength;
};
GeneralSecondaryFlags
,8个bit解析如下:NoFatChain
,如果是0,正常解析FAT表中的cluster chain,如果是1,忽略FAT表中的信息,此时分配的是一整块连续的多个cluster,计算方法就是用DataLength除以cluster的size,round up to the nearest integer。NameLength
,[1 -- 255]
,名字最长255,unicode string,这个字段的值,决定了File Name Directory Entry的数量。NameHash
,2字节大写文件名的hash值,用快速查找,所有匹配项都应该用大写进行比较,标准定义了hash算法。ValidDataLength
,8字节,一般与DataLength相等。FirstCluster
,DataLength
,8字节,突破了FAT32文件4G的限制。对于目录而言,标准规定最大256MB。File Name Entry
struct directory_entry{
uint8_t EntryType = 0xC1; // File Name
uint8_t GeneralSecondaryFlags;
uint8_t FileName[30];
};
每个File Name Entry可以最多存放15个符号(unicode),因此,文件名越长,需要的entry数量就越多。文件名最长255个unicode符号,即17个entry。
最后看一下这个示例文件dddd所在的9号cluster的内容:
$ cat /mnt/u2/dddd
1234567890
$ sudo xxd -a -u -s$((512*10240+32768*7)) -l32 /dev/sdc2
00538000: 3132 3334 3536 3738 3930 0A00 0000 0000 1234567890......
00538010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
接上一节,如果将dddd文件删除,硬盘中的数据会出现哪些变化?可以预料的是,文件内容还在9号扇区中,只是root cluster中的一些entry数据会发生变化,FAT表的内容也不会有啥变化。
# 删除之前的root cluster
005280c0: 8502 77EC 2000 6F00 8C33 C956 8C33 C956 ..w. .o..3.V.3.V
005280d0: A233 C956 C1C1 8080 8000 0000 0000 0000 .3.V............
005280e0: C003 0004 2D28 0000 0B00 0000 0000 0000 ....-(..........
005280f0: 0000 0000 0900 0000 0B00 0000 0000 0000 ................
00528100: C100 6400 6400 6400 6400 0000 0000 0000 ..d.d.d.d.......
00528110: 0000 0000 0000 0000 0000 0000 0000 0000 ................
# 删除后的
005280c0: 0502 2DED 2000 6F00 8C33 C956 8C33 C956 ..-. .o..3.V.3.V
005280d0: E738 CC56 C1C1 8080 8000 0000 0000 0000 .8.V............
005280e0: 4003 0004 2D28 0000 0B00 0000 0000 0000 @...-(..........
005280f0: 0000 0000 0900 0000 0B00 0000 0000 0000 ................
00528100: 4100 6400 6400 6400 6400 0000 0000 0000 A.d.d.d.d.......
00528110: 0000 0000 0000 0000 0000 0000 0000 0000 ................
变化:
对EntryType的变化,都是将最高位直接置0。其它都没有变化,FAT表依然是0,9号cluster的内容没有变化:
$ sudo xxd -a -u -s$((512*10240+32768*7)) -l10 /dev/sdc2
00538000: 3132 3334 3536 3738 3930 1234567890
参考:mkfs.exfat命令
创建一个名为abc(小写)的目录:
00528060: 8502 3682 1000 0000 651A CD56 081E CD56 ..6.....e..V...V
00528070: 081E CD56 9398 8080 8000 0000 0000 0000 ...V............
00528080: C003 0003 2BC8 0000 0080 0000 0000 0000 ....+...........
00528090: 0000 0000 0800 0000 0080 0000 0000 0000 ................
005280a0: C100 6100 6200 6300 0000 0000 0000 0000 ..a.b.c.........
005280b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
8号cluster,长度为2048,但此时目录为空,且全0。这里看到的是abc小写,到up-case table中查表,得到ABC大写。
0040h 0040h 0041h 0042h 0043h
0060h 0060h 0041h 0042h 0043h
如果创建大写的ABC,查表得到的还是大写。
本文链接:https://cs.pynote.net/hd/hdisk/202306081/
-- EOF --
-- MORE --