这个cli_untgz函数,是用来解压CVD文件的。

那么,就刚先搞清楚CVD文件的功能作用。下了源码,我们会发现,没有前面提到的*.mdb或者*.hbd等病毒签名文件。原因就是,那些文件都是由CVD文件解压生成的,是的,CVD是个病毒签名压缩文件。(下面是daily.cvd解压后的)

CVD文件,前512个bytes是一个特殊的头文件,在前面也提到过了(http://blog.csdn.net/betabin/article/details/7448447)。记录引擎病毒库的简单信息。然后后面的内容,曾经多次用UE打开,发现是乱码。所以,是个压缩文件。压缩类型,根据cli_untgz函数里面使用的gzread读取函数,可以猜到是使用zlib压缩库压缩的。然后根据函数内容,接着可以判断出,原信息是一个接着一个病毒库文件存储的。既是每个新的病毒库开始的前512bytes中,存储着名字及病毒签名数量。接着就是病毒签名信息。通过签名的病毒签名数量,可以判断正在读取的病毒签名是否读取完。

还是贴代码注释比较好理解:

  1. //解压CVD文件到临时目录中
  2. int cli_untgz(int fd, const char *destdir)
  3. {
  4. char *path, osize[13], name[101], type;
  5. char block[TAR_BLOCKSIZE];
  6. int nbytes, nread, nwritten, in_block = 0, fdd;
  7. unsigned int size, pathlen = strlen(destdir) + 100 + 5;
  8. FILE *outfile = NULL;
  9. struct stat foo;
  10. gzFile *infile;
  11.  
  12. //提示
  13. cli_dbgmsg("in cli_untgz()\n");
  14.  
  15. //dup复制文件描述符
  16. if((fdd = dup(fd)) == -1) {
  17. cli_errmsg("cli_untgz: Can't duplicate descriptor %d\n", fd);
  18. return -1;
  19. }
  20.  
  21. //打开文件
  22. if((infile = gzdopen(fdd, "rb")) == NULL) {
  23. cli_errmsg("cli_untgz: Can't gzdopen() descriptor %d, errno = %d\n", fdd, errno);
  24. if(fstat(fdd, &foo) == 0)
  25. close(fdd);
  26. return -1;
  27. }
  28.  
  29. //路径变量分配内存
  30. path = (char *) cli_calloc(sizeof(char), pathlen);
  31. if(!path) {
  32. cli_errmsg("cli_untgz: Can't allocate memory for path\n");
  33. gzclose(infile);
  34. return -1;
  35. }
  36.  
  37. //开始循环读取cvd文件内容
  38. while(1) {
  39.  
  40. //每次读取512个bytes部分
  41. nread = gzread(infile, block, TAR_BLOCKSIZE);
  42.  
  43. //上一种病毒库已经读完
  44. //且读不到下一种病毒库头信息时
  45. //结束
  46. if(!in_block && !nread)
  47. break;
  48.  
  49. if(nread != TAR_BLOCKSIZE) {
  50. cli_errmsg("cli_untgz: Incomplete block read\n");
  51. free(path);
  52. gzclose(infile);
  53. return -1;
  54. }
  55.  
  56. //上一种病毒库已经读完
  57. //进行下一种病毒库文件头信息处理
  58. //既是文件名、大小等
  59. if(!in_block) {
  60. //解压完病毒库
  61. if (block[0] == '\0') /* We're done */
  62. break;
  63.  
  64. //前99bytes中是文件名属性
  65. strncpy(name, block, 100);
  66. name[100] = '\0';
  67.  
  68. //该斜号分割不允许
  69. //在錡indows下应该也需要更改,不过不影响
  70. //name只能是文件名
  71. if(strchr(name, '/')) {
  72. cli_errmsg("cli_untgz: Slash separators are not allowed in CVD\n");
  73. free(path);
  74. gzclose(infile);
  75. return -1;
  76. }
  77.  
  78. //给路径变量赋值
  79. //设置为$tempdir$/newvirusfilename
  80. snprintf(path, pathlen, "%s/%s", destdir, name);
  81. cli_dbgmsg("cli_untgz: Unpacking %s\n", path);
  82.  
  83. //156位置文件标志
  84. type = block[156];
  85.  
  86. //判断类型
  87. switch(type) {
  88. case '0':
  89. case '\0':
  90. break;
  91. case '5':
  92. cli_errmsg("cli_untgz: Directories are not supported in CVD\n");
  93. free(path);
  94. gzclose(infile);
  95. return -1;
  96. default:
  97. cli_errmsg("cli_untgz: Unknown type flag '%c'\n", type);
  98. free(path);
  99. gzclose(infile);
  100. return -1;
  101. }
  102. //设置in_block参数
  103. //表示接下来开始写内容
  104. in_block = 1;
  105.  
  106. //关闭上一个病毒库文件指针
  107. if(outfile) {
  108. if(fclose(outfile)) {
  109. cli_errmsg("cli_untgz: Cannot close file %s\n", path);
  110. free(path);
  111. gzclose(infile);
  112. return -1;
  113. }
  114. outfile = NULL;
  115. }
  116.  
  117. //输出文件指针指向当前病毒库文件
  118. if(!(outfile = fopen(path, "wb"))) {
  119. cli_errmsg("cli_untgz: Cannot create file %s\n", path);
  120. free(path);
  121. gzclose(infile);
  122. return -1;
  123. }
  124.  
  125. //124后的为病毒签名数量
  126. strncpy(osize, block + 124, 12);
  127. osize[12] = '\0';
  128.  
  129. //读取数量,用于写是否结束判断标志
  130. if((sscanf(osize, "%o", &size)) == 0) {
  131. cli_errmsg("cli_untgz: Invalid size in header\n");
  132. free(path);
  133. gzclose(infile);
  134. fclose(outfile);
  135. return -1;
  136. }
  137.  
  138. } else { /* write or continue writing file contents */
  139. //写入path病毒文件
  140. nbytes = size > TAR_BLOCKSIZE ? TAR_BLOCKSIZE : size;
  141. nwritten = fwrite(block, 1, nbytes, outfile);
  142.  
  143. if(nwritten != nbytes) {
  144. cli_errmsg("cli_untgz: Wrote %d instead of %d (%s)\n", nwritten, nbytes, path);
  145. free(path);
  146. gzclose(infile);
  147. return -1;
  148. }
  149.  
  150. //减去已经写了的病毒签名数
  151. //判断是否结束
  152. size -= nbytes;
  153. if(size == 0)
  154. in_block = 0;
  155. }
  156. }
  157.  
  158. if(outfile)
  159. fclose(outfile);
  160.  
  161. gzclose(infile);
  162. free(path);
  163. return 0;
  164. }

原文:http://blog.csdn.net/betabin/article/details/7456873

ClamAV学习【9】——cvd文件解析及cli_untgz函数浏览的更多相关文章

  1. Android学习----AndroidManifest.xml文件解析

    一个Android应用程序的结构: 一.关于AndroidManifest.xml AndroidManifest.xml 是每个android程序中必须的文件.它位于整个项目的根目录,描述了pack ...

  2. mybatis 学习三 关键文件解析

    1:  mybatis-config.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYP ...

  3. 简单学习一下ibd数据文件解析

    来源:原创投稿 作者:花家舍 简介:数据库技术爱好者. GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 简单学习一下数据文件解析 这是尝试使用Golang语言简单解析My ...

  4. 八、Android学习第七天——XML文件解析方法(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 八.Android学习第七天——XML文件解析方法 XML文件:exten ...

  5. CocosBuilder 学习笔记(3) AnimationManager 与 ccbi 文件解析

    [CocosBuilder]学习笔记目录 1. 相关的类 先介绍和AnimationManager相关的几个类: CCBSequence 时间线.有成员duration(时间线时间,默认10秒).na ...

  6. 学习 WebService 第二步:知识准备——WSDL文件解析

    原文地址:https://www.cnblogs.com/yzw23333/p/7245104.html Web service中一个 WSDL 对应一个 web service地址. 可以想象成一个 ...

  7. android基础知识13:AndroidManifest.xml文件解析

    注:本文转载于:http://blog.csdn.net/xianming01/article/details/7526987 AndroidManifest.xml文件解析. 1.重要性 Andro ...

  8. Android之AndroidManifest.xml文件解析

    转自:Android学习笔记之AndroidManifest.xml文件解析 一.关于AndroidManifest.xml AndroidManifest.xml 是每个android程序中必须的文 ...

  9. [置顶] Android学习系列-Android中解析xml(7)

    Android学习系列-Android中解析xml(7) 一,概述 1,一个是DOM,它是生成一个树,有了树以后你搜索.查找都可以做. 2,另一种是基于流的,就是解析器从头到尾解析一遍xml文件.   ...

随机推荐

  1. 1 数据库开发--MySQL介绍

    1.数据库管理软件 C/S 并发.锁 :SQL语句.语法 基本管理和语法学习 一.介绍: mysql数据库管理软件: 套接字:服务端,客户端:客户端可访问服务端得数据 1.支持并发:操作得是共享得数据 ...

  2. 用API处理位图

    procedure TForm1.Button1Click(Sender: TObject); var dc : hdc; MemDc : hdc; MemBitmap : hBitmap; OldM ...

  3. 向ArcGIS的ToolBarControl中添加任意的windows组建的方法[转]

    向ArcGIS的ToolBarControl中添加任意的windows组建的方法[转] Link: http://www.cnblogs.com/mymhj/archive/2012/10/12/27 ...

  4. ajax传参里含有特殊字符的坑

    问题场景:今天在测试自己手上的页面功能时,发现一个小bug,在用ajax向后台发数据时,只要参数中出现一些特殊字符,控制台会报错http 400的问题,其实就是特殊字符服务器不能解析.好了,问题是找到 ...

  5. Varint 数值压缩

    [Varint 数值压缩] Varint 是一种紧凑的表示数字的方法.它用一个或多个字节来表示一个数字,值越小的数字使用越少的字节数.这能减少用来表示数字的字节数.比如对于 int32 类型的数字,一 ...

  6. s 销售视图数据

    INSERT,需将公司ID匹对到以下EXCEL表 INSERT,需将公司ID匹对到以下EXCEL表 [Public] ConnectString=host="siebel://10.10.0 ...

  7. memcache can't run as root without the -u switch

    memcached是一款高速.分布式的内存缓存系统.其官方主页在http://www.danga.com/memcached/1.安装前的准备要安装memcached,需要有libevent的支持.c ...

  8. asp.net 自定义节配置 (configSections下的section)

    <configuration> <configSections> <!--.自定义一个节 CustomSection --> <section name=&q ...

  9. Text Relatives

    [Text Relatives] With TextKit the resources at your disposal range from framework objects—such as te ...

  10. Atom 编辑器侧边栏忽略隐藏文件

    设置中配置需要忽略的文件后缀 package中找到treeview,勾选上这个配置就行