| ... | ... |
@@ -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, "", "" },
|