Merge branch 'master' of git.clam.sourcefire.com:/var/lib/git/clamav-devel

0.96
aCaB 16 years ago
commit af0297c78e
  1. 5
      ChangeLog
  2. 2
      clamdscan/clamdscan.c
  3. 6
      clamscan/clamscan.c
  4. 1
      clamscan/global.h
  5. 122
      clamscan/manager.c
  6. 30
      docs/man/clamscan.1.in

@ -4,6 +4,11 @@ Thu Feb 4 22:17:49 CET 2010 (acab)
* clamav-milter: new options MilterSocketMode and MilterSocketGroup
(bb#1789)
Thu Feb 4 21:31:27 CET 2010 (tk)
---------------------------------
* clamscan: properly report errors from libclamav; simplify
error codes
Wed Feb 3 18:23:08 CET 2010 (tk)
---------------------------------
* clamdscan: fix error logic once again

@ -145,7 +145,7 @@ int main(int argc, char **argv)
logg("\n----------- SCAN SUMMARY -----------\n");
logg("Infected files: %d\n", infected);
if(err)
logg("Errors: %d\n", err);
logg("Total errors: %d\n", err);
if(notremoved) {
logg("Not removed: %d\n", notremoved);
}

@ -75,7 +75,7 @@ int main(int argc, char **argv)
if((opts = optparse(NULL, argc, argv, 1, OPT_CLAMSCAN, 0, NULL)) == NULL) {
mprintf("!Can't parse command line options\n");
return 40;
return 2;
}
if(optget(opts, "verbose")->enabled) {
@ -129,7 +129,7 @@ int main(int argc, char **argv)
if(logg("#\n-------------------------------------------------------------------------------\n\n")) {
mprintf("!Problem with internal logger.\n");
optfree(opts);
return 62;
return 2;
}
} else
logg_file = NULL;
@ -159,6 +159,8 @@ int main(int argc, char **argv)
logg("Scanned directories: %u\n", info.dirs);
logg("Scanned files: %u\n", info.files);
logg("Infected files: %u\n", info.ifiles);
if(info.errors)
logg("Total errors: %u\n", info.errors);
if(notremoved) {
logg("Not removed: %u\n", notremoved);
}

@ -26,6 +26,7 @@ struct s_info {
unsigned int dirs; /* number of scanned directories */
unsigned int files; /* number of scanned files */
unsigned int ifiles; /* number of infected files */
unsigned int errors; /* number of errors */
unsigned long int blocks; /* number of *scanned* 16kb blocks */
unsigned long int rblocks; /* number of *read* 16kb blocks */
};

@ -64,10 +64,10 @@
dev_t procdev;
#endif
static int scanfile(const char *filename, struct cl_engine *engine, const struct optstruct *opts, unsigned int options)
void scanfile(const char *filename, struct cl_engine *engine, const struct optstruct *opts, unsigned int options)
{
int ret = 0, fd, included, printclean = 1;
unsigned int fsize;
int ret = 0, fd, included, printclean = 1;
unsigned int fsize;
const struct optstruct *opt;
const char *virname;
#ifdef C_LINUX
@ -79,7 +79,7 @@ static int scanfile(const char *filename, struct cl_engine *engine, const struct
if(sb.st_dev == procdev) {
if(!printinfected)
logg("~%s: Excluded (/proc)\n", filename);
return 0;
return;
}
#endif
@ -88,7 +88,7 @@ static int scanfile(const char *filename, struct cl_engine *engine, const struct
if(match_regex(filename, opt->strarg) == 1) {
if(!printinfected)
logg("~%s: Excluded\n", filename);
return 0;
return;
}
opt = opt->nextarg;
}
@ -106,7 +106,7 @@ static int scanfile(const char *filename, struct cl_engine *engine, const struct
if(!included) {
if(!printinfected)
logg("~%s: Excluded\n", filename);
return 0;
return;
}
}
@ -114,7 +114,7 @@ static int scanfile(const char *filename, struct cl_engine *engine, const struct
if(fsize == 0) {
if(!printinfected)
logg("~%s: Empty file\n", filename);
return 0;
return;
}
info.rblocks += fsize / CL_COUNT_PRECISION;
#ifndef _WIN32
@ -122,7 +122,8 @@ static int scanfile(const char *filename, struct cl_engine *engine, const struct
if(checkaccess(filename, NULL, R_OK) != 1) {
if(!printinfected)
logg("~%s: Access denied\n", filename);
return 0;
info.errors++;
return;
}
#endif
@ -130,13 +131,13 @@ static int scanfile(const char *filename, struct cl_engine *engine, const struct
if((fd = safe_open(filename, O_RDONLY|O_BINARY)) == -1) {
logg("^Can't open file %s: %s\n", filename, strerror(errno));
return 54;
info.errors++;
return;
}
info.files++;
if((ret = cl_scandesc(fd, &virname, &info.blocks, engine, options)) == CL_VIRUS) {
logg("~%s: %s FOUND\n", filename, virname);
info.files++;
info.ifiles++;
if(bell)
@ -145,25 +146,26 @@ static int scanfile(const char *filename, struct cl_engine *engine, const struct
} else if(ret == CL_CLEAN) {
if(!printinfected && printclean)
mprintf("~%s: OK\n", filename);
} else
info.files++;
} else {
if(!printinfected)
logg("~%s: %s ERROR\n", filename, cl_strerror(ret));
info.errors++;
}
close(fd);
if(ret == CL_VIRUS && action)
action(filename);
return ret;
}
static int scandirs(const char *dirname, struct cl_engine *engine, const struct optstruct *opts, unsigned int options, unsigned int depth, dev_t dev)
void scandirs(const char *dirname, struct cl_engine *engine, const struct optstruct *opts, unsigned int options, unsigned int depth, dev_t dev)
{
DIR *dd;
struct dirent *dent;
struct stat statbuf;
char *fname;
int scanret = 0, included;
int included;
const struct optstruct *opt;
@ -172,7 +174,7 @@ static int scandirs(const char *dirname, struct cl_engine *engine, const struct
if(match_regex(dirname, opt->strarg) == 1) {
if(!printinfected)
logg("~%s: Excluded\n", dirname);
return 0;
return;
}
opt = opt->nextarg;
}
@ -190,17 +192,16 @@ static int scandirs(const char *dirname, struct cl_engine *engine, const struct
if(!included) {
if(!printinfected)
logg("~%s: Excluded\n", dirname);
return 0;
return;
}
}
if(depth > (unsigned int) optget(opts, "max-dir-recursion")->numarg)
return 0;
info.dirs++;
depth++;
return;
if((dd = opendir(dirname)) != NULL) {
info.dirs++;
depth++;
while((dent = readdir(dd))) {
if(dent->d_ino)
{
@ -222,13 +223,10 @@ static int scandirs(const char *dirname, struct cl_engine *engine, const struct
continue;
}
}
if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode) && recursion) {
if(scandirs(fname, engine, opts, options, depth, dev) == 1)
scanret++;
} else {
if(S_ISREG(statbuf.st_mode))
scanret += scanfile(fname, engine, opts, options);
}
if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode) && recursion)
scandirs(fname, engine, opts, options, depth, dev);
else if(S_ISREG(statbuf.st_mode))
scanfile(fname, engine, opts, options);
}
free(fname);
}
@ -237,16 +235,10 @@ static int scandirs(const char *dirname, struct cl_engine *engine, const struct
} else {
if(!printinfected)
logg("~%s: Can't open directory.\n", dirname);
return 53;
info.errors++;
}
closedir(dd);
if(scanret)
return 1;
else
return 0;
}
static int scanstdin(const struct cl_engine *engine, const struct optstruct *opts, int options)
@ -266,7 +258,7 @@ static int scanstdin(const struct cl_engine *engine, const struct optstruct *opt
if(checkaccess(tmpdir, CLAMAVUSER, W_OK) != 1) {
logg("!Can't write to temporary directory\n");
return 64;
return 2;
}
file = cli_gentemp(tmpdir);
@ -274,7 +266,7 @@ static int scanstdin(const struct cl_engine *engine, const struct optstruct *opt
if(!(fs = fopen(file, "wb"))) {
logg("!Can't open %s for writing\n", file);
free(file);
return 63;
return 2;
}
while((bread = fread(buff, 1, FILEBUFF, stdin))) {
@ -282,7 +274,7 @@ static int scanstdin(const struct cl_engine *engine, const struct optstruct *opt
if(fwrite(buff, 1, bread, fs) < bread) {
logg("!Can't write to %s\n", file);
free(file);
return 58;
return 2;
}
}
fclose(fs);
@ -338,12 +330,12 @@ int scanmanager(const struct optstruct *opts)
if((ret = cl_init(CL_INIT_DEFAULT))) {
logg("!Can't initialize libclamav: %s\n", cl_strerror(ret));
return 50;
return 2;
}
if(!(engine = cl_engine_new())) {
logg("!Can't initialize antivirus engine\n");
return 50;
return 2;
}
if(optget(opts, "detect-pua")->enabled) {
@ -355,7 +347,7 @@ int scanmanager(const struct optstruct *opts)
if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
logg("!Can't allocate memory for pua_cats\n");
cl_engine_free(engine);
return 70;
return 2;
}
sprintf(pua_cats + i, ".%s", opt->strarg);
i += strlen(opt->strarg) + 1;
@ -371,14 +363,14 @@ int scanmanager(const struct optstruct *opts)
logg("!--exclude-pua and --include-pua cannot be used at the same time\n");
cl_engine_free(engine);
free(pua_cats);
return 40;
return 2;
}
dboptions |= CL_DB_PUA_INCLUDE;
i = 0;
while(opt) {
if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
logg("!Can't allocate memory for pua_cats\n");
return 70;
return 2;
}
sprintf(pua_cats + i, ".%s", opt->strarg);
i += strlen(opt->strarg) + 1;
@ -394,7 +386,7 @@ int scanmanager(const struct optstruct *opts)
logg("!cli_engine_set_str(CL_ENGINE_PUA_CATEGORIES) failed: %s\n", cl_strerror(ret));
free(pua_cats);
cl_engine_free(engine);
return 50;
return 2;
}
free(pua_cats);
}
@ -413,7 +405,7 @@ int scanmanager(const struct optstruct *opts)
if((ret = cl_engine_set_str(engine, CL_ENGINE_TMPDIR, opt->strarg))) {
logg("!cli_engine_set_str(CL_ENGINE_TMPDIR) failed: %s\n", cl_strerror(ret));
cl_engine_free(engine);
return 50;
return 2;
}
}
@ -421,7 +413,7 @@ int scanmanager(const struct optstruct *opts)
if((ret = cl_load(opt->strarg, engine, &info.sigs, dboptions))) {
logg("!%s\n", cl_strerror(ret));
cl_engine_free(engine);
return 50;
return 2;
}
} else {
@ -431,7 +423,7 @@ int scanmanager(const struct optstruct *opts)
logg("!%s\n", cl_strerror(ret));
free(dbdir);
cl_engine_free(engine);
return 50;
return 2;
}
free(dbdir);
}
@ -439,7 +431,7 @@ int scanmanager(const struct optstruct *opts)
if((ret = cl_engine_compile(engine)) != 0) {
logg("!Database initialization error: %s\n", cl_strerror(ret));;
cl_engine_free(engine);
return 50;
return 2;
}
/* set limits */
@ -448,7 +440,7 @@ int scanmanager(const struct optstruct *opts)
if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCANSIZE, opt->numarg))) {
logg("!cli_engine_set_num(CL_ENGINE_MAX_SCANSIZE) failed: %s\n", cl_strerror(ret));
cl_engine_free(engine);
return 50;
return 2;
}
}
@ -456,7 +448,7 @@ int scanmanager(const struct optstruct *opts)
if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILESIZE, opt->numarg))) {
logg("!cli_engine_set_num(CL_ENGINE_MAX_FILESIZE) failed: %s\n", cl_strerror(ret));
cl_engine_free(engine);
return 50;
return 2;
}
}
@ -475,7 +467,7 @@ int scanmanager(const struct optstruct *opts)
if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILES, opt->numarg))) {
logg("!cli_engine_set_num(CL_ENGINE_MAX_FILES) failed: %s\n", cl_strerror(ret));
cl_engine_free(engine);
return 50;
return 2;
}
}
@ -483,7 +475,7 @@ int scanmanager(const struct optstruct *opts)
if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_RECURSION, opt->numarg))) {
logg("!cli_engine_set_num(CL_ENGINE_MAX_RECURSION) failed: %s\n", cl_strerror(ret));
cl_engine_free(engine);
return 50;
return 2;
}
}
@ -543,7 +535,7 @@ int scanmanager(const struct optstruct *opts)
break;
default:
logg("!Invalid argument for --structured-ssn-format\n");
return 40;
return 2;
}
} else {
options |= CL_SCAN_STRUCTURED_SSN_NORMAL;
@ -553,7 +545,7 @@ int scanmanager(const struct optstruct *opts)
if((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_SSN_COUNT, opt->numarg))) {
logg("!cli_engine_set_num(CL_ENGINE_MIN_SSN_COUNT) failed: %s\n", cl_strerror(ret));
cl_engine_free(engine);
return 50;
return 2;
}
}
@ -561,7 +553,7 @@ int scanmanager(const struct optstruct *opts)
if((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_CC_COUNT, opt->numarg))) {
logg("!cli_engine_set_num(CL_ENGINE_MIN_CC_COUNT) failed: %s\n", cl_strerror(ret));
cl_engine_free(engine);
return 50;
return 2;
}
}
@ -580,10 +572,10 @@ int scanmanager(const struct optstruct *opts)
/* we need full path for some reasons (eg. archive handling) */
if(!getcwd(cwd, sizeof(cwd))) {
logg("!Can't get absolute pathname of current working directory\n");
ret = 57;
ret = 2;
} else {
stat(cwd, &sb);
ret = scandirs(cwd, engine, opts, options, 1, sb.st_dev);
scandirs(cwd, engine, opts, options, 1, sb.st_dev);
}
} else if(opts->filename && !optget(opts, "file-list")->enabled && !strcmp(opts->filename[0], "-")) { /* read data from stdin */
@ -597,7 +589,7 @@ int scanmanager(const struct optstruct *opts)
if((fmodeint = fileinfo(file, 2)) == -1) {
logg("^Can't access file %s\n", file);
perror(file);
ret = 56;
ret = 2;
} else {
for(i = strlen(file) - 1; i > 0; i--) {
if(file[i] == *PATHSEP)
@ -610,17 +602,17 @@ int scanmanager(const struct optstruct *opts)
switch(fmode & S_IFMT) {
case S_IFREG:
ret = scanfile(file, engine, opts, options);
scanfile(file, engine, opts, options);
break;
case S_IFDIR:
stat(file, &sb);
ret = scandirs(file, engine, opts, options, 1, sb.st_dev);
scandirs(file, engine, opts, options, 1, sb.st_dev);
break;
default:
logg("!Not supported file type (%s)\n", file);
ret = 52;
ret = 2;
}
}
free(file);
@ -630,11 +622,11 @@ int scanmanager(const struct optstruct *opts)
/* free the engine */
cl_engine_free(engine);
/* overwrite return code */
/* overwrite return code - infection takes priority */
if(info.ifiles)
ret = 1;
else if(ret < 50) /* hopefully no error detected */
ret = 0; /* just make sure it's 0 */
else if(info.errors)
ret = 2;
return ret;
}

@ -186,39 +186,11 @@ Maximum depth directories are scanned at (default: 15).
\fBclamscan \-r /var/spool/mail\fR
.SH "RETURN CODES"
.LP
Note: some return codes may only appear in a single file mode (when clamscan is started with a single argument). Those are marked with \fB(ofm)\fR.
0 : No virus found.
.TP
1 : Virus(es) found.
.TP
40: Unknown option passed.
.TP
50: Database initialization error.
.TP
52: Not supported file type.
.TP
53: Can't open directory.
.TP
54: Can't open file. (ofm)
.TP
55: Error reading file. (ofm)
.TP
56: Can't stat input file / directory.
.TP
57: Can't get absolute path name of current working directory.
.TP
58: I/O error, please check your file system.
.TP
62: Can't initialize logger.
.TP
63: Can't create temporary files/directories (check permissions).
.TP
64: Can't write to temporary directory (please specify another one).
.TP
70: Can't allocate memory (calloc).
.TP
71: Can't allocate memory (malloc).
2 : Some error(s) occured.
.SH "CREDITS"
Please check the full documentation for credits.
.SH "AUTHOR"

Loading…
Cancel
Save