... | ... |
@@ -55,7 +55,7 @@ static void print_server_version(const struct optstruct *opt) |
55 | 55 |
|
56 | 56 |
int main(int argc, char **argv) |
57 | 57 |
{ |
58 |
- int ds, dms, ret, infected = 0; |
|
58 |
+ int ds, dms, ret, infected = 0, err = 0; |
|
59 | 59 |
struct timeval t1, t2; |
60 | 60 |
time_t starttime; |
61 | 61 |
struct optstruct *opts; |
... | ... |
@@ -133,10 +133,10 @@ int main(int argc, char **argv) |
133 | 133 |
|
134 | 134 |
gettimeofday(&t1, NULL); |
135 | 135 |
|
136 |
- ret = client(opts, &infected); |
|
136 |
+ ret = client(opts, &infected, &err); |
|
137 | 137 |
|
138 | 138 |
/* TODO: Implement STATUS in clamd */ |
139 |
- if((infected || ret != 2) && !optget(opts, "no-summary")->enabled) { |
|
139 |
+ if(!optget(opts, "no-summary")->enabled) { |
|
140 | 140 |
gettimeofday(&t2, NULL); |
141 | 141 |
ds = t2.tv_sec - t1.tv_sec; |
142 | 142 |
dms = t2.tv_usec - t1.tv_usec; |
... | ... |
@@ -144,6 +144,8 @@ int main(int argc, char **argv) |
144 | 144 |
dms += (dms < 0) ? (1000000):(0); |
145 | 145 |
logg("\n----------- SCAN SUMMARY -----------\n"); |
146 | 146 |
logg("Infected files: %d\n", infected); |
147 |
+ if(err) |
|
148 |
+ logg("Errors: %d\n", err); |
|
147 | 149 |
if(notremoved) { |
148 | 150 |
logg("Not removed: %d\n", notremoved); |
149 | 151 |
} |
... | ... |
@@ -151,16 +151,16 @@ static char *makeabs(const char *basepath) { |
151 | 151 |
|
152 | 152 |
/* Recursively scans a path with the given scantype |
153 | 153 |
* Returns non zero for serious errors, zero otherwise */ |
154 |
-static int client_scan(const char *file, int scantype, int *infected, int maxlevel, int session, int flags) { |
|
154 |
+static int client_scan(const char *file, int scantype, int *infected, int *err, int maxlevel, int session, int flags) { |
|
155 | 155 |
int ret; |
156 | 156 |
char *fullpath = makeabs(file); |
157 | 157 |
|
158 | 158 |
if(!fullpath) |
159 | 159 |
return 0; |
160 | 160 |
if (!session) |
161 |
- ret = serial_client_scan(fullpath, scantype, infected, maxlevel, flags); |
|
161 |
+ ret = serial_client_scan(fullpath, scantype, infected, err, maxlevel, flags); |
|
162 | 162 |
else |
163 |
- ret = parallel_client_scan(fullpath, scantype, infected, maxlevel, flags); |
|
163 |
+ ret = parallel_client_scan(fullpath, scantype, infected, err, maxlevel, flags); |
|
164 | 164 |
free(fullpath); |
165 | 165 |
return ret; |
166 | 166 |
} |
... | ... |
@@ -218,7 +218,7 @@ int reload_clamd_database(const struct optstruct *opts) |
218 | 218 |
return 0; |
219 | 219 |
} |
220 | 220 |
|
221 |
-int client(const struct optstruct *opts, int *infected) |
|
221 |
+int client(const struct optstruct *opts, int *infected, int *err) |
|
222 | 222 |
{ |
223 | 223 |
const char *clamd_conf = optget(opts, "config-file")->strarg; |
224 | 224 |
struct optstruct *clamdopts; |
... | ... |
@@ -265,7 +265,7 @@ int client(const struct optstruct *opts, int *infected) |
265 | 265 |
struct stat sb; |
266 | 266 |
fstat(0, &sb); |
267 | 267 |
if((sb.st_mode & S_IFMT) != S_IFREG) scantype = STREAM; |
268 |
- if((sockd = dconnect()) >= 0 && (ret = dsresult(sockd, scantype, NULL, &ret, NULL, NULL)) >= 0) |
|
268 |
+ if((sockd = dconnect()) >= 0 && (ret = dsresult(sockd, scantype, NULL, &ret, NULL)) >= 0) |
|
269 | 269 |
*infected = ret; |
270 | 270 |
else |
271 | 271 |
errors = 1; |
... | ... |
@@ -274,15 +274,21 @@ int client(const struct optstruct *opts, int *infected) |
274 | 274 |
if(opts->filename && optget(opts, "file-list")->enabled) |
275 | 275 |
logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n"); |
276 | 276 |
|
277 |
- while(!errors && (fname = filelist(opts, NULL))) { |
|
277 |
+ while((fname = filelist(opts, NULL))) { |
|
278 | 278 |
if(!strcmp(fname, "-")) { |
279 | 279 |
logg("!Scanning from standard input requires \"-\" to be the only file argument\n"); |
280 | 280 |
continue; |
281 | 281 |
} |
282 |
- errors = client_scan(fname, scantype, infected, maxrec, session, flags); |
|
282 |
+ errors += client_scan(fname, scantype, infected, err, maxrec, session, flags); |
|
283 |
+ /* this may be too strict |
|
284 |
+ if(errors >= 10) { |
|
285 |
+ logg("!Too many errors\n"); |
|
286 |
+ break; |
|
287 |
+ } |
|
288 |
+ */ |
|
283 | 289 |
} |
284 | 290 |
} else { |
285 |
- errors = client_scan("", scantype, infected, maxrec, session, flags); |
|
291 |
+ errors = client_scan("", scantype, infected, err, maxrec, session, flags); |
|
286 | 292 |
} |
287 | 293 |
return *infected ? 1 : (errors ? 2 : 0); |
288 | 294 |
} |
... | ... |
@@ -30,7 +30,7 @@ enum { |
30 | 30 |
FILDES |
31 | 31 |
}; |
32 | 32 |
|
33 |
-int client(const struct optstruct *opts, int *infected); |
|
33 |
+int client(const struct optstruct *opts, int *infected, int *err); |
|
34 | 34 |
int get_clamd_version(const struct optstruct *opts); |
35 | 35 |
int reload_clamd_database(const struct optstruct *opts); |
36 | 36 |
|
... | ... |
@@ -247,7 +247,7 @@ static int send_fdpass(int sockd, const char *filename) { |
247 | 247 |
/* Sends a proper scan request to clamd and parses its replies |
248 | 248 |
* This is used only in non IDSESSION mode |
249 | 249 |
* Returns the number of infected files or -1 on error */ |
250 |
-int dsresult(int sockd, int scantype, const char *filename, int *printok, int *files, int *errors) { |
|
250 |
+int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors) { |
|
251 | 251 |
int infected = 0, len, beenthere = 0; |
252 | 252 |
char *bol, *eol; |
253 | 253 |
struct RCVLN rcv; |
... | ... |
@@ -288,8 +288,6 @@ int dsresult(int sockd, int scantype, const char *filename, int *printok, int *f |
288 | 288 |
while((len = recvln(&rcv, &bol, &eol))) { |
289 | 289 |
if(len == -1) return -1; |
290 | 290 |
beenthere = 1; |
291 |
- if(files) |
|
292 |
- (*files)++; |
|
293 | 291 |
if(!filename) logg("~%s\n", bol); |
294 | 292 |
if(len > 7) { |
295 | 293 |
char *colon = strrchr(bol, ':'); |
... | ... |
@@ -351,9 +349,11 @@ static int serial_callback(struct stat *sb, char *filename, const char *path, en |
351 | 351 |
int sockd, ret; |
352 | 352 |
const char *f = filename; |
353 | 353 |
|
354 |
+ c->files++; |
|
354 | 355 |
switch(reason) { |
355 | 356 |
case error_stat: |
356 | 357 |
logg("!Can't access file %s\n", path); |
358 |
+ c->errors++; |
|
357 | 359 |
return CL_SUCCESS; |
358 | 360 |
case error_mem: |
359 | 361 |
logg("!Memory allocation failed in ftw\n"); |
... | ... |
@@ -378,12 +378,16 @@ static int serial_callback(struct stat *sb, char *filename, const char *path, en |
378 | 378 |
|
379 | 379 |
if((sockd = dconnect()) < 0) { |
380 | 380 |
if(filename) free(filename); |
381 |
+ c->errors++; |
|
381 | 382 |
return CL_EOPEN; |
382 | 383 |
} |
383 |
- ret = dsresult(sockd, c->scantype, f, &c->printok, &c->files, &c->errors); |
|
384 |
+ ret = dsresult(sockd, c->scantype, f, &c->printok, &c->errors); |
|
384 | 385 |
if(filename) free(filename); |
385 | 386 |
closesocket(sockd); |
386 |
- if(ret < 0) return CL_EOPEN; |
|
387 |
+ if(ret < 0) { |
|
388 |
+ c->errors++; |
|
389 |
+ return CL_EOPEN; |
|
390 |
+ } |
|
387 | 391 |
c->infected += ret; |
388 | 392 |
if(reason == visit_directory_toplev) |
389 | 393 |
return CL_BREAK; |
... | ... |
@@ -392,7 +396,7 @@ static int serial_callback(struct stat *sb, char *filename, const char *path, en |
392 | 392 |
|
393 | 393 |
/* Non-IDSESSION handler |
394 | 394 |
* Returns non zero for serious errors, zero otherwise */ |
395 |
-int serial_client_scan(char *file, int scantype, int *infected, int maxlevel, int flags) { |
|
395 |
+int serial_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags) { |
|
396 | 396 |
struct cli_ftw_cbdata data; |
397 | 397 |
struct client_serial_data cdata; |
398 | 398 |
int ftw; |
... | ... |
@@ -406,8 +410,9 @@ int serial_client_scan(char *file, int scantype, int *infected, int maxlevel, in |
406 | 406 |
|
407 | 407 |
ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, serial_callback, &data, NULL); |
408 | 408 |
*infected += cdata.infected; |
409 |
+ *err += cdata.errors; |
|
409 | 410 |
|
410 |
- if((cdata.errors < cdata.files) && (ftw == CL_SUCCESS || ftw == CL_BREAK)) { |
|
411 |
+ if(!cdata.errors && (ftw == CL_SUCCESS || ftw == CL_BREAK)) { |
|
411 | 412 |
if(cdata.printok) |
412 | 413 |
logg("~%s: OK\n", file); |
413 | 414 |
return 0; |
... | ... |
@@ -496,9 +501,11 @@ static int parallel_callback(struct stat *sb, char *filename, const char *path, |
496 | 496 |
struct SCANID *cid; |
497 | 497 |
int res; |
498 | 498 |
|
499 |
+ c->files++; |
|
499 | 500 |
switch(reason) { |
500 | 501 |
case error_stat: |
501 | 502 |
logg("!Can't access file %s\n", path); |
503 |
+ c->errors++; |
|
502 | 504 |
return CL_SUCCESS; |
503 | 505 |
case error_mem: |
504 | 506 |
logg("!Memory allocation failed in ftw\n"); |
... | ... |
@@ -551,7 +558,6 @@ static int parallel_callback(struct stat *sb, char *filename, const char *path, |
551 | 551 |
cid->file = filename; |
552 | 552 |
cid->next = c->ids; |
553 | 553 |
c->ids = cid; |
554 |
- c->files++; |
|
555 | 554 |
|
556 | 555 |
switch(c->scantype) { |
557 | 556 |
#ifdef HAVE_FD_PASSING |
... | ... |
@@ -577,7 +583,7 @@ static int parallel_callback(struct stat *sb, char *filename, const char *path, |
577 | 577 |
|
578 | 578 |
/* IDSESSION handler |
579 | 579 |
* Returns non zero for serious errors, zero otherwise */ |
580 |
-int parallel_client_scan(char *file, int scantype, int *infected, int maxlevel, int flags) { |
|
580 |
+int parallel_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags) { |
|
581 | 581 |
struct cli_ftw_cbdata data; |
582 | 582 |
struct client_parallel_data cdata; |
583 | 583 |
int ftw; |
... | ... |
@@ -602,6 +608,7 @@ int parallel_client_scan(char *file, int scantype, int *infected, int maxlevel, |
602 | 602 |
ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, parallel_callback, &data, NULL); |
603 | 603 |
|
604 | 604 |
if(ftw != CL_SUCCESS) { |
605 |
+ *err += cdata.errors; |
|
605 | 606 |
*infected += cdata.infected; |
606 | 607 |
closesocket(cdata.sockd); |
607 | 608 |
return 1; |
... | ... |
@@ -612,15 +619,18 @@ int parallel_client_scan(char *file, int scantype, int *infected, int maxlevel, |
612 | 612 |
closesocket(cdata.sockd); |
613 | 613 |
|
614 | 614 |
*infected += cdata.infected; |
615 |
+ *err += cdata.errors; |
|
615 | 616 |
|
616 | 617 |
if(cdata.ids) { |
617 | 618 |
logg("!Clamd closed the connection before scanning all files.\n"); |
618 | 619 |
return 1; |
619 | 620 |
} |
621 |
+ if(cdata.errors) |
|
622 |
+ return 1; |
|
623 |
+ |
|
620 | 624 |
if(!cdata.files) |
621 | 625 |
return 0; |
622 |
- if(cdata.errors == cdata.files) |
|
623 |
- return 1; |
|
626 |
+ |
|
624 | 627 |
if(cdata.printok) |
625 | 628 |
logg("~%s: OK\n", file); |
626 | 629 |
return 0; |
... | ... |
@@ -34,7 +34,7 @@ int dconnect(void); |
34 | 34 |
int sendln(int sockd, const char *line, unsigned int len); |
35 | 35 |
void recvlninit(struct RCVLN *s, int sockd); |
36 | 36 |
int recvln(struct RCVLN *s, char **rbol, char **reol); |
37 |
-int serial_client_scan(char *file, int scantype, int *infected, int maxlevel, int flags); |
|
38 |
-int parallel_client_scan(char *file, int scantype, int *infected, int maxlevel, int flags); |
|
39 |
-int dsresult(int sockd, int scantype, const char *filename, int *printok, int *files, int *errors); |
|
37 |
+int serial_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags); |
|
38 |
+int parallel_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags); |
|
39 |
+int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors); |
|
40 | 40 |
#endif |