成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

帶你寫一個Linux 下的打包軟件 Tar

系統 Linux
相信你對 linux 的 .tar.gz 有點熟悉,這就是先 tar 打包(.tar 后綴),再對此 tar 文件用 gzip 壓縮(.tar.gz)的后綴名。

[[427101]]

相信你對 linux 的 .tar.gz 有點熟悉,這就是先 tar 打包(.tar 后綴),再對此 tar 文件用 gzip 壓縮(.tar.gz)的后綴名。

值得注意的是, tar 不是壓縮軟件,它只做把一堆文件/文件夾打包到一個文件(tar 文件)里的事情,而文件聯系,文件權限,相對的路徑等都會給你保存好。

一開始設計是 tar 跟 gzip 只做一件事情,各司其事,后來發現太麻煩了,于是就把壓縮功能整合到 tar 里了。

  1. Create a gzipped archive: 
  2.     tar czf target.tar.gz file1 file2 file3 

最近學習 OS 時寫了一個類似 tar 的項目,那么今天就趁熱打鐵簡單說一下如何寫一個打包軟件,這個軟件會將重復的文件內容通過 md5 比較,復用舊的內容。

基本單位 block

block 可以理解為文件系統的最小單位,分別有以下類型:

  • directory block,文件夾 block,存儲文件夾 meta 信息;
  • file block,文件 block,存儲文件 meta 信息;
  • data block,只用來存文件內容;

Directory block,注意的是 entry 里要有 fileindex 來存儲重復文件的 name 的下標。

同時,給 項目一個 root dir。

  1. typedef struct { 
  2.     char        name[SIFS_MAX_NAME_LENGTH]; // name of the directory 
  3.     time_t        modtime;    // time last modified <- time() 
  4.  
  5.     uint32_t        nentries;// 文件夾內的文件/文件夾數量 
  6.     struct { 
  7.         SIFS_BLOCKID    blockID;    // subdirectory 或者 file 的 blockID 
  8.         uint32_t    fileindex;    // 重復文件的不同名字 
  9.     } entries[SIFS_MAX_ENTRIES]; 
  10. } SIFS_DIRBLOCK; 

文件 Block,length 就是有多少 bytes 的文件內容,之后用來算有多少個 data block,firstblockID 記錄第一個數據 block 的 id,nfiles 記錄有多少重復內容的文件數量了,filenames 就是重復此文件 block 的文件內容的文件名字。

  1. typedef struct { 
  2.     time_t        modtime;    // time first file added <- time() 
  3.     size_t        length;        // length of files' contents in bytes 
  4.  
  5.     unsigned char    md5[MD5_BYTELEN];//the MD5 cryptographic digest (a summary) of the files' contents 
  6.     SIFS_BLOCKID    firstblockID;// the block number (blockID) of the files' first data-block 
  7.  
  8.     uint32_t        nfiles;        // n files with identical contents 
  9.     char        filenames[SIFS_MAX_ENTRIES][SIFS_MAX_NAME_LENGTH];// an array of each same file's name and its modification time
  10. } SIFS_FILEBLOCK; 

bitmaps數組,記錄了每個 block 的類型,有:文件、文件夾以及data block 三種類型。

通用函數

就讓大家看看關鍵函數好了:

