git-svn: trunk@4907
aCaB authored on 2009/03/07 10:55:07... | ... |
@@ -144,16 +144,16 @@ static char *makeabs(const char *basepath) { |
144 | 144 |
|
145 | 145 |
/* Recursively scans a path with the given scantype |
146 | 146 |
* Returns non zero for serious errors, zero otherwise */ |
147 |
-static int client_scan(const char *file, int scantype, int *infected, int *errors, int maxlevel, int session, int flags) { |
|
147 |
+static int client_scan(const char *file, int scantype, int *infected, int maxlevel, int session, int flags) { |
|
148 | 148 |
int ret; |
149 | 149 |
char *fullpath = makeabs(file); |
150 | 150 |
|
151 | 151 |
if(!fullpath) |
152 | 152 |
return 0; |
153 | 153 |
if (!session) |
154 |
- ret = serial_client_scan(fullpath, scantype, infected, errors, maxlevel, flags); |
|
154 |
+ ret = serial_client_scan(fullpath, scantype, infected, maxlevel, flags); |
|
155 | 155 |
else |
156 |
- ret = parallel_client_scan(fullpath, scantype, infected, errors, maxlevel, flags); |
|
156 |
+ ret = parallel_client_scan(fullpath, scantype, infected, maxlevel, flags); |
|
157 | 157 |
free(fullpath); |
158 | 158 |
return ret; |
159 | 159 |
} |
... | ... |
@@ -260,19 +260,19 @@ int client(const struct optstruct *opts, int *infected) |
260 | 260 |
if((sockd = dconnect()) >= 0 && (ret = dsresult(sockd, scantype, NULL)) >= 0) |
261 | 261 |
*infected = ret; |
262 | 262 |
else |
263 |
- errors++; |
|
263 |
+ errors = 1; |
|
264 | 264 |
if(sockd >= 0) close(sockd); |
265 | 265 |
} else if(opts->filename) { |
266 | 266 |
unsigned int i; |
267 |
- for (i = 0; opts->filename[i]; i++) { |
|
267 |
+ for (i = 0; !errors && opts->filename[i]; i++) { |
|
268 | 268 |
if(!strcmp(opts->filename[i], "-")) { |
269 | 269 |
logg("!Scanning from standard input requires \"-\" to be the only file argument\n"); |
270 | 270 |
continue; |
271 | 271 |
} |
272 |
- if(client_scan(opts->filename[i], scantype, infected, &errors, maxrec, session, flags)) break; |
|
272 |
+ errors = client_scan(opts->filename[i], scantype, infected, maxrec, session, flags); |
|
273 | 273 |
} |
274 | 274 |
} else { |
275 |
- client_scan("", scantype, infected, &errors, maxrec, session, flags); |
|
275 |
+ errors = client_scan("", scantype, infected, maxrec, session, flags); |
|
276 | 276 |
} |
277 | 277 |
return *infected ? 1 : (errors ? 2 : 0); |
278 | 278 |
} |
... | ... |
@@ -78,7 +78,7 @@ int sendln(int sockd, const char *line, unsigned int len) { |
78 | 78 |
int sent = send(sockd, line, len, 0); |
79 | 79 |
if(sent <= 0) { |
80 | 80 |
if(sent && errno == EINTR) continue; |
81 |
- logg("!Can't send request to clamd: %s\n", strerror(errno)); |
|
81 |
+ logg("!Can't send to clamd: %s\n", strerror(errno)); |
|
82 | 82 |
return 1; |
83 | 83 |
} |
84 | 84 |
line += sent; |
... | ... |
@@ -118,13 +118,10 @@ int recvln(struct RCVLN *s, char **rbol, char **reol) { |
118 | 118 |
*s->cur = '\0'; |
119 | 119 |
if(strcmp(s->buf, "UNKNOWN COMMAND\n")) |
120 | 120 |
logg("!Communication error\n"); |
121 |
- else { |
|
121 |
+ else |
|
122 | 122 |
logg("!Command rejected by clamd (wrong clamd version?)\n"); |
123 |
- exit(2); |
|
124 |
- } |
|
125 | 123 |
return -1; |
126 | 124 |
} |
127 |
- *rbol = NULL; |
|
128 | 125 |
return 0; |
129 | 126 |
} |
130 | 127 |
} |
... | ... |
@@ -177,7 +174,6 @@ static int send_stream(int sockd, const char *filename) { |
177 | 177 |
if((unsigned int)len > todo) len = todo; |
178 | 178 |
buf[0] = htonl(len); |
179 | 179 |
if(sendln(sockd, (const char *)buf, len+sizeof(uint32_t))) { |
180 |
- logg("!Can't write to the socket.\n"); |
|
181 | 180 |
close(fd); |
182 | 181 |
return 1; |
183 | 182 |
} |
... | ... |
@@ -189,7 +185,7 @@ static int send_stream(int sockd, const char *filename) { |
189 | 189 |
} |
190 | 190 |
close(fd); |
191 | 191 |
if(len) { |
192 |
- logg("!Failed to read from %s.\n", filename); |
|
192 |
+ logg("!Failed to read from %s.\n", filename ? filename : "STDIN"); |
|
193 | 193 |
return 1; |
194 | 194 |
} |
195 | 195 |
*buf=0; |
... | ... |
@@ -245,9 +241,9 @@ static int send_fdpass(int sockd, const char *filename) { |
245 | 245 |
* This is used only in non IDSESSION mode |
246 | 246 |
* Returns the number of infected files or -1 on error */ |
247 | 247 |
int dsresult(int sockd, int scantype, const char *filename) { |
248 |
- int infected = 0, waserror = 0, len, beenthere = 0; |
|
249 |
- char *bol, *eol; |
|
250 |
- struct RCVLN rcv; |
|
248 |
+ int infected = 0, len, beenthere = 0; |
|
249 |
+ char *bol, *eol; |
|
250 |
+ struct RCVLN rcv; |
|
251 | 251 |
|
252 | 252 |
recvlninit(&rcv, sockd); |
253 | 253 |
|
... | ... |
@@ -277,17 +273,14 @@ int dsresult(int sockd, int scantype, const char *filename) { |
277 | 277 |
} |
278 | 278 |
|
279 | 279 |
while((len = recvln(&rcv, &bol, &eol))) { |
280 |
- if(len == -1) { |
|
281 |
- waserror = 1; |
|
282 |
- break; |
|
283 |
- } |
|
280 |
+ if(len == -1) return -1; |
|
284 | 281 |
beenthere = 1; |
285 | 282 |
if(!filename) logg("~%s\n", bol); |
286 | 283 |
if(len > 7) { |
287 | 284 |
char *colon = strrchr(bol, ':'); |
288 | 285 |
if(!colon) { |
289 | 286 |
logg("Failed to parse reply\n"); |
290 |
- waserror = 1; |
|
287 |
+ return -1; |
|
291 | 288 |
} else if(!memcmp(eol - 7, " FOUND", 6)) { |
292 | 289 |
infected++; |
293 | 290 |
if(filename) { |
... | ... |
@@ -308,15 +301,14 @@ int dsresult(int sockd, int scantype, const char *filename) { |
308 | 308 |
else |
309 | 309 |
logg("~%s\n", bol); |
310 | 310 |
} |
311 |
- waserror = 1; |
|
312 | 311 |
} |
313 | 312 |
} |
314 | 313 |
} |
315 | 314 |
if(!beenthere) { |
316 | 315 |
logg("~%s: no reply from clamd\n", filename ? filename : "STDIN"); |
317 |
- waserror = 1; |
|
316 |
+ return -1; |
|
318 | 317 |
} |
319 |
- return infected ? infected : (waserror ? -1 : 0); |
|
318 |
+ return infected; |
|
320 | 319 |
} |
321 | 320 |
|
322 | 321 |
|
... | ... |
@@ -324,9 +316,7 @@ int dsresult(int sockd, int scantype, const char *filename) { |
324 | 324 |
/* Used by serial_callback() */ |
325 | 325 |
struct client_serial_data { |
326 | 326 |
int infected; |
327 |
- int errors; |
|
328 | 327 |
int scantype; |
329 |
- int spam; |
|
330 | 328 |
}; |
331 | 329 |
|
332 | 330 |
/* FTW callback for scanning in non IDSESSION mode |
... | ... |
@@ -349,27 +339,25 @@ static int serial_callback(struct stat *sb, char *filename, const char *path, en |
349 | 349 |
return CL_SUCCESS; |
350 | 350 |
case warning_skipped_special: |
351 | 351 |
logg("~%s: Not supported file type. ERROR\n", path); |
352 |
- c->errors++; |
|
353 | 352 |
return CL_SUCCESS; |
354 | 353 |
case visit_directory_toplev: |
355 |
- c->spam = 1; |
|
356 | 354 |
if(c->scantype >= STREAM) |
357 | 355 |
return CL_SUCCESS; |
358 | 356 |
f = path; |
359 |
- default: |
|
357 |
+ filename = NULL; |
|
358 |
+ case visit_file: |
|
360 | 359 |
break; |
361 | 360 |
} |
362 | 361 |
|
363 | 362 |
if((sockd = dconnect()) < 0) { |
364 |
- free(filename); |
|
363 |
+ if(filename) free(filename); |
|
365 | 364 |
return CL_EOPEN; |
366 | 365 |
} |
367 |
- if((ret = dsresult(sockd, c->scantype, f)) >= 0) |
|
368 |
- c->infected += ret; |
|
369 |
- else |
|
370 |
- c->errors++; |
|
366 |
+ ret = dsresult(sockd, c->scantype, f); |
|
367 |
+ if(filename) free(filename); |
|
371 | 368 |
close(sockd); |
372 |
- free(filename); |
|
369 |
+ if(ret < 0) return CL_VIRUS; |
|
370 |
+ c->infected += ret; |
|
373 | 371 |
if(reason == visit_directory_toplev) |
374 | 372 |
return CL_BREAK; |
375 | 373 |
return CL_SUCCESS; |
... | ... |
@@ -377,23 +365,20 @@ static int serial_callback(struct stat *sb, char *filename, const char *path, en |
377 | 377 |
|
378 | 378 |
/* Non-IDSESSION handler |
379 | 379 |
* Returns non zero for serious errors, zero otherwise */ |
380 |
-int serial_client_scan(char *file, int scantype, int *infected, int *errors, int maxlevel, int flags) { |
|
380 |
+int serial_client_scan(char *file, int scantype, int *infected, int maxlevel, int flags) { |
|
381 | 381 |
struct cli_ftw_cbdata data; |
382 | 382 |
struct client_serial_data cdata; |
383 | 383 |
int ftw; |
384 | 384 |
|
385 | 385 |
cdata.infected = 0; |
386 |
- cdata.errors = 0; |
|
387 | 386 |
cdata.scantype = scantype; |
388 |
- cdata.spam = 0; |
|
389 | 387 |
data.data = &cdata; |
390 | 388 |
|
391 | 389 |
ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, serial_callback, &data); |
392 | 390 |
*infected += cdata.infected; |
393 |
- *errors += cdata.errors; |
|
394 | 391 |
|
395 | 392 |
if(ftw == CL_SUCCESS || ftw == CL_BREAK) { |
396 |
- if(!printinfected && !cdata.infected && (!cdata.errors || cdata.spam)) |
|
393 |
+ if(!printinfected && !cdata.infected) |
|
397 | 394 |
logg("~%s: OK\n", file); |
398 | 395 |
return 0; |
399 | 396 |
} |
... | ... |
@@ -403,9 +388,7 @@ int serial_client_scan(char *file, int scantype, int *infected, int *errors, int |
403 | 403 |
/* Used in IDSESSION mode */ |
404 | 404 |
struct client_parallel_data { |
405 | 405 |
int infected; |
406 |
- int errors; |
|
407 | 406 |
int scantype; |
408 |
- int spam; |
|
409 | 407 |
int sockd; |
410 | 408 |
int lastid; |
411 | 409 |
struct SCANID { |
... | ... |
@@ -429,11 +412,8 @@ static int dspresult(struct client_parallel_data *c) { |
429 | 429 |
recvlninit(&rcv, c->sockd); |
430 | 430 |
do { |
431 | 431 |
len = recvln(&rcv, &bol, &eol); |
432 |
- if(!bol || len == -1) { |
|
433 |
- c->errors++; |
|
434 |
- return 1; |
|
435 |
- } |
|
436 |
- if(!bol) return 0; |
|
432 |
+ if(len < 0) return 1; |
|
433 |
+ if(!len) return 0; |
|
437 | 434 |
if((rid = atoi(bol))) { |
438 | 435 |
id = &c->ids; |
439 | 436 |
while(*id) { |
... | ... |
@@ -443,7 +423,6 @@ static int dspresult(struct client_parallel_data *c) { |
443 | 443 |
if(!*id) id = NULL; |
444 | 444 |
} |
445 | 445 |
if(!id) { |
446 |
- c->errors++; |
|
447 | 446 |
logg("!Bogus session id from clamd\n"); |
448 | 447 |
return 1; |
449 | 448 |
} |
... | ... |
@@ -451,16 +430,15 @@ static int dspresult(struct client_parallel_data *c) { |
451 | 451 |
if(len > 7) { |
452 | 452 |
char *colon = strrchr(bol, ':'); |
453 | 453 |
if(!colon) { |
454 |
- c->errors++; |
|
455 |
- logg("Failed to parse reply\n"); |
|
454 |
+ logg("!Failed to parse reply\n"); |
|
455 |
+ free((void *)filename); |
|
456 |
+ return 1; |
|
456 | 457 |
} else if(!memcmp(eol - 7, " FOUND", 6)) { |
457 | 458 |
c->infected++; |
458 | 459 |
logg("~%s%s\n", filename, colon); |
459 | 460 |
if(action) action(filename); |
460 | 461 |
} else if(!memcmp(eol-7, " ERROR", 6)) { |
461 |
- c->errors++; |
|
462 |
- if(filename) |
|
463 |
- logg("~%s%s\n", filename, colon); |
|
462 |
+ logg("~%s%s\n", filename, colon); |
|
464 | 463 |
} |
465 | 464 |
} |
466 | 465 |
free((void *)filename); |
... | ... |
@@ -473,7 +451,7 @@ static int dspresult(struct client_parallel_data *c) { |
473 | 473 |
} |
474 | 474 |
|
475 | 475 |
/* FTW callback for scanning in IDSESSION mode |
476 |
- * Returns SUCCESS or BREAK on success, CL_EXXX on error */ |
|
476 |
+ * Returns SUCCESS on success, CL_EXXX or BREAK on error */ |
|
477 | 477 |
static int parallel_callback(struct stat *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) { |
478 | 478 |
struct client_parallel_data *c = (struct client_parallel_data *)data->data; |
479 | 479 |
struct SCANID **id = &c->ids, *cid; |
... | ... |
@@ -490,12 +468,10 @@ static int parallel_callback(struct stat *sb, char *filename, const char *path, |
490 | 490 |
return CL_SUCCESS; |
491 | 491 |
case warning_skipped_special: |
492 | 492 |
logg("~%s: Not supported file type. ERROR\n", path); |
493 |
- c->errors++; |
|
494 |
- return CL_SUCCESS; |
|
493 |
+ case warning_skipped_link: |
|
495 | 494 |
case visit_directory_toplev: |
496 |
- c->spam = 1; |
|
497 | 495 |
return CL_SUCCESS; |
498 |
- default: |
|
496 |
+ case visit_file: |
|
499 | 497 |
break; |
500 | 498 |
} |
501 | 499 |
|
... | ... |
@@ -510,9 +486,8 @@ static int parallel_callback(struct stat *sb, char *filename, const char *path, |
510 | 510 |
FD_SET(c->sockd, &wfds); |
511 | 511 |
if(select(c->sockd + 1, &rfds, &wfds, NULL, NULL) < 0) { |
512 | 512 |
if(errno == EINTR) continue; |
513 |
- c->errors++; |
|
514 | 513 |
free(filename); |
515 |
- logg("!select failed during session\n"); |
|
514 |
+ logg("!select() failed during session\n"); |
|
516 | 515 |
return CL_BREAK; |
517 | 516 |
} |
518 | 517 |
if(FD_ISSET(c->sockd, &rfds)) { |
... | ... |
@@ -554,7 +529,7 @@ static int parallel_callback(struct stat *sb, char *filename, const char *path, |
554 | 554 |
|
555 | 555 |
/* IDSESSION handler |
556 | 556 |
* Returns non zero for serious errors, zero otherwise */ |
557 |
-int parallel_client_scan(char *file, int scantype, int *infected, int *errors, int maxlevel, int flags) { |
|
557 |
+int parallel_client_scan(char *file, int scantype, int *infected, int maxlevel, int flags) { |
|
558 | 558 |
struct cli_ftw_cbdata data; |
559 | 559 |
struct client_parallel_data cdata; |
560 | 560 |
int ftw; |
... | ... |
@@ -568,18 +543,15 @@ int parallel_client_scan(char *file, int scantype, int *infected, int *errors, i |
568 | 568 |
} |
569 | 569 |
|
570 | 570 |
cdata.infected = 0; |
571 |
- cdata.errors = 0; |
|
572 | 571 |
cdata.scantype = scantype; |
573 |
- cdata.spam = 0; |
|
574 | 572 |
cdata.lastid = 0; |
575 | 573 |
cdata.ids = NULL; |
576 | 574 |
data.data = &cdata; |
577 | 575 |
|
578 | 576 |
ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, parallel_callback, &data); |
579 | 577 |
|
580 |
- if(ftw != CL_SUCCESS && ftw != CL_BREAK) { |
|
578 |
+ if(ftw != CL_SUCCESS) { |
|
581 | 579 |
*infected += cdata.infected; |
582 |
- *errors += cdata.errors; |
|
583 | 580 |
close(cdata.sockd); |
584 | 581 |
return 1; |
585 | 582 |
} |
... | ... |
@@ -589,13 +561,12 @@ int parallel_client_scan(char *file, int scantype, int *infected, int *errors, i |
589 | 589 |
close(cdata.sockd); |
590 | 590 |
|
591 | 591 |
*infected += cdata.infected; |
592 |
- *errors += cdata.errors; |
|
593 | 592 |
|
594 | 593 |
if(cdata.ids) { |
595 |
- logg("!Clamd closed connection before scanning all files.\n"); |
|
594 |
+ logg("!Clamd closed the connection before scanning all files.\n"); |
|
596 | 595 |
return 1; |
597 | 596 |
} |
598 |
- if(!printinfected && !cdata.infected && (!cdata.errors || cdata.spam)) |
|
597 |
+ if(!printinfected && !cdata.infected) |
|
599 | 598 |
logg("~%s: OK\n", file); |
600 | 599 |
return 0; |
601 | 600 |
} |
... | ... |
@@ -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 *errors, int maxlevel, int flags); |
|
38 |
-int parallel_client_scan(char *file, int scantype, int *infected, int *errors, int maxlevel, int flags); |
|
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 | 39 |
int dsresult(int sockd, int scantype, const char *filename); |
40 | 40 |
#endif |