Browse code

clamscan, clamdscan: add support for --file-list/-f

git-svn: trunk@5069

Tomasz Kojm authored on 2009/05/21 22:43:05
Showing 10 changed files
... ...
@@ -1,3 +1,7 @@
1
+Thu May 21 15:41:36 CEST 2009 (tk)
2
+----------------------------------
3
+ * clamscan, clamdscan: add support for --file-list/-f
4
+
1 5
 Fri May 15 15:10:59 EEST 2009 (edwin)
2 6
 -------------------------------------
3 7
  * libclamav/others.h, libclamav/regex/regex.h: fix compiler warning
... ...
@@ -169,6 +169,7 @@ void help(void)
169 169
     mprintf("    --stdout                           Write to stdout instead of stderr\n");
170 170
     mprintf("                                       (this help is always written to stdout)\n");
171 171
     mprintf("    --log=FILE          -l FILE        Save scan report in FILE\n");
172
+    mprintf("    --file-list=FILE    -f FILE        Scan files from FILE\n");
172 173
     mprintf("    --remove                           Remove infected files. Be careful!\n");
173 174
     mprintf("    --move=DIRECTORY                   Move infected files into DIRECTORY\n");
174 175
     mprintf("    --copy=DIRECTORY                   Copy infected files into DIRECTORY\n");
... ...
@@ -215,13 +215,14 @@ int client(const struct optstruct *opts, int *infected)
215 215
 	const char *clamd_conf = optget(opts, "config-file")->strarg;
216 216
 	struct optstruct *clamdopts;
217 217
 	int remote, scantype, session = 0, errors = 0, scandash = 0, maxrec, flags = 0;
218
+	const char *fname;
218 219
 
