歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Unix知識 >> Unix教程

UNIX 系統中被誤刪文件的恢復策略


  與DOS/Windows不同,UNIX文件被刪除後很難恢復,這是由UNIX獨特的文件系統結構決定的。UNIX文件目錄不像DOS/Windows那樣,文件即使被刪除之後仍保存有完整的文件名、文件長度、始簇號(即文件占有的第一個磁盤塊號)等重要信息;相反,它的文件信息全部依靠一種被稱為i節點的數據結構來描述,而i節點在相應文件被刪除之後即被清空,因此,要想直接恢復被刪除的文件內容幾乎是不可能的,必須另辟蹊徑。本文結合實際,討論幾種文件恢復策略及其關鍵步驟的具體實現。
  
  一、UNIX文件系統結構
  我們知道,UNIX是以文件卷作為其文件系統存儲格式的,而不同的UNIX系統,文件卷格式是有差異的,甚至即使是同一UNIX*作系統的不同版本,其文件系統未必完全相同,例如:SCO UNIX 4.1版與5.0版文件系統結構就有明顯差異,但只要是UNIX系統,其文件卷的基本結構是一致的。分析如下:
  
  不管是什麼UNIX系統,不管什麼版本,其文件卷至少包括引導塊、超級塊、i節點表、數據區等幾個部分。除此之外,不同UNIX版本可能還有不同的差異。例如:SCO UNIX系統的位圖索引塊和位圖塊AIX的邏輯卷表等。這些系統的特殊性不影響下文的恢復策略,故這裡不作討論,僅介紹標准UNIX文件卷結構。
  
  1. 引導塊
  
  位於文件卷最開始的第一扇區,這512字節是文件系統的引導代碼,為根文件系統所特有,其他文件系統這512字節為空。
  
  2. 超級塊
  
  位於文件系統第二扇區,緊跟引導塊之後,用於描述本文件系統的結構。如i節點長度、文件系統大小等,其結構存放於/usr/include/sys/filsys.h中,其結構如下:
  
  struct filsys
  
  {
  
  ushort s_isize; /*磁盤索引節點區所占用的數據塊數*/
  
  daddr_t s_fsize; /*整個文件系統的數據塊數*/
  
  short s_nfree; /*在空閒塊登錄表中當前登記的空閒塊數目*/
  
  daddr_t s_free[NICFREE]; /*空閒塊登記表*/
  
  short s_ninode; /*空閒索引節點數*/
  
  ino_t s_inode[NICINOD]; /*空閒節點登記表*/
  
  char s_flock; /*加鎖標志位*/
  
  char s_ilock; /*節點加鎖標志位*/
  
  char s_fmod; /*超級塊修改標志*/
  
  char s_ronly; /*文件系統只讀標志*/
  
  time_t s_time; /*超級塊上次修改的時間*/
  
  short s_dinfo[4]; /*設備信息*/
  
  daddr_t s_tfree; /*空閒塊總數*/
  
  ino_t s_tinode; /*空閒節點總數*/
  
  char s_fname[6]; /*文件系統名稱*/
  
  char s_fpack[6];
  
  long s_fill[13]; /*填空位*/
  
  long s_magic; /*指示文件系統的幻數*/
  
  long s_type; /*新文件系統類型*/
  
  };
  
  3. i節點表
  
  i節點表存放在超級塊之後,其長度是由超級塊中的s_isize字段決定的,其作用是用來描述文件的屬性、長度、屬主、屬組、數據塊表等,其數據結構在/usr/include/sys/ino.h中,如下:
  
  struct dinode
  
  {
  
  ushort di_mode;
  
  short di_nlink;
  
  ushort di_uid;
  
  ushort di_gid;
  
  off_t di_size;
  
  char di_addr[40];
  
  time_t di_atime;
  
  time_t di_mtime;
  
  time_t di_ctime;
  
  };
  4. 目錄結構
  
  UNIX所有文件均存放於目錄中,目錄本身也是一個文件。目錄存放文件的機制如下:首先,目錄文件本身也象普通文件一樣,占用一個索引節點,其次,由這個索引節點得到目錄內容的存放位置,再次,從其內容中取出一個個的文件名和它對應的節點號,從而訪問一個文件。目錄結構如下:
  
  索引節點號(2字節) .(本目錄)(14字節)
  
  索引節點號(2字節) ..(父目錄)(14字節)
  
  索引節點號(2字節) 文件名(14字節)
  
  索引節點號(2字節) 文件名(14字節)
  
  索引節點號(2字節) 文件名(14字節)
  
  由上可知文件名是依靠目錄來描述的,文件的內容和其他信息則由索引節點來描述。
  
  二、文件的刪除過程
  UNIX下刪除一個文件的過程很簡單,那就是釋放索引節點表和文件占用的數據塊,清空文件占用的索引節點,但不清除文件內容。但刪除文件與刪除目錄的處理不盡相同,不同命令刪除文件的過程也不相同。
  
  1. 刪除一個文件
  
  UNIX 刪除一個文件的具體步驟是:根據文件i節點的地址表逐一釋放文件占用的磁盤數據塊,然後清空相應的節點,最後釋放i節點。
  
  2. 刪除一個目錄
  
  刪除一個目錄的過程:首先逐一刪除目錄裡的所有文件,然後刪除目錄。目錄本身也是一個文件,故刪除方法與刪除文件一致。
  
  3. 幾種不同的刪除命令
  
  .rm 命令
  
  一般刪除命令,刪除過程上述已說明。
  
  .mv命令
  
  格式:mv 文件1 文件2
  
  處理過程是將文件2的數據塊釋放,然後將文件1的名稱改為文件2,再釋放文件2所占的i節點。
  
  . > 命令
  
  格式:>文件名
  
  若產生一個新文件,>命令僅僅申請一個i節點,而不寫入任何文件內容;若清空一個已經存在的文件,則釋放文件所占的數據塊,並將文件長度清零。
  
  三、被刪文件的恢復策略
  要恢復被刪除的文件,只能根據刪除後留下的東西去做文章。文件被刪除後留下了什麼呢?由上述分析可知:其一、留下了文件的內容;其二、留下了“現場”。文件的恢復策略只能從這兩個方面來分析。以下談幾種恢復策略。
  
  1.根據磁盤現場進行恢復
  
  如果文件被刪除,現場未被破壞(即文件被刪除後硬盤未發生過寫*作),而且假定只刪除了一個文件,那麼可根據系統的分配算法進行恢復。因為系統建立一個文件時,必定根據某一特定的分配算法決定文件占用的數據塊位置。而當該文件被刪除後,它所占用的數據塊被釋放,又回到系統的分配表中,這時如果重新建立一個文件,系統根據原來的分配算法分配出的數據塊必定跟該文件原來占用的數據塊一致,而且我們知道,UNIX文件最後一數據塊尾部多出的字節是全部置0的,據此只要調用系統的數據分配算法,在系統中一塊塊的申請數據塊,因為UNIX文件最後一個數據塊尾部多出的字節全部為0,所以,只要發現一個分配出的數據塊中尾部全為0,即可認為文件結束,由此可確定文件長度和內容,進而實現恢復。方法如下:
  
  ⑴申請一個索引節點,即向系統申請創建一個新文件名而不寫入任何內容。如:#>/tmp/xx
  
  ⑵調用系統分配數據塊算法getnextfreeblock()得到一個數據塊號,記入某一地址表變量中。
  
  ⑶讀出這個數據塊,判斷其尾部是否全部連續為0,若不是,則回到(2),若是,則進行(4)。
  
  ⑷首先用系統函數fstat得到/tmp/xx的i節點號,然後將(2)步所得的地址表寫入索引節點的地址表中(注意間址問題),並根據數據塊個數和最後一塊中有效數據長度計算出文件大小,寫入i節點的di_size字段。
  
  ⑸回寫系統的索引節點表即可。
  需要說明的是,第一,系統分配數據塊的算法因不同的UNIX版本而不同;第二,有的UNIX如SCO UNIX 5.0版,其空閒數據塊的分配和回收是使用一種動態鏈表的數據結構來實現的,它們的文件恢復更加容易,只要在空閒鏈表中的表尾去尋找即可,筆者另行描述。
  
  2. 根據內容恢復。
  
  若現場已被破壞,即硬盤發生過寫*作,那麼只好根據內容來恢復。而且,由於UNIX是一個多進程、多用戶系統,它每一次開關機或硬件、通訊故障等都會記錄系統日志、.sh_history等,硬盤現場被破壞可能性極大。因此討論按內容恢復的方法具有更大的實用價值。筆者經過實際探索得出下列四種恢復策略供參考。
  
  ⑴關鍵字搜索法
  
  如果知道被刪除的文件內容中若干字節的內容,而且該文件長度又不超過一個磁盤塊,那麼可以在整個文件系統中搜索這一字節串,得出一個文件所在的數據塊,將它們的塊號填入一個i節點,即可恢復一個文件,搜索文件系統的算法很簡單,說明如下:
  
  a. #df -k 確定文件系統的設備文件名(如/dev/root)
  
  b.用下述函數搜索,若成功,返回數據塊號,反之返回-1。其中fsname是文件系統的設備名,如/dev/root,comp()參數是實現搜索條件的函數。
  
  long searchfs(char *fsname , int comp())
  
  {
  
  FILE *fp;
  
  char buf[1024];
  
  long i=0;
  
  fp=fopen(fsname,"r");
  
  while (!feof(fp))
  
  {
  
  fread(buf,1024,1,fp);
  
  if (comp()) /* 檢查是否符合搜索條件 */
  
  return i; /* 若成功返回塊號 */
  
  i++;
  
  }
  
  fclose(fp);
  
  return -1; /* 未找到符合條件的塊,返回-1*/
  
  }
  
  ⑵精確長度搜索法
  
  如果知道被刪除文件的精確長度(字節數),那麼可根據一個數據塊的大小,計算出文件的最後一個數據塊中數據的精確長度,該數據塊中其他字節必然是全0。根據這一條件,通過搜索整個文件系統,找出其中符合條件的數據塊,若出現多個塊符合要求,則還需要根據其他條件區分。但不管怎樣,根據精確長度分析也是恢復數據的一個策略。
Copyright © Linux教程網 All Rights Reserved