1*1e72d8d2Sderaadt /* Copyright (C) 1992 Free Software Foundation, Inc. 2*1e72d8d2Sderaadt This file is part of the GNU C Library. 3*1e72d8d2Sderaadt 4*1e72d8d2Sderaadt The GNU C Library is free software; you can redistribute it and/or 5*1e72d8d2Sderaadt modify it under the terms of the GNU Library General Public License as 6*1e72d8d2Sderaadt published by the Free Software Foundation; either version 2 of the 7*1e72d8d2Sderaadt License, or (at your option) any later version. 8*1e72d8d2Sderaadt 9*1e72d8d2Sderaadt The GNU C Library is distributed in the hope that it will be useful, 10*1e72d8d2Sderaadt but WITHOUT ANY WARRANTY; without even the implied warranty of 11*1e72d8d2Sderaadt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12*1e72d8d2Sderaadt Library General Public License for more details. 13*1e72d8d2Sderaadt 14*1e72d8d2Sderaadt You should have received a copy of the GNU Library General Public 15*1e72d8d2Sderaadt License along with the GNU C Library; see the file COPYING.LIB. If 16*1e72d8d2Sderaadt not, write to the Free Software Foundation, Inc., 675 Mass Ave, 17*1e72d8d2Sderaadt Cambridge, MA 02139, USA. */ 18*1e72d8d2Sderaadt 19*1e72d8d2Sderaadt /* Modified slightly by Brian Berliner <berliner@sun.com> and 20*1e72d8d2Sderaadt Jim Blandy <jimb@cyclic.com> for CVS use */ 21*1e72d8d2Sderaadt 22*1e72d8d2Sderaadt #ifdef HAVE_CONFIG_H 23*1e72d8d2Sderaadt #include "config.h" 24*1e72d8d2Sderaadt #endif 25*1e72d8d2Sderaadt 26*1e72d8d2Sderaadt /* Some file systems are case-insensitive. If FOLD_FN_CHAR is #defined, it maps 27*1e72d8d2Sderaadt the character C onto its "canonical" form. In a case-insensitive system, 28*1e72d8d2Sderaadt it would map all alphanumeric characters to lower case. Under Windows NT, 29*1e72d8d2Sderaadt / and \ are both path component separators, so FOLD_FN_CHAR would map them both 30*1e72d8d2Sderaadt to /. */ 31*1e72d8d2Sderaadt #ifndef FOLD_FN_CHAR 32*1e72d8d2Sderaadt #define FOLD_FN_CHAR(c) (c) 33*1e72d8d2Sderaadt #endif 34*1e72d8d2Sderaadt 35*1e72d8d2Sderaadt /* IGNORE(@ */ 36*1e72d8d2Sderaadt /* #include <ansidecl.h> */ 37*1e72d8d2Sderaadt /* @) */ 38*1e72d8d2Sderaadt #include <errno.h> 39*1e72d8d2Sderaadt #include <fnmatch.h> 40*1e72d8d2Sderaadt 41*1e72d8d2Sderaadt #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS) 42*1e72d8d2Sderaadt extern int errno; 43*1e72d8d2Sderaadt #endif 44*1e72d8d2Sderaadt 45*1e72d8d2Sderaadt /* Match STRING against the filename pattern PATTERN, returning zero if 46*1e72d8d2Sderaadt it matches, nonzero if not. */ 47*1e72d8d2Sderaadt int 48*1e72d8d2Sderaadt #if __STDC__ 49*1e72d8d2Sderaadt fnmatch (const char *pattern, const char *string, int flags) 50*1e72d8d2Sderaadt #else 51*1e72d8d2Sderaadt fnmatch (pattern, string, flags) 52*1e72d8d2Sderaadt char *pattern; 53*1e72d8d2Sderaadt char *string; 54*1e72d8d2Sderaadt int flags; 55*1e72d8d2Sderaadt #endif 56*1e72d8d2Sderaadt { 57*1e72d8d2Sderaadt register const char *p = pattern, *n = string; 58*1e72d8d2Sderaadt register char c; 59*1e72d8d2Sderaadt 60*1e72d8d2Sderaadt if ((flags & ~__FNM_FLAGS) != 0) 61*1e72d8d2Sderaadt { 62*1e72d8d2Sderaadt errno = EINVAL; 63*1e72d8d2Sderaadt return -1; 64*1e72d8d2Sderaadt } 65*1e72d8d2Sderaadt 66*1e72d8d2Sderaadt while ((c = *p++) != '\0') 67*1e72d8d2Sderaadt { 68*1e72d8d2Sderaadt switch (c) 69*1e72d8d2Sderaadt { 70*1e72d8d2Sderaadt case '?': 71*1e72d8d2Sderaadt if (*n == '\0') 72*1e72d8d2Sderaadt return FNM_NOMATCH; 73*1e72d8d2Sderaadt else if ((flags & FNM_PATHNAME) && *n == '/') 74*1e72d8d2Sderaadt return FNM_NOMATCH; 75*1e72d8d2Sderaadt else if ((flags & FNM_PERIOD) && *n == '.' && 76*1e72d8d2Sderaadt (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) 77*1e72d8d2Sderaadt return FNM_NOMATCH; 78*1e72d8d2Sderaadt break; 79*1e72d8d2Sderaadt 80*1e72d8d2Sderaadt case '\\': 81*1e72d8d2Sderaadt if (!(flags & FNM_NOESCAPE)) 82*1e72d8d2Sderaadt c = *p++; 83*1e72d8d2Sderaadt if (*n != c) 84*1e72d8d2Sderaadt return FNM_NOMATCH; 85*1e72d8d2Sderaadt break; 86*1e72d8d2Sderaadt 87*1e72d8d2Sderaadt case '*': 88*1e72d8d2Sderaadt if ((flags & FNM_PERIOD) && *n == '.' && 89*1e72d8d2Sderaadt (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) 90*1e72d8d2Sderaadt return FNM_NOMATCH; 91*1e72d8d2Sderaadt 92*1e72d8d2Sderaadt for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) 93*1e72d8d2Sderaadt if (((flags & FNM_PATHNAME) && *n == '/') || 94*1e72d8d2Sderaadt (c == '?' && *n == '\0')) 95*1e72d8d2Sderaadt return FNM_NOMATCH; 96*1e72d8d2Sderaadt 97*1e72d8d2Sderaadt if (c == '\0') 98*1e72d8d2Sderaadt return 0; 99*1e72d8d2Sderaadt 100*1e72d8d2Sderaadt { 101*1e72d8d2Sderaadt char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; 102*1e72d8d2Sderaadt for (--p; *n != '\0'; ++n) 103*1e72d8d2Sderaadt if ((c == '[' || *n == c1) && 104*1e72d8d2Sderaadt fnmatch(p, n, flags & ~FNM_PERIOD) == 0) 105*1e72d8d2Sderaadt return 0; 106*1e72d8d2Sderaadt return FNM_NOMATCH; 107*1e72d8d2Sderaadt } 108*1e72d8d2Sderaadt 109*1e72d8d2Sderaadt case '[': 110*1e72d8d2Sderaadt { 111*1e72d8d2Sderaadt /* Nonzero if the sense of the character class is inverted. */ 112*1e72d8d2Sderaadt register int not; 113*1e72d8d2Sderaadt 114*1e72d8d2Sderaadt if (*n == '\0') 115*1e72d8d2Sderaadt return FNM_NOMATCH; 116*1e72d8d2Sderaadt 117*1e72d8d2Sderaadt if ((flags & FNM_PERIOD) && *n == '.' && 118*1e72d8d2Sderaadt (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) 119*1e72d8d2Sderaadt return FNM_NOMATCH; 120*1e72d8d2Sderaadt 121*1e72d8d2Sderaadt not = (*p == '!' || *p == '^'); 122*1e72d8d2Sderaadt if (not) 123*1e72d8d2Sderaadt ++p; 124*1e72d8d2Sderaadt 125*1e72d8d2Sderaadt c = *p++; 126*1e72d8d2Sderaadt for (;;) 127*1e72d8d2Sderaadt { 128*1e72d8d2Sderaadt register char cstart = c, cend = c; 129*1e72d8d2Sderaadt 130*1e72d8d2Sderaadt if (!(flags & FNM_NOESCAPE) && c == '\\') 131*1e72d8d2Sderaadt cstart = cend = *p++; 132*1e72d8d2Sderaadt 133*1e72d8d2Sderaadt if (c == '\0') 134*1e72d8d2Sderaadt /* [ (unterminated) loses. */ 135*1e72d8d2Sderaadt return FNM_NOMATCH; 136*1e72d8d2Sderaadt 137*1e72d8d2Sderaadt c = *p++; 138*1e72d8d2Sderaadt 139*1e72d8d2Sderaadt if ((flags & FNM_PATHNAME) && c == '/') 140*1e72d8d2Sderaadt /* [/] can never match. */ 141*1e72d8d2Sderaadt return FNM_NOMATCH; 142*1e72d8d2Sderaadt 143*1e72d8d2Sderaadt if (c == '-' && *p != ']') 144*1e72d8d2Sderaadt { 145*1e72d8d2Sderaadt cend = *p++; 146*1e72d8d2Sderaadt if (!(flags & FNM_NOESCAPE) && cend == '\\') 147*1e72d8d2Sderaadt cend = *p++; 148*1e72d8d2Sderaadt if (cend == '\0') 149*1e72d8d2Sderaadt return FNM_NOMATCH; 150*1e72d8d2Sderaadt c = *p++; 151*1e72d8d2Sderaadt } 152*1e72d8d2Sderaadt 153*1e72d8d2Sderaadt if (*n >= cstart && *n <= cend) 154*1e72d8d2Sderaadt goto matched; 155*1e72d8d2Sderaadt 156*1e72d8d2Sderaadt if (c == ']') 157*1e72d8d2Sderaadt break; 158*1e72d8d2Sderaadt } 159*1e72d8d2Sderaadt if (!not) 160*1e72d8d2Sderaadt return FNM_NOMATCH; 161*1e72d8d2Sderaadt break; 162*1e72d8d2Sderaadt 163*1e72d8d2Sderaadt matched:; 164*1e72d8d2Sderaadt /* Skip the rest of the [...] that already matched. */ 165*1e72d8d2Sderaadt while (c != ']') 166*1e72d8d2Sderaadt { 167*1e72d8d2Sderaadt if (c == '\0') 168*1e72d8d2Sderaadt /* [... (unterminated) loses. */ 169*1e72d8d2Sderaadt return FNM_NOMATCH; 170*1e72d8d2Sderaadt 171*1e72d8d2Sderaadt c = *p++; 172*1e72d8d2Sderaadt if (!(flags & FNM_NOESCAPE) && c == '\\') 173*1e72d8d2Sderaadt /* 1003.2d11 is unclear if this is right. %%% */ 174*1e72d8d2Sderaadt ++p; 175*1e72d8d2Sderaadt } 176*1e72d8d2Sderaadt if (not) 177*1e72d8d2Sderaadt return FNM_NOMATCH; 178*1e72d8d2Sderaadt } 179*1e72d8d2Sderaadt break; 180*1e72d8d2Sderaadt 181*1e72d8d2Sderaadt default: 182*1e72d8d2Sderaadt if (FOLD_FN_CHAR (c) != FOLD_FN_CHAR (*n)) 183*1e72d8d2Sderaadt return FNM_NOMATCH; 184*1e72d8d2Sderaadt } 185*1e72d8d2Sderaadt 186*1e72d8d2Sderaadt ++n; 187*1e72d8d2Sderaadt } 188*1e72d8d2Sderaadt 189*1e72d8d2Sderaadt if (*n == '\0') 190*1e72d8d2Sderaadt return 0; 191*1e72d8d2Sderaadt 192*1e72d8d2Sderaadt return FNM_NOMATCH; 193*1e72d8d2Sderaadt } 194