Linux打包軟件版本帶時間,帶你寫一個 linux 下的打包軟件 tar

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

值得注意的是,?tar?不是壓縮軟件,它只做把一堆文件/文件夾打包到一個文件(tar 文件)里的事情,而文件聯系,文件權限,相對的路徑等都會給你保存好。一開始設計是?tar?跟?gzip?只做一件事情,各司其事,后來發現太麻煩了,于是就把壓縮功能整合到 tar 里了。

-?Create?a?gzipped?archive:

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。

typedef?struct?{

char????????name[SIFS_MAX_NAME_LENGTH];?//?name?of?the?directory

time_t????????modtime;????//?time?last?modified?

uint32_t????????nentries;//?文件夾內的文件/文件夾數量

struct?{

SIFS_BLOCKID????blockID;????//?subdirectory?或者?file?的?blockID

uint32_t????fileindex;????//?重復文件的不同名字

}?entries[SIFS_MAX_ENTRIES];

}?SIFS_DIRBLOCK;

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

typedef?struct?{

time_t????????modtime;????//?time?first?file?added?

size_t????????length;????????//?length?of?files'?contents?in?bytes

unsigned?char????md5[MD5_BYTELEN];//the?MD5?cryptographic?digest?(a?summary)?of?the?files'?contents

SIFS_BLOCKID????firstblockID;//?the?block?number?(blockID)?of?the?files'?first?data-block

uint32_t????????nfiles;????????//?n?files?with?identical?contents

char????????filenames[SIFS_MAX_ENTRIES][SIFS_MAX_NAME_LENGTH];//?an?array?of?each?same?file's?name?and?its?modification?time.

}?SIFS_FILEBLOCK;

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

通用函數

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

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

void?read_vol_header(FILE?*vol,?SIFS_VOLUME_HEADER?*header){

fread(header,?sizeof(SIFS_VOLUME_HEADER),?1,?vol);

printf("header->blocksize?%zu,?header->nblocks?%u\n",?header->blocksize?,?header->nblocks);

}

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

void?read_bitmap(FILE?*vol,?SIFS_BIT?*bitmap,?int?nblocks){

int?size?=?nblocks?*?sizeof(SIFS_BIT);

fread(bitmap,?size,?1,?vol);

}

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

