static int scanfile(const char *filename, struct cl_engine *engine, const struct optstruct *opt, const struct cl_limits *limits, unsigned int options) { int ret = 0, fd, included, printclean = 1; const struct optnode *optnode; char *argument; const char *virname; #ifdef C_LINUX struct stat sb; /* argh, don't scan /proc files */ if(procdev) if(stat(filename, &sb) != -1) if(sb.st_dev == procdev) { if(!printinfected) logg("~%s: Excluded (/proc)\n", filename); return 0; } #endif if(opt_check(opt, "exclude")) { argument = opt_firstarg(opt, "exclude", &optnode); while(argument) { if(cli_matchregex(filename, argument)) { if(!printinfected) logg("~%s: Excluded\n", filename); return 0; } argument = opt_nextarg(&optnode, "exclude"); } } if(opt_check(opt, "include")) { included = 0; argument = opt_firstarg(opt, "include", &optnode); while(argument && !included) { if(cli_matchregex(filename, argument)) { included = 1; break; } argument = opt_nextarg(&optnode, "include"); } if(!included) { if(!printinfected) logg("~%s: Excluded\n", filename); return 0; } } if(fileinfo(filename, 1) == 0) { if(!printinfected) logg("~%s: Empty file\n", filename); return 0; } #ifndef C_WINDOWS if(geteuid()) if(checkaccess(filename, NULL, R_OK) != 1) { if(!printinfected) logg("~%s: Access denied\n", filename); return 0; } #endif logg("*Scanning %s\n", filename); if((fd = open(filename, O_RDONLY|O_BINARY)) == -1) { logg("~%s: %s\n", filename, strerror(errno)); return 54; } cbdata.count = 0; cbdata.fd = fd; cbdata.oldvalue = 0; cbdata.filename = filename; cbdata.size = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); info.files++; if((ret = cl_scandesc(fd, &virname, &info.blocks, engine, limits, options)) == CL_VIRUS) { logg("~%s: %s FOUND\n", filename, virname); info.ifiles++; if(bell) fprintf(stderr, "\007"); } else if(ret == CL_CLEAN) { if(!printinfected && printclean) mprintf("~%s: OK\n", filename); } else if(!printinfected) logg("~%s: %s\n", filename, cl_strerror(ret)); close(fd); if(ret == CL_VIRUS) { if(opt_check(opt, "remove")) { if(unlink(filename)) { logg("^%s: Can't remove\n", filename); info.notremoved++; } else { logg("~%s: Removed\n", filename); } } else if(opt_check(opt, "move") || opt_check(opt, "copy")) move_infected(filename, opt); } return ret; }
int dsresult(int sockd, const struct optstruct *opt) { int infected = 0, waserror = 0; char buff[4096], *pt; FILE *fd; #ifndef C_OS2 if((fd = fdopen(dup(sockd), "r")) == NULL) { #else /* FIXME: accoriding to YD OS/2 does not support dup() for sockets */ if((fd = fdopen(sockd, "r")) == NULL) { #endif mprintf("@Can't open descriptor for reading.\n"); return -1; } while(fgets(buff, sizeof(buff), fd)) { if(strstr(buff, "FOUND\n")) { infected++; logg("%s", buff); mprintf("%s", buff); if(optl(opt, "move")) { /* filename: Virus FOUND */ if((pt = strrchr(buff, ':'))) { *pt = 0; move_infected(buff, opt); } else { mprintf("@Broken data format. File not moved.\n"); } } else if(optl(opt, "remove")) { if(!(pt = strrchr(buff, ':'))) { mprintf("@Broken data format. File not removed.\n"); } else { *pt = 0; if(unlink(buff)) { mprintf("%s: Can't remove.\n", buff); logg("%s: Can't remove.\n", buff); notremoved++; } else { mprintf("%s: Removed.\n", buff); logg("%s: Removed.\n", buff); } } } } if(strstr(buff, "ERROR\n")) { logg("%s", buff); mprintf("%s", buff); waserror = 1; } } #ifndef C_OS2 /* Small memory leak under OS/2 (see above) */ fclose(fd); #endif return infected ? infected : (waserror ? -1 : 0); } int dsfile(int sockd, const char *filename, const struct optstruct *opt) { int ret; char *scancmd; scancmd = mcalloc(strlen(filename) + 20, sizeof(char)); sprintf(scancmd, "CONTSCAN %s", filename); if(write(sockd, scancmd, strlen(scancmd)) <= 0) { mprintf("@Can't write to the socket.\n"); free(scancmd); return -1; } free(scancmd); ret = dsresult(sockd, opt); if(!ret) mprintf("%s: OK\n", filename); return ret; }