分享
 
 
 

gzip-1.2.4程序分析

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

gzip-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<<BITS);

#else

DECLARE(ush, tab_prefix0, 1L<<(BITS-1));

DECLARE(ush, tab_prefix1, 1L<<(BITS-1));

#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编码压缩,见RFC1951的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) 若找到匹配内容,则输出<length,distence>对的编码,否则输出字符编码。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有