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