在分析文件删除后文件系统中各个管理结构发生的变化之前,我们再总结一下UFS文件系统对文件的管理方式。
UFS文件系统首先被分为若干个柱面组,通过柱面组概要描述这些柱面组,超级块也会对柱面组的位置等信息进行描述,每个柱面组中还有组描述符对当前柱面组进行管理。
文件的分配单元有两个:块和段,每个块包含若干个段。每个文件都有自己的一个i-节点和目录项。i-节点中记录文件的大小、时间信息、分配地址(块指针)等信息。目录项中则记录文件的i-节点号、文件名等信息。将目录项和i-节点结合起来分析,就能获得某个具体文件的所有信息并通过块指针定位到其数据存放的地址。块指针所指向的块和段内就是文件的数据。
综上所述,UFS文件系统对文件的管理可以用一幅图来描述,如图5-57所示。
下面以Free BSD系统的UFS1文件系统中一个具体文件为例,讲解其删除前和删除后的底层变化。
目标文件名为“cron.2.gz”,它是Free BSD系统中的一个压缩文件,其具体存放路径为“/logs/var/log/cron.2.gz”。下面按照文件系统的管理方式定位该文件。
第1步 读取超级块的参数。
超级块位于文件系统的16号扇区,从超级块中获得如下参数:
第2步 读取i-节点表。
为了读取文件“cron.2.gz”,要从根目录入手。根目录的节点为2号i-节点,2号i-节点位于0号柱面组的i-节点表中,该i-节点表起始0号柱面组的32号段,即64号扇区。跳转到64号扇区,2号i-节点的内容如图5-58所示。
用WinHex的模板查看2号i-节点的参数,如图5-59所示。
从图5-59的参数中可以看到根目录的i-节点只用了一个直接块指针,指向1016号块,其实就是1016号段,对应3032扇区。
第3步 读取根目录区。
根目录的i-节点指向1016段,即3032扇区。跳转到该扇区,就是根目录区了,里面是根目录下的文件及文件夹的目录项,如图5-60所示。
我们的目标文件路径是“/logs/var/log/cron.2.gz”,所以应该找到“logs”目录的目录项,即图5-60中的阴影部分。用WinHex模板查看其具体内容,如图5-61所示。
从图5-61的参数中可以看到“logs”目录的i-节点号为114。
第4步 读取“logs”目录的i-节点。
“logs”目录的i-节点号为114,超级块中显示每个柱面组包含的i-节点数为7808,所以114号i-节点依然在0号柱面组,再跳转到0号柱面组的i-节点表,即64号扇区。因为每个i-节点占用128字节,所以114号i-节点开始于i-节点表的114×128=145 92字节偏移处,其内容如图5-62所示。
用WinHex的模板查看“logs”目录i-节点的参数,如图5-63所示。
从图5-63的参数中可以看到“logs”目录的i-节点只用了一个直接块指针,指向1329号块,其实就是1329号段,对应2658扇区。
第5步 读取“logs”目录的目录区。
“logs”目录的i-节点指向1329段,即2658扇区。跳转到该扇区,就是“logs”目录区了,里面是“logs”目录下的文件及文件夹的目录项,如图5-64所示。
该目录区除了“.”目录项和“..”目录项以外,只有一个“var”目录,它是该目录区中的最后一个目录项,所以其目录项的大小指向了该块的结束位置。
用WinHex模板查看“var”目录项的具体内容,如图5-65所示。
从图5-65的参数中可以看到“var”目录的i-节点号为115。
第6步 读取“var”目录的i-节点。
“var”目录的i-节点号为115,超级块中显示每个柱面组包含的i-节点数为7808,所以115号i-节点依然在0号柱面组,再跳转到0号柱面组的i-节点表,即64号扇区。因为每个i-节点占用128字节,所以115号i-节点开始于i-节点表的115×128=14 720字节偏移处,其内容如图5-66所示。
用WinHex的模板查看“var”目录i-节点的参数,如图5-67所示。
从图5-67的参数中可以看到“var”目录的i-节点只用了一个直接块指针,指向1330号块,其实就是1330号段,对应2660扇区。
第7步 读取“var”目录的目录区。
“var”目录的i-节点指向1330段,即2660扇区。跳转到该扇区,就是“var”目录区了,里面是“var”目录下的文件及文件夹的目录项,如图5-68所示。
“var”目录下有很多文件及目录,所以目录项很多。我们的目标文件路径是“/logs/var/log/cron.2.gz”,那么应该找到“var”的下级目录“log”的目录项,即图5-68中的阴影部分。用WinHex模板查看其具体内容,如图5-69所示。
从图5-69的参数中可以看到“log”目录的i-节点号为130。
第8步 读取“log”目录的i-节点。
“log”目录的i-节点号为130,超级块中显示每个柱面组包含的i-节点数为7808,所以130号i-节点依然在0号柱面组,再跳转到0号柱面组的i-节点表,即64号扇区。因为每个i-节点占用128字节,所以130号i-节点开始于i-节点表的130×128=16 640字节偏移处,其内容如图5-70所示。
用WinHex的模板查看“log”目录i-节点的参数,如图5-71所示。
从图5-71的参数中可以看到“log”目录的i-节点只用了一个直接块指针,指向1344号块,其实就是1344号段,对应2688扇区。
第9步 读取“log”目录的目录区。
“log”目录的i-节点指向1344段,即2688扇区。跳转到该扇区,就是“log”目录区了,里面是“log”目录下的文件及文件夹的目录项,如图5-72所示。
“log”目录下有很多文件及目录,所以目录项非常多。我们的目标文件是“/logs/var/log/cron.2.gz”,那么应该找到“cron.2.gz”文件的目录项,即图5-72中的阴影部分。用WinHex模板查看其具体内容,如图5-73所示。
从图5-73的参数中可以看到“cron.2.gz”文件的i-节点号为182。
第10步 读取“cron.2.gz”文件的i-节点。
“cron.2.gz”文件的i-节点号为182,超级块中显示每个柱面组包含的i-节点数为7808,所以182号i-节点依然在0号柱面组,再跳转到0号柱面组的i-节点表,即64号扇区。因为每个i-节点占用128字节,所以182号i-节点开始于i-节点表的182×128=23 296字节偏移处,其内容如图5-74所示。
用WinHex的模板查看“cron.2.gz”文件i-节点的参数,如图5-75所示。
从图5-75的参数中可以看到“cron.2.gz”文件的i-节点用了两个直接块指针:第一个直接块指针指向1768号块,也就是1768段;第二个直接块指针指向2181号块,也就是2181号段。从其i-节点的参数中还能看到文件大小为10 044字节。
第11步 读取“cron.2.gz”文件的数据。
“cron.2.gz”文件的数据分两部分存储:第一部分在1768号段中,对应3536扇区;第二部分在2181号段中,对应4362扇区。该文件系统每个块占16个扇区,所以文件的第一部分从3536扇区开始,共8192字节;文件的第二部分从4362扇区开始,因为文件总大小为10 044字节,所以第二部分共1852字节。
用WinHex的“新建”功能创建一个大小为10 044字节的文件,如图5-76所示。
然后将“cron.2.gz”文件两个块中的数据选中并复制,首尾相接地写入到用WinHex新创建的文件中,并另外保存到Windows环境下的分区中,文件名就保存为“cron.2.gz”。保存后的文件如图5-77所示。
UNIX中的“.gz”压缩文件可以用WinRAR程序解压,如图5-78所示。
压缩包内的文件名叫作“cron.0”,是一个UNIX的日志文件。该文件可以用Windows的写字板程序打开,打开后内容如图5-79所示。
到此,Free BSD系统中的“/logs/var/log/cron.2.gz”文件就分析完了。
在Free BSD系统中将“/logs/var/log/”路径下的“cron.2.gz”文件删除,删除后文件系统底层的变化分析如下。
①目录项的变化。
“cron.2.gz”文件被删除后,其目录项所占的空间会被收回。收回的方式是把“cron.2.gz”文件目录项的长度值添加到前一个目录项的报告长度当中。这样系统就会忽略对“cron.2.gz”文件目录项的读取。具体内容如图5-80所示。
图5-80中阴影部分是“log.smb”文件的目录项。目录项中的描述长度为24H字节,而实际上该目录项只用了10H个字节,后面的14H个字节其实就是“cron.2.gz”文件的目录项,该目录项的长度为14H字节,现在这个长度值被加入前一个文件“log.smb”的目录项长度值中。
从目录项中可以看到,“cron.2.gz”文件删除后其目录项中的i-节点号并没有改变,文件名也没有改变,所以还可以根据这些信息定位到“cron.2.gz”文件的i-节点。不过,如果是Solaris系统,目录项中的i-节点号也会被清除。
另外,“cron.2.gz”文件删除后,其上级目录的变化时间和修改时间都会发生相应改变。
②i-节点的变化。
“cron.2.gz”文件删除后,其i-节点的“文件模式”参数被清零;“链接数”将减1,说明对这个名字被删除,如果链接数成为0,意味着必须回收这个i-节点;文件大小和文件的块指针也全部清零,如图5-81所示。
用WinHex的模板查看其具体参数,如图5-82所示。
从图5-82中可以看到,文件模式、大小、链接数及原来的两个直接块指针都被清零了。
③位图的变化。
“cron.2.gz”文件删除后,其i-节点位图中的相应位设置为0以回收该i-节点,然后更新柱面组描述符和柱面组概要中的空闲i-节点数。
“cron.2.gz”文件原先占用的块和段也需要回收,将这些块和段位图中的相应位设置为1,说明它所对应的块或段为空闲,同时也需要更新柱面组描述符和柱面组概要中的空闲块数和空闲段数。
通过前文对Free BSD系统下UFS1文件系统中的一个文件的删除分析可以知道,文件被删除后,其目录项中的文件名和i-节点号还存在,通过这两个信息可以找到文件的i-节点,但是i-节点中的文件大小和直接块指针都被清零,虽然间接块指针不会清零,数据块也不会清零,但要找到文件的存储位置是很难的,所以Free BSD系统下文件删除后是比较难恢复的,可以考虑按照文件类型进行恢复。UNIX系统都对文件尾部的数据采用段存储,因此即使除尾部数据以外的其他数据是连续的,但尾部的这些数据未必与其他数据相连,也就给恢复带来了麻烦。
Open BSD和Net BSD系统与Free BSD的情况大致相同,但Solaris系统就更加麻烦一些。Solaris系统删除文件时会将目录项中的i-节点号清除掉,这样就无法定位文件的i-节点,使得恢复工作更为困难。