git-svn: trunk@5069
Tomasz Kojm authored on 2009/05/21 22:43:05... | ... |
@@ -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, "", "" }, |