Browse code

rework globbing

aCaB authored on 2010/03/18 09:43:53
Showing 11 changed files
... ...
@@ -493,7 +493,7 @@
493 493
 /* #undef USE_SYSLOG */
494 494
 
495 495
 /* Version number of package */
496
-#define VERSION "devel-clamav-0.96rc1-8-g9a04560"
496
+#define VERSION "devel-clamav-0.96rc1-13-g99a2d96"
497 497
 
498 498
 /* Version suffix for package */
499 499
 #define VERSION_SUFFIX ""
... ...
@@ -220,18 +220,6 @@
220 220
 					>
221 221
 				</File>
222 222
 			</Filter>
223
-			<Filter
224
-				Name="compat"
225
-				>
226
-				<File
227
-					RelativePath=".\compat\libgen.c"
228
-					>
229
-				</File>
230
-				<File
231
-					RelativePath=".\compat\setargv.c"
232
-					>
233
-				</File>
234
-			</Filter>
235 223
 		</Filter>
236 224
 		<Filter
237 225
 			Filter="h;hpp;hxx;hm;inl;inc;xsd"
... ...
@@ -204,18 +204,6 @@
204 204
 					>
205 205
 				</File>
206 206
 			</Filter>
207
-			<Filter
208
-				Name="compat"
209
-				>
210
-				<File
211
-					RelativePath=".\compat\libgen.c"
212
-					>
213
-				</File>
214
-				<File
215
-					RelativePath=".\compat\setargv.c"
216
-					>
217
-				</File>
218
-			</Filter>
219 207
 		</Filter>
220 208
 		<Filter
221 209
 			Filter="h;hpp;hxx;hm;inl;inc;xsd"
... ...
@@ -190,18 +190,6 @@
190 190
 				>
191 191
 			</File>
192 192
 			<Filter
193
-				Name="compat"
194
-				>
195
-				<File
196
-					RelativePath=".\compat\libgen.c"
197
-					>
198
-				</File>
199
-				<File
200
-					RelativePath=".\compat\setargv.c"
201
-					>
202
-				</File>
203
-			</Filter>
204
-			<Filter
205 193
 				Name="shared"
206 194
 				>
207 195
 				<File
