吃饱饭继续浏览Manager.c的scanmanager函数,这个函数的功能吧,暂时理解如下。

接收一个命令行参数(经过处理的optstruct结构指针)。

然后根据选项判断文件类型种类,还有一些扫描选项。看到了AC-Only选项,可是没有BM-Only选项,不解。然后就进行了病毒库的加载和引擎的初始化,接着进行了一些扫描限制(扫描文件大小、数量、递归深度等)设定,还有扫描的文件类型(貌似上面的是用来构建引擎,现在的是用来设置扫描)。然后就是重点,针对文件名进行处理,判断是否是目录还是单个文件,调用不同的扫描函数。

代码注释如下:(应该不是完全正确的)

int scanmanager(const struct optstruct *opt)
{
mode_t fmode;
int ret = 0, extunpacker = 0, fmodeint, i, x;
unsigned int options = 0, dboptions = 0;
struct cl_engine *engine = NULL;
struct cl_limits limits;
struct passwd *user = NULL;
struct stat sb;
char *fullpath = NULL, cwd[1024]; //扫描文件类型判断
if(opt_check(opt, "unzip") || opt_check(opt, "unrar") || opt_check(opt, "arj") ||
opt_check(opt, "unzoo") || opt_check(opt, "jar") || opt_check(opt, "lha") ||
opt_check(opt, "tar") || opt_check(opt, "tgz") || opt_check(opt, "deb"))
extunpacker = 1; //获取CLAMAVUSER的用户信息,识别码和根目录
//参考passwd结构
/* njh@bandsman.co.uk: BeOS */
#if !defined(C_CYGWIN) && !defined(C_OS2) && !defined(C_BEOS) && !defined(C_WINDOWS)
if(extunpacker && !geteuid()) {
if((user = getpwnam(CLAMAVUSER)) == NULL) {
logg("!Can't get information about user "CLAMAVUSER" (required to run external unpackers)\n");
exit(60); /* this is critical problem, so we just exit here */
}
}
#endif //添加扫描选项
if(!opt_check(opt, "no-phishing-sigs"))
dboptions |= CL_DB_PHISHING; if(!opt_check(opt,"no-phishing-scan-urls"))
dboptions |= CL_DB_PHISHING_URLS;
if(opt_check(opt,"phishing-ssl")) {
options |= CL_SCAN_PHISHING_BLOCKSSL;
}
if(opt_check(opt,"phishing-cloak")) {
options |= CL_SCAN_PHISHING_BLOCKCLOAK;
} if(opt_check(opt, "dev-ac-only"))
dboptions |= CL_DB_ACONLY; //这个选项需要学习下,深度搜查用AC?
if(opt_check(opt, "dev-ac-depth"))
cli_ac_setdepth(AC_DEFAULT_MIN_DEPTH, atoi(opt_arg(opt, "dev-ac-depth"))); if(opt_check(opt, "detect-pua"))
dboptions |= CL_DB_PUA; //传说中的病毒库加载
if(opt_check(opt, "database")) {
if((ret = cl_load(opt_arg(opt, "database"), &engine, &info.sigs, dboptions))) {
logg("!%s\n", cl_strerror(ret));
return 50;
} } else {
char *dbdir = freshdbdir(); //病毒库更新后重新加载
if((ret = cl_load(dbdir, &engine, &info.sigs, dboptions))) {
logg("!%s\n", cl_strerror(ret));
free(dbdir);
return 50;
}
free(dbdir);
} if(!engine) {
logg("!Can't initialize the virus database\n");
return 50;
} //引擎构建
if((ret = cl_build(engine)) != 0) {
logg("!Database initialization error: %s\n", cl_strerror(ret));;
return 50;
} /* set limits */
//开始设置限制,应该是扫描大小等
memset(&limits, 0, sizeof(struct cl_limits)); //最大的扫描大小
if(opt_check(opt, "max-scansize")) {
char *cpy, *ptr;
ptr = opt_arg(opt, "max-scansize");
if(tolower(ptr[strlen(ptr) - 1]) == 'm') {
cpy = calloc(strlen(ptr), 1);
strncpy(cpy, ptr, strlen(ptr) - 1);
cpy[strlen(ptr)-1]='\0';
limits.maxscansize = atoi(cpy) * 1024 * 1024;
free(cpy);
} else
limits.maxscansize = atoi(ptr) * 1024;
} else
limits.maxscansize = 104857600; //最大文件大小
if(opt_check(opt, "max-filesize")) {
char *cpy, *ptr;
ptr = opt_arg(opt, "max-filesize");
if(tolower(ptr[strlen(ptr) - 1]) == 'm') {
cpy = calloc(strlen(ptr), 1);
strncpy(cpy, ptr, strlen(ptr) - 1);
cpy[strlen(ptr)-1]='\0';
limits.maxfilesize = atoi(cpy) * 1024 * 1024;
free(cpy);
} else
limits.maxfilesize = atoi(ptr) * 1024;
} else
limits.maxfilesize = 26214400; //最大文件数
if(opt_check(opt, "max-files"))
limits.maxfiles = atoi(opt_arg(opt, "max-files"));
else
limits.maxfiles = 10000; //最大递归深度
if(opt_check(opt, "max-recursion"))
limits.maxreclevel = atoi(opt_arg(opt, "max-recursion"));
else
limits.maxreclevel = 16; /* set options */
//设置选项,扫描文件类型相关
if(opt_check(opt, "disable-archive") || opt_check(opt, "no-archive"))
options &= ~CL_SCAN_ARCHIVE;
else
options |= CL_SCAN_ARCHIVE; if(opt_check(opt, "detect-broken"))
options |= CL_SCAN_BLOCKBROKEN; if(opt_check(opt, "block-encrypted"))
options |= CL_SCAN_BLOCKENCRYPTED; if(opt_check(opt, "no-pe"))
options &= ~CL_SCAN_PE;
else
options |= CL_SCAN_PE; if(opt_check(opt, "no-elf"))
options &= ~CL_SCAN_ELF;
else
options |= CL_SCAN_ELF; if(opt_check(opt, "no-ole2"))
options &= ~CL_SCAN_OLE2;
else
options |= CL_SCAN_OLE2; if(opt_check(opt, "no-pdf"))
options &= ~CL_SCAN_PDF;
else
options |= CL_SCAN_PDF; if(opt_check(opt, "no-html"))
options &= ~CL_SCAN_HTML;
else
options |= CL_SCAN_HTML; if(opt_check(opt, "no-mail")) {
options &= ~CL_SCAN_MAIL;
} else {
options |= CL_SCAN_MAIL; if(opt_check(opt, "mail-follow-urls"))
options |= CL_SCAN_MAILURL;
} if(opt_check(opt, "no-algorithmic"))
options &= ~CL_SCAN_ALGORITHMIC;
else
options |= CL_SCAN_ALGORITHMIC; //Linux下,需要获取设备号
//具体参见文件属性stat结构
#ifdef C_LINUX
procdev = (dev_t) 0;
if(stat("/proc", &sb) != -1 && !sb.st_size)
procdev = sb.st_dev;
#endif /* check filetype */
//遇到扫描目录的情况
if(opt->filename == NULL || strlen(opt->filename) == 0) { /* we need full path for some reasons (eg. archive handling) */
//获取当前工作目录
//获取到后调用目录扫描函数scandirs
if(!getcwd(cwd, sizeof(cwd))) {
logg("!Can't get absolute pathname of current working directory\n");
ret = 57;
} else
ret = scandirs(cwd, engine, user, opt, &limits, options); } else if(!strcmp(opt->filename, "-")) { /* read data from stdin */
ret = scanstdin(engine, &limits, options); } else {
//扫描文件的情况
char *thefilename;
for (x = 0; (thefilename = cli_strtok(opt->filename, x, "\t")) != NULL; x++) {
//fileinfo函数在clamscan的others.c里定义
//2代表获取文件权限
//有访问权限后找出最右边/的个数
if((fmodeint = fileinfo(thefilename, 2)) == -1) {
logg("^Can't access file %s\n", thefilename);
perror(thefilename);
ret = 56;
} else {
int slash = 1;
for(i = strlen(thefilename) - 1; i > 0 && slash; i--) {
if(thefilename[i] == '/')
thefilename[i] = 0;
else
slash = 0;
} fmode = (mode_t) fmodeint; //下面依旧是处理文件名的
if(extunpacker && (thefilename[0] != '/' && thefilename[0] != '\\' && thefilename[1] != ':')) {
/* we need to complete the path */
if(!getcwd(cwd, sizeof(cwd))) {
logg("!Can't get absolute pathname of current working directory\n");
return 57;
} else {
fullpath = malloc(512);
#ifdef NO_SNPRINTF
sprintf(fullpath, "%s/%s", cwd, thefilename);
#else
snprintf(fullpath, 512, "%s/%s", cwd, thefilename);
#endif
logg("*Full path: %s\n", fullpath);
}
} else
fullpath = thefilename; //开始区别扫描文件和文件夹
switch(fmode & S_IFMT) {
case S_IFREG:
ret = scanfile(fullpath, engine, user, opt, &limits, options);
break; case S_IFDIR:
ret = scandirs(fullpath, engine, user, opt, &limits, options);
break; default:
logg("!Not supported file type (%s)\n", thefilename);
ret = 52;
} if(extunpacker && (thefilename[0] != '/' && thefilename[0] != '\\' && thefilename[1] != ':')) {
free(fullpath);
fullpath = NULL;
}
}
free(thefilename);
}
} /* free the engine */
cl_free(engine); /* overwrite return code */
if(info.ifiles)
ret = 1;
else if(ret < 50) /* hopefully no error detected */
ret = 0; /* just make sure it's 0 */ return ret;
}

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

