183 lines
4.5 KiB
C
183 lines
4.5 KiB
C
|
#include "libclamav.h"
|
||
|
|
||
|
|
||
|
int detect_virus_files(char *file)
|
||
|
{
|
||
|
int fd, ret;
|
||
|
unsigned long int size = 0;
|
||
|
unsigned int sigs = 0;
|
||
|
long double mb;
|
||
|
const char *virname;
|
||
|
const char *filename;
|
||
|
struct cl_engine *engine;
|
||
|
struct cl_scan_options options;
|
||
|
|
||
|
filename = (const char *)file;
|
||
|
|
||
|
if ((fd = open(file, O_RDONLY)) == -1) {
|
||
|
printf("Can't open file %s\n", file);
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
if ((ret = cl_init(CL_INIT_DEFAULT)) != CL_SUCCESS) {
|
||
|
printf("Can't initialize libclamav: %s\n", cl_strerror(ret));
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
if (!(engine = cl_engine_new())) {
|
||
|
printf("Can't create new engine\n");
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
/* Example version macro usage to determine if new feature is available */
|
||
|
#if defined(LIBCLAMAV_VERSION_NUM) && (LIBCLAMAV_VERSION_NUM >= 0x090400)
|
||
|
/* Example feature usage lowering max scan time to 15 seconds. */
|
||
|
cl_engine_set_num(engine, CL_ENGINE_MAX_SCANTIME, 15000);
|
||
|
#endif
|
||
|
|
||
|
/* load all available databases from default directory */
|
||
|
if ((ret = cl_load(cl_retdbdir(), engine, &sigs, CL_DB_STDOPT)) != CL_SUCCESS) {
|
||
|
printf("cl_load: %s\n", cl_strerror(ret));
|
||
|
close(fd);
|
||
|
cl_engine_free(engine);
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
printf("Loaded %u signatures.\n", sigs);
|
||
|
|
||
|
/* build engine */
|
||
|
if ((ret = cl_engine_compile(engine)) != CL_SUCCESS) {
|
||
|
printf("Database initialization error: %s\n", cl_strerror(ret));
|
||
|
cl_engine_free(engine);
|
||
|
close(fd);
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
/* scan file descriptor */
|
||
|
memset(&options, 0, sizeof(struct cl_scan_options));
|
||
|
options.parse |= ~0; /* enable all parsers */
|
||
|
options.general |= CL_SCAN_GENERAL_HEURISTICS; /* enable heuristic alert options */
|
||
|
|
||
|
if ((ret = cl_scandesc(fd, filename, &virname, &size, engine, &options)) == CL_VIRUS) {
|
||
|
printf("Virus detected: %s\n", virname);
|
||
|
|
||
|
#if IS_MOVE
|
||
|
char temp[sizeof(file) + 3];
|
||
|
sprintf(temp, "rm_ %s", file);
|
||
|
//system("rm filename");
|
||
|
FILE *fp = popen(temp, "r");
|
||
|
pclose(fp);
|
||
|
fp = NULL;
|
||
|
#endif
|
||
|
} else {
|
||
|
if (ret == CL_CLEAN) {
|
||
|
printf("No virus detected.\n");
|
||
|
} else {
|
||
|
printf("Error: %s\n", cl_strerror(ret));
|
||
|
cl_engine_free(engine);
|
||
|
close(fd);
|
||
|
return 2;
|
||
|
}
|
||
|
}
|
||
|
close(fd);
|
||
|
|
||
|
/* free memory */
|
||
|
cl_engine_free(engine);
|
||
|
|
||
|
/* calculate size of scanned data */
|
||
|
mb = size * (CL_COUNT_PRECISION / 1024) / 1024.0;
|
||
|
printf("Data scanned: %2.2Lf MB\n", mb);
|
||
|
|
||
|
return ret == CL_VIRUS ? 1 : 0;
|
||
|
}
|
||
|
|
||
|
int recursive_dir(char *path)
|
||
|
{
|
||
|
DIR *dp = NULL;
|
||
|
struct dirent *st;
|
||
|
struct stat sta;
|
||
|
int ret = 0;
|
||
|
char tmp_name[2048] = { 0 };
|
||
|
|
||
|
st = NULL;
|
||
|
memset(&sta, 0, sizeof(struct stat));
|
||
|
memset(tmp_name, 0, 2048);
|
||
|
|
||
|
dp = opendir(path);
|
||
|
if (dp == NULL) {
|
||
|
printf("open dir error!!\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
while (1) {
|
||
|
st = readdir(dp);
|
||
|
if (NULL == st) //读取完毕
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
strcpy(tmp_name, path);
|
||
|
if (path[strlen(path) - 1] != '/') //判断路径名是否带/
|
||
|
strcat(tmp_name, "/");
|
||
|
strcat(tmp_name, st->d_name); //新文件路径名
|
||
|
ret = stat(tmp_name, &sta); //查看目录下文件属性
|
||
|
if (ret < 0)
|
||
|
{
|
||
|
printf("read stat fail\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (S_ISDIR(sta.st_mode)) //如果为目录文件
|
||
|
{
|
||
|
if (0 == strcmp("..", st->d_name) || 0 == strcmp(".", st->d_name)) //忽略当前目录和上一层目录
|
||
|
continue;
|
||
|
else
|
||
|
{
|
||
|
recursive_dir(tmp_name); //递归读取
|
||
|
}
|
||
|
}
|
||
|
else //不为目录则打印文件路径名
|
||
|
{
|
||
|
printf("%s\n", tmp_name);
|
||
|
detect_virus_files(tmp_name);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
closedir(dp);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int is_file_dir(char *file)
|
||
|
{
|
||
|
struct stat buf;
|
||
|
int result = 0;
|
||
|
|
||
|
|
||
|
result = stat(file, &buf);
|
||
|
if(S_IFDIR & buf.st_mode)
|
||
|
{
|
||
|
return 2;
|
||
|
}
|
||
|
else if(S_IFREG & buf.st_mode)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
int _clamav(int argc, char *argv[], char **env)
|
||
|
{
|
||
|
int is_fd = is_file_dir(argv[argc-1]);
|
||
|
if (1 == is_fd)
|
||
|
{
|
||
|
detect_virus_files(argv[argc-1]);
|
||
|
}
|
||
|
else if (2 == is_fd)
|
||
|
{
|
||
|
recursive_dir(argv[argc-1]);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|