... | ... |
@@ -39,6 +39,10 @@ clang-format -i -verbose shared/*.c |
39 | 39 |
clang-format -i -verbose shared/*.h |
40 | 40 |
clang-format -i -verbose sigtool/*.c |
41 | 41 |
clang-format -i -verbose sigtool/*.h |
42 |
+clang-format -i -verbose clamonacc/*.c |
|
43 |
+clang-format -i -verbose clamonacc/*.h |
|
44 |
+clang-format -i -verbose clamonacc/*/*.c |
|
45 |
+clang-format -i -verbose clamonacc/*/*.h |
|
42 | 46 |
clang-format -i -verbose unit_tests/*.c |
43 | 47 |
clang-format -i -verbose unit_tests/*.h |
44 | 48 |
clang-format -i -verbose win32/compat/*.c |
... | ... |
@@ -71,3 +75,5 @@ git checkout libclamav/inflate64.h |
71 | 71 |
git checkout libclamav/inflate64.c |
72 | 72 |
git checkout libclamav/inflate64_priv.h |
73 | 73 |
git checkout shared/queue.h |
74 |
+git checkout clamonacc/c-thread-pool/thpool.c |
|
75 |
+git checkout clamonacc/c-thread-pool/thpool.h |
... | ... |
@@ -53,8 +53,7 @@ |
53 | 53 |
#include "inotif/inotif.h" |
54 | 54 |
#include "scan/queue.h" |
55 | 55 |
|
56 |
- |
|
57 |
-pthread_t ddd_pid = 0; |
|
56 |
+pthread_t ddd_pid = 0; |
|
58 | 57 |
pthread_t scan_queue_pid = 0; |
59 | 58 |
|
60 | 59 |
static void onas_handle_signals(); |
... | ... |
@@ -63,202 +62,203 @@ static struct onas_context *g_ctx = NULL; |
63 | 63 |
|
64 | 64 |
static void onas_clamonacc_exit(int sig) |
65 | 65 |
{ |
66 |
- logg("*Clamonacc: onas_clamonacc_exit(), signal %d\n", sig); |
|
67 |
- if (sig == 11) { |
|
68 |
- logg("!Clamonacc: clamonacc has experienced a fatal error, if you continue to see this error, please run clamonacc with --debug and report the issue and crash report to the developpers\n"); |
|
69 |
- } |
|
70 |
- |
|
71 |
- if (g_ctx) { |
|
72 |
- if(g_ctx->fan_fd) { |
|
73 |
- close(g_ctx->fan_fd); |
|
74 |
- } |
|
75 |
- g_ctx->fan_fd = 0; |
|
76 |
- } |
|
77 |
- |
|
78 |
- logg("*Clamonacc: attempting to stop event consumer thread ...\n"); |
|
79 |
- if (scan_queue_pid > 0) { |
|
80 |
- pthread_cancel(scan_queue_pid); |
|
81 |
- pthread_join(scan_queue_pid, NULL); |
|
82 |
- } |
|
83 |
- scan_queue_pid = 0; |
|
84 |
- |
|
85 |
- logg("*Clamonacc: attempting to stop ddd thread ... \n"); |
|
86 |
- if (ddd_pid > 0) { |
|
87 |
- pthread_cancel(ddd_pid); |
|
88 |
- pthread_join(ddd_pid, NULL); |
|
89 |
- } |
|
90 |
- ddd_pid = 0; |
|
91 |
- |
|
92 |
- logg("Clamonacc: stopped\n"); |
|
93 |
- onas_cleanup(g_ctx); |
|
94 |
- pthread_exit(NULL); |
|
66 |
+ logg("*Clamonacc: onas_clamonacc_exit(), signal %d\n", sig); |
|
67 |
+ if (sig == 11) { |
|
68 |
+ logg("!Clamonacc: clamonacc has experienced a fatal error, if you continue to see this error, please run clamonacc with --debug and report the issue and crash report to the developpers\n"); |
|
69 |
+ } |
|
70 |
+ |
|
71 |
+ if (g_ctx) { |
|
72 |
+ if (g_ctx->fan_fd) { |
|
73 |
+ close(g_ctx->fan_fd); |
|
74 |
+ } |
|
75 |
+ g_ctx->fan_fd = 0; |
|
76 |
+ } |
|
77 |
+ |
|
78 |
+ logg("*Clamonacc: attempting to stop event consumer thread ...\n"); |
|
79 |
+ if (scan_queue_pid > 0) { |
|
80 |
+ pthread_cancel(scan_queue_pid); |
|
81 |
+ pthread_join(scan_queue_pid, NULL); |
|
82 |
+ } |
|
83 |
+ scan_queue_pid = 0; |
|
84 |
+ |
|
85 |
+ logg("*Clamonacc: attempting to stop ddd thread ... \n"); |
|
86 |
+ if (ddd_pid > 0) { |
|
87 |
+ pthread_cancel(ddd_pid); |
|
88 |
+ pthread_join(ddd_pid, NULL); |
|
89 |
+ } |
|
90 |
+ ddd_pid = 0; |
|
91 |
+ |
|
92 |
+ logg("Clamonacc: stopped\n"); |
|
93 |
+ onas_cleanup(g_ctx); |
|
94 |
+ pthread_exit(NULL); |
|
95 | 95 |
} |
96 | 96 |
|
97 | 97 |
int main(int argc, char **argv) |
98 | 98 |
{ |
99 |
- const struct optstruct *opts; |
|
100 |
- const struct optstruct *clamdopts; |
|
101 |
- struct onas_context *ctx; |
|
102 |
- int ret = 0; |
|
103 |
- |
|
104 |
- /* Initialize context */ |
|
105 |
- ctx = onas_init_context(); |
|
106 |
- if(ctx == NULL) { |
|
107 |
- logg("!Clamonacc: can't initialize context\n"); |
|
108 |
- return 2; |
|
109 |
- } |
|
110 |
- |
|
111 |
- /* Parse out all our command line options */ |
|
112 |
- opts = optparse(NULL, argc, argv, 1, OPT_CLAMONACC, OPT_CLAMSCAN, NULL); |
|
113 |
- if(opts == NULL) { |
|
114 |
- logg("!Clamonacc: can't parse command line options\n"); |
|
115 |
- return 2; |
|
116 |
- } |
|
117 |
- ctx->opts = opts; |
|
118 |
- |
|
119 |
- /* And our config file options */ |
|
120 |
- clamdopts = optparse(optget(opts, "config-file")->strarg, 0, NULL, 1, OPT_CLAMD, 0, NULL); |
|
121 |
- if (clamdopts == NULL) { |
|
122 |
- logg("!Clamonacc: can't parse clamd configuration file %s\n", optget(opts, "config-file")->strarg); |
|
123 |
- return 2; |
|
124 |
- } |
|
125 |
- ctx->clamdopts = clamdopts; |
|
126 |
- |
|
127 |
- /* Make sure we're good to begin spinup */ |
|
128 |
- ret = startup_checks(ctx); |
|
129 |
- if (ret) { |
|
130 |
- goto clean_up; |
|
131 |
- } |
|
99 |
+ const struct optstruct *opts; |
|
100 |
+ const struct optstruct *clamdopts; |
|
101 |
+ struct onas_context *ctx; |
|
102 |
+ int ret = 0; |
|
103 |
+ |
|
104 |
+ /* Initialize context */ |
|
105 |
+ ctx = onas_init_context(); |
|
106 |
+ if (ctx == NULL) { |
|
107 |
+ logg("!Clamonacc: can't initialize context\n"); |
|
108 |
+ return 2; |
|
109 |
+ } |
|
110 |
+ |
|
111 |
+ /* Parse out all our command line options */ |
|
112 |
+ opts = optparse(NULL, argc, argv, 1, OPT_CLAMONACC, OPT_CLAMSCAN, NULL); |
|
113 |
+ if (opts == NULL) { |
|
114 |
+ logg("!Clamonacc: can't parse command line options\n"); |
|
115 |
+ return 2; |
|
116 |
+ } |
|
117 |
+ ctx->opts = opts; |
|
118 |
+ |
|
119 |
+ /* And our config file options */ |
|
120 |
+ clamdopts = optparse(optget(opts, "config-file")->strarg, 0, NULL, 1, OPT_CLAMD, 0, NULL); |
|
121 |
+ if (clamdopts == NULL) { |
|
122 |
+ logg("!Clamonacc: can't parse clamd configuration file %s\n", optget(opts, "config-file")->strarg); |
|
123 |
+ return 2; |
|
124 |
+ } |
|
125 |
+ ctx->clamdopts = clamdopts; |
|
126 |
+ |
|
127 |
+ /* Make sure we're good to begin spinup */ |
|
128 |
+ ret = startup_checks(ctx); |
|
129 |
+ if (ret) { |
|
130 |
+ goto clean_up; |
|
131 |
+ } |
|
132 | 132 |
|
133 | 133 |
#ifndef _WIN32 |
134 |
- /* Daemonize if sanity checks are good to go */ |
|
135 |
- if (!optget(ctx->opts, "foreground")->enabled) { |
|
136 |
- if (-1 == daemonize()) { |
|
137 |
- logg("!Clamonacc: could not daemonize\n"); |
|
138 |
- return 2; |
|
139 |
- } |
|
134 |
+ /* Daemonize if sanity checks are good to go */ |
|
135 |
+ if (!optget(ctx->opts, "foreground")->enabled) { |
|
136 |
+ if (-1 == daemonize()) { |
|
137 |
+ logg("!Clamonacc: could not daemonize\n"); |
|
138 |
+ return 2; |
|
140 | 139 |
} |
140 |
+ } |
|
141 | 141 |
#endif |
142 | 142 |
|
143 |
- /* Setup our client */ |
|
144 |
- switch(onas_setup_client(&ctx)) { |
|
145 |
- case CL_SUCCESS: |
|
146 |
- if (CL_SUCCESS == onas_check_client_connection(&ctx)) { |
|
147 |
- break; |
|
148 |
- } |
|
149 |
- case CL_BREAK: |
|
150 |
- ret = 0; |
|
151 |
- logg("*Clamonacc: not setting up client\n"); |
|
152 |
- goto clean_up; |
|
153 |
- break; |
|
154 |
- case CL_EARG: |
|
155 |
- default: |
|
156 |
- logg("!Clamonacc: can't setup client\n"); |
|
157 |
- ret = 2; |
|
158 |
- goto clean_up; |
|
159 |
- break; |
|
160 |
- } |
|
161 |
- |
|
162 |
- |
|
163 |
- /* Setup our event queue */ |
|
164 |
- ctx->maxthreads = optget(ctx->clamdopts, "OnAccessMaxThreads")->numarg; |
|
165 |
- |
|
166 |
- switch(onas_scan_queue_start(&ctx)) { |
|
143 |
+ /* Setup our client */ |
|
144 |
+ switch (onas_setup_client(&ctx)) { |
|
145 |
+ case CL_SUCCESS: |
|
146 |
+ if (CL_SUCCESS == onas_check_client_connection(&ctx)) { |
|
147 |
+ break; |
|
148 |
+ } |
|
149 |
+ case CL_BREAK: |
|
150 |
+ ret = 0; |
|
151 |
+ logg("*Clamonacc: not setting up client\n"); |
|
152 |
+ goto clean_up; |
|
153 |
+ break; |
|
154 |
+ case CL_EARG: |
|
155 |
+ default: |
|
156 |
+ logg("!Clamonacc: can't setup client\n"); |
|
157 |
+ ret = 2; |
|
158 |
+ goto clean_up; |
|
159 |
+ break; |
|
160 |
+ } |
|
161 |
+ |
|
162 |
+ /* Setup our event queue */ |
|
163 |
+ ctx->maxthreads = optget(ctx->clamdopts, "OnAccessMaxThreads")->numarg; |
|
164 |
+ |
|
165 |
+ switch (onas_scan_queue_start(&ctx)) { |
|
166 |
+ case CL_SUCCESS: |
|
167 |
+ break; |
|
168 |
+ case CL_BREAK: |
|
169 |
+ case CL_EARG: |
|
170 |
+ case CL_ECREAT: |
|
171 |
+ default: |
|
172 |
+ ret = 2; |
|
173 |
+ logg("!Clamonacc: can't setup event consumer queue\n"); |
|
174 |
+ goto clean_up; |
|
175 |
+ break; |
|
176 |
+ } |
|
177 |
+ |
|
178 |
+#if defined(FANOTIFY) |
|
179 |
+ /* Setup fanotify */ |
|
180 |
+ switch (onas_setup_fanotif(&ctx)) { |
|
181 |
+ case CL_SUCCESS: |
|
182 |
+ break; |
|
183 |
+ case CL_BREAK: |
|
184 |
+ ret = 0; |
|
185 |
+ goto clean_up; |
|
186 |
+ break; |
|
187 |
+ case CL_EARG: |
|
188 |
+ default: |
|
189 |
+ mprintf("!Clamonacc: can't setup fanotify\n"); |
|
190 |
+ ret = 2; |
|
191 |
+ goto clean_up; |
|
192 |
+ break; |
|
193 |
+ } |
|
194 |
+ |
|
195 |
+ if (ctx->ddd_enabled) { |
|
196 |
+ /* Setup inotify and kickoff DDD system */ |
|
197 |
+ switch (onas_enable_inotif_ddd(&ctx)) { |
|
167 | 198 |
case CL_SUCCESS: |
168 | 199 |
break; |
169 | 200 |
case CL_BREAK: |
201 |
+ ret = 0; |
|
202 |
+ goto clean_up; |
|
203 |
+ break; |
|
170 | 204 |
case CL_EARG: |
171 |
- case CL_ECREAT: |
|
172 | 205 |
default: |
206 |
+ mprintf("!Clamonacc: can't setup fanotify\n"); |
|
173 | 207 |
ret = 2; |
174 |
- logg("!Clamonacc: can't setup event consumer queue\n"); |
|
175 | 208 |
goto clean_up; |
176 | 209 |
break; |
177 | 210 |
} |
178 |
- |
|
179 |
-#if defined(FANOTIFY) |
|
180 |
- /* Setup fanotify */ |
|
181 |
- switch(onas_setup_fanotif(&ctx)) { |
|
182 |
- case CL_SUCCESS: |
|
183 |
- break; |
|
184 |
- case CL_BREAK: |
|
185 |
- ret = 0; |
|
186 |
- goto clean_up; |
|
187 |
- break; |
|
188 |
- case CL_EARG: |
|
189 |
- default: |
|
190 |
- mprintf("!Clamonacc: can't setup fanotify\n"); |
|
191 |
- ret = 2; |
|
192 |
- goto clean_up; |
|
193 |
- break; |
|
194 |
- } |
|
195 |
- |
|
196 |
- if (ctx->ddd_enabled) { |
|
197 |
- /* Setup inotify and kickoff DDD system */ |
|
198 |
- switch(onas_enable_inotif_ddd(&ctx)) { |
|
199 |
- case CL_SUCCESS: |
|
200 |
- break; |
|
201 |
- case CL_BREAK: |
|
202 |
- ret = 0; |
|
203 |
- goto clean_up; |
|
204 |
- break; |
|
205 |
- case CL_EARG: |
|
206 |
- default: |
|
207 |
- mprintf("!Clamonacc: can't setup fanotify\n"); |
|
208 |
- ret = 2; |
|
209 |
- goto clean_up; |
|
210 |
- break; |
|
211 |
- } |
|
212 |
- } |
|
211 |
+ } |
|
213 | 212 |
#else |
214 |
- mprintf("!Clamonacc: currently, this application only runs on linux systems with fanotify enabled\n"); |
|
215 |
- goto clean_up; |
|
213 |
+ mprintf("!Clamonacc: currently, this application only runs on linux systems with fanotify enabled\n"); |
|
214 |
+ goto clean_up; |
|
216 | 215 |
#endif |
217 | 216 |
|
218 |
- /* Setup signal handling */ |
|
219 |
- g_ctx = ctx; |
|
220 |
- onas_handle_signals(); |
|
217 |
+ /* Setup signal handling */ |
|
218 |
+ g_ctx = ctx; |
|
219 |
+ onas_handle_signals(); |
|
221 | 220 |
|
222 |
- logg("*Clamonacc: beginning event loops\n"); |
|
223 |
- /* Kick off event loop(s) */ |
|
224 |
- ret = onas_start_eloop(&ctx); |
|
221 |
+ logg("*Clamonacc: beginning event loops\n"); |
|
222 |
+ /* Kick off event loop(s) */ |
|
223 |
+ ret = onas_start_eloop(&ctx); |
|
225 | 224 |
|
226 |
- /* Clean up */ |
|
225 |
+ /* Clean up */ |
|
227 | 226 |
clean_up: |
228 |
- onas_cleanup(ctx); |
|
229 |
- exit(ret); |
|
227 |
+ onas_cleanup(ctx); |
|
228 |
+ exit(ret); |
|
230 | 229 |
} |
231 | 230 |
|
232 |
-static void onas_handle_signals() { |
|
233 |
- sigset_t sigset; |
|
234 |
- struct sigaction act; |
|
235 |
- |
|
236 |
- /* ignore all signals except SIGUSR1 */ |
|
237 |
- sigfillset(&sigset); |
|
238 |
- sigdelset(&sigset, SIGUSR1); |
|
239 |
- sigdelset(&sigset, SIGUSR2); |
|
240 |
- /* The behavior of a process is undefined after it ignores a |
|
231 |
+static void onas_handle_signals() |
|
232 |
+{ |
|
233 |
+ sigset_t sigset; |
|
234 |
+ struct sigaction act; |
|
235 |
+ |
|
236 |
+ /* ignore all signals except SIGUSR1 */ |
|
237 |
+ sigfillset(&sigset); |
|
238 |
+ sigdelset(&sigset, SIGUSR1); |
|
239 |
+ sigdelset(&sigset, SIGUSR2); |
|
240 |
+ /* The behavior of a process is undefined after it ignores a |
|
241 | 241 |
* SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ |
242 |
- sigdelset(&sigset, SIGFPE); |
|
243 |
- sigdelset(&sigset, SIGILL); |
|
244 |
- sigdelset(&sigset, SIGSEGV); |
|
245 |
- sigdelset(&sigset, SIGINT); |
|
246 |
- sigdelset(&sigset, SIGTERM); |
|
242 |
+ sigdelset(&sigset, SIGFPE); |
|
243 |
+ sigdelset(&sigset, SIGILL); |
|
244 |
+ sigdelset(&sigset, SIGSEGV); |
|
245 |
+ sigdelset(&sigset, SIGINT); |
|
246 |
+ sigdelset(&sigset, SIGTERM); |
|
247 | 247 |
#ifdef SIGBUS |
248 |
- sigdelset(&sigset, SIGBUS); |
|
248 |
+ sigdelset(&sigset, SIGBUS); |
|
249 | 249 |
#endif |
250 |
- pthread_sigmask(SIG_SETMASK, &sigset, NULL); |
|
251 |
- memset(&act, 0, sizeof(struct sigaction)); |
|
252 |
- act.sa_handler = onas_clamonacc_exit; |
|
253 |
- sigfillset(&(act.sa_mask)); |
|
254 |
- sigaction(SIGUSR2, &act, NULL); |
|
255 |
- sigaction(SIGTERM, &act, NULL); |
|
256 |
- sigaction(SIGSEGV, &act, NULL); |
|
257 |
- sigaction(SIGINT, &act, NULL); |
|
250 |
+ pthread_sigmask(SIG_SETMASK, &sigset, NULL); |
|
251 |
+ memset(&act, 0, sizeof(struct sigaction)); |
|
252 |
+ act.sa_handler = onas_clamonacc_exit; |
|
253 |
+ sigfillset(&(act.sa_mask)); |
|
254 |
+ sigaction(SIGUSR2, &act, NULL); |
|
255 |
+ sigaction(SIGTERM, &act, NULL); |
|
256 |
+ sigaction(SIGSEGV, &act, NULL); |
|
257 |
+ sigaction(SIGINT, &act, NULL); |
|
258 | 258 |
} |
259 | 259 |
|
260 |
-struct onas_context *onas_init_context(void) { |
|
261 |
- struct onas_context *ctx = (struct onas_context*) cli_malloc(sizeof(struct onas_context)); |
|
260 |
+struct onas_context *onas_init_context(void) |
|
261 |
+{ |
|
262 |
+ struct onas_context *ctx = (struct onas_context *)cli_malloc(sizeof(struct onas_context)); |
|
262 | 263 |
if (NULL == ctx) { |
263 | 264 |
return NULL; |
264 | 265 |
} |
... | ... |
@@ -267,88 +267,91 @@ struct onas_context *onas_init_context(void) { |
267 | 267 |
return ctx; |
268 | 268 |
} |
269 | 269 |
|
270 |
-cl_error_t onas_check_client_connection(struct onas_context **ctx) { |
|
270 |
+cl_error_t onas_check_client_connection(struct onas_context **ctx) |
|
271 |
+{ |
|
271 | 272 |
|
272 |
- cl_error_t err = CL_SUCCESS; |
|
273 |
+ cl_error_t err = CL_SUCCESS; |
|
273 | 274 |
|
274 |
- /* 0 local, non-zero remote, errno set on error */ |
|
275 |
- (*ctx)->isremote = onas_check_remote(ctx, &err); |
|
276 |
- if (CL_SUCCESS == err ) { |
|
277 |
- logg("*Clamonacc: "); |
|
278 |
- (*ctx)->isremote ? logg("*daemon is remote\n") : logg("*daemon is local\n"); |
|
279 |
- } |
|
280 |
- return err ? CL_EACCES : CL_SUCCESS; |
|
275 |
+ /* 0 local, non-zero remote, errno set on error */ |
|
276 |
+ (*ctx)->isremote = onas_check_remote(ctx, &err); |
|
277 |
+ if (CL_SUCCESS == err) { |
|
278 |
+ logg("*Clamonacc: "); |
|
279 |
+ (*ctx)->isremote ? logg("*daemon is remote\n") : logg("*daemon is local\n"); |
|
280 |
+ } |
|
281 |
+ return err ? CL_EACCES : CL_SUCCESS; |
|
281 | 282 |
} |
282 | 283 |
|
283 |
-int onas_start_eloop(struct onas_context **ctx) { |
|
284 |
- int ret = 0; |
|
284 |
+int onas_start_eloop(struct onas_context **ctx) |
|
285 |
+{ |
|
286 |
+ int ret = 0; |
|
285 | 287 |
|
286 |
- if (!ctx || !*ctx) { |
|
287 |
- mprintf("!Clamonacc: unable to start clamonacc. (bad context)\n"); |
|
288 |
- return CL_EARG; |
|
289 |
- } |
|
288 |
+ if (!ctx || !*ctx) { |
|
289 |
+ mprintf("!Clamonacc: unable to start clamonacc. (bad context)\n"); |
|
290 |
+ return CL_EARG; |
|
291 |
+ } |
|
290 | 292 |
|
291 | 293 |
#if defined(FANOTIFY) |
292 |
- ret = onas_fan_eloop(ctx); |
|
294 |
+ ret = onas_fan_eloop(ctx); |
|
293 | 295 |
#endif |
294 | 296 |
|
295 |
- return ret; |
|
297 |
+ return ret; |
|
296 | 298 |
} |
297 | 299 |
|
298 |
-static int startup_checks(struct onas_context *ctx) { |
|
300 |
+static int startup_checks(struct onas_context *ctx) |
|
301 |
+{ |
|
299 | 302 |
|
300 | 303 |
#if defined(FANOTIFY) |
301 |
- char faerr[128]; |
|
304 |
+ char faerr[128]; |
|
302 | 305 |
#endif |
303 |
- int ret = 0; |
|
304 |
- cl_error_t err = CL_SUCCESS; |
|
306 |
+ int ret = 0; |
|
307 |
+ cl_error_t err = CL_SUCCESS; |
|
305 | 308 |
|
306 |
- if(optget(ctx->opts, "help")->enabled) { |
|
307 |
- help(); |
|
308 |
- ret = 2; |
|
309 |
- goto done; |
|
310 |
- } |
|
309 |
+ if (optget(ctx->opts, "help")->enabled) { |
|
310 |
+ help(); |
|
311 |
+ ret = 2; |
|
312 |
+ goto done; |
|
313 |
+ } |
|
311 | 314 |
|
312 |
- if(optget(ctx->opts, "version")->enabled) { |
|
313 |
- onas_print_server_version(&ctx); |
|
314 |
- ret = 2; |
|
315 |
- goto done; |
|
316 |
- } |
|
315 |
+ if (optget(ctx->opts, "version")->enabled) { |
|
316 |
+ onas_print_server_version(&ctx); |
|
317 |
+ ret = 2; |
|
318 |
+ goto done; |
|
319 |
+ } |
|
317 | 320 |
|
318 | 321 |
#if defined(FANOTIFY) |
319 |
- ctx->fan_fd = fanotify_init(FAN_CLASS_CONTENT | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS, O_LARGEFILE | O_RDONLY); |
|
320 |
- if (ctx->fan_fd < 0) { |
|
321 |
- logg("!Clamonacc: fanotify_init failed: %s\n", cli_strerror(errno, faerr, sizeof(faerr))); |
|
322 |
- if (errno == EPERM) { |
|
323 |
- logg("!Clamonacc: clamonacc must have elevated permissions ... exiting ...\n"); |
|
324 |
- } |
|
325 |
- ret = 2; |
|
326 |
- goto done; |
|
327 |
- } |
|
322 |
+ ctx->fan_fd = fanotify_init(FAN_CLASS_CONTENT | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS, O_LARGEFILE | O_RDONLY); |
|
323 |
+ if (ctx->fan_fd < 0) { |
|
324 |
+ logg("!Clamonacc: fanotify_init failed: %s\n", cli_strerror(errno, faerr, sizeof(faerr))); |
|
325 |
+ if (errno == EPERM) { |
|
326 |
+ logg("!Clamonacc: clamonacc must have elevated permissions ... exiting ...\n"); |
|
327 |
+ } |
|
328 |
+ ret = 2; |
|
329 |
+ goto done; |
|
330 |
+ } |
|
328 | 331 |
#endif |
329 | 332 |
|
330 |
- if (curl_global_init(CURL_GLOBAL_NOTHING)) { |
|
331 |
- ret = 2; |
|
332 |
- goto done; |
|
333 |
- } |
|
334 |
- |
|
335 |
- if (0 == onas_check_remote(&ctx, &err)) { |
|
336 |
- |
|
337 |
- if (CL_SUCCESS != err) { |
|
338 |
- logg("!Clamonacc: daemon is local, but a connection could not be established\n"); |
|
339 |
- ret = 2; |
|
340 |
- goto done; |
|
341 |
- } |
|
342 |
- |
|
343 |
- if(!optget(ctx->clamdopts, "OnAccessExcludeUID")->enabled && |
|
344 |
- !optget(ctx->clamdopts, "OnAccessExcludeUname")->enabled && !optget(ctx->clamdopts, "OnAccessExcludeRootUID")->enabled) { |
|
345 |
- logg("!Clamonacc: at least one of OnAccessExcludeUID, OnAccessExcludeUname, or OnAccessExcludeRootUID must be specified ... it is reccomended you exclude the clamd instance UID or uname to prevent infinite event scanning loops\n"); |
|
346 |
- ret = 2; |
|
347 |
- goto done; |
|
348 |
- } |
|
349 |
- } |
|
333 |
+ if (curl_global_init(CURL_GLOBAL_NOTHING)) { |
|
334 |
+ ret = 2; |
|
335 |
+ goto done; |
|
336 |
+ } |
|
337 |
+ |
|
338 |
+ if (0 == onas_check_remote(&ctx, &err)) { |
|
339 |
+ |
|
340 |
+ if (CL_SUCCESS != err) { |
|
341 |
+ logg("!Clamonacc: daemon is local, but a connection could not be established\n"); |
|
342 |
+ ret = 2; |
|
343 |
+ goto done; |
|
344 |
+ } |
|
345 |
+ |
|
346 |
+ if (!optget(ctx->clamdopts, "OnAccessExcludeUID")->enabled && |
|
347 |
+ !optget(ctx->clamdopts, "OnAccessExcludeUname")->enabled && !optget(ctx->clamdopts, "OnAccessExcludeRootUID")->enabled) { |
|
348 |
+ logg("!Clamonacc: at least one of OnAccessExcludeUID, OnAccessExcludeUname, or OnAccessExcludeRootUID must be specified ... it is reccomended you exclude the clamd instance UID or uname to prevent infinite event scanning loops\n"); |
|
349 |
+ ret = 2; |
|
350 |
+ goto done; |
|
351 |
+ } |
|
352 |
+ } |
|
350 | 353 |
done: |
351 |
- return ret; |
|
354 |
+ return ret; |
|
352 | 355 |
} |
353 | 356 |
|
354 | 357 |
void help(void) |
... | ... |
@@ -381,17 +384,18 @@ void help(void) |
381 | 381 |
exit(0); |
382 | 382 |
} |
383 | 383 |
|
384 |
-void* onas_cleanup(struct onas_context *ctx) { |
|
385 |
- onas_context_cleanup(ctx); |
|
386 |
- logg_close(); |
|
384 |
+void *onas_cleanup(struct onas_context *ctx) |
|
385 |
+{ |
|
386 |
+ onas_context_cleanup(ctx); |
|
387 |
+ logg_close(); |
|
387 | 388 |
} |
388 | 389 |
|
389 |
-void* onas_context_cleanup(struct onas_context *ctx) { |
|
390 |
- close(ctx->fan_fd); |
|
391 |
- optfree((struct optstruct *) ctx->opts); |
|
392 |
- optfree((struct optstruct *) ctx->clamdopts); |
|
393 |
- ctx->opts = NULL; |
|
394 |
- ctx->clamdopts = NULL; |
|
395 |
- free(ctx); |
|
390 |
+void *onas_context_cleanup(struct onas_context *ctx) |
|
391 |
+{ |
|
392 |
+ close(ctx->fan_fd); |
|
393 |
+ optfree((struct optstruct *)ctx->opts); |
|
394 |
+ optfree((struct optstruct *)ctx->clamdopts); |
|
395 |
+ ctx->opts = NULL; |
|
396 |
+ ctx->clamdopts = NULL; |
|
397 |
+ free(ctx); |
|
396 | 398 |
} |
397 |
- |
... | ... |
@@ -41,31 +41,31 @@ |
41 | 41 |
#endif |
42 | 42 |
|
43 | 43 |
struct onas_context { |
44 |
- const struct optstruct *opts; |
|
45 |
- const struct optstruct *clamdopts; |
|
44 |
+ const struct optstruct *opts; |
|
45 |
+ const struct optstruct *clamdopts; |
|
46 | 46 |
|
47 |
- int printinfected; |
|
48 |
- int maxstream; |
|
47 |
+ int printinfected; |
|
48 |
+ int maxstream; |
|
49 | 49 |
|
50 |
- uint32_t ddd_enabled; |
|
50 |
+ uint32_t ddd_enabled; |
|
51 | 51 |
|
52 |
- int fan_fd; |
|
53 |
- uint64_t fan_mask; |
|
54 |
- uint8_t retry_on_error; |
|
55 |
- uint8_t retry_attempts; |
|
56 |
- uint8_t deny_on_error; |
|
52 |
+ int fan_fd; |
|
53 |
+ uint64_t fan_mask; |
|
54 |
+ uint8_t retry_on_error; |
|
55 |
+ uint8_t retry_attempts; |
|
56 |
+ uint8_t deny_on_error; |
|
57 | 57 |
|
58 |
- uint64_t sizelimit; |
|
59 |
- uint64_t extinfo; |
|
58 |
+ uint64_t sizelimit; |
|
59 |
+ uint64_t extinfo; |
|
60 | 60 |
|
61 |
- int scantype; |
|
62 |
- int isremote; |
|
63 |
- int session; |
|
64 |
- int timeout; |
|
61 |
+ int scantype; |
|
62 |
+ int isremote; |
|
63 |
+ int session; |
|
64 |
+ int timeout; |
|
65 | 65 |
|
66 |
- int64_t portnum; |
|
66 |
+ int64_t portnum; |
|
67 | 67 |
|
68 |
- int32_t maxthreads; |
|
68 |
+ int32_t maxthreads; |
|
69 | 69 |
} __attribute__((packed)); |
70 | 70 |
|
71 | 71 |
#ifdef HAVE_PRAGMA_PACK |
... | ... |
@@ -75,13 +75,11 @@ struct onas_context { |
75 | 75 |
#pragma pack |
76 | 76 |
#endif |
77 | 77 |
|
78 |
-struct onas_context* onas_init_context(void); |
|
79 |
-void* onas_cleanup(struct onas_context *ctx); |
|
80 |
-void* onas_context_cleanup(struct onas_context *ctx); |
|
78 |
+struct onas_context *onas_init_context(void); |
|
79 |
+void *onas_cleanup(struct onas_context *ctx); |
|
80 |
+void *onas_context_cleanup(struct onas_context *ctx); |
|
81 | 81 |
cl_error_t onas_check_client_connection(struct onas_context **ctx); |
82 | 82 |
int onas_start_eloop(struct onas_context **ctx); |
83 | 83 |
void help(void); |
84 | 84 |
|
85 |
- |
|
86 |
- |
|
87 | 85 |
#endif |
... | ... |
@@ -26,7 +26,7 @@ |
26 | 26 |
#include <stdio.h> |
27 | 27 |
#include <stdlib.h> |
28 | 28 |
#include <curl/curl.h> |
29 |
-#ifdef HAVE_UNISTD_H |
|
29 |
+#ifdef HAVE_UNISTD_H |
|
30 | 30 |
#include <unistd.h> |
31 | 31 |
#endif |
32 | 32 |
#include <string.h> |
... | ... |
@@ -71,89 +71,87 @@ struct sockaddr_un nixsock; |
71 | 71 |
|
72 | 72 |
void onas_print_server_version(struct onas_context **ctx) |
73 | 73 |
{ |
74 |
- if(onas_get_clamd_version(ctx)) { |
|
75 |
- /* can't get version from server, fallback */ |
|
76 |
- printf("ClamAV %s\n", get_version()); |
|
77 |
- |
|
78 |
- } |
|
74 |
+ if (onas_get_clamd_version(ctx)) { |
|
75 |
+ /* can't get version from server, fallback */ |
|
76 |
+ printf("ClamAV %s\n", get_version()); |
|
77 |
+ } |
|
79 | 78 |
} |
80 | 79 |
|
81 |
- |
|
82 | 80 |
/* Inits the communication layer |
83 | 81 |
* Returns 0 if clamd is local, non zero if clamd is remote */ |
84 |
-int onas_check_remote(struct onas_context **ctx, cl_error_t *err) { |
|
85 |
- int s, ret; |
|
86 |
- const struct optstruct *opt; |
|
87 |
- CURL *curl; |
|
88 |
- CURLcode curlcode; |
|
89 |
- char *ipaddr = NULL; |
|
90 |
- struct addrinfo hints, *info, *p; |
|
91 |
- int res; |
|
82 |
+int onas_check_remote(struct onas_context **ctx, cl_error_t *err) |
|
83 |
+{ |
|
84 |
+ int s, ret; |
|
85 |
+ const struct optstruct *opt; |
|
86 |
+ CURL *curl; |
|
87 |
+ CURLcode curlcode; |
|
88 |
+ char *ipaddr = NULL; |
|
89 |
+ struct addrinfo hints, *info, *p; |
|
90 |
+ int res; |
|
92 | 91 |
int64_t timeout; |
93 | 92 |
|
94 | 93 |
timeout = optget((*ctx)->clamdopts, "OnAccessCurlTimeout")->numarg; |
95 | 94 |
|
96 |
- |
|
97 |
- *err = CL_SUCCESS; |
|
95 |
+ *err = CL_SUCCESS; |
|
98 | 96 |
|
99 | 97 |
#ifndef _WIN32 |
100 |
- if((opt = optget((*ctx)->clamdopts, "LocalSocket"))->enabled) { |
|
101 |
- opt = optget((*ctx)->clamdopts, "LocalSocket"); |
|
102 |
- (*ctx)->portnum = 0; |
|
103 |
- ret = 0; |
|
104 |
- } else { |
|
105 |
- opt = optget((*ctx)->clamdopts, "TCPAddr"); |
|
106 |
- (*ctx)->portnum = optget((*ctx)->clamdopts, "TCPSocket")->numarg; |
|
107 |
- ret = 1; |
|
108 |
- } |
|
98 |
+ if ((opt = optget((*ctx)->clamdopts, "LocalSocket"))->enabled) { |
|
99 |
+ opt = optget((*ctx)->clamdopts, "LocalSocket"); |
|
100 |
+ (*ctx)->portnum = 0; |
|
101 |
+ ret = 0; |
|
102 |
+ } else { |
|
103 |
+ opt = optget((*ctx)->clamdopts, "TCPAddr"); |
|
104 |
+ (*ctx)->portnum = optget((*ctx)->clamdopts, "TCPSocket")->numarg; |
|
105 |
+ ret = 1; |
|
106 |
+ } |
|
109 | 107 |
#else |
110 |
- if(!(opt = optget((*ctx)->clamdopts, "TCPSocket"))->enabled) { |
|
111 |
- return 0; |
|
112 |
- } |
|
108 |
+ if (!(opt = optget((*ctx)->clamdopts, "TCPSocket"))->enabled) { |
|
109 |
+ return 0; |
|
110 |
+ } |
|
113 | 111 |
#endif |
114 | 112 |
|
115 |
- while (opt) { |
|
113 |
+ while (opt) { |
|
116 | 114 |
|
117 |
- if (opt->strarg) { |
|
118 |
- ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg); |
|
119 |
- } |
|
115 |
+ if (opt->strarg) { |
|
116 |
+ ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg); |
|
117 |
+ } |
|
120 | 118 |
|
121 |
- if (NULL == ipaddr) { |
|
122 |
- logg("!ClamClient: Clamonacc does not support binding to INADDR_ANY, \ |
|
119 |
+ if (NULL == ipaddr) { |
|
120 |
+ logg("!ClamClient: Clamonacc does not support binding to INADDR_ANY, \ |
|
123 | 121 |
please specify an address with TCPAddr in your clamd.conf config file\n"); |
124 |
- *err = CL_EARG; |
|
125 |
- return ret; |
|
126 |
- } |
|
127 |
- |
|
128 |
- curlcode = onas_curl_init(&curl, ipaddr, (*ctx)->portnum, timeout); |
|
129 |
- if (CURLE_OK != curlcode) { |
|
130 |
- logg("!ClamClient: could not init curl, %s\n", curl_easy_strerror(curlcode)); |
|
131 |
- *err = CL_EARG; |
|
132 |
- return ret; |
|
133 |
- } |
|
134 |
- |
|
135 |
- curlcode = curl_easy_perform(curl); |
|
136 |
- if (CURLE_OK != curlcode) { |
|
137 |
- logg("!ClamClient: could not connect to remote clam daemon, %s\n", curl_easy_strerror(curlcode)); |
|
138 |
- *err = CL_EARG; |
|
139 |
- return ret; |
|
140 |
- } |
|
122 |
+ *err = CL_EARG; |
|
123 |
+ return ret; |
|
124 |
+ } |
|
125 |
+ |
|
126 |
+ curlcode = onas_curl_init(&curl, ipaddr, (*ctx)->portnum, timeout); |
|
127 |
+ if (CURLE_OK != curlcode) { |
|
128 |
+ logg("!ClamClient: could not init curl, %s\n", curl_easy_strerror(curlcode)); |
|
129 |
+ *err = CL_EARG; |
|
130 |
+ return ret; |
|
131 |
+ } |
|
132 |
+ |
|
133 |
+ curlcode = curl_easy_perform(curl); |
|
134 |
+ if (CURLE_OK != curlcode) { |
|
135 |
+ logg("!ClamClient: could not connect to remote clam daemon, %s\n", curl_easy_strerror(curlcode)); |
|
136 |
+ *err = CL_EARG; |
|
137 |
+ return ret; |
|
138 |
+ } |
|
141 | 139 |
|
142 | 140 |
#ifndef ONAS_DEBUG |
143 |
- if(onas_sendln(curl, "zPING", 5, timeout)) { |
|
144 |
- logg("!ClamClient: could not ping clamd, %s\n", curl_easy_strerror(curlcode)); |
|
145 |
- *err = CL_EARG; |
|
146 |
- curl_easy_cleanup(curl); |
|
147 |
- return ret; |
|
148 |
- } |
|
141 |
+ if (onas_sendln(curl, "zPING", 5, timeout)) { |
|
142 |
+ logg("!ClamClient: could not ping clamd, %s\n", curl_easy_strerror(curlcode)); |
|
143 |
+ *err = CL_EARG; |
|
144 |
+ curl_easy_cleanup(curl); |
|
145 |
+ return ret; |
|
146 |
+ } |
|
149 | 147 |
#endif |
150 | 148 |
|
151 |
- curl_easy_cleanup(curl); |
|
149 |
+ curl_easy_cleanup(curl); |
|
152 | 150 |
|
153 |
- opt = opt->nextarg; |
|
154 |
- } |
|
151 |
+ opt = opt->nextarg; |
|
152 |
+ } |
|
155 | 153 |
|
156 |
- return ret; |
|
154 |
+ return ret; |
|
157 | 155 |
} |
158 | 156 |
|
159 | 157 |
/** |
... | ... |
@@ -164,104 +162,104 @@ int onas_check_remote(struct onas_context **ctx, cl_error_t *err) { |
164 | 164 |
* @param port the port to use in case of TCP connection, set to 0 if connecting to a local socket |
165 | 165 |
* @param timeout time in ms to allow curl before timing out connection attempts |
166 | 166 |
*/ |
167 |
-CURLcode onas_curl_init(CURL **curl, const char *ipaddr, int64_t port, int64_t timeout) { |
|
168 |
- |
|
169 |
- CURLcode curlcode = CURLE_OK; |
|
170 |
- |
|
171 |
- if (!curl || !ipaddr) { |
|
172 |
- logg("!ClamClient: invalid (NULL) args passed to onas_curl_init\n"); |
|
173 |
- return CURLE_FAILED_INIT; |
|
174 |
- } |
|
175 |
- |
|
176 |
- /* setup here, but caller needs to cleanup */ |
|
177 |
- *curl = curl_easy_init(); |
|
178 |
- |
|
179 |
- if (!port) { |
|
180 |
- |
|
181 |
- /* "ipaddr" is actually our unix socket path here */ |
|
182 |
- curlcode = curl_easy_setopt(*curl, CURLOPT_UNIX_SOCKET_PATH, ipaddr); |
|
183 |
- if (CURLE_OK != curlcode) { |
|
184 |
- logg("!ClamClient: could not setup curl with local unix socket, %s\n", curl_easy_strerror(curlcode)); |
|
185 |
- curl_easy_cleanup(*curl); |
|
186 |
- return curlcode; |
|
187 |
- } |
|
188 |
- |
|
189 |
- curlcode = curl_easy_setopt(*curl, CURLOPT_URL, "http://localhost/"); |
|
190 |
- if (CURLE_OK != curlcode) { |
|
191 |
- logg("!ClamClient: could not setup curl with local address, %s\n", curl_easy_strerror(curlcode)); |
|
192 |
- curl_easy_cleanup(*curl); |
|
193 |
- return curlcode; |
|
194 |
- } |
|
195 |
- |
|
196 |
- } else { |
|
197 |
- |
|
198 |
- curlcode = curl_easy_setopt(*curl, CURLOPT_PORT, port); |
|
199 |
- if (CURLE_OK != curlcode) { |
|
200 |
- logg("!ClamClient: could not setup curl with tcp port, %s\n", curl_easy_strerror(curlcode)); |
|
201 |
- curl_easy_cleanup(*curl); |
|
202 |
- return curlcode; |
|
203 |
- } |
|
204 |
- |
|
205 |
- curlcode = curl_easy_setopt(*curl, CURLOPT_URL, ipaddr); |
|
206 |
- if (CURLE_OK != curlcode) { |
|
207 |
- logg("!ClamClient: could not setup curl with tcp address, %s\n", curl_easy_strerror(curlcode)); |
|
208 |
- curl_easy_cleanup(*curl); |
|
209 |
- return curlcode; |
|
210 |
- } |
|
167 |
+CURLcode onas_curl_init(CURL **curl, const char *ipaddr, int64_t port, int64_t timeout) |
|
168 |
+{ |
|
169 |
+ |
|
170 |
+ CURLcode curlcode = CURLE_OK; |
|
171 |
+ |
|
172 |
+ if (!curl || !ipaddr) { |
|
173 |
+ logg("!ClamClient: invalid (NULL) args passed to onas_curl_init\n"); |
|
174 |
+ return CURLE_FAILED_INIT; |
|
175 |
+ } |
|
176 |
+ |
|
177 |
+ /* setup here, but caller needs to cleanup */ |
|
178 |
+ *curl = curl_easy_init(); |
|
179 |
+ |
|
180 |
+ if (!port) { |
|
181 |
+ |
|
182 |
+ /* "ipaddr" is actually our unix socket path here */ |
|
183 |
+ curlcode = curl_easy_setopt(*curl, CURLOPT_UNIX_SOCKET_PATH, ipaddr); |
|
184 |
+ if (CURLE_OK != curlcode) { |
|
185 |
+ logg("!ClamClient: could not setup curl with local unix socket, %s\n", curl_easy_strerror(curlcode)); |
|
186 |
+ curl_easy_cleanup(*curl); |
|
187 |
+ return curlcode; |
|
211 | 188 |
} |
212 | 189 |
|
213 |
- curlcode = curl_easy_setopt(*curl, CURLOPT_NOSIGNAL, 1L); |
|
214 |
- if (CURLE_OK != curlcode) { |
|
215 |
- logg("!ClamClient: could not setup curl to not use signals, %s\n", curl_easy_strerror(curlcode)); |
|
216 |
- curl_easy_cleanup(*curl); |
|
217 |
- return curlcode; |
|
218 |
- } |
|
219 |
- |
|
220 |
- curlcode = curl_easy_setopt(*curl, CURLOPT_CONNECTTIMEOUT_MS, (long) timeout); |
|
221 |
- if (CURLE_OK != curlcode) { |
|
222 |
- logg("!ClamClient: could not setup curl with connect timeout, %s\n", curl_easy_strerror(curlcode)); |
|
223 |
- curl_easy_cleanup(*curl); |
|
224 |
- return curlcode; |
|
225 |
- } |
|
226 |
- |
|
227 |
- /* we implement our own transfer protocol via send and recv, so we only need to connect */ |
|
228 |
- curlcode = curl_easy_setopt(*curl, CURLOPT_CONNECT_ONLY, 1L); |
|
229 |
- if (CURLE_OK != curlcode) { |
|
230 |
- logg("!ClamClient: could not setup curl to connect only, %s\n", curl_easy_strerror(curlcode)); |
|
231 |
- curl_easy_cleanup(*curl); |
|
232 |
- return curlcode; |
|
233 |
- } |
|
190 |
+ curlcode = curl_easy_setopt(*curl, CURLOPT_URL, "http://localhost/"); |
|
191 |
+ if (CURLE_OK != curlcode) { |
|
192 |
+ logg("!ClamClient: could not setup curl with local address, %s\n", curl_easy_strerror(curlcode)); |
|
193 |
+ curl_easy_cleanup(*curl); |
|
194 |
+ return curlcode; |
|
195 |
+ } |
|
234 | 196 |
|
197 |
+ } else { |
|
198 |
+ |
|
199 |
+ curlcode = curl_easy_setopt(*curl, CURLOPT_PORT, port); |
|
200 |
+ if (CURLE_OK != curlcode) { |
|
201 |
+ logg("!ClamClient: could not setup curl with tcp port, %s\n", curl_easy_strerror(curlcode)); |
|
202 |
+ curl_easy_cleanup(*curl); |
|
203 |
+ return curlcode; |
|
204 |
+ } |
|
205 |
+ |
|
206 |
+ curlcode = curl_easy_setopt(*curl, CURLOPT_URL, ipaddr); |
|
207 |
+ if (CURLE_OK != curlcode) { |
|
208 |
+ logg("!ClamClient: could not setup curl with tcp address, %s\n", curl_easy_strerror(curlcode)); |
|
209 |
+ curl_easy_cleanup(*curl); |
|
210 |
+ return curlcode; |
|
211 |
+ } |
|
212 |
+ } |
|
213 |
+ |
|
214 |
+ curlcode = curl_easy_setopt(*curl, CURLOPT_NOSIGNAL, 1L); |
|
215 |
+ if (CURLE_OK != curlcode) { |
|
216 |
+ logg("!ClamClient: could not setup curl to not use signals, %s\n", curl_easy_strerror(curlcode)); |
|
217 |
+ curl_easy_cleanup(*curl); |
|
218 |
+ return curlcode; |
|
219 |
+ } |
|
220 |
+ |
|
221 |
+ curlcode = curl_easy_setopt(*curl, CURLOPT_CONNECTTIMEOUT_MS, (long)timeout); |
|
222 |
+ if (CURLE_OK != curlcode) { |
|
223 |
+ logg("!ClamClient: could not setup curl with connect timeout, %s\n", curl_easy_strerror(curlcode)); |
|
224 |
+ curl_easy_cleanup(*curl); |
|
225 |
+ return curlcode; |
|
226 |
+ } |
|
227 |
+ |
|
228 |
+ /* we implement our own transfer protocol via send and recv, so we only need to connect */ |
|
229 |
+ curlcode = curl_easy_setopt(*curl, CURLOPT_CONNECT_ONLY, 1L); |
|
230 |
+ if (CURLE_OK != curlcode) { |
|
231 |
+ logg("!ClamClient: could not setup curl to connect only, %s\n", curl_easy_strerror(curlcode)); |
|
232 |
+ curl_easy_cleanup(*curl); |
|
233 |
+ return curlcode; |
|
234 |
+ } |
|
235 | 235 |
|
236 | 236 |
#ifdef ONAS_DEBUG |
237 |
- curlcode = curl_easy_setopt(*curl, CURLOPT_VERBOSE, 1L); |
|
238 |
- if (CURLE_OK != curlcode) { |
|
239 |
- logg("!ClamClient: could not tell curl to be verbose, %s\n", curl_easy_strerror(curlcode)); |
|
240 |
- curl_easy_cleanup(*curl); |
|
241 |
- return curlcode; |
|
242 |
- } |
|
237 |
+ curlcode = curl_easy_setopt(*curl, CURLOPT_VERBOSE, 1L); |
|
238 |
+ if (CURLE_OK != curlcode) { |
|
239 |
+ logg("!ClamClient: could not tell curl to be verbose, %s\n", curl_easy_strerror(curlcode)); |
|
240 |
+ curl_easy_cleanup(*curl); |
|
241 |
+ return curlcode; |
|
242 |
+ } |
|
243 | 243 |
#endif |
244 | 244 |
|
245 |
- /* don't care about the body of the return message */ |
|
246 |
- curlcode = curl_easy_setopt(*curl, CURLOPT_NOBODY, 1L); |
|
247 |
- if (CURLE_OK != curlcode) { |
|
248 |
- logg("!ClamClient: could not setup curl to send HEAD request, %s\n", curl_easy_strerror(curlcode)); |
|
249 |
- curl_easy_cleanup(*curl); |
|
250 |
- return curlcode; |
|
251 |
- } |
|
252 |
- |
|
253 |
- curlcode = curl_easy_setopt(*curl, CURLOPT_HEADER, 0L); |
|
254 |
- if (CURLE_OK != curlcode) { |
|
255 |
- logg("!ClamClient: could not setup curl to not send header, %s\n", curl_easy_strerror(curlcode)); |
|
256 |
- curl_easy_cleanup(*curl); |
|
257 |
- return curlcode; |
|
258 |
- } |
|
245 |
+ /* don't care about the body of the return message */ |
|
246 |
+ curlcode = curl_easy_setopt(*curl, CURLOPT_NOBODY, 1L); |
|
247 |
+ if (CURLE_OK != curlcode) { |
|
248 |
+ logg("!ClamClient: could not setup curl to send HEAD request, %s\n", curl_easy_strerror(curlcode)); |
|
249 |
+ curl_easy_cleanup(*curl); |
|
250 |
+ return curlcode; |
|
251 |
+ } |
|
259 | 252 |
|
253 |
+ curlcode = curl_easy_setopt(*curl, CURLOPT_HEADER, 0L); |
|
254 |
+ if (CURLE_OK != curlcode) { |
|
255 |
+ logg("!ClamClient: could not setup curl to not send header, %s\n", curl_easy_strerror(curlcode)); |
|
256 |
+ curl_easy_cleanup(*curl); |
|
257 |
+ return curlcode; |
|
258 |
+ } |
|
260 | 259 |
|
261 |
- return curlcode; |
|
260 |
+ return curlcode; |
|
262 | 261 |
} |
263 | 262 |
|
264 |
-cl_error_t onas_setup_client (struct onas_context **ctx) { |
|
263 |
+cl_error_t onas_setup_client(struct onas_context **ctx) |
|
264 |
+{ |
|
265 | 265 |
|
266 | 266 |
const struct optstruct *opts; |
267 | 267 |
const struct optstruct *opt; |
... | ... |
@@ -272,35 +270,35 @@ cl_error_t onas_setup_client (struct onas_context **ctx) { |
272 | 272 |
|
273 | 273 |
opts = (*ctx)->opts; |
274 | 274 |
|
275 |
- if(optget(opts, "verbose")->enabled) { |
|
275 |
+ if (optget(opts, "verbose")->enabled) { |
|
276 | 276 |
mprintf_verbose = 1; |
277 |
- logg_verbose = 1; |
|
277 |
+ logg_verbose = 1; |
|
278 | 278 |
} |
279 | 279 |
|
280 |
- if(optget(opts, "infected")->enabled) { |
|
281 |
- (*ctx)->printinfected = 1; |
|
280 |
+ if (optget(opts, "infected")->enabled) { |
|
281 |
+ (*ctx)->printinfected = 1; |
|
282 | 282 |
} |
283 | 283 |
|
284 | 284 |
/* initialize logger */ |
285 | 285 |
|
286 |
- if((opt = optget(opts, "log"))->enabled) { |
|
287 |
- logg_file = opt->strarg; |
|
288 |
- if(logg("--------------------------------------\n")) { |
|
289 |
- logg("!ClamClient: problem with internal logger\n"); |
|
286 |
+ if ((opt = optget(opts, "log"))->enabled) { |
|
287 |
+ logg_file = opt->strarg; |
|
288 |
+ if (logg("--------------------------------------\n")) { |
|
289 |
+ logg("!ClamClient: problem with internal logger\n"); |
|
290 | 290 |
return CL_EARG; |
291 |
- } |
|
291 |
+ } |
|
292 | 292 |
} else { |
293 |
- logg_file = NULL; |
|
293 |
+ logg_file = NULL; |
|
294 | 294 |
} |
295 | 295 |
|
296 |
- if(actsetup(opts)) { |
|
297 |
- return CL_EARG; |
|
296 |
+ if (actsetup(opts)) { |
|
297 |
+ return CL_EARG; |
|
298 | 298 |
} |
299 | 299 |
|
300 |
- (*ctx)->timeout = optget((*ctx)->clamdopts, "OnAccessCurlTimeout")->numarg; |
|
300 |
+ (*ctx)->timeout = optget((*ctx)->clamdopts, "OnAccessCurlTimeout")->numarg; |
|
301 | 301 |
(*ctx)->retry_attempts = optget((*ctx)->clamdopts, "OnAccessRetryAttempts")->numarg; |
302 | 302 |
(*ctx)->retry_attempts ? ((*ctx)->retry_on_error = 1) : ((*ctx)->retry_on_error = 0); |
303 |
- optget((*ctx)->clamdopts, "OnAccessDenyOnError")->enabled ? ((*ctx)->deny_on_error = 1) : ((*ctx)->deny_on_error = 0); |
|
303 |
+ optget((*ctx)->clamdopts, "OnAccessDenyOnError")->enabled ? ((*ctx)->deny_on_error = 1) : ((*ctx)->deny_on_error = 0); |
|
304 | 304 |
|
305 | 305 |
(*ctx)->isremote = onas_check_remote(ctx, &err); |
306 | 306 |
if (err) { |
... | ... |
@@ -309,26 +307,26 @@ cl_error_t onas_setup_client (struct onas_context **ctx) { |
309 | 309 |
|
310 | 310 |
remote = (*ctx)->isremote | optget(opts, "stream")->enabled; |
311 | 311 |
#ifdef HAVE_FD_PASSING |
312 |
- if(!remote && optget((*ctx)->clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled)) { |
|
312 |
+ if (!remote && optget((*ctx)->clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled)) { |
|
313 | 313 |
logg("*ClamClient: client setup to scan via fd passing\n"); |
314 | 314 |
(*ctx)->scantype = FILDES; |
315 |
- (*ctx)->session = optget(opts, "multiscan")->enabled; |
|
315 |
+ (*ctx)->session = optget(opts, "multiscan")->enabled; |
|
316 | 316 |
} else |
317 | 317 |
#endif |
318 |
- if(remote) { |
|
319 |
- logg("*ClamClient: client setup to scan via streaming\n"); |
|
320 |
- (*ctx)->scantype = STREAM; |
|
321 |
- (*ctx)->session = optget(opts, "multiscan")->enabled; |
|
322 |
- } else if(optget(opts, "multiscan")->enabled) { |
|
323 |
- logg("*ClamClient: client setup to scan in multiscan mode\n"); |
|
324 |
- (*ctx)->scantype = MULTI; |
|
325 |
- } else if(optget(opts, "allmatch")->enabled) { |
|
326 |
- logg("*ClamClient: client setup to scan in all-match mode\n"); |
|
327 |
- (*ctx)->scantype = ALLMATCH; |
|
328 |
- } else { |
|
329 |
- logg("*ClamClient: client setup for continuous scanning\n"); |
|
330 |
- (*ctx)->scantype = CONT; |
|
331 |
- } |
|
318 |
+ if (remote) { |
|
319 |
+ logg("*ClamClient: client setup to scan via streaming\n"); |
|
320 |
+ (*ctx)->scantype = STREAM; |
|
321 |
+ (*ctx)->session = optget(opts, "multiscan")->enabled; |
|
322 |
+ } else if (optget(opts, "multiscan")->enabled) { |
|
323 |
+ logg("*ClamClient: client setup to scan in multiscan mode\n"); |
|
324 |
+ (*ctx)->scantype = MULTI; |
|
325 |
+ } else if (optget(opts, "allmatch")->enabled) { |
|
326 |
+ logg("*ClamClient: client setup to scan in all-match mode\n"); |
|
327 |
+ (*ctx)->scantype = ALLMATCH; |
|
328 |
+ } else { |
|
329 |
+ logg("*ClamClient: client setup for continuous scanning\n"); |
|
330 |
+ (*ctx)->scantype = CONT; |
|
331 |
+ } |
|
332 | 332 |
|
333 | 333 |
(*ctx)->maxstream = optget((*ctx)->clamdopts, "StreamMaxLength")->numarg; |
334 | 334 |
|
... | ... |
@@ -350,36 +348,36 @@ int onas_get_clamd_version(struct onas_context **ctx) |
350 | 350 |
|
351 | 351 |
b_remote = onas_check_remote(ctx, &err); |
352 | 352 |
if (CL_SUCCESS != err) { |
353 |
- logg("!ClamClient: could not check to see if daemon was remote\n"); |
|
354 |
- return 2; |
|
353 |
+ logg("!ClamClient: could not check to see if daemon was remote\n"); |
|
354 |
+ return 2; |
|
355 | 355 |
} |
356 | 356 |
|
357 | 357 |
if (!b_remote) { |
358 |
- curlcode = onas_curl_init(&curl, optget((*ctx)->clamdopts, "LocalSocket")->strarg, 0, timeout); |
|
358 |
+ curlcode = onas_curl_init(&curl, optget((*ctx)->clamdopts, "LocalSocket")->strarg, 0, timeout); |
|
359 | 359 |
} else { |
360 |
- curlcode = onas_curl_init(&curl, optget((*ctx)->clamdopts, "TCPAddr")->strarg, (*ctx)->portnum, timeout); |
|
361 |
- if (CURLE_OK != curlcode) { |
|
362 |
- logg("!ClamClient: could not setup curl with tcp address and port, %s\n", curl_easy_strerror(curlcode)); |
|
363 |
- /* curl cleanup done in onas_curl_init on error */ |
|
364 |
- return 2; |
|
365 |
- } |
|
360 |
+ curlcode = onas_curl_init(&curl, optget((*ctx)->clamdopts, "TCPAddr")->strarg, (*ctx)->portnum, timeout); |
|
361 |
+ if (CURLE_OK != curlcode) { |
|
362 |
+ logg("!ClamClient: could not setup curl with tcp address and port, %s\n", curl_easy_strerror(curlcode)); |
|
363 |
+ /* curl cleanup done in onas_curl_init on error */ |
|
364 |
+ return 2; |
|
365 |
+ } |
|
366 | 366 |
} |
367 | 367 |
|
368 | 368 |
onas_recvlninit(&rcv, curl); |
369 | 369 |
|
370 | 370 |
curlcode = curl_easy_perform(curl); |
371 | 371 |
if (CURLE_OK != curlcode) { |
372 |
- logg("*ClamClient: could not connect to clam daemon, %s\n", curl_easy_strerror(curlcode)); |
|
373 |
- return 2; |
|
372 |
+ logg("*ClamClient: could not connect to clam daemon, %s\n", curl_easy_strerror(curlcode)); |
|
373 |
+ return 2; |
|
374 | 374 |
} |
375 | 375 |
|
376 |
- if(onas_sendln(curl, "zVERSION", 9, timeout)) { |
|
376 |
+ if (onas_sendln(curl, "zVERSION", 9, timeout)) { |
|
377 | 377 |
curl_easy_cleanup(curl); |
378 | 378 |
return 2; |
379 | 379 |
} |
380 | 380 |
|
381 |
- while((len = onas_recvln(&rcv, &buff, NULL, timeout))) { |
|
382 |
- if(len == -1) { |
|
381 |
+ while ((len = onas_recvln(&rcv, &buff, NULL, timeout))) { |
|
382 |
+ if (len == -1) { |
|
383 | 383 |
logg("*ClamClient: clamd did not respond with version information\n"); |
384 | 384 |
break; |
385 | 385 |
} |
... | ... |
@@ -407,39 +405,37 @@ int onas_get_clamd_version(struct onas_context **ctx) |
407 | 407 |
*/ |
408 | 408 |
int onas_client_scan(const char *tcpaddr, int64_t portnum, int32_t scantype, uint64_t maxstream, const char *fname, int fd, int64_t timeout, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) |
409 | 409 |
{ |
410 |
- CURL *curl = NULL; |
|
411 |
- CURLcode curlcode = CURLE_OK; |
|
412 |
- int errors = 0; |
|
413 |
- int sockd, ret; |
|
414 |
- |
|
415 |
- *infected = 0; |
|
416 |
- |
|
417 |
- if((sb.st_mode & S_IFMT) != S_IFREG) { |
|
418 |
- scantype = STREAM; |
|
419 |
- } |
|
420 |
- |
|
421 |
- curlcode = onas_curl_init(&curl, tcpaddr, portnum, timeout); |
|
422 |
- if (CURLE_OK != curlcode) { |
|
423 |
- logg("!ClamClient: could not init curl for scanning, %s\n", curl_easy_strerror(curlcode)); |
|
424 |
- /* curl cleanup done in onas_curl_init on error */ |
|
425 |
- return CL_ECREAT; |
|
426 |
- } |
|
427 |
- |
|
428 |
- curlcode = curl_easy_perform(curl); |
|
429 |
- if (CURLE_OK != curlcode) { |
|
430 |
- logg("!ClamClient: could not establish connection, %s\n", curl_easy_strerror(curlcode)); |
|
431 |
- return CL_ECREAT; |
|
432 |
- } |
|
433 |
- |
|
434 |
- |
|
435 |
- if((ret = onas_dsresult(curl, scantype, maxstream, fname, fd, timeout, &ret, err, ret_code)) >= 0) { |
|
436 |
- *infected = ret; |
|
437 |
- } else { |
|
438 |
- logg("*ClamClient: connection could not be established ... return code %d\n", *ret_code); |
|
439 |
- errors = 1; |
|
440 |
- } |
|
441 |
- |
|
442 |
- curl_easy_cleanup(curl); |
|
443 |
- return *infected ? CL_VIRUS : (errors ? CL_ECREAT : CL_CLEAN); |
|
444 |
-} |
|
410 |
+ CURL *curl = NULL; |
|
411 |
+ CURLcode curlcode = CURLE_OK; |
|
412 |
+ int errors = 0; |
|
413 |
+ int sockd, ret; |
|
414 |
+ |
|
415 |
+ *infected = 0; |
|
416 |
+ |
|
417 |
+ if ((sb.st_mode & S_IFMT) != S_IFREG) { |
|
418 |
+ scantype = STREAM; |
|
419 |
+ } |
|
420 |
+ |
|
421 |
+ curlcode = onas_curl_init(&curl, tcpaddr, portnum, timeout); |
|
422 |
+ if (CURLE_OK != curlcode) { |
|
423 |
+ logg("!ClamClient: could not init curl for scanning, %s\n", curl_easy_strerror(curlcode)); |
|
424 |
+ /* curl cleanup done in onas_curl_init on error */ |
|
425 |
+ return CL_ECREAT; |
|
426 |
+ } |
|
445 | 427 |
|
428 |
+ curlcode = curl_easy_perform(curl); |
|
429 |
+ if (CURLE_OK != curlcode) { |
|
430 |
+ logg("!ClamClient: could not establish connection, %s\n", curl_easy_strerror(curlcode)); |
|
431 |
+ return CL_ECREAT; |
|
432 |
+ } |
|
433 |
+ |
|
434 |
+ if ((ret = onas_dsresult(curl, scantype, maxstream, fname, fd, timeout, &ret, err, ret_code)) >= 0) { |
|
435 |
+ *infected = ret; |
|
436 |
+ } else { |
|
437 |
+ logg("*ClamClient: connection could not be established ... return code %d\n", *ret_code); |
|
438 |
+ errors = 1; |
|
439 |
+ } |
|
440 |
+ |
|
441 |
+ curl_easy_cleanup(curl); |
|
442 |
+ return *infected ? CL_VIRUS : (errors ? CL_ECREAT : CL_CLEAN); |
|
443 |
+} |
... | ... |
@@ -36,12 +36,11 @@ enum { |
36 | 36 |
MAX_SCANTYPE = ALLMATCH |
37 | 37 |
}; |
38 | 38 |
|
39 |
- |
|
40 | 39 |
void onas_print_server_version(struct onas_context **ctx); |
41 | 40 |
int onas_client_scan(const char *tcpaddr, int64_t portnum, int32_t scantype, uint64_t maxstream, const char *fname, int fd, int64_t timeout, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); |
42 | 41 |
CURLcode onas_curl_init(CURL **curl, const char *ipaddr, int64_t port, int64_t timeout); |
43 | 42 |
int onas_get_clamd_version(struct onas_context **ctx); |
44 | 43 |
cl_error_t onas_setup_client(struct onas_context **ctx); |
45 |
-int onas_check_remote(struct onas_context **ctx, cl_error_t *err); |
|
44 |
+int onas_check_remote(struct onas_context **ctx, cl_error_t *err); |
|
46 | 45 |
|
47 | 46 |
#endif |
... | ... |
@@ -42,7 +42,6 @@ |
42 | 42 |
|
43 | 43 |
#include "communication.h" |
44 | 44 |
|
45 |
- |
|
46 | 45 |
static int onas_socket_wait(curl_socket_t sockfd, int32_t b_recv, uint64_t timeout_ms); |
47 | 46 |
|
48 | 47 |
/** |
... | ... |
@@ -50,79 +49,79 @@ static int onas_socket_wait(curl_socket_t sockfd, int32_t b_recv, uint64_t timeo |
50 | 50 |
*/ |
51 | 51 |
static int onas_socket_wait(curl_socket_t sockfd, int32_t b_recv, uint64_t timeout_ms) |
52 | 52 |
{ |
53 |
- struct timeval tv; |
|
54 |
- fd_set infd, outfd, errfd; |
|
55 |
- int ret; |
|
53 |
+ struct timeval tv; |
|
54 |
+ fd_set infd, outfd, errfd; |
|
55 |
+ int ret; |
|
56 | 56 |
|
57 |
- tv.tv_sec = timeout_ms / 1000; |
|
58 |
- tv.tv_usec = (timeout_ms % 1000) * 1000; |
|
57 |
+ tv.tv_sec = timeout_ms / 1000; |
|
58 |
+ tv.tv_usec = (timeout_ms % 1000) * 1000; |
|
59 | 59 |
|
60 |
- FD_ZERO(&infd); |
|
61 |
- FD_ZERO(&outfd); |
|
62 |
- FD_ZERO(&errfd); |
|
60 |
+ FD_ZERO(&infd); |
|
61 |
+ FD_ZERO(&outfd); |
|
62 |
+ FD_ZERO(&errfd); |
|
63 | 63 |
|
64 |
- FD_SET(sockfd, &errfd); /* always check for error */ |
|
64 |
+ FD_SET(sockfd, &errfd); /* always check for error */ |
|
65 | 65 |
|
66 |
- if(b_recv) { |
|
67 |
- FD_SET(sockfd, &infd); |
|
68 |
- } |
|
69 |
- else { |
|
70 |
- FD_SET(sockfd, &outfd); |
|
71 |
- } |
|
66 |
+ if (b_recv) { |
|
67 |
+ FD_SET(sockfd, &infd); |
|
68 |
+ } else { |
|
69 |
+ FD_SET(sockfd, &outfd); |
|
70 |
+ } |
|
72 | 71 |
|
73 |
- /* select() returns the number of signalled sockets or -1 */ |
|
74 |
- ret = select((int)sockfd + 1, &infd, &outfd, &errfd, &tv); |
|
75 |
- return ret; |
|
72 |
+ /* select() returns the number of signalled sockets or -1 */ |
|
73 |
+ ret = select((int)sockfd + 1, &infd, &outfd, &errfd, &tv); |
|
74 |
+ return ret; |
|
76 | 75 |
} |
77 | 76 |
|
78 | 77 |
/* Sends bytes over a socket |
79 | 78 |
* Returns 0 on success */ |
80 |
-int onas_sendln(CURL *curl, const void *line, size_t len, int64_t timeout) { |
|
81 |
- size_t sent = 0; |
|
82 |
- CURLcode curlcode; |
|
83 |
- curl_socket_t sockfd; |
|
84 |
- |
|
85 |
- curlcode = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd); |
|
86 |
- |
|
87 |
- if(CURLE_OK != curlcode) { |
|
88 |
- logg("!ClamCom: could not get curl active socket info %s\n", curl_easy_strerror(curlcode)); |
|
89 |
- return 1; |
|
90 |
- } |
|
91 |
- |
|
92 |
- while(len) { |
|
93 |
- |
|
94 |
- do { |
|
95 |
- curlcode = curl_easy_send(curl, line, len, &sent); |
|
96 |
- if (CURLE_AGAIN == curlcode && !onas_socket_wait(sockfd, 0, timeout)) { |
|
97 |
- logg("!ClamCom: TIMEOUT while waiting on socket (send)\n"); |
|
98 |
- return 1; |
|
99 |
- } |
|
100 |
- } while (CURLE_AGAIN == curlcode); |
|
101 |
- |
|
102 |
- |
|
103 |
- if(sent <= 0) { |
|
104 |
- if(sent && errno == EINTR) { |
|
105 |
- continue; |
|
106 |
- } else { |
|
107 |
- logg("!Can't send to clamd: %s\n", strerror(errno)); |
|
108 |
- } |
|
109 |
- |
|
110 |
- return 1; |
|
111 |
- } |
|
112 |
- |
|
113 |
- line += sent; |
|
114 |
- len -= sent; |
|
115 |
- } |
|
116 |
- |
|
117 |
- return 0; |
|
79 |
+int onas_sendln(CURL *curl, const void *line, size_t len, int64_t timeout) |
|
80 |
+{ |
|
81 |
+ size_t sent = 0; |
|
82 |
+ CURLcode curlcode; |
|
83 |
+ curl_socket_t sockfd; |
|
84 |
+ |
|
85 |
+ curlcode = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd); |
|
86 |
+ |
|
87 |
+ if (CURLE_OK != curlcode) { |
|
88 |
+ logg("!ClamCom: could not get curl active socket info %s\n", curl_easy_strerror(curlcode)); |
|
89 |
+ return 1; |
|
90 |
+ } |
|
91 |
+ |
|
92 |
+ while (len) { |
|
93 |
+ |
|
94 |
+ do { |
|
95 |
+ curlcode = curl_easy_send(curl, line, len, &sent); |
|
96 |
+ if (CURLE_AGAIN == curlcode && !onas_socket_wait(sockfd, 0, timeout)) { |
|
97 |
+ logg("!ClamCom: TIMEOUT while waiting on socket (send)\n"); |
|
98 |
+ return 1; |
|
99 |
+ } |
|
100 |
+ } while (CURLE_AGAIN == curlcode); |
|
101 |
+ |
|
102 |
+ if (sent <= 0) { |
|
103 |
+ if (sent && errno == EINTR) { |
|
104 |
+ continue; |
|
105 |
+ } else { |
|
106 |
+ logg("!Can't send to clamd: %s\n", strerror(errno)); |
|
107 |
+ } |
|
108 |
+ |
|
109 |
+ return 1; |
|
110 |
+ } |
|
111 |
+ |
|
112 |
+ line += sent; |
|
113 |
+ len -= sent; |
|
114 |
+ } |
|
115 |
+ |
|
116 |
+ return 0; |
|
118 | 117 |
} |
119 | 118 |
|
120 | 119 |
/* Inits a RECVLN struct before it can be used in recvln() - see below */ |
121 |
-void onas_recvlninit(struct RCVLN *rcv_data, CURL *curl) { |
|
122 |
- rcv_data->curl = curl; |
|
123 |
- rcv_data->curlcode = CURLE_OK; |
|
124 |
- rcv_data->lnstart = rcv_data->curr = rcv_data->buf; |
|
125 |
- rcv_data->retlen = 0; |
|
120 |
+void onas_recvlninit(struct RCVLN *rcv_data, CURL *curl) |
|
121 |
+{ |
|
122 |
+ rcv_data->curl = curl; |
|
123 |
+ rcv_data->curlcode = CURLE_OK; |
|
124 |
+ rcv_data->lnstart = rcv_data->curr = rcv_data->buf; |
|
125 |
+ rcv_data->retlen = 0; |
|
126 | 126 |
} |
127 | 127 |
|
128 | 128 |
/* Receives a full (terminated with \0) line from a socket |
... | ... |
@@ -134,88 +133,88 @@ void onas_recvlninit(struct RCVLN *rcv_data, CURL *curl) { |
134 | 134 |
* - 0 if the connection is closed |
135 | 135 |
* - -1 on error |
136 | 136 |
*/ |
137 |
-int onas_recvln(struct RCVLN *rcv_data, char **ret_bol, char **ret_eol, int64_t timeout) { |
|
138 |
- char *eol; |
|
139 |
- int ret = 0; |
|
140 |
- curl_socket_t sockfd; |
|
141 |
- |
|
142 |
- rcv_data->curlcode = curl_easy_getinfo(rcv_data->curl, CURLINFO_ACTIVESOCKET, &sockfd); |
|
143 |
- |
|
144 |
- if(CURLE_OK != rcv_data->curlcode) { |
|
145 |
- logg("!ClamCom: could not get curl active socket info %s\n", curl_easy_strerror(rcv_data->curlcode)); |
|
146 |
- return -1; |
|
147 |
- } |
|
148 |
- |
|
149 |
- while(1) { |
|
150 |
- if (!rcv_data->retlen) { |
|
151 |
- do { |
|
152 |
- rcv_data->curlcode = curl_easy_recv(rcv_data->curl, rcv_data->curr, |
|
153 |
- sizeof(rcv_data->buf) - (rcv_data->curr - rcv_data->buf), &(rcv_data->retlen)); |
|
154 |
- |
|
155 |
- if (CURLE_AGAIN == rcv_data->curlcode && !onas_socket_wait(sockfd, 1, timeout)) { |
|
156 |
- logg("!ClamCom: TIMEOUT while waiting on socket (recv)\n"); |
|
157 |
- return -1; |
|
158 |
- } |
|
159 |
- |
|
160 |
- } while (CURLE_AGAIN == rcv_data->curlcode); |
|
161 |
- |
|
162 |
- if (rcv_data->retlen<=0) { |
|
163 |
- if (rcv_data->retlen && errno == EINTR) { |
|
164 |
- rcv_data->retlen = 0; |
|
165 |
- continue; |
|
166 |
- } |
|
167 |
- |
|
168 |
- if (rcv_data->retlen || rcv_data->curr!=rcv_data->buf) { |
|
169 |
- *rcv_data->curr = '\0'; |
|
170 |
- |
|
171 |
- if (strcmp(rcv_data->buf, "UNKNOWN COMMAND\n")) { |
|
172 |
- logg("!Communication error\n"); |
|
173 |
- } else { |
|
174 |
- logg("!Command rejected by clamd (wrong clamd version?)\n"); |
|
175 |
- } |
|
176 |
- |
|
177 |
- return -1; |
|
178 |
- } |
|
179 |
- |
|
180 |
- return 0; |
|
181 |
- } |
|
182 |
- } |
|
183 |
- |
|
184 |
- if ((eol = memchr(rcv_data->curr, 0, rcv_data->retlen))) { |
|
185 |
- eol++; |
|
186 |
- rcv_data->retlen -= eol - rcv_data->curr; |
|
187 |
- |
|
188 |
- *ret_bol = rcv_data->lnstart; |
|
189 |
- if (ret_eol) { |
|
190 |
- *ret_eol = eol; |
|
191 |
- } |
|
192 |
- |
|
193 |
- ret = eol - rcv_data->lnstart; |
|
194 |
- if (rcv_data->retlen) { |
|
195 |
- rcv_data->lnstart = rcv_data->curr = eol; |
|
196 |
- } else { |
|
197 |
- rcv_data->lnstart = rcv_data->curr = rcv_data->buf; |
|
198 |
- } |
|
199 |
- |
|
200 |
- return ret; |
|
201 |
- } |
|
202 |
- |
|
203 |
- rcv_data->retlen += rcv_data->curr - rcv_data->lnstart; |
|
204 |
- |
|
205 |
- if (!eol && rcv_data->retlen==sizeof(rcv_data->buf)) { |
|
206 |
- logg("!Overlong reply from clamd\n"); |
|
207 |
- return -1; |
|
208 |
- } |
|
209 |
- |
|
210 |
- if (!eol) { |
|
211 |
- if(rcv_data->buf != rcv_data->lnstart) { |
|
212 |
- memmove(rcv_data->buf, rcv_data->lnstart, rcv_data->retlen); |
|
213 |
- rcv_data->lnstart = rcv_data->buf; |
|
214 |
- } |
|
215 |
- |
|
216 |
- rcv_data->curr = &rcv_data->lnstart[rcv_data->retlen]; |
|
217 |
- rcv_data->retlen = 0; |
|
218 |
- } |
|
219 |
- } |
|
137 |
+int onas_recvln(struct RCVLN *rcv_data, char **ret_bol, char **ret_eol, int64_t timeout) |
|
138 |
+{ |
|
139 |
+ char *eol; |
|
140 |
+ int ret = 0; |
|
141 |
+ curl_socket_t sockfd; |
|
142 |
+ |
|
143 |
+ rcv_data->curlcode = curl_easy_getinfo(rcv_data->curl, CURLINFO_ACTIVESOCKET, &sockfd); |
|
144 |
+ |
|
145 |
+ if (CURLE_OK != rcv_data->curlcode) { |
|
146 |
+ logg("!ClamCom: could not get curl active socket info %s\n", curl_easy_strerror(rcv_data->curlcode)); |
|
147 |
+ return -1; |
|
148 |
+ } |
|
149 |
+ |
|
150 |
+ while (1) { |
|
151 |
+ if (!rcv_data->retlen) { |
|
152 |
+ do { |
|
153 |
+ rcv_data->curlcode = curl_easy_recv(rcv_data->curl, rcv_data->curr, |
|
154 |
+ sizeof(rcv_data->buf) - (rcv_data->curr - rcv_data->buf), &(rcv_data->retlen)); |
|
155 |
+ |
|
156 |
+ if (CURLE_AGAIN == rcv_data->curlcode && !onas_socket_wait(sockfd, 1, timeout)) { |
|
157 |
+ logg("!ClamCom: TIMEOUT while waiting on socket (recv)\n"); |
|
158 |
+ return -1; |
|
159 |
+ } |
|
160 |
+ |
|
161 |
+ } while (CURLE_AGAIN == rcv_data->curlcode); |
|
162 |
+ |
|
163 |
+ if (rcv_data->retlen <= 0) { |
|
164 |
+ if (rcv_data->retlen && errno == EINTR) { |
|
165 |
+ rcv_data->retlen = 0; |
|
166 |
+ continue; |
|
167 |
+ } |
|
168 |
+ |
|
169 |
+ if (rcv_data->retlen || rcv_data->curr != rcv_data->buf) { |
|
170 |
+ *rcv_data->curr = '\0'; |
|
171 |
+ |
|
172 |
+ if (strcmp(rcv_data->buf, "UNKNOWN COMMAND\n")) { |
|
173 |
+ logg("!Communication error\n"); |
|
174 |
+ } else { |
|
175 |
+ logg("!Command rejected by clamd (wrong clamd version?)\n"); |
|
176 |
+ } |
|
177 |
+ |
|
178 |
+ return -1; |
|
179 |
+ } |
|
180 |
+ |
|
181 |
+ return 0; |
|
182 |
+ } |
|
183 |
+ } |
|
184 |
+ |
|
185 |
+ if ((eol = memchr(rcv_data->curr, 0, rcv_data->retlen))) { |
|
186 |
+ eol++; |
|
187 |
+ rcv_data->retlen -= eol - rcv_data->curr; |
|
188 |
+ |
|
189 |
+ *ret_bol = rcv_data->lnstart; |
|
190 |
+ if (ret_eol) { |
|
191 |
+ *ret_eol = eol; |
|
192 |
+ } |
|
193 |
+ |
|
194 |
+ ret = eol - rcv_data->lnstart; |
|
195 |
+ if (rcv_data->retlen) { |
|
196 |
+ rcv_data->lnstart = rcv_data->curr = eol; |
|
197 |
+ } else { |
|
198 |
+ rcv_data->lnstart = rcv_data->curr = rcv_data->buf; |
|
199 |
+ } |
|
200 |
+ |
|
201 |
+ return ret; |
|
202 |
+ } |
|
203 |
+ |
|
204 |
+ rcv_data->retlen += rcv_data->curr - rcv_data->lnstart; |
|
205 |
+ |
|
206 |
+ if (!eol && rcv_data->retlen == sizeof(rcv_data->buf)) { |
|
207 |
+ logg("!Overlong reply from clamd\n"); |
|
208 |
+ return -1; |
|
209 |
+ } |
|
210 |
+ |
|
211 |
+ if (!eol) { |
|
212 |
+ if (rcv_data->buf != rcv_data->lnstart) { |
|
213 |
+ memmove(rcv_data->buf, rcv_data->lnstart, rcv_data->retlen); |
|
214 |
+ rcv_data->lnstart = rcv_data->buf; |
|
215 |
+ } |
|
216 |
+ |
|
217 |
+ rcv_data->curr = &rcv_data->lnstart[rcv_data->retlen]; |
|
218 |
+ rcv_data->retlen = 0; |
|
219 |
+ } |
|
220 |
+ } |
|
220 | 221 |
} |
221 |
- |
... | ... |
@@ -62,118 +62,119 @@ |
62 | 62 |
#include "protocol.h" |
63 | 63 |
#include "client.h" |
64 | 64 |
|
65 |
-static const char *scancmd[] = { "CONTSCAN", "MULTISCAN", "INSTREAM", "FILDES", "ALLMATCHSCAN" }; |
|
65 |
+static const char *scancmd[] = {"CONTSCAN", "MULTISCAN", "INSTREAM", "FILDES", "ALLMATCHSCAN"}; |
|
66 | 66 |
|
67 | 67 |
/* Issues an INSTREAM command to clamd and streams the given file |
68 | 68 |
* Returns >0 on success, 0 soft fail, -1 hard fail */ |
69 |
-static int onas_send_stream(CURL *curl, const char *filename, int fd, int64_t timeout, uint64_t maxstream) { |
|
70 |
- uint32_t buf[BUFSIZ/sizeof(uint32_t)]; |
|
71 |
- uint64_t len; |
|
72 |
- uint64_t todo = maxstream; |
|
73 |
- int ret = 1; |
|
74 |
- int close_flag = 0; |
|
75 |
- |
|
76 |
- if (0 == fd) { |
|
77 |
- if(filename) { |
|
78 |
- if((fd = safe_open(filename, O_RDONLY | O_BINARY))<0) { |
|
79 |
- logg("~%s: Access denied. ERROR\n", filename); |
|
80 |
- return 0; |
|
81 |
- } |
|
82 |
- //logg("DEBUG: >>>>> fd is %d\n", fd); |
|
83 |
- close_flag = 1; |
|
84 |
- } else { |
|
85 |
- fd = 0; |
|
69 |
+static int onas_send_stream(CURL *curl, const char *filename, int fd, int64_t timeout, uint64_t maxstream) |
|
70 |
+{ |
|
71 |
+ uint32_t buf[BUFSIZ / sizeof(uint32_t)]; |
|
72 |
+ uint64_t len; |
|
73 |
+ uint64_t todo = maxstream; |
|
74 |
+ int ret = 1; |
|
75 |
+ int close_flag = 0; |
|
76 |
+ |
|
77 |
+ if (0 == fd) { |
|
78 |
+ if (filename) { |
|
79 |
+ if ((fd = safe_open(filename, O_RDONLY | O_BINARY)) < 0) { |
|
80 |
+ logg("~%s: Access denied. ERROR\n", filename); |
|
81 |
+ return 0; |
|
86 | 82 |
} |
83 |
+ //logg("DEBUG: >>>>> fd is %d\n", fd); |
|
84 |
+ close_flag = 1; |
|
85 |
+ } else { |
|
86 |
+ fd = 0; |
|
87 | 87 |
} |
88 |
+ } |
|
89 |
+ |
|
90 |
+ if (onas_sendln(curl, "zINSTREAM", 10, timeout)) { |
|
91 |
+ ret = -1; |
|
92 |
+ goto strm_out; |
|
93 |
+ } |
|
94 |
+ |
|
95 |
+ while ((len = read(fd, &buf[1], sizeof(buf) - sizeof(uint32_t))) > 0) { |
|
96 |
+ if ((uint64_t)len > todo) len = todo; |
|
97 |
+ buf[0] = htonl(len); |
|
98 |
+ if (onas_sendln(curl, (const char *)buf, len + sizeof(uint32_t), timeout)) { |
|
99 |
+ ret = -1; |
|
100 |
+ goto strm_out; |
|
101 |
+ } |
|
102 |
+ todo -= len; |
|
103 |
+ if (!todo) { |
|
104 |
+ len = 0; |
|
105 |
+ break; |
|
106 |
+ } |
|
107 |
+ } |
|
88 | 108 |
|
89 |
- |
|
90 |
- if(onas_sendln(curl, "zINSTREAM", 10, timeout)) { |
|
91 |
- ret = -1; |
|
92 |
- goto strm_out; |
|
93 |
- } |
|
94 |
- |
|
95 |
- while((len = read(fd, &buf[1], sizeof(buf) - sizeof(uint32_t))) > 0) { |
|
96 |
- if((uint64_t)len > todo) len = todo; |
|
97 |
- buf[0] = htonl(len); |
|
98 |
- if (onas_sendln(curl, (const char *)buf, len+sizeof(uint32_t), timeout)) { |
|
99 |
- ret = -1; |
|
100 |
- goto strm_out; |
|
101 |
- } |
|
102 |
- todo -= len; |
|
103 |
- if(!todo) { |
|
104 |
- len = 0; |
|
105 |
- break; |
|
106 |
- } |
|
107 |
- } |
|
108 |
- |
|
109 |
- if(len) { |
|
110 |
- logg("!Failed to read from %s.\n", filename ? filename : "STDIN"); |
|
111 |
- ret = 0; |
|
112 |
- goto strm_out; |
|
113 |
- } |
|
114 |
- *buf=0; |
|
115 |
- onas_sendln(curl, (const char *)buf, 4, timeout); |
|
109 |
+ if (len) { |
|
110 |
+ logg("!Failed to read from %s.\n", filename ? filename : "STDIN"); |
|
111 |
+ ret = 0; |
|
112 |
+ goto strm_out; |
|
113 |
+ } |
|
114 |
+ *buf = 0; |
|
115 |
+ onas_sendln(curl, (const char *)buf, 4, timeout); |
|
116 | 116 |
|
117 | 117 |
strm_out: |
118 |
- if (close_flag) { |
|
119 |
- //logg("DEBUG: >>>>> closed fd %d\n", fd); |
|
120 |
- close(fd); |
|
121 |
- } |
|
122 |
- return ret; |
|
118 |
+ if (close_flag) { |
|
119 |
+ //logg("DEBUG: >>>>> closed fd %d\n", fd); |
|
120 |
+ close(fd); |
|
121 |
+ } |
|
122 |
+ return ret; |
|
123 | 123 |
} |
124 | 124 |
|
125 | 125 |
#ifdef HAVE_FD_PASSING |
126 | 126 |
/* Issues a FILDES command and pass a FD to clamd |
127 | 127 |
* Returns >0 on success, 0 soft fail, -1 hard fail */ |
128 |
-static int onas_send_fdpass(CURL *curl, const char *filename, int fd, int64_t timeout) { |
|
129 |
- CURLcode result; |
|
130 |
- struct iovec iov[1]; |
|
131 |
- struct msghdr msg; |
|
132 |
- struct cmsghdr *cmsg; |
|
133 |
- unsigned char fdbuf[CMSG_SPACE(sizeof(int))]; |
|
134 |
- char dummy[]=""; |
|
135 |
- int ret = 1; |
|
136 |
- int close_flag = 0; |
|
137 |
- |
|
138 |
- if (0 == fd) { |
|
139 |
- if(filename) { |
|
140 |
- if((fd = open(filename, O_RDONLY))<0) { |
|
141 |
- logg("~%s: Access denied. ERROR\n", filename); |
|
142 |
- return 0; |
|
143 |
- } |
|
144 |
- close_flag = 1; |
|
145 |
- } else { |
|
146 |
- fd = 0; |
|
128 |
+static int onas_send_fdpass(CURL *curl, const char *filename, int fd, int64_t timeout) |
|
129 |
+{ |
|
130 |
+ CURLcode result; |
|
131 |
+ struct iovec iov[1]; |
|
132 |
+ struct msghdr msg; |
|
133 |
+ struct cmsghdr *cmsg; |
|
134 |
+ unsigned char fdbuf[CMSG_SPACE(sizeof(int))]; |
|
135 |
+ char dummy[] = ""; |
|
136 |
+ int ret = 1; |
|
137 |
+ int close_flag = 0; |
|
138 |
+ |
|
139 |
+ if (0 == fd) { |
|
140 |
+ if (filename) { |
|
141 |
+ if ((fd = open(filename, O_RDONLY)) < 0) { |
|
142 |
+ logg("~%s: Access denied. ERROR\n", filename); |
|
143 |
+ return 0; |
|
147 | 144 |
} |
145 |
+ close_flag = 1; |
|
146 |
+ } else { |
|
147 |
+ fd = 0; |
|
148 | 148 |
} |
149 |
- if(result = onas_sendln(curl, "zFILDES", 8, timeout)) { |
|
150 |
- logg("*ClamProto: error sending w/ curl, %s\n", curl_easy_strerror(result)); |
|
151 |
- ret = -1; |
|
152 |
- goto fd_out; |
|
153 |
- } |
|
154 |
- |
|
155 |
- iov[0].iov_base = dummy; |
|
156 |
- iov[0].iov_len = 1; |
|
157 |
- memset(&msg, 0, sizeof(msg)); |
|
158 |
- msg.msg_control = fdbuf; |
|
159 |
- msg.msg_iov = iov; |
|
160 |
- msg.msg_iovlen = 1; |
|
161 |
- msg.msg_controllen = CMSG_LEN(sizeof(int)); |
|
162 |
- cmsg = CMSG_FIRSTHDR(&msg); |
|
163 |
- cmsg->cmsg_len = CMSG_LEN(sizeof(int)); |
|
164 |
- cmsg->cmsg_level = SOL_SOCKET; |
|
165 |
- cmsg->cmsg_type = SCM_RIGHTS; |
|
166 |
- *(int *)CMSG_DATA(cmsg) = fd; |
|
167 |
- if(onas_sendln(curl, &msg, 0, timeout) == -1) { |
|
168 |
- logg("!FD send failed: %s\n", strerror(errno)); |
|
169 |
- ret = -1; |
|
170 |
- goto fd_out; |
|
171 |
- } |
|
149 |
+ } |
|
150 |
+ if (result = onas_sendln(curl, "zFILDES", 8, timeout)) { |
|
151 |
+ logg("*ClamProto: error sending w/ curl, %s\n", curl_easy_strerror(result)); |
|
152 |
+ ret = -1; |
|
153 |
+ goto fd_out; |
|
154 |
+ } |
|
155 |
+ |
|
156 |
+ iov[0].iov_base = dummy; |
|
157 |
+ iov[0].iov_len = 1; |
|
158 |
+ memset(&msg, 0, sizeof(msg)); |
|
159 |
+ msg.msg_control = fdbuf; |
|
160 |
+ msg.msg_iov = iov; |
|
161 |
+ msg.msg_iovlen = 1; |
|
162 |
+ msg.msg_controllen = CMSG_LEN(sizeof(int)); |
|
163 |
+ cmsg = CMSG_FIRSTHDR(&msg); |
|
164 |
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int)); |
|
165 |
+ cmsg->cmsg_level = SOL_SOCKET; |
|
166 |
+ cmsg->cmsg_type = SCM_RIGHTS; |
|
167 |
+ *(int *)CMSG_DATA(cmsg) = fd; |
|
168 |
+ if (onas_sendln(curl, &msg, 0, timeout) == -1) { |
|
169 |
+ logg("!FD send failed: %s\n", strerror(errno)); |
|
170 |
+ ret = -1; |
|
171 |
+ goto fd_out; |
|
172 |
+ } |
|
172 | 173 |
fd_out: |
173 |
- if (close_flag) { |
|
174 |
- close(fd); |
|
175 |
- } |
|
176 |
- return ret; |
|
174 |
+ if (close_flag) { |
|
175 |
+ close(fd); |
|
176 |
+ } |
|
177 |
+ return ret; |
|
177 | 178 |
} |
178 | 179 |
#endif |
179 | 180 |
|
... | ... |
@@ -181,220 +182,219 @@ fd_out: |
181 | 181 |
* This is used only in non IDSESSION mode |
182 | 182 |
* Returns the number of infected files or -1 on error |
183 | 183 |
* NOTE: filename may be NULL for STREAM scantype. */ |
184 |
-int onas_dsresult(CURL *curl, int scantype, uint64_t maxstream, const char *filename, int fd, int64_t timeout, int *printok, int *errors, cl_error_t *ret_code) { |
|
185 |
- int infected = 0, len = 0, beenthere = 0; |
|
186 |
- char *bol, *eol; |
|
187 |
- struct RCVLN rcv; |
|
188 |
- STATBUF sb; |
|
189 |
- |
|
190 |
- onas_recvlninit(&rcv, curl); |
|
191 |
- |
|
192 |
- if (ret_code) { |
|
193 |
- *ret_code = CL_SUCCESS; |
|
194 |
- } |
|
195 |
- |
|
196 |
- switch(scantype) { |
|
197 |
- case MULTI: |
|
198 |
- case CONT: |
|
199 |
- case ALLMATCH: |
|
200 |
- if (!filename) { |
|
201 |
- logg("Filename cannot be NULL for MULTISCAN or CONTSCAN.\n"); |
|
202 |
- if (ret_code) { |
|
203 |
- *ret_code = CL_ENULLARG; |
|
204 |
- } |
|
205 |
- return -1; |
|
206 |
- } |
|
207 |
- len = strlen(filename) + strlen(scancmd[scantype]) + 3; |
|
208 |
- if (!(bol = malloc(len))) { |
|
209 |
- logg("!Cannot allocate a command buffer: %s\n", strerror(errno)); |
|
210 |
- if (ret_code) { |
|
211 |
- *ret_code = CL_EMEM; |
|
212 |
- } |
|
213 |
- return -1; |
|
214 |
- } |
|
215 |
- sprintf(bol, "z%s %s", scancmd[scantype], filename); |
|
216 |
- if(onas_sendln(curl, bol, len, timeout)) { |
|
217 |
- if (ret_code) { |
|
218 |
- *ret_code = CL_EWRITE; |
|
219 |
- } |
|
220 |
- free(bol); |
|
221 |
- return -1; |
|
222 |
- } |
|
223 |
- free(bol); |
|
224 |
- break; |
|
225 |
- |
|
226 |
- case STREAM: |
|
227 |
- /* NULL filename safe in send_stream() */ |
|
228 |
- len = onas_send_stream(curl, filename, fd, timeout, maxstream); |
|
229 |
- break; |
|
184 |
+int onas_dsresult(CURL *curl, int scantype, uint64_t maxstream, const char *filename, int fd, int64_t timeout, int *printok, int *errors, cl_error_t *ret_code) |
|
185 |
+{ |
|
186 |
+ int infected = 0, len = 0, beenthere = 0; |
|
187 |
+ char *bol, *eol; |
|
188 |
+ struct RCVLN rcv; |
|
189 |
+ STATBUF sb; |
|
190 |
+ |
|
191 |
+ onas_recvlninit(&rcv, curl); |
|
192 |
+ |
|
193 |
+ if (ret_code) { |
|
194 |
+ *ret_code = CL_SUCCESS; |
|
195 |
+ } |
|
196 |
+ |
|
197 |
+ switch (scantype) { |
|
198 |
+ case MULTI: |
|
199 |
+ case CONT: |
|
200 |
+ case ALLMATCH: |
|
201 |
+ if (!filename) { |
|
202 |
+ logg("Filename cannot be NULL for MULTISCAN or CONTSCAN.\n"); |
|
203 |
+ if (ret_code) { |
|
204 |
+ *ret_code = CL_ENULLARG; |
|
205 |
+ } |
|
206 |
+ return -1; |
|
207 |
+ } |
|
208 |
+ len = strlen(filename) + strlen(scancmd[scantype]) + 3; |
|
209 |
+ if (!(bol = malloc(len))) { |
|
210 |
+ logg("!Cannot allocate a command buffer: %s\n", strerror(errno)); |
|
211 |
+ if (ret_code) { |
|
212 |
+ *ret_code = CL_EMEM; |
|
213 |
+ } |
|
214 |
+ return -1; |
|
215 |
+ } |
|
216 |
+ sprintf(bol, "z%s %s", scancmd[scantype], filename); |
|
217 |
+ if (onas_sendln(curl, bol, len, timeout)) { |
|
218 |
+ if (ret_code) { |
|
219 |
+ *ret_code = CL_EWRITE; |
|
220 |
+ } |
|
221 |
+ free(bol); |
|
222 |
+ return -1; |
|
223 |
+ } |
|
224 |
+ free(bol); |
|
225 |
+ break; |
|
226 |
+ |
|
227 |
+ case STREAM: |
|
228 |
+ /* NULL filename safe in send_stream() */ |
|
229 |
+ len = onas_send_stream(curl, filename, fd, timeout, maxstream); |
|
230 |
+ break; |
|
230 | 231 |
#ifdef HAVE_FD_PASSING |
231 |
- case FILDES: |
|
232 |
- /* NULL filename safe in send_fdpass() */ |
|
233 |
- len = onas_send_fdpass(curl, filename, fd, timeout); |
|
234 |
- break; |
|
232 |
+ case FILDES: |
|
233 |
+ /* NULL filename safe in send_fdpass() */ |
|
234 |
+ len = onas_send_fdpass(curl, filename, fd, timeout); |
|
235 |
+ break; |
|
235 | 236 |
#endif |
236 |
- } |
|
237 |
- |
|
238 |
- if(len <=0) { |
|
239 |
- *printok = 0; |
|
240 |
- if(errors) |
|
241 |
- (*errors)++; |
|
242 |
- return len; |
|
243 |
- } |
|
244 |
- |
|
245 |
- while((len = onas_recvln(&rcv, &bol, &eol, timeout))) { |
|
246 |
- if(len == -1) { |
|
247 |
- if (ret_code) { |
|
248 |
- *ret_code = CL_EREAD; |
|
249 |
- } |
|
250 |
- return -1; |
|
251 |
- } |
|
252 |
- beenthere = 1; |
|
253 |
- if(!filename) { |
|
254 |
- logg("~%s\n", bol); |
|
255 |
- } |
|
256 |
- if(len > 7) { |
|
257 |
- char *colon = strrchr(bol, ':'); |
|
258 |
- |
|
259 |
- if(colon && colon[1] != ' ') { |
|
260 |
- char *br; |
|
261 |
- *colon = 0; |
|
262 |
- |
|
263 |
- br = strrchr(bol, '('); |
|
264 |
- if(br) { |
|
265 |
- *br = 0; |
|
266 |
- } |
|
267 |
- colon = strrchr(bol, ':'); |
|
268 |
- } |
|
269 |
- |
|
270 |
- if(!colon) { |
|
271 |
- char * unkco = "UNKNOWN COMMAND"; |
|
272 |
- if (!strncmp(bol, unkco, sizeof(unkco) - 1)) { |
|
273 |
- logg("*clamd replied \"UNKNOWN COMMAND\". Command was %s\n", |
|
274 |
- (scantype < 0 || scantype > MAX_SCANTYPE) ? "unidentified" : |
|
275 |
- scancmd[scantype]); |
|
276 |
- } else { |
|
277 |
- logg("*Failed to parse reply: \"%s\"\n", bol); |
|
278 |
- } |
|
279 |
- |
|
280 |
- if (ret_code) { |
|
281 |
- *ret_code = CL_EPARSE; |
|
282 |
- } |
|
283 |
- return -1; |
|
284 |
- |
|
285 |
- } else if(!memcmp(eol - 7, " FOUND", 6)) { |
|
286 |
- static char last_filename[PATH_MAX+1] = {'\0'}; |
|
287 |
- *(eol - 7) = 0; |
|
288 |
- *printok = 0; |
|
289 |
- |
|
290 |
- if (scantype != ALLMATCH) { |
|
291 |
- infected++; |
|
292 |
- } else { |
|
293 |
- if (filename != NULL && strcmp(filename, last_filename)) { |
|
294 |
- infected++; |
|
295 |
- strncpy(last_filename, filename, PATH_MAX); |
|
296 |
- last_filename[PATH_MAX] = '\0'; |
|
297 |
- } |
|
298 |
- } |
|
299 |
- |
|
300 |
- if(filename) { |
|
301 |
- if(scantype >= STREAM) { |
|
302 |
- logg("~%s%s FOUND\n", filename, colon); |
|
303 |
- if(action) { |
|
304 |
- action(filename); |
|
305 |
- } |
|
306 |
- } else { |
|
307 |
- logg("~%s FOUND\n", bol); |
|
308 |
- *colon = '\0'; |
|
309 |
- if(action) { |
|
310 |
- action(bol); |
|
311 |
- } |
|
312 |
- } |
|
313 |
- } |
|
314 |
- |
|
315 |
- if (ret_code) { |
|
316 |
- *ret_code = CL_VIRUS; |
|
317 |
- } |
|
318 |
- |
|
319 |
- } else if(len > 49 && !memcmp(eol-50, " lstat() failed: No such file or directory. ERROR", 49)) { |
|
320 |
- if(errors) { |
|
321 |
- (*errors)++; |
|
322 |
- } |
|
323 |
- *printok = 0; |
|
324 |
- |
|
325 |
- if(filename) { |
|
326 |
- (scantype >= STREAM) ? logg("*%s%s\n", filename, colon) : logg("*%s\n", bol); |
|
327 |
- } |
|
328 |
- |
|
329 |
- if (ret_code) { |
|
330 |
- *ret_code = CL_ESTAT; |
|
331 |
- } |
|
332 |
- } else if(len > 41 && !memcmp(eol-42, " lstat() failed: Permission denied. ERROR", 41)) { |
|
333 |
- if(errors) { |
|
334 |
- (*errors)++; |
|
335 |
- } |
|
336 |
- *printok = 0; |
|
337 |
- |
|
338 |
- if(filename) { |
|
339 |
- (scantype >= STREAM) ? logg("*%s%s\n", filename, colon) : logg("*%s\n", bol); |
|
340 |
- } |
|
341 |
- |
|
342 |
- if (ret_code) { |
|
343 |
- *ret_code = CL_ESTAT; |
|
344 |
- } |
|
345 |
- } else if(len > 21 && !memcmp(eol-22, " Access denied. ERROR", 21)) { |
|
346 |
- if(errors) { |
|
347 |
- (*errors)++; |
|
348 |
- } |
|
349 |
- *printok = 0; |
|
350 |
- |
|
351 |
- if(filename) { |
|
352 |
- (scantype >= STREAM) ? logg("*%s%s\n", filename, colon) : logg("*%s\n", bol); |
|
353 |
- } |
|
354 |
- |
|
355 |
- if (ret_code) { |
|
356 |
- *ret_code = CL_EACCES; |
|
357 |
- } |
|
358 |
- } else if(!memcmp(eol-7, " ERROR", 6)) { |
|
359 |
- if(errors) { |
|
360 |
- (*errors)++; |
|
361 |
- } |
|
362 |
- *printok = 0; |
|
363 |
- |
|
364 |
- if(filename) { |
|
365 |
- (scantype >= STREAM) ? logg("~%s%s\n", filename, colon) : logg("~%s\n", bol); |
|
366 |
- } |
|
367 |
- |
|
368 |
- if (ret_code) { |
|
369 |
- *ret_code = CL_ESTATE; |
|
370 |
- } |
|
371 |
- } |
|
372 |
- } |
|
373 |
- } |
|
374 |
- if(!beenthere) { |
|
375 |
- if (!filename) { |
|
376 |
- logg("STDIN: noreply from clamd\n."); |
|
377 |
- if (ret_code) { |
|
378 |
- *ret_code = CL_EACCES; |
|
379 |
- } |
|
380 |
- return -1; |
|
381 |
- } |
|
382 |
- if(CLAMSTAT(filename, &sb) == -1) { |
|
383 |
- logg("~%s: stat() failed with %s, clamd may not be responding\n", |
|
384 |
- filename, strerror(errno)); |
|
385 |
- if (ret_code) { |
|
386 |
- *ret_code = CL_EACCES; |
|
387 |
- } |
|
388 |
- return -1; |
|
389 |
- } |
|
390 |
- if(!S_ISDIR(sb.st_mode)) { |
|
391 |
- logg("~%s: no reply from clamd\n", filename); |
|
392 |
- if (ret_code) { |
|
393 |
- *ret_code = CL_EACCES; |
|
394 |
- } |
|
395 |
- return -1; |
|
396 |
- } |
|
397 |
- } |
|
398 |
- return infected; |
|
399 |
-} |
|
237 |
+ } |
|
238 |
+ |
|
239 |
+ if (len <= 0) { |
|
240 |
+ *printok = 0; |
|
241 |
+ if (errors) |
|
242 |
+ (*errors)++; |
|
243 |
+ return len; |
|
244 |
+ } |
|
245 |
+ |
|
246 |
+ while ((len = onas_recvln(&rcv, &bol, &eol, timeout))) { |
|
247 |
+ if (len == -1) { |
|
248 |
+ if (ret_code) { |
|
249 |
+ *ret_code = CL_EREAD; |
|
250 |
+ } |
|
251 |
+ return -1; |
|
252 |
+ } |
|
253 |
+ beenthere = 1; |
|
254 |
+ if (!filename) { |
|
255 |
+ logg("~%s\n", bol); |
|
256 |
+ } |
|
257 |
+ if (len > 7) { |
|
258 |
+ char *colon = strrchr(bol, ':'); |
|
259 |
+ |
|
260 |
+ if (colon && colon[1] != ' ') { |
|
261 |
+ char *br; |
|
262 |
+ *colon = 0; |
|
263 |
+ |
|
264 |
+ br = strrchr(bol, '('); |
|
265 |
+ if (br) { |
|
266 |
+ *br = 0; |
|
267 |
+ } |
|
268 |
+ colon = strrchr(bol, ':'); |
|
269 |
+ } |
|
400 | 270 |
|
271 |
+ if (!colon) { |
|
272 |
+ char *unkco = "UNKNOWN COMMAND"; |
|
273 |
+ if (!strncmp(bol, unkco, sizeof(unkco) - 1)) { |
|
274 |
+ logg("*clamd replied \"UNKNOWN COMMAND\". Command was %s\n", |
|
275 |
+ (scantype < 0 || scantype > MAX_SCANTYPE) ? "unidentified" : scancmd[scantype]); |
|
276 |
+ } else { |
|
277 |
+ logg("*Failed to parse reply: \"%s\"\n", bol); |
|
278 |
+ } |
|
279 |
+ |
|
280 |
+ if (ret_code) { |
|
281 |
+ *ret_code = CL_EPARSE; |
|
282 |
+ } |
|
283 |
+ return -1; |
|
284 |
+ |
|
285 |
+ } else if (!memcmp(eol - 7, " FOUND", 6)) { |
|
286 |
+ static char last_filename[PATH_MAX + 1] = {'\0'}; |
|
287 |
+ *(eol - 7) = 0; |
|
288 |
+ *printok = 0; |
|
289 |
+ |
|
290 |
+ if (scantype != ALLMATCH) { |
|
291 |
+ infected++; |
|
292 |
+ } else { |
|
293 |
+ if (filename != NULL && strcmp(filename, last_filename)) { |
|
294 |
+ infected++; |
|
295 |
+ strncpy(last_filename, filename, PATH_MAX); |
|
296 |
+ last_filename[PATH_MAX] = '\0'; |
|
297 |
+ } |
|
298 |
+ } |
|
299 |
+ |
|
300 |
+ if (filename) { |
|
301 |
+ if (scantype >= STREAM) { |
|
302 |
+ logg("~%s%s FOUND\n", filename, colon); |
|
303 |
+ if (action) { |
|
304 |
+ action(filename); |
|
305 |
+ } |
|
306 |
+ } else { |
|
307 |
+ logg("~%s FOUND\n", bol); |
|
308 |
+ *colon = '\0'; |
|
309 |
+ if (action) { |
|
310 |
+ action(bol); |
|
311 |
+ } |
|
312 |
+ } |
|
313 |
+ } |
|
314 |
+ |
|
315 |
+ if (ret_code) { |
|
316 |
+ *ret_code = CL_VIRUS; |
|
317 |
+ } |
|
318 |
+ |
|
319 |
+ } else if (len > 49 && !memcmp(eol - 50, " lstat() failed: No such file or directory. ERROR", 49)) { |
|
320 |
+ if (errors) { |
|
321 |
+ (*errors)++; |
|
322 |
+ } |
|
323 |
+ *printok = 0; |
|
324 |
+ |
|
325 |
+ if (filename) { |
|
326 |
+ (scantype >= STREAM) ? logg("*%s%s\n", filename, colon) : logg("*%s\n", bol); |
|
327 |
+ } |
|
328 |
+ |
|
329 |
+ if (ret_code) { |
|
330 |
+ *ret_code = CL_ESTAT; |
|
331 |
+ } |
|
332 |
+ } else if (len > 41 && !memcmp(eol - 42, " lstat() failed: Permission denied. ERROR", 41)) { |
|
333 |
+ if (errors) { |
|
334 |
+ (*errors)++; |
|
335 |
+ } |
|
336 |
+ *printok = 0; |
|
337 |
+ |
|
338 |
+ if (filename) { |
|
339 |
+ (scantype >= STREAM) ? logg("*%s%s\n", filename, colon) : logg("*%s\n", bol); |
|
340 |
+ } |
|
341 |
+ |
|
342 |
+ if (ret_code) { |
|
343 |
+ *ret_code = CL_ESTAT; |
|
344 |
+ } |
|
345 |
+ } else if (len > 21 && !memcmp(eol - 22, " Access denied. ERROR", 21)) { |
|
346 |
+ if (errors) { |
|
347 |
+ (*errors)++; |
|
348 |
+ } |
|
349 |
+ *printok = 0; |
|
350 |
+ |
|
351 |
+ if (filename) { |
|
352 |
+ (scantype >= STREAM) ? logg("*%s%s\n", filename, colon) : logg("*%s\n", bol); |
|
353 |
+ } |
|
354 |
+ |
|
355 |
+ if (ret_code) { |
|
356 |
+ *ret_code = CL_EACCES; |
|
357 |
+ } |
|
358 |
+ } else if (!memcmp(eol - 7, " ERROR", 6)) { |
|
359 |
+ if (errors) { |
|
360 |
+ (*errors)++; |
|
361 |
+ } |
|
362 |
+ *printok = 0; |
|
363 |
+ |
|
364 |
+ if (filename) { |
|
365 |
+ (scantype >= STREAM) ? logg("~%s%s\n", filename, colon) : logg("~%s\n", bol); |
|
366 |
+ } |
|
367 |
+ |
|
368 |
+ if (ret_code) { |
|
369 |
+ *ret_code = CL_ESTATE; |
|
370 |
+ } |
|
371 |
+ } |
|
372 |
+ } |
|
373 |
+ } |
|
374 |
+ if (!beenthere) { |
|
375 |
+ if (!filename) { |
|
376 |
+ logg("STDIN: noreply from clamd\n."); |
|
377 |
+ if (ret_code) { |
|
378 |
+ *ret_code = CL_EACCES; |
|
379 |
+ } |
|
380 |
+ return -1; |
|
381 |
+ } |
|
382 |
+ if (CLAMSTAT(filename, &sb) == -1) { |
|
383 |
+ logg("~%s: stat() failed with %s, clamd may not be responding\n", |
|
384 |
+ filename, strerror(errno)); |
|
385 |
+ if (ret_code) { |
|
386 |
+ *ret_code = CL_EACCES; |
|
387 |
+ } |
|
388 |
+ return -1; |
|
389 |
+ } |
|
390 |
+ if (!S_ISDIR(sb.st_mode)) { |
|
391 |
+ logg("~%s: no reply from clamd\n", filename); |
|
392 |
+ if (ret_code) { |
|
393 |
+ *ret_code = CL_EACCES; |
|
394 |
+ } |
|
395 |
+ return -1; |
|
396 |
+ } |
|
397 |
+ } |
|
398 |
+ return infected; |
|
399 |
+} |
... | ... |
@@ -60,231 +60,231 @@ extern pthread_t ddd_pid; |
60 | 60 |
extern pthread_t scan_queue_pid; |
61 | 61 |
static int onas_fan_fd; |
62 | 62 |
|
63 |
-cl_error_t onas_setup_fanotif(struct onas_context **ctx) { |
|
64 |
- |
|
65 |
- const struct optstruct *pt; |
|
66 |
- short int scan; |
|
67 |
- unsigned int sizelimit = 0, extinfo; |
|
68 |
- uint64_t fan_mask = FAN_EVENT_ON_CHILD; |
|
69 |
- |
|
70 |
- pthread_attr_t ddd_attr; |
|
71 |
- struct ddd_thrarg *ddd_tharg = NULL; |
|
72 |
- |
|
73 |
- ddd_pid = 0; |
|
74 |
- |
|
75 |
- if (!ctx || !*ctx) { |
|
76 |
- logg("!ClamFanotif: unable to start clamonacc. (bad context)\n"); |
|
77 |
- return CL_EARG; |
|
78 |
- } |
|
79 |
- |
|
80 |
- onas_fan_fd = (*ctx)->fan_fd; |
|
81 |
- (*ctx)->fan_mask = fan_mask; |
|
82 |
- |
|
83 |
- if (optget((*ctx)->clamdopts, "OnAccessPrevention")->enabled && !optget((*ctx)->clamdopts, "OnAccessMountPath")->enabled) { |
|
84 |
- logg("*ClamFanotif: kernel-level blocking feature enabled ... preventing malicious files access attempts\n"); |
|
85 |
- (*ctx)->fan_mask |= FAN_ACCESS_PERM | FAN_OPEN_PERM; |
|
86 |
- } else { |
|
87 |
- logg("*ClamFanotif: kernel-level blocking feature disabled ...\n"); |
|
88 |
- if (optget((*ctx)->clamdopts, "OnAccessPrevention")->enabled && optget((*ctx)->clamdopts, "OnAccessMountPath")->enabled) { |
|
89 |
- logg("*ClamFanotif: feature not available when watching mounts ... \n"); |
|
90 |
- } |
|
91 |
- (*ctx)->fan_mask |= FAN_ACCESS | FAN_OPEN; |
|
92 |
- } |
|
93 |
- |
|
94 |
- if ((pt = optget((*ctx)->clamdopts, "OnAccessMountPath"))->enabled) { |
|
95 |
- while (pt) { |
|
96 |
- if(fanotify_mark(onas_fan_fd, FAN_MARK_ADD | FAN_MARK_MOUNT, (*ctx)->fan_mask, (*ctx)->fan_fd, pt->strarg) != 0) { |
|
97 |
- logg("!ClamFanotif: can't include mountpoint '%s'\n", pt->strarg); |
|
98 |
- return CL_EARG; |
|
99 |
- } else { |
|
100 |
- logg("*ClamFanotif: recursively watching the mount point '%s'\n", pt->strarg); |
|
101 |
- } |
|
102 |
- pt = (struct optstruct *)pt->nextarg; |
|
103 |
- } |
|
104 |
- |
|
105 |
- } else if (!optget((*ctx)->clamdopts, "OnAccessDisableDDD")->enabled) { |
|
106 |
- (*ctx)->ddd_enabled = 1; |
|
107 |
- } else { |
|
108 |
- if((pt = optget((*ctx)->clamdopts, "OnAccessIncludePath"))->enabled) { |
|
109 |
- while (pt) { |
|
110 |
- if(fanotify_mark(onas_fan_fd, FAN_MARK_ADD, (*ctx)->fan_mask, (*ctx)->fan_fd, pt->strarg) != 0) { |
|
111 |
- logg("!ClamFanotif: can't include path '%s'\n", pt->strarg); |
|
112 |
- return CL_EARG; |
|
113 |
- } else { |
|
114 |
- logg("*ClamFanotif: watching directory '%s' (non-recursively)\n", pt->strarg); |
|
115 |
- } |
|
116 |
- pt = (struct optstruct *)pt->nextarg; |
|
117 |
- } |
|
118 |
- } else { |
|
119 |
- logg("!ClamFanotif: please specify at least one path with OnAccessIncludePath\n"); |
|
120 |
- return CL_EARG; |
|
121 |
- } |
|
122 |
- } |
|
123 |
- |
|
124 |
- /* Load other options. */ |
|
125 |
- (*ctx)->sizelimit = optget((*ctx)->clamdopts, "OnAccessMaxFileSize")->numarg; |
|
126 |
- if((*ctx)->sizelimit) { |
|
127 |
- logg("*ClamFanotif: max file size limited to %lu bytes\n", (*ctx)->sizelimit); |
|
128 |
- } else { |
|
129 |
- logg("*ClamFanotif: file size limit disabled\n"); |
|
130 |
- } |
|
131 |
- |
|
132 |
- extinfo = optget((*ctx)->clamdopts, "ExtendedDetectionInfo")->enabled; |
|
133 |
- |
|
134 |
- return CL_SUCCESS; |
|
63 |
+cl_error_t onas_setup_fanotif(struct onas_context **ctx) |
|
64 |
+{ |
|
65 |
+ |
|
66 |
+ const struct optstruct *pt; |
|
67 |
+ short int scan; |
|
68 |
+ unsigned int sizelimit = 0, extinfo; |
|
69 |
+ uint64_t fan_mask = FAN_EVENT_ON_CHILD; |
|
70 |
+ |
|
71 |
+ pthread_attr_t ddd_attr; |
|
72 |
+ struct ddd_thrarg *ddd_tharg = NULL; |
|
73 |
+ |
|
74 |
+ ddd_pid = 0; |
|
75 |
+ |
|
76 |
+ if (!ctx || !*ctx) { |
|
77 |
+ logg("!ClamFanotif: unable to start clamonacc. (bad context)\n"); |
|
78 |
+ return CL_EARG; |
|
79 |
+ } |
|
80 |
+ |
|
81 |
+ onas_fan_fd = (*ctx)->fan_fd; |
|
82 |
+ (*ctx)->fan_mask = fan_mask; |
|
83 |
+ |
|
84 |
+ if (optget((*ctx)->clamdopts, "OnAccessPrevention")->enabled && !optget((*ctx)->clamdopts, "OnAccessMountPath")->enabled) { |
|
85 |
+ logg("*ClamFanotif: kernel-level blocking feature enabled ... preventing malicious files access attempts\n"); |
|
86 |
+ (*ctx)->fan_mask |= FAN_ACCESS_PERM | FAN_OPEN_PERM; |
|
87 |
+ } else { |
|
88 |
+ logg("*ClamFanotif: kernel-level blocking feature disabled ...\n"); |
|
89 |
+ if (optget((*ctx)->clamdopts, "OnAccessPrevention")->enabled && optget((*ctx)->clamdopts, "OnAccessMountPath")->enabled) { |
|
90 |
+ logg("*ClamFanotif: feature not available when watching mounts ... \n"); |
|
91 |
+ } |
|
92 |
+ (*ctx)->fan_mask |= FAN_ACCESS | FAN_OPEN; |
|
93 |
+ } |
|
94 |
+ |
|
95 |
+ if ((pt = optget((*ctx)->clamdopts, "OnAccessMountPath"))->enabled) { |
|
96 |
+ while (pt) { |
|
97 |
+ if (fanotify_mark(onas_fan_fd, FAN_MARK_ADD | FAN_MARK_MOUNT, (*ctx)->fan_mask, (*ctx)->fan_fd, pt->strarg) != 0) { |
|
98 |
+ logg("!ClamFanotif: can't include mountpoint '%s'\n", pt->strarg); |
|
99 |
+ return CL_EARG; |
|
100 |
+ } else { |
|
101 |
+ logg("*ClamFanotif: recursively watching the mount point '%s'\n", pt->strarg); |
|
102 |
+ } |
|
103 |
+ pt = (struct optstruct *)pt->nextarg; |
|
104 |
+ } |
|
105 |
+ |
|
106 |
+ } else if (!optget((*ctx)->clamdopts, "OnAccessDisableDDD")->enabled) { |
|
107 |
+ (*ctx)->ddd_enabled = 1; |
|
108 |
+ } else { |
|
109 |
+ if ((pt = optget((*ctx)->clamdopts, "OnAccessIncludePath"))->enabled) { |
|
110 |
+ while (pt) { |
|
111 |
+ if (fanotify_mark(onas_fan_fd, FAN_MARK_ADD, (*ctx)->fan_mask, (*ctx)->fan_fd, pt->strarg) != 0) { |
|
112 |
+ logg("!ClamFanotif: can't include path '%s'\n", pt->strarg); |
|
113 |
+ return CL_EARG; |
|
114 |
+ } else { |
|
115 |
+ logg("*ClamFanotif: watching directory '%s' (non-recursively)\n", pt->strarg); |
|
116 |
+ } |
|
117 |
+ pt = (struct optstruct *)pt->nextarg; |
|
118 |
+ } |
|
119 |
+ } else { |
|
120 |
+ logg("!ClamFanotif: please specify at least one path with OnAccessIncludePath\n"); |
|
121 |
+ return CL_EARG; |
|
122 |
+ } |
|
123 |
+ } |
|
124 |
+ |
|
125 |
+ /* Load other options. */ |
|
126 |
+ (*ctx)->sizelimit = optget((*ctx)->clamdopts, "OnAccessMaxFileSize")->numarg; |
|
127 |
+ if ((*ctx)->sizelimit) { |
|
128 |
+ logg("*ClamFanotif: max file size limited to %lu bytes\n", (*ctx)->sizelimit); |
|
129 |
+ } else { |
|
130 |
+ logg("*ClamFanotif: file size limit disabled\n"); |
|
131 |
+ } |
|
132 |
+ |
|
133 |
+ extinfo = optget((*ctx)->clamdopts, "ExtendedDetectionInfo")->enabled; |
|
134 |
+ |
|
135 |
+ return CL_SUCCESS; |
|
135 | 136 |
} |
136 | 137 |
|
137 |
-int onas_fan_eloop(struct onas_context **ctx) { |
|
138 |
- int ret = 0; |
|
139 |
- int err_cnt = 0; |
|
140 |
- short int scan; |
|
141 |
- STATBUF sb; |
|
142 |
- fd_set rfds; |
|
143 |
- char buf[4096]; |
|
144 |
- ssize_t bread; |
|
145 |
- struct fanotify_event_metadata *fmd; |
|
146 |
- char fname[1024]; |
|
147 |
- int len, check, fres; |
|
148 |
- char err[128]; |
|
149 |
- |
|
150 |
- FD_ZERO(&rfds); |
|
151 |
- FD_SET((*ctx)->fan_fd, &rfds); |
|
152 |
- |
|
153 |
- logg("*ClamFanotif: starting fanotify event loop with process id (%d) ... \n", getpid()); |
|
154 |
- do { |
|
155 |
- ret = select((*ctx)->fan_fd + 1, &rfds, NULL, NULL, NULL); |
|
156 |
- } while((ret == -1 && errno == EINTR)); |
|
157 |
- |
|
158 |
- time_t start = time(NULL) - 30; |
|
159 |
- while(((bread = read((*ctx)->fan_fd, buf, sizeof(buf))) > 0) || (errno == EOVERFLOW || errno == EMFILE || errno == EACCES)) { |
|
160 |
- switch(errno) { |
|
161 |
- case EOVERFLOW: |
|
162 |
- if (time(NULL) - start >= 30) { |
|
163 |
- logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); |
|
164 |
- logg("*ClamFanotif: file too large for fanotify ... recovering and continuing scans...\n"); |
|
165 |
- start = time(NULL); |
|
166 |
- } |
|
167 |
- |
|
168 |
- errno = 0; |
|
169 |
- continue; |
|
170 |
- case EACCES: |
|
171 |
- logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); |
|
172 |
- logg("*ClamFanotif: check your SELinux audit logs and consider adding an exception \ |
|
138 |
+int onas_fan_eloop(struct onas_context **ctx) |
|
139 |
+{ |
|
140 |
+ int ret = 0; |
|
141 |
+ int err_cnt = 0; |
|
142 |
+ short int scan; |
|
143 |
+ STATBUF sb; |
|
144 |
+ fd_set rfds; |
|
145 |
+ char buf[4096]; |
|
146 |
+ ssize_t bread; |
|
147 |
+ struct fanotify_event_metadata *fmd; |
|
148 |
+ char fname[1024]; |
|
149 |
+ int len, check, fres; |
|
150 |
+ char err[128]; |
|
151 |
+ |
|
152 |
+ FD_ZERO(&rfds); |
|
153 |
+ FD_SET((*ctx)->fan_fd, &rfds); |
|
154 |
+ |
|
155 |
+ logg("*ClamFanotif: starting fanotify event loop with process id (%d) ... \n", getpid()); |
|
156 |
+ do { |
|
157 |
+ ret = select((*ctx)->fan_fd + 1, &rfds, NULL, NULL, NULL); |
|
158 |
+ } while ((ret == -1 && errno == EINTR)); |
|
159 |
+ |
|
160 |
+ time_t start = time(NULL) - 30; |
|
161 |
+ while (((bread = read((*ctx)->fan_fd, buf, sizeof(buf))) > 0) || (errno == EOVERFLOW || errno == EMFILE || errno == EACCES)) { |
|
162 |
+ switch (errno) { |
|
163 |
+ case EOVERFLOW: |
|
164 |
+ if (time(NULL) - start >= 30) { |
|
165 |
+ logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); |
|
166 |
+ logg("*ClamFanotif: file too large for fanotify ... recovering and continuing scans...\n"); |
|
167 |
+ start = time(NULL); |
|
168 |
+ } |
|
169 |
+ |
|
170 |
+ errno = 0; |
|
171 |
+ continue; |
|
172 |
+ case EACCES: |
|
173 |
+ logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); |
|
174 |
+ logg("*ClamFanotif: check your SELinux audit logs and consider adding an exception \ |
|
173 | 175 |
... recovering and continuing scans...\n"); |
174 | 176 |
|
175 |
- errno = 0; |
|
176 |
- continue; |
|
177 |
- case EMFILE: |
|
178 |
- logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); |
|
179 |
- logg("*ClamFanotif: waiting for consumer thread to catch up then retrying ...\n"); |
|
180 |
- sleep(3); |
|
181 |
- |
|
182 |
- errno = 0; |
|
183 |
- continue; |
|
184 |
- default: |
|
185 |
- break; |
|
186 |
- } |
|
187 |
- |
|
188 |
- fmd = (struct fanotify_event_metadata *)buf; |
|
189 |
- while (FAN_EVENT_OK(fmd, bread)) { |
|
190 |
- scan = 1; |
|
191 |
- if (fmd->fd >= 0) { |
|
192 |
- sprintf(fname, "/proc/self/fd/%d", fmd->fd); |
|
193 |
- errno = 0; |
|
194 |
- len = readlink(fname, fname, sizeof(fname) - 1); |
|
195 |
- if (len == -1) { |
|
196 |
- close(fmd->fd); |
|
197 |
- logg("!ClamFanotif: internal error (readlink() failed), %d, %s\n", fmd->fd, strerror(errno)); |
|
198 |
- if (errno == EBADF) { |
|
199 |
- logg("ClamWorker: fd already closed ... recovering ...\n"); |
|
200 |
- continue; |
|
201 |
- } else { |
|
202 |
- return 2; |
|
203 |
- } |
|
204 |
- } |
|
205 |
- fname[len] = '\0'; |
|
206 |
- |
|
207 |
- if((check = onas_fan_checkowner(fmd->pid, (*ctx)->clamdopts))) { |
|
208 |
- scan = 0; |
|
209 |
- if (check != CHK_SELF) { |
|
210 |
- logg("*ClamFanotif: %s skipped (excluded UID)\n", fname); |
|
211 |
- } |
|
212 |
- } |
|
213 |
- |
|
214 |
- if (scan) { |
|
215 |
- struct onas_scan_event *event_data; |
|
216 |
- |
|
217 |
- event_data = cli_calloc(1, sizeof(struct onas_scan_event)); |
|
218 |
- if (NULL == event_data) { |
|
219 |
- logg("!ClamFanotif: could not allocate memory for event data struct\n"); |
|
220 |
- return 2; |
|
221 |
- } |
|
222 |
- |
|
223 |
- /* general mapping */ |
|
224 |
- onas_map_context_info_to_event_data(*ctx, &event_data); |
|
225 |
- scan ? event_data->bool_opts |= ONAS_SCTH_B_SCAN : scan; |
|
226 |
- |
|
227 |
- /* fanotify specific stuffs */ |
|
228 |
- event_data->bool_opts |= ONAS_SCTH_B_FANOTIFY; |
|
229 |
- event_data->fmd = cli_malloc(sizeof(struct fanotify_event_metadata)); |
|
230 |
- if (NULL == event_data->fmd) { |
|
231 |
- logg("!ClamFanotif: could not allocate memory for event data struct fmd\n"); |
|
232 |
- return 2; |
|
233 |
- } |
|
234 |
- memcpy(event_data->fmd, fmd, sizeof(struct fanotify_event_metadata)); |
|
235 |
- event_data->pathname = cli_strdup(fname); |
|
236 |
- |
|
237 |
- |
|
238 |
- logg("*ClamFanotif: attempting to feed consumer queue\n"); |
|
239 |
- /* feed consumer queue */ |
|
240 |
- if (CL_SUCCESS != onas_queue_event(event_data)) { |
|
241 |
- close(fmd->fd); |
|
242 |
- logg("!ClamFanotif: error occurred while feeding consumer queue ... \n"); |
|
243 |
- if ((*ctx)->retry_on_error) { |
|
244 |
- err_cnt++; |
|
245 |
- if (err_cnt < (*ctx)->retry_attempts) { |
|
246 |
- logg("ClamFanotif: ... recovering ...\n"); |
|
247 |
- continue; |
|
248 |
- } |
|
249 |
- } |
|
250 |
- return 2; |
|
251 |
- } |
|
252 |
- } else { |
|
253 |
- if (fmd->mask & FAN_ALL_PERM_EVENTS) { |
|
254 |
- struct fanotify_response res; |
|
255 |
- |
|
256 |
- res.fd = fmd->fd; |
|
257 |
- res.response = FAN_ALLOW; |
|
258 |
- |
|
259 |
- if (-1 == write((*ctx)->fan_fd, &res, sizeof(res))) { |
|
260 |
- logg("!ClamFanotif: error occurred while excluding event\n"); |
|
261 |
- return 2; |
|
262 |
- } |
|
263 |
- } |
|
264 |
- |
|
265 |
- if (-1 == close(fmd->fd)) { |
|
266 |
- logg("!ClamFanotif: error occurred while closing metadata fd, %d\n", fmd->fd); |
|
267 |
- if (errno == EBADF) { |
|
268 |
- logg("ClamFanotif: fd already closed ... recovering ...\n"); |
|
269 |
- } else { |
|
270 |
- return 2; |
|
271 |
- } |
|
272 |
- } |
|
273 |
- } |
|
274 |
- } |
|
275 |
- fmd = FAN_EVENT_NEXT(fmd, bread); |
|
276 |
- } |
|
277 |
- do { |
|
278 |
- ret = select((*ctx)->fan_fd + 1, &rfds, NULL, NULL, NULL); |
|
279 |
- } while((ret == -1 && errno == EINTR)); |
|
280 |
- } |
|
281 |
- |
|
282 |
- if(bread < 0) { |
|
283 |
- logg("!ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); |
|
284 |
- return 2; |
|
285 |
- } |
|
286 |
- |
|
287 |
- |
|
288 |
- return ret; |
|
177 |
+ errno = 0; |
|
178 |
+ continue; |
|
179 |
+ case EMFILE: |
|
180 |
+ logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); |
|
181 |
+ logg("*ClamFanotif: waiting for consumer thread to catch up then retrying ...\n"); |
|
182 |
+ sleep(3); |
|
183 |
+ |
|
184 |
+ errno = 0; |
|
185 |
+ continue; |
|
186 |
+ default: |
|
187 |
+ break; |
|
188 |
+ } |
|
189 |
+ |
|
190 |
+ fmd = (struct fanotify_event_metadata *)buf; |
|
191 |
+ while (FAN_EVENT_OK(fmd, bread)) { |
|
192 |
+ scan = 1; |
|
193 |
+ if (fmd->fd >= 0) { |
|
194 |
+ sprintf(fname, "/proc/self/fd/%d", fmd->fd); |
|
195 |
+ errno = 0; |
|
196 |
+ len = readlink(fname, fname, sizeof(fname) - 1); |
|
197 |
+ if (len == -1) { |
|
198 |
+ close(fmd->fd); |
|
199 |
+ logg("!ClamFanotif: internal error (readlink() failed), %d, %s\n", fmd->fd, strerror(errno)); |
|
200 |
+ if (errno == EBADF) { |
|
201 |
+ logg("ClamWorker: fd already closed ... recovering ...\n"); |
|
202 |
+ continue; |
|
203 |
+ } else { |
|
204 |
+ return 2; |
|
205 |
+ } |
|
206 |
+ } |
|
207 |
+ fname[len] = '\0'; |
|
208 |
+ |
|
209 |
+ if ((check = onas_fan_checkowner(fmd->pid, (*ctx)->clamdopts))) { |
|
210 |
+ scan = 0; |
|
211 |
+ if (check != CHK_SELF) { |
|
212 |
+ logg("*ClamFanotif: %s skipped (excluded UID)\n", fname); |
|
213 |
+ } |
|
214 |
+ } |
|
215 |
+ |
|
216 |
+ if (scan) { |
|
217 |
+ struct onas_scan_event *event_data; |
|
218 |
+ |
|
219 |
+ event_data = cli_calloc(1, sizeof(struct onas_scan_event)); |
|
220 |
+ if (NULL == event_data) { |
|
221 |
+ logg("!ClamFanotif: could not allocate memory for event data struct\n"); |
|
222 |
+ return 2; |
|
223 |
+ } |
|
224 |
+ |
|
225 |
+ /* general mapping */ |
|
226 |
+ onas_map_context_info_to_event_data(*ctx, &event_data); |
|
227 |
+ scan ? event_data->bool_opts |= ONAS_SCTH_B_SCAN : scan; |
|
228 |
+ |
|
229 |
+ /* fanotify specific stuffs */ |
|
230 |
+ event_data->bool_opts |= ONAS_SCTH_B_FANOTIFY; |
|
231 |
+ event_data->fmd = cli_malloc(sizeof(struct fanotify_event_metadata)); |
|
232 |
+ if (NULL == event_data->fmd) { |
|
233 |
+ logg("!ClamFanotif: could not allocate memory for event data struct fmd\n"); |
|
234 |
+ return 2; |
|
235 |
+ } |
|
236 |
+ memcpy(event_data->fmd, fmd, sizeof(struct fanotify_event_metadata)); |
|
237 |
+ event_data->pathname = cli_strdup(fname); |
|
238 |
+ |
|
239 |
+ logg("*ClamFanotif: attempting to feed consumer queue\n"); |
|
240 |
+ /* feed consumer queue */ |
|
241 |
+ if (CL_SUCCESS != onas_queue_event(event_data)) { |
|
242 |
+ close(fmd->fd); |
|
243 |
+ logg("!ClamFanotif: error occurred while feeding consumer queue ... \n"); |
|
244 |
+ if ((*ctx)->retry_on_error) { |
|
245 |
+ err_cnt++; |
|
246 |
+ if (err_cnt < (*ctx)->retry_attempts) { |
|
247 |
+ logg("ClamFanotif: ... recovering ...\n"); |
|
248 |
+ continue; |
|
249 |
+ } |
|
250 |
+ } |
|
251 |
+ return 2; |
|
252 |
+ } |
|
253 |
+ } else { |
|
254 |
+ if (fmd->mask & FAN_ALL_PERM_EVENTS) { |
|
255 |
+ struct fanotify_response res; |
|
256 |
+ |
|
257 |
+ res.fd = fmd->fd; |
|
258 |
+ res.response = FAN_ALLOW; |
|
259 |
+ |
|
260 |
+ if (-1 == write((*ctx)->fan_fd, &res, sizeof(res))) { |
|
261 |
+ logg("!ClamFanotif: error occurred while excluding event\n"); |
|
262 |
+ return 2; |
|
263 |
+ } |
|
264 |
+ } |
|
265 |
+ |
|
266 |
+ if (-1 == close(fmd->fd)) { |
|
267 |
+ logg("!ClamFanotif: error occurred while closing metadata fd, %d\n", fmd->fd); |
|
268 |
+ if (errno == EBADF) { |
|
269 |
+ logg("ClamFanotif: fd already closed ... recovering ...\n"); |
|
270 |
+ } else { |
|
271 |
+ return 2; |
|
272 |
+ } |
|
273 |
+ } |
|
274 |
+ } |
|
275 |
+ } |
|
276 |
+ fmd = FAN_EVENT_NEXT(fmd, bread); |
|
277 |
+ } |
|
278 |
+ do { |
|
279 |
+ ret = select((*ctx)->fan_fd + 1, &rfds, NULL, NULL, NULL); |
|
280 |
+ } while ((ret == -1 && errno == EINTR)); |
|
281 |
+ } |
|
282 |
+ |
|
283 |
+ if (bread < 0) { |
|
284 |
+ logg("!ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); |
|
285 |
+ return 2; |
|
286 |
+ } |
|
287 |
+ |
|
288 |
+ return ret; |
|
289 | 289 |
} |
290 | 290 |
#endif |
... | ... |
@@ -33,7 +33,6 @@ |
33 | 33 |
#include <errno.h> |
34 | 34 |
#include <stdbool.h> |
35 | 35 |
|
36 |
- |
|
37 | 36 |
#if defined(FANOTIFY) |
38 | 37 |
#include <sys/fanotify.h> |
39 | 38 |
#endif |
... | ... |
@@ -55,7 +54,6 @@ |
55 | 55 |
#include "clamd/scanner.h" |
56 | 56 |
#include "../misc/priv_fts.h" |
57 | 57 |
|
58 |
- |
|
59 | 58 |
#if defined(FANOTIFY) |
60 | 59 |
|
61 | 60 |
static struct onas_bucket *onas_bucket_init(); |
... | ... |
@@ -671,7 +669,7 @@ int onas_ht_add_hierarchy(struct onas_ht *ht, const char *pathname) |
671 | 671 |
{ |
672 | 672 |
if (!ht || !pathname) return CL_ENULLARG; |
673 | 673 |
|
674 |
- int ret = 0; |
|
674 |
+ int ret = 0; |
|
675 | 675 |
FTS *ftsp = NULL; |
676 | 676 |
int ftspopts = FTS_PHYSICAL | FTS_XDEV; |
677 | 677 |
FTSENT *curr = NULL; |
... | ... |
@@ -684,9 +682,9 @@ int onas_ht_add_hierarchy(struct onas_ht *ht, const char *pathname) |
684 | 684 |
|
685 | 685 |
char *const pathargv[] = {(char *)pathname, NULL}; |
686 | 686 |
if (!(ftsp = _priv_fts_open(pathargv, ftspopts, NULL))) { |
687 |
- logg("!ClamHash: could not open '%s'\n", pathname); |
|
688 |
- ret = CL_EARG; |
|
689 |
- goto out; |
|
687 |
+ logg("!ClamHash: could not open '%s'\n", pathname); |
|
688 |
+ ret = CL_EARG; |
|
689 |
+ goto out; |
|
690 | 690 |
} |
691 | 691 |
|
692 | 692 |
while ((curr = _priv_fts_read(ftsp))) { |
... | ... |
@@ -728,26 +726,26 @@ int onas_ht_add_hierarchy(struct onas_ht *ht, const char *pathname) |
728 | 728 |
} |
729 | 729 |
|
730 | 730 |
struct onas_element *elem = onas_element_init(hnode, hnode->pathname, hnode->pathlen); |
731 |
- if (!elem) { |
|
732 |
- ret = CL_EMEM; |
|
733 |
- goto out; |
|
734 |
- } |
|
731 |
+ if (!elem) { |
|
732 |
+ ret = CL_EMEM; |
|
733 |
+ goto out; |
|
734 |
+ } |
|
735 | 735 |
|
736 | 736 |
if (onas_ht_insert(ht, elem)) { |
737 | 737 |
|
738 |
- ret = -1; |
|
739 |
- goto out; |
|
738 |
+ ret = -1; |
|
739 |
+ goto out; |
|
740 | 740 |
} |
741 | 741 |
} |
742 | 742 |
|
743 | 743 |
out: |
744 |
- if (ftsp) { |
|
745 |
- _priv_fts_close(ftsp); |
|
746 |
- } |
|
744 |
+ if (ftsp) { |
|
745 |
+ _priv_fts_close(ftsp); |
|
746 |
+ } |
|
747 | 747 |
|
748 |
- if (ret) { |
|
749 |
- return ret; |
|
750 |
- } |
|
748 |
+ if (ret) { |
|
749 |
+ return ret; |
|
750 |
+ } |
|
751 | 751 |
|
752 | 752 |
return CL_SUCCESS; |
753 | 753 |
} |
... | ... |
@@ -22,7 +22,6 @@ |
22 | 22 |
#include "clamav-config.h" |
23 | 23 |
#endif |
24 | 24 |
|
25 |
- |
|
26 | 25 |
#include <stdio.h> |
27 | 26 |
#include <stdlib.h> |
28 | 27 |
#include <unistd.h> |
... | ... |
@@ -59,7 +58,6 @@ |
59 | 59 |
#include "clamd/others.h" |
60 | 60 |
#include "clamd/scanner.h" |
61 | 61 |
|
62 |
- |
|
63 | 62 |
#if defined(FANOTIFY) |
64 | 63 |
|
65 | 64 |
static int onas_ddd_init_ht(uint32_t ht_size); |
... | ... |
@@ -329,447 +327,447 @@ static int onas_ddd_unwatch_hierarchy(const char *pathname, size_t len, int fd, |
329 | 329 |
return CL_SUCCESS; |
330 | 330 |
} |
331 | 331 |
|
332 |
-cl_error_t onas_enable_inotif_ddd(struct onas_context **ctx) { |
|
333 |
- |
|
334 |
- pthread_attr_t ddd_attr; |
|
335 |
- int32_t thread_started = 1; |
|
332 |
+cl_error_t onas_enable_inotif_ddd(struct onas_context **ctx) |
|
333 |
+{ |
|
336 | 334 |
|
337 |
- if (!ctx || !*ctx) { |
|
338 |
- logg("!ClamInotif: unable to start clamonacc. (bad context)\n"); |
|
339 |
- return CL_EARG; |
|
340 |
- } |
|
335 |
+ pthread_attr_t ddd_attr; |
|
336 |
+ int32_t thread_started = 1; |
|
341 | 337 |
|
342 |
- if ((*ctx)->ddd_enabled) { |
|
343 |
- do { |
|
344 |
- if(pthread_attr_init(&ddd_attr)) break; |
|
345 |
- pthread_attr_setdetachstate(&ddd_attr, PTHREAD_CREATE_JOINABLE); |
|
346 |
- thread_started = pthread_create(&ddd_pid, &ddd_attr, onas_ddd_th, *ctx); |
|
347 |
- } while(0); |
|
338 |
+ if (!ctx || !*ctx) { |
|
339 |
+ logg("!ClamInotif: unable to start clamonacc. (bad context)\n"); |
|
340 |
+ return CL_EARG; |
|
341 |
+ } |
|
348 | 342 |
|
349 |
- } |
|
343 |
+ if ((*ctx)->ddd_enabled) { |
|
344 |
+ do { |
|
345 |
+ if (pthread_attr_init(&ddd_attr)) break; |
|
346 |
+ pthread_attr_setdetachstate(&ddd_attr, PTHREAD_CREATE_JOINABLE); |
|
347 |
+ thread_started = pthread_create(&ddd_pid, &ddd_attr, onas_ddd_th, *ctx); |
|
348 |
+ } while (0); |
|
349 |
+ } |
|
350 | 350 |
|
351 |
- if (0 != thread_started) { |
|
352 |
- /* Failed to create thread */ |
|
353 |
- logg("!ClamInotif: Unable to start dynamic directory determination ... \n"); |
|
354 |
- return CL_ECREAT; |
|
355 |
- } |
|
351 |
+ if (0 != thread_started) { |
|
352 |
+ /* Failed to create thread */ |
|
353 |
+ logg("!ClamInotif: Unable to start dynamic directory determination ... \n"); |
|
354 |
+ return CL_ECREAT; |
|
355 |
+ } |
|
356 | 356 |
|
357 |
- return CL_SUCCESS; |
|
357 |
+ return CL_SUCCESS; |
|
358 | 358 |
} |
359 | 359 |
|
360 |
-void *onas_ddd_th(void *arg) { |
|
361 |
- struct onas_context *ctx = (struct onas_context *) arg; |
|
362 |
- sigset_t sigset; |
|
363 |
- struct sigaction act; |
|
364 |
- const struct optstruct *pt; |
|
365 |
- uint64_t in_mask = IN_ONLYDIR | IN_MOVE | IN_DELETE | IN_CREATE; |
|
366 |
- fd_set rfds; |
|
367 |
- char buf[4096]; |
|
368 |
- ssize_t bread; |
|
369 |
- const struct inotify_event *event; |
|
370 |
- int ret, len, idx; |
|
371 |
- |
|
372 |
- char** include_list = NULL; |
|
373 |
- char** exclude_list = NULL; |
|
374 |
- int num_exdirs, num_indirs; |
|
375 |
- cl_error_t err; |
|
376 |
- |
|
377 |
- /* ignore all signals */ |
|
378 |
- sigfillset(&sigset); |
|
379 |
- sigdelset(&sigset, SIGUSR1); |
|
380 |
- sigdelset(&sigset, SIGUSR2); |
|
381 |
- /* The behavior of a process is undefined after it ignores a |
|
360 |
+void *onas_ddd_th(void *arg) |
|
361 |
+{ |
|
362 |
+ struct onas_context *ctx = (struct onas_context *)arg; |
|
363 |
+ sigset_t sigset; |
|
364 |
+ struct sigaction act; |
|
365 |
+ const struct optstruct *pt; |
|
366 |
+ uint64_t in_mask = IN_ONLYDIR | IN_MOVE | IN_DELETE | IN_CREATE; |
|
367 |
+ fd_set rfds; |
|
368 |
+ char buf[4096]; |
|
369 |
+ ssize_t bread; |
|
370 |
+ const struct inotify_event *event; |
|
371 |
+ int ret, len, idx; |
|
372 |
+ |
|
373 |
+ char **include_list = NULL; |
|
374 |
+ char **exclude_list = NULL; |
|
375 |
+ int num_exdirs, num_indirs; |
|
376 |
+ cl_error_t err; |
|
377 |
+ |
|
378 |
+ /* ignore all signals */ |
|
379 |
+ sigfillset(&sigset); |
|
380 |
+ sigdelset(&sigset, SIGUSR1); |
|
381 |
+ sigdelset(&sigset, SIGUSR2); |
|
382 |
+ /* The behavior of a process is undefined after it ignores a |
|
382 | 383 |
* SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ |
383 |
- sigdelset(&sigset, SIGFPE); |
|
384 |
- sigdelset(&sigset, SIGILL); |
|
385 |
- sigdelset(&sigset, SIGTERM); |
|
386 |
- sigdelset(&sigset, SIGINT); |
|
384 |
+ sigdelset(&sigset, SIGFPE); |
|
385 |
+ sigdelset(&sigset, SIGILL); |
|
386 |
+ sigdelset(&sigset, SIGTERM); |
|
387 |
+ sigdelset(&sigset, SIGINT); |
|
387 | 388 |
#ifdef SIGBUS |
388 |
- sigdelset(&sigset, SIGBUS); |
|
389 |
+ sigdelset(&sigset, SIGBUS); |
|
389 | 390 |
#endif |
390 | 391 |
|
391 |
- logg("*ClamInotif: starting inotify event loop ...\n"); |
|
392 |
- |
|
393 |
- onas_in_fd = inotify_init1(IN_NONBLOCK); |
|
394 |
- if (onas_in_fd == -1) { |
|
395 |
- logg("!ClamInotif: could not init inotify\n"); |
|
396 |
- return NULL; |
|
397 |
- } |
|
398 |
- |
|
399 |
- ret = onas_ddd_init(0, ONAS_DEFAULT_HT_SIZE); |
|
400 |
- if (ret) { |
|
401 |
- logg("!ClamInotif: failed to initialize DDD system\n"); |
|
402 |
- return NULL; |
|
403 |
- } |
|
404 |
- |
|
405 |
- |
|
406 |
- logg("*ClamInotif: dynamically determining directory hierarchy...\n"); |
|
407 |
- /* Add provided paths recursively. */ |
|
408 |
- |
|
409 |
- if (!optget(ctx->opts, "watch-list")->enabled && !optget(ctx->clamdopts, "OnAccessIncludePath")->enabled) { |
|
410 |
- logg("!ClamInotif: Please specify at least one path with OnAccessIncludePath\n"); |
|
411 |
- return NULL; |
|
412 |
- } |
|
413 |
- |
|
414 |
- if((pt = optget(ctx->clamdopts, "OnAccessIncludePath"))->enabled) { |
|
415 |
- |
|
416 |
- while (pt) { |
|
417 |
- if (!strcmp(pt->strarg, "/")) { |
|
418 |
- logg("!ClamInotif: not including path '%s' while DDD is enabled\n", pt->strarg); |
|
419 |
- logg("!ClamInotif: please use the OnAccessMountPath option to watch '%s'\n", pt->strarg); |
|
420 |
- pt = (struct optstruct *)pt->nextarg; |
|
421 |
- continue; |
|
422 |
- } |
|
423 |
- if (onas_ht_get(ddd_ht, pt->strarg, strlen(pt->strarg), NULL) != CL_SUCCESS) { |
|
424 |
- if (onas_ht_add_hierarchy(ddd_ht, pt->strarg)) { |
|
425 |
- logg("!ClamInotif: can't include '%s'\n", pt->strarg); |
|
426 |
- return NULL; |
|
427 |
- } else { |
|
428 |
- logg("ClamInotif: watching '%s' (and all sub-directories)\n", pt->strarg); |
|
429 |
- } |
|
430 |
- } |
|
431 |
- |
|
432 |
- pt = (struct optstruct *)pt->nextarg; |
|
433 |
- } |
|
434 |
- } |
|
435 |
- |
|
436 |
- if((pt = optget(ctx->opts, "watch-list"))->enabled) { |
|
437 |
- |
|
438 |
- num_indirs = 0; |
|
439 |
- err = CL_SUCCESS; |
|
440 |
- |
|
441 |
- include_list = onas_get_opt_list(pt->strarg, &num_indirs, &err); |
|
442 |
- if (NULL == include_list) { |
|
443 |
- logg("!ClamInotif: could not parse include list (%d)\n", err); |
|
444 |
- return NULL; |
|
445 |
- } |
|
446 |
- |
|
447 |
- idx = 0; |
|
448 |
- while (NULL != include_list[idx]) { |
|
449 |
- if(onas_ht_get(ddd_ht, include_list[idx], strlen(include_list[idx]), NULL) != CL_SUCCESS) { |
|
450 |
- if(onas_ht_add_hierarchy(ddd_ht, include_list[idx])) { |
|
451 |
- logg("!ClamInotif: can't include '%s'\n", include_list[idx]); |
|
452 |
- return NULL; |
|
453 |
- } else { |
|
454 |
- logg("ClamInotif: watching '%s' (and all sub-directories)\n", include_list[idx]); |
|
455 |
- } |
|
456 |
- } |
|
457 |
- |
|
458 |
- |
|
459 |
- idx++; |
|
460 |
- } |
|
461 |
- } |
|
462 |
- |
|
463 |
- /* Remove provided paths recursively. */ |
|
464 |
- if((pt = optget(ctx->clamdopts, "OnAccessExcludePath"))->enabled) { |
|
465 |
- while (pt) { |
|
466 |
- size_t ptlen = strlen(pt->strarg); |
|
467 |
- if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) { |
|
468 |
- if (onas_ht_rm_hierarchy(ddd_ht, pt->strarg, ptlen, 0)) { |
|
469 |
- logg("!ClamInotif: can't exclude '%s'\n", pt->strarg); |
|
470 |
- return NULL; |
|
471 |
- } else |
|
472 |
- logg("ClamInotif: excluding '%s' (and all sub-directories)\n", pt->strarg); |
|
473 |
- } |
|
474 |
- |
|
475 |
- pt = (struct optstruct *)pt->nextarg; |
|
476 |
- } |
|
477 |
- } |
|
478 |
- |
|
479 |
- if((pt = optget(ctx->opts, "exclude-list"))->enabled) { |
|
480 |
- |
|
481 |
- num_exdirs = 0; |
|
482 |
- err = CL_SUCCESS; |
|
483 |
- |
|
484 |
- exclude_list = onas_get_opt_list(pt->strarg, &num_exdirs, &err); |
|
485 |
- if (NULL == exclude_list) { |
|
486 |
- logg("!ClamInotif: could not parse exclude list (%d)\n", err); |
|
487 |
- return NULL; |
|
488 |
- } |
|
489 |
- |
|
490 |
- idx = 0; |
|
491 |
- while (exclude_list[idx] != NULL) { |
|
492 |
- if(onas_ht_get(ddd_ht, exclude_list[idx], strlen(exclude_list[idx]), NULL) == CL_SUCCESS) { |
|
493 |
- if(onas_ht_rm_hierarchy(ddd_ht, exclude_list[idx], strlen(exclude_list[idx]), 0)){ |
|
494 |
- logg("!ClamInotif: can't exclude '%s'\n", exclude_list[idx]); |
|
495 |
- return NULL; |
|
496 |
- } else { |
|
497 |
- logg("ClamInotif: excluding '%s' (and all sub-directories)\n", exclude_list[idx]); |
|
498 |
- } |
|
499 |
- } |
|
500 |
- |
|
501 |
- idx++; |
|
502 |
- } |
|
503 |
- } |
|
504 |
- |
|
505 |
- /* Watch provided paths recursively */ |
|
506 |
- if((pt = optget(ctx->clamdopts, "OnAccessIncludePath"))->enabled) { |
|
507 |
- while (pt) { |
|
508 |
- errno = 0; |
|
509 |
- size_t ptlen = strlen(pt->strarg); |
|
510 |
- if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) { |
|
511 |
- if(err = onas_ddd_watch(pt->strarg, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask)) { |
|
512 |
- |
|
513 |
- if (0 == errno) { |
|
514 |
- logg("!ClamInotif: could not watch path '%s', %d\n ", pt->strarg, err); |
|
515 |
- } else { |
|
516 |
- logg("!ClamInotif: could not watch path '%s', %s\n", pt->strarg, strerror(errno)); |
|
517 |
- if(errno == EINVAL && optget(ctx->clamdopts, "OnAccessPrevention")->enabled) { |
|
518 |
- logg("*ClamInotif: when using the OnAccessPrevention option, please ensure your kernel\n\t\t\twas compiled with CONFIG_FANOTIFY_ACCESS_PERMISSIONS set to Y\n"); |
|
519 |
- |
|
520 |
- kill(getpid(), SIGTERM); |
|
521 |
- } |
|
522 |
- if (errno == ENOSPC) { |
|
523 |
- |
|
524 |
- logg("*ClamInotif: you likely do not have enough inotify watchpoints available ... run the follow command to increase available watchpoints and try again ...\n"); |
|
525 |
- logg("*\t $ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n"); |
|
526 |
- |
|
527 |
- kill(getpid(), SIGTERM); |
|
528 |
- } |
|
529 |
- } |
|
530 |
- } |
|
531 |
- pt = (struct optstruct *)pt->nextarg; |
|
532 |
- } |
|
533 |
- } |
|
534 |
- } |
|
535 |
- |
|
536 |
- if(NULL != include_list) { |
|
537 |
- idx = 0; |
|
538 |
- while(NULL != include_list[idx]) { |
|
539 |
- errno = 0; |
|
540 |
- uint64_t ptlen = strlen(include_list[idx]); |
|
541 |
- if(onas_ht_get(ddd_ht, include_list[idx], ptlen, NULL) == CL_SUCCESS) { |
|
542 |
- if(err = onas_ddd_watch(include_list[idx], ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask)) { |
|
543 |
- if (0 == errno) { |
|
544 |
- logg("!ClamInotif: could not watch path '%s', %d\n ", include_list[idx], err); |
|
545 |
- } else { |
|
546 |
- logg("!ClamInotif: could not watch path '%s', %s\n", include_list[idx], strerror(errno)); |
|
547 |
- if(errno == EINVAL && optget(ctx->clamdopts, "OnAccessPrevention")->enabled) { |
|
548 |
- logg("*ClamInotif: when using the OnAccessPrevention option, please ensure your kernel\n\t\t\twas compiled with CONFIG_FANOTIFY_ACCESS_PERMISSIONS set to Y\n"); |
|
549 |
- |
|
550 |
- kill(getpid(), SIGTERM); |
|
551 |
- } |
|
552 |
- if (errno == ENOSPC) { |
|
553 |
- |
|
554 |
- logg("*ClamInotif: you likely do not have enough inotify watchpoints available ... run the follow command to increase available watchpoints and try again ...\n"); |
|
555 |
- logg("*\t $ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n"); |
|
556 |
- |
|
557 |
- kill(getpid(), SIGTERM); |
|
558 |
- } |
|
559 |
- } |
|
560 |
- } |
|
561 |
- } |
|
562 |
- idx++; |
|
563 |
- } |
|
564 |
- } |
|
565 |
- |
|
566 |
- if(optget(ctx->clamdopts, "OnAccessExtraScanning")->enabled) { |
|
567 |
- logg("ClamInotif: extra scanning on inotify events enabled\n"); |
|
568 |
- } |
|
569 |
- |
|
570 |
- FD_ZERO(&rfds); |
|
571 |
- FD_SET(onas_in_fd, &rfds); |
|
572 |
- |
|
573 |
- pthread_cleanup_push(onas_ddd_exit, NULL); |
|
574 |
- |
|
575 |
- while (1) { |
|
576 |
- do { |
|
577 |
- ret = select(onas_in_fd + 1, &rfds, NULL, NULL, NULL); |
|
578 |
- } while (ret == -1 && errno == EINTR); |
|
579 |
- |
|
580 |
- while ((bread = read(onas_in_fd, buf, sizeof(buf))) > 0) { |
|
581 |
- pthread_testcancel(); |
|
582 |
- /* Handle events. */ |
|
583 |
- int wd; |
|
584 |
- char *p = buf; |
|
585 |
- const char *path = NULL; |
|
586 |
- const char *child = NULL; |
|
587 |
- for (; p < buf + bread; p += sizeof(struct inotify_event) + event->len) { |
|
588 |
- |
|
589 |
- event = (const struct inotify_event *)p; |
|
590 |
- wd = event->wd; |
|
591 |
- path = wdlt[wd]; |
|
592 |
- child = event->name; |
|
593 |
- |
|
594 |
- if (path == NULL) { |
|
595 |
- logg("*ClamInotif: watch descriptor not found in lookup table ... skipping\n"); |
|
596 |
- continue; |
|
597 |
- } |
|
598 |
- |
|
599 |
- len = strlen(path); |
|
600 |
- size_t size = strlen(child) + len + 2; |
|
601 |
- char *child_path = (char *)cli_malloc(size); |
|
602 |
- if (child_path == NULL) { |
|
603 |
- logg("*ClamInotif: could not allocate space for child path ... aborting\n"); |
|
604 |
- return NULL; |
|
605 |
- } |
|
606 |
- |
|
607 |
- if (path[len-1] == '/') { |
|
608 |
- snprintf(child_path, --size, "%s%s", path, child); |
|
609 |
- } else { |
|
610 |
- snprintf(child_path, size, "%s/%s", path, child); |
|
611 |
- } |
|
612 |
- |
|
613 |
- if (event->mask & IN_DELETE) { |
|
614 |
- onas_ddd_handle_in_delete(ctx, path, child_path, event, wd); |
|
615 |
- |
|
616 |
- } else if (event->mask & IN_MOVED_FROM) { |
|
617 |
- onas_ddd_handle_in_moved_from(ctx, path, child_path, event, wd); |
|
618 |
- |
|
619 |
- } else if (event->mask & IN_CREATE) { |
|
620 |
- onas_ddd_handle_in_create(ctx, path, child_path, event, wd, in_mask); |
|
621 |
- |
|
622 |
- } else if (event->mask & IN_MOVED_TO) { |
|
623 |
- onas_ddd_handle_in_moved_to(ctx, path, child_path, event, wd, in_mask); |
|
624 |
- } |
|
625 |
- |
|
626 |
- free(child_path); |
|
627 |
- child_path = NULL; |
|
628 |
- } |
|
629 |
- } |
|
630 |
- } |
|
631 |
- |
|
632 |
- logg("*ClamInotif: exiting inotify event thread\n"); |
|
633 |
- pthread_cleanup_pop(1); |
|
634 |
- return NULL; |
|
635 |
-} |
|
392 |
+ logg("*ClamInotif: starting inotify event loop ...\n"); |
|
393 |
+ |
|
394 |
+ onas_in_fd = inotify_init1(IN_NONBLOCK); |
|
395 |
+ if (onas_in_fd == -1) { |
|
396 |
+ logg("!ClamInotif: could not init inotify\n"); |
|
397 |
+ return NULL; |
|
398 |
+ } |
|
399 |
+ |
|
400 |
+ ret = onas_ddd_init(0, ONAS_DEFAULT_HT_SIZE); |
|
401 |
+ if (ret) { |
|
402 |
+ logg("!ClamInotif: failed to initialize DDD system\n"); |
|
403 |
+ return NULL; |
|
404 |
+ } |
|
405 |
+ |
|
406 |
+ logg("*ClamInotif: dynamically determining directory hierarchy...\n"); |
|
407 |
+ /* Add provided paths recursively. */ |
|
408 |
+ |
|
409 |
+ if (!optget(ctx->opts, "watch-list")->enabled && !optget(ctx->clamdopts, "OnAccessIncludePath")->enabled) { |
|
410 |
+ logg("!ClamInotif: Please specify at least one path with OnAccessIncludePath\n"); |
|
411 |
+ return NULL; |
|
412 |
+ } |
|
636 | 413 |
|
414 |
+ if ((pt = optget(ctx->clamdopts, "OnAccessIncludePath"))->enabled) { |
|
415 |
+ |
|
416 |
+ while (pt) { |
|
417 |
+ if (!strcmp(pt->strarg, "/")) { |
|
418 |
+ logg("!ClamInotif: not including path '%s' while DDD is enabled\n", pt->strarg); |
|
419 |
+ logg("!ClamInotif: please use the OnAccessMountPath option to watch '%s'\n", pt->strarg); |
|
420 |
+ pt = (struct optstruct *)pt->nextarg; |
|
421 |
+ continue; |
|
422 |
+ } |
|
423 |
+ if (onas_ht_get(ddd_ht, pt->strarg, strlen(pt->strarg), NULL) != CL_SUCCESS) { |
|
424 |
+ if (onas_ht_add_hierarchy(ddd_ht, pt->strarg)) { |
|
425 |
+ logg("!ClamInotif: can't include '%s'\n", pt->strarg); |
|
426 |
+ return NULL; |
|
427 |
+ } else { |
|
428 |
+ logg("ClamInotif: watching '%s' (and all sub-directories)\n", pt->strarg); |
|
429 |
+ } |
|
430 |
+ } |
|
431 |
+ |
|
432 |
+ pt = (struct optstruct *)pt->nextarg; |
|
433 |
+ } |
|
434 |
+ } |
|
435 |
+ |
|
436 |
+ if ((pt = optget(ctx->opts, "watch-list"))->enabled) { |
|
437 |
+ |
|
438 |
+ num_indirs = 0; |
|
439 |
+ err = CL_SUCCESS; |
|
440 |
+ |
|
441 |
+ include_list = onas_get_opt_list(pt->strarg, &num_indirs, &err); |
|
442 |
+ if (NULL == include_list) { |
|
443 |
+ logg("!ClamInotif: could not parse include list (%d)\n", err); |
|
444 |
+ return NULL; |
|
445 |
+ } |
|
446 |
+ |
|
447 |
+ idx = 0; |
|
448 |
+ while (NULL != include_list[idx]) { |
|
449 |
+ if (onas_ht_get(ddd_ht, include_list[idx], strlen(include_list[idx]), NULL) != CL_SUCCESS) { |
|
450 |
+ if (onas_ht_add_hierarchy(ddd_ht, include_list[idx])) { |
|
451 |
+ logg("!ClamInotif: can't include '%s'\n", include_list[idx]); |
|
452 |
+ return NULL; |
|
453 |
+ } else { |
|
454 |
+ logg("ClamInotif: watching '%s' (and all sub-directories)\n", include_list[idx]); |
|
455 |
+ } |
|
456 |
+ } |
|
457 |
+ |
|
458 |
+ idx++; |
|
459 |
+ } |
|
460 |
+ } |
|
461 |
+ |
|
462 |
+ /* Remove provided paths recursively. */ |
|
463 |
+ if ((pt = optget(ctx->clamdopts, "OnAccessExcludePath"))->enabled) { |
|
464 |
+ while (pt) { |
|
465 |
+ size_t ptlen = strlen(pt->strarg); |
|
466 |
+ if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) { |
|
467 |
+ if (onas_ht_rm_hierarchy(ddd_ht, pt->strarg, ptlen, 0)) { |
|
468 |
+ logg("!ClamInotif: can't exclude '%s'\n", pt->strarg); |
|
469 |
+ return NULL; |
|
470 |
+ } else |
|
471 |
+ logg("ClamInotif: excluding '%s' (and all sub-directories)\n", pt->strarg); |
|
472 |
+ } |
|
473 |
+ |
|
474 |
+ pt = (struct optstruct *)pt->nextarg; |
|
475 |
+ } |
|
476 |
+ } |
|
477 |
+ |
|
478 |
+ if ((pt = optget(ctx->opts, "exclude-list"))->enabled) { |
|
479 |
+ |
|
480 |
+ num_exdirs = 0; |
|
481 |
+ err = CL_SUCCESS; |
|
482 |
+ |
|
483 |
+ exclude_list = onas_get_opt_list(pt->strarg, &num_exdirs, &err); |
|
484 |
+ if (NULL == exclude_list) { |
|
485 |
+ logg("!ClamInotif: could not parse exclude list (%d)\n", err); |
|
486 |
+ return NULL; |
|
487 |
+ } |
|
488 |
+ |
|
489 |
+ idx = 0; |
|
490 |
+ while (exclude_list[idx] != NULL) { |
|
491 |
+ if (onas_ht_get(ddd_ht, exclude_list[idx], strlen(exclude_list[idx]), NULL) == CL_SUCCESS) { |
|
492 |
+ if (onas_ht_rm_hierarchy(ddd_ht, exclude_list[idx], strlen(exclude_list[idx]), 0)) { |
|
493 |
+ logg("!ClamInotif: can't exclude '%s'\n", exclude_list[idx]); |
|
494 |
+ return NULL; |
|
495 |
+ } else { |
|
496 |
+ logg("ClamInotif: excluding '%s' (and all sub-directories)\n", exclude_list[idx]); |
|
497 |
+ } |
|
498 |
+ } |
|
499 |
+ |
|
500 |
+ idx++; |
|
501 |
+ } |
|
502 |
+ } |
|
503 |
+ |
|
504 |
+ /* Watch provided paths recursively */ |
|
505 |
+ if ((pt = optget(ctx->clamdopts, "OnAccessIncludePath"))->enabled) { |
|
506 |
+ while (pt) { |
|
507 |
+ errno = 0; |
|
508 |
+ size_t ptlen = strlen(pt->strarg); |
|
509 |
+ if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) { |
|
510 |
+ if (err = onas_ddd_watch(pt->strarg, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask)) { |
|
511 |
+ |
|
512 |
+ if (0 == errno) { |
|
513 |
+ logg("!ClamInotif: could not watch path '%s', %d\n ", pt->strarg, err); |
|
514 |
+ } else { |
|
515 |
+ logg("!ClamInotif: could not watch path '%s', %s\n", pt->strarg, strerror(errno)); |
|
516 |
+ if (errno == EINVAL && optget(ctx->clamdopts, "OnAccessPrevention")->enabled) { |
|
517 |
+ logg("*ClamInotif: when using the OnAccessPrevention option, please ensure your kernel\n\t\t\twas compiled with CONFIG_FANOTIFY_ACCESS_PERMISSIONS set to Y\n"); |
|
518 |
+ |
|
519 |
+ kill(getpid(), SIGTERM); |
|
520 |
+ } |
|
521 |
+ if (errno == ENOSPC) { |
|
522 |
+ |
|
523 |
+ logg("*ClamInotif: you likely do not have enough inotify watchpoints available ... run the follow command to increase available watchpoints and try again ...\n"); |
|
524 |
+ logg("*\t $ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n"); |
|
525 |
+ |
|
526 |
+ kill(getpid(), SIGTERM); |
|
527 |
+ } |
|
528 |
+ } |
|
529 |
+ } |
|
530 |
+ pt = (struct optstruct *)pt->nextarg; |
|
531 |
+ } |
|
532 |
+ } |
|
533 |
+ } |
|
534 |
+ |
|
535 |
+ if (NULL != include_list) { |
|
536 |
+ idx = 0; |
|
537 |
+ while (NULL != include_list[idx]) { |
|
538 |
+ errno = 0; |
|
539 |
+ uint64_t ptlen = strlen(include_list[idx]); |
|
540 |
+ if (onas_ht_get(ddd_ht, include_list[idx], ptlen, NULL) == CL_SUCCESS) { |
|
541 |
+ if (err = onas_ddd_watch(include_list[idx], ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask)) { |
|
542 |
+ if (0 == errno) { |
|
543 |
+ logg("!ClamInotif: could not watch path '%s', %d\n ", include_list[idx], err); |
|
544 |
+ } else { |
|
545 |
+ logg("!ClamInotif: could not watch path '%s', %s\n", include_list[idx], strerror(errno)); |
|
546 |
+ if (errno == EINVAL && optget(ctx->clamdopts, "OnAccessPrevention")->enabled) { |
|
547 |
+ logg("*ClamInotif: when using the OnAccessPrevention option, please ensure your kernel\n\t\t\twas compiled with CONFIG_FANOTIFY_ACCESS_PERMISSIONS set to Y\n"); |
|
548 |
+ |
|
549 |
+ kill(getpid(), SIGTERM); |
|
550 |
+ } |
|
551 |
+ if (errno == ENOSPC) { |
|
552 |
+ |
|
553 |
+ logg("*ClamInotif: you likely do not have enough inotify watchpoints available ... run the follow command to increase available watchpoints and try again ...\n"); |
|
554 |
+ logg("*\t $ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n"); |
|
555 |
+ |
|
556 |
+ kill(getpid(), SIGTERM); |
|
557 |
+ } |
|
558 |
+ } |
|
559 |
+ } |
|
560 |
+ } |
|
561 |
+ idx++; |
|
562 |
+ } |
|
563 |
+ } |
|
564 |
+ |
|
565 |
+ if (optget(ctx->clamdopts, "OnAccessExtraScanning")->enabled) { |
|
566 |
+ logg("ClamInotif: extra scanning on inotify events enabled\n"); |
|
567 |
+ } |
|
568 |
+ |
|
569 |
+ FD_ZERO(&rfds); |
|
570 |
+ FD_SET(onas_in_fd, &rfds); |
|
571 |
+ |
|
572 |
+ pthread_cleanup_push(onas_ddd_exit, NULL); |
|
573 |
+ |
|
574 |
+ while (1) { |
|
575 |
+ do { |
|
576 |
+ ret = select(onas_in_fd + 1, &rfds, NULL, NULL, NULL); |
|
577 |
+ } while (ret == -1 && errno == EINTR); |
|
578 |
+ |
|
579 |
+ while ((bread = read(onas_in_fd, buf, sizeof(buf))) > 0) { |
|
580 |
+ pthread_testcancel(); |
|
581 |
+ /* Handle events. */ |
|
582 |
+ int wd; |
|
583 |
+ char *p = buf; |
|
584 |
+ const char *path = NULL; |
|
585 |
+ const char *child = NULL; |
|
586 |
+ for (; p < buf + bread; p += sizeof(struct inotify_event) + event->len) { |
|
587 |
+ |
|
588 |
+ event = (const struct inotify_event *)p; |
|
589 |
+ wd = event->wd; |
|
590 |
+ path = wdlt[wd]; |
|
591 |
+ child = event->name; |
|
592 |
+ |
|
593 |
+ if (path == NULL) { |
|
594 |
+ logg("*ClamInotif: watch descriptor not found in lookup table ... skipping\n"); |
|
595 |
+ continue; |
|
596 |
+ } |
|
597 |
+ |
|
598 |
+ len = strlen(path); |
|
599 |
+ size_t size = strlen(child) + len + 2; |
|
600 |
+ char *child_path = (char *)cli_malloc(size); |
|
601 |
+ if (child_path == NULL) { |
|
602 |
+ logg("*ClamInotif: could not allocate space for child path ... aborting\n"); |
|
603 |
+ return NULL; |
|
604 |
+ } |
|
605 |
+ |
|
606 |
+ if (path[len - 1] == '/') { |
|
607 |
+ snprintf(child_path, --size, "%s%s", path, child); |
|
608 |
+ } else { |
|
609 |
+ snprintf(child_path, size, "%s/%s", path, child); |
|
610 |
+ } |
|
611 |
+ |
|
612 |
+ if (event->mask & IN_DELETE) { |
|
613 |
+ onas_ddd_handle_in_delete(ctx, path, child_path, event, wd); |
|
614 |
+ |
|
615 |
+ } else if (event->mask & IN_MOVED_FROM) { |
|
616 |
+ onas_ddd_handle_in_moved_from(ctx, path, child_path, event, wd); |
|
617 |
+ |
|
618 |
+ } else if (event->mask & IN_CREATE) { |
|
619 |
+ onas_ddd_handle_in_create(ctx, path, child_path, event, wd, in_mask); |
|
620 |
+ |
|
621 |
+ } else if (event->mask & IN_MOVED_TO) { |
|
622 |
+ onas_ddd_handle_in_moved_to(ctx, path, child_path, event, wd, in_mask); |
|
623 |
+ } |
|
624 |
+ |
|
625 |
+ free(child_path); |
|
626 |
+ child_path = NULL; |
|
627 |
+ } |
|
628 |
+ } |
|
629 |
+ } |
|
630 |
+ |
|
631 |
+ logg("*ClamInotif: exiting inotify event thread\n"); |
|
632 |
+ pthread_cleanup_pop(1); |
|
633 |
+ return NULL; |
|
634 |
+} |
|
637 | 635 |
|
638 | 636 |
static void onas_ddd_handle_in_delete(struct onas_context *ctx, |
639 |
- const char *path, const char *child_path, const struct inotify_event *event, int wd) { |
|
637 |
+ const char *path, const char *child_path, const struct inotify_event *event, int wd) |
|
638 |
+{ |
|
640 | 639 |
|
641 |
- struct stat s; |
|
642 |
- if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; |
|
643 |
- if (!(event->mask & IN_ISDIR)) return; |
|
640 |
+ struct stat s; |
|
641 |
+ if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; |
|
642 |
+ if (!(event->mask & IN_ISDIR)) return; |
|
644 | 643 |
|
645 |
- logg("*ClamInotif: DELETE - removing %s from %s with wd:%d\n", child_path, path, wd); |
|
646 |
- onas_ddd_unwatch(child_path, ctx->fan_fd, onas_in_fd); |
|
647 |
- onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0); |
|
644 |
+ logg("*ClamInotif: DELETE - removing %s from %s with wd:%d\n", child_path, path, wd); |
|
645 |
+ onas_ddd_unwatch(child_path, ctx->fan_fd, onas_in_fd); |
|
646 |
+ onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0); |
|
648 | 647 |
|
649 |
- return; |
|
648 |
+ return; |
|
650 | 649 |
} |
651 | 650 |
|
652 | 651 |
static void onas_ddd_handle_in_moved_from(struct onas_context *ctx, |
653 |
- const char *path, const char *child_path, const struct inotify_event *event, int wd) { |
|
652 |
+ const char *path, const char *child_path, const struct inotify_event *event, int wd) |
|
653 |
+{ |
|
654 | 654 |
|
655 |
- struct stat s; |
|
656 |
- if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; |
|
657 |
- if (!(event->mask & IN_ISDIR)) return; |
|
655 |
+ struct stat s; |
|
656 |
+ if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; |
|
657 |
+ if (!(event->mask & IN_ISDIR)) return; |
|
658 | 658 |
|
659 |
- logg("*ClamInotif: MOVED_FROM - removing %s from %s with wd:%d\n", child_path, path, wd); |
|
660 |
- onas_ddd_unwatch(child_path, ctx->fan_fd, onas_in_fd); |
|
661 |
- onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0); |
|
659 |
+ logg("*ClamInotif: MOVED_FROM - removing %s from %s with wd:%d\n", child_path, path, wd); |
|
660 |
+ onas_ddd_unwatch(child_path, ctx->fan_fd, onas_in_fd); |
|
661 |
+ onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0); |
|
662 | 662 |
|
663 |
- return; |
|
663 |
+ return; |
|
664 | 664 |
} |
665 | 665 |
|
666 | 666 |
static void onas_ddd_handle_in_create(struct onas_context *ctx, |
667 |
- const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask) { |
|
667 |
+ const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask) |
|
668 |
+{ |
|
668 | 669 |
|
669 |
- struct stat s; |
|
670 |
+ struct stat s; |
|
670 | 671 |
|
671 |
- if (optget(ctx->clamdopts, "OnAccessExtraScanning")->enabled) { |
|
672 |
- if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) { |
|
673 |
- onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_FILE); |
|
672 |
+ if (optget(ctx->clamdopts, "OnAccessExtraScanning")->enabled) { |
|
673 |
+ if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) { |
|
674 |
+ onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_FILE); |
|
674 | 675 |
|
675 |
- } else if(event->mask & IN_ISDIR) { |
|
676 |
- logg("*ClamInotif: CREATE - adding %s to %s with wd:%d\n", child_path, path, wd); |
|
677 |
- onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_DIR); |
|
676 |
+ } else if (event->mask & IN_ISDIR) { |
|
677 |
+ logg("*ClamInotif: CREATE - adding %s to %s with wd:%d\n", child_path, path, wd); |
|
678 |
+ onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_DIR); |
|
678 | 679 |
|
679 |
- onas_ht_add_hierarchy(ddd_ht, child_path); |
|
680 |
- onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask); |
|
681 |
- } |
|
682 |
- } |
|
683 |
- else |
|
684 |
- { |
|
685 |
- if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; |
|
686 |
- if (!(event->mask & IN_ISDIR)) return; |
|
680 |
+ onas_ht_add_hierarchy(ddd_ht, child_path); |
|
681 |
+ onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask); |
|
682 |
+ } |
|
683 |
+ } else { |
|
684 |
+ if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; |
|
685 |
+ if (!(event->mask & IN_ISDIR)) return; |
|
687 | 686 |
|
688 |
- logg("*ClamInotif: MOVED_TO - adding %s to %s with wd:%d\n", child_path, path, wd); |
|
689 |
- onas_ht_add_hierarchy(ddd_ht, child_path); |
|
690 |
- onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask); |
|
691 |
- } |
|
687 |
+ logg("*ClamInotif: MOVED_TO - adding %s to %s with wd:%d\n", child_path, path, wd); |
|
688 |
+ onas_ht_add_hierarchy(ddd_ht, child_path); |
|
689 |
+ onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask); |
|
690 |
+ } |
|
692 | 691 |
|
693 |
- return; |
|
692 |
+ return; |
|
694 | 693 |
} |
695 | 694 |
|
696 | 695 |
static void onas_ddd_handle_in_moved_to(struct onas_context *ctx, |
697 |
- const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask) { |
|
698 |
- |
|
699 |
- struct stat s; |
|
700 |
- if (optget(ctx->clamdopts, "OnAccessExtraScanning")->enabled) { |
|
701 |
- if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) { |
|
702 |
- onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_FILE); |
|
696 |
+ const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask) |
|
697 |
+{ |
|
703 | 698 |
|
704 |
- } else if(event->mask & IN_ISDIR) { |
|
705 |
- logg("*ClamInotif: MOVED_TO - adding %s to %s with wd:%d\n", child_path, path, wd); |
|
706 |
- onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_DIR); |
|
699 |
+ struct stat s; |
|
700 |
+ if (optget(ctx->clamdopts, "OnAccessExtraScanning")->enabled) { |
|
701 |
+ if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) { |
|
702 |
+ onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_FILE); |
|
707 | 703 |
|
708 |
- onas_ht_add_hierarchy(ddd_ht, child_path); |
|
709 |
- onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask); |
|
704 |
+ } else if (event->mask & IN_ISDIR) { |
|
705 |
+ logg("*ClamInotif: MOVED_TO - adding %s to %s with wd:%d\n", child_path, path, wd); |
|
706 |
+ onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_DIR); |
|
710 | 707 |
|
711 |
- } |
|
712 |
- } else { |
|
713 |
- if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; |
|
714 |
- if (!(event->mask & IN_ISDIR)) return; |
|
708 |
+ onas_ht_add_hierarchy(ddd_ht, child_path); |
|
709 |
+ onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask); |
|
710 |
+ } |
|
711 |
+ } else { |
|
712 |
+ if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; |
|
713 |
+ if (!(event->mask & IN_ISDIR)) return; |
|
715 | 714 |
|
716 |
- logg("*ClamInotif: MOVED_TO - adding %s to %s with wd:%d\n", child_path, path, wd); |
|
717 |
- onas_ht_add_hierarchy(ddd_ht, child_path); |
|
718 |
- onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask); |
|
719 |
- } |
|
715 |
+ logg("*ClamInotif: MOVED_TO - adding %s to %s with wd:%d\n", child_path, path, wd); |
|
716 |
+ onas_ht_add_hierarchy(ddd_ht, child_path); |
|
717 |
+ onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask); |
|
718 |
+ } |
|
720 | 719 |
|
721 |
- return; |
|
720 |
+ return; |
|
722 | 721 |
} |
723 | 722 |
|
724 |
-static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char *pathname, int extra_options) { |
|
725 |
- |
|
726 |
- struct onas_scan_event *event_data; |
|
727 |
- |
|
728 |
- |
|
729 |
- event_data = (struct onas_scan_event *) cli_calloc(1, sizeof(struct onas_scan_event)); |
|
730 |
- if (NULL == event_data) { |
|
731 |
- logg("!ClamInotif: could not allocate memory for event data struct\n"); |
|
732 |
- } |
|
723 |
+static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char *pathname, int extra_options) |
|
724 |
+{ |
|
733 | 725 |
|
734 |
- /* general mapping */ |
|
735 |
- onas_map_context_info_to_event_data(ctx, &event_data); |
|
736 |
- event_data->pathname = cli_strdup(pathname); |
|
737 |
- event_data->bool_opts |= ONAS_SCTH_B_SCAN; |
|
726 |
+ struct onas_scan_event *event_data; |
|
738 | 727 |
|
739 |
- /* inotify specific stuffs */ |
|
740 |
- event_data->bool_opts |= ONAS_SCTH_B_INOTIFY; |
|
741 |
- extra_options & ONAS_SCTH_B_FILE ? event_data->bool_opts |= ONAS_SCTH_B_FILE : extra_options; |
|
742 |
- extra_options & ONAS_SCTH_B_DIR ? event_data->bool_opts |= ONAS_SCTH_B_DIR : extra_options; |
|
728 |
+ event_data = (struct onas_scan_event *)cli_calloc(1, sizeof(struct onas_scan_event)); |
|
729 |
+ if (NULL == event_data) { |
|
730 |
+ logg("!ClamInotif: could not allocate memory for event data struct\n"); |
|
731 |
+ } |
|
743 | 732 |
|
744 |
- logg("*ClamInotif: attempting to feed consumer queue\n"); |
|
745 |
- /* feed consumer queue */ |
|
746 |
- if (CL_SUCCESS != onas_queue_event(event_data)) { |
|
747 |
- logg("!ClamInotif: error occurred while feeding consumer queue extra event ... continuing ...\n"); |
|
748 |
- return; |
|
749 |
- } |
|
733 |
+ /* general mapping */ |
|
734 |
+ onas_map_context_info_to_event_data(ctx, &event_data); |
|
735 |
+ event_data->pathname = cli_strdup(pathname); |
|
736 |
+ event_data->bool_opts |= ONAS_SCTH_B_SCAN; |
|
737 |
+ |
|
738 |
+ /* inotify specific stuffs */ |
|
739 |
+ event_data->bool_opts |= ONAS_SCTH_B_INOTIFY; |
|
740 |
+ extra_options &ONAS_SCTH_B_FILE ? event_data->bool_opts |= ONAS_SCTH_B_FILE : extra_options; |
|
741 |
+ extra_options &ONAS_SCTH_B_DIR ? event_data->bool_opts |= ONAS_SCTH_B_DIR : extra_options; |
|
742 |
+ |
|
743 |
+ logg("*ClamInotif: attempting to feed consumer queue\n"); |
|
744 |
+ /* feed consumer queue */ |
|
745 |
+ if (CL_SUCCESS != onas_queue_event(event_data)) { |
|
746 |
+ logg("!ClamInotif: error occurred while feeding consumer queue extra event ... continuing ...\n"); |
|
747 |
+ return; |
|
748 |
+ } |
|
750 | 749 |
|
751 |
- return; |
|
750 |
+ return; |
|
752 | 751 |
} |
753 | 752 |
|
754 |
-static void onas_ddd_exit(void *arg) { |
|
755 |
- logg("*ClamInotif: onas_ddd_exit()\n"); |
|
753 |
+static void onas_ddd_exit(void *arg) |
|
754 |
+{ |
|
755 |
+ logg("*ClamInotif: onas_ddd_exit()\n"); |
|
756 | 756 |
|
757 |
- if (onas_in_fd) { |
|
758 |
- close(onas_in_fd); |
|
759 |
- } |
|
760 |
- onas_in_fd = 0; |
|
757 |
+ if (onas_in_fd) { |
|
758 |
+ close(onas_in_fd); |
|
759 |
+ } |
|
760 |
+ onas_in_fd = 0; |
|
761 | 761 |
|
762 |
- if (ddd_ht) { |
|
763 |
- onas_free_ht(ddd_ht); |
|
764 |
- } |
|
765 |
- ddd_ht = NULL; |
|
762 |
+ if (ddd_ht) { |
|
763 |
+ onas_free_ht(ddd_ht); |
|
764 |
+ } |
|
765 |
+ ddd_ht = NULL; |
|
766 | 766 |
|
767 |
- if (wdlt) { |
|
768 |
- free(wdlt); |
|
769 |
- } |
|
770 |
- wdlt = NULL; |
|
767 |
+ if (wdlt) { |
|
768 |
+ free(wdlt); |
|
769 |
+ } |
|
770 |
+ wdlt = NULL; |
|
771 | 771 |
|
772 |
- logg("ClamInotif: stopped\n"); |
|
772 |
+ logg("ClamInotif: stopped\n"); |
|
773 | 773 |
} |
774 | 774 |
|
775 | 775 |
#endif |
... | ... |
@@ -75,16 +75,16 @@ static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94"; |
75 | 75 |
#define LSTAT lstat |
76 | 76 |
|
77 | 77 |
#define internal_function |
78 |
-# define __set_errno(val) (errno = (val)) |
|
78 |
+#define __set_errno(val) (errno = (val)) |
|
79 | 79 |
|
80 | 80 |
/* Largest alignment size needed, minus one. |
81 | 81 |
Usually long double is the worst case. */ |
82 | 82 |
#ifndef ALIGNBYTES |
83 |
-#define ALIGNBYTES (__alignof__ (long double) - 1) |
|
83 |
+#define ALIGNBYTES (__alignof__(long double) - 1) |
|
84 | 84 |
#endif |
85 | 85 |
/* Align P to that size. */ |
86 | 86 |
#ifndef ALIGN |
87 |
-#define ALIGN(p) (((unsigned long int) (p) + ALIGNBYTES) & ~ALIGNBYTES) |
|
87 |
+#define ALIGN(p) (((unsigned long int)(p) + ALIGNBYTES) & ~ALIGNBYTES) |
|
88 | 88 |
#endif |
89 | 89 |
|
90 | 90 |
/* Support for the LFS API version. */ |
... | ... |
@@ -94,303 +94,305 @@ static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94"; |
94 | 94 |
#define FTS_READ fts_read |
95 | 95 |
#define FTS_SET fts_set |
96 | 96 |
#define FTS_CHILDREN fts_children |
97 |
-# define FTSOBJ FTS |
|
98 |
-# define FTSENTRY FTSENT |
|
99 |
-# define INO_T ino_t |
|
100 |
-# define STAT stat |
|
101 |
-# define LSTAT lstat |
|
97 |
+#define FTSOBJ FTS |
|
98 |
+#define FTSENTRY FTSENT |
|
99 |
+#define INO_T ino_t |
|
100 |
+#define STAT stat |
|
101 |
+#define LSTAT lstat |
|
102 | 102 |
#endif |
103 | 103 |
|
104 |
-static FTSENTRY *fts_alloc (FTSOBJ *, const char *, size_t) internal_function; |
|
105 |
-static FTSENTRY *fts_build (FTSOBJ *, int) internal_function; |
|
106 |
-static void fts_lfree (FTSENTRY *) internal_function; |
|
107 |
-static void fts_load (FTSOBJ *, FTSENTRY *) internal_function; |
|
108 |
-static size_t fts_maxarglen (char * const *) internal_function; |
|
109 |
-static void fts_padjust (FTSOBJ *, FTSENTRY *) internal_function; |
|
110 |
-static int fts_palloc (FTSOBJ *, size_t) internal_function; |
|
111 |
-static FTSENTRY *fts_sort (FTSOBJ *, FTSENTRY *, int) internal_function; |
|
112 |
-static u_short fts_stat (FTSOBJ *, FTSENTRY *, int) internal_function; |
|
113 |
-static int fts_safe_changedir (FTSOBJ *, FTSENTRY *, int, const char *) |
|
114 |
- internal_function; |
|
104 |
+static FTSENTRY *fts_alloc(FTSOBJ *, const char *, size_t) internal_function; |
|
105 |
+static FTSENTRY *fts_build(FTSOBJ *, int) internal_function; |
|
106 |
+static void fts_lfree(FTSENTRY *) internal_function; |
|
107 |
+static void fts_load(FTSOBJ *, FTSENTRY *) internal_function; |
|
108 |
+static size_t fts_maxarglen(char *const *) internal_function; |
|
109 |
+static void fts_padjust(FTSOBJ *, FTSENTRY *) internal_function; |
|
110 |
+static int fts_palloc(FTSOBJ *, size_t) internal_function; |
|
111 |
+static FTSENTRY *fts_sort(FTSOBJ *, FTSENTRY *, int) internal_function; |
|
112 |
+static u_short fts_stat(FTSOBJ *, FTSENTRY *, int) internal_function; |
|
113 |
+static int fts_safe_changedir(FTSOBJ *, FTSENTRY *, int, const char *) |
|
114 |
+ internal_function; |
|
115 | 115 |
|
116 | 116 |
#ifndef MAX |
117 |
-#define MAX(a, b) ({ __typeof__ (a) _a = (a); \ |
|
117 |
+#define MAX(a, b) ({ __typeof__ (a) _a = (a); \ |
|
118 | 118 |
__typeof__ (b) _b = (b); \ |
119 | 119 |
_a > _b ? _a : _b; }) |
120 | 120 |
#endif |
121 | 121 |
|
122 |
-#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) |
|
122 |
+#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) |
|
123 | 123 |
|
124 |
-#define CLR(opt) (sp->fts_options &= ~(opt)) |
|
125 |
-#define ISSET(opt) (sp->fts_options & (opt)) |
|
126 |
-#define SET(opt) (sp->fts_options |= (opt)) |
|
124 |
+#define CLR(opt) (sp->fts_options &= ~(opt)) |
|
125 |
+#define ISSET(opt) (sp->fts_options & (opt)) |
|
126 |
+#define SET(opt) (sp->fts_options |= (opt)) |
|
127 | 127 |
|
128 |
-#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) |
|
128 |
+#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) |
|
129 | 129 |
|
130 | 130 |
/* fts_build flags */ |
131 |
-#define BCHILD 1 /* fts_children */ |
|
132 |
-#define BNAMES 2 /* fts_children, names only */ |
|
133 |
-#define BREAD 3 /* fts_read */ |
|
131 |
+#define BCHILD 1 /* fts_children */ |
|
132 |
+#define BNAMES 2 /* fts_children, names only */ |
|
133 |
+#define BREAD 3 /* fts_read */ |
|
134 | 134 |
|
135 | 135 |
FTSOBJ * |
136 |
-FTS_OPEN (char * const *argv, int options, |
|
137 |
- int (*compar) (const FTSENTRY **, const FTSENTRY **)) |
|
136 |
+FTS_OPEN(char *const *argv, int options, |
|
137 |
+ int (*compar)(const FTSENTRY **, const FTSENTRY **)) |
|
138 | 138 |
{ |
139 |
- FTSOBJ *sp; |
|
140 |
- FTSENTRY *p, *root; |
|
141 |
- int nitems; |
|
142 |
- FTSENTRY *parent = NULL; |
|
143 |
- FTSENTRY *tmp; |
|
144 |
- |
|
145 |
- /* Options check. */ |
|
146 |
- if (options & ~FTS_OPTIONMASK) { |
|
147 |
- __set_errno (EINVAL); |
|
148 |
- return (NULL); |
|
149 |
- } |
|
150 |
- |
|
151 |
- /* Allocate/initialize the stream */ |
|
152 |
- if ((sp = malloc((u_int)sizeof(FTSOBJ))) == NULL) |
|
153 |
- return (NULL); |
|
154 |
- memset(sp, 0, sizeof(FTSOBJ)); |
|
155 |
- sp->fts_compar = (int (*) (const void *, const void *)) compar; |
|
156 |
- sp->fts_options = options; |
|
157 |
- |
|
158 |
- /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ |
|
159 |
- if (ISSET(FTS_LOGICAL)) |
|
160 |
- SET(FTS_NOCHDIR); |
|
161 |
- |
|
162 |
- /* |
|
139 |
+ FTSOBJ *sp; |
|
140 |
+ FTSENTRY *p, *root; |
|
141 |
+ int nitems; |
|
142 |
+ FTSENTRY *parent = NULL; |
|
143 |
+ FTSENTRY *tmp; |
|
144 |
+ |
|
145 |
+ /* Options check. */ |
|
146 |
+ if (options & ~FTS_OPTIONMASK) { |
|
147 |
+ __set_errno(EINVAL); |
|
148 |
+ return (NULL); |
|
149 |
+ } |
|
150 |
+ |
|
151 |
+ /* Allocate/initialize the stream */ |
|
152 |
+ if ((sp = malloc((u_int)sizeof(FTSOBJ))) == NULL) |
|
153 |
+ return (NULL); |
|
154 |
+ memset(sp, 0, sizeof(FTSOBJ)); |
|
155 |
+ sp->fts_compar = (int (*)(const void *, const void *))compar; |
|
156 |
+ sp->fts_options = options; |
|
157 |
+ |
|
158 |
+ /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ |
|
159 |
+ if (ISSET(FTS_LOGICAL)) |
|
160 |
+ SET(FTS_NOCHDIR); |
|
161 |
+ |
|
162 |
+ /* |
|
163 | 163 |
* Start out with 1K of path space, and enough, in any case, |
164 | 164 |
* to hold the user's paths. |
165 | 165 |
*/ |
166 | 166 |
#ifndef MAXPATHLEN |
167 | 167 |
#define MAXPATHLEN 1024 |
168 | 168 |
#endif |
169 |
- size_t maxarglen = fts_maxarglen(argv); |
|
170 |
- if (fts_palloc(sp, MAX(maxarglen, MAXPATHLEN))) |
|
171 |
- goto mem1; |
|
172 |
- |
|
173 |
- /* Allocate/initialize root's parent. */ |
|
174 |
- if (*argv != NULL) { |
|
175 |
- if ((parent = fts_alloc(sp, "", 0)) == NULL) |
|
176 |
- goto mem2; |
|
177 |
- parent->fts_level = FTS_ROOTPARENTLEVEL; |
|
178 |
- } |
|
179 |
- |
|
180 |
- /* Allocate/initialize root(s). */ |
|
181 |
- for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) { |
|
182 |
- /* Don't allow zero-length paths. */ |
|
183 |
- size_t len = strlen(*argv); |
|
184 |
- if (len == 0) { |
|
185 |
- __set_errno (ENOENT); |
|
186 |
- goto mem3; |
|
187 |
- } |
|
188 |
- |
|
189 |
- p = fts_alloc(sp, *argv, len); |
|
190 |
- p->fts_level = FTS_ROOTLEVEL; |
|
191 |
- p->fts_parent = parent; |
|
192 |
- p->fts_accpath = p->fts_name; |
|
193 |
- p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW)); |
|
194 |
- |
|
195 |
- /* Command-line "." and ".." are real directories. */ |
|
196 |
- if (p->fts_info == FTS_DOT) |
|
197 |
- p->fts_info = FTS_D; |
|
198 |
- |
|
199 |
- /* |
|
169 |
+ size_t maxarglen = fts_maxarglen(argv); |
|
170 |
+ if (fts_palloc(sp, MAX(maxarglen, MAXPATHLEN))) |
|
171 |
+ goto mem1; |
|
172 |
+ |
|
173 |
+ /* Allocate/initialize root's parent. */ |
|
174 |
+ if (*argv != NULL) { |
|
175 |
+ if ((parent = fts_alloc(sp, "", 0)) == NULL) |
|
176 |
+ goto mem2; |
|
177 |
+ parent->fts_level = FTS_ROOTPARENTLEVEL; |
|
178 |
+ } |
|
179 |
+ |
|
180 |
+ /* Allocate/initialize root(s). */ |
|
181 |
+ for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) { |
|
182 |
+ /* Don't allow zero-length paths. */ |
|
183 |
+ size_t len = strlen(*argv); |
|
184 |
+ if (len == 0) { |
|
185 |
+ __set_errno(ENOENT); |
|
186 |
+ goto mem3; |
|
187 |
+ } |
|
188 |
+ |
|
189 |
+ p = fts_alloc(sp, *argv, len); |
|
190 |
+ p->fts_level = FTS_ROOTLEVEL; |
|
191 |
+ p->fts_parent = parent; |
|
192 |
+ p->fts_accpath = p->fts_name; |
|
193 |
+ p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW)); |
|
194 |
+ |
|
195 |
+ /* Command-line "." and ".." are real directories. */ |
|
196 |
+ if (p->fts_info == FTS_DOT) |
|
197 |
+ p->fts_info = FTS_D; |
|
198 |
+ |
|
199 |
+ /* |
|
200 | 200 |
* If comparison routine supplied, traverse in sorted |
201 | 201 |
* order; otherwise traverse in the order specified. |
202 | 202 |
*/ |
203 |
- if (compar) { |
|
204 |
- p->fts_link = root; |
|
205 |
- root = p; |
|
206 |
- } else { |
|
207 |
- p->fts_link = NULL; |
|
208 |
- if (root == NULL) |
|
209 |
- tmp = root = p; |
|
210 |
- else { |
|
211 |
- tmp->fts_link = p; |
|
212 |
- tmp = p; |
|
213 |
- } |
|
214 |
- } |
|
215 |
- } |
|
216 |
- if (compar && nitems > 1) |
|
217 |
- root = fts_sort(sp, root, nitems); |
|
218 |
- |
|
219 |
- /* |
|
203 |
+ if (compar) { |
|
204 |
+ p->fts_link = root; |
|
205 |
+ root = p; |
|
206 |
+ } else { |
|
207 |
+ p->fts_link = NULL; |
|
208 |
+ if (root == NULL) |
|
209 |
+ tmp = root = p; |
|
210 |
+ else { |
|
211 |
+ tmp->fts_link = p; |
|
212 |
+ tmp = p; |
|
213 |
+ } |
|
214 |
+ } |
|
215 |
+ } |
|
216 |
+ if (compar && nitems > 1) |
|
217 |
+ root = fts_sort(sp, root, nitems); |
|
218 |
+ |
|
219 |
+ /* |
|
220 | 220 |
* Allocate a dummy pointer and make fts_read think that we've just |
221 | 221 |
* finished the node before the root(s); set p->fts_info to FTS_INIT |
222 | 222 |
* so that everything about the "current" node is ignored. |
223 | 223 |
*/ |
224 |
- if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL) |
|
225 |
- goto mem3; |
|
226 |
- sp->fts_cur->fts_link = root; |
|
227 |
- sp->fts_cur->fts_info = FTS_INIT; |
|
224 |
+ if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL) |
|
225 |
+ goto mem3; |
|
226 |
+ sp->fts_cur->fts_link = root; |
|
227 |
+ sp->fts_cur->fts_info = FTS_INIT; |
|
228 | 228 |
|
229 |
- /* |
|
229 |
+ /* |
|
230 | 230 |
* If using chdir(2), grab a file descriptor pointing to dot to ensure |
231 | 231 |
* that we can get back here; this could be avoided for some paths, |
232 | 232 |
* but almost certainly not worth the effort. Slashes, symbolic links, |
233 | 233 |
* and ".." are all fairly nasty problems. Note, if we can't get the |
234 | 234 |
* descriptor we run anyway, just more slowly. |
235 | 235 |
*/ |
236 |
- if (!ISSET(FTS_NOCHDIR) |
|
237 |
- && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0) |
|
238 |
- SET(FTS_NOCHDIR); |
|
239 |
- |
|
240 |
- return (sp); |
|
241 |
- |
|
242 |
-mem3: fts_lfree(root); |
|
243 |
- free(parent); |
|
244 |
-mem2: free(sp->fts_path); |
|
245 |
-mem1: free(sp); |
|
246 |
- return (NULL); |
|
236 |
+ if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0) |
|
237 |
+ SET(FTS_NOCHDIR); |
|
238 |
+ |
|
239 |
+ return (sp); |
|
240 |
+ |
|
241 |
+mem3: |
|
242 |
+ fts_lfree(root); |
|
243 |
+ free(parent); |
|
244 |
+mem2: |
|
245 |
+ free(sp->fts_path); |
|
246 |
+mem1: |
|
247 |
+ free(sp); |
|
248 |
+ return (NULL); |
|
247 | 249 |
} |
248 | 250 |
|
249 | 251 |
static void |
250 |
-internal_function |
|
251 |
-fts_load (FTSOBJ *sp, FTSENTRY *p) |
|
252 |
+ internal_function |
|
253 |
+ fts_load(FTSOBJ *sp, FTSENTRY *p) |
|
252 | 254 |
{ |
253 |
- int len; |
|
254 |
- char *cp; |
|
255 |
+ int len; |
|
256 |
+ char *cp; |
|
255 | 257 |
|
256 |
- /* |
|
258 |
+ /* |
|
257 | 259 |
* Load the stream structure for the next traversal. Since we don't |
258 | 260 |
* actually enter the directory until after the preorder visit, set |
259 | 261 |
* the fts_accpath field specially so the chdir gets done to the right |
260 | 262 |
* place and the user can access the first node. From fts_open it's |
261 | 263 |
* known that the path will fit. |
262 | 264 |
*/ |
263 |
- len = p->fts_pathlen = p->fts_namelen; |
|
264 |
- memmove(sp->fts_path, p->fts_name, len + 1); |
|
265 |
- if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) { |
|
266 |
- len = strlen(++cp); |
|
267 |
- memmove(p->fts_name, cp, len + 1); |
|
268 |
- p->fts_namelen = len; |
|
269 |
- } |
|
270 |
- p->fts_accpath = p->fts_path = sp->fts_path; |
|
271 |
- sp->fts_dev = p->fts_dev; |
|
265 |
+ len = p->fts_pathlen = p->fts_namelen; |
|
266 |
+ memmove(sp->fts_path, p->fts_name, len + 1); |
|
267 |
+ if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) { |
|
268 |
+ len = strlen(++cp); |
|
269 |
+ memmove(p->fts_name, cp, len + 1); |
|
270 |
+ p->fts_namelen = len; |
|
271 |
+ } |
|
272 |
+ p->fts_accpath = p->fts_path = sp->fts_path; |
|
273 |
+ sp->fts_dev = p->fts_dev; |
|
272 | 274 |
} |
273 | 275 |
|
274 |
-int |
|
275 |
-FTS_CLOSE (FTSOBJ *sp) |
|
276 |
+int FTS_CLOSE(FTSOBJ *sp) |
|
276 | 277 |
{ |
277 |
- FTSENTRY *freep, *p; |
|
278 |
- int saved_errno; |
|
278 |
+ FTSENTRY *freep, *p; |
|
279 |
+ int saved_errno; |
|
279 | 280 |
|
280 |
- /* |
|
281 |
+ /* |
|
281 | 282 |
* This still works if we haven't read anything -- the dummy structure |
282 | 283 |
* points to the root list, so we step through to the end of the root |
283 | 284 |
* list which has a valid parent pointer. |
284 | 285 |
*/ |
285 |
- if (sp->fts_cur) { |
|
286 |
- for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) { |
|
287 |
- freep = p; |
|
288 |
- p = p->fts_link != NULL ? p->fts_link : p->fts_parent; |
|
289 |
- free(freep); |
|
290 |
- } |
|
291 |
- free(p); |
|
292 |
- } |
|
293 |
- |
|
294 |
- /* Free up child linked list, sort array, path buffer. */ |
|
295 |
- if (sp->fts_child) |
|
296 |
- fts_lfree(sp->fts_child); |
|
297 |
- free(sp->fts_array); |
|
298 |
- free(sp->fts_path); |
|
299 |
- |
|
300 |
- /* Return to original directory, save errno if necessary. */ |
|
301 |
- if (!ISSET(FTS_NOCHDIR)) { |
|
302 |
- saved_errno = fchdir(sp->fts_rfd) ? errno : 0; |
|
303 |
- (void)close(sp->fts_rfd); |
|
304 |
- |
|
305 |
- /* Set errno and return. */ |
|
306 |
- if (saved_errno != 0) { |
|
307 |
- /* Free up the stream pointer. */ |
|
308 |
- free(sp); |
|
309 |
- __set_errno (saved_errno); |
|
310 |
- return (-1); |
|
311 |
- } |
|
312 |
- } |
|
313 |
- |
|
314 |
- /* Free up the stream pointer. */ |
|
315 |
- free(sp); |
|
316 |
- return (0); |
|
286 |
+ if (sp->fts_cur) { |
|
287 |
+ for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) { |
|
288 |
+ freep = p; |
|
289 |
+ p = p->fts_link != NULL ? p->fts_link : p->fts_parent; |
|
290 |
+ free(freep); |
|
291 |
+ } |
|
292 |
+ free(p); |
|
293 |
+ } |
|
294 |
+ |
|
295 |
+ /* Free up child linked list, sort array, path buffer. */ |
|
296 |
+ if (sp->fts_child) |
|
297 |
+ fts_lfree(sp->fts_child); |
|
298 |
+ free(sp->fts_array); |
|
299 |
+ free(sp->fts_path); |
|
300 |
+ |
|
301 |
+ /* Return to original directory, save errno if necessary. */ |
|
302 |
+ if (!ISSET(FTS_NOCHDIR)) { |
|
303 |
+ saved_errno = fchdir(sp->fts_rfd) ? errno : 0; |
|
304 |
+ (void)close(sp->fts_rfd); |
|
305 |
+ |
|
306 |
+ /* Set errno and return. */ |
|
307 |
+ if (saved_errno != 0) { |
|
308 |
+ /* Free up the stream pointer. */ |
|
309 |
+ free(sp); |
|
310 |
+ __set_errno(saved_errno); |
|
311 |
+ return (-1); |
|
312 |
+ } |
|
313 |
+ } |
|
314 |
+ |
|
315 |
+ /* Free up the stream pointer. */ |
|
316 |
+ free(sp); |
|
317 |
+ return (0); |
|
317 | 318 |
} |
318 | 319 |
|
319 | 320 |
/* |
320 | 321 |
* Special case of "/" at the end of the path so that slashes aren't |
321 | 322 |
* appended which would cause paths to be written as "....//foo". |
322 | 323 |
*/ |
323 |
-#define NAPPEND(p) \ |
|
324 |
- (p->fts_path[p->fts_pathlen - 1] == '/' \ |
|
325 |
- ? p->fts_pathlen - 1 : p->fts_pathlen) |
|
324 |
+#define NAPPEND(p) \ |
|
325 |
+ (p->fts_path[p->fts_pathlen - 1] == '/' \ |
|
326 |
+ ? p->fts_pathlen - 1 \ |
|
327 |
+ : p->fts_pathlen) |
|
326 | 328 |
|
327 | 329 |
FTSENTRY * |
328 |
-FTS_READ (FTSOBJ *sp) |
|
330 |
+FTS_READ(FTSOBJ *sp) |
|
329 | 331 |
{ |
330 |
- FTSENTRY *p, *tmp; |
|
331 |
- int instr; |
|
332 |
- char *t; |
|
333 |
- int saved_errno; |
|
332 |
+ FTSENTRY *p, *tmp; |
|
333 |
+ int instr; |
|
334 |
+ char *t; |
|
335 |
+ int saved_errno; |
|
334 | 336 |
|
335 |
- /* If finished or unrecoverable error, return NULL. */ |
|
336 |
- if (sp->fts_cur == NULL || ISSET(FTS_STOP)) |
|
337 |
- return (NULL); |
|
337 |
+ /* If finished or unrecoverable error, return NULL. */ |
|
338 |
+ if (sp->fts_cur == NULL || ISSET(FTS_STOP)) |
|
339 |
+ return (NULL); |
|
338 | 340 |
|
339 |
- /* Set current node pointer. */ |
|
340 |
- p = sp->fts_cur; |
|
341 |
+ /* Set current node pointer. */ |
|
342 |
+ p = sp->fts_cur; |
|
341 | 343 |
|
342 |
- /* Save and zero out user instructions. */ |
|
343 |
- instr = p->fts_instr; |
|
344 |
- p->fts_instr = FTS_NOINSTR; |
|
344 |
+ /* Save and zero out user instructions. */ |
|
345 |
+ instr = p->fts_instr; |
|
346 |
+ p->fts_instr = FTS_NOINSTR; |
|
345 | 347 |
|
346 |
- /* Any type of file may be re-visited; re-stat and re-turn. */ |
|
347 |
- if (instr == FTS_AGAIN) { |
|
348 |
- p->fts_info = fts_stat(sp, p, 0); |
|
349 |
- return (p); |
|
350 |
- } |
|
348 |
+ /* Any type of file may be re-visited; re-stat and re-turn. */ |
|
349 |
+ if (instr == FTS_AGAIN) { |
|
350 |
+ p->fts_info = fts_stat(sp, p, 0); |
|
351 |
+ return (p); |
|
352 |
+ } |
|
351 | 353 |
|
352 |
- /* |
|
354 |
+ /* |
|
353 | 355 |
* Following a symlink -- SLNONE test allows application to see |
354 | 356 |
* SLNONE and recover. If indirecting through a symlink, have |
355 | 357 |
* keep a pointer to current location. If unable to get that |
356 | 358 |
* pointer, follow fails. |
357 | 359 |
*/ |
358 |
- if (instr == FTS_FOLLOW && |
|
359 |
- (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { |
|
360 |
- p->fts_info = fts_stat(sp, p, 1); |
|
361 |
- if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { |
|
362 |
- if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) { |
|
363 |
- p->fts_errno = errno; |
|
364 |
- p->fts_info = FTS_ERR; |
|
365 |
- } else |
|
366 |
- p->fts_flags |= FTS_SYMFOLLOW; |
|
367 |
- } |
|
368 |
- return (p); |
|
369 |
- } |
|
370 |
- |
|
371 |
- /* Directory in pre-order. */ |
|
372 |
- if (p->fts_info == FTS_D) { |
|
373 |
- /* If skipped or crossed mount point, do post-order visit. */ |
|
374 |
- if (instr == FTS_SKIP || |
|
375 |
- (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) { |
|
376 |
- if (p->fts_flags & FTS_SYMFOLLOW) |
|
377 |
- (void)close(p->fts_symfd); |
|
378 |
- if (sp->fts_child) { |
|
379 |
- fts_lfree(sp->fts_child); |
|
380 |
- sp->fts_child = NULL; |
|
381 |
- } |
|
382 |
- p->fts_info = FTS_DP; |
|
383 |
- return (p); |
|
384 |
- } |
|
385 |
- |
|
386 |
- /* Rebuild if only read the names and now traversing. */ |
|
387 |
- if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) { |
|
388 |
- CLR(FTS_NAMEONLY); |
|
389 |
- fts_lfree(sp->fts_child); |
|
390 |
- sp->fts_child = NULL; |
|
391 |
- } |
|
392 |
- |
|
393 |
- /* |
|
360 |
+ if (instr == FTS_FOLLOW && |
|
361 |
+ (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { |
|
362 |
+ p->fts_info = fts_stat(sp, p, 1); |
|
363 |
+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { |
|
364 |
+ if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) { |
|
365 |
+ p->fts_errno = errno; |
|
366 |
+ p->fts_info = FTS_ERR; |
|
367 |
+ } else |
|
368 |
+ p->fts_flags |= FTS_SYMFOLLOW; |
|
369 |
+ } |
|
370 |
+ return (p); |
|
371 |
+ } |
|
372 |
+ |
|
373 |
+ /* Directory in pre-order. */ |
|
374 |
+ if (p->fts_info == FTS_D) { |
|
375 |
+ /* If skipped or crossed mount point, do post-order visit. */ |
|
376 |
+ if (instr == FTS_SKIP || |
|
377 |
+ (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) { |
|
378 |
+ if (p->fts_flags & FTS_SYMFOLLOW) |
|
379 |
+ (void)close(p->fts_symfd); |
|
380 |
+ if (sp->fts_child) { |
|
381 |
+ fts_lfree(sp->fts_child); |
|
382 |
+ sp->fts_child = NULL; |
|
383 |
+ } |
|
384 |
+ p->fts_info = FTS_DP; |
|
385 |
+ return (p); |
|
386 |
+ } |
|
387 |
+ |
|
388 |
+ /* Rebuild if only read the names and now traversing. */ |
|
389 |
+ if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) { |
|
390 |
+ CLR(FTS_NAMEONLY); |
|
391 |
+ fts_lfree(sp->fts_child); |
|
392 |
+ sp->fts_child = NULL; |
|
393 |
+ } |
|
394 |
+ |
|
395 |
+ /* |
|
394 | 396 |
* Cd to the subdirectory. |
395 | 397 |
* |
396 | 398 |
* If have already read and now fail to chdir, whack the list |
... | ... |
@@ -402,115 +404,117 @@ FTS_READ (FTSOBJ *sp) |
402 | 402 |
* If haven't read do so. If the read fails, fts_build sets |
403 | 403 |
* FTS_STOP or the fts_info field of the node. |
404 | 404 |
*/ |
405 |
- if (sp->fts_child != NULL) { |
|
406 |
- if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) { |
|
407 |
- p->fts_errno = errno; |
|
408 |
- p->fts_flags |= FTS_DONTCHDIR; |
|
409 |
- for (p = sp->fts_child; p != NULL; |
|
410 |
- p = p->fts_link) |
|
411 |
- p->fts_accpath = |
|
412 |
- p->fts_parent->fts_accpath; |
|
413 |
- } |
|
414 |
- } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) { |
|
415 |
- if (ISSET(FTS_STOP)) |
|
416 |
- return (NULL); |
|
417 |
- return (p); |
|
418 |
- } |
|
419 |
- p = sp->fts_child; |
|
420 |
- sp->fts_child = NULL; |
|
421 |
- sp->fts_cur = p; |
|
422 |
- goto name; |
|
423 |
- } |
|
424 |
- |
|
425 |
- /* Move to the next node on this level. */ |
|
426 |
-next: tmp = p; |
|
427 |
- if ((p = p->fts_link) != NULL) { |
|
428 |
- sp->fts_cur = p; |
|
429 |
- free(tmp); |
|
430 |
- |
|
431 |
- /* |
|
405 |
+ if (sp->fts_child != NULL) { |
|
406 |
+ if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) { |
|
407 |
+ p->fts_errno = errno; |
|
408 |
+ p->fts_flags |= FTS_DONTCHDIR; |
|
409 |
+ for (p = sp->fts_child; p != NULL; |
|
410 |
+ p = p->fts_link) |
|
411 |
+ p->fts_accpath = |
|
412 |
+ p->fts_parent->fts_accpath; |
|
413 |
+ } |
|
414 |
+ } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) { |
|
415 |
+ if (ISSET(FTS_STOP)) |
|
416 |
+ return (NULL); |
|
417 |
+ return (p); |
|
418 |
+ } |
|
419 |
+ p = sp->fts_child; |
|
420 |
+ sp->fts_child = NULL; |
|
421 |
+ sp->fts_cur = p; |
|
422 |
+ goto name; |
|
423 |
+ } |
|
424 |
+ |
|
425 |
+ /* Move to the next node on this level. */ |
|
426 |
+next: |
|
427 |
+ tmp = p; |
|
428 |
+ if ((p = p->fts_link) != NULL) { |
|
429 |
+ sp->fts_cur = p; |
|
430 |
+ free(tmp); |
|
431 |
+ |
|
432 |
+ /* |
|
432 | 433 |
* If reached the top, return to the original directory (or |
433 | 434 |
* the root of the tree), and load the paths for the next root. |
434 | 435 |
*/ |
435 |
- if (p->fts_level == FTS_ROOTLEVEL) { |
|
436 |
- if (FCHDIR(sp, sp->fts_rfd)) { |
|
437 |
- SET(FTS_STOP); |
|
438 |
- return (NULL); |
|
439 |
- } |
|
440 |
- fts_load(sp, p); |
|
441 |
- return p; |
|
442 |
- } |
|
443 |
- |
|
444 |
- /* |
|
436 |
+ if (p->fts_level == FTS_ROOTLEVEL) { |
|
437 |
+ if (FCHDIR(sp, sp->fts_rfd)) { |
|
438 |
+ SET(FTS_STOP); |
|
439 |
+ return (NULL); |
|
440 |
+ } |
|
441 |
+ fts_load(sp, p); |
|
442 |
+ return p; |
|
443 |
+ } |
|
444 |
+ |
|
445 |
+ /* |
|
445 | 446 |
* User may have called fts_set on the node. If skipped, |
446 | 447 |
* ignore. If followed, get a file descriptor so we can |
447 | 448 |
* get back if necessary. |
448 | 449 |
*/ |
449 |
- if (p->fts_instr == FTS_SKIP) |
|
450 |
- goto next; |
|
451 |
- if (p->fts_instr == FTS_FOLLOW) { |
|
452 |
- p->fts_info = fts_stat(sp, p, 1); |
|
453 |
- if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { |
|
454 |
- if ((p->fts_symfd = |
|
455 |
- open(".", O_RDONLY, 0)) < 0) { |
|
456 |
- p->fts_errno = errno; |
|
457 |
- p->fts_info = FTS_ERR; |
|
458 |
- } else |
|
459 |
- p->fts_flags |= FTS_SYMFOLLOW; |
|
460 |
- } |
|
461 |
- p->fts_instr = FTS_NOINSTR; |
|
462 |
- } |
|
463 |
- |
|
464 |
-name: t = sp->fts_path + NAPPEND(p->fts_parent); |
|
465 |
- *t++ = '/'; |
|
466 |
- memmove(t, p->fts_name, p->fts_namelen + 1); |
|
467 |
- return p; |
|
468 |
- } |
|
469 |
- |
|
470 |
- /* Move up to the parent node. */ |
|
471 |
- p = tmp->fts_parent; |
|
472 |
- sp->fts_cur = p; |
|
473 |
- free(tmp); |
|
474 |
- |
|
475 |
- if (p->fts_level == FTS_ROOTPARENTLEVEL) { |
|
476 |
- /* |
|
450 |
+ if (p->fts_instr == FTS_SKIP) |
|
451 |
+ goto next; |
|
452 |
+ if (p->fts_instr == FTS_FOLLOW) { |
|
453 |
+ p->fts_info = fts_stat(sp, p, 1); |
|
454 |
+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { |
|
455 |
+ if ((p->fts_symfd = |
|
456 |
+ open(".", O_RDONLY, 0)) < 0) { |
|
457 |
+ p->fts_errno = errno; |
|
458 |
+ p->fts_info = FTS_ERR; |
|
459 |
+ } else |
|
460 |
+ p->fts_flags |= FTS_SYMFOLLOW; |
|
461 |
+ } |
|
462 |
+ p->fts_instr = FTS_NOINSTR; |
|
463 |
+ } |
|
464 |
+ |
|
465 |
+ name: |
|
466 |
+ t = sp->fts_path + NAPPEND(p->fts_parent); |
|
467 |
+ *t++ = '/'; |
|
468 |
+ memmove(t, p->fts_name, p->fts_namelen + 1); |
|
469 |
+ return p; |
|
470 |
+ } |
|
471 |
+ |
|
472 |
+ /* Move up to the parent node. */ |
|
473 |
+ p = tmp->fts_parent; |
|
474 |
+ sp->fts_cur = p; |
|
475 |
+ free(tmp); |
|
476 |
+ |
|
477 |
+ if (p->fts_level == FTS_ROOTPARENTLEVEL) { |
|
478 |
+ /* |
|
477 | 479 |
* Done; free everything up and set errno to 0 so the user |
478 | 480 |
* can distinguish between error and EOF. |
479 | 481 |
*/ |
480 |
- free(p); |
|
481 |
- __set_errno (0); |
|
482 |
- return (sp->fts_cur = NULL); |
|
483 |
- } |
|
482 |
+ free(p); |
|
483 |
+ __set_errno(0); |
|
484 |
+ return (sp->fts_cur = NULL); |
|
485 |
+ } |
|
484 | 486 |
|
485 |
- /* NUL terminate the pathname. */ |
|
486 |
- sp->fts_path[p->fts_pathlen] = '\0'; |
|
487 |
+ /* NUL terminate the pathname. */ |
|
488 |
+ sp->fts_path[p->fts_pathlen] = '\0'; |
|
487 | 489 |
|
488 |
- /* |
|
490 |
+ /* |
|
489 | 491 |
* Return to the parent directory. If at a root node or came through |
490 | 492 |
* a symlink, go back through the file descriptor. Otherwise, cd up |
491 | 493 |
* one directory. |
492 | 494 |
*/ |
493 |
- if (p->fts_level == FTS_ROOTLEVEL) { |
|
494 |
- if (FCHDIR(sp, sp->fts_rfd)) { |
|
495 |
- SET(FTS_STOP); |
|
496 |
- return (NULL); |
|
497 |
- } |
|
498 |
- } else if (p->fts_flags & FTS_SYMFOLLOW) { |
|
499 |
- if (FCHDIR(sp, p->fts_symfd)) { |
|
500 |
- saved_errno = errno; |
|
501 |
- (void)close(p->fts_symfd); |
|
502 |
- __set_errno (saved_errno); |
|
503 |
- SET(FTS_STOP); |
|
504 |
- return (NULL); |
|
505 |
- } |
|
506 |
- (void)close(p->fts_symfd); |
|
507 |
- } else if (!(p->fts_flags & FTS_DONTCHDIR) && |
|
508 |
- fts_safe_changedir(sp, p->fts_parent, -1, "..")) { |
|
509 |
- SET(FTS_STOP); |
|
510 |
- return (NULL); |
|
511 |
- } |
|
512 |
- p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; |
|
513 |
- return p; |
|
495 |
+ if (p->fts_level == FTS_ROOTLEVEL) { |
|
496 |
+ if (FCHDIR(sp, sp->fts_rfd)) { |
|
497 |
+ SET(FTS_STOP); |
|
498 |
+ return (NULL); |
|
499 |
+ } |
|
500 |
+ } else if (p->fts_flags & FTS_SYMFOLLOW) { |
|
501 |
+ if (FCHDIR(sp, p->fts_symfd)) { |
|
502 |
+ saved_errno = errno; |
|
503 |
+ (void)close(p->fts_symfd); |
|
504 |
+ __set_errno(saved_errno); |
|
505 |
+ SET(FTS_STOP); |
|
506 |
+ return (NULL); |
|
507 |
+ } |
|
508 |
+ (void)close(p->fts_symfd); |
|
509 |
+ } else if (!(p->fts_flags & FTS_DONTCHDIR) && |
|
510 |
+ fts_safe_changedir(sp, p->fts_parent, -1, "..")) { |
|
511 |
+ SET(FTS_STOP); |
|
512 |
+ return (NULL); |
|
513 |
+ } |
|
514 |
+ p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; |
|
515 |
+ return p; |
|
514 | 516 |
} |
515 | 517 |
|
516 | 518 |
/* |
... | ... |
@@ -520,91 +524,90 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent); |
520 | 520 |
* reasons. |
521 | 521 |
*/ |
522 | 522 |
/* ARGSUSED */ |
523 |
-int |
|
524 |
-FTS_SET (FTSOBJ *sp, FTSENTRY *p, int instr) |
|
523 |
+int FTS_SET(FTSOBJ *sp, FTSENTRY *p, int instr) |
|
525 | 524 |
{ |
526 |
- if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW && |
|
527 |
- instr != FTS_NOINSTR && instr != FTS_SKIP) { |
|
528 |
- __set_errno (EINVAL); |
|
529 |
- return (1); |
|
530 |
- } |
|
531 |
- p->fts_instr = instr; |
|
532 |
- return (0); |
|
525 |
+ if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW && |
|
526 |
+ instr != FTS_NOINSTR && instr != FTS_SKIP) { |
|
527 |
+ __set_errno(EINVAL); |
|
528 |
+ return (1); |
|
529 |
+ } |
|
530 |
+ p->fts_instr = instr; |
|
531 |
+ return (0); |
|
533 | 532 |
} |
534 | 533 |
|
535 | 534 |
FTSENTRY * |
536 | 535 |
FTS_CHILDREN(FTSOBJ *sp, int instr) |
537 | 536 |
{ |
538 |
- FTSENTRY *p; |
|
539 |
- int fd; |
|
537 |
+ FTSENTRY *p; |
|
538 |
+ int fd; |
|
540 | 539 |
|
541 |
- if (instr != 0 && instr != FTS_NAMEONLY) { |
|
542 |
- __set_errno (EINVAL); |
|
543 |
- return (NULL); |
|
544 |
- } |
|
540 |
+ if (instr != 0 && instr != FTS_NAMEONLY) { |
|
541 |
+ __set_errno(EINVAL); |
|
542 |
+ return (NULL); |
|
543 |
+ } |
|
545 | 544 |
|
546 |
- /* Set current node pointer. */ |
|
547 |
- p = sp->fts_cur; |
|
545 |
+ /* Set current node pointer. */ |
|
546 |
+ p = sp->fts_cur; |
|
548 | 547 |
|
549 |
- /* |
|
548 |
+ /* |
|
550 | 549 |
* Errno set to 0 so user can distinguish empty directory from |
551 | 550 |
* an error. |
552 | 551 |
*/ |
553 |
- __set_errno (0); |
|
552 |
+ __set_errno(0); |
|
554 | 553 |
|
555 |
- /* Fatal errors stop here. */ |
|
556 |
- if (ISSET(FTS_STOP)) |
|
557 |
- return (NULL); |
|
554 |
+ /* Fatal errors stop here. */ |
|
555 |
+ if (ISSET(FTS_STOP)) |
|
556 |
+ return (NULL); |
|
558 | 557 |
|
559 |
- /* Return logical hierarchy of user's arguments. */ |
|
560 |
- if (p->fts_info == FTS_INIT) |
|
561 |
- return (p->fts_link); |
|
558 |
+ /* Return logical hierarchy of user's arguments. */ |
|
559 |
+ if (p->fts_info == FTS_INIT) |
|
560 |
+ return (p->fts_link); |
|
562 | 561 |
|
563 |
- /* |
|
562 |
+ /* |
|
564 | 563 |
* If not a directory being visited in pre-order, stop here. Could |
565 | 564 |
* allow FTS_DNR, assuming the user has fixed the problem, but the |
566 | 565 |
* same effect is available with FTS_AGAIN. |
567 | 566 |
*/ |
568 |
- if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */) |
|
569 |
- return (NULL); |
|
567 |
+ if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */) |
|
568 |
+ return (NULL); |
|
570 | 569 |
|
571 |
- /* Free up any previous child list. */ |
|
572 |
- if (sp->fts_child != NULL) |
|
573 |
- fts_lfree(sp->fts_child); |
|
570 |
+ /* Free up any previous child list. */ |
|
571 |
+ if (sp->fts_child != NULL) |
|
572 |
+ fts_lfree(sp->fts_child); |
|
574 | 573 |
|
575 |
- if (instr == FTS_NAMEONLY) { |
|
576 |
- SET(FTS_NAMEONLY); |
|
577 |
- instr = BNAMES; |
|
578 |
- } else |
|
579 |
- instr = BCHILD; |
|
574 |
+ if (instr == FTS_NAMEONLY) { |
|
575 |
+ SET(FTS_NAMEONLY); |
|
576 |
+ instr = BNAMES; |
|
577 |
+ } else |
|
578 |
+ instr = BCHILD; |
|
580 | 579 |
|
581 |
- /* |
|
580 |
+ /* |
|
582 | 581 |
* If using chdir on a relative path and called BEFORE fts_read does |
583 | 582 |
* its chdir to the root of a traversal, we can lose -- we need to |
584 | 583 |
* chdir into the subdirectory, and we don't know where the current |
585 | 584 |
* directory is, so we can't get back so that the upcoming chdir by |
586 | 585 |
* fts_read will work. |
587 | 586 |
*/ |
588 |
- if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' || |
|
589 |
- ISSET(FTS_NOCHDIR)) |
|
590 |
- return (sp->fts_child = fts_build(sp, instr)); |
|
591 |
- |
|
592 |
- if ((fd = open(".", O_RDONLY, 0)) < 0) |
|
593 |
- return (NULL); |
|
594 |
- sp->fts_child = fts_build(sp, instr); |
|
595 |
- if (fchdir(fd)) |
|
596 |
- return (NULL); |
|
597 |
- (void)close(fd); |
|
598 |
- return (sp->fts_child); |
|
587 |
+ if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' || |
|
588 |
+ ISSET(FTS_NOCHDIR)) |
|
589 |
+ return (sp->fts_child = fts_build(sp, instr)); |
|
590 |
+ |
|
591 |
+ if ((fd = open(".", O_RDONLY, 0)) < 0) |
|
592 |
+ return (NULL); |
|
593 |
+ sp->fts_child = fts_build(sp, instr); |
|
594 |
+ if (fchdir(fd)) |
|
595 |
+ return (NULL); |
|
596 |
+ (void)close(fd); |
|
597 |
+ return (sp->fts_child); |
|
599 | 598 |
} |
600 | 599 |
|
601 | 600 |
static inline int |
602 | 601 |
dirent_not_directory(const struct dirent *dp) |
603 | 602 |
{ |
604 | 603 |
#if defined DT_DIR && defined _DIRENT_HAVE_D_TYPE |
605 |
- return dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN; |
|
604 |
+ return dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN; |
|
606 | 605 |
#else |
607 |
- return 0; |
|
606 |
+ return 0; |
|
608 | 607 |
#endif |
609 | 608 |
} |
610 | 609 |
|
... | ... |
@@ -623,66 +626,66 @@ dirent_not_directory(const struct dirent *dp) |
623 | 623 |
* been found, cutting the stat calls by about 2/3. |
624 | 624 |
*/ |
625 | 625 |
static FTSENTRY * |
626 |
-internal_function |
|
627 |
-fts_build (FTSOBJ *sp, int type) |
|
626 |
+ internal_function |
|
627 |
+ fts_build(FTSOBJ *sp, int type) |
|
628 | 628 |
{ |
629 |
- struct dirent *dp; |
|
630 |
- FTSENTRY *p, *head; |
|
631 |
- int nitems; |
|
632 |
- FTSENTRY *cur, *tail; |
|
633 |
- DIR *dirp; |
|
634 |
- void *oldaddr; |
|
635 |
- int cderrno, descend, len, level, nlinks, saved_errno, |
|
636 |
- nostat, doadjust; |
|
637 |
- size_t maxlen; |
|
638 |
- char *cp; |
|
639 |
- |
|
640 |
- /* Set current node pointer. */ |
|
641 |
- cur = sp->fts_cur; |
|
642 |
- |
|
643 |
- /* |
|
629 |
+ struct dirent *dp; |
|
630 |
+ FTSENTRY *p, *head; |
|
631 |
+ int nitems; |
|
632 |
+ FTSENTRY *cur, *tail; |
|
633 |
+ DIR *dirp; |
|
634 |
+ void *oldaddr; |
|
635 |
+ int cderrno, descend, len, level, nlinks, saved_errno, |
|
636 |
+ nostat, doadjust; |
|
637 |
+ size_t maxlen; |
|
638 |
+ char *cp; |
|
639 |
+ |
|
640 |
+ /* Set current node pointer. */ |
|
641 |
+ cur = sp->fts_cur; |
|
642 |
+ |
|
643 |
+ /* |
|
644 | 644 |
* Open the directory for reading. If this fails, we're done. |
645 | 645 |
* If being called from fts_read, set the fts_info field. |
646 | 646 |
*/ |
647 | 647 |
#if defined FTS_WHITEOUT && 0 |
648 |
- if (ISSET(FTS_WHITEOUT)) |
|
649 |
- oflag = DTF_NODUP|DTF_REWIND; |
|
650 |
- else |
|
651 |
- oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND; |
|
648 |
+ if (ISSET(FTS_WHITEOUT)) |
|
649 |
+ oflag = DTF_NODUP | DTF_REWIND; |
|
650 |
+ else |
|
651 |
+ oflag = DTF_HIDEW | DTF_NODUP | DTF_REWIND; |
|
652 | 652 |
#else |
653 |
-# define __opendir2(path, flag) opendir(path) |
|
653 |
+#define __opendir2(path, flag) opendir(path) |
|
654 | 654 |
#endif |
655 |
- if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) { |
|
656 |
- if (type == BREAD) { |
|
657 |
- cur->fts_info = FTS_DNR; |
|
658 |
- cur->fts_errno = errno; |
|
659 |
- } |
|
660 |
- return (NULL); |
|
661 |
- } |
|
662 |
- |
|
663 |
- /* |
|
655 |
+ if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) { |
|
656 |
+ if (type == BREAD) { |
|
657 |
+ cur->fts_info = FTS_DNR; |
|
658 |
+ cur->fts_errno = errno; |
|
659 |
+ } |
|
660 |
+ return (NULL); |
|
661 |
+ } |
|
662 |
+ |
|
663 |
+ /* |
|
664 | 664 |
* Nlinks is the number of possible entries of type directory in the |
665 | 665 |
* directory if we're cheating on stat calls, 0 if we're not doing |
666 | 666 |
* any stat calls at all, -1 if we're doing stats on everything. |
667 | 667 |
*/ |
668 |
- if (type == BNAMES) { |
|
669 |
- nlinks = 0; |
|
670 |
- /* Be quiet about nostat, GCC. */ |
|
671 |
- nostat = 0; |
|
672 |
- } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) { |
|
673 |
- nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2); |
|
674 |
- nostat = 1; |
|
675 |
- } else { |
|
676 |
- nlinks = -1; |
|
677 |
- nostat = 0; |
|
678 |
- } |
|
668 |
+ if (type == BNAMES) { |
|
669 |
+ nlinks = 0; |
|
670 |
+ /* Be quiet about nostat, GCC. */ |
|
671 |
+ nostat = 0; |
|
672 |
+ } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) { |
|
673 |
+ nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2); |
|
674 |
+ nostat = 1; |
|
675 |
+ } else { |
|
676 |
+ nlinks = -1; |
|
677 |
+ nostat = 0; |
|
678 |
+ } |
|
679 | 679 |
|
680 | 680 |
#ifdef notdef |
681 |
- (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink); |
|
682 |
- (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n", |
|
683 |
- ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT)); |
|
681 |
+ (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink); |
|
682 |
+ (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n", |
|
683 |
+ ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT)); |
|
684 | 684 |
#endif |
685 |
- /* |
|
685 |
+ /* |
|
686 | 686 |
* If we're going to need to stat anything or we want to descend |
687 | 687 |
* and stay in the directory, chdir. If this fails we keep going, |
688 | 688 |
* but set a flag so we don't chdir after the post-order visit. |
... | ... |
@@ -697,22 +700,22 @@ fts_build (FTSOBJ *sp, int type) |
697 | 697 |
* needed sorted entries or stat information, they had better be |
698 | 698 |
* checking FTS_NS on the returned nodes. |
699 | 699 |
*/ |
700 |
- cderrno = 0; |
|
701 |
- if (nlinks || type == BREAD) { |
|
702 |
- if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) { |
|
703 |
- if (nlinks && type == BREAD) |
|
704 |
- cur->fts_errno = errno; |
|
705 |
- cur->fts_flags |= FTS_DONTCHDIR; |
|
706 |
- descend = 0; |
|
707 |
- cderrno = errno; |
|
708 |
- (void)closedir(dirp); |
|
709 |
- dirp = NULL; |
|
710 |
- } else |
|
711 |
- descend = 1; |
|
712 |
- } else |
|
713 |
- descend = 0; |
|
714 |
- |
|
715 |
- /* |
|
700 |
+ cderrno = 0; |
|
701 |
+ if (nlinks || type == BREAD) { |
|
702 |
+ if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) { |
|
703 |
+ if (nlinks && type == BREAD) |
|
704 |
+ cur->fts_errno = errno; |
|
705 |
+ cur->fts_flags |= FTS_DONTCHDIR; |
|
706 |
+ descend = 0; |
|
707 |
+ cderrno = errno; |
|
708 |
+ (void)closedir(dirp); |
|
709 |
+ dirp = NULL; |
|
710 |
+ } else |
|
711 |
+ descend = 1; |
|
712 |
+ } else |
|
713 |
+ descend = 0; |
|
714 |
+ |
|
715 |
+ /* |
|
716 | 716 |
* Figure out the max file name length that can be stored in the |
717 | 717 |
* current path -- the inner loop allocates more path as necessary. |
718 | 718 |
* We really wouldn't have to do the maxlen calculations here, we |
... | ... |
@@ -722,293 +725,292 @@ fts_build (FTSOBJ *sp, int type) |
722 | 722 |
* If not changing directories set a pointer so that can just append |
723 | 723 |
* each new name into the path. |
724 | 724 |
*/ |
725 |
- len = NAPPEND(cur); |
|
726 |
- if (ISSET(FTS_NOCHDIR)) { |
|
727 |
- cp = sp->fts_path + len; |
|
728 |
- *cp++ = '/'; |
|
729 |
- } else { |
|
730 |
- /* GCC, you're too verbose. */ |
|
731 |
- cp = NULL; |
|
732 |
- } |
|
733 |
- len++; |
|
734 |
- maxlen = sp->fts_pathlen - len; |
|
735 |
- |
|
736 |
- level = cur->fts_level + 1; |
|
737 |
- |
|
738 |
- /* Read the directory, attaching each entry to the `link' pointer. */ |
|
739 |
- doadjust = 0; |
|
740 |
- for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) { |
|
741 |
- if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) |
|
742 |
- continue; |
|
743 |
- |
|
744 |
- if ((p = fts_alloc(sp, dp->d_name, _D_EXACT_NAMLEN (dp))) == NULL) |
|
745 |
- goto mem1; |
|
746 |
- if (_D_EXACT_NAMLEN (dp) >= maxlen) {/* include space for NUL */ |
|
747 |
- oldaddr = sp->fts_path; |
|
748 |
- if (fts_palloc(sp, _D_EXACT_NAMLEN (dp) + len + 1)) { |
|
749 |
- /* |
|
725 |
+ len = NAPPEND(cur); |
|
726 |
+ if (ISSET(FTS_NOCHDIR)) { |
|
727 |
+ cp = sp->fts_path + len; |
|
728 |
+ *cp++ = '/'; |
|
729 |
+ } else { |
|
730 |
+ /* GCC, you're too verbose. */ |
|
731 |
+ cp = NULL; |
|
732 |
+ } |
|
733 |
+ len++; |
|
734 |
+ maxlen = sp->fts_pathlen - len; |
|
735 |
+ |
|
736 |
+ level = cur->fts_level + 1; |
|
737 |
+ |
|
738 |
+ /* Read the directory, attaching each entry to the `link' pointer. */ |
|
739 |
+ doadjust = 0; |
|
740 |
+ for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) { |
|
741 |
+ if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) |
|
742 |
+ continue; |
|
743 |
+ |
|
744 |
+ if ((p = fts_alloc(sp, dp->d_name, _D_EXACT_NAMLEN(dp))) == NULL) |
|
745 |
+ goto mem1; |
|
746 |
+ if (_D_EXACT_NAMLEN(dp) >= maxlen) { /* include space for NUL */ |
|
747 |
+ oldaddr = sp->fts_path; |
|
748 |
+ if (fts_palloc(sp, _D_EXACT_NAMLEN(dp) + len + 1)) { |
|
749 |
+ /* |
|
750 | 750 |
* No more memory for path or structures. Save |
751 | 751 |
* errno, free up the current structure and the |
752 | 752 |
* structures already allocated. |
753 | 753 |
*/ |
754 |
-mem1: saved_errno = errno; |
|
755 |
- free(p); |
|
756 |
- fts_lfree(head); |
|
757 |
- (void)closedir(dirp); |
|
758 |
- cur->fts_info = FTS_ERR; |
|
759 |
- SET(FTS_STOP); |
|
760 |
- __set_errno (saved_errno); |
|
761 |
- return (NULL); |
|
762 |
- } |
|
763 |
- /* Did realloc() change the pointer? */ |
|
764 |
- if (oldaddr != sp->fts_path) { |
|
765 |
- doadjust = 1; |
|
766 |
- if (ISSET(FTS_NOCHDIR)) |
|
767 |
- cp = sp->fts_path + len; |
|
768 |
- } |
|
769 |
- maxlen = sp->fts_pathlen - len; |
|
770 |
- } |
|
771 |
- |
|
772 |
- if (len + _D_EXACT_NAMLEN (dp) >= USHRT_MAX) { |
|
773 |
- /* |
|
754 |
+ mem1: |
|
755 |
+ saved_errno = errno; |
|
756 |
+ free(p); |
|
757 |
+ fts_lfree(head); |
|
758 |
+ (void)closedir(dirp); |
|
759 |
+ cur->fts_info = FTS_ERR; |
|
760 |
+ SET(FTS_STOP); |
|
761 |
+ __set_errno(saved_errno); |
|
762 |
+ return (NULL); |
|
763 |
+ } |
|
764 |
+ /* Did realloc() change the pointer? */ |
|
765 |
+ if (oldaddr != sp->fts_path) { |
|
766 |
+ doadjust = 1; |
|
767 |
+ if (ISSET(FTS_NOCHDIR)) |
|
768 |
+ cp = sp->fts_path + len; |
|
769 |
+ } |
|
770 |
+ maxlen = sp->fts_pathlen - len; |
|
771 |
+ } |
|
772 |
+ |
|
773 |
+ if (len + _D_EXACT_NAMLEN(dp) >= USHRT_MAX) { |
|
774 |
+ /* |
|
774 | 775 |
* In an FTSENT, fts_pathlen is a u_short so it is |
775 | 776 |
* possible to wraparound here. If we do, free up |
776 | 777 |
* the current structure and the structures already |
777 | 778 |
* allocated, then error out with ENAMETOOLONG. |
778 | 779 |
*/ |
779 |
- free(p); |
|
780 |
- fts_lfree(head); |
|
781 |
- (void)closedir(dirp); |
|
782 |
- cur->fts_info = FTS_ERR; |
|
783 |
- SET(FTS_STOP); |
|
784 |
- __set_errno (ENAMETOOLONG); |
|
785 |
- return (NULL); |
|
786 |
- } |
|
787 |
- p->fts_level = level; |
|
788 |
- p->fts_parent = sp->fts_cur; |
|
789 |
- p->fts_pathlen = len + _D_EXACT_NAMLEN (dp); |
|
780 |
+ free(p); |
|
781 |
+ fts_lfree(head); |
|
782 |
+ (void)closedir(dirp); |
|
783 |
+ cur->fts_info = FTS_ERR; |
|
784 |
+ SET(FTS_STOP); |
|
785 |
+ __set_errno(ENAMETOOLONG); |
|
786 |
+ return (NULL); |
|
787 |
+ } |
|
788 |
+ p->fts_level = level; |
|
789 |
+ p->fts_parent = sp->fts_cur; |
|
790 |
+ p->fts_pathlen = len + _D_EXACT_NAMLEN(dp); |
|
790 | 791 |
|
791 | 792 |
#if defined FTS_WHITEOUT && 0 |
792 |
- if (dp->d_type == DT_WHT) |
|
793 |
- p->fts_flags |= FTS_ISW; |
|
793 |
+ if (dp->d_type == DT_WHT) |
|
794 |
+ p->fts_flags |= FTS_ISW; |
|
794 | 795 |
#endif |
795 | 796 |
|
796 |
- /* Unreachable code. cderrno is only ever set to a nonnull |
|
797 |
+ /* Unreachable code. cderrno is only ever set to a nonnull |
|
797 | 798 |
value if dirp is closed at the same time. But then we |
798 | 799 |
cannot enter this loop. */ |
799 |
- if (0 && cderrno) { |
|
800 |
- if (nlinks) { |
|
801 |
- p->fts_info = FTS_NS; |
|
802 |
- p->fts_errno = cderrno; |
|
803 |
- } else |
|
804 |
- p->fts_info = FTS_NSOK; |
|
805 |
- p->fts_accpath = cur->fts_accpath; |
|
806 |
- } else if (nlinks == 0 |
|
807 |
- || (nostat && dirent_not_directory(dp))) { |
|
808 |
- p->fts_accpath = |
|
809 |
- ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name; |
|
810 |
- p->fts_info = FTS_NSOK; |
|
811 |
- } else { |
|
812 |
- /* Build a file name for fts_stat to stat. */ |
|
813 |
- if (ISSET(FTS_NOCHDIR)) { |
|
814 |
- p->fts_accpath = p->fts_path; |
|
815 |
- memmove(cp, p->fts_name, p->fts_namelen + 1); |
|
816 |
- } else |
|
817 |
- p->fts_accpath = p->fts_name; |
|
818 |
- /* Stat it. */ |
|
819 |
- p->fts_info = fts_stat(sp, p, 0); |
|
820 |
- |
|
821 |
- /* Decrement link count if applicable. */ |
|
822 |
- if (nlinks > 0 && (p->fts_info == FTS_D || |
|
823 |
- p->fts_info == FTS_DC || p->fts_info == FTS_DOT)) |
|
824 |
- --nlinks; |
|
825 |
- } |
|
826 |
- |
|
827 |
- /* We walk in directory order so "ls -f" doesn't get upset. */ |
|
828 |
- p->fts_link = NULL; |
|
829 |
- if (head == NULL) |
|
830 |
- head = tail = p; |
|
831 |
- else { |
|
832 |
- tail->fts_link = p; |
|
833 |
- tail = p; |
|
834 |
- } |
|
835 |
- ++nitems; |
|
836 |
- } |
|
837 |
- if (dirp) |
|
838 |
- (void)closedir(dirp); |
|
839 |
- |
|
840 |
- /* |
|
800 |
+ if (0 && cderrno) { |
|
801 |
+ if (nlinks) { |
|
802 |
+ p->fts_info = FTS_NS; |
|
803 |
+ p->fts_errno = cderrno; |
|
804 |
+ } else |
|
805 |
+ p->fts_info = FTS_NSOK; |
|
806 |
+ p->fts_accpath = cur->fts_accpath; |
|
807 |
+ } else if (nlinks == 0 || (nostat && dirent_not_directory(dp))) { |
|
808 |
+ p->fts_accpath = |
|
809 |
+ ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name; |
|
810 |
+ p->fts_info = FTS_NSOK; |
|
811 |
+ } else { |
|
812 |
+ /* Build a file name for fts_stat to stat. */ |
|
813 |
+ if (ISSET(FTS_NOCHDIR)) { |
|
814 |
+ p->fts_accpath = p->fts_path; |
|
815 |
+ memmove(cp, p->fts_name, p->fts_namelen + 1); |
|
816 |
+ } else |
|
817 |
+ p->fts_accpath = p->fts_name; |
|
818 |
+ /* Stat it. */ |
|
819 |
+ p->fts_info = fts_stat(sp, p, 0); |
|
820 |
+ |
|
821 |
+ /* Decrement link count if applicable. */ |
|
822 |
+ if (nlinks > 0 && (p->fts_info == FTS_D || |
|
823 |
+ p->fts_info == FTS_DC || p->fts_info == FTS_DOT)) |
|
824 |
+ --nlinks; |
|
825 |
+ } |
|
826 |
+ |
|
827 |
+ /* We walk in directory order so "ls -f" doesn't get upset. */ |
|
828 |
+ p->fts_link = NULL; |
|
829 |
+ if (head == NULL) |
|
830 |
+ head = tail = p; |
|
831 |
+ else { |
|
832 |
+ tail->fts_link = p; |
|
833 |
+ tail = p; |
|
834 |
+ } |
|
835 |
+ ++nitems; |
|
836 |
+ } |
|
837 |
+ if (dirp) |
|
838 |
+ (void)closedir(dirp); |
|
839 |
+ |
|
840 |
+ /* |
|
841 | 841 |
* If realloc() changed the address of the path, adjust the |
842 | 842 |
* addresses for the rest of the tree and the dir list. |
843 | 843 |
*/ |
844 |
- if (doadjust) |
|
845 |
- fts_padjust(sp, head); |
|
844 |
+ if (doadjust) |
|
845 |
+ fts_padjust(sp, head); |
|
846 | 846 |
|
847 |
- /* |
|
847 |
+ /* |
|
848 | 848 |
* If not changing directories, reset the path back to original |
849 | 849 |
* state. |
850 | 850 |
*/ |
851 |
- if (ISSET(FTS_NOCHDIR)) { |
|
852 |
- if (len == sp->fts_pathlen || nitems == 0) |
|
853 |
- --cp; |
|
854 |
- *cp = '\0'; |
|
855 |
- } |
|
851 |
+ if (ISSET(FTS_NOCHDIR)) { |
|
852 |
+ if (len == sp->fts_pathlen || nitems == 0) |
|
853 |
+ --cp; |
|
854 |
+ *cp = '\0'; |
|
855 |
+ } |
|
856 | 856 |
|
857 |
- /* |
|
857 |
+ /* |
|
858 | 858 |
* If descended after called from fts_children or after called from |
859 | 859 |
* fts_read and nothing found, get back. At the root level we use |
860 | 860 |
* the saved fd; if one of fts_open()'s arguments is a relative path |
861 | 861 |
* to an empty directory, we wind up here with no other way back. If |
862 | 862 |
* can't get back, we're done. |
863 | 863 |
*/ |
864 |
- if (descend && (type == BCHILD || !nitems) && |
|
865 |
- (cur->fts_level == FTS_ROOTLEVEL ? |
|
866 |
- FCHDIR(sp, sp->fts_rfd) : |
|
867 |
- fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) { |
|
868 |
- cur->fts_info = FTS_ERR; |
|
869 |
- SET(FTS_STOP); |
|
870 |
- fts_lfree(head); |
|
871 |
- return (NULL); |
|
872 |
- } |
|
873 |
- |
|
874 |
- /* If didn't find anything, return NULL. */ |
|
875 |
- if (!nitems) { |
|
876 |
- if (type == BREAD) |
|
877 |
- cur->fts_info = FTS_DP; |
|
878 |
- fts_lfree(head); |
|
879 |
- return (NULL); |
|
880 |
- } |
|
881 |
- |
|
882 |
- /* Sort the entries. */ |
|
883 |
- if (sp->fts_compar && nitems > 1) |
|
884 |
- head = fts_sort(sp, head, nitems); |
|
885 |
- return (head); |
|
864 |
+ if (descend && (type == BCHILD || !nitems) && |
|
865 |
+ (cur->fts_level == FTS_ROOTLEVEL ? FCHDIR(sp, sp->fts_rfd) : fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) { |
|
866 |
+ cur->fts_info = FTS_ERR; |
|
867 |
+ SET(FTS_STOP); |
|
868 |
+ fts_lfree(head); |
|
869 |
+ return (NULL); |
|
870 |
+ } |
|
871 |
+ |
|
872 |
+ /* If didn't find anything, return NULL. */ |
|
873 |
+ if (!nitems) { |
|
874 |
+ if (type == BREAD) |
|
875 |
+ cur->fts_info = FTS_DP; |
|
876 |
+ fts_lfree(head); |
|
877 |
+ return (NULL); |
|
878 |
+ } |
|
879 |
+ |
|
880 |
+ /* Sort the entries. */ |
|
881 |
+ if (sp->fts_compar && nitems > 1) |
|
882 |
+ head = fts_sort(sp, head, nitems); |
|
883 |
+ return (head); |
|
886 | 884 |
} |
887 | 885 |
|
888 | 886 |
static u_short |
889 |
-internal_function |
|
890 |
-fts_stat (FTSOBJ *sp, FTSENTRY *p, int follow) |
|
887 |
+ internal_function |
|
888 |
+ fts_stat(FTSOBJ *sp, FTSENTRY *p, int follow) |
|
891 | 889 |
{ |
892 |
- FTSENTRY *t; |
|
893 |
- dev_t dev; |
|
894 |
- INO_T ino; |
|
895 |
- struct STAT *sbp, sb; |
|
896 |
- int saved_errno; |
|
890 |
+ FTSENTRY *t; |
|
891 |
+ dev_t dev; |
|
892 |
+ INO_T ino; |
|
893 |
+ struct STAT *sbp, sb; |
|
894 |
+ int saved_errno; |
|
897 | 895 |
|
898 |
- /* If user needs stat info, stat buffer already allocated. */ |
|
899 |
- sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; |
|
896 |
+ /* If user needs stat info, stat buffer already allocated. */ |
|
897 |
+ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; |
|
900 | 898 |
|
901 | 899 |
#if defined FTS_WHITEOUT && 0 |
902 |
- /* check for whiteout */ |
|
903 |
- if (p->fts_flags & FTS_ISW) { |
|
904 |
- if (sbp != &sb) { |
|
905 |
- memset(sbp, '\0', sizeof (*sbp)); |
|
906 |
- sbp->st_mode = S_IFWHT; |
|
907 |
- } |
|
908 |
- return (FTS_W); |
|
909 |
- } |
|
900 |
+ /* check for whiteout */ |
|
901 |
+ if (p->fts_flags & FTS_ISW) { |
|
902 |
+ if (sbp != &sb) { |
|
903 |
+ memset(sbp, '\0', sizeof(*sbp)); |
|
904 |
+ sbp->st_mode = S_IFWHT; |
|
905 |
+ } |
|
906 |
+ return (FTS_W); |
|
907 |
+ } |
|
910 | 908 |
#endif |
911 | 909 |
|
912 |
- /* |
|
910 |
+ /* |
|
913 | 911 |
* If doing a logical walk, or application requested FTS_FOLLOW, do |
914 | 912 |
* a stat(2). If that fails, check for a non-existent symlink. If |
915 | 913 |
* fail, set the errno from the stat call. |
916 | 914 |
*/ |
917 |
- if (ISSET(FTS_LOGICAL) || follow) { |
|
918 |
- if (STAT(p->fts_accpath, sbp)) { |
|
919 |
- saved_errno = errno; |
|
920 |
- if (!LSTAT(p->fts_accpath, sbp)) { |
|
921 |
- __set_errno (0); |
|
922 |
- return (FTS_SLNONE); |
|
923 |
- } |
|
924 |
- p->fts_errno = saved_errno; |
|
925 |
- goto err; |
|
926 |
- } |
|
927 |
- } else if (LSTAT(p->fts_accpath, sbp)) { |
|
928 |
- p->fts_errno = errno; |
|
929 |
-err: memset(sbp, 0, sizeof(struct STAT)); |
|
930 |
- return (FTS_NS); |
|
931 |
- } |
|
932 |
- |
|
933 |
- if (S_ISDIR(sbp->st_mode)) { |
|
934 |
- /* |
|
915 |
+ if (ISSET(FTS_LOGICAL) || follow) { |
|
916 |
+ if (STAT(p->fts_accpath, sbp)) { |
|
917 |
+ saved_errno = errno; |
|
918 |
+ if (!LSTAT(p->fts_accpath, sbp)) { |
|
919 |
+ __set_errno(0); |
|
920 |
+ return (FTS_SLNONE); |
|
921 |
+ } |
|
922 |
+ p->fts_errno = saved_errno; |
|
923 |
+ goto err; |
|
924 |
+ } |
|
925 |
+ } else if (LSTAT(p->fts_accpath, sbp)) { |
|
926 |
+ p->fts_errno = errno; |
|
927 |
+ err: |
|
928 |
+ memset(sbp, 0, sizeof(struct STAT)); |
|
929 |
+ return (FTS_NS); |
|
930 |
+ } |
|
931 |
+ |
|
932 |
+ if (S_ISDIR(sbp->st_mode)) { |
|
933 |
+ /* |
|
935 | 934 |
* Set the device/inode. Used to find cycles and check for |
936 | 935 |
* crossing mount points. Also remember the link count, used |
937 | 936 |
* in fts_build to limit the number of stat calls. It is |
938 | 937 |
* understood that these fields are only referenced if fts_info |
939 | 938 |
* is set to FTS_D. |
940 | 939 |
*/ |
941 |
- dev = p->fts_dev = sbp->st_dev; |
|
942 |
- ino = p->fts_ino = sbp->st_ino; |
|
943 |
- p->fts_nlink = sbp->st_nlink; |
|
940 |
+ dev = p->fts_dev = sbp->st_dev; |
|
941 |
+ ino = p->fts_ino = sbp->st_ino; |
|
942 |
+ p->fts_nlink = sbp->st_nlink; |
|
944 | 943 |
|
945 |
- if (ISDOT(p->fts_name)) |
|
946 |
- return (FTS_DOT); |
|
944 |
+ if (ISDOT(p->fts_name)) |
|
945 |
+ return (FTS_DOT); |
|
947 | 946 |
|
948 |
- /* |
|
947 |
+ /* |
|
949 | 948 |
* Cycle detection is done by brute force when the directory |
950 | 949 |
* is first encountered. If the tree gets deep enough or the |
951 | 950 |
* number of symbolic links to directories is high enough, |
952 | 951 |
* something faster might be worthwhile. |
953 | 952 |
*/ |
954 |
- for (t = p->fts_parent; |
|
955 |
- t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent) |
|
956 |
- if (ino == t->fts_ino && dev == t->fts_dev) { |
|
957 |
- p->fts_cycle = t; |
|
958 |
- return (FTS_DC); |
|
959 |
- } |
|
960 |
- return (FTS_D); |
|
961 |
- } |
|
962 |
- if (S_ISLNK(sbp->st_mode)) |
|
963 |
- return (FTS_SL); |
|
964 |
- if (S_ISREG(sbp->st_mode)) |
|
965 |
- return (FTS_F); |
|
966 |
- return (FTS_DEFAULT); |
|
953 |
+ for (t = p->fts_parent; |
|
954 |
+ t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent) |
|
955 |
+ if (ino == t->fts_ino && dev == t->fts_dev) { |
|
956 |
+ p->fts_cycle = t; |
|
957 |
+ return (FTS_DC); |
|
958 |
+ } |
|
959 |
+ return (FTS_D); |
|
960 |
+ } |
|
961 |
+ if (S_ISLNK(sbp->st_mode)) |
|
962 |
+ return (FTS_SL); |
|
963 |
+ if (S_ISREG(sbp->st_mode)) |
|
964 |
+ return (FTS_F); |
|
965 |
+ return (FTS_DEFAULT); |
|
967 | 966 |
} |
968 | 967 |
|
969 | 968 |
static FTSENTRY * |
970 |
-internal_function |
|
971 |
-fts_sort (FTSOBJ *sp, FTSENTRY *head, int nitems) |
|
969 |
+ internal_function |
|
970 |
+ fts_sort(FTSOBJ *sp, FTSENTRY *head, int nitems) |
|
972 | 971 |
{ |
973 |
- FTSENTRY **ap, *p; |
|
972 |
+ FTSENTRY **ap, *p; |
|
974 | 973 |
|
975 |
- /* |
|
974 |
+ /* |
|
976 | 975 |
* Construct an array of pointers to the structures and call qsort(3). |
977 | 976 |
* Reassemble the array in the order returned by qsort. If unable to |
978 | 977 |
* sort for memory reasons, return the directory entries in their |
979 | 978 |
* current order. Allocate enough space for the current needs plus |
980 | 979 |
* 40 so don't realloc one entry at a time. |
981 | 980 |
*/ |
982 |
- if (nitems > sp->fts_nitems) { |
|
983 |
- FTSENTRY **a; |
|
984 |
- |
|
985 |
- sp->fts_nitems = nitems + 40; |
|
986 |
- if ((a = realloc(sp->fts_array, |
|
987 |
- (size_t)(sp->fts_nitems * sizeof(FTSENTRY *)))) == NULL) { |
|
988 |
- free(sp->fts_array); |
|
989 |
- sp->fts_array = NULL; |
|
990 |
- sp->fts_nitems = 0; |
|
991 |
- return (head); |
|
992 |
- } |
|
993 |
- sp->fts_array = a; |
|
994 |
- } |
|
995 |
- for (ap = sp->fts_array, p = head; p; p = p->fts_link) |
|
996 |
- *ap++ = p; |
|
997 |
- qsort((void *)sp->fts_array, nitems, sizeof(FTSENTRY *), sp->fts_compar); |
|
998 |
- for (head = *(ap = sp->fts_array); --nitems; ++ap) |
|
999 |
- ap[0]->fts_link = ap[1]; |
|
1000 |
- ap[0]->fts_link = NULL; |
|
1001 |
- return (head); |
|
981 |
+ if (nitems > sp->fts_nitems) { |
|
982 |
+ FTSENTRY **a; |
|
983 |
+ |
|
984 |
+ sp->fts_nitems = nitems + 40; |
|
985 |
+ if ((a = realloc(sp->fts_array, |
|
986 |
+ (size_t)(sp->fts_nitems * sizeof(FTSENTRY *)))) == NULL) { |
|
987 |
+ free(sp->fts_array); |
|
988 |
+ sp->fts_array = NULL; |
|
989 |
+ sp->fts_nitems = 0; |
|
990 |
+ return (head); |
|
991 |
+ } |
|
992 |
+ sp->fts_array = a; |
|
993 |
+ } |
|
994 |
+ for (ap = sp->fts_array, p = head; p; p = p->fts_link) |
|
995 |
+ *ap++ = p; |
|
996 |
+ qsort((void *)sp->fts_array, nitems, sizeof(FTSENTRY *), sp->fts_compar); |
|
997 |
+ for (head = *(ap = sp->fts_array); --nitems; ++ap) |
|
998 |
+ ap[0]->fts_link = ap[1]; |
|
999 |
+ ap[0]->fts_link = NULL; |
|
1000 |
+ return (head); |
|
1002 | 1001 |
} |
1003 | 1002 |
|
1004 | 1003 |
static FTSENTRY * |
1005 |
-internal_function |
|
1006 |
-fts_alloc (FTSOBJ *sp, const char *name, size_t namelen) |
|
1004 |
+ internal_function |
|
1005 |
+ fts_alloc(FTSOBJ *sp, const char *name, size_t namelen) |
|
1007 | 1006 |
{ |
1008 |
- FTSENTRY *p; |
|
1009 |
- size_t len; |
|
1007 |
+ FTSENTRY *p; |
|
1008 |
+ size_t len; |
|
1010 | 1009 |
|
1011 |
- /* |
|
1010 |
+ /* |
|
1012 | 1011 |
* The file name is a variable length array and no stat structure is |
1013 | 1012 |
* necessary if the user has set the nostat bit. Allocate the FTSENT |
1014 | 1013 |
* structure, the file name and the stat structure in one chunk, but |
... | ... |
@@ -1016,39 +1018,39 @@ fts_alloc (FTSOBJ *sp, const char *name, size_t namelen) |
1016 | 1016 |
* fts_name field is declared to be of size 1, the fts_name pointer is |
1017 | 1017 |
* namelen + 2 before the first possible address of the stat structure. |
1018 | 1018 |
*/ |
1019 |
- len = sizeof(FTSENTRY) + namelen; |
|
1020 |
- if (!ISSET(FTS_NOSTAT)) |
|
1021 |
- len += sizeof(struct STAT) + ALIGNBYTES; |
|
1022 |
- if ((p = malloc(len)) == NULL) |
|
1023 |
- return (NULL); |
|
1024 |
- |
|
1025 |
- /* Copy the name and guarantee NUL termination. */ |
|
1026 |
- memmove(p->fts_name, name, namelen); |
|
1027 |
- p->fts_name[namelen] = '\0'; |
|
1028 |
- |
|
1029 |
- if (!ISSET(FTS_NOSTAT)) |
|
1030 |
- p->fts_statp = (struct STAT *)ALIGN(p->fts_name + namelen + 2); |
|
1031 |
- p->fts_namelen = namelen; |
|
1032 |
- p->fts_path = sp->fts_path; |
|
1033 |
- p->fts_errno = 0; |
|
1034 |
- p->fts_flags = 0; |
|
1035 |
- p->fts_instr = FTS_NOINSTR; |
|
1036 |
- p->fts_number = 0; |
|
1037 |
- p->fts_pointer = NULL; |
|
1038 |
- return (p); |
|
1019 |
+ len = sizeof(FTSENTRY) + namelen; |
|
1020 |
+ if (!ISSET(FTS_NOSTAT)) |
|
1021 |
+ len += sizeof(struct STAT) + ALIGNBYTES; |
|
1022 |
+ if ((p = malloc(len)) == NULL) |
|
1023 |
+ return (NULL); |
|
1024 |
+ |
|
1025 |
+ /* Copy the name and guarantee NUL termination. */ |
|
1026 |
+ memmove(p->fts_name, name, namelen); |
|
1027 |
+ p->fts_name[namelen] = '\0'; |
|
1028 |
+ |
|
1029 |
+ if (!ISSET(FTS_NOSTAT)) |
|
1030 |
+ p->fts_statp = (struct STAT *)ALIGN(p->fts_name + namelen + 2); |
|
1031 |
+ p->fts_namelen = namelen; |
|
1032 |
+ p->fts_path = sp->fts_path; |
|
1033 |
+ p->fts_errno = 0; |
|
1034 |
+ p->fts_flags = 0; |
|
1035 |
+ p->fts_instr = FTS_NOINSTR; |
|
1036 |
+ p->fts_number = 0; |
|
1037 |
+ p->fts_pointer = NULL; |
|
1038 |
+ return (p); |
|
1039 | 1039 |
} |
1040 | 1040 |
|
1041 | 1041 |
static void |
1042 |
-internal_function |
|
1043 |
-fts_lfree (FTSENTRY *head) |
|
1042 |
+ internal_function |
|
1043 |
+ fts_lfree(FTSENTRY *head) |
|
1044 | 1044 |
{ |
1045 |
- FTSENTRY *p; |
|
1045 |
+ FTSENTRY *p; |
|
1046 | 1046 |
|
1047 |
- /* Free a linked list of structures. */ |
|
1048 |
- while ((p = head)) { |
|
1049 |
- head = head->fts_link; |
|
1050 |
- free(p); |
|
1051 |
- } |
|
1047 |
+ /* Free a linked list of structures. */ |
|
1048 |
+ while ((p = head)) { |
|
1049 |
+ head = head->fts_link; |
|
1050 |
+ free(p); |
|
1051 |
+ } |
|
1052 | 1052 |
} |
1053 | 1053 |
|
1054 | 1054 |
/* |
... | ... |
@@ -1058,31 +1060,31 @@ fts_lfree (FTSENTRY *head) |
1058 | 1058 |
* plus 256 bytes so don't realloc the path 2 bytes at a time. |
1059 | 1059 |
*/ |
1060 | 1060 |
static int |
1061 |
-internal_function |
|
1062 |
-fts_palloc (FTSOBJ *sp, size_t more) |
|
1061 |
+ internal_function |
|
1062 |
+ fts_palloc(FTSOBJ *sp, size_t more) |
|
1063 | 1063 |
{ |
1064 |
- char *p; |
|
1064 |
+ char *p; |
|
1065 | 1065 |
|
1066 |
- sp->fts_pathlen += more + 256; |
|
1067 |
- /* |
|
1066 |
+ sp->fts_pathlen += more + 256; |
|
1067 |
+ /* |
|
1068 | 1068 |
* Check for possible wraparound. In an FTS, fts_pathlen is |
1069 | 1069 |
* a signed int but in an FTSENT it is an unsigned short. |
1070 | 1070 |
* We limit fts_pathlen to USHRT_MAX to be safe in both cases. |
1071 | 1071 |
*/ |
1072 |
- if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) { |
|
1073 |
- free(sp->fts_path); |
|
1074 |
- sp->fts_path = NULL; |
|
1075 |
- __set_errno (ENAMETOOLONG); |
|
1076 |
- return (1); |
|
1077 |
- } |
|
1078 |
- p = realloc(sp->fts_path, sp->fts_pathlen); |
|
1079 |
- if (p == NULL) { |
|
1080 |
- free(sp->fts_path); |
|
1081 |
- sp->fts_path = NULL; |
|
1082 |
- return 1; |
|
1083 |
- } |
|
1084 |
- sp->fts_path = p; |
|
1085 |
- return 0; |
|
1072 |
+ if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) { |
|
1073 |
+ free(sp->fts_path); |
|
1074 |
+ sp->fts_path = NULL; |
|
1075 |
+ __set_errno(ENAMETOOLONG); |
|
1076 |
+ return (1); |
|
1077 |
+ } |
|
1078 |
+ p = realloc(sp->fts_path, sp->fts_pathlen); |
|
1079 |
+ if (p == NULL) { |
|
1080 |
+ free(sp->fts_path); |
|
1081 |
+ sp->fts_path = NULL; |
|
1082 |
+ return 1; |
|
1083 |
+ } |
|
1084 |
+ sp->fts_path = p; |
|
1085 |
+ return 0; |
|
1086 | 1086 |
} |
1087 | 1087 |
|
1088 | 1088 |
/* |
... | ... |
@@ -1090,40 +1092,41 @@ fts_palloc (FTSOBJ *sp, size_t more) |
1090 | 1090 |
* already returned. |
1091 | 1091 |
*/ |
1092 | 1092 |
static void |
1093 |
-internal_function |
|
1094 |
-fts_padjust (FTSOBJ *sp, FTSENTRY *head) |
|
1093 |
+ internal_function |
|
1094 |
+ fts_padjust(FTSOBJ *sp, FTSENTRY *head) |
|
1095 | 1095 |
{ |
1096 |
- FTSENTRY *p; |
|
1097 |
- char *addr = sp->fts_path; |
|
1098 |
- |
|
1099 |
-#define ADJUST(p) do { \ |
|
1100 |
- if ((p)->fts_accpath != (p)->fts_name) { \ |
|
1101 |
- (p)->fts_accpath = \ |
|
1102 |
- (char *)addr + ((p)->fts_accpath - (p)->fts_path); \ |
|
1103 |
- } \ |
|
1104 |
- (p)->fts_path = addr; \ |
|
1105 |
-} while (0) |
|
1106 |
- /* Adjust the current set of children. */ |
|
1107 |
- for (p = sp->fts_child; p; p = p->fts_link) |
|
1108 |
- ADJUST(p); |
|
1109 |
- |
|
1110 |
- /* Adjust the rest of the tree, including the current level. */ |
|
1111 |
- for (p = head; p->fts_level >= FTS_ROOTLEVEL;) { |
|
1112 |
- ADJUST(p); |
|
1113 |
- p = p->fts_link ? p->fts_link : p->fts_parent; |
|
1114 |
- } |
|
1096 |
+ FTSENTRY *p; |
|
1097 |
+ char *addr = sp->fts_path; |
|
1098 |
+ |
|
1099 |
+#define ADJUST(p) \ |
|
1100 |
+ do { \ |
|
1101 |
+ if ((p)->fts_accpath != (p)->fts_name) { \ |
|
1102 |
+ (p)->fts_accpath = \ |
|
1103 |
+ (char *)addr + ((p)->fts_accpath - (p)->fts_path); \ |
|
1104 |
+ } \ |
|
1105 |
+ (p)->fts_path = addr; \ |
|
1106 |
+ } while (0) |
|
1107 |
+ /* Adjust the current set of children. */ |
|
1108 |
+ for (p = sp->fts_child; p; p = p->fts_link) |
|
1109 |
+ ADJUST(p); |
|
1110 |
+ |
|
1111 |
+ /* Adjust the rest of the tree, including the current level. */ |
|
1112 |
+ for (p = head; p->fts_level >= FTS_ROOTLEVEL;) { |
|
1113 |
+ ADJUST(p); |
|
1114 |
+ p = p->fts_link ? p->fts_link : p->fts_parent; |
|
1115 |
+ } |
|
1115 | 1116 |
} |
1116 | 1117 |
|
1117 | 1118 |
static size_t |
1118 |
-internal_function |
|
1119 |
-fts_maxarglen (char * const *argv) |
|
1119 |
+ internal_function |
|
1120 |
+ fts_maxarglen(char *const *argv) |
|
1120 | 1121 |
{ |
1121 |
- size_t len, max; |
|
1122 |
+ size_t len, max; |
|
1122 | 1123 |
|
1123 |
- for (max = 0; *argv; ++argv) |
|
1124 |
- if ((len = strlen(*argv)) > max) |
|
1125 |
- max = len; |
|
1126 |
- return (max + 1); |
|
1124 |
+ for (max = 0; *argv; ++argv) |
|
1125 |
+ if ((len = strlen(*argv)) > max) |
|
1126 |
+ max = len; |
|
1127 |
+ return (max + 1); |
|
1127 | 1128 |
} |
1128 | 1129 |
|
1129 | 1130 |
/* |
... | ... |
@@ -1132,31 +1135,31 @@ fts_maxarglen (char * const *argv) |
1132 | 1132 |
* Assumes p->fts_dev and p->fts_ino are filled in. |
1133 | 1133 |
*/ |
1134 | 1134 |
static int |
1135 |
-internal_function |
|
1136 |
-fts_safe_changedir (FTSOBJ *sp, FTSENTRY *p, int fd, const char *path) |
|
1135 |
+ internal_function |
|
1136 |
+ fts_safe_changedir(FTSOBJ *sp, FTSENTRY *p, int fd, const char *path) |
|
1137 | 1137 |
{ |
1138 |
- int ret, oerrno, newfd; |
|
1139 |
- struct stat sb; |
|
1140 |
- |
|
1141 |
- newfd = fd; |
|
1142 |
- if (ISSET(FTS_NOCHDIR)) |
|
1143 |
- return (0); |
|
1144 |
- if (fd < 0 && (newfd = open(path, O_RDONLY, 0)) < 0) |
|
1145 |
- return (-1); |
|
1146 |
- if (fstat(newfd, &sb)) { |
|
1147 |
- ret = -1; |
|
1148 |
- goto bail; |
|
1149 |
- } |
|
1150 |
- if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) { |
|
1151 |
- __set_errno (ENOENT); /* disinformation */ |
|
1152 |
- ret = -1; |
|
1153 |
- goto bail; |
|
1154 |
- } |
|
1155 |
- ret = fchdir(newfd); |
|
1138 |
+ int ret, oerrno, newfd; |
|
1139 |
+ struct stat sb; |
|
1140 |
+ |
|
1141 |
+ newfd = fd; |
|
1142 |
+ if (ISSET(FTS_NOCHDIR)) |
|
1143 |
+ return (0); |
|
1144 |
+ if (fd < 0 && (newfd = open(path, O_RDONLY, 0)) < 0) |
|
1145 |
+ return (-1); |
|
1146 |
+ if (fstat(newfd, &sb)) { |
|
1147 |
+ ret = -1; |
|
1148 |
+ goto bail; |
|
1149 |
+ } |
|
1150 |
+ if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) { |
|
1151 |
+ __set_errno(ENOENT); /* disinformation */ |
|
1152 |
+ ret = -1; |
|
1153 |
+ goto bail; |
|
1154 |
+ } |
|
1155 |
+ ret = fchdir(newfd); |
|
1156 | 1156 |
bail: |
1157 |
- oerrno = errno; |
|
1158 |
- if (fd < 0) |
|
1159 |
- (void)close(newfd); |
|
1160 |
- __set_errno (oerrno); |
|
1161 |
- return (ret); |
|
1157 |
+ oerrno = errno; |
|
1158 |
+ if (fd < 0) |
|
1159 |
+ (void)close(newfd); |
|
1160 |
+ __set_errno(oerrno); |
|
1161 |
+ return (ret); |
|
1162 | 1162 |
} |
... | ... |
@@ -5,28 +5,28 @@ |
5 | 5 |
|
6 | 6 |
static inline FTSENT *_priv_fts_children(FTS *ftsp, int options) |
7 | 7 |
{ |
8 |
- return fts_children(ftsp, options); |
|
8 |
+ return fts_children(ftsp, options); |
|
9 | 9 |
} |
10 | 10 |
|
11 | 11 |
static inline int _priv_fts_close(FTS *ftsp) |
12 | 12 |
{ |
13 |
- return fts_close(ftsp); |
|
13 |
+ return fts_close(ftsp); |
|
14 | 14 |
} |
15 | 15 |
|
16 |
-static inline FTS *_priv_fts_open (char * const *path_argv, int options, |
|
17 |
- int (*compar)(const FTSENT **, const FTSENT **)) |
|
16 |
+static inline FTS *_priv_fts_open(char *const *path_argv, int options, |
|
17 |
+ int (*compar)(const FTSENT **, const FTSENT **)) |
|
18 | 18 |
{ |
19 |
- return fts_open(path_argv, options, compar); |
|
19 |
+ return fts_open(path_argv, options, compar); |
|
20 | 20 |
} |
21 | 21 |
|
22 |
-static inline FTSENT *_priv_fts_read (FTS *ftsp) |
|
22 |
+static inline FTSENT *_priv_fts_read(FTS *ftsp) |
|
23 | 23 |
{ |
24 |
- return fts_read(ftsp); |
|
24 |
+ return fts_read(ftsp); |
|
25 | 25 |
} |
26 | 26 |
|
27 |
-static inline int _priv_fts_set (FTS *ftsp, FTSENT *f, int options) |
|
27 |
+static inline int _priv_fts_set(FTS *ftsp, FTSENT *f, int options) |
|
28 | 28 |
{ |
29 |
- return fts_set(ftsp, f, options); |
|
29 |
+ return fts_set(ftsp, f, options); |
|
30 | 30 |
} |
31 | 31 |
|
32 | 32 |
#else |
... | ... |
@@ -79,142 +79,141 @@ static inline int _priv_fts_set (FTS *ftsp, FTSENT *f, int options) |
79 | 79 |
* @(#)fts.h 8.3 (Berkeley) 8/14/94 |
80 | 80 |
*/ |
81 | 81 |
|
82 |
-#ifndef _FTS_H |
|
83 |
-#define _FTS_H 1 |
|
82 |
+#ifndef _FTS_H |
|
83 |
+#define _FTS_H 1 |
|
84 | 84 |
|
85 | 85 |
#include <sys/types.h> |
86 | 86 |
|
87 |
- |
|
88 | 87 |
typedef struct { |
89 |
- struct _ftsent *fts_cur; /* current node */ |
|
90 |
- struct _ftsent *fts_child; /* linked list of children */ |
|
91 |
- struct _ftsent **fts_array; /* sort array */ |
|
92 |
- dev_t fts_dev; /* starting device # */ |
|
93 |
- char *fts_path; /* path for this descent */ |
|
94 |
- int fts_rfd; /* fd for root */ |
|
95 |
- int fts_pathlen; /* sizeof(path) */ |
|
96 |
- int fts_nitems; /* elements in the sort array */ |
|
97 |
- int (*fts_compar) (const void *, const void *); /* compare fn */ |
|
98 |
- |
|
99 |
-#define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */ |
|
100 |
-#define FTS_LOGICAL 0x0002 /* logical walk */ |
|
101 |
-#define FTS_NOCHDIR 0x0004 /* don't change directories */ |
|
102 |
-#define FTS_NOSTAT 0x0008 /* don't get stat info */ |
|
103 |
-#define FTS_PHYSICAL 0x0010 /* physical walk */ |
|
104 |
-#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */ |
|
105 |
-#define FTS_XDEV 0x0040 /* don't cross devices */ |
|
106 |
-#define FTS_WHITEOUT 0x0080 /* return whiteout information */ |
|
107 |
-#define FTS_OPTIONMASK 0x00ff /* valid user option mask */ |
|
108 |
- |
|
109 |
-#define FTS_NAMEONLY 0x0100 /* (private) child names only */ |
|
110 |
-#define FTS_STOP 0x0200 /* (private) unrecoverable error */ |
|
111 |
- int fts_options; /* fts_open options, global flags */ |
|
88 |
+ struct _ftsent *fts_cur; /* current node */ |
|
89 |
+ struct _ftsent *fts_child; /* linked list of children */ |
|
90 |
+ struct _ftsent **fts_array; /* sort array */ |
|
91 |
+ dev_t fts_dev; /* starting device # */ |
|
92 |
+ char *fts_path; /* path for this descent */ |
|
93 |
+ int fts_rfd; /* fd for root */ |
|
94 |
+ int fts_pathlen; /* sizeof(path) */ |
|
95 |
+ int fts_nitems; /* elements in the sort array */ |
|
96 |
+ int (*fts_compar)(const void *, const void *); /* compare fn */ |
|
97 |
+ |
|
98 |
+#define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */ |
|
99 |
+#define FTS_LOGICAL 0x0002 /* logical walk */ |
|
100 |
+#define FTS_NOCHDIR 0x0004 /* don't change directories */ |
|
101 |
+#define FTS_NOSTAT 0x0008 /* don't get stat info */ |
|
102 |
+#define FTS_PHYSICAL 0x0010 /* physical walk */ |
|
103 |
+#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */ |
|
104 |
+#define FTS_XDEV 0x0040 /* don't cross devices */ |
|
105 |
+#define FTS_WHITEOUT 0x0080 /* return whiteout information */ |
|
106 |
+#define FTS_OPTIONMASK 0x00ff /* valid user option mask */ |
|
107 |
+ |
|
108 |
+#define FTS_NAMEONLY 0x0100 /* (private) child names only */ |
|
109 |
+#define FTS_STOP 0x0200 /* (private) unrecoverable error */ |
|
110 |
+ int fts_options; /* fts_open options, global flags */ |
|
112 | 111 |
} FTS; |
113 | 112 |
|
114 | 113 |
#ifdef __USE_LARGEFILE64 |
115 | 114 |
typedef struct { |
116 |
- struct _ftsent64 *fts_cur; /* current node */ |
|
117 |
- struct _ftsent64 *fts_child; /* linked list of children */ |
|
118 |
- struct _ftsent64 **fts_array; /* sort array */ |
|
119 |
- dev_t fts_dev; /* starting device # */ |
|
120 |
- char *fts_path; /* path for this descent */ |
|
121 |
- int fts_rfd; /* fd for root */ |
|
122 |
- int fts_pathlen; /* sizeof(path) */ |
|
123 |
- int fts_nitems; /* elements in the sort array */ |
|
124 |
- int (*fts_compar) (const void *, const void *); /* compare fn */ |
|
125 |
- int fts_options; /* fts_open options, global flags */ |
|
115 |
+ struct _ftsent64 *fts_cur; /* current node */ |
|
116 |
+ struct _ftsent64 *fts_child; /* linked list of children */ |
|
117 |
+ struct _ftsent64 **fts_array; /* sort array */ |
|
118 |
+ dev_t fts_dev; /* starting device # */ |
|
119 |
+ char *fts_path; /* path for this descent */ |
|
120 |
+ int fts_rfd; /* fd for root */ |
|
121 |
+ int fts_pathlen; /* sizeof(path) */ |
|
122 |
+ int fts_nitems; /* elements in the sort array */ |
|
123 |
+ int (*fts_compar)(const void *, const void *); /* compare fn */ |
|
124 |
+ int fts_options; /* fts_open options, global flags */ |
|
126 | 125 |
} FTS64; |
127 | 126 |
#endif |
128 | 127 |
|
129 | 128 |
typedef struct _ftsent { |
130 |
- struct _ftsent *fts_cycle; /* cycle node */ |
|
131 |
- struct _ftsent *fts_parent; /* parent directory */ |
|
132 |
- struct _ftsent *fts_link; /* next file in directory */ |
|
133 |
- long fts_number; /* local numeric value */ |
|
134 |
- void *fts_pointer; /* local address value */ |
|
135 |
- char *fts_accpath; /* access path */ |
|
136 |
- char *fts_path; /* root path */ |
|
137 |
- int fts_errno; /* errno for this node */ |
|
138 |
- int fts_symfd; /* fd for symlink */ |
|
139 |
- u_short fts_pathlen; /* strlen(fts_path) */ |
|
140 |
- u_short fts_namelen; /* strlen(fts_name) */ |
|
141 |
- |
|
142 |
- ino_t fts_ino; /* inode */ |
|
143 |
- dev_t fts_dev; /* device */ |
|
144 |
- nlink_t fts_nlink; /* link count */ |
|
145 |
- |
|
146 |
-#define FTS_ROOTPARENTLEVEL -1 |
|
147 |
-#define FTS_ROOTLEVEL 0 |
|
148 |
- short fts_level; /* depth (-1 to N) */ |
|
149 |
- |
|
150 |
-#define FTS_D 1 /* preorder directory */ |
|
151 |
-#define FTS_DC 2 /* directory that causes cycles */ |
|
152 |
-#define FTS_DEFAULT 3 /* none of the above */ |
|
153 |
-#define FTS_DNR 4 /* unreadable directory */ |
|
154 |
-#define FTS_DOT 5 /* dot or dot-dot */ |
|
155 |
-#define FTS_DP 6 /* postorder directory */ |
|
156 |
-#define FTS_ERR 7 /* error; errno is set */ |
|
157 |
-#define FTS_F 8 /* regular file */ |
|
158 |
-#define FTS_INIT 9 /* initialized only */ |
|
159 |
-#define FTS_NS 10 /* stat(2) failed */ |
|
160 |
-#define FTS_NSOK 11 /* no stat(2) requested */ |
|
161 |
-#define FTS_SL 12 /* symbolic link */ |
|
162 |
-#define FTS_SLNONE 13 /* symbolic link without target */ |
|
163 |
-#define FTS_W 14 /* whiteout object */ |
|
164 |
- u_short fts_info; /* user flags for FTSENT structure */ |
|
165 |
- |
|
166 |
-#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ |
|
167 |
-#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ |
|
168 |
- u_short fts_flags; /* private flags for FTSENT structure */ |
|
169 |
- |
|
170 |
-#define FTS_AGAIN 1 /* read node again */ |
|
171 |
-#define FTS_FOLLOW 2 /* follow symbolic link */ |
|
172 |
-#define FTS_NOINSTR 3 /* no instructions */ |
|
173 |
-#define FTS_SKIP 4 /* discard node */ |
|
174 |
- u_short fts_instr; /* fts_set() instructions */ |
|
175 |
- |
|
176 |
- struct stat *fts_statp; /* stat(2) information */ |
|
177 |
- char fts_name[1]; /* file name */ |
|
129 |
+ struct _ftsent *fts_cycle; /* cycle node */ |
|
130 |
+ struct _ftsent *fts_parent; /* parent directory */ |
|
131 |
+ struct _ftsent *fts_link; /* next file in directory */ |
|
132 |
+ long fts_number; /* local numeric value */ |
|
133 |
+ void *fts_pointer; /* local address value */ |
|
134 |
+ char *fts_accpath; /* access path */ |
|
135 |
+ char *fts_path; /* root path */ |
|
136 |
+ int fts_errno; /* errno for this node */ |
|
137 |
+ int fts_symfd; /* fd for symlink */ |
|
138 |
+ u_short fts_pathlen; /* strlen(fts_path) */ |
|
139 |
+ u_short fts_namelen; /* strlen(fts_name) */ |
|
140 |
+ |
|
141 |
+ ino_t fts_ino; /* inode */ |
|
142 |
+ dev_t fts_dev; /* device */ |
|
143 |
+ nlink_t fts_nlink; /* link count */ |
|
144 |
+ |
|
145 |
+#define FTS_ROOTPARENTLEVEL -1 |
|
146 |
+#define FTS_ROOTLEVEL 0 |
|
147 |
+ short fts_level; /* depth (-1 to N) */ |
|
148 |
+ |
|
149 |
+#define FTS_D 1 /* preorder directory */ |
|
150 |
+#define FTS_DC 2 /* directory that causes cycles */ |
|
151 |
+#define FTS_DEFAULT 3 /* none of the above */ |
|
152 |
+#define FTS_DNR 4 /* unreadable directory */ |
|
153 |
+#define FTS_DOT 5 /* dot or dot-dot */ |
|
154 |
+#define FTS_DP 6 /* postorder directory */ |
|
155 |
+#define FTS_ERR 7 /* error; errno is set */ |
|
156 |
+#define FTS_F 8 /* regular file */ |
|
157 |
+#define FTS_INIT 9 /* initialized only */ |
|
158 |
+#define FTS_NS 10 /* stat(2) failed */ |
|
159 |
+#define FTS_NSOK 11 /* no stat(2) requested */ |
|
160 |
+#define FTS_SL 12 /* symbolic link */ |
|
161 |
+#define FTS_SLNONE 13 /* symbolic link without target */ |
|
162 |
+#define FTS_W 14 /* whiteout object */ |
|
163 |
+ u_short fts_info; /* user flags for FTSENT structure */ |
|
164 |
+ |
|
165 |
+#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ |
|
166 |
+#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ |
|
167 |
+ u_short fts_flags; /* private flags for FTSENT structure */ |
|
168 |
+ |
|
169 |
+#define FTS_AGAIN 1 /* read node again */ |
|
170 |
+#define FTS_FOLLOW 2 /* follow symbolic link */ |
|
171 |
+#define FTS_NOINSTR 3 /* no instructions */ |
|
172 |
+#define FTS_SKIP 4 /* discard node */ |
|
173 |
+ u_short fts_instr; /* fts_set() instructions */ |
|
174 |
+ |
|
175 |
+ struct stat *fts_statp; /* stat(2) information */ |
|
176 |
+ char fts_name[1]; /* file name */ |
|
178 | 177 |
} FTSENT; |
179 | 178 |
|
180 | 179 |
#ifdef __USE_LARGEFILE64 |
181 | 180 |
typedef struct _ftsent64 { |
182 |
- struct _ftsent64 *fts_cycle; /* cycle node */ |
|
183 |
- struct _ftsent64 *fts_parent; /* parent directory */ |
|
184 |
- struct _ftsent64 *fts_link; /* next file in directory */ |
|
185 |
- long fts_number; /* local numeric value */ |
|
186 |
- void *fts_pointer; /* local address value */ |
|
187 |
- char *fts_accpath; /* access path */ |
|
188 |
- char *fts_path; /* root path */ |
|
189 |
- int fts_errno; /* errno for this node */ |
|
190 |
- int fts_symfd; /* fd for symlink */ |
|
191 |
- u_short fts_pathlen; /* strlen(fts_path) */ |
|
192 |
- u_short fts_namelen; /* strlen(fts_name) */ |
|
181 |
+ struct _ftsent64 *fts_cycle; /* cycle node */ |
|
182 |
+ struct _ftsent64 *fts_parent; /* parent directory */ |
|
183 |
+ struct _ftsent64 *fts_link; /* next file in directory */ |
|
184 |
+ long fts_number; /* local numeric value */ |
|
185 |
+ void *fts_pointer; /* local address value */ |
|
186 |
+ char *fts_accpath; /* access path */ |
|
187 |
+ char *fts_path; /* root path */ |
|
188 |
+ int fts_errno; /* errno for this node */ |
|
189 |
+ int fts_symfd; /* fd for symlink */ |
|
190 |
+ u_short fts_pathlen; /* strlen(fts_path) */ |
|
191 |
+ u_short fts_namelen; /* strlen(fts_name) */ |
|
193 | 192 |
|
194 |
- ino64_t fts_ino; /* inode */ |
|
195 |
- dev_t fts_dev; /* device */ |
|
196 |
- nlink_t fts_nlink; /* link count */ |
|
193 |
+ ino64_t fts_ino; /* inode */ |
|
194 |
+ dev_t fts_dev; /* device */ |
|
195 |
+ nlink_t fts_nlink; /* link count */ |
|
197 | 196 |
|
198 |
- short fts_level; /* depth (-1 to N) */ |
|
197 |
+ short fts_level; /* depth (-1 to N) */ |
|
199 | 198 |
|
200 |
- u_short fts_info; /* user flags for FTSENT structure */ |
|
199 |
+ u_short fts_info; /* user flags for FTSENT structure */ |
|
201 | 200 |
|
202 |
- u_short fts_flags; /* private flags for FTSENT structure */ |
|
201 |
+ u_short fts_flags; /* private flags for FTSENT structure */ |
|
203 | 202 |
|
204 |
- u_short fts_instr; /* fts_set() instructions */ |
|
203 |
+ u_short fts_instr; /* fts_set() instructions */ |
|
205 | 204 |
|
206 |
- struct stat64 *fts_statp; /* stat(2) information */ |
|
207 |
- char fts_name[1]; /* file name */ |
|
205 |
+ struct stat64 *fts_statp; /* stat(2) information */ |
|
206 |
+ char fts_name[1]; /* file name */ |
|
208 | 207 |
} FTSENT64; |
209 | 208 |
#endif |
210 | 209 |
|
211 | 210 |
__BEGIN_DECLS |
212 |
-FTSENT *_priv_fts_children (FTS *, int); |
|
213 |
-int _priv_fts_close (FTS *); |
|
214 |
-FTS *_priv_fts_open (char * const *, int, |
|
215 |
- int (*)(const FTSENT **, const FTSENT **)); |
|
216 |
-FTSENT *_priv_fts_read (FTS *); |
|
217 |
-int _priv_fts_set (FTS *, FTSENT *, int) __THROW; |
|
211 |
+FTSENT *_priv_fts_children(FTS *, int); |
|
212 |
+int _priv_fts_close(FTS *); |
|
213 |
+FTS *_priv_fts_open(char *const *, int, |
|
214 |
+ int (*)(const FTSENT **, const FTSENT **)); |
|
215 |
+FTSENT *_priv_fts_read(FTS *); |
|
216 |
+int _priv_fts_set(FTS *, FTSENT *, int) __THROW; |
|
218 | 217 |
__END_DECLS |
219 | 218 |
|
220 | 219 |
#endif /* fts.h */ |
... | ... |
@@ -49,10 +49,10 @@ int onas_fan_checkowner(int pid, const struct optstruct *opts) |
49 | 49 |
struct passwd *pwd; |
50 | 50 |
char path[32]; |
51 | 51 |
STATBUF sb; |
52 |
- const struct optstruct *opt = NULL; |
|
53 |
- const struct optstruct *opt_root = NULL; |
|
52 |
+ const struct optstruct *opt = NULL; |
|
53 |
+ const struct optstruct *opt_root = NULL; |
|
54 | 54 |
const struct optstruct *opt_uname = NULL; |
55 |
- int retry = 0; |
|
55 |
+ int retry = 0; |
|
56 | 56 |
|
57 | 57 |
/* always ignore ourselves */ |
58 | 58 |
if (pid == (int)getpid()) { |
... | ... |
@@ -60,9 +60,9 @@ int onas_fan_checkowner(int pid, const struct optstruct *opts) |
60 | 60 |
} |
61 | 61 |
|
62 | 62 |
/* look up options */ |
63 |
- opt = optget(opts, "OnAccessExcludeUID"); |
|
64 |
- opt_root = optget(opts, "OnAccessExcludeRootUID"); |
|
65 |
- opt_uname = optget (opts, "OnAccessExcludeUname"); |
|
63 |
+ opt = optget(opts, "OnAccessExcludeUID"); |
|
64 |
+ opt_root = optget(opts, "OnAccessExcludeRootUID"); |
|
65 |
+ opt_uname = optget(opts, "OnAccessExcludeUname"); |
|
66 | 66 |
|
67 | 67 |
/* we can return immediately if no uid exclusions were requested */ |
68 | 68 |
if (!(opt->enabled || opt_root->enabled || opt_uname->enabled)) |
... | ... |
@@ -81,47 +81,46 @@ int onas_fan_checkowner(int pid, const struct optstruct *opts) |
81 | 81 |
} |
82 | 82 |
/* then check our unames */ |
83 | 83 |
if (opt_uname->enabled) { |
84 |
- while (opt_uname) |
|
85 |
- { |
|
84 |
+ while (opt_uname) { |
|
86 | 85 |
errno = 0; |
87 |
- pwd = getpwuid(sb.st_uid); |
|
88 |
- if (NULL == pwd) { |
|
89 |
- if (errno) { |
|
90 |
- logg("*ClamMisc: internal error (failed to exclude event) ... %s\n", strerror(errno)); |
|
91 |
- switch (errno) { |
|
92 |
- case EIO: |
|
93 |
- logg("*ClamMisc: system i/o failed while retrieving username information (excluding for safety)\n"); |
|
94 |
- return CHK_FOUND; |
|
95 |
- break; |
|
96 |
- case EINTR: |
|
97 |
- logg("*ClamMisc: caught signal while retrieving username information from system (excluding for safety)\n"); |
|
98 |
- return CHK_FOUND; |
|
99 |
- break; |
|
100 |
- case EMFILE: |
|
101 |
- case ENFILE: |
|
102 |
- if (0 == retry) { |
|
103 |
- logg("*ClamMisc: waiting for consumer thread to catch up then retrying ...\n"); |
|
104 |
- sleep(3); |
|
105 |
- retry = 1; |
|
106 |
- continue; |
|
107 |
- } else { |
|
108 |
- logg("*ClamMisc: fds have been exhausted ... attempting to force the consumer thread to catch up ... (excluding for safety)\n"); |
|
109 |
- pthread_cond_signal(&onas_scan_queue_empty_cond); |
|
110 |
- sleep(3); |
|
111 |
- return CHK_FOUND; |
|
112 |
- } |
|
113 |
- case ERANGE: |
|
114 |
- default: |
|
115 |
- logg("*ClamMisc: unknown error occurred (excluding for safety)\n"); |
|
116 |
- return CHK_FOUND; |
|
117 |
- break; |
|
118 |
- } |
|
119 |
- } |
|
120 |
- } else { |
|
121 |
- if (!strncmp(opt_uname->strarg, pwd->pw_name, strlen(opt_uname->strarg))) { |
|
122 |
- return CHK_FOUND; |
|
123 |
- } |
|
124 |
- } |
|
86 |
+ pwd = getpwuid(sb.st_uid); |
|
87 |
+ if (NULL == pwd) { |
|
88 |
+ if (errno) { |
|
89 |
+ logg("*ClamMisc: internal error (failed to exclude event) ... %s\n", strerror(errno)); |
|
90 |
+ switch (errno) { |
|
91 |
+ case EIO: |
|
92 |
+ logg("*ClamMisc: system i/o failed while retrieving username information (excluding for safety)\n"); |
|
93 |
+ return CHK_FOUND; |
|
94 |
+ break; |
|
95 |
+ case EINTR: |
|
96 |
+ logg("*ClamMisc: caught signal while retrieving username information from system (excluding for safety)\n"); |
|
97 |
+ return CHK_FOUND; |
|
98 |
+ break; |
|
99 |
+ case EMFILE: |
|
100 |
+ case ENFILE: |
|
101 |
+ if (0 == retry) { |
|
102 |
+ logg("*ClamMisc: waiting for consumer thread to catch up then retrying ...\n"); |
|
103 |
+ sleep(3); |
|
104 |
+ retry = 1; |
|
105 |
+ continue; |
|
106 |
+ } else { |
|
107 |
+ logg("*ClamMisc: fds have been exhausted ... attempting to force the consumer thread to catch up ... (excluding for safety)\n"); |
|
108 |
+ pthread_cond_signal(&onas_scan_queue_empty_cond); |
|
109 |
+ sleep(3); |
|
110 |
+ return CHK_FOUND; |
|
111 |
+ } |
|
112 |
+ case ERANGE: |
|
113 |
+ default: |
|
114 |
+ logg("*ClamMisc: unknown error occurred (excluding for safety)\n"); |
|
115 |
+ return CHK_FOUND; |
|
116 |
+ break; |
|
117 |
+ } |
|
118 |
+ } |
|
119 |
+ } else { |
|
120 |
+ if (!strncmp(opt_uname->strarg, pwd->pw_name, strlen(opt_uname->strarg))) { |
|
121 |
+ return CHK_FOUND; |
|
122 |
+ } |
|
123 |
+ } |
|
125 | 124 |
opt_uname = opt_uname->nextarg; |
126 | 125 |
} |
127 | 126 |
} |
... | ... |
@@ -145,93 +144,93 @@ int onas_fan_checkowner(int pid, const struct optstruct *opts) |
145 | 145 |
char **onas_get_opt_list(const char *fname, int *num_entries, cl_error_t *err) |
146 | 146 |
{ |
147 | 147 |
|
148 |
- FILE* opt_file = 0; |
|
149 |
- STATBUF sb; |
|
150 |
- char** opt_list = NULL; |
|
151 |
- char** rlc_ptr = NULL; |
|
152 |
- uint64_t len = 0; |
|
153 |
- int32_t ret = 0; |
|
154 |
- |
|
155 |
- *num_entries = 0; |
|
156 |
- |
|
157 |
- opt_list = cli_malloc(sizeof(char*)); |
|
158 |
- if (NULL == opt_list) { |
|
159 |
- *err = CL_EMEM; |
|
160 |
- return NULL; |
|
161 |
- } |
|
162 |
- opt_list[*num_entries] = NULL; |
|
163 |
- |
|
164 |
- errno = 0; |
|
165 |
- opt_file = fopen(fname, "r"); |
|
166 |
- |
|
167 |
- if (NULL == opt_file) { |
|
168 |
- logg("!ClamMisc: could not open path list file `%s', %s\n", fname, errno ? strerror(errno) : ""); |
|
169 |
- *err = CL_EARG; |
|
170 |
- return NULL; |
|
171 |
- } |
|
172 |
- |
|
173 |
- while((ret = getline(opt_list + *num_entries, &len, opt_file)) != -1) { |
|
174 |
- |
|
175 |
- opt_list[*num_entries][strlen(opt_list[*num_entries])-1] = '\0'; |
|
176 |
- errno = 0; |
|
177 |
- if (0 != CLAMSTAT(opt_list[*num_entries], &sb)) { |
|
178 |
- logg("*ClamMisc: when parsing path list ... could not stat '%s' ... %s ... skipping\n", opt_list[*num_entries], strerror(errno)); |
|
179 |
- len = 0; |
|
180 |
- free(opt_list[*num_entries]); |
|
181 |
- opt_list[*num_entries] = NULL; |
|
182 |
- continue; |
|
183 |
- } |
|
184 |
- |
|
185 |
- if (!S_ISDIR(sb.st_mode)) { |
|
186 |
- logg("*ClamMisc: when parsing path list ... '%s' is not a directory ... skipping\n", opt_list[*num_entries]); |
|
187 |
- len = 0; |
|
188 |
- free(opt_list[*num_entries]); |
|
189 |
- opt_list[*num_entries] = NULL; |
|
190 |
- continue; |
|
191 |
- } |
|
192 |
- |
|
193 |
- if (strcmp(opt_list[*num_entries], "/") == 0) { |
|
194 |
- logg("*ClamMisc: when parsing path list ... ignoring path '%s' while DDD is enabled ... skipping\n", opt_list[*num_entries]); |
|
195 |
- logg("*ClamMisc: use the OnAccessMountPath configuration option to watch '%s'\n", opt_list[*num_entries]); |
|
196 |
- len = 0; |
|
197 |
- free(opt_list[*num_entries]); |
|
198 |
- opt_list[*num_entries] = NULL; |
|
199 |
- continue; |
|
200 |
- } |
|
201 |
- |
|
202 |
- (*num_entries)++; |
|
203 |
- rlc_ptr = cli_realloc(opt_list, sizeof(char*) * (*num_entries+1)); |
|
204 |
- if (rlc_ptr) { |
|
205 |
- opt_list = rlc_ptr; |
|
206 |
- opt_list[*num_entries] = NULL; |
|
207 |
- } else { |
|
208 |
- *err = CL_EMEM; |
|
209 |
- fclose(opt_file); |
|
210 |
- free_opt_list(opt_list, *num_entries); |
|
211 |
- return NULL; |
|
212 |
- } |
|
213 |
- |
|
214 |
- len = 0; |
|
215 |
- } |
|
216 |
- |
|
217 |
- opt_list[*num_entries] = NULL; |
|
218 |
- fclose(opt_file); |
|
219 |
- return opt_list; |
|
148 |
+ FILE *opt_file = 0; |
|
149 |
+ STATBUF sb; |
|
150 |
+ char **opt_list = NULL; |
|
151 |
+ char **rlc_ptr = NULL; |
|
152 |
+ uint64_t len = 0; |
|
153 |
+ int32_t ret = 0; |
|
154 |
+ |
|
155 |
+ *num_entries = 0; |
|
156 |
+ |
|
157 |
+ opt_list = cli_malloc(sizeof(char *)); |
|
158 |
+ if (NULL == opt_list) { |
|
159 |
+ *err = CL_EMEM; |
|
160 |
+ return NULL; |
|
161 |
+ } |
|
162 |
+ opt_list[*num_entries] = NULL; |
|
163 |
+ |
|
164 |
+ errno = 0; |
|
165 |
+ opt_file = fopen(fname, "r"); |
|
166 |
+ |
|
167 |
+ if (NULL == opt_file) { |
|
168 |
+ logg("!ClamMisc: could not open path list file `%s', %s\n", fname, errno ? strerror(errno) : ""); |
|
169 |
+ *err = CL_EARG; |
|
170 |
+ return NULL; |
|
171 |
+ } |
|
172 |
+ |
|
173 |
+ while ((ret = getline(opt_list + *num_entries, &len, opt_file)) != -1) { |
|
174 |
+ |
|
175 |
+ opt_list[*num_entries][strlen(opt_list[*num_entries]) - 1] = '\0'; |
|
176 |
+ errno = 0; |
|
177 |
+ if (0 != CLAMSTAT(opt_list[*num_entries], &sb)) { |
|
178 |
+ logg("*ClamMisc: when parsing path list ... could not stat '%s' ... %s ... skipping\n", opt_list[*num_entries], strerror(errno)); |
|
179 |
+ len = 0; |
|
180 |
+ free(opt_list[*num_entries]); |
|
181 |
+ opt_list[*num_entries] = NULL; |
|
182 |
+ continue; |
|
183 |
+ } |
|
184 |
+ |
|
185 |
+ if (!S_ISDIR(sb.st_mode)) { |
|
186 |
+ logg("*ClamMisc: when parsing path list ... '%s' is not a directory ... skipping\n", opt_list[*num_entries]); |
|
187 |
+ len = 0; |
|
188 |
+ free(opt_list[*num_entries]); |
|
189 |
+ opt_list[*num_entries] = NULL; |
|
190 |
+ continue; |
|
191 |
+ } |
|
192 |
+ |
|
193 |
+ if (strcmp(opt_list[*num_entries], "/") == 0) { |
|
194 |
+ logg("*ClamMisc: when parsing path list ... ignoring path '%s' while DDD is enabled ... skipping\n", opt_list[*num_entries]); |
|
195 |
+ logg("*ClamMisc: use the OnAccessMountPath configuration option to watch '%s'\n", opt_list[*num_entries]); |
|
196 |
+ len = 0; |
|
197 |
+ free(opt_list[*num_entries]); |
|
198 |
+ opt_list[*num_entries] = NULL; |
|
199 |
+ continue; |
|
200 |
+ } |
|
201 |
+ |
|
202 |
+ (*num_entries)++; |
|
203 |
+ rlc_ptr = cli_realloc(opt_list, sizeof(char *) * (*num_entries + 1)); |
|
204 |
+ if (rlc_ptr) { |
|
205 |
+ opt_list = rlc_ptr; |
|
206 |
+ opt_list[*num_entries] = NULL; |
|
207 |
+ } else { |
|
208 |
+ *err = CL_EMEM; |
|
209 |
+ fclose(opt_file); |
|
210 |
+ free_opt_list(opt_list, *num_entries); |
|
211 |
+ return NULL; |
|
212 |
+ } |
|
213 |
+ |
|
214 |
+ len = 0; |
|
215 |
+ } |
|
216 |
+ |
|
217 |
+ opt_list[*num_entries] = NULL; |
|
218 |
+ fclose(opt_file); |
|
219 |
+ return opt_list; |
|
220 | 220 |
} |
221 | 221 |
|
222 |
-void free_opt_list(char** opt_list, int entries) |
|
222 |
+void free_opt_list(char **opt_list, int entries) |
|
223 | 223 |
{ |
224 | 224 |
|
225 |
- int i = 0; |
|
226 |
- for (i; i < entries; i++) { |
|
227 |
- if (opt_list[i]) { |
|
228 |
- free(opt_list[i]); |
|
229 |
- opt_list[i] = NULL; |
|
230 |
- } |
|
231 |
- } |
|
225 |
+ int i = 0; |
|
226 |
+ for (i; i < entries; i++) { |
|
227 |
+ if (opt_list[i]) { |
|
228 |
+ free(opt_list[i]); |
|
229 |
+ opt_list[i] = NULL; |
|
230 |
+ } |
|
231 |
+ } |
|
232 | 232 |
|
233 |
- free(opt_list); |
|
234 |
- opt_list = NULL; |
|
233 |
+ free(opt_list); |
|
234 |
+ opt_list = NULL; |
|
235 | 235 |
|
236 |
- return; |
|
236 |
+ return; |
|
237 | 237 |
} |
... | ... |
@@ -31,11 +31,10 @@ typedef enum { |
31 | 31 |
CHK_SELF |
32 | 32 |
} cli_check_t; |
33 | 33 |
|
34 |
- |
|
35 | 34 |
#if defined(FANOTIFY) |
36 | 35 |
int onas_fan_checkowner(int pid, const struct optstruct *opts); |
37 | 36 |
#endif |
38 | 37 |
char **onas_get_opt_list(const char *fname, int *num_entries, cl_error_t *err); |
39 |
-void free_opt_list(char** opt_list, int entries); |
|
38 |
+void free_opt_list(char **opt_list, int entries); |
|
40 | 39 |
|
41 | 40 |
#endif |
... | ... |
@@ -44,7 +44,7 @@ |
44 | 44 |
#include "thread.h" |
45 | 45 |
#include "queue.h" |
46 | 46 |
|
47 |
-static void onas_scan_queue_exit(void * arg); |
|
47 |
+static void onas_scan_queue_exit(void *arg); |
|
48 | 48 |
static int onas_consume_event(threadpool thpool); |
49 | 49 |
static cl_error_t onas_new_event_queue_node(struct onas_event_queue_node **node); |
50 | 50 |
static void onas_destroy_event_queue_node(struct onas_event_queue_node *node); |
... | ... |
@@ -52,7 +52,7 @@ static void onas_destroy_event_queue_node(struct onas_event_queue_node *node); |
52 | 52 |
static pthread_mutex_t onas_queue_lock = PTHREAD_MUTEX_INITIALIZER; |
53 | 53 |
|
54 | 54 |
static pthread_mutex_t onas_scan_queue_loop = PTHREAD_MUTEX_INITIALIZER; |
55 |
-pthread_cond_t onas_scan_queue_empty_cond = PTHREAD_COND_INITIALIZER; |
|
55 |
+pthread_cond_t onas_scan_queue_empty_cond = PTHREAD_COND_INITIALIZER; |
|
56 | 56 |
extern pthread_t scan_queue_pid; |
57 | 57 |
|
58 | 58 |
static threadpool g_thpool; |
... | ... |
@@ -62,133 +62,135 @@ static struct onas_event_queue_node *g_onas_event_queue_tail = NULL; |
62 | 62 |
|
63 | 63 |
static struct onas_event_queue g_onas_event_queue; |
64 | 64 |
|
65 |
-static cl_error_t onas_new_event_queue_node(struct onas_event_queue_node **node) { |
|
66 |
- |
|
67 |
- *node = malloc(sizeof(struct onas_event_queue_node)); |
|
68 |
- if (NULL == *node) { |
|
69 |
- return CL_EMEM; |
|
70 |
- } |
|
65 |
+static cl_error_t onas_new_event_queue_node(struct onas_event_queue_node **node) |
|
66 |
+{ |
|
71 | 67 |
|
68 |
+ *node = malloc(sizeof(struct onas_event_queue_node)); |
|
69 |
+ if (NULL == *node) { |
|
70 |
+ return CL_EMEM; |
|
71 |
+ } |
|
72 | 72 |
|
73 |
- **node = (struct onas_event_queue_node) { |
|
74 |
- .next = NULL, |
|
75 |
- .prev = NULL, |
|
73 |
+ **node = (struct onas_event_queue_node){ |
|
74 |
+ .next = NULL, |
|
75 |
+ .prev = NULL, |
|
76 | 76 |
|
77 |
- .data = NULL |
|
78 |
- }; |
|
77 |
+ .data = NULL}; |
|
79 | 78 |
|
80 |
- return CL_SUCCESS; |
|
79 |
+ return CL_SUCCESS; |
|
81 | 80 |
} |
82 | 81 |
|
83 |
-static void *onas_init_event_queue() { |
|
82 |
+static void *onas_init_event_queue() |
|
83 |
+{ |
|
84 | 84 |
|
85 |
- if (CL_EMEM == onas_new_event_queue_node(&g_onas_event_queue_head)) { |
|
86 |
- return NULL; |
|
87 |
- } |
|
85 |
+ if (CL_EMEM == onas_new_event_queue_node(&g_onas_event_queue_head)) { |
|
86 |
+ return NULL; |
|
87 |
+ } |
|
88 | 88 |
|
89 |
- if (CL_EMEM == onas_new_event_queue_node(&g_onas_event_queue_tail)) { |
|
90 |
- return NULL; |
|
91 |
- } |
|
89 |
+ if (CL_EMEM == onas_new_event_queue_node(&g_onas_event_queue_tail)) { |
|
90 |
+ return NULL; |
|
91 |
+ } |
|
92 | 92 |
|
93 |
- g_onas_event_queue_tail->prev = g_onas_event_queue_head; |
|
94 |
- g_onas_event_queue_head->next = g_onas_event_queue_tail; |
|
93 |
+ g_onas_event_queue_tail->prev = g_onas_event_queue_head; |
|
94 |
+ g_onas_event_queue_head->next = g_onas_event_queue_tail; |
|
95 | 95 |
|
96 |
- g_onas_event_queue = (struct onas_event_queue) { |
|
97 |
- .head = g_onas_event_queue_head, |
|
98 |
- .tail = g_onas_event_queue_tail, |
|
96 |
+ g_onas_event_queue = (struct onas_event_queue){ |
|
97 |
+ .head = g_onas_event_queue_head, |
|
98 |
+ .tail = g_onas_event_queue_tail, |
|
99 | 99 |
|
100 |
- .size = 0 |
|
101 |
- }; |
|
100 |
+ .size = 0}; |
|
102 | 101 |
|
103 |
- return &g_onas_event_queue; |
|
102 |
+ return &g_onas_event_queue; |
|
104 | 103 |
} |
105 | 104 |
|
106 |
-static void onas_destroy_event_queue_node(struct onas_event_queue_node *node) { |
|
105 |
+static void onas_destroy_event_queue_node(struct onas_event_queue_node *node) |
|
106 |
+{ |
|
107 | 107 |
|
108 |
- if (NULL == node) { |
|
109 |
- return; |
|
110 |
- } |
|
108 |
+ if (NULL == node) { |
|
109 |
+ return; |
|
110 |
+ } |
|
111 | 111 |
|
112 |
- node->next = NULL; |
|
113 |
- node->prev = NULL; |
|
114 |
- node->data = NULL; |
|
112 |
+ node->next = NULL; |
|
113 |
+ node->prev = NULL; |
|
114 |
+ node->data = NULL; |
|
115 | 115 |
|
116 |
- free(node); |
|
117 |
- node = NULL; |
|
116 |
+ free(node); |
|
117 |
+ node = NULL; |
|
118 | 118 |
|
119 |
- return; |
|
119 |
+ return; |
|
120 | 120 |
} |
121 | 121 |
|
122 |
-static void onas_destroy_event_queue() { |
|
122 |
+static void onas_destroy_event_queue() |
|
123 |
+{ |
|
123 | 124 |
|
124 |
- if (NULL == g_onas_event_queue_head) { |
|
125 |
- return; |
|
126 |
- } |
|
125 |
+ if (NULL == g_onas_event_queue_head) { |
|
126 |
+ return; |
|
127 |
+ } |
|
127 | 128 |
|
128 |
- struct onas_event_queue_node *curr = g_onas_event_queue_head; |
|
129 |
- struct onas_event_queue_node *next = curr->next; |
|
129 |
+ struct onas_event_queue_node *curr = g_onas_event_queue_head; |
|
130 |
+ struct onas_event_queue_node *next = curr->next; |
|
130 | 131 |
|
131 |
- do { |
|
132 |
- onas_destroy_event_queue_node(curr); |
|
133 |
- curr = next; |
|
134 |
- if (curr) { |
|
135 |
- next = curr->next; |
|
136 |
- } |
|
137 |
- } while (curr); |
|
132 |
+ do { |
|
133 |
+ onas_destroy_event_queue_node(curr); |
|
134 |
+ curr = next; |
|
135 |
+ if (curr) { |
|
136 |
+ next = curr->next; |
|
137 |
+ } |
|
138 |
+ } while (curr); |
|
138 | 139 |
|
139 |
- return; |
|
140 |
+ return; |
|
140 | 141 |
} |
141 | 142 |
|
143 |
+void *onas_scan_queue_th(void *arg) |
|
144 |
+{ |
|
142 | 145 |
|
143 |
-void *onas_scan_queue_th(void *arg) { |
|
146 |
+ /* not a ton of use for context right now, but perhaps in the future we can pass in more options */ |
|
147 |
+ struct onas_context *ctx = (struct onas_context *)arg; |
|
148 |
+ sigset_t sigset; |
|
149 |
+ struct sigaction act; |
|
150 |
+ const struct optstruct *pt; |
|
151 |
+ int ret, len, idx; |
|
144 | 152 |
|
145 |
- /* not a ton of use for context right now, but perhaps in the future we can pass in more options */ |
|
146 |
- struct onas_context *ctx = (struct onas_context *) arg; |
|
147 |
- sigset_t sigset; |
|
148 |
- struct sigaction act; |
|
149 |
- const struct optstruct *pt; |
|
150 |
- int ret, len, idx; |
|
153 |
+ cl_error_t err; |
|
151 | 154 |
|
152 |
- cl_error_t err; |
|
153 |
- |
|
154 |
- /* ignore all signals except SIGUSR2 */ |
|
155 |
- sigfillset(&sigset); |
|
156 |
- sigdelset(&sigset, SIGUSR2); |
|
157 |
- /* The behavior of a process is undefined after it ignores a |
|
155 |
+ /* ignore all signals except SIGUSR2 */ |
|
156 |
+ sigfillset(&sigset); |
|
157 |
+ sigdelset(&sigset, SIGUSR2); |
|
158 |
+ /* The behavior of a process is undefined after it ignores a |
|
158 | 159 |
* SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ |
159 |
- sigdelset(&sigset, SIGFPE); |
|
160 |
- sigdelset(&sigset, SIGILL); |
|
161 |
- sigdelset(&sigset, SIGSEGV); |
|
162 |
- sigdelset(&sigset, SIGTERM); |
|
163 |
- sigdelset(&sigset, SIGINT); |
|
160 |
+ sigdelset(&sigset, SIGFPE); |
|
161 |
+ sigdelset(&sigset, SIGILL); |
|
162 |
+ sigdelset(&sigset, SIGSEGV); |
|
163 |
+ sigdelset(&sigset, SIGTERM); |
|
164 |
+ sigdelset(&sigset, SIGINT); |
|
164 | 165 |
#ifdef SIGBUS |
165 |
- sigdelset(&sigset, SIGBUS); |
|
166 |
+ sigdelset(&sigset, SIGBUS); |
|
166 | 167 |
#endif |
167 | 168 |
|
168 |
- logg("*ClamScanQueue: initializing event queue consumer ... (%d) threads in thread pool\n", ctx->maxthreads); |
|
169 |
- onas_init_event_queue(); |
|
170 |
- threadpool thpool = thpool_init(ctx->maxthreads); |
|
171 |
- g_thpool = thpool; |
|
172 |
- |
|
173 |
- /* loop w/ onas_consume_event until we die */ |
|
174 |
- pthread_cleanup_push(onas_scan_queue_exit, NULL); |
|
175 |
- logg("*ClamScanQueue: waiting to consume events ...\n"); |
|
176 |
- do { |
|
177 |
- pthread_mutex_lock(&onas_scan_queue_loop); |
|
178 |
- pthread_cond_wait(&onas_scan_queue_empty_cond, &onas_scan_queue_loop); |
|
179 |
- /* run 'till we're empty */ |
|
180 |
- do { |
|
181 |
- pthread_testcancel(); |
|
182 |
- ret = onas_consume_event(thpool); |
|
183 |
- } while (1 != ret); |
|
184 |
- pthread_mutex_unlock(&onas_scan_queue_loop); |
|
185 |
- |
|
186 |
- } while(1); |
|
187 |
- |
|
188 |
- pthread_cleanup_pop(1); |
|
169 |
+ logg("*ClamScanQueue: initializing event queue consumer ... (%d) threads in thread pool\n", ctx->maxthreads); |
|
170 |
+ onas_init_event_queue(); |
|
171 |
+ threadpool thpool = thpool_init(ctx->maxthreads); |
|
172 |
+ g_thpool = thpool; |
|
173 |
+ |
|
174 |
+ /* loop w/ onas_consume_event until we die */ |
|
175 |
+ pthread_cleanup_push(onas_scan_queue_exit, NULL); |
|
176 |
+ logg("*ClamScanQueue: waiting to consume events ...\n"); |
|
177 |
+ do { |
|
178 |
+ pthread_mutex_lock(&onas_scan_queue_loop); |
|
179 |
+ pthread_cond_wait(&onas_scan_queue_empty_cond, &onas_scan_queue_loop); |
|
180 |
+ /* run 'till we're empty */ |
|
181 |
+ do { |
|
182 |
+ pthread_testcancel(); |
|
183 |
+ ret = onas_consume_event(thpool); |
|
184 |
+ } while (1 != ret); |
|
185 |
+ pthread_mutex_unlock(&onas_scan_queue_loop); |
|
186 |
+ |
|
187 |
+ } while (1); |
|
188 |
+ |
|
189 |
+ pthread_cleanup_pop(1); |
|
189 | 190 |
} |
190 | 191 |
|
191 |
-static int onas_queue_is_b_empty() { |
|
192 |
+static int onas_queue_is_b_empty() |
|
193 |
+{ |
|
192 | 194 |
|
193 | 195 |
if (g_onas_event_queue.head->next == g_onas_event_queue.tail) { |
194 | 196 |
return 1; |
... | ... |
@@ -197,7 +199,8 @@ static int onas_queue_is_b_empty() { |
197 | 197 |
return 0; |
198 | 198 |
} |
199 | 199 |
|
200 |
-static int onas_consume_event(threadpool thpool) { |
|
200 |
+static int onas_consume_event(threadpool thpool) |
|
201 |
+{ |
|
201 | 202 |
|
202 | 203 |
pthread_mutex_lock(&onas_queue_lock); |
203 | 204 |
|
... | ... |
@@ -212,9 +215,9 @@ static int onas_consume_event(threadpool thpool) { |
212 | 212 |
logg("*ClamScanQueue: consuming event!\n"); |
213 | 213 |
#endif |
214 | 214 |
|
215 |
- thpool_add_work(thpool, (void *) onas_scan_worker, (void *) popped_node->data); |
|
215 |
+ thpool_add_work(thpool, (void *)onas_scan_worker, (void *)popped_node->data); |
|
216 | 216 |
|
217 |
- g_onas_event_queue_head->next = g_onas_event_queue_head->next->next; |
|
217 |
+ g_onas_event_queue_head->next = g_onas_event_queue_head->next->next; |
|
218 | 218 |
g_onas_event_queue_head->next->prev = g_onas_event_queue_head; |
219 | 219 |
|
220 | 220 |
onas_destroy_event_queue_node(popped_node); |
... | ... |
@@ -225,7 +228,8 @@ static int onas_consume_event(threadpool thpool) { |
225 | 225 |
return 0; |
226 | 226 |
} |
227 | 227 |
|
228 |
-cl_error_t onas_queue_event(struct onas_scan_event *event_data) { |
|
228 |
+cl_error_t onas_queue_event(struct onas_scan_event *event_data) |
|
229 |
+{ |
|
229 | 230 |
|
230 | 231 |
pthread_mutex_lock(&onas_queue_lock); |
231 | 232 |
|
... | ... |
@@ -236,7 +240,7 @@ cl_error_t onas_queue_event(struct onas_scan_event *event_data) { |
236 | 236 |
#endif |
237 | 237 |
|
238 | 238 |
if (CL_EMEM == onas_new_event_queue_node(&node)) { |
239 |
- return CL_EMEM; |
|
239 |
+ return CL_EMEM; |
|
240 | 240 |
} |
241 | 241 |
|
242 | 242 |
node->next = g_onas_event_queue_tail; |
... | ... |
@@ -245,8 +249,8 @@ cl_error_t onas_queue_event(struct onas_scan_event *event_data) { |
245 | 245 |
node->data = event_data; |
246 | 246 |
|
247 | 247 |
/* tail will always have a .prev */ |
248 |
- ((struct onas_event_queue_node *) g_onas_event_queue_tail->prev)->next = node; |
|
249 |
- g_onas_event_queue_tail->prev = node; |
|
248 |
+ ((struct onas_event_queue_node *)g_onas_event_queue_tail->prev)->next = node; |
|
249 |
+ g_onas_event_queue_tail->prev = node; |
|
250 | 250 |
|
251 | 251 |
g_onas_event_queue.size++; |
252 | 252 |
|
... | ... |
@@ -256,44 +260,45 @@ cl_error_t onas_queue_event(struct onas_scan_event *event_data) { |
256 | 256 |
return CL_SUCCESS; |
257 | 257 |
} |
258 | 258 |
|
259 |
-cl_error_t onas_scan_queue_start(struct onas_context **ctx) { |
|
259 |
+cl_error_t onas_scan_queue_start(struct onas_context **ctx) |
|
260 |
+{ |
|
260 | 261 |
|
261 |
- pthread_attr_t scan_queue_attr; |
|
262 |
- int32_t thread_started = 1; |
|
262 |
+ pthread_attr_t scan_queue_attr; |
|
263 |
+ int32_t thread_started = 1; |
|
263 | 264 |
|
264 |
- if (!ctx || !*ctx) { |
|
265 |
- logg("*ClamScanQueue: unable to start clamonacc. (bad context)\n"); |
|
266 |
- return CL_EARG; |
|
267 |
- } |
|
265 |
+ if (!ctx || !*ctx) { |
|
266 |
+ logg("*ClamScanQueue: unable to start clamonacc. (bad context)\n"); |
|
267 |
+ return CL_EARG; |
|
268 |
+ } |
|
268 | 269 |
|
269 |
- if(pthread_attr_init(&scan_queue_attr)) { |
|
270 |
- return CL_BREAK; |
|
271 |
- } |
|
272 |
- pthread_attr_setdetachstate(&scan_queue_attr, PTHREAD_CREATE_JOINABLE); |
|
273 |
- thread_started = pthread_create(&scan_queue_pid, &scan_queue_attr, onas_scan_queue_th, *ctx); |
|
270 |
+ if (pthread_attr_init(&scan_queue_attr)) { |
|
271 |
+ return CL_BREAK; |
|
272 |
+ } |
|
273 |
+ pthread_attr_setdetachstate(&scan_queue_attr, PTHREAD_CREATE_JOINABLE); |
|
274 |
+ thread_started = pthread_create(&scan_queue_pid, &scan_queue_attr, onas_scan_queue_th, *ctx); |
|
274 | 275 |
|
275 |
- if (0 != thread_started) { |
|
276 |
- /* Failed to create thread */ |
|
277 |
- logg("*ClamScanQueue: Unable to start event consumer queue thread ... \n"); |
|
278 |
- return CL_ECREAT; |
|
279 |
- } |
|
276 |
+ if (0 != thread_started) { |
|
277 |
+ /* Failed to create thread */ |
|
278 |
+ logg("*ClamScanQueue: Unable to start event consumer queue thread ... \n"); |
|
279 |
+ return CL_ECREAT; |
|
280 |
+ } |
|
280 | 281 |
|
281 |
- return CL_SUCCESS; |
|
282 |
+ return CL_SUCCESS; |
|
282 | 283 |
} |
283 | 284 |
|
284 |
-static void onas_scan_queue_exit(void *arg) { |
|
285 |
+static void onas_scan_queue_exit(void *arg) |
|
286 |
+{ |
|
285 | 287 |
|
286 |
- logg("*ClamScanQueue: onas_scan_queue_exit()\n"); |
|
288 |
+ logg("*ClamScanQueue: onas_scan_queue_exit()\n"); |
|
287 | 289 |
|
288 |
- pthread_mutex_lock(&onas_queue_lock); |
|
289 |
- onas_destroy_event_queue(); |
|
290 |
+ pthread_mutex_lock(&onas_queue_lock); |
|
291 |
+ onas_destroy_event_queue(); |
|
290 | 292 |
|
291 |
- if (g_thpool) { |
|
292 |
- thpool_destroy(g_thpool); |
|
293 |
- } |
|
294 |
- g_thpool = NULL; |
|
295 |
- pthread_mutex_unlock(&onas_queue_lock); |
|
293 |
+ if (g_thpool) { |
|
294 |
+ thpool_destroy(g_thpool); |
|
295 |
+ } |
|
296 |
+ g_thpool = NULL; |
|
297 |
+ pthread_mutex_unlock(&onas_queue_lock); |
|
296 | 298 |
|
297 |
- logg("ClamScanQueue: stopped\n"); |
|
299 |
+ logg("ClamScanQueue: stopped\n"); |
|
298 | 300 |
} |
299 |
- |
... | ... |
@@ -22,7 +22,6 @@ |
22 | 22 |
#include "clamav-config.h" |
23 | 23 |
#endif |
24 | 24 |
|
25 |
- |
|
26 | 25 |
#include <stdio.h> |
27 | 26 |
#include <errno.h> |
28 | 27 |
#include <unistd.h> |
... | ... |
@@ -46,7 +45,6 @@ |
46 | 46 |
|
47 | 47 |
static pthread_mutex_t onas_scan_lock = PTHREAD_MUTEX_INITIALIZER; |
48 | 48 |
|
49 |
- |
|
50 | 49 |
static int onas_scan(struct onas_scan_event *event_data, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); |
51 | 50 |
static cl_error_t onas_scan_safe(struct onas_scan_event *event_data, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); |
52 | 51 |
static cl_error_t onas_scan_thread_scanfile(struct onas_scan_event *event_data, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); |
... | ... |
@@ -70,8 +68,8 @@ static void onas_scan_thread_exit(int sig) |
70 | 70 |
*/ |
71 | 71 |
static int onas_scan(struct onas_scan_event *event_data, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) |
72 | 72 |
{ |
73 |
- int ret = 0; |
|
74 |
- int i = 0; |
|
73 |
+ int ret = 0; |
|
74 |
+ int i = 0; |
|
75 | 75 |
uint8_t retry_on_error = event_data->bool_opts & ONAS_SCTH_B_RETRY_ON_E; |
76 | 76 |
|
77 | 77 |
ret = onas_scan_safe(event_data, fname, sb, infected, err, ret_code); |
... | ... |
@@ -92,17 +90,17 @@ static int onas_scan(struct onas_scan_event *event_data, const char *fname, STAT |
92 | 92 |
default: |
93 | 93 |
logg("~ClamMisc: internal issue (client failed to scan)\n"); |
94 | 94 |
} |
95 |
- if (retry_on_error) { |
|
96 |
- logg("*ClamMisc: reattempting scan ... \n"); |
|
97 |
- while (err) { |
|
98 |
- ret = onas_scan_safe(event_data, fname, sb, infected, err, ret_code); |
|
99 |
- |
|
100 |
- i++; |
|
101 |
- if (*err && i == event_data->retry_attempts) { |
|
102 |
- *err = 0; |
|
103 |
- } |
|
104 |
- } |
|
105 |
- } |
|
95 |
+ if (retry_on_error) { |
|
96 |
+ logg("*ClamMisc: reattempting scan ... \n"); |
|
97 |
+ while (err) { |
|
98 |
+ ret = onas_scan_safe(event_data, fname, sb, infected, err, ret_code); |
|
99 |
+ |
|
100 |
+ i++; |
|
101 |
+ if (*err && i == event_data->retry_attempts) { |
|
102 |
+ *err = 0; |
|
103 |
+ } |
|
104 |
+ } |
|
105 |
+ } |
|
106 | 106 |
} |
107 | 107 |
|
108 | 108 |
return ret; |
... | ... |
@@ -115,194 +113,196 @@ static int onas_scan(struct onas_scan_event *event_data, const char *fname, STAT |
115 | 115 |
* |
116 | 116 |
* TODO: make this configurable? |
117 | 117 |
*/ |
118 |
-static cl_error_t onas_scan_safe(struct onas_scan_event *event_data, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) { |
|
118 |
+static cl_error_t onas_scan_safe(struct onas_scan_event *event_data, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) |
|
119 |
+{ |
|
119 | 120 |
|
120 |
- int ret = 0; |
|
121 |
- int fd = 0; |
|
121 |
+ int ret = 0; |
|
122 |
+ int fd = 0; |
|
122 | 123 |
|
123 | 124 |
#if defined(FANOTIFY) |
124 |
- uint8_t b_fanotify; |
|
125 |
+ uint8_t b_fanotify; |
|
125 | 126 |
|
126 |
- b_fanotify = event_data->bool_opts & ONAS_SCTH_B_FANOTIFY ? 1 : 0; |
|
127 |
+ b_fanotify = event_data->bool_opts & ONAS_SCTH_B_FANOTIFY ? 1 : 0; |
|
127 | 128 |
|
128 |
- if (b_fanotify) { |
|
129 |
- fd = event_data->fmd->fd; |
|
130 |
- } |
|
129 |
+ if (b_fanotify) { |
|
130 |
+ fd = event_data->fmd->fd; |
|
131 |
+ } |
|
131 | 132 |
#endif |
132 | 133 |
|
133 |
- pthread_mutex_lock(&onas_scan_lock); |
|
134 |
+ pthread_mutex_lock(&onas_scan_lock); |
|
134 | 135 |
|
136 |
+ ret = onas_client_scan(event_data->tcpaddr, event_data->portnum, event_data->scantype, event_data->maxstream, |
|
137 |
+ fname, fd, event_data->timeout, sb, infected, err, ret_code); |
|
135 | 138 |
|
136 |
- ret = onas_client_scan(event_data->tcpaddr, event_data->portnum, event_data->scantype, event_data->maxstream, |
|
137 |
- fname, fd, event_data->timeout, sb, infected, err, ret_code); |
|
139 |
+ pthread_mutex_unlock(&onas_scan_lock); |
|
138 | 140 |
|
139 |
- pthread_mutex_unlock(&onas_scan_lock); |
|
140 |
- |
|
141 |
- return ret; |
|
141 |
+ return ret; |
|
142 | 142 |
} |
143 | 143 |
|
144 |
-static cl_error_t onas_scan_thread_scanfile(struct onas_scan_event *event_data, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) { |
|
145 |
- |
|
144 |
+static cl_error_t onas_scan_thread_scanfile(struct onas_scan_event *event_data, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) |
|
145 |
+{ |
|
146 | 146 |
|
147 | 147 |
#if defined(FANOTIFY) |
148 |
- struct fanotify_response res; |
|
149 |
- uint8_t b_fanotify; |
|
148 |
+ struct fanotify_response res; |
|
149 |
+ uint8_t b_fanotify; |
|
150 | 150 |
#endif |
151 | 151 |
|
152 |
- int ret = 0; |
|
152 |
+ int ret = 0; |
|
153 | 153 |
|
154 |
- uint8_t b_scan; |
|
155 |
- uint8_t b_deny_on_error; |
|
154 |
+ uint8_t b_scan; |
|
155 |
+ uint8_t b_deny_on_error; |
|
156 | 156 |
|
157 |
- if (NULL == event_data || NULL == fname || NULL == infected || NULL == err || NULL == ret_code) { |
|
158 |
- logg("!ClamWorker: scan failed (NULL arg given)\n"); |
|
159 |
- return CL_ENULLARG; |
|
160 |
- } |
|
157 |
+ if (NULL == event_data || NULL == fname || NULL == infected || NULL == err || NULL == ret_code) { |
|
158 |
+ logg("!ClamWorker: scan failed (NULL arg given)\n"); |
|
159 |
+ return CL_ENULLARG; |
|
160 |
+ } |
|
161 | 161 |
|
162 |
- b_scan = event_data->bool_opts & ONAS_SCTH_B_SCAN ? 1 : 0; |
|
163 |
- b_deny_on_error = event_data->bool_opts & ONAS_SCTH_B_DENY_ON_E ? 1 : 0; |
|
162 |
+ b_scan = event_data->bool_opts & ONAS_SCTH_B_SCAN ? 1 : 0; |
|
163 |
+ b_deny_on_error = event_data->bool_opts & ONAS_SCTH_B_DENY_ON_E ? 1 : 0; |
|
164 | 164 |
|
165 | 165 |
#if defined(FANOTIFY) |
166 |
- b_fanotify = event_data->bool_opts & ONAS_SCTH_B_FANOTIFY ? 1 : 0; |
|
167 |
- if (b_fanotify) { |
|
168 |
- res.fd = event_data->fmd->fd; |
|
169 |
- res.response = FAN_ALLOW; |
|
170 |
- } |
|
166 |
+ b_fanotify = event_data->bool_opts & ONAS_SCTH_B_FANOTIFY ? 1 : 0; |
|
167 |
+ if (b_fanotify) { |
|
168 |
+ res.fd = event_data->fmd->fd; |
|
169 |
+ res.response = FAN_ALLOW; |
|
170 |
+ } |
|
171 | 171 |
#endif |
172 | 172 |
|
173 |
- if (b_scan) { |
|
174 |
- ret = onas_scan(event_data, fname, sb, infected, err, ret_code); |
|
173 |
+ if (b_scan) { |
|
174 |
+ ret = onas_scan(event_data, fname, sb, infected, err, ret_code); |
|
175 | 175 |
|
176 |
- if (*err && *ret_code != CL_SUCCESS) { |
|
177 |
- logg("*ClamWorker: scan failed with error code %d\n", *ret_code); |
|
178 |
- } |
|
176 |
+ if (*err && *ret_code != CL_SUCCESS) { |
|
177 |
+ logg("*ClamWorker: scan failed with error code %d\n", *ret_code); |
|
178 |
+ } |
|
179 | 179 |
|
180 | 180 |
#if defined(FANOTIFY) |
181 |
- if (b_fanotify) { |
|
182 |
- if ((*err && *ret_code && b_deny_on_error) || *infected) { |
|
183 |
- res.response = FAN_DENY; |
|
184 |
- } |
|
185 |
- } |
|
181 |
+ if (b_fanotify) { |
|
182 |
+ if ((*err && *ret_code && b_deny_on_error) || *infected) { |
|
183 |
+ res.response = FAN_DENY; |
|
184 |
+ } |
|
185 |
+ } |
|
186 | 186 |
#endif |
187 |
- } |
|
187 |
+ } |
|
188 | 188 |
|
189 | 189 |
#if defined(FANOTIFY) |
190 |
- if (b_fanotify) { |
|
191 |
- if(event_data->fmd->mask & FAN_ALL_PERM_EVENTS) { |
|
192 |
- ret = write(event_data->fan_fd, &res, sizeof(res)); |
|
193 |
- if(ret == -1) { |
|
194 |
- logg("!ClamWorker: internal error (can't write to fanotify)\n"); |
|
195 |
- if (errno == ENOENT) { |
|
196 |
- logg("*ClamWorker: permission event has already been written ... recovering ...\n"); |
|
197 |
- } else { |
|
198 |
- ret = CL_EWRITE; |
|
199 |
- } |
|
200 |
- } |
|
201 |
- } |
|
202 |
- } |
|
203 |
- |
|
204 |
- if (b_fanotify) { |
|
190 |
+ if (b_fanotify) { |
|
191 |
+ if (event_data->fmd->mask & FAN_ALL_PERM_EVENTS) { |
|
192 |
+ ret = write(event_data->fan_fd, &res, sizeof(res)); |
|
193 |
+ if (ret == -1) { |
|
194 |
+ logg("!ClamWorker: internal error (can't write to fanotify)\n"); |
|
195 |
+ if (errno == ENOENT) { |
|
196 |
+ logg("*ClamWorker: permission event has already been written ... recovering ...\n"); |
|
197 |
+ } else { |
|
198 |
+ ret = CL_EWRITE; |
|
199 |
+ } |
|
200 |
+ } |
|
201 |
+ } |
|
202 |
+ } |
|
203 |
+ |
|
204 |
+ if (b_fanotify) { |
|
205 | 205 |
|
206 | 206 |
#ifdef ONAS_DEBUG |
207 |
- logg("*ClamWorker: closing fd, %d)\n", event_data->fmd->fd); |
|
207 |
+ logg("*ClamWorker: closing fd, %d)\n", event_data->fmd->fd); |
|
208 | 208 |
#endif |
209 |
- if (-1 == close(event_data->fmd->fd) ) { |
|
210 |
- |
|
211 |
- logg("!ClamWorker: internal error (can't close fanotify meta fd, %d)\n", event_data->fmd->fd); |
|
212 |
- if (errno == EBADF) { |
|
213 |
- logg("*ClamWorker: fd already closed ... recovering ...\n"); |
|
214 |
- } else { |
|
215 |
- ret = CL_EUNLINK; |
|
216 |
- } |
|
217 |
- } |
|
218 |
- } |
|
209 |
+ if (-1 == close(event_data->fmd->fd)) { |
|
210 |
+ |
|
211 |
+ logg("!ClamWorker: internal error (can't close fanotify meta fd, %d)\n", event_data->fmd->fd); |
|
212 |
+ if (errno == EBADF) { |
|
213 |
+ logg("*ClamWorker: fd already closed ... recovering ...\n"); |
|
214 |
+ } else { |
|
215 |
+ ret = CL_EUNLINK; |
|
216 |
+ } |
|
217 |
+ } |
|
218 |
+ } |
|
219 | 219 |
#endif |
220 |
- return ret; |
|
220 |
+ return ret; |
|
221 | 221 |
} |
222 | 222 |
|
223 |
-static cl_error_t onas_scan_thread_handle_dir(struct onas_scan_event *event_data, const char *pathname) { |
|
224 |
- FTS *ftsp = NULL; |
|
225 |
- int32_t ftspopts = FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV; |
|
226 |
- FTSENT *curr = NULL; |
|
223 |
+static cl_error_t onas_scan_thread_handle_dir(struct onas_scan_event *event_data, const char *pathname) |
|
224 |
+{ |
|
225 |
+ FTS *ftsp = NULL; |
|
226 |
+ int32_t ftspopts = FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV; |
|
227 |
+ FTSENT *curr = NULL; |
|
227 | 228 |
|
228 |
- int32_t infected = 0; |
|
229 |
- int32_t err = 0; |
|
230 |
- cl_error_t ret_code = CL_SUCCESS; |
|
231 |
- cl_error_t ret = CL_SUCCESS; |
|
229 |
+ int32_t infected = 0; |
|
230 |
+ int32_t err = 0; |
|
231 |
+ cl_error_t ret_code = CL_SUCCESS; |
|
232 |
+ cl_error_t ret = CL_SUCCESS; |
|
232 | 233 |
|
233 |
- int32_t fres = 0; |
|
234 |
- STATBUF sb; |
|
234 |
+ int32_t fres = 0; |
|
235 |
+ STATBUF sb; |
|
235 | 236 |
|
236 |
- char *const pathargv[] = {(char *)pathname, NULL}; |
|
237 |
+ char *const pathargv[] = {(char *)pathname, NULL}; |
|
237 | 238 |
|
238 |
- if (!(ftsp = _priv_fts_open(pathargv, ftspopts, NULL))) { |
|
239 |
- ret = CL_EOPEN; |
|
240 |
- goto out; |
|
241 |
- } |
|
239 |
+ if (!(ftsp = _priv_fts_open(pathargv, ftspopts, NULL))) { |
|
240 |
+ ret = CL_EOPEN; |
|
241 |
+ goto out; |
|
242 |
+ } |
|
242 | 243 |
|
243 |
- while ((curr = _priv_fts_read(ftsp))) { |
|
244 |
- if (curr->fts_info != FTS_D) { |
|
244 |
+ while ((curr = _priv_fts_read(ftsp))) { |
|
245 |
+ if (curr->fts_info != FTS_D) { |
|
245 | 246 |
|
246 |
- fres = CLAMSTAT(curr->fts_path, &sb); |
|
247 |
+ fres = CLAMSTAT(curr->fts_path, &sb); |
|
247 | 248 |
|
248 |
- if (event_data->sizelimit) { |
|
249 |
- if (fres != 0 || sb.st_size > event_data->sizelimit) { |
|
250 |
- /* okay to skip w/o allow/deny since dir comes from inotify |
|
249 |
+ if (event_data->sizelimit) { |
|
250 |
+ if (fres != 0 || sb.st_size > event_data->sizelimit) { |
|
251 |
+ /* okay to skip w/o allow/deny since dir comes from inotify |
|
251 | 252 |
* events and (probably) won't block w/ protection enabled */ |
252 |
- event_data->bool_opts &= ((uint16_t) ~ONAS_SCTH_B_SCAN); |
|
253 |
- logg("*ClamWorker: size limit surpassed while doing extra scanning ... skipping object ...\n"); |
|
254 |
- } |
|
255 |
- } |
|
253 |
+ event_data->bool_opts &= ((uint16_t)~ONAS_SCTH_B_SCAN); |
|
254 |
+ logg("*ClamWorker: size limit surpassed while doing extra scanning ... skipping object ...\n"); |
|
255 |
+ } |
|
256 |
+ } |
|
256 | 257 |
|
257 |
- ret = onas_scan_thread_scanfile(event_data, curr->fts_path, sb, &infected, &err, &ret_code); |
|
258 |
- } |
|
259 |
- } |
|
258 |
+ ret = onas_scan_thread_scanfile(event_data, curr->fts_path, sb, &infected, &err, &ret_code); |
|
259 |
+ } |
|
260 |
+ } |
|
260 | 261 |
|
261 | 262 |
out: |
262 |
- if(ftsp) { |
|
263 |
- _priv_fts_close(ftsp); |
|
264 |
- } |
|
263 |
+ if (ftsp) { |
|
264 |
+ _priv_fts_close(ftsp); |
|
265 |
+ } |
|
265 | 266 |
|
266 |
- return ret; |
|
267 |
+ return ret; |
|
267 | 268 |
} |
268 | 269 |
|
269 |
-static cl_error_t onas_scan_thread_handle_file(struct onas_scan_event *event_data, const char *pathname) { |
|
270 |
+static cl_error_t onas_scan_thread_handle_file(struct onas_scan_event *event_data, const char *pathname) |
|
271 |
+{ |
|
270 | 272 |
|
271 |
- STATBUF sb; |
|
272 |
- int32_t infected = 0; |
|
273 |
- int32_t err = 0; |
|
274 |
- cl_error_t ret_code = CL_SUCCESS; |
|
275 |
- int fres = 0; |
|
276 |
- cl_error_t ret = 0; |
|
273 |
+ STATBUF sb; |
|
274 |
+ int32_t infected = 0; |
|
275 |
+ int32_t err = 0; |
|
276 |
+ cl_error_t ret_code = CL_SUCCESS; |
|
277 |
+ int fres = 0; |
|
278 |
+ cl_error_t ret = 0; |
|
277 | 279 |
|
278 |
- if (NULL == pathname || NULL == event_data) { |
|
279 |
- return CL_ENULLARG; |
|
280 |
- } |
|
280 |
+ if (NULL == pathname || NULL == event_data) { |
|
281 |
+ return CL_ENULLARG; |
|
282 |
+ } |
|
281 | 283 |
|
282 |
- fres = CLAMSTAT(pathname, &sb); |
|
283 |
- if (event_data->sizelimit) { |
|
284 |
- if (fres != 0 || sb.st_size > event_data->sizelimit) { |
|
285 |
- /* don't skip so we avoid lockups, but don't scan either; |
|
284 |
+ fres = CLAMSTAT(pathname, &sb); |
|
285 |
+ if (event_data->sizelimit) { |
|
286 |
+ if (fres != 0 || sb.st_size > event_data->sizelimit) { |
|
287 |
+ /* don't skip so we avoid lockups, but don't scan either; |
|
286 | 288 |
* while it should be obvious, this will unconditionally set |
287 | 289 |
* the bit in the map to 0 regardless of original orientation */ |
288 |
- event_data->bool_opts &= ((uint16_t) ~ONAS_SCTH_B_SCAN); |
|
289 |
- } |
|
290 |
- } |
|
290 |
+ event_data->bool_opts &= ((uint16_t)~ONAS_SCTH_B_SCAN); |
|
291 |
+ } |
|
292 |
+ } |
|
291 | 293 |
|
292 |
- ret = onas_scan_thread_scanfile(event_data, pathname, sb, &infected, &err, &ret_code); |
|
294 |
+ ret = onas_scan_thread_scanfile(event_data, pathname, sb, &infected, &err, &ret_code); |
|
293 | 295 |
|
294 | 296 |
#ifdef ONAS_DEBUG |
295 |
- /* very noisy, debug only */ |
|
296 |
- if (event_data->bool_opts & ONAS_SCTH_B_INOTIFY) { |
|
297 |
- logg("*ClamWorker: Inotify Scan Results ...\n\tret = %d ...\n\tinfected = %d ...\n\terr = %d ...\n\tret_code = %d\n", |
|
298 |
- ret, infected, err, ret_code); |
|
299 |
- } else { |
|
300 |
- logg("*ClamWorker: Fanotify Scan Results ...\n\tret = %d ...\n\tinfected = %d ...\n\terr = %d ...\n\tret_code = %d\n\tfd = %d\n", |
|
301 |
- ret, infected, err, ret_code, event_data->fmd->fd); |
|
302 |
- } |
|
297 |
+ /* very noisy, debug only */ |
|
298 |
+ if (event_data->bool_opts & ONAS_SCTH_B_INOTIFY) { |
|
299 |
+ logg("*ClamWorker: Inotify Scan Results ...\n\tret = %d ...\n\tinfected = %d ...\n\terr = %d ...\n\tret_code = %d\n", |
|
300 |
+ ret, infected, err, ret_code); |
|
301 |
+ } else { |
|
302 |
+ logg("*ClamWorker: Fanotify Scan Results ...\n\tret = %d ...\n\tinfected = %d ...\n\terr = %d ...\n\tret_code = %d\n\tfd = %d\n", |
|
303 |
+ ret, infected, err, ret_code, event_data->fmd->fd); |
|
304 |
+ } |
|
303 | 305 |
#endif |
304 | 306 |
|
305 |
- return ret; |
|
307 |
+ return ret; |
|
306 | 308 |
} |
307 | 309 |
|
308 | 310 |
/** |
... | ... |
@@ -310,78 +310,79 @@ static cl_error_t onas_scan_thread_handle_file(struct onas_scan_event *event_dat |
310 | 310 |
* |
311 | 311 |
* @param arg this should always be an onas_scan_event struct |
312 | 312 |
*/ |
313 |
-void *onas_scan_worker(void *arg) { |
|
313 |
+void *onas_scan_worker(void *arg) |
|
314 |
+{ |
|
314 | 315 |
|
315 |
- struct onas_scan_event *event_data = (struct onas_scan_event *) arg; |
|
316 |
+ struct onas_scan_event *event_data = (struct onas_scan_event *)arg; |
|
316 | 317 |
|
317 |
- uint8_t b_dir; |
|
318 |
- uint8_t b_file; |
|
319 |
- uint8_t b_inotify; |
|
320 |
- uint8_t b_fanotify; |
|
318 |
+ uint8_t b_dir; |
|
319 |
+ uint8_t b_file; |
|
320 |
+ uint8_t b_inotify; |
|
321 |
+ uint8_t b_fanotify; |
|
321 | 322 |
|
322 |
- if (NULL == event_data || NULL == event_data->pathname) { |
|
323 |
- logg("ClamWorker: invalid worker arguments for scanning thread\n"); |
|
324 |
- if (event_data) { |
|
325 |
- logg("ClamWorker: pathname is null\n"); |
|
326 |
- } |
|
327 |
- goto done; |
|
328 |
- } |
|
323 |
+ if (NULL == event_data || NULL == event_data->pathname) { |
|
324 |
+ logg("ClamWorker: invalid worker arguments for scanning thread\n"); |
|
325 |
+ if (event_data) { |
|
326 |
+ logg("ClamWorker: pathname is null\n"); |
|
327 |
+ } |
|
328 |
+ goto done; |
|
329 |
+ } |
|
329 | 330 |
|
330 |
- /* load in boolean info from event struct; makes for easier reading--you're welcome */ |
|
331 |
- b_dir = event_data->bool_opts & ONAS_SCTH_B_DIR ? 1 : 0; |
|
332 |
- b_file = event_data->bool_opts & ONAS_SCTH_B_FILE ? 1 : 0; |
|
333 |
- b_inotify = event_data->bool_opts & ONAS_SCTH_B_INOTIFY ? 1 : 0; |
|
334 |
- b_fanotify = event_data->bool_opts & ONAS_SCTH_B_FANOTIFY ? 1 : 0; |
|
331 |
+ /* load in boolean info from event struct; makes for easier reading--you're welcome */ |
|
332 |
+ b_dir = event_data->bool_opts & ONAS_SCTH_B_DIR ? 1 : 0; |
|
333 |
+ b_file = event_data->bool_opts & ONAS_SCTH_B_FILE ? 1 : 0; |
|
334 |
+ b_inotify = event_data->bool_opts & ONAS_SCTH_B_INOTIFY ? 1 : 0; |
|
335 |
+ b_fanotify = event_data->bool_opts & ONAS_SCTH_B_FANOTIFY ? 1 : 0; |
|
335 | 336 |
|
336 | 337 |
#if defined(FANOTIFY) |
337 |
- if (b_inotify) { |
|
338 |
- logg("*ClamWorker: handling inotify event ...\n"); |
|
339 |
- |
|
340 |
- if (b_dir) { |
|
341 |
- logg("*ClamWorker: performing (extra) scanning on directory '%s'\n", event_data->pathname); |
|
342 |
- onas_scan_thread_handle_dir(event_data, event_data->pathname); |
|
343 |
- } else if (b_file) { |
|
344 |
- logg("*ClamWorker: performing (extra) scanning on file '%s'\n", event_data->pathname); |
|
345 |
- onas_scan_thread_handle_file(event_data, event_data->pathname); |
|
346 |
- } |
|
347 |
- |
|
348 |
- } else if (b_fanotify) { |
|
349 |
- |
|
350 |
- logg("*ClamWorker: performing scanning on file '%s'\n", event_data->pathname); |
|
351 |
- onas_scan_thread_handle_file(event_data, event_data->pathname); |
|
352 |
- } else { |
|
353 |
- /* something went very wrong, so check if we have an open fd, |
|
338 |
+ if (b_inotify) { |
|
339 |
+ logg("*ClamWorker: handling inotify event ...\n"); |
|
340 |
+ |
|
341 |
+ if (b_dir) { |
|
342 |
+ logg("*ClamWorker: performing (extra) scanning on directory '%s'\n", event_data->pathname); |
|
343 |
+ onas_scan_thread_handle_dir(event_data, event_data->pathname); |
|
344 |
+ } else if (b_file) { |
|
345 |
+ logg("*ClamWorker: performing (extra) scanning on file '%s'\n", event_data->pathname); |
|
346 |
+ onas_scan_thread_handle_file(event_data, event_data->pathname); |
|
347 |
+ } |
|
348 |
+ |
|
349 |
+ } else if (b_fanotify) { |
|
350 |
+ |
|
351 |
+ logg("*ClamWorker: performing scanning on file '%s'\n", event_data->pathname); |
|
352 |
+ onas_scan_thread_handle_file(event_data, event_data->pathname); |
|
353 |
+ } else { |
|
354 |
+ /* something went very wrong, so check if we have an open fd, |
|
354 | 355 |
* try to close it to resolve any potential lingering permissions event, |
355 | 356 |
* then move to cleanup */ |
356 |
- if (event_data->fmd) { |
|
357 |
- if (event_data->fmd->fd) { |
|
358 |
- close(event_data->fmd->fd); |
|
359 |
- goto done; |
|
360 |
- } |
|
361 |
- } |
|
362 |
- } |
|
357 |
+ if (event_data->fmd) { |
|
358 |
+ if (event_data->fmd->fd) { |
|
359 |
+ close(event_data->fmd->fd); |
|
360 |
+ goto done; |
|
361 |
+ } |
|
362 |
+ } |
|
363 |
+ } |
|
363 | 364 |
#endif |
364 | 365 |
done: |
365 |
- /* our job to cleanup event data: worker queue just kicks us off in a thread pool, drops the event object |
|
366 |
+ /* our job to cleanup event data: worker queue just kicks us off in a thread pool, drops the event object |
|
366 | 367 |
* from the queue and forgets about us */ |
367 | 368 |
|
368 |
- if (NULL != event_data) { |
|
369 |
- if (NULL != event_data->pathname) { |
|
370 |
- free(event_data->pathname); |
|
371 |
- event_data->pathname = NULL; |
|
372 |
- } |
|
369 |
+ if (NULL != event_data) { |
|
370 |
+ if (NULL != event_data->pathname) { |
|
371 |
+ free(event_data->pathname); |
|
372 |
+ event_data->pathname = NULL; |
|
373 |
+ } |
|
373 | 374 |
|
374 | 375 |
#if defined(FANOTIFY) |
375 |
- if (NULL != event_data->fmd) { |
|
376 |
- free(event_data->fmd); |
|
377 |
- event_data->fmd = NULL; |
|
378 |
- } |
|
376 |
+ if (NULL != event_data->fmd) { |
|
377 |
+ free(event_data->fmd); |
|
378 |
+ event_data->fmd = NULL; |
|
379 |
+ } |
|
379 | 380 |
#endif |
380 |
- free(event_data); |
|
381 |
- event_data = NULL; |
|
382 |
- } |
|
381 |
+ free(event_data); |
|
382 |
+ event_data = NULL; |
|
383 |
+ } |
|
383 | 384 |
|
384 |
- return NULL; |
|
385 |
+ return NULL; |
|
385 | 386 |
} |
386 | 387 |
|
387 | 388 |
/** |
... | ... |
@@ -394,18 +395,19 @@ done: |
394 | 394 |
* to further cut down on space used, but (among other thread safety concerns) I'd prefer the worker threads not |
395 | 395 |
* have the ability to modify it at all to keep down on potential maintenance headaches in the future. |
396 | 396 |
*/ |
397 |
-cl_error_t onas_map_context_info_to_event_data(struct onas_context *ctx, struct onas_scan_event **event_data) { |
|
397 |
+cl_error_t onas_map_context_info_to_event_data(struct onas_context *ctx, struct onas_scan_event **event_data) |
|
398 |
+{ |
|
398 | 399 |
|
399 |
- if(NULL == ctx || NULL == event_data || NULL == *event_data) { |
|
400 |
+ if (NULL == ctx || NULL == event_data || NULL == *event_data) { |
|
400 | 401 |
logg("*ClamScThread: context and scan event struct are null ...\n"); |
401 | 402 |
return CL_ENULLARG; |
402 | 403 |
} |
403 | 404 |
|
404 |
- (*event_data)->scantype = ctx->scantype; |
|
405 |
- (*event_data)->timeout = ctx->timeout; |
|
406 |
- (*event_data)->maxstream = ctx->maxstream; |
|
407 |
- (*event_data)->fan_fd = ctx->fan_fd; |
|
408 |
- (*event_data)->sizelimit = ctx->sizelimit; |
|
405 |
+ (*event_data)->scantype = ctx->scantype; |
|
406 |
+ (*event_data)->timeout = ctx->timeout; |
|
407 |
+ (*event_data)->maxstream = ctx->maxstream; |
|
408 |
+ (*event_data)->fan_fd = ctx->fan_fd; |
|
409 |
+ (*event_data)->sizelimit = ctx->sizelimit; |
|
409 | 410 |
(*event_data)->retry_attempts = ctx->retry_attempts; |
410 | 411 |
|
411 | 412 |
if (ctx->retry_on_error) { |
... | ... |
@@ -21,21 +21,20 @@ |
21 | 21 |
#ifndef __ONAS_SCTH_H |
22 | 22 |
#define __ONAS_SCTH_H |
23 | 23 |
|
24 |
- |
|
25 | 24 |
#if defined(FANOTIFY) |
26 | 25 |
#include <sys/fanotify.h> |
27 | 26 |
#endif |
28 | 27 |
#include "shared/optparser.h" |
29 | 28 |
#include "libclamav/clamav.h" |
30 | 29 |
|
31 |
-#define ONAS_SCTH_B_DIR 0x01 |
|
32 |
-#define ONAS_SCTH_B_FILE 0x02 |
|
33 |
-#define ONAS_SCTH_B_INOTIFY 0x04 |
|
34 |
-#define ONAS_SCTH_B_FANOTIFY 0x08 |
|
35 |
-#define ONAS_SCTH_B_SCAN 0x10 |
|
36 |
-#define ONAS_SCTH_B_RETRY_ON_E 0x20 |
|
37 |
-#define ONAS_SCTH_B_DENY_ON_E 0x40 |
|
38 |
-#define ONAS_SCTH_B_REMOTE 0x80 |
|
30 |
+#define ONAS_SCTH_B_DIR 0x01 |
|
31 |
+#define ONAS_SCTH_B_FILE 0x02 |
|
32 |
+#define ONAS_SCTH_B_INOTIFY 0x04 |
|
33 |
+#define ONAS_SCTH_B_FANOTIFY 0x08 |
|
34 |
+#define ONAS_SCTH_B_SCAN 0x10 |
|
35 |
+#define ONAS_SCTH_B_RETRY_ON_E 0x20 |
|
36 |
+#define ONAS_SCTH_B_DENY_ON_E 0x40 |
|
37 |
+#define ONAS_SCTH_B_REMOTE 0x80 |
|
39 | 38 |
|
40 | 39 |
#ifndef HAVE_ATTRIB_PACKED |
41 | 40 |
#define __attribute__(x) |
... | ... |
@@ -48,19 +47,19 @@ |
48 | 48 |
#endif |
49 | 49 |
|
50 | 50 |
struct onas_scan_event { |
51 |
- const char *tcpaddr; |
|
52 |
- int64_t portnum; |
|
53 |
- char *pathname; |
|
54 |
- int fan_fd; |
|
51 |
+ const char *tcpaddr; |
|
52 |
+ int64_t portnum; |
|
53 |
+ char *pathname; |
|
54 |
+ int fan_fd; |
|
55 | 55 |
#if defined(FANOTIFY) |
56 |
- struct fanotify_event_metadata *fmd; |
|
56 |
+ struct fanotify_event_metadata *fmd; |
|
57 | 57 |
#endif |
58 |
- uint8_t retry_attempts; |
|
59 |
- uint64_t sizelimit; |
|
60 |
- int32_t scantype; |
|
61 |
- int64_t maxstream; |
|
62 |
- int64_t timeout; |
|
63 |
- uint8_t bool_opts; |
|
58 |
+ uint8_t retry_attempts; |
|
59 |
+ uint64_t sizelimit; |
|
60 |
+ int32_t scantype; |
|
61 |
+ int64_t maxstream; |
|
62 |
+ int64_t timeout; |
|
63 |
+ uint8_t bool_opts; |
|
64 | 64 |
} __attribute((packed)); |
65 | 65 |
|
66 | 66 |
#ifdef HAVE_PRAGMA_PACK |
... | ... |
@@ -226,19 +226,19 @@ int main(int argc, char *argv[]) |
226 | 226 |
fromStream = 1; |
227 | 227 |
} |
228 | 228 |
|
229 |
- if (g_debug) { |
|
230 |
- /* ask libcurl to show us the verbose output */ |
|
231 |
- if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_VERBOSE, 1L)) { |
|
232 |
- fprintf(stderr, "!ERROR: Failed to set CURLOPT_VERBOSE!\n"); |
|
233 |
- } |
|
234 |
- if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_STDERR, stdout)) { |
|
235 |
- fprintf(stderr, "!ERROR: Failed to direct curl debug output to stdout!\n"); |
|
236 |
- } |
|
237 |
- } |
|
238 |
- |
|
239 |
- if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1)) { |
|
240 |
- fprintf(stderr, "ERROR: Failed to set HTTP version to 1.1 (to prevent 2.0 responses which we don't yet parse properly)!\n"); |
|
241 |
- } |
|
229 |
+ if (g_debug) { |
|
230 |
+ /* ask libcurl to show us the verbose output */ |
|
231 |
+ if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_VERBOSE, 1L)) { |
|
232 |
+ fprintf(stderr, "!ERROR: Failed to set CURLOPT_VERBOSE!\n"); |
|
233 |
+ } |
|
234 |
+ if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_STDERR, stdout)) { |
|
235 |
+ fprintf(stderr, "!ERROR: Failed to direct curl debug output to stdout!\n"); |
|
236 |
+ } |
|
237 |
+ } |
|
238 |
+ |
|
239 |
+ if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1)) { |
|
240 |
+ fprintf(stderr, "ERROR: Failed to set HTTP version to 1.1 (to prevent 2.0 responses which we don't yet parse properly)!\n"); |
|
241 |
+ } |
|
242 | 242 |
|
243 | 243 |
#if defined(C_DARWIN) || defined(_WIN32) |
244 | 244 |
if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function)) { |
... | ... |
@@ -377,30 +377,30 @@ int main(int argc, char *argv[]) |
377 | 377 |
memcpy(submissionID, sp, ep - sp); |
378 | 378 |
submissionID[ep - sp] = '\0'; |
379 | 379 |
|
380 |
- aws_curl = curl_easy_init(); |
|
380 |
+ aws_curl = curl_easy_init(); |
|
381 | 381 |
if (!(aws_curl)) { |
382 | 382 |
fprintf(stderr, "ERROR: Could not initialize libcurl POST presigned\n"); |
383 | 383 |
goto cleanup; |
384 | 384 |
} |
385 | 385 |
|
386 |
- if (g_debug) { |
|
387 |
- /* ask libcurl to show us the verbose output */ |
|
388 |
- if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_VERBOSE, 1L)) { |
|
389 |
- fprintf(stderr, "!ERROR: Failed to set CURLOPT_VERBOSE!\n"); |
|
390 |
- } |
|
391 |
- if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_STDERR, stdout)) { |
|
392 |
- fprintf(stderr, "!ERROR: Failed to direct curl debug output to stdout!\n"); |
|
393 |
- } |
|
394 |
- } |
|
386 |
+ if (g_debug) { |
|
387 |
+ /* ask libcurl to show us the verbose output */ |
|
388 |
+ if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_VERBOSE, 1L)) { |
|
389 |
+ fprintf(stderr, "!ERROR: Failed to set CURLOPT_VERBOSE!\n"); |
|
390 |
+ } |
|
391 |
+ if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_STDERR, stdout)) { |
|
392 |
+ fprintf(stderr, "!ERROR: Failed to direct curl debug output to stdout!\n"); |
|
393 |
+ } |
|
394 |
+ } |
|
395 | 395 |
|
396 |
- if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1)) { |
|
397 |
- fprintf(stderr, "ERROR: Failed to set HTTP version to 1.1 (to prevent 2.0 responses which we don't yet parse properly)!\n"); |
|
398 |
- } |
|
396 |
+ if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1)) { |
|
397 |
+ fprintf(stderr, "ERROR: Failed to set HTTP version to 1.1 (to prevent 2.0 responses which we don't yet parse properly)!\n"); |
|
398 |
+ } |
|
399 | 399 |
|
400 | 400 |
#ifdef _WIN32 |
401 |
- if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function)) { |
|
402 |
- fprintf(stderr, "ERROR: Failed to set SSL CTX function!\n"); |
|
403 |
- } |
|
401 |
+ if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function)) { |
|
402 |
+ fprintf(stderr, "ERROR: Failed to set SSL CTX function!\n"); |
|
403 |
+ } |
|
404 | 404 |
#endif |
405 | 405 |
|
406 | 406 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "key", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
... | ... |
@@ -89,7 +89,13 @@ static inline int bcfail(const char *msg, long a, long b, |
89 | 89 |
#define TRACE_R(x) cli_dbgmsg("bytecode trace: %u, read %llx\n", pc, (long long)x); |
90 | 90 |
#define TRACE_W(x, w, p) cli_dbgmsg("bytecode trace: %u, write%d @%u %llx\n", pc, p, w, (long long)(x)); |
91 | 91 |
#define TRACE_EXEC(id, dest, ty, stack) cli_dbgmsg("bytecode trace: executing %d, -> %u (%u); %u\n", id, dest, ty, stack) |
92 |
-#define TRACE_INST(inst) do {unsigned bbnum = 0; printf("LibClamAV debug: bytecode trace: executing instruction "); cli_byteinst_describe(inst, &bbnum); printf("\n");} while (0) |
|
92 |
+#define TRACE_INST(inst) \ |
|
93 |
+ do { \ |
|
94 |
+ unsigned bbnum = 0; \ |
|
95 |
+ printf("LibClamAV debug: bytecode trace: executing instruction "); \ |
|
96 |
+ cli_byteinst_describe(inst, &bbnum); \ |
|
97 |
+ printf("\n"); \ |
|
98 |
+ } while (0) |
|
93 | 99 |
#define TRACE_API(s, dest, ty, stack) cli_dbgmsg("bytecode trace: executing %s, -> %u (%u); %u\n", s, dest, ty, stack) |
94 | 100 |
#else |
95 | 101 |
#define CHECK_UNREACHABLE return CL_EBYTECODE |
... | ... |
@@ -48,7 +48,6 @@ |
48 | 48 |
#define EC32(v, conv) (conv ? cbswap32(v) : v) |
49 | 49 |
#define EC64(v, conv) (conv ? cbswap64(v) : v) |
50 | 50 |
|
51 |
- |
|
52 | 51 |
#define CLI_TMPUNLK() \ |
53 | 52 |
if (!ctx->engine->keeptmp) { \ |
54 | 53 |
if (cli_unlink(tempfile)) { \ |
... | ... |
@@ -876,7 +875,7 @@ int cli_unpackelf(cli_ctx *ctx) |
876 | 876 |
ndesc = cli_bytecode_context_getresult_file(bc_ctx, &tempfile); |
877 | 877 |
cli_bytecode_context_destroy(bc_ctx); |
878 | 878 |
if (ndesc != -1 && tempfile) { |
879 |
- if (ctx->engine->keeptmp) |
|
879 |
+ if (ctx->engine->keeptmp) |
|
880 | 880 |
cli_dbgmsg("cli_scanelf: Unpacked and rebuilt executable saved in %s\n", tempfile); |
881 | 881 |
else |
882 | 882 |
cli_dbgmsg("cli_scanelf: Unpacked and rebuilt executable\n"); |
... | ... |
@@ -887,7 +886,7 @@ int cli_unpackelf(cli_ctx *ctx) |
887 | 887 |
CLI_TMPUNLK(); |
888 | 888 |
free(tempfile); |
889 | 889 |
return CL_VIRUS; |
890 |
- } |
|
890 |
+ } |
|
891 | 891 |
close(ndesc); |
892 | 892 |
CLI_TMPUNLK(); |
893 | 893 |
free(tempfile); |
... | ... |
@@ -900,4 +899,3 @@ int cli_unpackelf(cli_ctx *ctx) |
900 | 900 |
|
901 | 901 |
return CL_CLEAN; |
902 | 902 |
} |
903 |
- |
... | ... |
@@ -596,7 +596,7 @@ int cli_unpackmacho(cli_ctx *ctx) |
596 | 596 |
ndesc = cli_bytecode_context_getresult_file(bc_ctx, &tempfile); |
597 | 597 |
cli_bytecode_context_destroy(bc_ctx); |
598 | 598 |
if (ndesc != -1 && tempfile) { |
599 |
- if (ctx->engine->keeptmp) |
|
599 |
+ if (ctx->engine->keeptmp) |
|
600 | 600 |
cli_dbgmsg("cli_scanmacho: Unpacked and rebuilt executable saved in %s\n", tempfile); |
601 | 601 |
else |
602 | 602 |
cli_dbgmsg("cli_scanmacho: Unpacked and rebuilt executable\n"); |
... | ... |
@@ -607,7 +607,7 @@ int cli_unpackmacho(cli_ctx *ctx) |
607 | 607 |
CLI_TMPUNLK(); |
608 | 608 |
free(tempfile); |
609 | 609 |
return CL_VIRUS; |
610 |
- } |
|
610 |
+ } |
|
611 | 611 |
close(ndesc); |
612 | 612 |
CLI_TMPUNLK(); |
613 | 613 |
free(tempfile); |
... | ... |
@@ -620,4 +620,3 @@ int cli_unpackmacho(cli_ctx *ctx) |
620 | 620 |
|
621 | 621 |
return CL_CLEAN; |
622 | 622 |
} |
623 |
- |
... | ... |
@@ -43,8 +43,8 @@ struct pdf_obj { |
43 | 43 |
uint32_t statsflags; |
44 | 44 |
uint32_t numfilters; |
45 | 45 |
uint32_t filterlist[PDF_FILTERLIST_MAX]; |
46 |
- const char *stream; // pointer to stream contained in object. |
|
47 |
- size_t stream_size; // size of stream contained in object. |
|
46 |
+ const char *stream; // pointer to stream contained in object. |
|
47 |
+ size_t stream_size; // size of stream contained in object. |
|
48 | 48 |
struct objstm_struct *objstm; // Should be NULL unless the obj exists in an object stream (separate buffer) |
49 | 49 |
char *path; |
50 | 50 |
}; |
... | ... |
@@ -64,29 +64,29 @@ const struct clam_option __clam_options[] = { |
64 | 64 |
/* name, longopt, sopt, argtype, regex, num, str, flags, owner, description, suggested */ |
65 | 65 |
|
66 | 66 |
/* cmdline only */ |
67 |
- { NULL, "help", 'h', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL | OPT_MILTER | OPT_CLAMCONF | OPT_CLAMDTOP | OPT_CLAMBC | OPT_CLAMONACC, "", "" }, |
|
68 |
- { NULL, "config-file", 'c', CLOPT_TYPE_STRING, NULL, 0, CONFDIR_CLAMD, FLAG_REQUIRED, OPT_CLAMD | OPT_CLAMDSCAN | OPT_CLAMDTOP | OPT_CLAMONACC, "", "" }, |
|
67 |
+ {NULL, "help", 'h', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL | OPT_MILTER | OPT_CLAMCONF | OPT_CLAMDTOP | OPT_CLAMBC | OPT_CLAMONACC, "", ""}, |
|
68 |
+ {NULL, "config-file", 'c', CLOPT_TYPE_STRING, NULL, 0, CONFDIR_CLAMD, FLAG_REQUIRED, OPT_CLAMD | OPT_CLAMDSCAN | OPT_CLAMDTOP | OPT_CLAMONACC, "", ""}, |
|
69 | 69 |
{NULL, "config-file", 0, CLOPT_TYPE_STRING, NULL, 0, CONFDIR_FRESHCLAM, FLAG_REQUIRED, OPT_FRESHCLAM, "", ""}, |
70 | 70 |
{NULL, "config-file", 'c', CLOPT_TYPE_STRING, NULL, 0, CONFDIR_MILTER, FLAG_REQUIRED, OPT_MILTER, "", ""}, |
71 |
- { NULL, "version", 'V', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL | OPT_MILTER | OPT_CLAMCONF | OPT_CLAMDTOP | OPT_CLAMBC | OPT_CLAMONACC, "", "" }, |
|
71 |
+ {NULL, "version", 'V', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL | OPT_MILTER | OPT_CLAMCONF | OPT_CLAMDTOP | OPT_CLAMBC | OPT_CLAMONACC, "", ""}, |
|
72 | 72 |
{NULL, "debug", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC | OPT_CLAMD | OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_SIGTOOL, "", ""}, |
73 | 73 |
{NULL, "gen-json", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN | OPT_SIGTOOL, "", ""}, |
74 |
- { NULL, "verbose", 'v', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL | OPT_CLAMONACC, "", "" }, |
|
74 |
+ {NULL, "verbose", 'v', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL | OPT_CLAMONACC, "", ""}, |
|
75 | 75 |
{NULL, "dumpcerts", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "Dump authenticode certificate chain.", ""}, |
76 |
- { NULL, "quiet", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL | OPT_CLAMONACC, "", "" }, |
|
76 |
+ {NULL, "quiet", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL | OPT_CLAMONACC, "", ""}, |
|
77 | 77 |
{NULL, "leave-temps", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", ""}, |
78 | 78 |
{NULL, "no-warnings", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "", ""}, |
79 | 79 |
{NULL, "show-progress", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "", ""}, |
80 |
- { NULL, "stdout", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL | OPT_CLAMONACC, "", "" }, |
|
80 |
+ {NULL, "stdout", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL | OPT_CLAMONACC, "", ""}, |
|
81 | 81 |
{NULL, "daemon", 'd', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "", ""}, |
82 | 82 |
{NULL, "no-dns", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "", ""}, |
83 | 83 |
{NULL, "list-mirrors", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "", ""}, |
84 | 84 |
{NULL, "update-db", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_FRESHCLAM, "", ""}, |
85 | 85 |
{NULL, "reload", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN, "", ""}, |
86 |
- { NULL, "multiscan", 'm', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN | OPT_CLAMONACC, "", "" }, |
|
87 |
- { NULL, "fdpass", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN | OPT_CLAMONACC, "", "" }, |
|
88 |
- { NULL, "stream", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN | OPT_CLAMONACC, "", "" }, |
|
89 |
- { NULL, "allmatch", 'z', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_CLAMONACC, "", "" }, |
|
86 |
+ {NULL, "multiscan", 'm', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN | OPT_CLAMONACC, "", ""}, |
|
87 |
+ {NULL, "fdpass", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN | OPT_CLAMONACC, "", ""}, |
|
88 |
+ {NULL, "stream", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN | OPT_CLAMONACC, "", ""}, |
|
89 |
+ {NULL, "allmatch", 'z', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_CLAMONACC, "", ""}, |
|
90 | 90 |
{NULL, "normalize", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMSCAN, "Perform HTML, script, and text normalization", ""}, |
91 | 91 |
{NULL, "database", 'd', CLOPT_TYPE_STRING, NULL, -1, DATADIR, FLAG_REQUIRED | FLAG_MULTIPLE, OPT_CLAMSCAN, "", ""}, /* merge it with DatabaseDirectory (and fix conflict with --datadir */ |
92 | 92 |
{NULL, "recursive", 'r', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", ""}, |
... | ... |
@@ -96,11 +96,11 @@ const struct clam_option __clam_options[] = { |
96 | 96 |
{NULL, "bell", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", ""}, |
97 | 97 |
{NULL, "no-summary", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", ""}, |
98 | 98 |
{NULL, "file-list", 'f', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", ""}, |
99 |
- { NULL, "infected", 'i', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_CLAMONACC, "", "" }, |
|
99 |
+ {NULL, "infected", 'i', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_CLAMONACC, "", ""}, |
|
100 | 100 |
{NULL, "suppress-ok-results", 'o', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", ""}, |
101 |
- { NULL, "move", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_CLAMONACC, "", "" }, |
|
102 |
- { NULL, "copy", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_CLAMONACC, "", "" }, |
|
103 |
- { NULL, "remove", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_CLAMONACC, "", "" }, |
|
101 |
+ {NULL, "move", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_CLAMONACC, "", ""}, |
|
102 |
+ {NULL, "copy", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_CLAMONACC, "", ""}, |
|
103 |
+ {NULL, "remove", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_CLAMONACC, "", ""}, |
|
104 | 104 |
{NULL, "exclude", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMSCAN, "", ""}, |
105 | 105 |
{NULL, "exclude-dir", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMSCAN, "", ""}, |
106 | 106 |
{NULL, "include", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMSCAN, "", ""}, |
... | ... |
@@ -192,7 +192,7 @@ const struct clam_option __clam_options[] = { |
192 | 192 |
|
193 | 193 |
{"PreludeAnalyzerName", "prelude-analyzer-name", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD, "Name of the analyzer as seen in prewikka", ""}, |
194 | 194 |
|
195 |
- { "LogFile", "log", 'l', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD | OPT_MILTER | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_CLAMONACC, "Save all reports to a log file.", "/tmp/clamav.log" }, |
|
195 |
+ {"LogFile", "log", 'l', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD | OPT_MILTER | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_CLAMONACC, "Save all reports to a log file.", "/tmp/clamav.log"}, |
|
196 | 196 |
|
197 | 197 |
{"LogFileUnlock", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_MILTER, "By default the log file is locked for writing and only a single\ndaemon process can write to it. This option disables the lock.", "yes"}, |
198 | 198 |
|
... | ... |
@@ -277,7 +277,7 @@ const struct clam_option __clam_options[] = { |
277 | 277 |
|
278 | 278 |
{"AllowAllMatchScan", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD, "Permit use of the ALLMATCHSCAN command.", "yes"}, |
279 | 279 |
|
280 |
- { "Foreground", "foreground", 'F', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER | OPT_CLAMONACC, "Don't fork into background.", "no" }, |
|
280 |
+ {"Foreground", "foreground", 'F', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER | OPT_CLAMONACC, "Don't fork into background.", "no"}, |
|
281 | 281 |
|
282 | 282 |
{"Debug", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM, "Enable debug messages in libclamav.", "no"}, |
283 | 283 |
|
... | ... |
@@ -402,7 +402,7 @@ const struct clam_option __clam_options[] = { |
402 | 402 |
/* OnAccess settings */ |
403 | 403 |
{"OnAccessMountPath", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option specifies a directory or mount point which should be scanned on access. The mount point specified, or the mount point containing the specified directory will be watched, but only notifications will occur. If any directories are specified, this option will preempt the DDD system. It can also be used multiple times.", "/\n/home/user"}, |
404 | 404 |
|
405 |
- { "OnAccessIncludePath", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option specifies a directory (including all files and directories\ninside it), which should be scanned on access. This option can\nbe used multiple times.", "/home\n/students" }, |
|
405 |
+ {"OnAccessIncludePath", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option specifies a directory (including all files and directories\ninside it), which should be scanned on access. This option can\nbe used multiple times.", "/home\n/students"}, |
|
406 | 406 |
|
407 | 407 |
{"OnAccessExcludePath", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option allows excluding directories from on-access scanning. It can\nbe used multiple times. Only works with DDD system.", "/home/bofh\n/root"}, |
408 | 408 |
|
... | ... |
@@ -410,30 +410,28 @@ const struct clam_option __clam_options[] = { |
410 | 410 |
|
411 | 411 |
{"OnAccessExcludeUID", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "With this option you can whitelist specific UIDs. Processes with these UIDs\nwill be able to access all files.\nThis option can be used multiple times (one per line). Using a value of 0 on any line will disable this option entirely. To whitelist the root UID please enable the OnAccessExcludeRootUID option.", "0"}, |
412 | 412 |
|
413 |
- { "OnAccessExcludeUname", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option allows exclusions via user names when using the on-access scanning client. It can\nbe used multiple times.", "clamuser" }, |
|
413 |
+ {"OnAccessExcludeUname", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option allows exclusions via user names when using the on-access scanning client. It can\nbe used multiple times.", "clamuser"}, |
|
414 | 414 |
|
415 | 415 |
{"OnAccessMaxFileSize", NULL, 0, CLOPT_TYPE_SIZE, MATCH_SIZE, 5242880, NULL, 0, OPT_CLAMD, "Files larger than this value will not be scanned in on access.", "5M"}, |
416 | 416 |
|
417 |
- { "OnAccessDisableDDD", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "This option toggles the dynamic directory determination system for on-access scanning (Linux only).", "no" }, |
|
417 |
+ {"OnAccessDisableDDD", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "This option toggles the dynamic directory determination system for on-access scanning (Linux only).", "no"}, |
|
418 | 418 |
|
419 | 419 |
{"OnAccessPrevention", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "This option changes fanotify behavior to prevent access attempts on malicious files instead of simply notifying the user (On Access scan only).", "yes"}, |
420 | 420 |
|
421 | 421 |
{"OnAccessExtraScanning", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Enables extra scanning and notification after catching certain inotify events. Only works with the DDD system enabled.", "yes"}, |
422 | 422 |
|
423 |
+ {"OnAccessCurlTimeout", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 5000l, NULL, 0, OPT_CLAMD, "Max amount of time (in milliseconds) that the OnAccess client should spend for every connect, send, and recieve attempt when communicating with clamd via curl (5s default)", "10000L"}, |
|
423 | 424 |
|
424 |
- { "OnAccessCurlTimeout", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 5000l, NULL, 0, OPT_CLAMD, "Max amount of time (in milliseconds) that the OnAccess client should spend for every connect, send, and recieve attempt when communicating with clamd via curl (5s default)", "10000L" }, |
|
425 |
+ {"OnAccessMaxThreads", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 5, NULL, 0, OPT_CLAMD, "Max number of scanning threads to allocate to the OnAccess thread pool at startup--these threads are the ones responsible for creating a connection with the daemon and kicking off scanning after an event has been processed. To prevent clamonacc from consuming all clamd's resources keep this lower than clamd's max threads. Default is 5", "10"}, |
|
425 | 426 |
|
426 |
- { "OnAccessMaxThreads", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 5, NULL, 0, OPT_CLAMD, "Max number of scanning threads to allocate to the OnAccess thread pool at startup--these threads are the ones responsible for creating a connection with the daemon and kicking off scanning after an event has been processed. To prevent clamonacc from consuming all clamd's resources keep this lower than clamd's max threads. Default is 5", "10" }, |
|
427 |
- |
|
428 |
- { "OnAccessRetryAttempts", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_CLAMD, "Number of times the OnAccess client will retry a failed scan due to connection problems (or other issues). Defaults to no retries.", "3" }, |
|
429 |
- |
|
430 |
- { "OnAccessDenyOnError", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "When using prevention, if this option is turned on, any errors that occur during scanning will result in the event attempt being denied. This could potentially lead to unwanted system behaviour with certain configurations, so the client defaults to off and allowing access events in case of error.", "yes" }, |
|
427 |
+ {"OnAccessRetryAttempts", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_CLAMD, "Number of times the OnAccess client will retry a failed scan due to connection problems (or other issues). Defaults to no retries.", "3"}, |
|
431 | 428 |
|
429 |
+ {"OnAccessDenyOnError", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "When using prevention, if this option is turned on, any errors that occur during scanning will result in the event attempt being denied. This could potentially lead to unwanted system behaviour with certain configurations, so the client defaults to off and allowing access events in case of error.", "yes"}, |
|
432 | 430 |
|
433 | 431 |
/* clamonacc cmdline options */ |
434 | 432 |
|
435 |
- { NULL, "watch-list", 'w', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMONACC, "", ""}, |
|
436 |
- { NULL, "exclude-list", 'e', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMONACC, "", ""}, |
|
433 |
+ {NULL, "watch-list", 'w', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMONACC, "", ""}, |
|
434 |
+ {NULL, "exclude-list", 'e', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMONACC, "", ""}, |
|
437 | 435 |
|
438 | 436 |
/* FIXME: mark these as private and don't output into clamd.conf/man */ |
439 | 437 |
{"DevACOnly", "dev-ac-only", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, FLAG_HIDDEN, OPT_CLAMD | OPT_CLAMSCAN, "", ""}, |
... | ... |
@@ -525,7 +523,7 @@ const struct clam_option __clam_options[] = { |
525 | 525 |
{"ArchiveLimitMemoryUsage", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", ""}, |
526 | 526 |
{"MailFollowURLs", "mail-follow-urls", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN | OPT_DEPRECATED, "", ""}, |
527 | 527 |
{"AllowSupplementaryGroups", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER | OPT_DEPRECATED, "Initialize a supplementary group access (the process must be started by root).", "no"}, |
528 |
- { "ScanOnAccess", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" }, |
|
528 |
+ {"ScanOnAccess", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", ""}, |
|
529 | 529 |
|
530 | 530 |
/* Milter specific options */ |
531 | 531 |
|
... | ... |
@@ -254,8 +254,8 @@ static int rename_logg(STATBUF *sb) |
254 | 254 |
} |
255 | 255 |
|
256 | 256 |
#ifdef _WIN32 |
257 |
- if (0 == MoveFileA(logg_file, rotate_file)) { |
|
258 |
- fprintf(stderr, "Failed to rename file with error code: %d\n", GetLastError()); |
|
257 |
+ if (0 == MoveFileA(logg_file, rotate_file)) { |
|
258 |
+ fprintf(stderr, "Failed to rename file with error code: %d\n", GetLastError()); |
|
259 | 259 |
#else |
260 | 260 |
if (rename(logg_file, rotate_file)) { |
261 | 261 |
#endif |
... | ... |
@@ -29,44 +29,44 @@ |
29 | 29 |
/* Ensure we have print format types */ |
30 | 30 |
/* PRIu64 should be in <inttypes.h> */ |
31 | 31 |
#ifndef _SF64_PREFIX |
32 |
- #define _SF64_PREFIX "ll" |
|
32 |
+#define _SF64_PREFIX "ll" |
|
33 | 33 |
#endif |
34 | 34 |
|
35 | 35 |
#ifndef PRIu64 |
36 |
- #define PRIu64 _SF64_PREFIX "u" |
|
36 |
+#define PRIu64 _SF64_PREFIX "u" |
|
37 | 37 |
#endif |
38 | 38 |
#ifndef PRIx64 |
39 |
- #define PRIx64 _SF64_PREFIX "i" |
|
39 |
+#define PRIx64 _SF64_PREFIX "i" |
|
40 | 40 |
#endif |
41 | 41 |
#ifndef PRIi64 |
42 |
- #define PRIi64 _SF64_PREFIX "x" |
|
42 |
+#define PRIi64 _SF64_PREFIX "x" |
|
43 | 43 |
#endif |
44 | 44 |
|
45 | 45 |
#ifndef STDu64 |
46 |
- #define STDu64 "%" PRIu64 |
|
47 |
- #define STDi64 "%" PRIi64 |
|
48 |
- #define STDx64 "%" PRIx64 |
|
46 |
+#define STDu64 "%" PRIu64 |
|
47 |
+#define STDi64 "%" PRIi64 |
|
48 |
+#define STDx64 "%" PRIx64 |
|
49 | 49 |
#endif |
50 | 50 |
|
51 | 51 |
/* PRIu32 should also be in <inttypes.h> */ |
52 | 52 |
#ifndef PRIu32 |
53 |
- #ifndef _SF32_PREFIX |
|
54 |
- #define _SF32_PREFIX "l" |
|
55 |
- #endif |
|
53 |
+#ifndef _SF32_PREFIX |
|
54 |
+#define _SF32_PREFIX "l" |
|
55 |
+#endif |
|
56 | 56 |
|
57 |
- #define PRIu32 _SF32_PREFIX "u" |
|
58 |
- #define PRIi32 _SF32_PREFIX "i" |
|
59 |
- #define PRIx32 _SF32_PREFIX "x" |
|
57 |
+#define PRIu32 _SF32_PREFIX "u" |
|
58 |
+#define PRIi32 _SF32_PREFIX "i" |
|
59 |
+#define PRIx32 _SF32_PREFIX "x" |
|
60 | 60 |
#endif |
61 | 61 |
|
62 | 62 |
#ifndef STDu32 |
63 |
- #define STDu32 "%" PRIu32 |
|
64 |
- #define STDi32 "%" PRIi32 |
|
65 |
- #define STDx32 "%" PRIx32 |
|
63 |
+#define STDu32 "%" PRIu32 |
|
64 |
+#define STDi32 "%" PRIi32 |
|
65 |
+#define STDx32 "%" PRIx32 |
|
66 | 66 |
#endif |
67 | 67 |
|
68 | 68 |
#ifndef INT32_MAX |
69 |
- #define INT32_MAX 2147483647 |
|
69 |
+#define INT32_MAX 2147483647 |
|
70 | 70 |
#endif |
71 | 71 |
|
72 | 72 |
#endif |