if(!(tmp = strrchr(filename, '/'))) {
mprintf("@error moving file '%s'.\n", filename);
mprintf("clamscan: '%s' does not appear to be a valid filename.\n", filename);
logg("clamscan: '%s' does not appear to be a valid filename.\n", filename);
claminfo.notmoved++;
return;
}
if(!(movefilename = malloc(movefilename_size))) {
mprintf("@error moving file '%s'.\n", filename);
mprintf("clamscan: malloc() returned NULL.\n");
logg("clamscan: malloc() returned NULL.\n");
claminfo.notmoved++;
return;
}
if(!(strrcpy(movefilename, movedir))) {
mprintf("@error moving file '%s'.\n", filename);
mprintf("clamscan: strrcpy() returned NULL.\n");
logg("clamscan: strrcpy() returned NULL.\n");
claminfo.notmoved++;
free(movefilename);
return;
}
if(!(strcat(movefilename, tmp))) {
mprintf("@error moving file '%s'.\n", filename);
mprintf("clamscan: strcat() returned NULL.\n");
logg("clamscan: strcat() returned NULL.\n");
claminfo.notmoved++;
free(movefilename);
return;
}
stat(filename, &fstat);
if(!stat(movefilename, &mfstat)) {
if(fstat.st_ino == mfstat.st_ino) { /* It's the same file*/
mprintf("clamscan: file excluded '%s'.\n", filename);
logg("clamscan: file excluded '%s'.\n", filename);
claminfo.notmoved++;
free(movefilename);
return;
} else {
/* file exists - try to append an ordinal number to the
* quranatined file in an attempt not to overwrite existing
* files in quarantine
*/
len = strlen(movefilename);
n = 0;
do {
/* reset the movefilename to it's initial value by
* truncating to the original filename length
*/
movefilename[len] = 0;
/* append .XXX */
sprintf(numext, ".%03d", n++);
strcat(movefilename, numext);
} while(!stat(movefilename, &mfstat) && (n < 1000));
}
}
/* it has guaranteed read access to the archive */
int scancompressed(const char *filename, struct cl_node *root, const struct passwd *user, const struct optstruct *opt, const struct cl_limits *limits, int options)
{
int ret = 0;
char *tmpdir, *gendir, *userprg;
struct stat statbuf;
stat(filename, &statbuf);
if(!S_ISREG(statbuf.st_mode)) {
mprintf("^Suspected archive %s is not a regular file.\n", filename);
return 0; /* hmm ? */
}
/* remove the directory - as clamav */
clamav_rmdirs(gendir);
/* free gendir - it's not necessary now */
free(gendir);
switch(ret) {
case -1:
mprintf("@Can't fork().\n");
exit(61); /* this is critical problem, so we just exit here */
case -2:
mprintf("@Can't execute some unpacker. Check paths and permissions on the temporary directory.\n");
/* This is no longer a critical error (since 0.24). We scan
* raw archive.
*/
if(!printinfected)
mprintf("(raw) ");
if((ret = checkfile(filename, root, limits, 0)) == CL_VIRUS) {
if(optl(opt, "remove")) {
if(unlink(filename)) {
mprintf("%s: Can't remove.\n", filename);
logg("%s: Can't remove.\n", filename);
claminfo.notremoved++;
} else {
mprintf("%s: Removed.\n", filename);
logg("%s: Removed.\n", filename);
}
} else if (optl(opt, "move"))
move_infected(filename, opt);
}
return ret;
case -3:
return 0;
case 0:
/* no viruses found in archive, we scan just in case the same
* archive
*/
if(!printinfected)
mprintf("(raw) ");
/* we need full path for some reasons (eg. archive handling) */
if(!getcwd(cwd, sizeof(cwd))) {
mprintf("@Can't get absolute pathname of current working directory.\n");
ret = 57;
} else
ret = scandirs(cwd, trie, user, opt, limits, options);
} else if(!strcmp(opt->filename, "-")) { /* read data from stdin */
ret = checkstdin(trie, limits, options);
/*
* check the extension - this is a special case, normally we don't need to
* do this (libclamav detects archive by its magic string), but here we
* want to know the exit code from internal unpacker and try to use
* external (if provided) when internal cannot extract data.
*/
} else if(ret == CL_CLEAN)
return 0;
/* in other case try to continue with external archivers */
options &= ~CL_SCAN_ARCHIVE; /* and disable decompression for the below checkfile() */
}
/* check permissions */
switch(checkaccess(filename, UNPUSER, R_OK)) {
case -1:
mprintf("@Can't get information about user "UNPUSER".\n");
exit(60); /* this is a critical problem so we just exit here */
case -2:
mprintf("@Can't fork.\n");
exit(61);
case 0: /* read access denied */
if(geteuid()) {
if(!printinfected)
mprintf("%s: Access denied to archive.\n", filename);
} else {
#if !defined(C_CYGWIN) && !defined(C_BEOS)
if(!geteuid()) {
if((user = getpwnam(UNPUSER)) == NULL) {
mprintf("@Can't get information about user "UNPUSER".\n");
exit(60); /* this is critical problem, so we just exit here */
}
}
#endif