Commit | Line | Data |
---|---|---|
c627d613 AT |
1 | #include "../rsync.h" |
2 | #ifndef HAVE_FNMATCH | |
3 | ||
9dce9b45 DD |
4 | /* ----- THE FOLLOWING UP TO 'END' is glibc-2.1.2 posix/fnmatch.c |
5 | except for the part with the '#if 0' */ | |
c627d613 | 6 | |
9dce9b45 DD |
7 | /* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc. |
8 | This file is part of the GNU C Library. | |
c627d613 | 9 | |
9dce9b45 DD |
10 | This library is free software; you can redistribute it and/or |
11 | modify it under the terms of the GNU Library General Public License as | |
12 | published by the Free Software Foundation; either version 2 of the | |
13 | License, or (at your option) any later version. | |
c627d613 | 14 | |
9dce9b45 DD |
15 | This library is distributed in the hope that it will be useful, |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 | Library General Public License for more details. | |
c627d613 | 19 | |
9dce9b45 DD |
20 | You should have received a copy of the GNU Library General Public |
21 | License along with this library; see the file COPYING.LIB. If not, | |
22 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
23 | Boston, MA 02111-1307, USA. */ | |
c627d613 | 24 | |
9dce9b45 DD |
25 | #if HAVE_CONFIG_H |
26 | # include <config.h> | |
27 | #endif | |
28 | ||
29 | /* Enable GNU extensions in fnmatch.h. */ | |
30 | #ifndef _GNU_SOURCE | |
31 | # define _GNU_SOURCE 1 | |
32 | #endif | |
33 | ||
34 | #include <errno.h> | |
35 | #include <fnmatch.h> | |
36 | #include <ctype.h> | |
37 | ||
38 | #if HAVE_STRING_H || defined _LIBC | |
39 | # include <string.h> | |
c627d613 | 40 | #else |
9dce9b45 | 41 | # include <strings.h> |
c627d613 AT |
42 | #endif |
43 | ||
9dce9b45 DD |
44 | #if defined STDC_HEADERS || defined _LIBC |
45 | # include <stdlib.h> | |
46 | #endif | |
c627d613 | 47 | |
9dce9b45 DD |
48 | /* For platform which support the ISO C amendement 1 functionality we |
49 | support user defined character classes. */ | |
50 | #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) | |
51 | /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */ | |
52 | # include <wchar.h> | |
53 | # include <wctype.h> | |
54 | #endif | |
c627d613 AT |
55 | |
56 | /* Comment out all this code if we are using the GNU C Library, and are not | |
57 | actually compiling the library itself. This code is part of the GNU C | |
58 | Library, but also included in many other GNU distributions. Compiling | |
59 | and linking in this code is a waste when using the GNU C library | |
60 | (especially if it is a shared library). Rather than having every GNU | |
61 | program understand `configure --with-gnu-libc' and omit the object files, | |
62 | it is simpler to just do this in the source for each such file. */ | |
63 | ||
9dce9b45 DD |
64 | #if defined _LIBC || !defined __GNU_LIBRARY__ |
65 | ||
66 | ||
67 | # if defined STDC_HEADERS || !defined isascii | |
68 | # define ISASCII(c) 1 | |
69 | # else | |
70 | # define ISASCII(c) isascii(c) | |
71 | # endif | |
72 | ||
73 | #ifdef isblank | |
74 | # define ISBLANK(c) (ISASCII (c) && isblank (c)) | |
75 | #else | |
76 | # define ISBLANK(c) ((c) == ' ' || (c) == '\t') | |
c627d613 | 77 | #endif |
9dce9b45 DD |
78 | #ifdef isgraph |
79 | # define ISGRAPH(c) (ISASCII (c) && isgraph (c)) | |
80 | #else | |
81 | # define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) | |
82 | #endif | |
83 | ||
84 | #define ISPRINT(c) (ISASCII (c) && isprint (c)) | |
85 | #define ISDIGIT(c) (ISASCII (c) && isdigit (c)) | |
86 | #define ISALNUM(c) (ISASCII (c) && isalnum (c)) | |
87 | #define ISALPHA(c) (ISASCII (c) && isalpha (c)) | |
88 | #define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) | |
89 | #define ISLOWER(c) (ISASCII (c) && islower (c)) | |
90 | #define ISPUNCT(c) (ISASCII (c) && ispunct (c)) | |
91 | #define ISSPACE(c) (ISASCII (c) && isspace (c)) | |
92 | #define ISUPPER(c) (ISASCII (c) && isupper (c)) | |
93 | #define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) | |
94 | ||
95 | # define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) | |
96 | ||
97 | # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) | |
98 | /* The GNU C library provides support for user-defined character classes | |
99 | and the functions from ISO C amendement 1. */ | |
100 | # ifdef CHARCLASS_NAME_MAX | |
101 | # define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX | |
102 | # else | |
103 | /* This shouldn't happen but some implementation might still have this | |
104 | problem. Use a reasonable default value. */ | |
105 | # define CHAR_CLASS_MAX_LENGTH 256 | |
106 | # endif | |
107 | ||
108 | # ifdef _LIBC | |
109 | # define IS_CHAR_CLASS(string) __wctype (string) | |
110 | # else | |
111 | # define IS_CHAR_CLASS(string) wctype (string) | |
112 | # endif | |
113 | # else | |
114 | # define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ | |
115 | ||
116 | # define IS_CHAR_CLASS(string) \ | |
117 | (STREQ (string, "alpha") || STREQ (string, "upper") \ | |
118 | || STREQ (string, "lower") || STREQ (string, "digit") \ | |
119 | || STREQ (string, "alnum") || STREQ (string, "xdigit") \ | |
120 | || STREQ (string, "space") || STREQ (string, "print") \ | |
121 | || STREQ (string, "punct") || STREQ (string, "graph") \ | |
122 | || STREQ (string, "cntrl") || STREQ (string, "blank")) | |
123 | # endif | |
124 | ||
125 | /* Avoid depending on library functions or files | |
126 | whose names are inconsistent. */ | |
127 | ||
128 | # if !defined _LIBC && !defined getenv | |
129 | extern char *getenv (); | |
130 | # endif | |
131 | ||
132 | # ifndef errno | |
133 | extern int errno; | |
134 | # endif | |
c627d613 AT |
135 | |
136 | /* Match STRING against the filename pattern PATTERN, returning zero if | |
137 | it matches, nonzero if not. */ | |
9dce9b45 DD |
138 | static int |
139 | #ifdef _LIBC | |
140 | internal_function | |
141 | #endif | |
142 | internal_fnmatch (const char *pattern, const char *string, | |
143 | int no_leading_period, int flags) | |
c627d613 AT |
144 | { |
145 | register const char *p = pattern, *n = string; | |
9dce9b45 | 146 | register unsigned char c; |
c627d613 | 147 | |
9dce9b45 DD |
148 | /* Note that this evaluates C many times. */ |
149 | # ifdef _LIBC | |
150 | # define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) | |
151 | # else | |
152 | # define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) | |
153 | # endif | |
c627d613 AT |
154 | |
155 | while ((c = *p++) != '\0') | |
156 | { | |
157 | c = FOLD (c); | |
158 | ||
159 | switch (c) | |
160 | { | |
161 | case '?': | |
162 | if (*n == '\0') | |
163 | return FNM_NOMATCH; | |
9dce9b45 | 164 | else if (*n == '/' && (flags & FNM_FILE_NAME)) |
c627d613 | 165 | return FNM_NOMATCH; |
9dce9b45 DD |
166 | else if (*n == '.' && no_leading_period |
167 | && (n == string | |
168 | || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) | |
c627d613 AT |
169 | return FNM_NOMATCH; |
170 | break; | |
171 | ||
172 | case '\\': | |
173 | if (!(flags & FNM_NOESCAPE)) | |
174 | { | |
175 | c = *p++; | |
9dce9b45 DD |
176 | if (c == '\0') |
177 | /* Trailing \ loses. */ | |
178 | return FNM_NOMATCH; | |
c627d613 AT |
179 | c = FOLD (c); |
180 | } | |
9dce9b45 | 181 | if (FOLD ((unsigned char) *n) != c) |
c627d613 AT |
182 | return FNM_NOMATCH; |
183 | break; | |
184 | ||
185 | case '*': | |
9dce9b45 DD |
186 | if (*n == '.' && no_leading_period |
187 | && (n == string | |
188 | || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) | |
c627d613 AT |
189 | return FNM_NOMATCH; |
190 | ||
9dce9b45 DD |
191 | for (c = *p++; c == '?' || c == '*'; c = *p++) |
192 | { | |
193 | if (*n == '/' && (flags & FNM_FILE_NAME)) | |
194 | /* A slash does not match a wildcard under FNM_FILE_NAME. */ | |
195 | return FNM_NOMATCH; | |
196 | else if (c == '?') | |
197 | { | |
198 | /* A ? needs to match one character. */ | |
199 | if (*n == '\0') | |
200 | /* There isn't another character; no match. */ | |
201 | return FNM_NOMATCH; | |
202 | else | |
203 | /* One character of the string is consumed in matching | |
204 | this ? wildcard, so *??? won't match if there are | |
205 | less than three characters. */ | |
206 | ++n; | |
207 | } | |
208 | } | |
c627d613 AT |
209 | |
210 | if (c == '\0') | |
9dce9b45 DD |
211 | /* The wildcard(s) is/are the last element of the pattern. |
212 | If the name is a file name and contains another slash | |
213 | this does mean it cannot match. */ | |
214 | return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL | |
215 | ? FNM_NOMATCH : 0); | |
216 | else | |
217 | { | |
218 | const char *endp; | |
c627d613 | 219 | |
9dce9b45 DD |
220 | #if 0 |
221 | endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0'); | |
222 | #else | |
223 | /* replace call to internal glibc function with equivalent */ | |
224 | if (!(flags & FNM_FILE_NAME) || ((endp = strchr(n, '/')) == NULL)) | |
225 | endp = n + strlen(n); | |
226 | #endif | |
227 | ||
228 | if (c == '[') | |
229 | { | |
230 | int flags2 = ((flags & FNM_FILE_NAME) | |
231 | ? flags : (flags & ~FNM_PERIOD)); | |
232 | ||
233 | for (--p; n < endp; ++n) | |
234 | if (internal_fnmatch (p, n, | |
235 | (no_leading_period | |
236 | && (n == string | |
237 | || (n[-1] == '/' | |
238 | && (flags | |
239 | & FNM_FILE_NAME)))), | |
240 | flags2) | |
241 | == 0) | |
242 | return 0; | |
243 | } | |
244 | else if (c == '/' && (flags & FNM_FILE_NAME)) | |
245 | { | |
246 | while (*n != '\0' && *n != '/') | |
247 | ++n; | |
248 | if (*n == '/' | |
249 | && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD, | |
250 | flags) == 0)) | |
251 | return 0; | |
252 | } | |
253 | else | |
254 | { | |
255 | int flags2 = ((flags & FNM_FILE_NAME) | |
256 | ? flags : (flags & ~FNM_PERIOD)); | |
257 | ||
258 | if (c == '\\' && !(flags & FNM_NOESCAPE)) | |
259 | c = *p; | |
260 | c = FOLD (c); | |
261 | for (--p; n < endp; ++n) | |
262 | if (FOLD ((unsigned char) *n) == c | |
263 | && (internal_fnmatch (p, n, | |
264 | (no_leading_period | |
265 | && (n == string | |
266 | || (n[-1] == '/' | |
267 | && (flags | |
268 | & FNM_FILE_NAME)))), | |
269 | flags2) == 0)) | |
270 | return 0; | |
271 | } | |
272 | } | |
273 | ||
274 | /* If we come here no match is possible with the wildcard. */ | |
275 | return FNM_NOMATCH; | |
c627d613 AT |
276 | |
277 | case '[': | |
278 | { | |
279 | /* Nonzero if the sense of the character class is inverted. */ | |
9dce9b45 | 280 | static int posixly_correct; |
c627d613 | 281 | register int not; |
9dce9b45 DD |
282 | char cold; |
283 | ||
284 | if (posixly_correct == 0) | |
285 | posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; | |
c627d613 AT |
286 | |
287 | if (*n == '\0') | |
288 | return FNM_NOMATCH; | |
289 | ||
9dce9b45 DD |
290 | if (*n == '.' && no_leading_period && (n == string |
291 | || (n[-1] == '/' | |
292 | && (flags | |
293 | & FNM_FILE_NAME)))) | |
294 | return FNM_NOMATCH; | |
295 | ||
296 | if (*n == '/' && (flags & FNM_FILE_NAME)) | |
297 | /* `/' cannot be matched. */ | |
c627d613 AT |
298 | return FNM_NOMATCH; |
299 | ||
9dce9b45 | 300 | not = (*p == '!' || (posixly_correct < 0 && *p == '^')); |
c627d613 AT |
301 | if (not) |
302 | ++p; | |
303 | ||
304 | c = *p++; | |
305 | for (;;) | |
306 | { | |
9dce9b45 | 307 | unsigned char fn = FOLD ((unsigned char) *n); |
c627d613 AT |
308 | |
309 | if (!(flags & FNM_NOESCAPE) && c == '\\') | |
9dce9b45 DD |
310 | { |
311 | if (*p == '\0') | |
312 | return FNM_NOMATCH; | |
313 | c = FOLD ((unsigned char) *p); | |
314 | ++p; | |
c627d613 | 315 | |
9dce9b45 DD |
316 | if (c == fn) |
317 | goto matched; | |
318 | } | |
319 | else if (c == '[' && *p == ':') | |
320 | { | |
321 | /* Leave room for the null. */ | |
322 | char str[CHAR_CLASS_MAX_LENGTH + 1]; | |
323 | size_t c1 = 0; | |
324 | # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) | |
325 | wctype_t wt; | |
326 | # endif | |
327 | const char *startp = p; | |
328 | ||
329 | for (;;) | |
330 | { | |
331 | if (c1 == CHAR_CLASS_MAX_LENGTH) | |
332 | /* The name is too long and therefore the pattern | |
333 | is ill-formed. */ | |
334 | return FNM_NOMATCH; | |
335 | ||
336 | c = *++p; | |
337 | if (c == ':' && p[1] == ']') | |
338 | { | |
339 | p += 2; | |
340 | break; | |
341 | } | |
342 | if (c < 'a' || c >= 'z') | |
343 | { | |
344 | /* This cannot possibly be a character class name. | |
345 | Match it as a normal range. */ | |
346 | p = startp; | |
347 | c = '['; | |
348 | goto normal_bracket; | |
349 | } | |
350 | str[c1++] = c; | |
351 | } | |
352 | str[c1] = '\0'; | |
353 | ||
354 | # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) | |
355 | wt = IS_CHAR_CLASS (str); | |
356 | if (wt == 0) | |
357 | /* Invalid character class name. */ | |
358 | return FNM_NOMATCH; | |
c627d613 | 359 | |
9dce9b45 DD |
360 | if (__iswctype (__btowc ((unsigned char) *n), wt)) |
361 | goto matched; | |
362 | # else | |
363 | if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n)) | |
364 | || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n)) | |
365 | || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n)) | |
366 | || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n)) | |
367 | || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n)) | |
368 | || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n)) | |
369 | || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n)) | |
370 | || (STREQ (str, "print") && ISPRINT ((unsigned char) *n)) | |
371 | || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n)) | |
372 | || (STREQ (str, "space") && ISSPACE ((unsigned char) *n)) | |
373 | || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n)) | |
374 | || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n))) | |
375 | goto matched; | |
376 | # endif | |
377 | } | |
378 | else if (c == '\0') | |
c627d613 AT |
379 | /* [ (unterminated) loses. */ |
380 | return FNM_NOMATCH; | |
9dce9b45 DD |
381 | else |
382 | { | |
383 | normal_bracket: | |
384 | if (FOLD (c) == fn) | |
385 | goto matched; | |
c627d613 | 386 | |
9dce9b45 DD |
387 | cold = c; |
388 | c = *p++; | |
c627d613 | 389 | |
9dce9b45 DD |
390 | if (c == '-' && *p != ']') |
391 | { | |
392 | /* It is a range. */ | |
393 | unsigned char cend = *p++; | |
394 | if (!(flags & FNM_NOESCAPE) && cend == '\\') | |
395 | cend = *p++; | |
396 | if (cend == '\0') | |
397 | return FNM_NOMATCH; | |
c627d613 | 398 | |
9dce9b45 DD |
399 | if (cold <= fn && fn <= FOLD (cend)) |
400 | goto matched; | |
c627d613 | 401 | |
9dce9b45 DD |
402 | c = *p++; |
403 | } | |
c627d613 AT |
404 | } |
405 | ||
c627d613 AT |
406 | if (c == ']') |
407 | break; | |
408 | } | |
9dce9b45 | 409 | |
c627d613 AT |
410 | if (!not) |
411 | return FNM_NOMATCH; | |
412 | break; | |
413 | ||
9dce9b45 | 414 | matched: |
c627d613 AT |
415 | /* Skip the rest of the [...] that already matched. */ |
416 | while (c != ']') | |
417 | { | |
418 | if (c == '\0') | |
419 | /* [... (unterminated) loses. */ | |
420 | return FNM_NOMATCH; | |
421 | ||
422 | c = *p++; | |
423 | if (!(flags & FNM_NOESCAPE) && c == '\\') | |
9dce9b45 DD |
424 | { |
425 | if (*p == '\0') | |
426 | return FNM_NOMATCH; | |
427 | /* XXX 1003.2d11 is unclear if this is right. */ | |
428 | ++p; | |
429 | } | |
430 | else if (c == '[' && *p == ':') | |
431 | { | |
432 | do | |
433 | if (*++p == '\0') | |
434 | return FNM_NOMATCH; | |
435 | while (*p != ':' || p[1] == ']'); | |
436 | p += 2; | |
437 | c = *p; | |
438 | } | |
c627d613 AT |
439 | } |
440 | if (not) | |
441 | return FNM_NOMATCH; | |
442 | } | |
443 | break; | |
444 | ||
445 | default: | |
9dce9b45 | 446 | if (c != FOLD ((unsigned char) *n)) |
c627d613 AT |
447 | return FNM_NOMATCH; |
448 | } | |
449 | ||
450 | ++n; | |
451 | } | |
452 | ||
453 | if (*n == '\0') | |
454 | return 0; | |
455 | ||
456 | if ((flags & FNM_LEADING_DIR) && *n == '/') | |
457 | /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ | |
458 | return 0; | |
459 | ||
460 | return FNM_NOMATCH; | |
9dce9b45 DD |
461 | |
462 | # undef FOLD | |
c627d613 AT |
463 | } |
464 | ||
9dce9b45 DD |
465 | |
466 | int | |
467 | fnmatch (pattern, string, flags) | |
468 | const char *pattern; | |
469 | const char *string; | |
470 | int flags; | |
471 | { | |
472 | return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags); | |
473 | } | |
474 | ||
475 | #endif /* _LIBC or not __GNU_LIBRARY__. */ | |
476 | /* ----- END glibc-2.1.2 posix/fnmatch.c */ | |
477 | ||
c627d613 AT |
478 | #else /* HAVE_FNMATCH */ |
479 | void fnmatch_dummy(void) {} | |
480 | #endif |