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