tar在unix系統中是常被用來把許多檔案打包成一個檔案

和一般我們常見的壓縮檔(.zip .rar .7z)比較不同的就是

使用者可以選擇要用壓縮的方式或是不壓縮的方式來製作tar檔

下面wiki的網站有tar很詳細的介紹

http://en.wikipedia.org/wiki/Tar_file_format

這次作業是要寫出一個可以解讀一個tar檔裡所有資料的介紹

像是user id,group id 權限 檔名 檔案大小等

tar的sturct:

struct TarHeader {
    char filename[100];
    char filemode[8];
    char userid[8];
    char groupid[8];
    char filesize[12];

    char mtime[12];
    char checksum[8];
    char type[1];
    char lname[100];

    /* USTAR Section */
    char USTAR_id[6];
    char USTAR_ver[2];
    char username[32];
    char groupname[32];
    char devmajor[8];
    char devminor[8];
    char prefix[155];
    char pad[12];

   struct TarHeader *next;// TarHeader *next;
//此行是自行加入 因要以link list的方式去做檔案的連接
};


執行範例:

$ ./mytar /student/test.tar
total 8 files
-rw-r--r-- root root 512 b9134001/512byte
drwxr-xr-x root             wheel         0 b9134001/hw1/
-rw-r--r--   root             wheel    256 b9134001/hw1/Makefile
-rw-r--r--   root             wheel    551 b9134001/hw1/tarfile.h
-rw-r--r--   root             wheel    318 b9134001/hw1/main.cpp
-rw-r--r--   root             wheel    148 b9134001/hw1/main.h
-rw-r--r--   root             wheel  1662 b9134001/hw1/tarfile.cpp
drwx------  b9134001 student 0 b9134001/hw3/
$ ./mytar mytar
Not a ustar file.

我把這次作業比較值得注意的部份筆記一下

1. seekg , read的使用

   作業最常會使用的應該就是這兩個member fucntions

   主要是分別控制我們讀進來資料流的位置及讀取範圍

  * seekg(offset,postion)

     ex:
         inStream.seekg(0,ios::beg);   
         //資料流指標從InStream的開頭位置位移0個byte

 *read(storage variable,offset)
    
    ex:
        inStream.read(ptr->filename,100);  
        //目前資料流指標往右位移100個byte的資料存入ptr->name
 
    至於為什麼會常用到這兩個function呢?

    因為我們可以從上面tar的struct看到 
 
    很多檔案資訊都是分散於資料流中不同的位置且佔不同大小
 
    所以我們必須利用這兩個函式去存取我們真正需要的資料

2.各項目的轉換


   知道了上面的用法後 我們就可以取出我們要的東西

   其中"檔案權限" "檔案大小"的轉換是要特別注意的

  
  一、檔案權限
 
  檔案權限就是我們在linux下看到的 r w x
  
   r:readable  w:writable x:executable
 
   然後又可分為

  owner  (此檔案擁有者的權限)
  group  (與此檔案擁有者同群組的權限)
  other   (其他不相干人的權限)

  所以說 如果看到    rwx           rwx        rwx
                               (owner)   (group)  (other)

  就表示任何在這台主機上的使用者

  都能對此檔案做讀、寫、執行的動作

  而tar檔中以0~7來表示權限  

   ex:   rwx rwx rwx =777 (所有人都能讀寫執行)
           r --   ---   --x  =401 (owner可讀 other可執行)

  所以我們從tar檔取出權限的資料應該有三組0~7的數值

  那要如何把這三組數字轉成我們要的rwx格式呢

  我用的方式是把八種方式建表= =+

  也就是

   const string Mode[8]={"---","--x","-w-","-wx","r--","r-x","rw-","rwx"};

   如果看到取到的資料是755 就直接分三次丟到table裡直接轉換

   二、檔案大小

   如果有看tar檔的介紹 應該知道為了要讓tar能讓不同系統都看得懂

   他裡面的文字都是用ASCII來做編碼

   而其中檔案大小又是以八進位來表示大小
 
   比如說我們從tar檔取到檔案大小資料為221
 
   那就是實際我們145byte

   所以我還是建表.....=  =+

   const string OctToBin[8]={"000","001","010","011","100","101","110","111"};

  首先先將讀到的資料減掉'0'  因為上面有提到說他是以ASCII做編碼

  像'1' 他的int值就是 49   所以我們減掉'0'(int  48)取得int 1

  把所得值丟進table 把轉換好的二進位數字串起來(strcat)

  再用pow函式傳換成十進位

  (助教: 這真是特別.....XD)

3.不同檔案間的連接

  tar檔的內容排列示意圖為下:
 
 
 
我們可以從tar 的struct 算出他是以512byte為一個block

當檔案內容大於512時 他所占block就會增加

在讀下一個檔案時 資料流指標的位移就要多一個block

所以當我們要讀下一個檔案資訊時 就要依據上一個檔案大小

做我們資料流指標的位移

最後再用link list的方式把我們所有檔案資串起來

以計算此tar的檔案個數

4.其他

其他像user id groupid的東西

都只是透過1的方式去讀出  沒啥好講
--------------------------------------------------------------------

這次作業 我想除了是訓練對於資料流的操控外

還有就是文件拿到  怎麼透過文件的內容

去實做出功能的能力

還有就是建表的威力展現XD 




創作者介紹

Humdrum Moli...

molimomo 發表在 痞客邦 PIXNET 留言(0) 人氣()