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