这个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中,存储着名字及病毒签名数量。接着就是病毒签名信息。通过签名的病毒签名数量,可以判断正在读取的病毒签名是否读取完。

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

//解压CVD文件到临时目录中
int cli_untgz(int fd, const char *destdir)
{
char *path, osize[13], name[101], type;
char block[TAR_BLOCKSIZE];
int nbytes, nread, nwritten, in_block = 0, fdd;
unsigned int size, pathlen = strlen(destdir) + 100 + 5;
FILE *outfile = NULL;
struct stat foo;
gzFile *infile; //提示
cli_dbgmsg("in cli_untgz()\n"); //dup复制文件描述符
if((fdd = dup(fd)) == -1) {
cli_errmsg("cli_untgz: Can't duplicate descriptor %d\n", fd);
return -1;
} //打开文件
if((infile = gzdopen(fdd, "rb")) == NULL) {
cli_errmsg("cli_untgz: Can't gzdopen() descriptor %d, errno = %d\n", fdd, errno);
if(fstat(fdd, &foo) == 0)
close(fdd);
return -1;
} //路径变量分配内存
path = (char *) cli_calloc(sizeof(char), pathlen);
if(!path) {
cli_errmsg("cli_untgz: Can't allocate memory for path\n");
gzclose(infile);
return -1;
} //开始循环读取cvd文件内容
while(1) { //每次读取512个bytes部分
nread = gzread(infile, block, TAR_BLOCKSIZE); //上一种病毒库已经读完
//且读不到下一种病毒库头信息时
//结束
if(!in_block && !nread)
break; if(nread != TAR_BLOCKSIZE) {
cli_errmsg("cli_untgz: Incomplete block read\n");
free(path);
gzclose(infile);
return -1;
} //上一种病毒库已经读完
//进行下一种病毒库文件头信息处理
//既是文件名、大小等
if(!in_block) {
//解压完病毒库
if (block[0] == '\0') /* We're done */
break; //前99bytes中是文件名属性
strncpy(name, block, 100);
name[100] = '\0'; //该斜号分割不允许
//在錡indows下应该也需要更改,不过不影响
//name只能是文件名
if(strchr(name, '/')) {
cli_errmsg("cli_untgz: Slash separators are not allowed in CVD\n");
free(path);
gzclose(infile);
return -1;
} //给路径变量赋值
//设置为$tempdir$/newvirusfilename
snprintf(path, pathlen, "%s/%s", destdir, name);
cli_dbgmsg("cli_untgz: Unpacking %s\n", path); //156位置文件标志
type = block[156]; //判断类型
switch(type) {
case '0':
case '\0':
break;
case '5':
cli_errmsg("cli_untgz: Directories are not supported in CVD\n");
free(path);
gzclose(infile);
return -1;
default:
cli_errmsg("cli_untgz: Unknown type flag '%c'\n", type);
free(path);
gzclose(infile);
return -1;
}
//设置in_block参数
//表示接下来开始写内容
in_block = 1; //关闭上一个病毒库文件指针
if(outfile) {
if(fclose(outfile)) {
cli_errmsg("cli_untgz: Cannot close file %s\n", path);
free(path);
gzclose(infile);
return -1;
}
outfile = NULL;
} //输出文件指针指向当前病毒库文件
if(!(outfile = fopen(path, "wb"))) {
cli_errmsg("cli_untgz: Cannot create file %s\n", path);
free(path);
gzclose(infile);
return -1;
} //124后的为病毒签名数量
strncpy(osize, block + 124, 12);
osize[12] = '\0'; //读取数量,用于写是否结束判断标志
if((sscanf(osize, "%o", &size)) == 0) {
cli_errmsg("cli_untgz: Invalid size in header\n");
free(path);
gzclose(infile);
fclose(outfile);
return -1;
} } else { /* write or continue writing file contents */
//写入path病毒文件
nbytes = size > TAR_BLOCKSIZE ? TAR_BLOCKSIZE : size;
nwritten = fwrite(block, 1, nbytes, outfile); if(nwritten != nbytes) {
cli_errmsg("cli_untgz: Wrote %d instead of %d (%s)\n", nwritten, nbytes, path);
free(path);
gzclose(infile);
return -1;
} //减去已经写了的病毒签名数
//判断是否结束
size -= nbytes;
if(size == 0)
in_block = 0;
}
} if(outfile)
fclose(outfile); gzclose(infile);
free(path);
return 0;
}

原文: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. 使用openal与mpg123播放MP3,附带工程文件(转)

    使用openal与mpg123播放MP3,附带工程文件 使用openal和mpg123播放MP3文件 使用静态编译,相关文件都在附件里 相关工程文件:openal_mpg123_player.7z 使 ...

  2. js中获取页面元素节点的几种方式

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  3. PowerDesigner如何导出建表sql脚本(转)

    1 按照数据库类型,切换数据库. Database-> Change Current DBMS... 2 生成sql脚本 Database -> Database Generation 的 ...

  4. EmEditor的正则表达式

    前提是 "使用正则表达式"的复选框打上勾. 1 查找<>之间的字符串:   ".*?"2 查找双引号之间的字符串:   ".*?" ...

  5. ConcurrentHashMap的简单理解

    一.效率低下的HashTable容器HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈的情况下HashTable的效率非常低下.因为当一个线程访问HashTable的同 ...

  6. codeforces:MEX Queries分析和实现

    首先说明一下MEX,设S是自然数集合N的一个子集,那么S的MEX则为min(N\S),即不包含于S的最小自然数. 题目大意是存在一个空集S,提供n组输入(n<10^5),每组输入对应下面的一个指 ...

  7. 二叉树垂直遍历 · Binary Tree Vertical Order Traversal

    [抄题]: 给定二叉树,返回其节点值的垂直遍历顺序. (即逐列从上到下).如果两个节点在同一行和同一列中,则顺序应 从左到右. 给定一个二叉树 {3,9,20,#,#,15,7} 3 /\ / \ 9 ...

  8. JAVA-用HttpClient来模拟浏览器GET,POST

    一般的情况下我们都是使用IE或者Navigator浏览器来访问一个WEB服务器,用来浏览页面查看信息或者提交一些数据等等.所访问的这些页面有的仅仅是一些普通的页面,有的需要用户登录后方可使用,或者需要 ...

  9. COGS 2189 帕秋莉的超级多项式

    放模板啦! 以后打比赛的时候直接复制过来. 说句实话vector的效率真的不怎么样,但是似乎也还行,最主要是……写得比较爽. #include <cstdio> #include < ...

  10. 启动memcached

    /usr/local/bin/memcached -d -c -m -u root