denyhosts/libclamav.c
2022-10-22 18:41:00 +08:00

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;
}