荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Peter (小飞侠), 信区: Program
标  题: 喑袒指碪NIX中误删的文件
发信站: BBS 荔园晨风站 (Thu Jan 21 23:15:09 1999), 转信


  Undelete、Recycled(回收站)早已成为Dos/Windows用户熟悉的恢
复删除文件的管理工具,而在UNIX中,虽然有些版本的UNIX操作系统提
供有类似于"垃圾箱"的工具,却一直没有给用户提供恢复删除文件的
程序。在UNIX中,一不小心误删了重要文件该怎么办?早先,有不少用
户自己编制程序解决此问题,不过程序结构较复杂,而且可靠性欠佳,
一般UNIX初级用户也较难掌握。笔者针对此问题编写了一段简短的C
语言程序(UNIX中ANSIC标准),由UNIX自带的C编译器cc进行编译,在UN
IX下运行。
    首先介绍一下UNIX磁盘文件系统结构。UNIX文件系统结构完全不
同于DOS/Windows系统,它给磁盘上的每个物理块一个对应的逻辑块号
。在一般不涉及物理存取的操作中只用逻辑块号,在涉及到物理存取
时,再将逻辑号转换为物理块号 。UNIX还把磁盘的文件当作磁带来看
待,一条带称为一个文件卷。每个文件都可存放一个独立的文件系统,
但不能将一个文件卷分散在多个储存质上。文件按物理块号排列如下
所示:
    0# 1# 2# … m#  m+1#  m+2# … n-1#  n#
    在文件卷中,0#块一般用于系统引导或空闲,与文件系统关系不大
。1#块存放了整个文件卷的资源信息,一般称为超级块(superblock)
或专用块。从2#块起直至某一块(这里暂且定为m+1#块)止是索引节点
,称为i节点表,其中存放的是文件的描述信息,如用户标识、组标识、
文件类别、文件存取时间、文件链接个数、文件大小等。每个磁盘的
i节点大小为64字节,而每个物理块为512字节(或1024字节),因而一个
物理块可以存放8(或16)个节点。从第m+2#块到第n块,存放文件本身

    下面我们对本程序的构思和机理作适当分析。用户在使用某个文
件时,通过该文件的路径找到该文件的目录项,再由目录中的i节点号
找到该文件的i节点,根据i节点提供的地址信息就能找到该文件中的
数据。文件被删除后,目录项中的i节点号被置成0,内部i节点加入到
空闲i节点表中,将文件占用的数据项也作为空闲块连入到空闲块表中
。但是i节点及文件所占数据块中的内容并未被破坏(未进行磁盘写操
作),这就为文件的恢复工作提供可能。
    根据以上情况,当文件被删除后,又没有磁盘空间分配操作时,可
以用下述方法恢复删除文件。获取被删除文件的i节点号,按文件系统
的结构找到相应的i节点,读取它所指出的数据块信息,存入一个新文
件中 ,由此可达到恢复文件的目的。例如,在lk文件系统中,m号i节点
在文件系统中的偏移值为(2*1024)+64*(m-1),如要获取相应的i节点
信息,可以利用lseek函数将文件的读写指针移到该位置,读取64个字
节,便是i节点信息了,再利用其中的addr[40]域即可找到文件的数据
块地址。
    文件被删除时,该文件的i节点号已从当前目录中删除,因此事先
必须保存i节点号,以备恢复时使用。所以,如何在文件被删除时保存i
节点号就成为一个关键问题。这里采用开辟缓冲区的方法:在文件被
删除之前将该文件的目录项内容拷贝到某一个公用的文件中,暂时存
起来。这个公用文件定义为/usr/restore,该文件的最大长度是固定
的,需恢复删除文件时就从/usr/restore文件中读取i节点号。下面是
程序清单。
    /*restore.c*/
    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/ino.h>
    #include<dirent.h>
    #include<sys/dir.h>
    main(argc,argv)
    int argc;
    char*argv[];
    {
    int no,a,fd,fdt,*ip,i,m,k,n;
    char s[4],buf[1024],buft[1024],sbu[300000],*point;
    struct dinode inodet;
    if(argc!=3){
     printf("Usage:restore oldfile newfile!\n");
     exit(1);
    }
    if((no=getino(argv[1]))==0 {
     printf("No file has been delete!\n");
     exit(1);
    }
    if((fd=open("/dev/dsk/0s3",0))==-1 ){
     printf("Can not open /dev/dsk/0s3 \n");
         /* /dev/dsk/0s3为被删文件所在文件系统的设备文件名 *
/
     exit(1);
    }
    lseek(fd,(no-1)*64+2048,0);
    if((n=read(fd,&inode,64))!=64) {
     printf("Error in read i-node\n");
     exit(1);
    }
    if((fdt—creat(argv[2],0666))==-1) {
     printf("Can not creat %s\n",argv[2]);
     exit(1);
    }
    point=sbu;
    k=inodet.di—size/1024;
    if(k<10) {
    m=0;
    k++;
    m=3*k;
    }
    else{
    m=k-9;
    k=30;
    }
    for(i=0;i<k;i++) {
    s[i%3]=inodet.de—addr[i];
    if(i%3==2) {
         s[3]=0;
         ip=(int *)s;
         lseek(fd,(*ip)*1024,0);
         n=read(fd,buf,1024);
         strcpy(point,buf,n);
         point+=n;
    }
    }
    if(1) { /* 文件大小超过 10k*/
    s[0]=inodet.di—adrr[30];
    s[1]=inodet.di—adrr[31];
    s[2]=inodet.di—adrr[32];
    s[3]=0;
    ip=(int *)s;
    lseek(fd,(*ip)*1024,0);
    read(fd,buft,1024);
    1 *=4;
    for(i=0;i<1;i++){
    s[i%4]=buf1[i];
    if(i%4==3)
        ip=(int *)s;
        lseek(fd,(*ip)*1024,0);
        n=read(fd,buf,1024);
        strcpy(point,buf,n);
        point  +=n;
    } /* if */
    } /* for */
    }
    write(fdt,sbu,inodet,di—size);
    }
        int getino(name)
    /*函数getino从/usr/restore文件中获取误删文件的i节点号
    char *name;
    {
    int fd,n;
    struct direct buf;
    fd=open("/usr/restore",0);
    while((n=read(fd,&buf,sizeof(buf)))!=0) {
     if(n!=16){
        printf("Error in read  \n");
        exit(1);
     }
     if(strcmp(buf.d—name,name)==0) {
        close(fd);
        return(buf.d—ino);
     }
    } /*while */
    close(fd);
    return(0);
    }
    用户可以直接使用UNIX的vi编辑器进行程序编辑,然后使用UNIX
的cc编译器编译,例如# cc -o unrm restore.c,生成可执行文件unrm
。必须注意,以上程序可以恢复lk文件系统中的小型和中型文件,而且
在恢复文件时,必须处于超级用户的权限下。
    本程序在AT&T System V Release 4环境下编写通过,有兴趣的用
户可以根据自己所使用的系统软硬件配置情况 ,对程序做相应的修改
,实现其功能
--

--
※ 来源:.BBS 荔园晨风站 bbs.szu.edu.cn.[FROM: 192.168.1.3]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店