卷头结构分析
HFS+文件系统卷头位于宗卷的2号扇区,占用1个扇区,其重要性类似于FAT文件系统和NTFS文件系统中的DBR。卷头中记录着许多参数,具体见表6-12。
表6-12 卷头的结构参数
字节偏移 | 字段长度(字节) | 字段名和定义 |
0x00~0x01 | 2 | 签名值 |
0x02~0x03 | 2 | 版本 |
0x04~0x07 | 4 | 属性 |
0x08~0x0B | 4 | 最后加载版本 |
0x0C~0x0F | 4 | 日志信息块 |
0x10~0x13 | 4 | 创建时间(非GMT时间,而是本地时间) |
0x14~0x17 | 4 | 修改时间(非GMT时间,而是本地时间) |
0x18~0x1B | 4 | 备份时间(非GMT时间,而是本地时间) |
0x1C~0x1F | 4 | 最后检查时间(非GMT时间,而是本地时间) |
0x20~0x23 | 4 | 文件数目 |
0x24~0x27 | 4 | 目录数目 |
0x28~0x2B | 4 | 每块字节数 |
0x2C~0x2F | 4 | 总块数 |
0x30~0x33 | 4 | 空闲块数 |
0x34~0x37 | 4 | 下一个分配块号 |
0x38~0x3B | 4 | 资源分支的块大小 |
0x3C~0x3F | 4 | 数据分支的块大小 |
0x40~0x43 | 4 | 下一目录的ID |
0x44~0x47 | 4 | 写记数 |
0x48~0x4F | 8 | 文档编码位图 |
0x50~0x6F | 32 | 系统引导信息(FinderInfo)(具体见表6-13) |
0x70~0xBF | 80 | 分配文件的信息 |
0xC0~0x10F | 80 | 盘区溢出文件的信息 |
0x110~0x15F | 80 | 编录文件的信息 |
0x160~0x1AF | 80 | 属性文件的信息 |
0x1B0~0x1FF | 80 | 启动文件的信息 |
对各参数进一步解释如下:
(1) 0x00~0x01:签名值。签名值是卷头的标志位,“H+”表示该宗卷格式为HFS+;“HX”则表示该宗卷格式为HFSX。
(2) 0x02~0x03:版本。版本也是对宗卷格式的描述,通常来说版本“4”表示HFS+格式;版本“5”表示HFSX格式。
(3) 0x04~0x07:属性。属性参数描述该宗卷所具备的属性,用32位进行描述,具体属性的含义如下:
- 第0~7位:系统视它们为保留位。
- 第8位:宗卷干净标志。宗卷正常卸载时设置此位,用以说明该宗卷没有异常情况出现;当宗卷正常挂载并且可写时,将此标志清除。
- 第9位:如果盘区溢出文件区域里有任何坏块,则用该位来设置。
- 第10位:如果宗卷上的块没有设置缓存,就设置该位。
- 第11位:宗卷肮脏标志。该标志与宗卷的干净标志用法相反,当宗卷挂载时,先设置此位时,宗卷使用完毕需要卸载时,如果没有异常情况,将该位清除;而在宗卷卸载时存在异常,该位不清除,则在下次挂载该宗卷时,系统首先会对其做一致性检查。
- 第12位:当“下一目录ID”参数的值超出32位时将设置该位,目的是强迫较小的CNID(CNID的含义在后面讲解)被回收再利用。当这一位被设置时,说明编录文件记录中的CNID值已经大于或等于“下一目录ID”参数的值,这种情况并不是一个错误,而是一个正常现象。但设置这一位后,需要注意避免新创建文件的CNID与现有文件的CNID相冲突。
- 第13位:如果该位被设置了,则该宗卷包含日志文件,日志文件的地址可以通过卷头中“日志信息块”的值确定。
- 第14位:系统视其为保留位。
- 第15位:当该宗卷被软件设置为写保护状态时,就设置该位。只要该位被设置为有效,则任何系统都无法在该宗卷上进行写操作。这个标识位在一些不能写保护的宗卷上有很突出的作用,还可以用来保护分区表映射免于被重写。
- 第16~31位:保留。
(4) 0x08~0x0B:最后加载版本。最后加载版本的值用来唯一的识别最后对该宗卷做写操作的系统版本。从Mac OS 8.1到Mac OS 9.2.2版本的系统,该值为“8.10”;而Mac OS X的值为“10.0”。对于Mac OS X系统来说,包括HFSX格式在内的日志宗卷的值为“HFSJ”,但对于fsck_hfs格式的值为“fsck”。
(5) 0x0C~0x0F:日志信息块。描述日志信息块的地址,当属性中的13位被设置时该参数有效,否则保留不用。
(6) 0x10~0x13:创建时间。创建时间参数记录了该宗卷创建的日期和时间。
卷头中的时间并不是GMT(格林威治时间),而是本地时间。
HFS+文件系统能够表示的时间范围是从GMT时间的1904年1月1日0时到2040年2月6日06时28分15秒。
(7) 0x14~0x17:修改时间。修改时间参数记录了该宗卷最后一次修改的日期和时间,此处也是本地时间。
(8) 0x18~0x1B:备份时间。备份时间参数记录了该宗卷最后一次备份的日期和时间,此处也是本地时间。
(9) 0x1C~0x1F:检查时间。检查时间参数记录了该宗卷最后一次做一致性检测的日期和时间。磁盘检测工具,包括Disk First Aid,都必须在完成磁盘检测以后才能被安装使用。磁盘检测工具有可能周期性地对宗卷进行检测。此处也是本地时间。
(10) 0x20~0x23:文件数目。文件数目参数记录了该宗卷上文件的总数,但不包括元文件,它和编录文件里记录的文件数是一致的。
(11) 0x24~0x27:目录数目。目录数目参数记录了该宗卷的文件夹的总数,但不包括根目录。它应等于编录文件记录的文件夹总数值减1。
(12) 0x28~0x2B:每块字节数。每块字节数参数即块大小,指每个块包含的字节数。
(13) 0x2C~0x2F:总块数。总块数参数记录了宗卷中块的总数。如果一个宗卷的总大小是分配块的整数倍大小,那么该磁盘上的所有区域都包括在一个块中,包括卷头和备份卷头在内的区域。如果一个磁盘的总大小不是分配块的整数倍大小,分配块能够覆盖的就只是该磁盘被记录的范围,剩余的部分在磁盘的末尾,这部分不会被格式化。
(14) 0x30~0x33:空闲块数。空闲块数参数记录了宗卷上没有被使用的块总数。
(15) 0x34~0x37:下一个分配块号。下一个分配块号参数记录下次分配搜索的起始位置。当需要为一文件分配块时,该值被Mac OS系统用来记录寻找未使用块的起始位置。它记录的是搜索块的起始块号,如果该系统不用这个来记录搜索的起始位置,则该区域为保留区域。
(16) 0x38~0x3B:资源分支的块组大小。资源分支的块组大小是在为文件增加存储空间时,需要以这个大小给文件分配空间。不过所有的苹果系统都忽略资源分支的块组大小,而只以数据分支的块组大小作为给数据分支和资源分支分配空间的依据。
(17) 0x3C~0x3F:数据分支的块组大小。数据分支的块组大小参数记录了默认的数据分支块组的大小,以字节为单位。
(18) 0x40~0x43:下一个目录的ID。下一个目录的ID参数记录了下一个未使用的目录文件ID。
(19) 0x44~0x47:写记数。写记数区域的记录在每次宗卷被加载时都会增加。它允许一个操作跟踪该宗卷的加载情况,甚至是未被正确加载或意外失去连接的情况。当介质重新接入时,系统会检测此处的值以确定意外失去连接时是否对宗卷产生了改变。
写记数的这一功能可以说明某些程序是否对宗卷结构做了修改。
(20) 0x48~0x4F:文档编码位图。文档编码位图部分记录了文件和目录名的编码类型,它允许用Unicode码以外的编码以达到最佳的描述效果。
(21) 0x50~0x6F:系统引导信息(FinderInfo)。系统引导信息包含Mac OS系统的探测器信息和系统程序引导进程的信息,共分为8组,每组信息4个字节,每组信息的具体含义见表6-13。
表6-13 系统引导信息的含义
系统引导信息编号 | 字节偏移(相对偏移) | 字段长度(字节) | 含义 |
系统引导信息[0] | 0x00~0x03 | 4 | 包含启动系统所需文件的目录ID,对于Mac OS 8或Mac OS 9系统,是指系统目录;对于Mac OS X系统,是指/System/Library/CoreServices目录。 如果不是可引导宗卷,则置0。 它兼具系统引导信息[3]和系统引导信息[5]两个位置的功能 |
系统引导信息[1] | 0x04~0x07 | 4 | 包含启动程序的父目录的ID,如果是非启动宗卷则置0 |
系统引导信息[2] | 0x08~0x0B | 4 | 包含宗卷被加载时所显示的目录窗口文件所在的目录ID,如果没有打开的目录窗口则置0 |
系统引导信息[3] | 0x0C~0x0F | 4 | 包含可引导的Mac OS 8或Mac OS 9系统文件夹的目录ID,如没有则置0 |
系统引导信息[4] | 0x10~0x13 | 4 | 保留未用 |
系统引导信息[5] | 0x14~0x17 | 4 | 包含可引导的Mac OS X系统文件夹的目录ID,如没有则置0 |
系统引导信息[6] | 0x18~0x1B | 4 | 包含Mac OS X记录的一个64位的唯一卷ID。这个ID的一个用处是跟踪一个指定宗卷的所有者(即用户ID)是否能够被取信。 如果宗卷中没有这样的ID被创建,则置0 |
系统引导信息[7] | 0x1C~0x1F | 4 | 同“系统引导信息[6]” |
(22) 0x70~0xBF:分配文件的信息。分配文件的信息用来记录分配文件的位置和大小。
分配文件的信息使用HFS+文件系统的分支数据结构(HFSPlusForkData),其具体结构见表6-14。
表6-14 HFS+文件系统的分支数据结构
字节偏移(相对偏移) | 字段长度(字节) | 字段名和定义 |
0x00~0x07 | 8 | 分支的总字节数 |
0x08~0x0B | 4 | 分支的块组大小 |
0x0C~0x0F | 4 | 分支的总块数 |
0x10~0x4F | 64 | 8个盘区描述符(具体见表6-15) |
在HFS+文件系统的分支数据结构中描述了8个盘区描述符(ExtentDescriptor),每个盘区描述符占8个字节,其结构见表6-15。
表6-15 盘区描述符的结构
字节偏移(相对偏移) | 字段长度(字节) | 字段名和定义 |
0x00~0x03 | 4 | 起始块号 |
0x04~0x07 | 4 | 块数 |
盘区描述符用来描述分支数据前8个盘区的信息,如果分支数据需要的空间大于8个盘区,那么8个盘区以外的空间用盘区溢出文件描述,盘区溢出文件中也用盘区描述符结构描述每一个盘区。
(23) 0xC0~0x10F:盘区溢出文件的信息。盘区溢出文件的信息用来记录盘区溢出文件的位置和大小,其结构也采用HFS+文件系统的分支数据结构,其结构可以参见表6-14。
(24) 0x110~0x15F:编录文件的信息。编录文件的信息用来记录编录文件的位置和大小,其结构也采用HFS+文件系统的分支数据结构,其结构可以参见表6-14。
(25) 0x160~0x1AF:属性文件的信息。属性文件的信息用来记录属性文件的位置和大小,其结构也采用HFS+文件系统的分支数据结构,其结构可以参见表6-14。
(26) 0x1B0~0x1FF:启动文件的信息。启动文件的信息用来记录启动文件的位置和大小,其结构也采用HFS+文件系统的分支数据结构,其结构可以参见表6-14。
卷头实例分析
下面具体分析一个HFS+文件系统卷头的实例,该卷头的内容如图6-26所示。
图6-26 HFS+文件系统卷头
Mac OS系统使用Big-Endian字节序。
图6-26中HFS+文件系统卷头主要参数的解释如图6-27所示。
图6-27 HFS+文件系统卷头中主要参数的模板内容
图6-26中HFS+文件系统卷头分配文件信息的解释如图6-28所示。
图6-28 分配文件信息的模板内容
图6-26中HFS+文件系统卷头盘区溢出文件信息的解释如图6-29所示。
图6-29 盘区溢出文件信息的模板内容
图6-26中HFS+文件系统卷头编录文件信息的解释如图6-30所示。
图6-30 编录文件信息的模板内容
图6-26中HFS+文件系统卷头的属性文件信息没有任何数据,其模板内容如图6-31所示。
图6-31 属性文件信息的模板内容
图6-26中HFS+文件系统卷头的启动文件信息也没有任何数据,就不再看其模板了。