Browse code

merge multiscan() with dirscan() (also closes bb#302)

git-svn: trunk@2821

Tomasz Kojm authored on 2007/02/21 06:19:04
Showing 4 changed files
... ...
@@ -1,3 +1,7 @@
1
+Tue Feb 20 20:19:04 CET 2007 (tk)
2
+---------------------------------
3
+  * clamd: merge multiscan() with dirscan() (also closes bb#302)
4
+
1 5
 Tue Feb 20 16:43:27 CET 2007 (tk)
2 6
 ---------------------------------
3 7
   * libclamav/others.c: increase f-level to activate RTF extractor
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
2
+ *  Copyright (C) 2002 - 2007 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -63,16 +63,28 @@
63 63
 #include "scanner.h"
64 64
 #include "shared.h"
65 65
 #include "network.h"
66
+#include "thrmgr.h"
66 67
 
67 68
 #ifdef C_LINUX
68 69
 dev_t procdev; /* /proc device */
69 70
 #endif
70 71
 
72
+extern int progexit;
73
+
71 74
 #ifndef	C_WINDOWS
72 75
 #define	closesocket(s)	close(s)
73 76
 #endif
74 77
 
75
-int checksymlink(const char *path)
78
+struct multi_tag {
79
+    int sd;
80
+    unsigned int options;
81
+    const struct cfgstruct *copt;
82
+    char *fname;
83
+    const struct cl_engine *engine;
84
+    const struct cl_limits *limits;
85
+};
86
+
87
+static int checksymlink(const char *path)
76 88
 {
77 89
 	struct stat statbuf;
78 90
 
... ...
@@ -88,8 +100,7 @@ int checksymlink(const char *path)
88 88
     return 0;
89 89
 }
90 90
 
91
-/* :set nowrap, if you don't like this style ;)) */
92
-int dirscan(const char *dirname, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int odesc, unsigned int *reclev, short contscan)
91
+static int dirscan(const char *dirname, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int odesc, unsigned int *reclev, unsigned int type, threadpool_t *multi_pool)
93 92
 {
94 93
 	DIR *dd;
95 94
 	struct dirent *dent;
... ...
@@ -103,6 +114,7 @@ int dirscan(const char *dirname, const char **virname, unsigned long int *scanne
103 103
 	char *fname;
104 104
 	int ret = 0, scanret = 0;
105 105
 	unsigned int maxdirrec = 0;
106
+	struct multi_tag *scandata;
106 107
 
107 108
 
108 109
     maxdirrec = cfgopt(copt, "MaxDirectoryRecursion")->numarg;
... ...
@@ -127,6 +139,12 @@ int dirscan(const char *dirname, const char **virname, unsigned long int *scanne
127 127
 		closedir(dd);
128 128
 		return 1;
129 129
 	    }
130
+
131
+            if(progexit) {
132
+		closedir(dd);
133
+		return 1;
134
+	    }
135
+
130 136
 #if	(!defined(C_INTERIX)) && (!defined(C_WINDOWS)) && (!defined(C_CYGWIN))
131 137
 	    if(dent->d_ino)
132 138
 #endif
... ...
@@ -134,55 +152,98 @@ int dirscan(const char *dirname, const char **virname, unsigned long int *scanne
134 134
 		if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
135 135
 		    /* build the full name */
136 136
 		    fname = (char *) mcalloc(strlen(dirname) + strlen(dent->d_name) + 2, sizeof(char));
137
+                    if(!fname) {
138
+			logg("!Can't allocate memory for fname\n");
139
+			closedir(dd);
140
+			return -2;
141
+		    }
137 142
 		    sprintf(fname, "%s/%s", dirname, dent->d_name);
138 143
 
139 144
 		    /* stat the file */
140 145
 		    if(lstat(fname, &statbuf) != -1) {
141 146
 			if((S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) || (S_ISLNK(statbuf.st_mode) && (checksymlink(fname) == 1) && cfgopt(copt, "FollowDirectorySymlinks")->enabled)) {
142
-			    if(dirscan(fname, virname, scanned, engine, limits, options, copt, odesc, reclev, contscan) == 1) {
147
+			    if(dirscan(fname, virname, scanned, engine, limits, options, copt, odesc, reclev, type, multi_pool) == 1) {
143 148
 				free(fname);
144 149
 				closedir(dd);
145 150
 				return 1;
146 151
 			    }
152
+			    free(fname);
147 153
 			} else {
148 154
 			    if(S_ISREG(statbuf.st_mode) || (S_ISLNK(statbuf.st_mode) && (checksymlink(fname) == 2) && cfgopt(copt, "FollowFileSymlinks")->enabled)) {
149 155
 
150 156
 #ifdef C_LINUX
151 157
 				if(procdev && (statbuf.st_dev == procdev))
152
-				    scanret = CL_CLEAN;
158
+				    free(fname);
153 159
 				else
154 160
 #endif
155
-				    scanret = cl_scanfile(fname, virname, scanned, engine, limits, options);
156
-
157
-				if(scanret == CL_VIRUS) {
161
+				{
162
+				    if(type == TYPE_MULTISCAN) {
163
+
164
+					scandata = (struct multi_tag *) mmalloc(sizeof(struct multi_tag));
165
+					if(!scandata) {
166
+					    logg("!Can't allocate memory for scandata\n");
167
+					    free(fname);
168
+					    closedir(dd);
169
+					    return -2;
170
+					}
171
+					scandata->sd = odesc;
172
+					scandata->options = options;
173
+					scandata->copt = copt;
174
+					scandata->fname = fname;
175
+					scandata->engine = engine;
176
+					scandata->limits = limits;
177
+					if(!thrmgr_dispatch(multi_pool, scandata)) {
178
+					    logg("!thread dispatch failed for multi_pool (file %s)\n", fname);
179
+					    mdprintf(odesc, "ERROR: Can't scan file %s\n", fname);
180
+					    free(fname);
181
+					    free(scandata);
182
+					    closedir(dd);
183
+					    return 1;
184
+					}
185
+
186
+					while(!multi_pool->thr_idle) /* non-critical */
187
+#ifdef C_WINDOWS
188
+					    Sleep(1);
189
+#else
190
+					    usleep(200);
191
+#endif
158 192
 
159
-				    mdprintf(odesc, "%s: %s FOUND\n", fname, *virname);
160
-				    logg("%s: %s FOUND\n", fname, *virname);
161
-				    virusaction(fname, *virname, copt);
162
-				    if(!contscan) {
163
-					closedir(dd);
193
+				    } else { /* CONTSCAN, SCAN */
194
+
195
+					scanret = cl_scanfile(fname, virname, scanned, engine, limits, options);
196
+
197
+					if(scanret == CL_VIRUS) {
198
+
199
+					    mdprintf(odesc, "%s: %s FOUND\n", fname, *virname);
200
+					    logg("%s: %s FOUND\n", fname, *virname);
201
+					    virusaction(fname, *virname, copt);
202
+					    if(type == TYPE_SCAN) {
203
+						closedir(dd);
204
+						free(fname);
205
+						return 1;
206
+					    } else /* CONTSCAN */
207
+						ret = 2;
208
+
209
+					} else if(scanret != CL_CLEAN) {
210
+					    mdprintf(odesc, "%s: %s ERROR\n", fname, cl_strerror(scanret));
211
+					    logg("%s: %s ERROR\n", fname, cl_strerror(scanret));
212
+					    if(scanret == CL_EMEM) {
213
+						closedir(dd);
214
+						free(fname);
215
+						return -2;
216
+					    }
217
+
218
+					} else if(logok) {
219
+					    logg("%s: OK\n", fname);
220
+					}
164 221
 					free(fname);
165
-					return 1;
166
-				    } else
167
-					ret = 2;
168
-
169
-				} else if(scanret != CL_CLEAN) {
170
-				    mdprintf(odesc, "%s: %s ERROR\n", fname, cl_strerror(scanret));
171
-				    logg("%s: %s ERROR\n", fname, cl_strerror(scanret));
172
-				    if(scanret == CL_EMEM) {
173
-					closedir(dd);
174
-				        free(fname);
175
-				        return -2;
176 222
 				    }
177
-
178
-				} else if(logok) {
179
-				    logg("%s: OK\n", fname);
180 223
 				}
181 224
 			    }
182 225
 			}
226
+		    } else {
227
+			free(fname);
183 228
 		    }
184
-
185
-		    free(fname);
186 229
 		}
187 230
 	    }
188 231
 	}
... ...
@@ -193,15 +254,49 @@ int dirscan(const char *dirname, const char **virname, unsigned long int *scanne
193 193
 
194 194
     (*reclev)--;
195 195
     return ret;
196
+}
197
+
198
+static void multiscanfile(void *arg)
199
+{
200
+	struct multi_tag *tag = (struct multi_tag *) arg;
201
+	const char *virname;
202
+#ifndef	C_WINDOWS
203
+        sigset_t sigset;
204
+#endif
205
+	int ret;
196 206
 
207
+
208
+#ifndef	C_WINDOWS
209
+    /* ignore all signals */
210
+    sigfillset(&sigset);
211
+    pthread_sigmask(SIG_SETMASK, &sigset, NULL);
212
+#endif
213
+
214
+    ret = cl_scanfile(tag->fname, &virname, NULL, tag->engine, tag->limits, tag->options);
215
+
216
+    if(ret == CL_VIRUS) {
217
+	mdprintf(tag->sd, "%s: %s FOUND\n", tag->fname, virname);
218
+	logg("%s: %s FOUND\n", tag->fname, virname);
219
+	virusaction(tag->fname, virname, tag->copt);
220
+    } else if(ret != CL_CLEAN) {
221
+	mdprintf(tag->sd, "%s: %s ERROR\n", tag->fname, cl_strerror(ret));
222
+	logg("%s: %s ERROR\n", tag->fname, cl_strerror(ret));
223
+    } else if(logok) {
224
+	logg("%s: OK\n", tag->fname);
225
+    }
226
+
227
+    free(tag->fname);
228
+    free(tag);
229
+    return;
197 230
 }
198 231
 
199
-int scan(const char *filename, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int odesc, short contscan)
232
+int scan(const char *filename, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int odesc, unsigned int type)
200 233
 {
201 234
 	struct stat sb;
202 235
 	int ret = 0;
203 236
 	unsigned int reclev = 0;
204 237
 	const char *virname;
238
+	threadpool_t *multi_pool = NULL;
205 239
 
206 240
 
207 241
     /* stat file */
... ...
@@ -249,7 +344,22 @@ int scan(const char *filename, unsigned long int *scanned, const struct cl_engin
249 249
 	    }
250 250
 	    break;
251 251
 	case S_IFDIR:
252
-	    ret = dirscan(filename, &virname, scanned, engine, limits, options, copt, odesc, &reclev, contscan);
252
+	    if(type == TYPE_MULTISCAN) {
253
+		    int idletimeout = cfgopt(copt, "IdleTimeout")->numarg;
254
+		    int max_threads = cfgopt(copt, "MaxThreads")->numarg;
255
+
256
+		if((multi_pool = thrmgr_new(max_threads, idletimeout, multiscanfile)) == NULL) {
257
+		    logg("!thrmgr_new failed for multi_pool\n");
258
+		    mdprintf(odesc, "thrmgr_new failed for multi_pool ERROR\n");
259
+		    return -1;
260
+		}
261
+	    }
262
+
263
+	    ret = dirscan(filename, &virname, scanned, engine, limits, options, copt, odesc, &reclev, type, multi_pool);
264
+
265
+	    if(multi_pool)
266
+		thrmgr_destroy(multi_pool);
267
+
253 268
 	    break;
254 269
 	default:
255 270
 	    mdprintf(odesc, "%s: Not supported file type. ERROR\n", filename);
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 Tomasz Kojm <tkojm@clamav.net>
2
+ *  Copyright (C) 2002 - 2007 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -20,17 +20,17 @@
20 20
 #ifndef __SCANNER_H
21 21
 #define __SCANNER_H
22 22
 
23
+#define TYPE_SCAN	0
24
+#define TYPE_CONTSCAN	1
25
+#define TYPE_MULTISCAN	2
26
+
23 27
 #include "libclamav/clamav.h"
24 28
 #include "shared/cfgparser.h"
25 29
 
26
-int dirscan(const char *dirname, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int odesc, unsigned int *reclev, short contscan);
27
-
28
-int scan(const char *filename, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int odesc, short contscan);
30
+int scan(const char *filename, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int odesc, unsigned int type);
29 31
 
30 32
 int scanfd(const int fd, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int odesc);
31 33
 
32 34
 int scanstream(int odesc, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt);
33 35
 
34
-int checksymlink(const char *path);
35
-
36 36
 #endif
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
2
+ *  Copyright (C) 2002 - 2007 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -54,179 +54,9 @@
54 54
 #include "others.h"
55 55
 #include "scanner.h"
56 56
 #include "server.h"
57
-#include "clamuko.h"
58 57
 #include "session.h"
59
-#include "thrmgr.h"
60
-#include "shared.h"
61 58
 
62 59
 static pthread_mutex_t ctime_mutex = PTHREAD_MUTEX_INITIALIZER;
63
-extern int progexit;
64
-
65
-struct multi_tag {
66
-    int sd;
67
-    unsigned int options;
68
-    const struct cfgstruct *copt;
69
-    char *fname;
70
-    const struct cl_engine *engine;
71
-    const struct cl_limits *limits;
72
-};
73
-
74
-static void multiscanfile(void *arg)
75
-{
76
-	struct multi_tag *tag = (struct multi_tag *) arg;
77
-	const char *virname;
78
-#ifndef	C_WINDOWS
79
-        sigset_t sigset;
80
-#endif
81
-	int ret;
82
-
83
-
84
-#ifndef	C_WINDOWS
85
-    /* ignore all signals */
86
-    sigfillset(&sigset);
87
-    pthread_sigmask(SIG_SETMASK, &sigset, NULL);
88
-#endif
89
-
90
-    ret = cl_scanfile(tag->fname, &virname, NULL, tag->engine, tag->limits, tag->options);
91
-
92
-    if(ret == CL_VIRUS) {
93
-	mdprintf(tag->sd, "%s: %s FOUND\n", tag->fname, virname);
94
-	logg("%s: %s FOUND\n", tag->fname, virname);
95
-	virusaction(tag->fname, virname, tag->copt);
96
-    } else if(ret != CL_CLEAN) {
97
-	mdprintf(tag->sd, "%s: %s ERROR\n", tag->fname, cl_strerror(ret));
98
-	logg("%s: %s ERROR\n", tag->fname, cl_strerror(ret));
99
-    } else if(logok) {
100
-	logg("%s: OK\n", tag->fname);
101
-    }
102
-
103
-    free(tag->fname);
104
-    free(tag);
105
-    return;
106
-}
107
-
108
-static int multiscan(const char *dirname, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int odesc, unsigned int *reclev, threadpool_t *multi_pool)
109
-{
110
-	DIR *dd;
111
-	struct dirent *dent;
112
-#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2)
113
-	union {
114
-	    struct dirent d;
115
-	    char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
116
-	} result;
117
-#endif
118
-	struct stat statbuf;
119
-	char *fname;
120
-	int scanret = 0;
121
-	unsigned int maxdirrec = 0;
122
-	struct multi_tag *scandata;
123
-
124
-
125
-    maxdirrec = cfgopt(copt, "MaxDirectoryRecursion")->numarg;
126
-    if(maxdirrec) {
127
-	if(*reclev > maxdirrec) {
128
-	    logg("*multiscan: Directory recursion limit exceeded at %s\n", dirname);
129
-	    return 0;
130
-	}
131
-	(*reclev)++;
132
-    }
133
-
134
-    if((dd = opendir(dirname)) != NULL) {
135
-#ifdef HAVE_READDIR_R_3
136
-	while(!readdir_r(dd, &result.d, &dent) && dent) {
137
-#elif defined(HAVE_READDIR_R_2)
138
-	while((dent = (struct dirent *) readdir_r(dd, &result.d))) {
139
-#else
140
-	while((dent = readdir(dd))) {
141
-#endif
142
-	    if (!is_fd_connected(odesc)) {
143
-		logg("multiscan: Client disconnected\n");
144
-		closedir(dd);
145
-		return -1;
146
-	    }
147
-
148
-	    if(progexit) {
149
-		closedir(dd);
150
-		return -1;
151
-	    }
152
-
153
-#if	(!defined(C_INTERIX)) && (!defined(C_WINDOWS)) && (!defined(C_CYGWIN))
154
-	    if(dent->d_ino)
155
-#endif
156
-	    {
157
-		if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
158
-		    /* build the full name */
159
-		    fname = (char *) mcalloc(strlen(dirname) + strlen(dent->d_name) + 2, sizeof(char));
160
-		    if(!fname) {
161
-			logg("!multiscan: Can't allocate memory for fname\n");
162
-			closedir(dd);
163
-			return -1;
164
-		    }
165
-		    sprintf(fname, "%s/%s", dirname, dent->d_name);
166
-
167
-		    /* stat the file */
168
-		    if(lstat(fname, &statbuf) != -1) {
169
-			if((S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) || (S_ISLNK(statbuf.st_mode) && (checksymlink(fname) == 1) && cfgopt(copt, "FollowDirectorySymlinks")->enabled)) {
170
-			    if(multiscan(fname, engine, limits, options, copt, odesc, reclev, multi_pool) == -1) {
171
-				free(fname);
172
-				closedir(dd);
173
-				return -1;
174
-			    }
175
-			    free(fname);
176
-			} else {
177
-			    if(S_ISREG(statbuf.st_mode) || (S_ISLNK(statbuf.st_mode) && (checksymlink(fname) == 2) && cfgopt(copt, "FollowFileSymlinks")->enabled)) {
178
-
179
-#ifdef C_LINUX
180
-				if(procdev && (statbuf.st_dev == procdev))
181
-				    scanret = CL_CLEAN;
182
-				else
183
-#endif
184
-				{
185
-				    scandata = (struct multi_tag *) mmalloc(sizeof(struct multi_tag));
186
-				    if(!scandata) {
187
-					logg("!multiscan: Can't allocate memory for scandata\n");
188
-					free(fname);
189
-					closedir(dd);
190
-					return -1;
191
-				    }
192
-				    scandata->sd = odesc;
193
-				    scandata->options = options;
194
-				    scandata->copt = copt;
195
-				    scandata->fname = fname;
196
-				    scandata->engine = engine;
197
-				    scandata->limits = limits;
198
-				    if(!thrmgr_dispatch(multi_pool, scandata)) {
199
-					logg("!multiscan: thread dispatch failed for multi_pool (file %s)\n", fname);
200
-					mdprintf(odesc, "ERROR: Can't scan file %s\n", fname);
201
-					free(fname);
202
-					free(scandata);
203
-					closedir(dd);
204
-					return -1;
205
-				    }
206
-
207
-				    while(!multi_pool->thr_idle) /* non-critical */
208
-#ifdef C_WINDOWS
209
-					Sleep(1);
210
-#else
211
-					usleep(200);
212
-#endif
213
-				}
214
-			    }
215
-			}
216
-		    } else {
217
-			free(fname);
218
-		    }
219
-		}
220
-	    }
221
-	}
222
-	closedir(dd);
223
-    } else {
224
-	return -2;
225
-    }
226
-
227
-    (*reclev)--;
228
-    return 0;
229
-}
230 60
 
231 61
 int command(int desc, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int timeout)
232 62
 {
... ...
@@ -249,13 +79,13 @@ int command(int desc, const struct cl_engine *engine, const struct cl_limits *li
249 249
     cli_chomp(buff);
250 250
 
251 251
     if(!strncmp(buff, CMD1, strlen(CMD1))) { /* SCAN */
252
-	if(scan(buff + strlen(CMD1) + 1, NULL, engine, limits, options, copt, desc, 0) == -2)
252
+	if(scan(buff + strlen(CMD1) + 1, NULL, engine, limits, options, copt, desc, TYPE_SCAN) == -2)
253 253
 	    if(cfgopt(copt, "ExitOnOOM")->enabled)
254 254
 		return COMMAND_SHUTDOWN;
255 255
 
256 256
     } else if(!strncmp(buff, CMD2, strlen(CMD2))) { /* RAWSCAN */
257 257
 	opt = options & ~CL_SCAN_ARCHIVE;
258
-	if(scan(buff + strlen(CMD2) + 1, NULL, engine, NULL, opt, copt, desc, 0) == -2)
258
+	if(scan(buff + strlen(CMD2) + 1, NULL, engine, NULL, opt, copt, desc, TYPE_SCAN) == -2)
259 259
 	    if(cfgopt(copt, "ExitOnOOM")->enabled)
260 260
 		return COMMAND_SHUTDOWN;
261 261
 
... ...
@@ -270,7 +100,7 @@ int command(int desc, const struct cl_engine *engine, const struct cl_limits *li
270 270
 	mdprintf(desc, "PONG\n");
271 271
 
272 272
     } else if(!strncmp(buff, CMD6, strlen(CMD6))) { /* CONTSCAN */
273
-	if(scan(buff + strlen(CMD6) + 1, NULL, engine, limits, options, copt, desc, 1) == -2)
273
+	if(scan(buff + strlen(CMD6) + 1, NULL, engine, limits, options, copt, desc, TYPE_CONTSCAN) == -2)
274 274
 	    if(cfgopt(copt, "ExitOnOOM")->enabled)
275 275
 		return COMMAND_SHUTDOWN;
276 276
 
... ...
@@ -324,49 +154,9 @@ int command(int desc, const struct cl_engine *engine, const struct cl_limits *li
324 324
 	close(fd); /* FIXME: should we close it here? */
325 325
 
326 326
     } else if(!strncmp(buff, CMD13, strlen(CMD13))) { /* MULTISCAN */
327
-	    threadpool_t *multi_pool;
328
-	    int idletimeout = cfgopt(copt, "IdleTimeout")->numarg;
329
-	    int max_threads = cfgopt(copt, "MaxThreads")->numarg;
330
-	    int ret;
331
-	    unsigned int reclev = 0;
332
-	    const char *path = buff + strlen(CMD13) + 1;
333
-	    const char *virname;
334
-	    struct stat sb;
335
-
336
-	if(stat(path, &sb) == -1) {
337
-	    mdprintf(desc, "Can't stat file %s\n", path);
338
-	    return -1;
339
-	}
340
-
341
-	if(S_ISDIR(sb.st_mode)) {
342
-	    if((multi_pool = thrmgr_new(max_threads, idletimeout, multiscanfile)) == NULL) {
343
-		logg("!thrmgr_new failed for multi_pool\n");
344
-		mdprintf(desc, "ERROR: thrmgr_new failed for multi_pool\n");
345
-		return -1;
346
-	    }
347
-
348
-	    ret = multiscan(path, engine, limits, options, copt, desc, &reclev, multi_pool);
349
-	    thrmgr_destroy(multi_pool);
350
-
351
-	    if(ret < 0)
352
-		return -1;
353
-
354
-	} else {
355
-	    ret = cl_scanfile(path, &virname, NULL, engine, limits, options);
356
-
357
-	    if(ret == CL_VIRUS) {
358
-		mdprintf(desc, "%s: %s FOUND\n", path, virname);
359
-		logg("%s: %s FOUND\n", path, virname);
360
-		virusaction(path, virname, copt);
361
-	    } else if(ret != CL_CLEAN) {
362
-		mdprintf(desc, "%s: %s ERROR\n", path, cl_strerror(ret));
363
-		logg("%s: %s ERROR\n", path, cl_strerror(ret));
364
-	    } else {
365
-		mdprintf(desc, "%s: OK\n", path); 
366
-		if(logok)
367
-		    logg("%s: OK\n", path);
368
-	    }
369
-	}
327
+	if(scan(buff + strlen(CMD13) + 1, NULL, engine, limits, options, copt, desc, TYPE_MULTISCAN) == -2)
328
+	    if(cfgopt(copt, "ExitOnOOM")->enabled)
329
+		return COMMAND_SHUTDOWN;
370 330
 
371 331
     } else {
372 332
 	mdprintf(desc, "UNKNOWN COMMAND\n");