gzip-1.2.4程式分析 (轉)
gzip-1.2.4程式分析 (轉)[@more@]-1.2.4分析
-1.2.4分析
一點說明:
在gzip.c中:
DECLARE(uch, inbuf, INBUFSIZ +INBUF_EXTRA);
DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
DECLARE(ush, d_buf, DIST_BUFSIZE);
DECLARE(uch, window, 2L*WSIZE);
#ifndef MAXSEG_64K
DECLARE(ush, tab_prefix, 1L<#else
DECLARE(ush, tab_prefix0, 1L< DECLARE(ush, tab_prefix1, 1L<#endif
實際上定義了一些陣列:inbuf,outbuf,d_buf,window,tab_prefix,tab_prefix0,tabfix1.
1/
==================================================================================
入口程式:gzip-1.2.4/gzip.c
: int main (argc, argv)
int argc;
char **argv;
功能: 1)透過命令內容(gzip,gunzip,unzip等),設定操作型別(或是解壓縮)。
2)透過引數,設定一些全域性變數的值,對我們而言,有用的是:ascii(表示
為文字,可以根據本地的換行符來代替解壓後的檔案中的換行符)、decompress(表示進行解壓操作)和level(轉換操作的級別-進行更快
的轉換還是進行更大壓縮比的轉換,當然,這隻對壓縮而言)。
3)為輸入、輸出及視窗的緩衝分配。
4)treat_file(argv[optind++]);對檔案進行操作。
DECLARE(ush, tab_prefix0, 1L< DECLARE(ush, tab_prefix1, 1L<#endif
實際上定義了一些陣列:inbuf,outbuf,d_buf,window,tab_prefix,tab_prefix0,tabfix1.
1/
==================================================================================
入口程式:gzip-1.2.4/gzip.c
: int main (argc, argv)
int argc;
char **argv;
功能: 1)透過命令內容(gzip,gunzip,unzip等),設定操作型別(或是解壓縮)。
2)透過引數,設定一些全域性變數的值,對我們而言,有用的是:ascii(表示
為文字,可以根據本地的換行符來代替解壓後的檔案中的換行符)、decompress(表示進行解壓操作)和level(轉換操作的級別-進行更快
的轉換還是進行更大壓縮比的轉換,當然,這隻對壓縮而言)。
3)為輸入、輸出及視窗的緩衝分配。
4)treat_file(argv[optind++]);對檔案進行操作。
2/
==================================================================================
函式: local void treat_file(iname)
char *iname;
引數: 為檔名稱;
功能: 1)得到輸入的檔案的狀態:name,size,time,mode等。
2)建立輸出檔案的名稱。
3)當進行解壓操作時,呼叫 local int get_method(in) 來得到gz檔案的壓縮方法。
4)如果命令列中的引數-l,則呼叫do_list()顯示檔案資訊。
5)呼叫local int create_outfile()建立輸出檔案。
6) 呼叫(*work)(ifd, ofd)進行壓縮、解壓縮的操作。這時的work指標被get_method()
函式置為unzip()函式(解壓時),或是為預設的zip()函式。在解壓縮時,
這個過程是在迴圈中的,因為可能會包含多個檔案。
3/
==================================================================================
函式: local int get_method(in)
int in; /* input file descriptor */
引數: 檔名稱
功能: 1)驗證第一第二位元組是否為0x1F,0x8B。
2)驗證第三位元組是否為0x08(deflate)。
3)設定函式指標work = unzip。(work的預設值是zip)
4)得到做為flags的第四位元組。
5)如果設定了第1、5、6、7位,則給出錯誤提示。(編號0到7是從最低位開始)
6)將第5到8位元組中的時間值儲存在全域性變數time_stamp中。
7)跳過第9位元組(壓縮時採用的演算法-更快或是比例更高)和
第10位元組(壓縮時的操作)。
8)如果設定了flags的第1位,則得到當前檔案的編號
9)如果設定了flags的第2位(存在有附加的內容),則得到附加內容的長度,
並跳過這部分內容。
10)如果設定了flags的第3位(存在有原始檔案的名稱),則得到原始檔案的名稱。
11)如果設定了flags的第4位(存在一段不用解析的內容,是給人提供可讀資訊的),
跳過這部分可讀資訊。
12) 設定頭部資訊的長度:header_bytes,包括了最後的CRC及檔案長度部分。
返回: 函式壓縮方法(一般為“deflate”,程式中的返回值為8)
4/
==================================================================================
在檔案gzip-1.2.4/unzip.c中:
函式: int unzip(in, out)
int in, out; /* input and output file descriptors */
引數:為輸入、輸出檔案。
功能: 1)初始化全域性變數crc。
2)呼叫函式inflate()進行解碼操作。
3)得到原來檔案中儲存的CRC及長度值。如果與當前計算出的值不同,則產生提示。
5/
==================================================================================
在檔案gzip-1.2.4/inflate.c中:
函式: int inflate()
說明: ulg bb; /* 是 bit buffer */
unsigned bk; /* 是bit buffer中還有多少位,即剩餘的位數 */
功能: 1) 迴圈呼叫inflate_block(&e),一塊一塊的解壓資料。
2)若bk>-8,即bb中有完整的位元組,則將此位元組放回輸入中。
3)輸出解壓得到的內容。
6/
==================================================================================
在檔案gzip-1.2.4/inflate.c中:
函式: int inflate_block(e)
int *e; /* last block flag */
引數:如果是1,是說明當前塊是最後一塊。
功能: 1)得到第一位,這一位說明當前塊是否為最後一塊(0,不是;1,是)並相應的設定引數。
2)得到下兩位的值:
0,本塊沒有壓縮,
1,用固定的Huffman編碼壓縮,見1951的3.2.6節。
2,用動態的Huffman編碼壓縮,見RFC1951的3.2.7節。
3)根據前面得到的值,呼叫不同的函式解壓:
inflate_stored(); 對於未壓縮的資料,呼叫這個函式。
inflate_fixed(); 對於用固定的Huffman編碼壓縮的資料,呼叫這個函式。
inflate_dynamic(); 對於用動態的Huffman編碼壓縮的資料,呼叫這個函式。
7/
==================================================================================
在檔案gzip-1.2.4/inflate.c中:
函式: int inflate_stored()
功能: 處理非壓縮的資料內容
1)丟棄不足一位元組的位。由於非壓縮的資料中,內容都是以位元組為單位的,所以原來按
位讀取的時候,會剩餘不足一位元組位內容,現在要去掉這些位。
2)讀入兩位元組的內容,其值是未壓縮的資料長度。再讀入兩位元組的內容,其值應該是前
兩位元組所表示的長度的補碼,若不是,則錯誤。
3)逐位元組的讀入內容,並輸出到輸出檔案中。
8/
==================================================================================
在檔案gzip-1.2.4/inflate.c中:
函式: int inflate_fixed()
功能: 用固定的Huffman編碼壓縮的資料
1) 為0至287的文字/length值設定編碼長度:
Lit Value Bits Codes
--------- ---- -----
0 - 143 8 00110000 through
10111111
144 - 255 9 110010000 through
111111111
256 - 279 7 0000000 through
0010111
280 - 287 8 11000000 through
11000111
2) 呼叫huft_build()建造文字/length值的Huffman樹
3) 設定所有distance值(從0至29)的編碼長度為5。
4) 呼叫huft_build()建造distance值的Huffman樹
5) 呼叫函式inflate_codes()進行解碼。
9/
==================================================================================
在檔案gzip-1.2.4/inflate.c中:
函式: int inflate_dynamic()
功能: 用動態的Huffman編碼壓縮的資料
1) 讀入5位的值HLIT,算出nl = 257+HLIT。這是需要編碼的最大值。
2) 讀入5位的值HDIST,算出nd = 1+HDIST。這是distance的最大值。
3) 讀入4位的值HCLEN,算出nb = 4+HCLEN。說明有多少種編碼長度。
4) 再讀入3*nb位,每三位的值表示用多少位來表示所對應的編碼長度。
5) 呼叫huft_build()建造編碼長度的Huffman樹。
6) 利用這個Huffman樹,對接下來的若干位解碼出nl+nd個值,這些值依次是0~nl-1
的編碼長度(對於文字/length平說),及0~nd-1的編碼長度(對於distance來說)。
7) 利用上面解碼出的兩組長度值,兩次呼叫huft_build()函式,建造兩個Huffman樹
(一個是為文字/length,另一個是為distance)。
8) 呼叫函式inflate_codes()進行解碼。
10/
==================================================================================
在檔案gzip-1.2.4/inflate.c中:
函式: int inflate_codes(tl, td, bl, bd)
struct huft *tl, *td; /* literal/length and distance decoder tables */
int bl, bd; /* number of bits decoded by tl[] and td[] */
引數: tl,td是進行Huffman編碼解碼時用到的結構體,由於length和distance用不同的編碼
方式,所以要有兩個指標進行解碼。
在兩種編碼中,用struct huft結構編碼時,分別以bl,bd位進行編碼。
功能: 用兩個以經做好的連結串列來進行解碼。
1) 解碼一個值X,如果0<=X<=255,則X是一個字元,輸出,迴圈1)。
2) 如果X==255,則說明塊結束,函式返回。
3) X>255,則說明讀到的是一個length值,根據這個值,及其後的附加位,得到真實的
length值。
4) 繼續讀入一個值,這個值是distance的標誌值,根據這個值及其後的附加位得到真實
的distance。
5) 在已經輸出的串中,向前查詢distance個位元組,複製length個位元組到輸出串的末尾。
6) 迴圈1)
11/
==================================================================================
在檔案gzip-1.2.4/inflate.c中:
函式: int huft_build() 和函式int huft_free()比較獨立,可以直接引用,不再分析。
功能: int huft_build() :建立Huffman解碼連結串列。
int huft_free() :清除連結串列。
12/
==================================================================================
在檔案gzip-1.2.4/zip.c中:
函式: int zip(in, out)
int in, out; /* input and output file descriptors */
引數:為輸入、輸出檔案。
功能:
1) 向輸出寫入三位元組:0x1F 0x8B 0x08。
2) 向輸出寫入一個含有8個標誌位的位元組。
3) 向輸出寫入4位元組的系統時間。
4) 初始化CRC的值。
5) 呼叫bi_init(out)初始化讀入位串的程式。
6) 呼叫ct_init()進行分配記憶體,初始化變數表,儲存原始檔案資訊的
操作。
7) 呼叫lm_init()為新檔案初始化“最長匹配”的程式。
8) 再向輸出寫入2位元組,一個為額外的標誌,一個為系統型別。
9) 如果需要,則儲存原始檔名稱。
10) 儲存頭部資訊的長度。
11) 呼叫函式deflate()壓縮。
12) 寫入4位元組的CRC值。
13) 寫入4位元組的原始內容長度值。
14)修改前面儲存的頭部資訊長度的值。
13/
==================================================================================
在檔案gzip-1.2.4/deflate.c中:
函式: ulg deflate()
功能: 壓縮資料。此函式透過一些複雜的演算法來進行壓縮操作,可以直接引用。
1) 如果需要壓縮,則呼叫函式deflate_fast(),然後返回。
2) 將當前內容插入到雜湊表中,並查詢最長匹配。
3) 若找到匹配內容,則輸出對的編碼,否則輸出字元編碼。
:namespace prefix = o ns = "urn:schemas--com::office" />
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10794571/viewspace-974312/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- qmail-local程式碼分析(轉)AI
- Linux核心分析--系統呼叫實現程式碼分析(轉)Linux
- Gmail程式資訊轉儲分析工具pdgmailAI
- 中文詞法分析的簡單程式 (轉)詞法分析
- 定時器時間資料轉換子程式分析 (轉)定時器
- Discuz!X升級/轉換程式GETSHELL漏洞分析
- ORACLE程式佔用CPU情況分析(轉載)Oracle
- tomcat程式意外退出的問題分析(轉)Tomcat
- SQL worm sapphire 關鍵程式碼分析 (轉)SQLWormAPP
- 利用Java編寫HTML檔案分析程式(轉)JavaHTML
- 微信小程式-開心大轉盤(圓盤指標)程式碼分析微信小程式指標
- Win2K下關聯程式/埠之程式碼初步分析(轉)
- 一個用Perl分析Apache Log的簡單程式(轉)Apache
- 對.NET Framework "事件"機制理解的程式碼分析 (轉)Framework事件
- duwamish7的一些程式碼分析總結 (轉)
- ORACLE常見錯誤程式碼的分析與解決(轉)Oracle
- 關於繼承內部類——java程式設計思想示例程式分析; (轉)繼承Java程式設計
- 轉轉OLAP自助分析實踐
- SWOT分析 (轉載)
- 程式碼分析
- 中綴轉字尾表示式思路分析和程式碼實現
- 劍指offer—58_2.左旋轉字串—分析及程式碼(Java)字串Java
- Linux作業系統的許可權程式碼分析【轉】Linux作業系統
- 追捕檔案WRY.DLL的淺顯分析及程式示例 (轉)
- 深入淺出分析Linux裝置驅動程式中斷(轉)Linux
- 情感分析資源 (轉)
- oracle 分析函式(轉)Oracle函式
- Oracle分析函式{轉}Oracle函式
- 成本效益分析(轉載)
- 叛逃者病毒分析(轉)
- linux核心分析筆記----中斷和中斷處理程式【轉】Linux筆記
- php4.0.0遠端溢位原始碼分析與測試程式 (轉)PHP原始碼
- Linux程式分析Linux
- AsyncTask 程式碼分析
- Perfview 分析程式效能View
- Swoole 程式模型分析模型
- 詞法分析程式詞法分析
- 分析古老的程式