208 196
new file mode 100644
... ...
@@ -0,0 +1,274 @@
0
+/*
1
+ *  Copyright (C) 2010 Sourcefire, Inc.
2
+ *
3
+ *  Authors: aCaB <acab@clamav.net>
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#include "dirent.h"
21
+#include "libgen.h"
22
+
23
+/* 
24
+    I GIVE UP! The CRT is b0rked and cannot be helped.
25
+
26
+    The documentation suggestes to handle globbing automagically via linking in
27
+    the msvc-provided setargv.obj. Unfortunately that thing has got any sort of bugs
28
+    and perverts filenames rather than expanding them.
29
+
30
+    The other suggested approach is to override the crt-builtin "_setargv" with a
31
+    custom routine to manually process the command line args before they are fed to main.
32
+    Now this is even funnier: the hook is indeed called bedore main(), but then its work
33
+    is discarded and replaced with that of the default parser... how useful!
34
+    After some debugging the problem turned out to be in the design. The flow is like:
35
+    pre_c_init -> _setargv
36
+    then
37
+    pre_cpp_init -> _setargv
38
+    Looking at the code in there, it clearly shows that both _init functions are 99% the
39
+    same. In case you are wondering... yes, everything is done twice! Including the
40
+    command line parsing...
41
+    There is however a small difference: while pre_c_init correctly calls the custom
42
+    _setargv if present, pre_cpp_init always calls the crt-builtin!
43
+    If you want to double check this link the msvc-provided noarg.obj in, then break in main
44
+    and see how argv and argc are actually set... If you try with setargv.obj, instead, you
45
+    will see that it apparently works, but that's just a hack for which pre_cpp_init ends
46
+    up calling __setargv instead of _setargv based on the _dowildcard flag.
47
+
48
+    So the way to FIX this mess involves a small trick: in the _setargv override I
49
+    don't just parse the command line properly, but I also turn my arguments into a new
50
+    command line, which I use to replace the existing one. The replaced line will then be
51
+    processed by pre_cpp_init and everything is fine.
52
+    To replace the original line with the fixed one it's sufficient to replace the pointer
53
+    returned by the __p__acmdln() function. The proto it "extern char **__p__acmdln(void)".
54
+
55
+    Of course the trick only works if the line is crafted in a way that can be understood
56
+    and parsed by the _setargv builtin.
57
+    Apparently, however, the authors of this pile of crap which goes under the name of CRT,
58
+    are not even able to keep their bugs consistent. So, while in MSVC 2008 it was enough to
59
+    put each arg in "'s, in MSVC 2008 SP 1 you additionally need to take care of "escaped"
60
+    quotes. I.e.: \".
61
+
62
+    Whatever...
63
+    I've given up trying to fit globbing below main. It's now hooked into main via a
64
+    #define wrapper.
65
+*/
66
+
67
+static int glob_add(const char *path, int *argc, char ***argv) {
68
+    char *tail = strchr(path, '*'), *tailqmark;
69
+    char *dup1, *dup2, *dir, *base, *taildirsep, *tailwldsep;
70
+    struct dirent *de;
71
+    int baselen, taillen, dirlen, mergedir = 0, outlen = 0;
72
+    int qmarklen = 0;
73
+    DIR *d;
74
+
75
+    if(strlen(path) > 4 && !memcmp(path, "\\\\?\\", 4))
76
+	tailqmark = strchr(&path[4], '?');
77
+    else
78
+	tailqmark = strchr(path, '?');
79
+
80
+    if(tailqmark && (!tail || tailqmark < tail))
81
+	tail = tailqmark;
82
+
83
+    if(!tail) {
84
+	*argv = realloc(*argv, sizeof(**argv) * (*argc + 1));
85
+	(*argv)[*argc] = path;
86
+	(*argc)++;
87
+	return strlen(path);
88
+    }
89
+
90
+    if(tail!=path && tail[-1] == '\\') {
91
+	tail[-1] = '\0';
92
+	mergedir = 1;
93
+    }
94
+    while(*tail) {
95
+	if(*tail == '?') {
96
+	    if(tail == tailqmark || qmarklen) 
97
+		qmarklen++;
98
+	    *tail = 0;
99
+	} else if(*tail == '*') {
100
+	    *tail = '\0';
101
+	    qmarklen = 0;
102
+	} else 
103
+	    break;
104
+	tail++;
105
+    }
106
+    taillen = strlen(tail);
107
+    taildirsep = strchr(tail, '\\');
108
+    if(taildirsep && taildirsep - tail == taillen - 1) {
109
+	*taildirsep = '\0';
110
+	taildirsep = NULL;
111
+	taillen--;
112
+    }
113
+    if(!taildirsep)
114
+	taildirsep = tail + taillen;
115
+
116
+    tailwldsep = strchr(tail, '*');
117
+    tailqmark = strchr(tail, '?');
118
+    if(tailqmark && (!tailwldsep || tailqmark < tailwldsep))
119
+	tailwldsep = tailqmark;
120
+    if(!tailwldsep)
121
+	tailwldsep = tail + taillen;
122
+
123
+    dup1 = strdup(path);
124
+    dup2 = strdup(path);
125
+
126
+    if(!mergedir) {
127
+	dir = dirname(dup1);
128
+	base = basename(dup2);
129
+    } else {
130
+	dir = dup1;
131
+	base = dup2;
132
+	*dup2 = '\0';
133
+    }
134
+
135
+    dirlen = strlen(dir);
136
+    baselen = strlen(base);
137
+
138
+    d = opendir(dir);
139
+    while(d && (de = readdir(d))) {
140
+	int namelen = strlen(de->d_name);
141
+	char *newpath;
142
+
143
+	if(!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue;
144
+	if(namelen < baselen) continue;
145
+	if(strncasecmp(base, de->d_name, baselen)) continue;
146
+	if(de->d_type == DT_DIR && taildirsep < tailwldsep) {
147
+	    int d_taillen = taildirsep - tail;
148
+	    if(namelen < baselen + d_taillen) continue;
149
+	    if(strncasecmp(tail, &de->d_name[namelen - d_taillen], d_taillen)) continue;
150
+	    newpath = malloc(dirlen + namelen + taillen - d_taillen + 3);
151
+	    sprintf(newpath, "%s\\%s\\%s", dir, de->d_name, &tail[d_taillen+1]);
152
+	    outlen += glob_add(newpath, argc, argv);
153
+	} else {
154
+	    int d_taillen = tailwldsep - tail;
155
+	    char *start;
156
+	    if(namelen < baselen + d_taillen) continue;
157
+	    if(qmarklen && baselen + qmarklen + d_taillen != namelen)	continue;
158
+	    if(d_taillen == taillen) {
159
+		start = &de->d_name[namelen - d_taillen];
160
+		namelen = d_taillen;
161
+	    } else {
162
+		start = &de->d_name[baselen];
163
+		namelen -= baselen;
164
+	    }
165
+
166
+	    for(; namelen >= d_taillen; start++, namelen--) {
167
+		if(strncasecmp(start, tail, d_taillen)) continue;
168
+		newpath = malloc(dirlen + (start - de->d_name) +  taillen + 2);
169
+		sprintf(newpath, "%s\\", dir);
170
+		memcpy(&newpath[dirlen + 1], de->d_name, start - de->d_name);
171
+		strcpy(&newpath[dirlen + 1 + start - de->d_name], tail);
172
+		outlen += glob_add(newpath, argc, argv);
173
+	    }
174
+	}
175
+    }
176
+    if(d) closedir(d);
177
+    free(dup1);
178
+    free(dup2);
179
+    free(path);
180
+    return outlen;
181
+}
182
+
183
+void w32_glob(int *argc_ptr, char ***argv_ptr) {
184
+    char *cur = GetCommandLineA(), *begparm = NULL, *endparm = NULL;
185
+    char **argv = NULL, c;
186
+    int argc = 0, in_sq = 0, in_dq = 0, need_glob = 0, allarglen = 0;
187
+
188
+    do {
189
+	c = *cur;
190
+	switch(c) {
191
+	    case '\0':
192
+		endparm = cur;
193
+		break;
194
+	    case ' ':
195
+		if(begparm && !(in_sq | in_dq))
196
+		    endparm = cur;
197
+		break;
198
+	    case '\'':
199
+		if(!in_dq) {
200
+		    in_sq = !in_sq;
201
+		    if(!in_sq)
202
+			endparm = cur;
203
+		}
204
+		break;
205
+	    case '"':
206
+		if(!in_sq) {
207
+		    in_dq = !in_dq;
208
+		    if(!in_dq)
209
+			endparm = cur;
210
+		}
211
+		break;
212
+	    case '*':
213
+	    case '?':
214
+		if(!in_sq)
215
+		    need_glob = 1;
216
+	    default:
217
+		if(!begparm) {
218
+		    begparm = cur;
219
+		    endparm = NULL;
220
+		}
221
+	}
222
+	if (begparm && endparm) {
223
+	    if(begparm < endparm) {
224
+		char *path = malloc(endparm - begparm + 1), *quotes;
225
+		int arglen = 0;
226
+
227
+		memcpy(path, begparm, endparm - begparm);
228
+		path[endparm - begparm] = '\0';
229
+		quotes = path;
230
+		while((quotes = strchr(quotes, '"')))
231
+		    memmove(quotes, quotes + 1, (endparm - begparm) - (quotes - path));
232
+		if(argc && need_glob) {
233
+		    arglen = glob_add(path, &argc, &argv);
234
+		    if(!arglen) {
235
+			path = malloc(endparm - begparm + 1);
236
+			memcpy(path, begparm, endparm - begparm);
237
+			path[endparm - begparm] = '\0';
238
+		    }
239
+		}
240
+		if(!arglen) {
241
+		    argv = realloc(argv, sizeof(*argv) * (argc + 1));
242
+		    argv[argc] = path;
243
+		    argc++;
244
+		    arglen = endparm - begparm;
245
+		}
246
+		allarglen += arglen;
247
+	    }
248
+	    need_glob = 0;
249
+	    in_sq = 0;
250
+	    in_dq = 0;
251
+	    begparm = NULL;
252
+	    endparm = NULL;
253
+	}
254
+	cur++;
255
+    } while (c);
256
+
257
+    if(argc) {
258
+	int i, argvlen = sizeof(*argv) * (argc + 1), argclen = 0;
259
+	argv = realloc(argv, argvlen + allarglen + argc);
260
+	argv[argc] = NULL;
261
+	for(i=0; i<argc; i++) {
262
+	    int curlen = strlen(argv[i]) + 1;
263
+	    char *curarg = (char *)argv + argvlen + argclen;
264
+	    memcpy(curarg, argv[i], curlen);
265
+	    argclen += curlen;
266
+	    free(argv[i]);
267
+	    argv[i] = curarg;
268
+	}
269
+    }
270
+    *argc_ptr = argc;
271
+    *argv_ptr = argv;
272
+}
273
+
... ...
@@ -1,3 +1,23 @@
1
+/*
2
+ *  Copyright (C) 2010 Sourcefire, Inc.
3
+ *
4
+ *  Authors: aCaB <acab@clamav.net>
5
+ *
6
+ *  This program is free software; you can redistribute it and/or modify
7
+ *  it under the terms of the GNU General Public License version 2 as
8
+ *  published by the Free Software Foundation.
9
+ *
10
+ *  This program is distributed in the hope that it will be useful,
11
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ *  GNU General Public License for more details.
14
+ *
15
+ *  You should have received a copy of the GNU General Public License
16
+ *  along with this program; if not, write to the Free Software
17
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ *  MA 02110-1301, USA.
19
+ */
20
+
1 21
 /* just a draft for now */
2 22
 
3 23
 #if HAVE_CONFIG_H
4 24
deleted file mode 100644
... ...
@@ -1,269 +0,0 @@
1
-/*
2
- *  Copyright (C) 2009 Sourcefire, Inc.
3
- *
4
- *  Authors: aCaB <acab@clamav.net>
5
- *
6
- *  This program is free software; you can redistribute it and/or modify
7
- *  it under the terms of the GNU General Public License version 2 as
8
- *  published by the Free Software Foundation.
9
- *
10
- *  This program is distributed in the hope that it will be useful,
11
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
- *  GNU General Public License for more details.
14
- *
15
- *  You should have received a copy of the GNU General Public License
16
- *  along with this program; if not, write to the Free Software
17
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
- *  MA 02110-1301, USA.
19
- */
20
-
21
-#if HAVE_CONFIG_H
22
-#include "clamav-config.h"
23
-#endif
24
-
25
-#include "dirent.h"
26
-#include "libgen.h"
27
-
28
-#include <fcntl.h>
29
-
30
-/* THIS IS A HACK ! */
31
-/* _setargv is the designed way to customize command line parsing which we use here
32
-   for globbing reasons (incidentally the globbing in setargv.obj is badly broken)
33
-   
34
-   The crt first calls OUR _setargv from pre_c_init but later, from within pre_cpp_init,
35
-   it also calls ITS OWN BUILTIN NATIVE CRAP, which re-parses the command line and 
36
-   eventually overrides our override.
37
-
38
-   So, we additionally replace the command line global pointer _acmdln with a
39
-   crafted set of arguments in order to fool buggy CRT's.
40
-*/
41
-#define _MY_CRT_INSISTS_ON_PARSING_THE_COMMAND_LINE_TWICE_FOR_NO_REASONS_
42
-#ifdef _MY_CRT_INSISTS_ON_PARSING_THE_COMMAND_LINE_TWICE_FOR_NO_REASONS_
43
-extern char ** __p__acmdln(void);
44
-#endif
45
-
46
-int glob_add(const char *path, int *argc, char ***argv);
47
-
48
-int _setargv() {
49
-    char *cur = GetCommandLineA(), *begparm = NULL, *endparm = NULL;
50
-    char **argv = NULL, c;
51
-    int argc = 0, in_sq = 0, in_dq = 0, need_glob = 0, allarglen = 0;
52
-    int *g_argc = __p___argc();
53
-    char ***g_argv = __p___argv();
54
-
55
-    _setmode(_fileno(stdin), _O_BINARY);
56
-    do {
57
-	c = *cur;
58
-	switch(c) {
59
-	    case '\0':
60
-		endparm = cur;
61
-		break;
62
-	    case ' ':
63
-		if(begparm && !(in_sq | in_dq))
64
-		    endparm = cur;
65
-		break;
66
-	    case '\'':
67
-		if(!in_dq) {
68
-		    in_sq = !in_sq;
69
-		    if(!in_sq)
70
-			endparm = cur;
71
-		}
72
-		break;
73
-	    case '"':
74
-		if(!in_sq) {
75
-		    in_dq = !in_dq;
76
-		    if(!in_dq)
77
-			endparm = cur;
78
-		}
79
-		break;
80
-	    case '*':
81
-	    case '?':
82
-		if(!in_sq)
83
-		    need_glob = 1;
84
-	    default:
85
-		if(!begparm) {
86
-		    begparm = cur;
87
-		    endparm = NULL;
88
-		}
89
-	}
90
-	if (begparm && endparm) {
91
-	    if(begparm < endparm) {
92
-		char *path = malloc(endparm - begparm + 1), *quotes;
93
-		int arglen = 0;
94
-
95
-		memcpy(path, begparm, endparm - begparm);
96
-		path[endparm - begparm] = '\0';
97
-		quotes = path;
98
-		while((quotes = strchr(quotes, '"')))
99
-		    memmove(quotes, quotes + 1, (endparm - begparm) - (quotes - path));
100
-		if(argc && need_glob) {
101
-		    arglen = glob_add(path, &argc, &argv);
102
-		    if(!arglen) {
103
-			path = malloc(endparm - begparm + 1);
104
-			memcpy(path, begparm, endparm - begparm);
105
-			path[endparm - begparm] = '\0';
106
-		    }
107
-		}
108
-		if(!arglen) {
109
-		    argv = realloc(argv, sizeof(*argv) * (argc + 1));
110
-		    argv[argc] = path;
111
-		    argc++;
112
-		    arglen = endparm - begparm;
113
-		}
114
-		allarglen += arglen;
115
-	    }
116
-	    need_glob = 0;
117
-	    in_sq = 0;
118
-	    in_dq = 0;
119
-	    begparm = NULL;
120
-	    endparm = NULL;
121
-	}
122
-	cur++;
123
-    } while (c);
124
-
125
-    if(argc) {
126
-	int i, argvlen = sizeof(*argv) * (argc + 1), argclen = 0;
127
-	argv = realloc(argv, argvlen + allarglen + argc);
128
-	argv[argc] = NULL;
129
-	for(i=0; i<argc; i++) {
130
-	    int curlen = strlen(argv[i]) + 1;
131
-	    char *curarg = (char *)argv + argvlen + argclen;
132
-	    memcpy(curarg, argv[i], curlen);
133
-	    argclen += curlen;
134
-	    free(argv[i]);
135
-	    argv[i] = curarg;
136
-	}
137
-#ifdef _MY_CRT_INSISTS_ON_PARSING_THE_COMMAND_LINE_TWICE_FOR_NO_REASONS_
138
-        {
139
-	    char *fake_cmdl = malloc(argclen + 1 + 2*argc);
140
-	    char *curarg = fake_cmdl;
141
-	    char **g_cmdl = __p__acmdln();
142
-	    for(i=0; i<argc; i++)
143
-		curarg += sprintf(curarg, "\"%s\" ", argv[i]);
144
-	    curarg--;
145
-	    *curarg = '\0';
146
-	    *g_cmdl = fake_cmdl;
147
-	}
148
-#endif
149
-	*g_argc = argc;
150
-	*g_argv = argv;
151
-    }
152
-    return 0;
153
-}
154
-
155
-int glob_add(const char *path, int *argc, char ***argv) {
156
-    char *tail = strchr(path, '*'), *tailqmark;
157
-    char *dup1, *dup2, *dir, *base, *taildirsep, *tailwldsep;
158
-    struct dirent *de;
159
-    int baselen, taillen, dirlen, mergedir = 0, outlen = 0;
160
-    int qmarklen = 0;
161
-    DIR *d;
162
-
163
-    if(strlen(path) > 4 && !memcmp(path, "\\\\?\\", 4))
164
-	tailqmark = strchr(&path[4], '?');
165
-    else
166
-	tailqmark = strchr(path, '?');
167
-
168
-    if(tailqmark && (!tail || tailqmark < tail))
169
-	tail = tailqmark;
170
-
171
-    if(!tail) {
172
-	*argv = realloc(*argv, sizeof(**argv) * (*argc + 1));
173
-	(*argv)[*argc] = path;
174
-	(*argc)++;
175
-	return strlen(path);
176
-    }
177
-
178
-    if(tail!=path && tail[-1] == '\\') {
179
-	tail[-1] = '\0';
180
-	mergedir = 1;
181
-    }
182
-    while(*tail) {
183
-	if(*tail == '?') {
184
-	    if(tail == tailqmark || qmarklen) 
185
-		qmarklen++;
186
-	    *tail = 0;
187
-	} else if(*tail == '*') {
188
-	    *tail = '\0';
189
-	    qmarklen = 0;
190
-	} else 
191
-	    break;
192
-	tail++;
193
-    }
194
-    taillen = strlen(tail);
195
-    taildirsep = strchr(tail, '\\');
196
-    if(taildirsep && taildirsep - tail == taillen - 1) {
197
-	*taildirsep = '\0';
198
-	taildirsep = NULL;
199
-	taillen--;
200
-    }
201
-    if(!taildirsep)
202
-	taildirsep = tail + taillen;
203
-
204
-    tailwldsep = strchr(tail, '*');
205
-    tailqmark = strchr(tail, '?');
206
-    if(tailqmark && (!tailwldsep || tailqmark < tailwldsep))
207
-	tailwldsep = tailqmark;
208
-    if(!tailwldsep)
209
-	tailwldsep = tail + taillen;
210
-
211
-    dup1 = strdup(path);
212
-    dup2 = strdup(path);
213
-
214
-    if(!mergedir) {
215
-	dir = dirname(dup1);
216
-	base = basename(dup2);
217
-    } else {
218
-	dir = dup1;
219
-	base = dup2;
220
-	*dup2 = '\0';
221
-    }
222
-
223
-    dirlen = strlen(dir);
224
-    baselen = strlen(base);
225
-
226
-    d = opendir(dir);
227
-    while(d && (de = readdir(d))) {
228
-	int namelen = strlen(de->d_name);
229
-	char *newpath;
230
-
231
-	if(!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue;
232
-	if(namelen < baselen) continue;
233
-	if(strncasecmp(base, de->d_name, baselen)) continue;
234
-	if(de->d_type == DT_DIR && taildirsep < tailwldsep) {
235
-	    int d_taillen = taildirsep - tail;
236
-	    if(namelen < baselen + d_taillen) continue;
237
-	    if(strncasecmp(tail, &de->d_name[namelen - d_taillen], d_taillen)) continue;
238
-	    newpath = malloc(dirlen + namelen + taillen - d_taillen + 3);
239
-	    sprintf(newpath, "%s\\%s\\%s", dir, de->d_name, &tail[d_taillen+1]);
240
-	    outlen += glob_add(newpath, argc, argv);
241
-	} else {
242
-	    int d_taillen = tailwldsep - tail;
243
-	    char *start;
244
-	    if(namelen < baselen + d_taillen) continue;
245
-	    if(qmarklen && baselen + qmarklen + d_taillen != namelen)	continue;
246
-	    if(d_taillen == taillen) {
247
-		start = &de->d_name[namelen - d_taillen];
248
-		namelen = d_taillen;
249
-	    } else {
250
-		start = &de->d_name[baselen];
251
-		namelen -= baselen;
252
-	    }
253
-
254
-	    for(; namelen >= d_taillen; start++, namelen--) {
255
-		if(strncasecmp(start, tail, d_taillen)) continue;
256
-		newpath = malloc(dirlen + (start - de->d_name) +  taillen + 2);
257
-		sprintf(newpath, "%s\\", dir);
258
-		memcpy(&newpath[dirlen + 1], de->d_name, start - de->d_name);
259
-		strcpy(&newpath[dirlen + 1 + start - de->d_name], tail);
260
-		outlen += glob_add(newpath, argc, argv);
261
-	    }
262
-	}
263
-    }
264
-    if(d) closedir(d);
265
-    free(dup1);
266
-    free(dup2);
267
-    free(path);
268
-    return outlen;
269
-}
... ...
@@ -132,61 +132,64 @@ EXPORTS sha256_final @44274 NONAME
132 132
 EXPORTS optget @44275 NONAME
133 133
 EXPORTS optparse @44276 NONAME
134 134
 EXPORTS optfree @44277 NONAME
135
-EXPORTS clam_options @44278 NONAME DATA
135
+EXPORTS w32_glob @44278 NONAME
136
+EXPORTS dirname @44279 NONAME
137
+EXPORTS basename @44280 NONAME
138
+EXPORTS clam_options @44281 NONAME DATA
136 139
 
137 140
 ; zlib
138
-EXPORTS gzopen @44279 NONAME
139
-EXPORTS gzgets @44280 NONAME
140
-EXPORTS gzdopen @44281 NONAME
141
-EXPORTS gzclose @44282 NONAME
142
-EXPORTS gzwrite @44283 NONAME
141
+EXPORTS gzopen @44282 NONAME
142
+EXPORTS gzgets @44283 NONAME
143
+EXPORTS gzdopen @44284 NONAME
144
+EXPORTS gzclose @44285 NONAME
145
+EXPORTS gzwrite @44286 NONAME
143 146
 
144 147
 ; pthreads
145
-EXPORTS pthread_mutex_lock @44284 NONAME
146
-EXPORTS pthread_mutex_unlock @44285 NONAME
147
-EXPORTS pthread_mutex_destroy @44286 NONAME
148
-EXPORTS pthread_once @44287 NONAME
149
-EXPORTS pthread_getspecific @44288 NONAME
150
-EXPORTS pthread_setspecific @44289 NONAME
151
-EXPORTS pthread_create @44290 NONAME
152
-EXPORTS pthread_cond_timedwait @44291 NONAME
153
-EXPORTS pthread_cond_init @44292 NONAME
154
-EXPORTS pthread_cond_broadcast @44293 NONAME
155
-EXPORTS pthread_cond_signal @44294 NONAME
156
-EXPORTS pthread_cond_destroy @44295 NONAME
157
-EXPORTS pthread_join @44296 NONAME
158
-EXPORTS pthread_key_create @44297 NONAME
159
-EXPORTS pthread_cond_wait @44298 NONAME
160
-EXPORTS pthread_attr_init @44299 NONAME
161
-EXPORTS pthread_attr_setdetachstate @44300 NONAME
162
-EXPORTS pthread_attr_destroy @44301 NONAME
163
-EXPORTS pthread_mutex_init @44302 NONAME
148
+EXPORTS pthread_mutex_lock @44287 NONAME
149
+EXPORTS pthread_mutex_unlock @44288 NONAME
150
+EXPORTS pthread_mutex_destroy @44289 NONAME
151
+EXPORTS pthread_once @44290 NONAME
152
+EXPORTS pthread_getspecific @44291 NONAME
153
+EXPORTS pthread_setspecific @44292 NONAME
154
+EXPORTS pthread_create @44293 NONAME
155
+EXPORTS pthread_cond_timedwait @44294 NONAME
156
+EXPORTS pthread_cond_init @44295 NONAME
157
+EXPORTS pthread_cond_broadcast @44296 NONAME
158
+EXPORTS pthread_cond_signal @44297 NONAME
159
+EXPORTS pthread_cond_destroy @44298 NONAME
160
+EXPORTS pthread_join @44299 NONAME
161
+EXPORTS pthread_key_create @44300 NONAME
162
+EXPORTS pthread_cond_wait @44301 NONAME
163
+EXPORTS pthread_attr_init @44302 NONAME
164
+EXPORTS pthread_attr_setdetachstate @44303 NONAME
165
+EXPORTS pthread_attr_destroy @44304 NONAME
166
+EXPORTS pthread_mutex_init @44305 NONAME
164 167
 
165 168
 ; winsock bridge and compatibility functions
166
-EXPORTS htonl @44303 NONAME
167
-EXPORTS htons @44304 NONAME
168
-EXPORTS ntohl @44305 NONAME
169
-EXPORTS ntohs @44306 NONAME
170
-EXPORTS __WSAFDIsSet @44307 NONAME
171
-EXPORTS w32_socket @44308 NONAME
172
-EXPORTS w32_getsockopt @44309 NONAME
173
-EXPORTS w32_setsockopt @44310 NONAME
174
-EXPORTS w32_bind @44311 NONAME
175
-EXPORTS w32_listen @44312 NONAME
176
-EXPORTS w32_accept @44313 NONAME
177
-EXPORTS w32_connect @44314 NONAME
178
-EXPORTS w32_shutdown @44315 NONAME
179
-EXPORTS w32_send @44316 NONAME
180
-EXPORTS w32_recv @44317 NONAME
181
-EXPORTS w32_closesocket @44318 NONAME
182
-EXPORTS w32_getservbyname @44319 NONAME
183
-EXPORTS w32_getaddrinfo @44320 NONAME
184
-EXPORTS w32_freeaddrinfo @44321 NONAME
185
-EXPORTS w32_inet_ntop @44322 NONAME
186
-EXPORTS w32_gethostbyname @44323 NONAME
187
-EXPORTS w32_select @44324 NONAME
188
-EXPORTS poll_with_event @44325 NONAME
189
-EXPORTS w32_stat @44326 NONAME
190
-EXPORTS w32_strerror @44327 NONAME
191
-EXPORTS w32_strerror_r @44328 NONAME
192
-EXPORTS inet_addr @44329 NONAME
169
+EXPORTS htonl @44306 NONAME
170
+EXPORTS htons @44307 NONAME
171
+EXPORTS ntohl @44308 NONAME
172
+EXPORTS ntohs @44309 NONAME
173
+EXPORTS __WSAFDIsSet @44310 NONAME
174
+EXPORTS w32_socket @44311 NONAME
175
+EXPORTS w32_getsockopt @44312 NONAME
176
+EXPORTS w32_setsockopt @44313 NONAME
177
+EXPORTS w32_bind @44314 NONAME
178
+EXPORTS w32_listen @44315 NONAME
179
+EXPORTS w32_accept @44316 NONAME
180
+EXPORTS w32_connect @44317 NONAME
181
+EXPORTS w32_shutdown @44318 NONAME
182
+EXPORTS w32_send @44319 NONAME
183
+EXPORTS w32_recv @44320 NONAME
184
+EXPORTS w32_closesocket @44321 NONAME
185
+EXPORTS w32_getservbyname @44322 NONAME
186
+EXPORTS w32_getaddrinfo @44323 NONAME
187
+EXPORTS w32_freeaddrinfo @44324 NONAME
188
+EXPORTS w32_inet_ntop @44325 NONAME
189
+EXPORTS w32_gethostbyname @44326 NONAME
190
+EXPORTS w32_select @44327 NONAME
191
+EXPORTS poll_with_event @44328 NONAME
192
+EXPORTS w32_stat @44329 NONAME
193
+EXPORTS w32_strerror @44330 NONAME
194
+EXPORTS w32_strerror_r @44331 NONAME
195
+EXPORTS inet_addr @44332 NONAME
... ...
@@ -6,7 +6,7 @@
6 6
 	ProjectType="Visual C++"
7 7
 	RootNamespace="libclamav"
8 8
 	TargetFrameworkVersion="196613"
9
-	Version="9.00"
9
+	Version="9,00"
10 10
 	>
11 11
 	<Platforms>
12 12
 		<Platform
... ...
@@ -185,14 +185,6 @@
185 185
 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
186 186
 			>
187 187
 			<File
188
-				RelativePath="..\libclamav\filtering.c"
189
-				>
190
-			</File>
191
-			<File
192
-				RelativePath="..\libclamav\perflogging.c"
193
-				>
194
-			</File>
195
-			<File
196 188
 				RelativePath="..\libclamav\7z.c"
197 189
 				>
198 190
 			</File>
... ...
@@ -285,6 +277,10 @@
285 285
 				>
286 286
 			</File>
287 287
 			<File
288
+				RelativePath="..\libclamav\filtering.c"
289
+				>
290
+			</File>
291
+			<File
288 292
 				RelativePath="..\libclamav\fmap.c"
289 293
 				>
290 294
 			</File>
... ...
@@ -393,6 +389,10 @@
393 393
 				>
394 394
 			</File>
395 395
 			<File
396
+				RelativePath="..\libclamav\perflogging.c"
397
+				>
398
+			</File>
399
+			<File
396 400
 				RelativePath="..\libclamav\petite.c"
397 401
 				>
398 402
 			</File>
... ...
@@ -792,6 +792,10 @@
792 792
 					>
793 793
 				</File>
794 794
 				<File
795
+					RelativePath=".\compat\glob.c"
796
+					>
797
+				</File>
798
+				<File
795 799
 					RelativePath=".\compat\libclamav_main.c"
796 800
 					>
797 801
 				</File>
... ...
@@ -6,6 +6,7 @@
6 6
 #include <stdio.h>
7 7
 #include <stdlib.h>
8 8
 #include <io.h>
9
+#include <fcntl.h>
9 10
 #include <direct.h>
10 11
 #include <Ws2tcpip.h>
11 12
 #include <process.h>
... ...
@@ -73,6 +74,8 @@ typedef	unsigned	int	in_addr_t;
73 73
 
74 74
 #define PATHSEP "\\"
75 75
 
76
+void w32_glob(int *argc_ptr, char ***argv_ptr);
77
+
76 78
 #undef DATADIR
77 79
 #undef CONFDIR
78 80
 #if !defined(THIS_IS_LIBCLAMAV) && defined(_MSC_VER)
... ...
@@ -91,5 +94,8 @@ LIBCLAMAV_EXPORT extern const char *CONFDIR_MILTER;
91 91
 #undef OUT
92 92
 #endif
93 93
 
94
+int real_main(int, char**);
95
+#define main main(int argc, char **argv) { _setmode(_fileno(stdin), _O_BINARY); w32_glob(&argc, &argv); return real_main(argc, argv); }; int real_main
96
+
94 97
 #endif /* __PLATFORM_H */
95 98
 
... ...
@@ -215,13 +215,13 @@ my @PROJECTS = (
215 215
     {makefile => 'libclamav/c++', sections => ['libclamavcxx'], output => 'win32/libclamavcxx.vcproj'},
216 216
 
217 217
     # CLAMSCAN #
218
-    {makefile => 'clamscan', sections => ['clamscan'], output => 'win32/clamscan.vcproj', makefile_only => '(optparser\\.c|getopt\\.c)$', vcproj_only => 'compat\\\\'},
218
+    {makefile => 'clamscan', sections => ['clamscan'], output => 'win32/clamscan.vcproj', makefile_only => '(optparser\\.c|getopt\\.c)$'},
219 219
 
220 220
     # CLAMDSCAN #
221
-    {makefile => 'clamdscan', sections => ['clamdscan'], output => 'win32/clamdscan.vcproj', makefile_only => '(optparser\\.c|getopt\\.c)$', vcproj_only => 'compat\\\\'},
221
+    {makefile => 'clamdscan', sections => ['clamdscan'], output => 'win32/clamdscan.vcproj', makefile_only => '(optparser\\.c|getopt\\.c)$'},
222 222
 
223 223
     # CLAMD #
224
-    {makefile => 'clamd', sections => ['clamd'], output => 'win32/clamd.vcproj', makefile_only => '(optparser\\.c|getopt\\.c|(daz|clam)uko.*)$', vcproj_only => 'compat\\\\'},
224
+    {makefile => 'clamd', sections => ['clamd'], output => 'win32/clamd.vcproj', makefile_only => '(optparser\\.c|getopt\\.c|(daz|clam)uko.*)$'},
225 225
 
226 226
     # FRESHCLAM #
227 227
     {makefile => 'freshclam', sections => ['freshclam'], output => 'win32/freshclam.vcproj', makefile_only => '(optparser\\.c|getopt\\.c)$', vcproj_only => 'compat\\\\'},