文件的删除
在前面已经说过如何通过BPB里的各项参数去找到Data Area,从而得到文件对应的Directory Entry,最后找到文件的内容;对于目录,也是大同小异,不同之处只是更“曲折”一点,会先找到目录,去目录的“内容”里找到文件的Directory Entry,进一步,才可以找到文件内容。那么,在FAT32里,文件如何删除?
实际上非常简单,FAT32文件系统在删除文件的时候,仅仅是对其文件名进行处理,对于内容是不做任何处理的。对文件名的处理,就是把其所相关的所有Directory Entry(参考篇二的Long Name Entry)的第一个byte都置为0xE5,此时就认为该文件已经被删除了。还是用FAT32的image为例来观察:
首先用dd命令创建一个空的文件,然后用mkfs.vfat对其格式化,接着挂载到/mnt/目录,后面创建一个长文件名的文件,叫做abcdefghijklmnopqrstuvxwyz.1234567890,里面的内容是通过“echo "just a test string for this long name file" >> abcdefghijklmnopqrstuvxwyz.1234567890” 完成的。下图是test.img的内容:
接下来就是把它删除之后的状态,如下图:
很容易可以看到,从0x9e000 - 0x9e070一共4个Directory entry的第一个字符都变成0xE5了,而它的文件内容在0x9e200的地方并没有任何改变。
目录的删除
对于文件的删除是把它相关的directory entry第一个bytes全部置为0xE5,那么,删除目录的时候,是不是把目录相关的directory entry以及它所包含的文件的directory entry第一个bytes全部置为0xE5呢?以实验为例
mkdir test
cd /test
touch 1.txt
touch 2.txt
echo 12345 >> 1.txt
echo abcde >> 2.txt
cd ~
umount /mnt/
下图是以上步骤之后image的内容:
可以看到,test这个目录仍然是在0x9e000的地方,这是因为之前的文件已经被删除,因此这里的空间是可用的,test目录的内容在簇4,也就是0x9e400,它包括目录“.",目录"..",文件”1.txt",文件“2.txt”。接下来就来删除。
下图是删除test目录之后,image的内容:
可以看到,确实和预料的一样,
0x9e000和0x9e020这两个对应test目录的directory entry里,第一个byte都被置为0xE5;
同时,0x9e440和0x9e460这两个对应1.txt的directory entry第一个byte也被置为0xE5,
0x9e480和0x9e4a0这两个对应2.txt的directory entry第一个byte也被置为0xE5。
FAT32表的用途
在之前所有的内容里,都没有用到FAT32表,那是因为目前为止所有实验中产生的文件大小都很小,小于一个簇的大小,还用不到FAT32表。当文件大小超过一个簇的大小时,从该文件的directory entry里能知道该文件的内容位于哪个簇,那个簇的内容读完之后,接下来要去哪个簇读取文件剩下的内容?此时就需要去FAT32表里查找。
假设一个文件的size是3个簇的大小,这个文件依次放在簇4,5,7里面。那么,在簇4所对应的FAT32表项里,就会填入5;而簇5所对应的FAT32表项里则会填入7;簇7就已经可以把该文件剩余部分全部存放完,不需要再链接到下一个簇,簇7所对应的FAT32表项里就会填入0xFFFFFFFF,表示EOC(End Of Clusterchain)
FsInfo的作用
目前为止,发现在FsInfo里最有用的就是offset 0x1EC,FSI_Nxt_Free,用来指明下一个可用的cluster在哪里。如果没有这个指针,每次需要存储新的内容时,都要对整个FAT32进行一次扫描,这样太浪费时间,没有效率。在FSI_Nxt_Free的帮助下就可以省却这个扫描的步骤,直接跳到那个cluster去进行存放。当然,在前面还是要经过一些其他的检验,例如size是否足够,是否有坏簇之类的。