219 220
     if((clamdopts = optparse(clamd_conf, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL) {
220 221
 	logg("!Can't parse clamd configuration file %s\n", clamd_conf);
221 222
 	return 2;
222 223
     }
223 224
 
224
-    scandash = (opts->filename && opts->filename[0] && !strcmp(opts->filename[0], "-") && !opts->filename[1]);
225
+    scandash = (opts->filename && opts->filename[0] && !strcmp(opts->filename[0], "-") && !optget(opts, "file-list")->enabled && !opts->filename[1]);
225 226
     remote = isremote(opts) | optget(opts, "stream")->enabled;
226 227
 #ifdef HAVE_FD_PASSING
227 228
     if(!remote && optget(clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled || scandash)) {
... ...
@@ -261,14 +262,16 @@ int client(const struct optstruct *opts, int *infected)
261 261
 	else
262 262
 	    errors = 1;
263 263
 	if(sockd >= 0) close(sockd);
264
-    } else if(opts->filename) {
265
-	unsigned int i;
266
-	for (i = 0; !errors && opts->filename[i]; i++) {
267
-	    if(!strcmp(opts->filename[i], "-")) {
264
+    } else if(opts->filename || optget(opts, "file-list")->enabled) {
265
+	if(opts->filename && optget(opts, "file-list")->enabled)
266
+	    logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n");
267
+
268
+	while(!errors && (fname = filelist(opts, NULL))) {
269
+	    if(!strcmp(fname, "-")) {
268 270
 		logg("!Scanning from standard input requires \"-\" to be the only file argument\n");
269 271
 		continue;
270 272
 	    }
271
-	    errors = client_scan(opts->filename[i], scantype, infected, maxrec, session, flags);
273
+	    errors = client_scan(fname, scantype, infected, maxrec, session, flags);
272 274
 	}
273 275
     } else {
274 276
 	errors = client_scan("", scantype, infected, maxrec, session, flags);
... ...
@@ -238,6 +238,7 @@ void help(void)
238 238
     mprintf("                                         all supported db files from DIR\n");
239 239
     mprintf("    --log=FILE            -l FILE        Save scan report to FILE\n");
240 240
     mprintf("    --recursive[=yes/no(*)]  -r          Scan subdirectories recursively\n");
241
+    mprintf("    --file-list=FILE      -f FILE        Scan files from FILE\n");
241 242
     mprintf("    --remove[=yes/no(*)]                 Remove infected files. Be careful!\n");
242 243
     mprintf("    --move=DIRECTORY                     Move infected files into DIRECTORY\n");
243 244
     mprintf("    --copy=DIRECTORY                     Copy infected files into DIRECTORY\n");
... ...
@@ -238,7 +238,6 @@ static int scandirs(const char *dirname, struct cl_engine *engine, const struct
238 238
 		    }
239 239
 		    free(fname);
240 240
 		}
241
-
242 241
 	    }
243 242
 	}
244 243
     } else {
... ...
@@ -328,11 +327,12 @@ static int scanstdin(const struct cl_engine *engine, const struct optstruct *opt
328 328
 int scanmanager(const struct optstruct *opts)
329 329
 {
330 330
 	mode_t fmode;
331
-	int ret = 0, fmodeint, i, x;
331
+	int ret = 0, fmodeint, i;
332 332
 	unsigned int options = 0, dboptions = 0;
333 333
 	struct cl_engine *engine;
334 334
 	struct stat sb;
335 335
 	char *file, cwd[1024], *pua_cats = NULL;
336
+	const char *filename;
336 337
 	const struct optstruct *opt;
337 338
 #ifndef C_WINDOWS
338 339
 	struct rlimit rlim;
... ...
@@ -588,7 +588,7 @@ int scanmanager(const struct optstruct *opts)
588 588
 #endif
589 589
 
590 590
     /* check filetype */
591
-    if(opts->filename == NULL) {
591
+    if(!opts->filename && !optget(opts, "file-list")->enabled) {
592 592
 	/* we need full path for some reasons (eg. archive handling) */
593 593
 	if(!getcwd(cwd, sizeof(cwd))) {
594 594
 	    logg("!Can't get absolute pathname of current working directory\n");
... ...
@@ -596,11 +596,14 @@ int scanmanager(const struct optstruct *opts)
596 596
 	} else
597 597
 	    ret = scandirs(cwd, engine, opts, options, 1);
598 598
 
599
-    } else if(!strcmp(opts->filename[0], "-")) { /* read data from stdin */
599
+    } else if(opts->filename && !optget(opts, "file-list")->enabled && !strcmp(opts->filename[0], "-")) { /* read data from stdin */
600 600
 	ret = scanstdin(engine, opts, options);
601 601
 
602 602
     } else {
603
-	for (x = 0; opts->filename[x] && (file = strdup(opts->filename[x])); x++) {
603
+	if(opts->filename && optget(opts, "file-list")->enabled)
604
+	    logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n");
605
+
606
+	while((filename = filelist(opts, &ret)) && (file = strdup(filename))) {
604 607
 	    if((fmodeint = fileinfo(file, 2)) == -1) {
605 608
 		logg("^Can't access file %s\n", file);
606 609
 		perror(file);
... ...
@@ -33,6 +33,9 @@ Read clamd settings from FILE.
33 33
 \fB\-l FILE, \-\-log=FILE\fR
34 34
 Save the scan report to FILE.
35 35
 .TP 
36
+\fB\-f FILE, \-\-file\-list=FILE\fR
37
+Scan files listed line by line in FILE.
38
+.TP 
36 39
 \fB\-m, \-\-multiscan\fR
37 40
 In multiscan mode several files are scanned in parallel, one for each available scan thread in clamd.
38 41
 This is achieved either via MULTISCAN or IDSESSION requests, depending on the configuration and other options.
... ...
@@ -42,6 +42,9 @@ Create temporary files in DIRECTORY. Directory must be writable for the '@CLAMAV
42 42
 \fB\-\-leave\-temps\fR
43 43
 Do not remove temporary files.
44 44
 .TP 
45
+\fB\-f FILE, \-\-file\-list=FILE\fR
46
+Scan files listed line by line in FILE.
47
+.TP 
45 48
 \fB\-r, \-\-recursive\fR
46 49
 Scan directories recursively. All the subdirectories in the given directory will be scanned.
47 50
 .TP 
... ...
@@ -159,6 +159,45 @@ void print_version(const char *dbdir)
159 159
 }
160 160
 #endif
161 161
 
162
+const char *filelist(const struct optstruct *opts, int *err)
163
+{
164
+	static char buff[1025];
165
+	static unsigned int cnt = 0;
166
+	const struct optstruct *opt;
167
+	static FILE *fs = NULL;
168
+	size_t len;
169
+
170
+    if(!cnt && (opt = optget(opts, "file-list"))->enabled) {
171
+	if(!fs) {
172
+	    fs = fopen(opt->strarg, "r");
173
+	    if(!fs) {
174
+		fprintf(stderr, "ERROR: --file-list: Can't open file %s\n", opt->strarg);
175
+		if(err)
176
+		    *err = 54;
177
+		return NULL;
178
+	    }
179
+	}
180
+
181
+	if(fgets(buff, 1024, fs)) {
182
+	    buff[1024] = 0;
183
+	    len = strlen(buff);
184
+	    if(!len) {
185
+		fclose(fs);
186
+		return NULL;
187
+	    }
188
+	    len--;
189
+	    while(len && ((buff[len] == '\n') || (buff[len] == '\r')))
190
+		buff[len--] = '\0';
191
+	    return buff;
192
+	} else {
193
+	    fclose(fs);
194
+	    return NULL;
195
+	}
196
+    }
197
+
198
+    return opts->filename ? opts->filename[cnt++] : NULL;
199
+}
200
+
162 201
 int filecopy(const char *src, const char *dest)
163 202
 {
164 203
 #ifdef C_DARWIN
... ...
@@ -46,6 +46,7 @@ typedef unsigned        int     in_addr_t;
46 46
 
47 47
 char *freshdbdir(void);
48 48
 void print_version(const char *dbdir);
49
+const char *filelist(const struct optstruct *opts, int *err);
49 50
 int filecopy(const char *src, const char *dest);
50 51
 int daemonize(void);
51 52
 const char *get_version(void);
... ...
@@ -85,6 +85,7 @@ const struct clam_option clam_options[] = {
85 85
     { NULL, "recursive", 'r', TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", "" },
86 86
     { NULL, "bell", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", "" },
87 87
     { NULL, "no-summary", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
88
+    { NULL, "file-list", 'f', TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
88 89
     { NULL, "infected", 'i', TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
89 90
     { NULL, "move", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
90 91
     { NULL, "copy", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },