Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/roken/fnmatch.c
39507 views
1
/* $NetBSD: fnmatch.c,v 1.11 1995/02/27 03:43:06 cgd 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
static char rcsid[] = "$NetBSD: fnmatch.c,v 1.11 1995/02/27 03:43:06 cgd 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
#ifdef HAVE_CONFIG_H
49
#include <config.h>
50
#endif
51
52
#include <roken.h>
53
54
#include <fnmatch.h>
55
#include <string.h>
56
57
#define EOS '\0'
58
59
static const char *rangematch (const char *, int, int);
60
61
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
62
rk_fnmatch(const char *pattern, const char *string, int flags)
63
{
64
const char *stringstart;
65
char c, test;
66
67
for (stringstart = string;;)
68
switch (c = *pattern++) {
69
case EOS:
70
return (*string == EOS ? 0 : FNM_NOMATCH);
71
case '?':
72
if (*string == EOS)
73
return (FNM_NOMATCH);
74
if (*string == '/' && (flags & FNM_PATHNAME))
75
return (FNM_NOMATCH);
76
if (*string == '.' && (flags & FNM_PERIOD) &&
77
(string == stringstart ||
78
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
79
return (FNM_NOMATCH);
80
++string;
81
break;
82
case '*':
83
c = *pattern;
84
/* Collapse multiple stars. */
85
while (c == '*')
86
c = *++pattern;
87
88
if (*string == '.' && (flags & FNM_PERIOD) &&
89
(string == stringstart ||
90
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
91
return (FNM_NOMATCH);
92
93
/* Optimize for pattern with * at end or before /. */
94
if (c == EOS)
95
if (flags & FNM_PATHNAME)
96
return (strchr(string, '/') == NULL ?
97
0 : FNM_NOMATCH);
98
else
99
return (0);
100
else if (c == '/' && flags & FNM_PATHNAME) {
101
if ((string = strchr(string, '/')) == NULL)
102
return (FNM_NOMATCH);
103
break;
104
}
105
106
/* General case, use recursion. */
107
while ((test = *string) != EOS) {
108
if (!rk_fnmatch(pattern, string, flags & ~FNM_PERIOD))
109
return (0);
110
if (test == '/' && flags & FNM_PATHNAME)
111
break;
112
++string;
113
}
114
return (FNM_NOMATCH);
115
case '[':
116
if (*string == EOS)
117
return (FNM_NOMATCH);
118
if (*string == '/' && flags & FNM_PATHNAME)
119
return (FNM_NOMATCH);
120
if ((pattern =
121
rangematch(pattern, *string, flags)) == NULL)
122
return (FNM_NOMATCH);
123
++string;
124
break;
125
case '\\':
126
if (!(flags & FNM_NOESCAPE)) {
127
if ((c = *pattern++) == EOS) {
128
c = '\\';
129
--pattern;
130
}
131
}
132
/* FALLTHROUGH */
133
default:
134
if (c != *string++)
135
return (FNM_NOMATCH);
136
break;
137
}
138
/* NOTREACHED */
139
}
140
141
static const char *
142
rangematch(const char *pattern, int test, int flags)
143
{
144
int negate, ok;
145
char c, c2;
146
147
/*
148
* A bracket expression starting with an unquoted circumflex
149
* character produces unspecified results (IEEE 1003.2-1992,
150
* 3.13.2). This implementation treats it like '!', for
151
* consistency with the regular expression syntax.
152
* J.T. Conklin ([email protected])
153
*/
154
if (negate = (*pattern == '!' || *pattern == '^'))
155
++pattern;
156
157
for (ok = 0; (c = *pattern++) != ']';) {
158
if (c == '\\' && !(flags & FNM_NOESCAPE))
159
c = *pattern++;
160
if (c == EOS)
161
return (NULL);
162
if (*pattern == '-'
163
&& (c2 = *(pattern+1)) != EOS && c2 != ']') {
164
pattern += 2;
165
if (c2 == '\\' && !(flags & FNM_NOESCAPE))
166
c2 = *pattern++;
167
if (c2 == EOS)
168
return (NULL);
169
if (c <= test && test <= c2)
170
ok = 1;
171
} else if (c == test)
172
ok = 1;
173
}
174
return (ok == negate ? NULL : pattern);
175
}
176
177