SCO UNIX文件卷结构分析及误删文件的恢复
首页 > 业界动态
摘要 该文以SCO UNIX 3.2.4.1版本为例,分析其文件卷结构和磁盘块管理方式,并在此基础上讲述了误删文件恢复的方法。
我们知道,UNIX操作系统是以文件卷作为其文件系统的存储格式的。对于UNIX用户尤其是系统管理员而言,要想更好地掌握UNIX操作系统,熟悉文件卷的结构是很有必要的。由于SCOUNIX在全球的微机UNIX操作系统市场中所占份额最大,在我国更是处于垄断地位,而它的文件卷结构和磁盘块管理方式都和其它UNIX SYSTEM V不完全一样,介绍这方面信息的资料也很少。本文就以SCO UNIX 3.2.4.1版本为例,彻底分析它的文件卷结构和磁盘块管理方式,并在此基础上,讲述一个应用--恢复误删的文件。
一、文件卷的结构
文件卷是由大小相同的磁盘块序列组成的。在文件卷偏移量512字节处,有一个长度为512字节的超级块,其后是若干i节点块、位图索引块、位图块、数据块等,如图1所示。
图1
其中,位图索引块和位图块是SCO UNIX专有的,它们含有关于磁盘块管理的重要数据,一般情况下,位图块不止一个,它们的数量和块号是由位图索引块中的数据决定的。4.1版本中,磁盘块的大小是1024字节,因此引导块和超级块合占0号磁盘块。若块尺寸为512字节,则0号块是引导块,1号块是超级块。其中超级块含有文件卷的许多重要信息,如文件卷的大小、位图索引块的位置等。其数据结构放在
struct filsys
{
ushort s-isize;
daddr-t s-fsize;
short s-nfree;
daddr-t sfree[NICFREE];
…
};
其中:s-nfree、sfree[NICFREE]是SCO UNIX涉及磁盘块管理的两项重要数据,在其它UNIX SYSTEM V中也有这两项数据,但二者的含义不同。s-nfree是SCO UNIX的文件卷标志,恒为-1;sfree[NICFREE]是位图索引块地址表,表中的数据是位图索引块的块号,对于容量小于2GB的文件卷,只有sfree[0]含有数据。
我们来看一看子文件卷/dev/user的超级块内容:
# hd -abx -s 0x200 -n 0x200 /dev/user
0200 1d 06 00 00 a0 86 01 00 ff ff 00 00 1e 06 00 00
0210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
02d0 00 00 00 00 00 00 00 00 8d 00 8c 00 8b 00 8a 00
02e0 89 00 88 00 87 00 86 00 85 00 84 00 83 00 82 00
02f0 81 00 80 00 7f 00 7e 00 7d 00 7c 00 7b 00 7a 00
0300 79 00 78 00 77 00 76 00 75 00 74 00 73 00 72 00
0310 71 00 70 00 6f 00 6e 00 6d 00 6c 00 6b 00 6a 00
0320 69 00 68 00 67 00 66 00 65 00 64 00 63 00 62 00
0330 61 00 60 00 5f 00 5e 00 5d 00 5c 00 5b 00 5a 00
0340 59 00 58 00 57 00 56 00 55 00 54 00 53 00 52 00
0350 51 00 50 00 4f 00 4e 00 4d 00 4c 00 4b 00 4a 00
0360 49 00 48 00 47 00 46 00 45 00 44 00 43 00 42 00
0370 41 00 40 00 3f 00 3e 00 3d 00 3c 00 3b 00 3a 00
0380 39 00 38 00 37 00 36 00 35 00 34 00 33 00 32 00
0390 31 00 30 00 2f 00 2e 00 2c 00 10 00 1d 00 00 00
03a0 00 00 00 00 74 65 0e 31 01 00 90 01 00 00 00 00
03b0 74 7f 01 00 86 61 00 00 00 00 00 00 00 00 00 00
03c0 00 00 00 00 10 00 00 00 01 00 00 00 1d 06 00 00
03d0 1d 06 00 00 00 e0 14 f1 00 00 00 00 00 00 00 00
03e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
03f0 00 00 00 00 c4 37 18 4b 21 7e 18 fd 02 00 00 00
0400
从上可见,文件卷/dev/user只有一个位图索引块,其块号是0x61e它在文件卷中的偏移量是0x61e*0x400=0x187400字节。位图索引块的数据结构是长整型数组,数组中的数据是它所管理的位图块的块号。
下面是位图索引块0x61e的数据。
# hd alx -s 0x187800 -n 0x400 /dev/user
187800 0000061d 0000261d 0000461d 0000661d
187810 0000861d 0000a61d 0000c61d 0000e61d
187820 0001061d 0001261d 0001461d 0001661d
187830 0001861d 00000000 00000000 00000000
187840 00000000 00000000 00000000 00000000
*
187c00
由此可见,该位图索引块管理的位图块有0x61d,0x261d,……,0x1861d。位图块的数据结构可以看作是一个长度为1024字节的二进制数。该数中的每一位都是反映某个磁盘块使用情况的标志位。若该位为1,则表明该磁盘块未被使用,是空闲块;若该位为0,则表明该磁盘块已被使用。该标志位所代表的磁盘块的块号等于位图块号加上标志位在二进制数中的偏移量。下面是位图块0x61d的数据。
# hd -abx -s 0x187400 -n 0x400 /dev/user
187410 f8 ff 80 ff ff ff ff ff ff ff ff ff ff ff fe ff
187420 00 00 ff ff 00 00 00 00 00 00 00 00 00 00 ff ff
187430 ff ff bf ff 00 00 00 00 00 00 f8 ff ff ff ff ff
187440 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
*
187800
二、误删文件的恢复
在UNIX系统下,常常发生误删文件的情况,造成意外损失。其实,只要在文件恢复之前不向系统申请分配磁盘块和写数据,误删的文件是完全可以恢复的。因为删除一个文件,只是释放了该文件所占用的i节点和磁盘块资源,而记录文件数据的磁盘块的内容还未被清除。只要找到这些磁盘块,重建文件的i节点,便可恢复误删的文件了。
1.SCO UNIX分配磁盘块算法
由于一个磁盘块的大小为1024字节,所以一个位图块可以管理0x400*8=0x2000个磁盘块。那么,下一个位图块的块号就是0x61d+0x2000=0x261d。这与位图索引块中的数据是相符的。那么,位图块0x61d管理着块号为0x61d-0x261c的磁盘块。由以上数据可见,在这个位图块中,第一个被使用的磁盘块块号是0x61d,即位图块本身。第一个空闲块块号由0x187401处字节0x1c的第2位指示,是0x627。由于该位图块是文件卷中的第一个位图块,所以0x627号磁盘块也是文件卷中的第一个空闲块。当我们向系统申请磁盘块时,系统通过超级块、位图索引块、位图块来寻找那些标志位为1的块,然后将相应的标置位置0。当释放一个磁盘块时,系统就将相应的标志位置1。现在,我们就可以判断出文件卷中的每一个磁盘块是否被使用了。但是仅赁这些还不能完全恢复误删的文件,我们还得了解SCO UNIX分配磁盘块的算法。为了使一个文件所占用的磁盘块相对集中,SCO UNIX是按照特定的算法来选择空闲块分配给文件的。假设某文件所占用的最后一个磁盘块的块号为m,现在要再分配一磁盘块给该文件,若该文件是新文件则m=0。分配算法的流程图如图2。
图2
现在我们在文件卷/dev/user下创建一个新文件1.tmp,根据以上磁盘块分配算法,可以推测它将占据磁盘块0x627,那么0x187401处的字节的第2位将置0,变为0x18。
# cat> 1.tmp
1234567 ^c
# hd -abx -s 0x187400 -n 0x400 /dev/user
187400 00 18 00 00 00 00 20 00 80 ff 00 00 07 9c ff ff
187410 f8 ff 80 ff ff ff ff ff ff ff ff ff ff ff fe ff
187420 00 00 ff ff 00 00 00 00 00 00 00 00 00 00 ff ff
187430 ff ff bf ff 00 00 00 00 00 00 f8 ff ff ff ff ff
187440 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
*
187800
磁盘块0x627的内容如下:
# hd -s 0x189c00 -n 0x400 /dev/user
189c00 31 32 33 34 35 36 37 1a 00 00 00 00 00 00 00 00 1
234567……
189c10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
……………
*
18a000
我们再把1.tmp删除,释放磁盘块0x62f,则0x187401处字节又成为0x1c。
# rm 1.tmp
# hd -abx -s 0x187400 -n 0x400 /dev/user
187400 00 1c 00 00 00 00 20 00 80 ff 00 00 07 9c ff ff
187410 f8 ff 80 ff ff ff ff ff ff ff ff ff ff ff fe ff
187420 00 00 ff ff 00 00 00 00 00 00 00 00 00 00 ff ff
187430 ff ff bf ff 00 00 00 00 00 00 f8 ff ff ff ff ff
187440 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
*
187800
磁盘块0x627的内容没有丢失:
# hd -s 0x189c00 -n 0x400 /dev/user
189c00 31 32 33 34 35 36 37 1a 00 00 00 00 00 00 00 00
1234567……
189c10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
……………
*
18a000
由于系统每次分配磁盘块给文件时,都遵循这一算法,所以当文件被删除后,我们同样可以按照这一算法推算出原本属于该文件的磁盘块号,这样我们就能完全恢复误删的文件了。
2.误删文件的恢复
根据以上SCO UNIX文件卷结构和磁盘块管理的特点,笔者编制了一恢复误删文件的程序并投入使用,挽救了许多数据。限于篇幅,这里只给出软件的构思和磁盘块分配算法函数getNextFreeBlock(long BN)的源代码。软件构思是这样的,首先在被误删文件的文件卷下,创建一新文件,不向该文件写任何数据即关闭它,然后调用系统函数stat (char* path, structstat* buf)得到该文件的i节点,再根据磁盘块分配算法在文件卷上寻找将分配的空闲块,将块号填入i节点的磁盘块地址表并把相应位图块中的标志位置0;由于SCO UNIX把已分配磁盘块中未被使用的字节全部署0,所以我们只要找到一个尾部字节全部为0的磁盘块,就可以认为它是文件的最后一个磁盘块了,由这些磁盘块的数量和最后一个磁盘块中有效字节的长度,可以算出文件的字节长度,将此长度值也填入i节点,再把该i节点写回文件卷即可。i节点的数据结构在
struct dinode
{
ushort dimode;
short dinlink;
ushort diuid;
ushort digid;
off-t disize;
char diaddr[40]; /*磁盘块地址表*/
.
.
.
};
对于大文件的一次间址块、二次间址块和三次间址块的块号,只要稍做处理即可找到,这里不再赘述,留给读者思考。
函数getNextFreeBlock(long BN)的返回值是文件卷中下一个将要分配的空闲块的块号,失败时返回-1,表明已无空闲块可分配。输入参数是起始块号,若是分配给文件的第一块,则BN为0。源代码如下,其中BBIT存放的是文件卷位图索引块的数据。函数readABlock (longBN, void* buf)的功能是将文件卷的BN号磁盘块的内容读入缓冲区buf。
extern long BBIT[0x100];
long getNextFreeBlock(long BN)
{
long lg;
ushort uBuf[0x200];
int i,k,m,n;
if (BN>superBlock,s-fsize)
return -1;
sync();
for (k=BN
readABlock(BBIT[k],uBuf);
for (m=(BBIT[k]
n=(BBIT[k]+m*0x10)>BN?0:(BN-BBIT[k]-m*0x10+1);
while (n<0x10&&(uBuf[m]&(1<
if (n!=0x10)
{
lg=BBIT[k]+m*0x10+n;
i=0x10-(BN-BBIT[0])%0x10;
if (BN==0||lg
return lg;
}
}
}
return -1;
}
注意,在恢复文件之后,为了使系统的内存超级块和文件卷上的超级块保持一致,对于子文件卷和根文件卷,应分别执行以下命令:
# fsck -f y /dev/user
# fsck -f y -b /dev/root
显然,掌握了SCO UNIX文件卷的结构特点和磁盘块的管理方式后,我们还能进行更多的应用。比如磁盘块使用情况图、文件磁盘块规整等等。由于当前涉及SCO UNIX内核设计方面的资料太少,笔者对它也只有一个初步地探索。在这里,笔者殷切地希望此篇拙作还能起一抛砖引玉之用。
提示:
本站部分文章收集于网络,版权归原作者及出版社所有 如果您觉得侵犯了您的版权请来信告诉我们,我们会尽快删除其内容! 本站原创文章版权归本站所有,除特别申明外,大家可以自由转载,但原作者和来自本站的链接必须保留!