讀 tar 后的文件的 meta 頭,記錄了 block 的大小( blocksize) 以及多少個 blocks。

  1. void read_vol_header(FILE *vol, SIFS_VOLUME_HEADER *header) { 
  2.     fread(header, sizeof(SIFS_VOLUME_HEADER), 1, vol); 
  3.     printf("header->blocksize %zu, header->nblocks %u\n", header->blocksize , header->nblocks); 

bitmap,每次操作 tar 文件都要讀的。

  1. void read_bitmap(FILE *vol, SIFS_BIT *bitmap, int nblocks) { 
  2.     int size = nblocks * sizeof(SIFS_BIT); 
  3.     fread(bitmap, size, 1, vol); 

root_block 同理,讀和寫啥東西都要從 root block、root dir 出發。

  1. void read_root_block(FILE *vol, SIFS_DIRBLOCK *dirblock){ 
  2.     fread(dirblock, sizeof(SIFS_DIRBLOCK), 1, vol); 
  3.     printf("read_root_block finish, dirblock.name: %s, dirblock.entrieds: %d, dirblock.modtime %ld\n", dirblock->name, dirblock->nentries,dirblock->modtime); 

路徑嘛,你懂的,./sifs_put volumn ~/res.txt /dirB/subdirB/subsubdir/newfileB,要讀的內容可以靠 read 函數解決,但是寫到 tar 文件里的就要手動解析遞歸查路徑了。

  1. void read_route_names(char* pathname, char** route_names, int *route_cnt) { 
  2.     char *dir; 
  3.     char *pathname_to_split = copyStr(pathname); 
  4.     strcpy(pathname_to_split, pathname); 
  5.     while ((dir = strsep(&pathname_to_split, "/")) != NULL) { 
  6.         route_names[*route_cnt] = copyStr(dir); 
  7.         (*route_cnt)++; 
  8.     } 

以上幾乎是 mkdir,rmdir,writefile,readfile,putfile 等等操作都要做的。

實現

然后,應該舉一個 readfile 的例子就可以做代表了。

  1. int recursive_dirinfo(SIFS_DIRBLOCK *cur_dir_block, char **route_names, int route_name_p, int route_cnt); 

實現:

  1. int recursive_dirinfo(SIFS_DIRBLOCK *cur_dir_block, char **route_names, int route_name_p, int route_cnt) { 
  2.     for(int i=0; i<cur_dir_block->nentries ; i++) { 
  3.         int blockid = cur_dir_block->entries[i].blockID; 
  4.         if(bitmap[blockid]==SIFS_DIR) { 
  5.             SIFS_DIRBLOCK dirblock; 
  6.             int start = sizeof(SIFS_VOLUME_HEADER) + header.nblocks*sizeof(SIFS_BIT); 
  7.             read_dir_block(vol, &dirblock, blockid * blocksize, start); 
  8.             if(strcmp(dirblock.name, route_names[route_name_p]) == 0) { 
  9.                 if(route_name_p+2 == route_cnt) { 
  10.                     return do_read_file(cur_dir_block, route_names[route_name_p+1], blockid); 
  11.                 } 
  12.                 return recursive_dirinfo(&dirblock, route_names, route_name_p+1, route_cnt); 
  13.             } 
  14.         } 
  15.     } 
  16.     return 1; 

以``./sifs_put volumn ~/res.txt /dirB/subdirB/subsubdir/newfileB 為例子,如果遞歸找到 subsubdir`這個文件夾 block,進行相應操作:

  • 寫文件就往 bitmap 一直找沒有用過的 block,夠寫文件就寫進去,文件夾更新一下信息。
  • 讀文件就是根據此文件夾 block,找里面的 newfileB
  1. int do_read_file(SIFS_DIRBLOCK *parent_dir, char *filename,  int parent_dir_block) { 
  2.     printf("do_find_file_info, filename %s\n", filename); 
  3.     for(int i=1; i<header.nblocks ; i++) { 
  4.         SIFS_FILEBLOCK fileblock; 
  5.         if(bitmap[i]==SIFS_FILE) { 
  6.             int start = sizeof(SIFS_VOLUME_HEADER) + header.nblocks*sizeof(SIFS_BIT); 
  7.             read_file_block(vol, &fileblock, i * blocksize, start); 
  8.             *nbytes = fileblock.length; 
  9.             int need_data_blocks = *nbytes / header.blocksize; 
  10.             if(strcmp(fileblock.filenames[0],  filename) == 0) { 
  11.                 for(int d_block_id = fileblock.firstblockID; d_block_id - i -1 < need_data_blocks; d_block_id++) { 
  12.                     read_data_block(vol, (char*)(*data)+(d_block_id - i -1), blocksize, d_block_id * header.blocksize, start); 
  13.                 } 
  14.                 return 0; 
  15.             } 
  16.  
  17.         } 
  18.     } 
  19.     return 1; 

而真實的 tar 自然更復雜,還要記錄用戶權限、用戶、group文件等等:

  1. struct posix_header 
  2. {                       /* byte offset */ 
  3.   char name[100];       /*   0 */   文件名 
  4.   char mode[8];         /* 100 */   用戶權限 
  5.   char uid[8];          /* 108 */   user id 
  6.   char gid[8];          /* 116 */   group id 
  7.   char size[12];        /* 124 */   文件大小 
  8.   char mtime[12];       /* 136 */   修改時間 
  9.   char chksum[8];       /* 148 */   校驗值 
  10.   char typeflag;        /* 156 */   文件類型標志 
  11.   char linkname[100];   /* 157 */   符號鏈接指向 
  12.   char magic[6];        /* 257 */    
  13.   char version[2];      /* 263 */ 
  14.   char uname[32];       /* 265 */   user name 
  15.   char gname[32];       /* 297 */   group name 
  16.   char devmajor[8];     /* 329 */   設備文件 major 
  17.   char devminor[8];     /* 337 */   設備文件 minor 
  18.   char prefix[155];     /* 345 */ 
  19.                         /* 500 */ 
  20. }; 
  21.  
  22. 文件類型標志定義,包含了所有 Unix 系統中的文件類型 
  23.  
  24. #define REGTYPE  '0'            /* regular file */ 
  25. #define LNKTYPE  '1'            /* link */ 
  26. #define SYMTYPE  '2'            /* reserved */ 
  27. #define CHRTYPE  '3'            /* character special */ 
  28. #define BLKTYPE  '4'            /* block special */ 
  29. #define DIRTYPE  '5'            /* directory */ 
  30. #define FIFOTYPE '6'            /* FIFO special */ 
  31. #define CONTTYPE '7'            /* reserved */ 

概覽如此,寫起來其實有點煩 - = -,有興趣的讀者可以寫寫。

責任編輯:武曉燕 來源: 山盡寫東西的cache
相關推薦

2021-06-26 16:24:21

Linux命令系統

2013-12-17 11:35:16

2009-10-21 11:16:23

Linux壓縮打包方法

2018-10-31 10:11:24

Python編程語言語音播放

2021-06-10 13:50:55

代碼開發數據庫

2021-08-03 09:07:39

GolangGrpc服務

2019-08-02 15:39:06

PythonLinuxJSON

2021-08-04 11:55:45

Python天氣查詢PySide2

2020-03-26 17:00:53

HashMapputJava

2015-09-09 13:29:17

FISHShellLinux

2020-08-25 07:29:48

2020-06-23 10:03:33

版本控制項目

2017-04-26 14:48:01

Chrome程序擴展

2021-09-07 07:34:42

CSS 技巧代碼重構

2021-09-08 08:36:50

ncursesLinux猜謎游戲

2023-04-07 15:45:13

Emojicode開源編碼語言

2010-04-19 17:21:36

Oracle寫文件

2014-02-14 09:37:01

JavascriptDOM

2017-11-27 15:17:24

PythonMonkey腳本

2017-09-20 16:39:31

云主機網站MySQL
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品美女久久久 | 亚洲欧美在线视频 | aaaaaaa片毛片免费观看 | 日韩中出| 亚洲欧美一区二区三区在线 | 欧美亚洲视频 | 黄色片亚洲 | 成人h动漫精品一区二区器材 | 欧美日韩综合 | 欧美激情在线精品一区二区三区 | а_天堂中文最新版地址 | 久久久久久久电影 | 久久免费视频2 | 成人高潮片免费视频欧美 | 日本免费一区二区三区视频 | 国产一级视频免费播放 | 91精品久久久久久久久 | 中文字幕在线观看视频网站 | 亚洲精品电影在线观看 | 在线免费观看黄色 | 欧美精品在线观看 | 羞羞涩涩在线观看 | 精品乱子伦一区二区三区 | av黄色免费 | 一区在线观看 | 亚洲成人精品一区 | 黄色免费网| 亚洲三级国产 | 国家一级黄色片 | 亚洲一区二区三区四区五区午夜 | 亚洲视频在线观看 | 国产精品国产自产拍高清 | 久久精品国产一区 | 中文字幕国产高清 | 免费看大片bbbb欧美 | 中文字幕一区二区三区四区五区 | 一级在线毛片 | 成人免费网站视频 | 国产日产久久高清欧美一区 | 亚洲久在线 | 夜夜爽99久久国产综合精品女不卡 |