Browse code

Preliminary ftw adoption

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
Showing 1 changed files
... ...
@@ -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];