1*d3273b5bSchristos /* $NetBSD: fnmatch.c,v 1.2 2017/01/28 21:31:50 christos Exp $ */
2ca1c9b0cSelric
3ca1c9b0cSelric /* NetBSD: fnmatch.c,v 1.11 1995/02/27 03:43:06 cgd Exp */
4ca1c9b0cSelric
5ca1c9b0cSelric /*
6ca1c9b0cSelric * Copyright (c) 1989, 1993, 1994
7ca1c9b0cSelric * The Regents of the University of California. All rights reserved.
8ca1c9b0cSelric *
9ca1c9b0cSelric * This code is derived from software contributed to Berkeley by
10ca1c9b0cSelric * Guido van Rossum.
11ca1c9b0cSelric *
12ca1c9b0cSelric * Redistribution and use in source and binary forms, with or without
13ca1c9b0cSelric * modification, are permitted provided that the following conditions
14ca1c9b0cSelric * are met:
15ca1c9b0cSelric * 1. Redistributions of source code must retain the above copyright
16ca1c9b0cSelric * notice, this list of conditions and the following disclaimer.
17ca1c9b0cSelric * 2. Redistributions in binary form must reproduce the above copyright
18ca1c9b0cSelric * notice, this list of conditions and the following disclaimer in the
19ca1c9b0cSelric * documentation and/or other materials provided with the distribution.
20ca1c9b0cSelric * 3. Neither the name of the University nor the names of its contributors
21ca1c9b0cSelric * may be used to endorse or promote products derived from this software
22ca1c9b0cSelric * without specific prior written permission.
23ca1c9b0cSelric *
24ca1c9b0cSelric * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25ca1c9b0cSelric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26ca1c9b0cSelric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27ca1c9b0cSelric * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28ca1c9b0cSelric * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29ca1c9b0cSelric * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30ca1c9b0cSelric * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31ca1c9b0cSelric * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32ca1c9b0cSelric * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33ca1c9b0cSelric * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34ca1c9b0cSelric * SUCH DAMAGE.
35ca1c9b0cSelric */
36ca1c9b0cSelric
37ca1c9b0cSelric #if defined(LIBC_SCCS) && !defined(lint)
38ca1c9b0cSelric #if 0
39ca1c9b0cSelric static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
40ca1c9b0cSelric #else
41ca1c9b0cSelric static char rcsid[] = "NetBSD: fnmatch.c,v 1.11 1995/02/27 03:43:06 cgd Exp";
42ca1c9b0cSelric #endif
43ca1c9b0cSelric #endif /* LIBC_SCCS and not lint */
44ca1c9b0cSelric
45ca1c9b0cSelric /*
46ca1c9b0cSelric * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
47ca1c9b0cSelric * Compares a filename or pathname to a pattern.
48ca1c9b0cSelric */
49ca1c9b0cSelric
50ca1c9b0cSelric #ifdef HAVE_CONFIG_H
51ca1c9b0cSelric #include <config.h>
52ca1c9b0cSelric #endif
53ca1c9b0cSelric
54ca1c9b0cSelric #include <krb5/roken.h>
55ca1c9b0cSelric
56ca1c9b0cSelric #include <fnmatch.h>
57ca1c9b0cSelric #include <string.h>
58ca1c9b0cSelric
59ca1c9b0cSelric #define EOS '\0'
60ca1c9b0cSelric
61ca1c9b0cSelric static const char *rangematch (const char *, int, int);
62ca1c9b0cSelric
63ca1c9b0cSelric ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_fnmatch(const char * pattern,const char * string,int flags)64ca1c9b0cSelric rk_fnmatch(const char *pattern, const char *string, int flags)
65ca1c9b0cSelric {
66ca1c9b0cSelric const char *stringstart;
67ca1c9b0cSelric char c, test;
68ca1c9b0cSelric
69ca1c9b0cSelric for (stringstart = string;;)
70ca1c9b0cSelric switch (c = *pattern++) {
71ca1c9b0cSelric case EOS:
72ca1c9b0cSelric return (*string == EOS ? 0 : FNM_NOMATCH);
73ca1c9b0cSelric case '?':
74ca1c9b0cSelric if (*string == EOS)
75ca1c9b0cSelric return (FNM_NOMATCH);
76ca1c9b0cSelric if (*string == '/' && (flags & FNM_PATHNAME))
77ca1c9b0cSelric return (FNM_NOMATCH);
78ca1c9b0cSelric if (*string == '.' && (flags & FNM_PERIOD) &&
79ca1c9b0cSelric (string == stringstart ||
80ca1c9b0cSelric ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
81ca1c9b0cSelric return (FNM_NOMATCH);
82ca1c9b0cSelric ++string;
83ca1c9b0cSelric break;
84ca1c9b0cSelric case '*':
85ca1c9b0cSelric c = *pattern;
86ca1c9b0cSelric /* Collapse multiple stars. */
87ca1c9b0cSelric while (c == '*')
88ca1c9b0cSelric c = *++pattern;
89ca1c9b0cSelric
90ca1c9b0cSelric if (*string == '.' && (flags & FNM_PERIOD) &&
91ca1c9b0cSelric (string == stringstart ||
92ca1c9b0cSelric ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
93ca1c9b0cSelric return (FNM_NOMATCH);
94ca1c9b0cSelric
95ca1c9b0cSelric /* Optimize for pattern with * at end or before /. */
96ca1c9b0cSelric if (c == EOS)
97ca1c9b0cSelric if (flags & FNM_PATHNAME)
98ca1c9b0cSelric return (strchr(string, '/') == NULL ?
99ca1c9b0cSelric 0 : FNM_NOMATCH);
100ca1c9b0cSelric else
101ca1c9b0cSelric return (0);
102ca1c9b0cSelric else if (c == '/' && flags & FNM_PATHNAME) {
103ca1c9b0cSelric if ((string = strchr(string, '/')) == NULL)
104ca1c9b0cSelric return (FNM_NOMATCH);
105ca1c9b0cSelric break;
106ca1c9b0cSelric }
107ca1c9b0cSelric
108ca1c9b0cSelric /* General case, use recursion. */
109ca1c9b0cSelric while ((test = *string) != EOS) {
110ca1c9b0cSelric if (!rk_fnmatch(pattern, string, flags & ~FNM_PERIOD))
111ca1c9b0cSelric return (0);
112ca1c9b0cSelric if (test == '/' && flags & FNM_PATHNAME)
113ca1c9b0cSelric break;
114ca1c9b0cSelric ++string;
115ca1c9b0cSelric }
116ca1c9b0cSelric return (FNM_NOMATCH);
117ca1c9b0cSelric case '[':
118ca1c9b0cSelric if (*string == EOS)
119ca1c9b0cSelric return (FNM_NOMATCH);
120ca1c9b0cSelric if (*string == '/' && flags & FNM_PATHNAME)
121ca1c9b0cSelric return (FNM_NOMATCH);
122ca1c9b0cSelric if ((pattern =
123ca1c9b0cSelric rangematch(pattern, *string, flags)) == NULL)
124ca1c9b0cSelric return (FNM_NOMATCH);
125ca1c9b0cSelric ++string;
126ca1c9b0cSelric break;
127ca1c9b0cSelric case '\\':
128ca1c9b0cSelric if (!(flags & FNM_NOESCAPE)) {
129ca1c9b0cSelric if ((c = *pattern++) == EOS) {
130ca1c9b0cSelric c = '\\';
131ca1c9b0cSelric --pattern;
132ca1c9b0cSelric }
133ca1c9b0cSelric }
134ca1c9b0cSelric /* FALLTHROUGH */
135ca1c9b0cSelric default:
136ca1c9b0cSelric if (c != *string++)
137ca1c9b0cSelric return (FNM_NOMATCH);
138ca1c9b0cSelric break;
139ca1c9b0cSelric }
140ca1c9b0cSelric /* NOTREACHED */
141ca1c9b0cSelric }
142ca1c9b0cSelric
143ca1c9b0cSelric static const char *
rangematch(const char * pattern,int test,int flags)144ca1c9b0cSelric rangematch(const char *pattern, int test, int flags)
145ca1c9b0cSelric {
146ca1c9b0cSelric int negate, ok;
147ca1c9b0cSelric char c, c2;
148ca1c9b0cSelric
149ca1c9b0cSelric /*
150ca1c9b0cSelric * A bracket expression starting with an unquoted circumflex
151ca1c9b0cSelric * character produces unspecified results (IEEE 1003.2-1992,
152ca1c9b0cSelric * 3.13.2). This implementation treats it like '!', for
153ca1c9b0cSelric * consistency with the regular expression syntax.
154ca1c9b0cSelric * J.T. Conklin (conklin@ngai.kaleida.com)
155ca1c9b0cSelric */
156ca1c9b0cSelric if (negate = (*pattern == '!' || *pattern == '^'))
157ca1c9b0cSelric ++pattern;
158ca1c9b0cSelric
159ca1c9b0cSelric for (ok = 0; (c = *pattern++) != ']';) {
160ca1c9b0cSelric if (c == '\\' && !(flags & FNM_NOESCAPE))
161ca1c9b0cSelric c = *pattern++;
162ca1c9b0cSelric if (c == EOS)
163ca1c9b0cSelric return (NULL);
164ca1c9b0cSelric if (*pattern == '-'
165ca1c9b0cSelric && (c2 = *(pattern+1)) != EOS && c2 != ']') {
166ca1c9b0cSelric pattern += 2;
167ca1c9b0cSelric if (c2 == '\\' && !(flags & FNM_NOESCAPE))
168ca1c9b0cSelric c2 = *pattern++;
169ca1c9b0cSelric if (c2 == EOS)
170ca1c9b0cSelric return (NULL);
171ca1c9b0cSelric if (c <= test && test <= c2)
172ca1c9b0cSelric ok = 1;
173ca1c9b0cSelric } else if (c == test)
174ca1c9b0cSelric ok = 1;
175ca1c9b0cSelric }
176ca1c9b0cSelric return (ok == negate ? NULL : pattern);
177ca1c9b0cSelric }
178