ClamAV学习【3】——scanmanager函数浏览的更多相关文章

  1. 学习js回调函数

    <!DOCTYPE HTML> <html> <head> <meta charset="GBK" /> <title> ...

  2. JavaScript学习03 JS函数

    JavaScript学习03 JS函数 函数就是包裹在花括号中的代码块,前面使用了关键词function: function functionName() { 这里是要执行的代码 } 函数参数 函数的 ...

  3. Matlab学习笔记 figure函数

    Matlab学习笔记 figure函数 matlab中的 figure 命令,能够创建一个用来显示图形输出的一个窗口对象.每一个这样的窗口都有一些属性,例如窗口的尺寸.位置,等等.下面一一介绍它们. ...

  4. iOS学习09C语言函数指针

    本次主要学习和理解函数指针 1.函数指针 void printValue(int number) { printf("number = %d\n", number); } int ...

  5. iOS学习05C语言函数

    本次主要是学习和理解函数,函数树状图如下: 1.函数的声明和定义 函数定义的四要素分别为: 返回值类型 :函数的结果值类型,函数不能返回数组. 指定返回类型是void类型说明函数没有返回值. 函数名 ...

  6. matlab学习笔记 bsxfun函数

    matlab学习笔记 bsxfun函数 最近总是遇到 bsxfun这个函数,前几次因为无关紧要只是大概看了一下函数体去对比结果,今天再一次遇见了这个函数,想想还是有必要掌握的,遂查了些资料总结如下. ...

  7. haskell学习笔记_函数

    一开始学习函数式编程语言就被告知函数式编程语言是一种“定义式”的语言,而不是一种命令式的语言,在学习haskell的函数语法时,此感觉更加强烈,haskell的函数定义倾向于一种类似C++里面的swi ...

  8. Haskell学习-高阶函数

    原文地址:Haskell学习-高阶函数 高阶函数(higher-order function)就是指可以操作函数的函数,即函数可以作为参数,也可以作为返回结果.有了这两个特性,haskell可以实现许 ...

  9. python入门学习:7.函数

    python入门学习:7.函数 关键点:函数 7.1 定义函数7.2 传递实参7.3 返回值7.4 传递列表7.5 传递任意数量的实参7.6 将函数存储在模块中 7.1 定义函数   使用关键字def ...

