|
|
1.1 cgd 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Guido van Rossum.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #if defined(LIBC_SCCS) && !defined(lint)
38: static char sccsid[] = "@(#)fnmatch.c 5.4 (Berkeley) 2/23/91";
39: #endif /* LIBC_SCCS and not lint */
40:
41: /*
42: * Function fnmatch() as proposed in Posix 1003.2 B.6 (rev. 9).
43: * Compares a filename or pathname to a pattern.
44: */
45:
46: #include <unistd.h>
47: #include <string.h>
48:
49: #define EOS '\0'
50:
51: static char *
52: rangematch(pattern, test)
53: register char *pattern, test;
54: {
55: register char c, c2;
56: int negate, ok;
57:
58: if (negate = (*pattern == '!'))
59: ++pattern;
60:
61: /*
62: * TO DO: quoting
63: */
64:
65: for (ok = 0; (c = *pattern++) != ']';) {
66: if (c == EOS)
67: return(NULL); /* illegal pattern */
68: if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']') {
69: if (c <= test && test <= c2)
70: ok = 1;
71: pattern += 2;
72: }
73: else if (c == test)
74: ok = 1;
75: }
76: return(ok == negate ? NULL : pattern);
77: }
78:
79: fnmatch(pattern, string, flags)
80: register const char *pattern;
81: register const char *string;
82: int flags;
83: {
84: register char c;
85: char test, *rangematch();
86:
87: for (;;)
88: switch (c = *pattern++) {
89: case EOS:
90: return(*string == EOS);
91: case '?':
92: if ((test = *string++) == EOS ||
93: test == '/' && flags & FNM_PATHNAME)
94: return(0);
95: break;
96: case '*':
97: c = *pattern;
98: /* collapse multiple stars */
99: while (c == '*')
100: c = *++pattern;
101:
102: /* optimize for pattern with * at end or before / */
103: if (c == EOS)
104: if (flags & FNM_PATHNAME)
105: return(!index(string, '/'));
106: else
107: return(1);
108: else if (c == '/' && flags & FNM_PATHNAME) {
109: if ((string = index(string, '/')) == NULL)
110: return(0);
111: break;
112: }
113:
114: /* general case, use recursion */
115: while ((test = *string) != EOS) {
116: if (fnmatch(pattern, string, flags))
117: return(1);
118: if (test == '/' && flags & FNM_PATHNAME)
119: break;
120: ++string;
121: }
122: return(0);
123: case '[':
124: if ((test = *string++) == EOS ||
125: test == '/' && flags & FNM_PATHNAME)
126: return(0);
127: if ((pattern = rangematch(pattern, test)) == NULL)
128: return(0);
129: break;
130: case '\\':
131: if (flags & FNM_QUOTE) {
132: if ((c = *pattern++) == EOS) {
133: c = '\\';
134: --pattern;
135: }
136: if (c != *string++)
137: return(0);
138: break;
139: }
140: /* FALLTHROUGH */
141: default:
142: if (c != *string++)
143: return(0);
144: break;
145: }
146: }