目录项的作用及结构特点
目录项对于FAT文件系统来讲也是很重要的一个组成部分,其主要作用及结构特点如下(如果没有特别说明,以下的作用和特点适用于FAT12、FAT16及FAT32文件系统中的目录项)。
(1)分区中的每个文件和文件夹(也称为目录)都被分配一个大小为32字节的目录项,用以描述文件或文件夹的属性、大小、起始簇号和时间、日期等信息,当然还会把文件名或目录名也记录在目录项中。
(2)在FAT文件系统中,目录被视为特殊类型的文件,所以每个目录也跟文件一样有目录项。
(3)在FAT16文件系统下,分区根目录下的文件及文件夹的目录项存放在FDT中,分区子目录下的文件及文件夹的目录项存放在数据区相应的簇中。
(4)根据目录项的作用和结构特点,可以把目录项分为四类:
①短文件名目录项;
②长文件名目录项;
③“.”目录项和“..”目录项;
④卷标目录项。
短文件名目录项
所谓短文件名是指DOS和Windows 3.x时代文件名的传统格式,即“8.3”格式。在这种格式的限制下,用户在给文件起名时,主文件名不能超过8个字符,并且不能支持中文;扩展名不能超过3个字符,所以称为“8.3”格式。在这种格式下,文件目录项中只需要8+3=11字节就可以记录文件名了(主文件名和扩展名之间的“.”是默认的,不用记录),这种格式的目录项也就称为短文件名目录项。
下面看一个具体的短文件名目录项,如图4-232所示。
图4-232 短文件名目录项
图4-232所示是两条文件目录项,每条目录项占32字节,从WinHex中看也就是两行数据。短文件名目录项的含义见表4-23。
表4-23 FAT16短文件名目录项的含义
另外WinHex的模板管理器中也提供模板可以查看文件目录项的结构。这里以图4-232中的第二条目录项为例,将光标放在第二条目录项的第一字节上,然后打开模板管理器,选择短文件名目录项的模板,如图4-233所示。
图4-233 选中短文件名目录项的模板
双击选中的模板,就能看见该目录项各字节的含义了,如图4-234所示。
图4-234 短文件名目录项的模板
下面对这些参数做详细分析。
(1)主文件名(00~07H)
这是主文件名,共占8字节,如果文件名用不完8字节,后面用空格(十六进制数值为20H)填充。在当前例子中,主文件名为“FAT16”。
另外该位置的第一字节也用来表示目录项的分配状态:当这个字节是“00”时,表示该目录项从未使用过;当这个字节是“E5”时,表示该目录项曾经使用过,但目前已经被删除。
(2)文件的扩展名(08H~0AH)
文件的扩展名共占3字节,对于文件夹来说没有扩展名,那么这三个字节用空格填充。在当前例子中扩展名为“TXT”。
(3)文件属性(0BH~0BH)
文件属性占1字节,可以表示文件的各种属性,表示的方法是按二进制位定义,最高两位保留未用,0~5位分别是只读位、隐藏位、系统位、卷标位、子目录位、存档位。在当前例子中属性值为“20H”,换算为二进制等于“00100000”,所以该文件为存档属性。
(4)未用(0CH~0CH)
该字节不使用。
(5)文件创建时间精确到10ms的值(0DH~0DH)
文件在创建时的时间值中精确到10ms的值用该字节表示。在当前例子该值为“86H”,换算为十进制等于134,所以文件的创建时间为1340ms,也就是1.34s。
(6)文件创建时间(0EH~0FH)
这是文件创建的时、分、秒的数值,用十六位二进制记录文件创建时间,时、分、秒三个部分的表达方法如下:
①0~4位,这5位记录“秒”值,单位是2s,也就是把这四个位的值乘以2才是文件创建时间的“秒”值,其取值范围是0~29。
②5~10位,这6位记录“分”值,其取值范围是0~59。
③11~15位,这5位记录“时”值,其取值范围是0~23。
在当前例子中该值为“27H 98H”,这是Little-Endian的字节序,从高位往低位写应为“98H 27H”,将其换算为二进制,结果为“1001100000100111”。具体时间表达方式如图4-235所示。
图4-235 时间表达方式
经过计算其时间为19时01分14秒,再加上其毫秒值1340,所以该文件最终的创建时间为19时01分15秒340毫秒。这个时间可以通过查看文件的属性获得,如图4-236所示。
图4-236 “fat16.txt”的属性信息
在属性信息中文件的创建时间精确到秒,所以是19时01分15秒。
(7)文件创建日期(10H~11H)
这是文件创建的年、月、日的数值,用十六位二进制记录文件创建日期,年、月、日三个部分的表达方法如下:
①0~4位,这5位记录“日”值,其取值范围是1~31。
②5~8位,这4位记录“月”值,其取值范围是1~12。
③9~15位,这7位记录“年”值,其值是相对于1980年开始计数的,必须加上1980才是正确的年份,其取值范围是0~127,也就是可以从1980年记录到2107年。
在当前例子中该值为“52H 3BH”,这是Little-Endian的字节序,从高位往低位写应为“3BH 52H”,将其换算为二进制,结果为“0011101101010010”。具体日期表达方式如图4-237所示。
图4-237 日期表达方式
(8)文件最近访问日期(12H~13H)
这是文件最后访问的年、月、日的数值,用十六位二进制记录文件最后访问日期。其表达方式与文件创建日期一致,不再重复。
(9)未用(14H~15H)
这两个字节FAT16不用。
(10)文件修改时间(16H~17H)
这是文件最后修改的时、分、秒的数值,用十六位二进制记录文件最后修改时间。其表达方式与文件创建时间一致,不再重复。
(11)文件修改日期(18H~19H)
这是文件最后修改的年、月、日的数值,用十六位二进制记录文件最后修改日期,其表达方式与文件创建日期一致,不再重复。
(12)文件起始簇号(1AH~1BH)
文件起始簇号占用2字节,文件起始簇号是指文件的内容在数据区中存放的地址中的第一个簇号。当前值为5,说明文件开始于5号簇。
(13)文件大小(1CH~1FH)
文件大小占用4字节,记录着文件的总字节数。当前值为“01H 40H”,换算成十进制就是320,说明文件大小为320字节。文件大小也可以通过查看文件的属性获得,如图4-238所示。
图4-238 文件大小的信息
到此一个FAT16的短文件名目录项也就分析完了。
长文件名目录项
从在Windows 95开始,文件名“8.3”格式的限制被打破了,文件名可以超过8个字符,并且可以使用中文了,扩展名也可以超过3字节,这种格式的文件名就称为长文件名。
不过在Windows 95以上的系统中创建的长文件名需要考虑与DOS和Windows 3.x的兼容问题,所以在Windows 95以上的系统中,超过8.3格式的文件或目录实际存储着两个名字,一个短文件名和一个长文件名。如果是短文件名,则存储在短文件名目录项中。当创建一个长文件名时,其对应短文件名的存储有以下三个处理原则。
①系统取长文件名的前6个字符加上“~1”形成短文件名,其扩展名不变;
②如果已存在这个名字的文件,则符号“~”后的数字自动增加;
③如果有DOS和Windows 3.x非法的字符,则以下画线“_”替代。
每个长文件名目录项也占用32字节,一个目录项作为长文件名目录项使用时,其属性字节值为0FH,能够存储13个字符,如果文件名很长,一个长文件名就需要多个目录项,这些目录项按倒序排列在其短文件名目录项之前。
长文件名目录项的具体结构见表4-24。
表4-24 FAT长文件名目录项的含义
字节偏移 | 字段长度(字节) | 字段内容及含义 |
0x00 | 1 | 序列号 |
0x01 | 10 | 文件名的第1~5个Unicode码字符 |
0x0B | 1 | 长文件名目录项的属性标志,固定为“0F” |
0x0C | 1 | 保留未用 |
0x0D | 1 | 短文件名校验和 |
0x0E | 12 | 文件名的第6~11个Unicode码字符 |
0x1A | 2 | 始终为0 |
0x1C | 2 | 文件名的第12~13个Unicode码字符 |
下面看一个具体的实例,一个文件的名称为“shu-ju-hui-fu-ji-shu-shen-du-jie-mi.txt”,它共有4个目录项:1个短文件名目录项、3个长文件名目录项,如图4-239所示。
图4-239 长文件名目录项
图4-239中的“①”是一条短文件名目录项,文件名为“shu-ju~1.txt”,这是系统自动生成的,其结构在前面分析过,不再重复。
图4-239中的“②、③、④”是三条长文件名目录项,它们以倒序的方式排列在其短文件名目录项之前。
另外WinHex的模板管理器中也提供模板可以查看长文件目录项的结构。这里以图4-239中的“②”号目录项为例,将光标放在“②”号目录项的第一个字节上,然后打开模板管理器,选择长文件名目录项的模板,如图4-240所示。
图4-240 选中长文件名目录项的模板
双击选中的模板,就能看见该目录项各字节的含义了,如图4-241所示。
图4-241 “②”号长文件名目录项的模板
下面对这些参数做详细分析。
(1)序列号(00)
序列号占1字节,该参数用来描述长文件名目录项的排序。
在这个字节的8位当中,0~4位这5位描述长文件名目录项的顺序号,从1开始编号。6位(也就是第7位)如果为“1”表明该目录项是最后一项。如果文件删除,该字节也会改为“E5”。
在当前例子中的值为“01”,说明这是第一个长文件名目录项。
(2)文件名的第1~5个Unicode码字符(01H~0AH)
该参数长度为10字节,使用UTF-16编码存储5个Unicode字符的文件名,每个字符占用两字节。
如果文件名已经记录完,但该参数的空间中还有未用的字节,就会在文件名最后一个字符后填充两个字节的“00”,随后未用的字节用“FF”填充。
在当前例子中该位置记录了5个字符:shu-j。
(3)长文件名目录项的属性标志(0BH~0BH)
该参数长度为1字节,是属性字节。当属性的只读位、隐藏位、系统位、卷标位全为1,其他位全为0时,该值就为十六进制的“0FH”,表示该目录项为长文件名记录项。
(4)未用(0CH~0CH)
该字节不使用。
(5)短文件名校验和(0DH~0DH)
该参数长度为1字节,是一个校验和,长文件名目录项通过这个校验和将其与相应的短文件名目录项关联起来。校验和的数值是使用短文件名计算得到,同一文件的长文件名目录项的校验和必须是相同的。
校验和的计算方法是依次将短文件名的各个字符对应的二进制值相加,在每一步相加前要先将二进制的结果值依次向右移动一位,最右边的位循环移动到最左边,然后再加上下一个字符所对应的二进制值,直到把最后一个字符加完,结果就是校验和的数值。
(6)文件名的第6~11个字符(0EH~19H)
该参数长度为12字节,使用UTF-16编码存储6个Unicode字符的文件名,每个字符占用2字节。如果文件名已经记录完,但该参数的空间中还有未用的字节,就会在文件名最后一个字符后填充两个字节的“00”,随后未用的字节用“FF”填充。
在当前例子中该位置记录了6个字符:u-hui-。
(7)始终为0(1AH~1BH)
该参数长度为2字节,始终都为0。
(8)文件名的第12~13字符(0EH~19H)
该参数长度为4字节,使用UTF-16编码存储2个Unicode字符的文件名,每个字符占用两字节。该参数的空间中未用的字节用“FF”填充。
在当前例子中该位置记录了2个字符:fu。
图4-239中的“②”号长文件名目录项就分析完了。下面继续分析“③”号和“④”号长文件名目录项,它们的模板如图4-242和图4-243所示。
图4-242 “③”号长文件名目录项的模板
图4-243 “④”号长文件名目录项的模板
“④”号长文件名目录项的首字节为“43H”,换算为二进制等于“01000011”,其0~4位的值为“00011”,说明这是第三个长文件名目录项,6位上的值是“1”,说明这是最后一项长文件名目录项。
“②、③、④”三条长文件名目录项的结构完全一样,以倒序的方式排列在其短文件名目录项之前,完整地记录了文件名“shu-ju-hui-fu-ji-shu-shen-du-jie-mi.txt”。
“.”目录项和“..”目录项
在子目录所在的文件目录项区域中,总有两个特殊的目录,它们就是“.”目录和“..”目录。这两个目录可以用DOS命令“DIR”查看到,如图4-244所示。
图4-244 “DIR”命令查看“.”目录和“..”目录
使用DIR列目录后,可以看到前两个就是“.”目录和“..”目录,其中:
①“.”表示当前目录。
②“..”表示上级目录。
打开WinHex查看“.”目录和“..”目录的目录项,其内容如图4-245所示。
图4-245 “.”目录和“..”目录的目录项
其中“①”号目录项是“.”目录的目录项,“②”号目录项是“..”目录的目录项,它们的模板如图4-246和图4-247所示。
图4-246 “.”目录的目录项模板
图4-247 “..”目录的目录项模板
从这两个目录项的实际数据可以得到以下结论:
①“.”目录项所描述的“起始簇号”是子目录本身所在的簇号。当前值为7,说明“.”目录项所在的簇就是7号簇。
②“..”目录项所描述的“起始簇号”是上一级目录的起始簇号,如果上一级目录是根目录,则该簇号值被置成0。当前值为0,说明该子目录的上级目录就是根目录。
③“.”目录和“..”目录的“文件大小”都是0,这同所有的目录一样,不记录大小。
系统利用“.”目录和“..”目录来实现目录之间的双向联系,从而把整个文件系统联系在一起。
卷标目录项
卷标就是一个分区的名字,可以在格式化分区时创建,也可以随时修改。在DOS时代,卷标记录在DBR的BPB中,目前的系统则把卷标当作文件,用文件目录项进行管理,系统为卷标建一个目录项,放在根目录区中,对于FAT16来说,就是放在FDT中。
当前有一个卷标为“1234567890”的分区G,如图4-248所示。
图4-248 卷标为“1234567890”的分区G
其卷标所在目录项如图4-249所示。
图4-249 卷标的目录项
卷标的目录项属于短文件名目录项,它有如下特点:
①对于FAT格式的分区,卷标的长度最多允许达到11字节,如果卷标为中文,则最多支持5个字符。
②卷标的目录项中不记录起始簇号和大小。
③卷标的目录项中不记录创建时间和最后访问时间,只记录修改时间。