随机推荐

  1. 在VS2005编程中,有的时候DataGridView数据源有几个表的联合查询,而系统又有限制为一个表,怎么办?

    在VS2005编程中,有的时候DataGridView数据源有几个表的联合查询,而系统又有限制为一个表,怎么办? 解决方法:在SqlServer的企业管理器里增加一个视图吧!!!!!!!!(从来没用过 ...

  2. OpenCv dnn module -实时图像分类

    配置环境:OpenCv3.4, vs2013(x64),Win7.用OpenCv dnn module 实时检测摄像头,视频和图像的分类示例原代码为:https://docs.opencv.org/3 ...

  3. myeclipse10安装了activiti插件后创建BPMN 文件时报错,

    以上错误需要,下载一个补丁. 补丁地址:http://www.shareyx.com/blog/2 补丁的安装可以参考: http://jingyan.baidu.com/article/dca1fa ...

  4. Qt Thread

    Threading Classes (Qt help manual key words) These Qt Core classes provide threading support to appl ...

  5. Java文件下载详解

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException ...

  6. DataTable记录

    DataTable dt2 = dt.Copy();//复制结构和数据 //复制结构,不要数据 DataTable dt2 = new DataTable(); for (int i = 0; i & ...

  7. 在Qt(C++)中使用QThread实现多线程

    1. 引言 多线程对于需要处理耗时任务的应用很有用,一方面响应用户操作.更新界面显示,另一方面在"后台"进行耗时操作,比如大量运算.复制大文件.网络传输等. 使用Qt框架开发应用程 ...

  8. Laravel 使用 seeder 使用要点

    一.关于 DB use DB; 再使用 DB::table(database.table)->get(); 二.关于 ERROR 1366 (HY000): Incorrect string v ...

  9. mysql索引原理及用法

    MySQL索引原理及慢查询优化 Mysql explain用法和性能分析 MySQL 索引优化全攻略 1.索引作用 在索引列上,除了上面提到的有序查找之外,数据库利用各种各样的快速定位技术,能够大大提 ...

  10. CoreText

    [CoreText]  Core Text is designed for development of higher-level text-handling frameworks. General ...