Last Updated: 2023-06-26 09:26:11 Monday
-- TOC --
理解了分区,接下来自然就到了格式化文件系统了。而学习文件系统的开始,一定是FAT系列。它年代最久,最早可追溯到比尔盖茨发明BASIC语言的时候(FAT8),也最简单,兼容性最好。
Windows系统进行文件操作时并非以扇区为单位,而是簇(cluster),簇是系统进行硬盘空间读写的最小单位,一个簇可以包含多个扇区。(现在硬盘扇区的实际size不再是512Bytes,参考:4K对齐)
FAT文件系统整体结构如下:
BPB|Info|Backup|
Reserved | FAT | Data
BPB,info,backup这些扇区都包含在reserved区域中。
FAT分区的第一块扇区,512字节,叫做BPB,Bios Parameter Block
,常常称BPB为FAT文件系统的引导扇区。
从Grub项目的fat.h中查到bpb的结构:
struct grub_fat_bpb
{
grub_uint8_t jmp_boot[3];
grub_uint8_t oem_name[8];
grub_uint16_t bytes_per_sector;
grub_uint8_t sectors_per_cluster;
grub_uint16_t num_reserved_sectors;
grub_uint8_t num_fats; /* 0x10 */
grub_uint16_t num_root_entries;
grub_uint16_t num_total_sectors_16;
grub_uint8_t media; /* 0x15 */
grub_uint16_t sectors_per_fat_16;
grub_uint16_t sectors_per_track; /* 0x18 */
grub_uint16_t num_heads; /* 0x1A */
grub_uint32_t num_hidden_sectors; /* 0x1C */
grub_uint32_t num_total_sectors_32; /* 0x20 */
union
{
struct
{
grub_uint8_t num_ph_drive;
grub_uint8_t reserved;
grub_uint8_t boot_sig;
grub_uint32_t num_serial;
grub_uint8_t label[11];
grub_uint8_t fstype[8];
} GRUB_PACKED fat12_or_fat16;
struct
{
grub_uint32_t sectors_per_fat_32;
grub_uint16_t extended_flags;
grub_uint16_t fs_version;
grub_uint32_t root_cluster;
grub_uint16_t fs_info;
grub_uint16_t backup_boot_sector;
grub_uint8_t reserved[12];
grub_uint8_t num_ph_drive;
grub_uint8_t reserved1;
grub_uint8_t boot_sig;
grub_uint32_t num_serial;
grub_uint8_t label[11];
grub_uint8_t fstype[8];
} GRUB_PACKED fat32;
} GRUB_PACKED version_specific;
} GRUB_PACKED;
下面是读取U盘中一块FAT32分区的BPB扇区的内容:
$ sudo xxd -a -u -l512 /dev/sdc1
00000000: EB58 906D 6B66 732E 6661 7400 0220 2000 .X.mkfs.fat.. .
00000010: 0200 0000 00F8 0000 2000 4000 0008 0000 ........ .@.....
00000020: 00D0 9403 6039 0000 0000 0000 0200 0000 ....`9..........
00000030: 0100 0600 0000 0000 0000 0000 0000 0000 ................
00000040: 8000 29CD FA6B 824E 4F20 4E41 4D45 2020 ..)..k.NO NAME
00000050: 2020 4641 5433 3220 2020 0E1F BE77 7CAC FAT32 ...w|.
00000060: 22C0 740B 56B4 0EBB 0700 CD10 5EEB F032 ".t.V.......^..2
00000070: E4CD 16CD 19EB FE54 6869 7320 6973 206E .......This is n
00000080: 6F74 2061 2062 6F6F 7461 626C 6520 6469 ot a bootable di
00000090: 736B 2E20 2050 6C65 6173 6520 696E 7365 sk. Please inse
000000a0: 7274 2061 2062 6F6F 7461 626C 6520 666C rt a bootable fl
000000b0: 6F70 7079 2061 6E64 0D0A 7072 6573 7320 oppy and..press
000000c0: 616E 7920 6B65 7920 746F 2074 7279 2061 any key to try a
000000d0: 6761 696E 202E 2E2E 200D 0A00 0000 0000 gain ... .......
000000e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
000001f0: 0000 0000 0000 0000 0000 0000 0000 55AA ..............U.
grub_uint8_t jmp_boot[3]
,应该不用关心grub_uint8_t oem_name[8]
,清晰可见,mkfs.fat,这是格式化工具的名称grub_uint16_t bytes_per_sector
, 0x0200,即512,都是little endiangrub_uint8_t sectors_per_cluster
,0x20,即32,每个cluster有32个512扇区,即每cluster大小为16KB(是不是大了点...这个值可以用mkfs.fat命令指定)grub_uint16_t num_reserved_sectors
,0x0020,32,保留扇区数32,这个数字包含了此引导扇区grub_uint8_t num_fats
,0x02,FAT表个数,默认是2,有个备份grub_uint16_t num_root_entries
,0x0000,FAT32为0,FAT12/16表示根目录中entry数量grub_uint16_t num_total_sectors_16
,0x0000,FAT32为0,FAT12/16表示扇区总数grub_uint8_t media
,0xF8,储存介质grub_uint16_t sectors_per_fat_16
,0x0000,FAT32为0,FAT12/16表示每个FAT表占用扇区数grub_uint16_t sectors_per_track
,0x0020,32,每磁道扇区数,应该没啥意义了grub_uint16_t num_heads
,0x0040,64,磁头数,who caregrub_uint32_t num_hidden_sectors
,0x00000800,2048grub_uint32_t num_total_sectors_32
,0x0394D000,60084224,这块分区的扇区总数最后这两个数字,看起来像似跟下面显示出来的数字对应的:
Device Start End Sectors Size Type
/dev/sdc1 2048 60086271 60084224 28.7G Linux filesystem
接着解析union.fat32:
grub_uint32_t sectors_per_fat_32
,0x00003960,14688,每个FAT32表所占扇区数grub_uint16_t extended_flags
,0x0000,扩展flaggrub_uint16_t fs_version
,0x0000,版本号grub_uint32_t root_cluster
,0x00000002,root cluster号,总是2,根目录开始的clustergrub_uint16_t fs_info
,0x0001,文件系统info所在扇区,一般都是1,紧挨着此引导扇区grub_uint16_t backup_boot_sector
,0x0006,备份引导扇区位置,这里boot是指boot file system,6是从0开始编号的index,默认是6。7号扇区是fs_info的备份。grub_uint8_t reserved[12]
,全0,保留12字节grub_uint8_t num_ph_drive
,0x80,grub_uint8_t reserved1
,0x00,保留grub_uint8_t boot_sig
,0x29,grub_uint32_t num_serial
,0x826BFACD,序列号,这个值被lsblk -f
命令当做UUID了。grub_uint8_t label[11]
,清晰可见,NO NAMEgrub_uint8_t fstype[8]
,清晰可见,FAT32Windows系统查看U盘此分区的总容量,刚好等于:
>>> # (总扇区数 - 保留扇区数 - 两张FAT表所用扇区数) * 512
>>> (60084224-32-14688*2)*512
30748065792
在Windows系统查看小文件的空间占用情况,大小是实际字节数,而占用空间,是cluster size的倍数。
紧挨着BPB(0号),就是fs_info所在的1号扇区。fs_info扇区也有备份,在BPB备份扇区后面,默认是7。fs_info里面记录了FAT文件系统的两个重要信息:
$ sudo xxd -a -u -s512 -l512 /dev/sdc1
00000200: 5252 6141 0000 0000 0000 0000 0000 0000 RRaA............
00000210: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
000003e0: 0000 0000 7272 4161 75A1 1C00 7601 0000 ....rrAau...v...
000003f0: 0000 0000 0000 0000 0000 0000 0000 55AA ..............U.
RRaA
72724161
,就是rrAa
做个算术题:
>>> (60084224-32-14688*2)/32 # total cluster number
1876713.0
>>> 1876341+374-2
1876713
0号和1号,只在FAT表中存在,没有真实的cluster对应。
保留扇区之后,就是两个一模一样的FAT表。
FAT表内存放的,是每个cluster的使用情况,用4个字节表示,即每4字节表示一个cluster,依然是little endian:
0x00000000
,空闲cluster0x00000001
,保留cluster0x00000002 -- 0x0FFFFFEF
,被占用cluster,其值表示next cluster,以此形成cluster chain0x0FFFFFF0 -- 0x0FFFFFF6
,保留值0x0FFFFFF7
,坏cluster0x0FFFFFF8 -- 0x0FFFFFFF
,表示last cluster$ sudo xxd -a -u -s$((512*32)) -l32 /dev/sdc1
00004000: F8FF FF0F FFFF FFFF F8FF FF0F FFFF FF0F ................
00004010: FFFF FF0F FFFF FF0F 2101 0000 FFFF FF0F ........!.......
0x0FFFFFF8
0xFFFFFFFF
0x0FFFFFF8
,说明根目录所占用空间,没有超过一个cluster的容量备份FAT拥有完全一样的值:
$ sudo xxd -a -u -s$((512*(32+14688))) -l32 /dev/sdc1
00730000: F8FF FF0F FFFF FFFF F8FF FF0F FFFF FF0F ................
00730010: FFFF FF0F FFFF FF0F 2101 0000 FFFF FF0F ........!.......
下面来做一道小学数学题:
>>> 14688*512//4
1880064
>>> 1880064-1876713
3351
FAT表可以表达的cluster数量,超过了总的cluster数量,超的还不少...?
跳过保留区和两个FAT表的区域,就是数据区了。
$ sudo mount /dev/sdd1 /mnt/u
$ ll /mnt/u
total 224K
drwxr-xr-x. 5 root root 16K Jan 1 1970 .
drwxr-xr-x. 1 root root 8 Jun 1 09:44 ..
drwxr-xr-x. 3 root root 16K Jun 4 20:28 EFI
drwxr-xr-x. 4 root root 16K Jun 4 18:33 grub
-rwxr-xr-x. 1 root root 136K Jun 4 18:33 grubx64.efi
drwxr-xr-x. 2 root root 16K Jun 6 13:57 'System Volume Information'
-rwxr-xr-x. 1 root root 6 Jun 6 16:01 test.txt
$ sudo xxd -a -u -s$((512*(32+14688*2))) -l512 /dev/sdd1
00e5c000: 4167 0072 0075 0062 0000 000F 008F FFFF Ag.r.u.b........
00e5c010: FFFF FFFF FFFF FFFF FFFF 0000 FFFF FFFF ................
00e5c020: 4752 5542 2020 2020 2020 2010 0017 2C94 GRUB ...,.
00e5c030: C456 C456 0000 2D94 C456 0300 0000 0000 .V.V..-..V......
00e5c040: 4546 4920 2020 2020 2020 2010 0026 2C94 EFI ..&,.
00e5c050: C456 C456 0000 8EA3 C456 0400 0000 0000 .V.V.....V......
00e5c060: 4167 0072 0075 0062 0078 000F 0067 3600 Ag.r.u.b.x...g6.
00e5c070: 3400 2E00 6500 6600 6900 0000 0000 FFFF 4...e.f.i.......
00e5c080: 4752 5542 5836 3420 4546 4920 0072 2D94 GRUBX64 EFI .r-.
00e5c090: C456 C756 0000 2D94 C456 6B01 0020 0200 .V.V..-..Vk.. ..
00e5c0a0: 4220 0049 006E 0066 006F 000F 0072 7200 B .I.n.f.o...rr.
00e5c0b0: 6D00 6100 7400 6900 6F00 0000 6E00 0000 m.a.t.i.o...n...
00e5c0c0: 0153 0079 0073 0074 0065 000F 0072 6D00 .S.y.s.t.e...rm.
00e5c0d0: 2000 5600 6F00 6C00 7500 0000 6D00 6500 .V.o.l.u...m.e.
00e5c0e0: 5359 5354 454D 7E31 2020 2016 0031 3A6F SYSTEM~1 ..1:o
00e5c0f0: C656 C656 0000 3B6F C656 7501 0000 0000 .V.V..;o.Vu.....
00e5c100: 4174 0065 0073 0074 002E 000F 008F 7400 At.e.s.t......t.
00e5c110: 7800 7400 0000 FFFF FFFF 0000 FFFF FFFF x.t.............
00e5c120: 5445 5354 2020 2020 5458 5420 0079 3080 TEST TXT .y0.
00e5c130: C656 C756 0000 3080 C656 7901 0600 0000 .V.V..0..Vy.....
00e5c140: E52E 0074 0065 0073 0074 000F 00A1 2E00 ...t.e.s.t......
00e5c150: 7400 7800 7400 2E00 7300 0000 7700 7000 t.x.t...s...w.p.
00e5c160: E545 5354 5458 7E31 5357 5020 0016 2F80 .ESTTX~1SWP ../.
00e5c170: C656 C656 0000 2F80 C656 7801 0010 0000 .V.V../..Vx.....
00e5c180: E574 0065 0073 0074 002E 000F 008D 7400 .t.e.s.t......t.
00e5c190: 7800 7400 7E00 0000 FFFF 0000 FFFF FFFF x.t.~...........
00e5c1a0: E545 5354 7E31 2020 5458 5420 0079 3080 .EST~1 TXT .y0.
00e5c1b0: C656 C656 0000 3080 C656 0000 0000 0000 .V.V..0..V......
00e5c1c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
00e5c1f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
2号root cluster紧挨在两张FAT表后面。
root cluster是分区根目录,目录中的数据,按32字节划分entry。这32自己的结构如下:
struct grub_fat_dir_entry
{
grub_uint8_t name[11];
grub_uint8_t attr;
grub_uint8_t nt_reserved;
grub_uint8_t c_time_tenth;
grub_uint16_t c_time;
grub_uint16_t c_date;
grub_uint16_t a_date;
grub_uint16_t first_cluster_high;
grub_uint16_t w_time;
grub_uint16_t w_date;
grub_uint16_t first_cluster_low;
grub_uint32_t file_size;
} GRUB_PACKED;
用这两行(32字节)数据来解释:
00e5c120: 5445 5354 2020 2020 5458 5420 0079 3080 TEST TXT .y0.
00e5c130: C656 C756 0000 3080 C656 7901 0600 0000 .V.V..0..Vy.....
grub_uint8_t name[11]
,11字节,8.3名称,短文件名,前8个字节存名字,后3个字节存后缀grub_uint8_t attr
,1字节,属性,有子目录标志grub_uint8_t nt_reserved
,1字节,系统保留grub_uint8_t c_time_tenth
,1字节,创建时间的10毫秒位,0x79*10 = 1210
毫秒,创建时间精度为10毫秒grub_uint16_t c_time
,2字节,创建时间,见下grub_uint16_t c_date
,2字节,创建日期,见下grub_uint16_t a_date
,2字节,最后访问日期grub_uint16_t first_cluster_high
,2字节,cluster高2字节,0x0000
grub_uint16_t w_time
,2字节,最后修改时间grub_uint16_t w_date
,2字节,最后修改日期grub_uint16_t first_cluster_low
,2字节,cluster低2字节,0x7901
grub_uint32_t file_size
,4字节,size,文件夹的size为全0,文件最大size是4G-1,此处size为0x00000006,即6bytes两部分cluster拼在一起为,0x00000179
,即377,直接看看377号cluster的内容:
$ sudo xxd -a -u -s$((512*(32+14688*2)+32*512*(377-2))) -l512 /dev/sdd1
01438000: 6961 6161 610A 0000 0000 0000 0000 0000 iaaaa...........
01438010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
014381f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
长度刚好是6个字节!
FAT表的377号为:
$ sudo xxd -a -u -s$((512*32+377*4)) -l4 /dev/sdd1
000045e4: FFFF FF0F ....
0x0FFFFFFF,表示这是last cluster。如果文件size超过了一个cluster的容量,这个位置记录的就是next cluster,以此类推。
属性
1字节,6个属性:
创建时间为0x8030,二进制为1000 0000 0011 0000
,表示时间(加上毫秒进位)16时1分17秒(210毫秒):
创建日期为0x56C6,二进制为0101 0110 1100 0110
,表示日期2023年6月6日:
最后访问日期的计算与创建日期相同,最后修改时间和最后修改日期的计算同上。
当我在root cluster中touch一个新的空文件t2后,能看到出现了一个新的entry:
00e5c160: 5432 2020 2020 2020 2020 2020 00C7 D46D T2 ...m
00e5c170: C756 C756 0000 D46D C756 0000 0000 0000 .V.V...m.V......
size为0,也cluster全0。
文件夹Entry
下面是grub目录的entry数据:
00e5c020: 4752 5542 2020 2020 2020 2010 0017 2C94 GRUB ...,.
00e5c030: C456 C456 0000 2D94 C456 0300 0000 0000 .V.V..-..V......
size为0,cluster是0x00000003,即3号cluster(紧挨着FAT后面的是2号cluster):
$ ll /mnt/u/grub
total 96K
drwxr-xr-x. 4 root root 16K Jun 4 18:33 .
drwxr-xr-x. 5 root root 16K Jan 1 1970 ..
drwxr-xr-x. 2 root root 16K Jun 4 18:33 fonts
-rwxr-xr-x. 1 root root 1.0K Jun 4 18:33 grubenv
drwxr-xr-x. 2 root root 32K Jun 4 18:33 x86_64-efi
$ sudo xxd -a -u -s$((512*(32+14688*2)+512*32*(3-2))) -l512 /dev/sdd1
00e60000: 2E20 2020 2020 2020 2020 2010 0017 2C94 . ...,.
00e60010: C456 C456 0000 2C94 C456 0300 0000 0000 .V.V..,..V......
00e60020: 2E2E 2020 2020 2020 2020 2010 0017 2C94 .. ...,.
00e60030: C456 C456 0000 2C94 C456 0000 0000 0000 .V.V..,..V......
00e60040: 4178 0038 0036 005F 0036 000F 00CF 3400 Ax.8.6._.6....4.
00e60050: 2D00 6500 6600 6900 0000 0000 FFFF FFFF -.e.f.i.........
00e60060: 5838 365F 3634 7E31 2020 2010 0027 2C94 X86_64~1 ..',.
00e60070: C456 C456 0000 2D94 C456 0600 0000 0000 .V.V..-..V......
00e60080: 4166 006F 006E 0074 0073 000F 009A 0000 Af.o.n.t.s......
00e60090: FFFF FFFF FFFF FFFF FFFF 0000 FFFF FFFF ................
00e600a0: 464F 4E54 5320 2020 2020 2010 0029 2D94 FONTS ..)-.
00e600b0: C456 C456 0000 2D94 C456 5701 0000 0000 .V.V..-..VW.....
00e600c0: E567 0072 0075 0062 0065 000F 002D 6E00 .g.r.u.b.e...-n.
00e600d0: 7600 2E00 6E00 6500 7700 0000 0000 FFFF v...n.e.w.......
00e600e0: E552 5542 454E 5620 4E45 5720 0029 2D94 .RUBENV NEW .)-.
00e600f0: C456 C456 0000 2D94 C456 5801 0004 0000 .V.V..-..VX.....
00e60100: 4167 0072 0075 0062 0065 000F 00D8 6E00 Ag.r.u.b.e....n.
00e60110: 7600 0000 FFFF FFFF FFFF 0000 FFFF FFFF v...............
00e60120: 4752 5542 454E 5620 2020 2020 0029 2D94 GRUBENV .)-.
00e60130: C456 C756 0000 2D94 C456 5801 0004 0000 .V.V..-..VX.....
00e60140: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
00e601f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
上一节的数据,多少看着有些怪异,那是因为除了存在短文件名entry之外,还有长文件名entry。这是FAT32增加的特性。
struct grub_fat_long_name_entry
{
grub_uint8_t id;
grub_uint16_t name1[5];
grub_uint8_t attr;
grub_uint8_t reserved;
grub_uint8_t checksum;
grub_uint16_t name2[6];
grub_uint16_t first_cluster;
grub_uint16_t name3[2];
} GRUB_PACKED;
同样是32字节。
FAT32文件系统,长短文件名共存!
为了兼容低版本的OS或程序能正确读取长文件名文件,系统自动为所有长文件名文件创建了一个对应的短文件名,使对应数据既保存长文件名,也保存短文件名。不支持长文件名的OS或程序会忽略它认为不合法的长文件名Entry,而支持长文件名的OS或程序则会以长文件名为显式项来记录和编辑,并隐藏起短文件名。(测试发现,创建短文件名时,也会同时增加长文件名对应的entry。)
分析下面这段Entry数据:
00e5c0a0: 4220 0049 006E 0066 006F 000F 0072 7200 B .I.n.f.o...rr.
00e5c0b0: 6D00 6100 7400 6900 6F00 0000 6E00 0000 m.a.t.i.o...n...
00e5c0c0: 0153 0079 0073 0074 0065 000F 0072 6D00 .S.y.s.t.e...rm.
00e5c0d0: 2000 5600 6F00 6C00 7500 0000 6D00 6500 .V.o.l.u...m.e.
00e5c0e0: 5359 5354 454D 7E31 2020 2016 0031 3A6F SYSTEM~1 ..1:o
00e5c0f0: C656 C656 0000 3B6F C656 7501 0000 0000 .V.V..;o.Vu.....
这段数据一共包含3个entry项,前2个是长名Entry,后1个是短名Entry。完成的名称是System Volume Information
。这3项Entry,只对应了一个文件(夹)。
grub_uint8_t id
,上例中,0x42,0b0100 0010
,第7位值为1,表示这是最后一项Entry,低5位是顺序,0b00010
,值2,这才是id,表示这是第2项Entry。组合在一起:这是第2项Entry,并且是最后一项。紧着着的Entry,这个id字段的值为0x01
,这不是最后一项,只是第1项。长名Entry是倒序排列的!unicode编码,最后才是短名Entry。grub_uint8_t attr
,与短文件名entry位置一致,值为0x0F
,表示这是长文件Entry,这个值对于短文件Entry来说,是个错误的值,因此代码可以区分。grub_uint8_t checksum
,见下grub_uint16_t first_cluster
,全0长名Entry里面都是名字的unicode编码,没啥具体信息,具体信息还是要分析最后的短名Entry。
checksum
checksum的作用,是确保长Entry与短Entry是对应起来的,checksum的值通过短Entry中11个字节的name计算出来,计算方法如下:
#include <stdio.h>
int main(void) {
unsigned char cks = 0;
char *name = "SYSTEM~1 ";
for(int i=0; i<11; ++i)
cks = ((cks>>1) | (cks<<7)) + name[i];
printf("0x%x\n", cks);
return 0;
}
输出:0x72,与上面的数据对应!两个长Entry的checksum都是72。
看出来了吧,FAT32文件系统中,短名全是大写!长名才分大小写!
Windows系统文件路径不区分大小写的由来,恐怕就是这里。
FAT32文件系统,没有任何权限相关的信息。
参考:mkfs.fat命令
至此,FAT系列文件系统学习到这里,就差不多了,基本上主要关注FAT32。
读取扇区,就是fopen,正常读,sudo执行。下来尝试一下如何直接写入字节到扇区。
在FAT32分区中,创建一个文件,名abc,内容1234567890
。
下面是此文件的Entry,一长一短:
00204060: 4161 0062 0063 0000 00FF FF0F 0074 FFFF Aa.b.c.......t..
00204070: FFFF FFFF FFFF FFFF FFFF 0000 FFFF FFFF ................
00204080: 4142 4320 2020 2020 2020 2020 0068 A248 ABC .h.H
00204090: C956 C956 0000 A248 C956 0700 0B00 0000 .V.V...H.V......
此文件存放的cluster号为0x00000007,即7号。文件长度0x0000000B,即10Bytes。
确认一下位置:
$ sudo xxd -a -u -s$((512*(32+2048*2)+4096*(7-2))) -l16 /dev/sdc1
00209000: 3132 3334 3536 3738 3930 0A00 0000 0000 1234567890......
没错,就是这里。现在开始尝试直接修改这部分,用sudo进Python Shell:
>>> f = open('/dev/sdc1', 'rb+') # rb+
>>> offset = 512*(32+2048*2) + 4096*(7-2)
>>> f.seek(offset)
2134016
>>> f.read(10)
b'1234567890' # nice
>>> f.seek(offset)
2134016
>>> f.write(b'555')
3
>>> f.close()
用rb+
打开设备文件,可读可写。检查写入效果:
$ sudo xxd -a -u -s$((512*(32+2048*2)+4096*(7-2))) -l16 /dev/sdc1
00209000: 3535 3534 3536 3738 3930 0A00 0000 0000 5554567890......
Nice....:)
如果用cat命令查看abc文件内容,注意有缓存,重新mount之后再看。
接着上面一节,继续测试,现在将abc文件用rm命令删除,查看Entry:
00204060: E561 0062 0063 0000 00FF FF0F 0074 FFFF .a.b.c.......t..
00204070: FFFF FFFF FFFF FFFF FFFF 0000 FFFF FFFF ................
00204080: E542 4320 2020 2020 2020 2020 0068 A248 .BC .h.H
00204090: C956 C956 0000 A248 C956 0700 0B00 0000 .V.V...H.V......
变化的仅仅是两个Entry的第1个字节,都变成了0xE5
。
文件内容部分也没有变化:
$ sudo xxd -a -u -s$((512*(32+2048*2)+4096*(7-2))) -l16 /dev/sdc1
00209000: 3535 3534 3536 3738 3930 0A00 0000 0000 5554567890......
查看FAT表,全0,已是空闲状态:
$ sudo xxd -a -u -s$((512*32+4*7)) -l4 /dev/sdc1
0000401c: 0000 0000
这就是删除文件的本质,只是在Entry上设置了一个标志(注意:不同文件系统,这里的细节肯定会不一样)。了解了删除的本质,也就理解了,有一些文件是可以恢复的。
恢复的过程可以这样:
但是,如果被删除的文件很长,占用了好多个cluster,只有第1个cluster可以顺利恢复出来。其它的cluster位置信息已经丢失了。此时,可以尝试通过文件size来计算一共占用了多少cluster,也许下一个空闲cluster就是(连续存储)。(从这个角度来看,扩大cluster的size还有点意义)
恢复数据不一定需要写入硬盘扇区,完全可以将恢复出来的数据存在别处。
本文链接:https://cs.pynote.net/hd/hdisk/202306061/
-- EOF --
-- MORE --