git-svn-id: file:///var/lib/svn/clamav-devel/branches/clamd-proto@4663 77e5149b-7576-45b1-b177-96237e5ba77b
aCaB authored on 2009/01/30 02:31:37... | ... |
@@ -47,6 +47,7 @@ |
47 | 47 |
#include "shared/output.h" |
48 | 48 |
#include "shared/misc.h" |
49 | 49 |
#include "libclamav/str.h" |
50 |
+#include "libclamav/others.h" |
|
50 | 51 |
|
51 | 52 |
#include "client.h" |
52 | 53 |
|
... | ... |
@@ -206,7 +207,7 @@ static int dsresult(int sockd, int scantype, const char *filename) |
206 | 206 |
if(filename) { |
207 | 207 |
if(!(fd = open(filename, O_RDONLY))) { |
208 | 208 |
logg("!Open failed on %s.\n", filename); |
209 |
- return -1; |
|
209 |
+ return -1; |
|
210 | 210 |
} |
211 | 211 |
} else fd = 0; |
212 | 212 |
if(sendln(sockd, "zSTREAM", 8)) return -1; |
... | ... |
@@ -397,81 +398,75 @@ static int isremote(const struct optstruct *opts) { |
397 | 397 |
return ret; |
398 | 398 |
} |
399 | 399 |
|
400 |
-static int client_scan(const char *file, int scantype, int *infected, int *errors, int level) { |
|
401 |
- struct stat sb; |
|
402 |
- char *fullpath; |
|
403 |
- DIR *dir; |
|
404 |
- struct dirent *dent; |
|
405 |
- int ret, sockd; |
|
406 |
- |
|
407 |
- level++; |
|
408 |
- if(stat(file, &sb) == -1) { |
|
409 |
- logg("^Can't access file %s\n", file); |
|
410 |
- perror(file); |
|
411 |
- (*errors)++; |
|
412 |
- return 0; |
|
413 |
- } |
|
414 |
- if(!(fullpath = malloc(PATH_MAX + 1))) { |
|
415 |
- logg("^Can't make room for fullpath.\n"); |
|
416 |
- (*errors)++; |
|
417 |
- return 0; |
|
400 |
+struct client_cb_data { |
|
401 |
+ int infected; |
|
402 |
+ int errors; |
|
403 |
+ int scantype; |
|
404 |
+ int spam; |
|
405 |
+}; |
|
406 |
+ |
|
407 |
+int callback(struct stat *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) { |
|
408 |
+ struct client_cb_data *c = (struct client_cb_data *)data->data; |
|
409 |
+ int sockd, ret; |
|
410 |
+ const char *f = filename; |
|
411 |
+ |
|
412 |
+ switch(reason) { |
|
413 |
+ case error_stat: |
|
414 |
+ logg("^Can't access file %s\n", filename); |
|
415 |
+ return CL_SUCCESS; |
|
416 |
+ case error_mem: |
|
417 |
+ logg("^Memory allocation failed in ftw\n"); |
|
418 |
+ return CL_EMEM; |
|
419 |
+ case warning_skipped_dir: |
|
420 |
+ logg("^Directory recursion limit reached\n"); |
|
421 |
+ return CL_SUCCESS; |
|
422 |
+ case warning_skipped_special: |
|
423 |
+ logg("~%s: Not supported file type. ERROR\n", filename); |
|
424 |
+ c->errors++; |
|
425 |
+ return CL_SUCCESS; |
|
426 |
+ default: |
|
427 |
+ break; |
|
418 | 428 |
} |
419 | 429 |
|
420 |
- if(*file != '/') { /* FIXME: to be unified */ |
|
421 |
- int namelen; |
|
422 |
- if(!getcwd(fullpath, PATH_MAX)) { |
|
423 |
- logg("^Can't get absolute pathname of current working directory.\n"); |
|
424 |
- free(fullpath); |
|
425 |
- (*errors)++; |
|
426 |
- return 0; |
|
430 |
+ if(reason == visit_directory_toplev) { |
|
431 |
+ c->spam = 1; |
|
432 |
+ if(c->scantype >= STREAM) { |
|
433 |
+ free(filename); |
|
434 |
+ return CL_SUCCESS; |
|
427 | 435 |
} |
428 |
- namelen = strlen(fullpath); |
|
429 |
- snprintf(&fullpath[namelen], PATH_MAX - namelen, "/%s", file); |
|
430 |
- } else { |
|
431 |
- strncpy(fullpath, file, PATH_MAX); |
|
436 |
+ f = path; |
|
432 | 437 |
} |
433 |
- fullpath[PATH_MAX] = '\0'; |
|
434 |
- |
|
435 |
- switch(sb.st_mode & S_IFMT) { |
|
436 |
- case S_IFDIR: |
|
437 |
- if(scantype >= STREAM) { |
|
438 |
- if(!(dir = opendir(fullpath))) |
|
439 |
- break; |
|
440 |
- ret = strlen(fullpath); |
|
441 |
- while((dent = readdir(dir))) { |
|
442 |
- if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) continue; |
|
443 |
- snprintf(&fullpath[ret], PATH_MAX - ret, "/%s", dent->d_name); |
|
444 |
- fullpath[PATH_MAX] = '\0'; |
|
445 |
- if(client_scan(fullpath, scantype, infected, errors, level)) { |
|
446 |
- closedir(dir); |
|
447 |
- free(fullpath); |
|
448 |
- return 1; |
|
449 |
- } |
|
438 |
+ if((sockd = dconnect()) < 0) { |
|
439 |
+ free(filename); |
|
440 |
+ return CL_BREAK; |
|
441 |
+ } |
|
442 |
+ if((ret = dsresult(sockd, c->scantype, f)) >= 0) |
|
443 |
+ c->infected += ret; |
|
444 |
+ else |
|
445 |
+ c->errors++; |
|
446 |
+ close(sockd); |
|
447 |
+ free(filename); |
|
448 |
+ if(reason == visit_directory_toplev) |
|
449 |
+ return CL_BREAK; |
|
450 |
+ return CL_SUCCESS; |
|
451 |
+} |
|
450 | 452 |
|
451 |
- } |
|
452 |
- closedir(dir); |
|
453 |
- if(level == 1) fullpath[ret] = '\0'; |
|
454 |
- break; |
|
455 |
- } |
|
453 |
+static int client_scan(const char *file, int scantype, int *infected, int *errors, int level) { |
|
454 |
+ struct cli_ftw_cbdata data; |
|
455 |
+ struct client_cb_data cdata; |
|
456 | 456 |
|
457 |
- case S_IFREG: |
|
458 |
- if((sockd = dconnect()) < 0) |
|
459 |
- return 1; |
|
460 |
- if((ret = dsresult(sockd, scantype, fullpath)) >= 0) |
|
461 |
- *infected += ret; |
|
462 |
- else |
|
463 |
- (*errors)++; |
|
464 |
- close(sockd); |
|
465 |
- break; |
|
457 |
+ cdata.infected = 0; |
|
458 |
+ cdata.errors = 0; |
|
459 |
+ cdata.scantype = scantype; |
|
460 |
+ cdata.spam = 0; |
|
461 |
+ data.data = &cdata; |
|
466 | 462 |
|
467 |
- default: |
|
468 |
- logg("^Not supported file type (%s)\n", fullpath); |
|
469 |
- errors++; |
|
470 |
- } |
|
463 |
+ cli_ftw(file, CLI_FTW_STD, 10, callback, &data); |
|
471 | 464 |
|
472 |
- if(level == 1 && !*infected && ((sb.st_mode & S_IFMT) == S_IFDIR || !*errors)) logg("~%s: OK\n", fullpath); |
|
465 |
+ if(!cdata.errors) logg("~%s: OK\n", file); |
|
473 | 466 |
|
474 |
- free(fullpath); |
|
467 |
+ *infected += cdata.infected; |
|
468 |
+ *errors += cdata.errors; |
|
475 | 469 |
return 0; |
476 | 470 |
} |
477 | 471 |
|
... | ... |
@@ -487,7 +482,6 @@ int get_clamd_version(const struct optstruct *opts) |
487 | 487 |
recvlninit(&rcv, sockd); |
488 | 488 |
|
489 | 489 |
if(sendln(sockd, "zVERSION", 9)) { |
490 |
- logg("!Can't write to the socket.\n"); |
|
491 | 490 |
close(sockd); |
492 | 491 |
return 2; |
493 | 492 |
} |
... | ... |
@@ -577,11 +571,32 @@ int client(const struct optstruct *opts, int *infected) |
577 | 577 |
} else if(opts->filename) { |
578 | 578 |
unsigned int i; |
579 | 579 |
for (i = 0; opts->filename[i]; i++) { |
580 |
+ char *fullpath; |
|
580 | 581 |
if(!strcmp(opts->filename[i], "-")) { |
581 | 582 |
logg("!Scanning from standard input requires \"-\" to be the only file argument\n"); |
582 | 583 |
continue; |
583 | 584 |
} |
585 |
+ if(!(fullpath = malloc(PATH_MAX + 1))) { |
|
586 |
+ logg("^Can't make room for fullpath.\n"); |
|
587 |
+ errors++; |
|
588 |
+ continue; |
|
589 |
+ } |
|
590 |
+ if(*opts->filename[i] != '/') { /* FIXME: to be unified */ |
|
591 |
+ int namelen; |
|
592 |
+ if(!getcwd(fullpath, PATH_MAX)) { |
|
593 |
+ logg("^Can't get absolute pathname of current working directory.\n"); |
|
594 |
+ free(fullpath); |
|
595 |
+ errors++; |
|
596 |
+ break; |
|
597 |
+ } |
|
598 |
+ namelen = strlen(fullpath); |
|
599 |
+ snprintf(&fullpath[namelen], PATH_MAX - namelen, "/%s", opts->filename[i]); |
|
600 |
+ } else { |
|
601 |
+ strncpy(fullpath, opts->filename[i], PATH_MAX); |
|
602 |
+ } |
|
603 |
+ fullpath[PATH_MAX] = '\0'; |
|
584 | 604 |
client_scan(opts->filename[i], scantype, infected, &errors, 0); |
605 |
+ free(fullpath); |
|
585 | 606 |
} |
586 | 607 |
} else { |
587 | 608 |
char cwd[PATH_MAX+1]; |