xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/roken/fnmatch.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
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