void?read_root_block(FILE?*vol,?SIFS_DIRBLOCK?*dirblock){

fread(dirblock,?sizeof(SIFS_DIRBLOCK),?1,?vol);

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 文件里的就要手動解析遞歸查路徑了。

void?read_route_names(char*?pathname,?char**?route_names,?int?*route_cnt)?{

char?*dir;

char?*pathname_to_split?=?copyStr(pathname);

strcpy(pathname_to_split,?pathname);

while?((dir?=?strsep(&pathname_to_split,?"/"))?!=?NULL)?{

route_names[*route_cnt]?=?copyStr(dir);

(*route_cnt)++;

}

}

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

實現

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

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

實現:

int?recursive_dirinfo(SIFS_DIRBLOCK?*cur_dir_block,?char?**route_names,?int?route_name_p,?int?route_cnt){

for(int?i=0;?inentries?;?i++)?{

int?blockid?=?cur_dir_block->entries[i].blockID;

if(bitmap[blockid]==SIFS_DIR)?{

SIFS_DIRBLOCK?dirblock;

int?start?=?sizeof(SIFS_VOLUME_HEADER)?+?header.nblocks*sizeof(SIFS_BIT);

read_dir_block(vol,?&dirblock,?blockid?*?blocksize,?start);

if(strcmp(dirblock.name,?route_names[route_name_p])?==?0)?{

if(route_name_p+2?==?route_cnt)?{

return?do_read_file(cur_dir_block,?route_names[route_name_p+1],?blockid);

}

return?recursive_dirinfo(&dirblock,?route_names,?route_name_p+1,?route_cnt);

}

}

}

return?1;

}

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

?寫文件就往 bitmap 一直找沒有用過的 block,夠寫文件就寫進去,文件夾更新一下信息。

?讀文件就是根據此文件夾 block,找里面的?newfileB

int?do_read_file(SIFS_DIRBLOCK?*parent_dir,?char?*filename,??int?parent_dir_block){

printf("do_find_file_info,?filename?%s\n",?filename);

for(int?i=1;?i

SIFS_FILEBLOCK?fileblock;

if(bitmap[i]==SIFS_FILE)?{

int?start?=?sizeof(SIFS_VOLUME_HEADER)?+?header.nblocks*sizeof(SIFS_BIT);

read_file_block(vol,?&fileblock,?i?*?blocksize,?start);

*nbytes?=?fileblock.length;

int?need_data_blocks?=?*nbytes?/?header.blocksize;

if(strcmp(fileblock.filenames[0],??filename)?==?0)?{

for(int?d_block_id?=?fileblock.firstblockID;?d_block_id?-?i?-1?

read_data_block(vol,?(char*)(*data)+(d_block_id?-?i?-1),?blocksize,?d_block_id?*?header.blocksize,?start);

}

return?0;

}

}

}

return?1;

}

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

struct?posix_header

{???????????????????????/*?byte?offset?*/

char?name[100];???????/*???0?*/???文件名

char?mode[8];?????????/*?100?*/???用戶權限

char?uid[8];??????????/*?108?*/???user?id

char?gid[8];??????????/*?116?*/???group?id

char?size[12];????????/*?124?*/???文件大小

char?mtime[12];???????/*?136?*/???修改時間

char?chksum[8];???????/*?148?*/???校驗值

char?typeflag;????????/*?156?*/???文件類型標志

char?linkname[100];???/*?157?*/???符號鏈接指向

char?magic[6];????????/*?257?*/

char?version[2];??????/*?263?*/

char?uname[32];???????/*?265?*/???user?name

char?gname[32];???????/*?297?*/???group?name

char?devmajor[8];?????/*?329?*/???設備文件?major

char?devminor[8];?????/*?337?*/???設備文件?minor

char?prefix[155];?????/*?345?*/

/*?500?*/

};

文件類型標志定義,包含了所有?Unix?系統中的文件類型

#define?REGTYPE??'0'????????????/*?regular?file?*/

#define?LNKTYPE??'1'????????????/*?link?*/

#define?SYMTYPE??'2'????????????/*?reserved?*/

#define?CHRTYPE??'3'????????????/*?character?special?*/

#define?BLKTYPE??'4'????????????/*?block?special?*/

#define?DIRTYPE??'5'????????????/*?directory?*/

#define?FIFOTYPE?'6'????????????/*?FIFO?special?*/

#define?CONTTYPE?'7'????????????/*?reserved?*/

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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/533813.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/533813.shtml
英文地址,請注明出處:http://en.pswp.cn/news/533813.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

優先隊列默認是小頂堆嗎_一分鐘帶你讀懂什么是堆?

堆其實就是一種特殊的隊列——優先隊列。 普通的隊列游戲規則很簡單:就是先進先出;但這種優先隊列搞特殊,不是按照進隊列的時間順序,而是按照每個元素的優先級來比拼,優先級高的在堆頂。 這也很容易理解吧,…

螺旋測微器b類不確定度_物理實驗直測量不確定度評估.ppt

物理實驗直測量不確定度評估直接測量不確定度評估 Gauss分布 測量列的平均值、標準差 A類不確定度 t分布 B類不確定度 直接測量的合成不確定度 Gauss分布 也稱正態分布。 δ的平均值等于0、方差為σ。 特征: 對稱性——大于平均值與小于平均值的概率相等&#xff1b…

python 執行shell_python執行shell命令的方法

python執行shell命令的方法 os模塊 os.system方式: import os os.system(top) os.system(cat /proc/cpuinfo) 說明 這個調用相當直接,且是同步進行的,程序需要阻塞并等待返回。 返回值是依賴于系統的,直接返回系統的調用返回值&am…

linux下c語言讀取roed文件,如何在Linux系統上安裝Android4.4.docx

Android (x86)項目致力于移植 Android系統到X86處理器上,使用戶可以更容易的在任何電腦上安裝Android。他們通過使用android源碼,增加補丁來使 Android能夠在X86處理器,筆記本電腦和平板 電腦下工作。前一段時間,項目組發布了最新…

微信小程序setinterval_簡單談談setTimeout與setInterval

感謝踩過的坑sf社區的第一篇文章。最近在做一個拍賣的微信小程序,用到了定時器setTimout和setInterval,簡單談談這兩個api。setTimeout最常見的用法就是第二種(第三種mdn文檔不推薦),如:var timeoutId setTimeout(function() {console.log(hello world!…

python 注釋一段話_Python快速入門(一)

引言Python作為一個,目前最火的編程語言之一,已經滲透到了各行各業。它易學好懂,擁有著豐富的庫,功能齊全。人生苦短,就用Python。這個快速入門系列分為六篇,包含了Python大部分基礎知識,每篇閱…

linux ibus獲取窗體位置,Ubuntu 12.04 顯示ibus 的輸入框

在虛擬機中安裝了Ubuntu 12.04,系統是英文版本的,我能接受,但是苦于沒有中文輸入法。起先,我是安裝SCIM,結果我折騰了半天,發現其只能在lib-office下使用。firefox,文字編輯器中都不能調出SCIM。無奈將其卸…

transporter上傳卡正在交付_【iOS】Xcode11使用Transporter將APP上傳到App Store,卡在正在驗證APP...

問題:在使用Transporter時,會卡主,一直顯示正在驗證APP在這里插入圖片描述解決方案一:利用V-P-N在這里插入圖片描述使用安全上網(V-P-N),雙擊打開iTMSTransporter,等待幾分鐘lichuangMacBook-Pro-3 ~ % /Ap…

python練手經典100例微盤_20個Python練手經典案例,能全做對的人確實很少!

100個Python練手小程序,學習python的很好的資料,覆蓋了python中的每一部分,可以邊學習邊練習,更容易掌握python。 如果你感覺學不會?莫慌,小編推薦大家加入群, 前面548中間377后面875&#xff0…

小紅帽linux各功能中英,英文短劇《小紅帽》劇本臺詞完整版---中英對照文本版...

大灰狼和小紅帽的故事紅帽第一場:小紅帽家 媽媽: (媽媽拿著一個籃子,把桌子上的水果放在籃子里) 小紅帽唱著歌,歡快地跑進來)Hi,mummy, what are you doing? 嘿,媽媽 你在什么? 媽媽: (一邊把水…

uipath循環datatable_UiPath之DataTable轉換為List和Array

今天給大家分享一下,如何將DataTable轉為List和Array,為此小U也花了不少時間研究,最后發現沒有那么復雜。先來說說List和Array的區別:List:就像一個鏈條,存儲數據的空間可以不連續。Array:就像一…

python批量下載文件教程_Python抓包菜鳥教程:批量下載圖片的方法,電腦和手機都能用...

筆者看上了一組圖集,然后準備一張一張下載時,瞄了一眼,這組圖集還有100,好吧,我酸了。 筆者就是試試工具,你們別像我這樣用,這么好的工具,做自媒體,那絕對了那如何批量下…

esxi掛載Linux的nfs盤,ESXi安裝centos7掛載群暉NFS

前段時間折騰了ESXi,然后無盡的折騰接踵而來,今天要說的是如何安裝centos7并掛載群暉虛擬機的NFS共享文件夾直接步入正題!先是下載centos7鏡像,因為我是用來當服務器的,所以只需要minimal版即可【centos下載鏈接】自己…

python使用的編輯器_我用過的最好的python編輯器PyScripter

用了IDLE, PythonWin等幾個python編輯器,在代碼補全、參數提示等功能上都非常不滿意。 終于找到PyScripter并且試用了一下,代碼補全、參數提示等功能非常強大。這個功能其實非常重要,可以大大提高開發效率,減少出錯。很滿意.PyScr…

linux is not unix由來,一些奇怪的 unix 指令名字的由來(轉)

一些奇怪的 unix 指令名字的由來(轉)[more]一些奇怪的 unix 指令名字的由來awk "Aho Weinberger and Kernighan"這個語言以作者 Al Aho, Peter Weinberger 和 Brian Kernighan 的姓來命名。grep "Global Regular Expression Print"grep 來自 ed 的列印所…

python discuz_pythonDiscuz發帖器的實現

網絡技術需要大家共同分享,不能閉門造車,下面是bj-dnsCom提示:首先要清楚discuz論壇發帖的流程,簡單地說就是以下流程:進入登錄頁 ->登錄 -> 進入版面 ->發帖 首先要清楚discuz論壇發帖的流程,簡單地說就是以…

基于linux的業設計課題,基于linux下智能手機的設計與制作 畢業設計.doc

本科生畢業論文(設計)題 目: 基于linux下智能手機的設計與制作目錄1. 緒論11.1 嵌入式系統的應用前景11.2linux操作系統21.2.1Linux介紹22.硬件、軟件介紹32.1S3c2440知識32.1.1S3c2440系統結構介紹32.1.2arm實驗儀介紹72.2 GPRS無線模組92.2.1 GPRS概述及工作原理9…

excel文件導入hive亂碼_將excel中的數據導入hive

步驟一:將excel另存為txt文檔(文本文件(制表符分割))假設名字為CompanyCode.txt步驟二,將該txt文件導入Linux指定目錄中步驟三,轉換編碼格式,在指定目錄下執行如下命令:piconv -f gb2312 -t UTF-8 CompanyCode.txt &g…

傳統的6d位姿估計fangfa1_李飛飛團隊最新論文:基于anchor關鍵點的類別級物體6D位姿跟蹤...

點擊上方“3D視覺工坊”,選擇“星標”干貨第一時間送達簡介作者提出了一種基于RGB-D的深度學習方法6PACK,能夠實時的跟蹤已知類別物體。通過學習用少量的3D關鍵點來簡潔地表示一個物體,基于這些關鍵點,通過關鍵點匹配來估計物體在…

c語言的程序結構語序,第3章 C語序結構.doc

第3章 C語序結構第三章 基本語句本章要求:1.表達式語句,空語句,復合語句2.數據的輸入與輸出,輸入,輸出函數的調用C語句概述C程序的執行部分是由語句組成的。 程序的功能也是由執行語句實現的。3.1 賦值語句賦值語句: 是由賦值表達式再加上分號構成的表達…