Path: blob/main/crypto/krb5/src/util/support/fnmatch.c
34889 views
/* $NetBSD: fnmatch.c,v 1.24 2011/01/31 19:10:18 christos Exp $ */12/*3* Copyright (c) 1989, 1993, 19944* The Regents of the University of California. All rights reserved.5*6* This code is derived from software contributed to Berkeley by7* Guido van Rossum.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17* 3. Neither the name of the University nor the names of its contributors18* may be used to endorse or promote products derived from this software19* without specific prior written permission.20*21* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND22* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE23* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE24* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE25* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL26* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS27* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)28* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT29* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY30* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF31* SUCH DAMAGE.32*/3334#if defined(LIBC_SCCS) && !defined(lint)35#if 036static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";37#else38__RCSID("$NetBSD: fnmatch.c,v 1.24 2011/01/31 19:10:18 christos Exp $");39#endif40#endif /* LIBC_SCCS and not lint */4142/*43* Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.44* Compares a filename or pathname to a pattern.45*/4647#include "k5-platform.h"48#include <ctype.h>49#ifndef _DIAGASSERT50#define _DIAGASSERT(x)51#endif5253#define EOS '\0'5455static inline int56foldcase(int ch, int flags)57{5859if ((flags & FNM_CASEFOLD) != 0 && isupper(ch))60return tolower(ch);61return ch;62}6364#define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags))6566static const char *67rangematch(const char *pattern, int test, int flags)68{69int negate, ok;70char c, c2;7172_DIAGASSERT(pattern != NULL);7374/*75* A bracket expression starting with an unquoted circumflex76* character produces unspecified results (IEEE 1003.2-1992,77* 3.13.2). This implementation treats it like '!', for78* consistency with the regular expression syntax.79* J.T. Conklin ([email protected])80*/81if ((negate = (*pattern == '!' || *pattern == '^')) != 0)82++pattern;8384for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']';) {85if (c == '\\' && !(flags & FNM_NOESCAPE))86c = FOLDCASE(*pattern++, flags);87if (c == EOS)88return NULL;89if (*pattern == '-'90&& (c2 = FOLDCASE(*(pattern + 1), flags)) != EOS &&91c2 != ']') {92pattern += 2;93if (c2 == '\\' && !(flags & FNM_NOESCAPE))94c2 = FOLDCASE(*pattern++, flags);95if (c2 == EOS)96return NULL;97if (c <= test && test <= c2)98ok = 1;99} else if (c == test)100ok = 1;101}102return ok == negate ? NULL : pattern;103}104105106static int107fnmatchx(const char *pattern, const char *string, int flags, size_t recursion)108{109const char *stringstart;110char c, test;111112_DIAGASSERT(pattern != NULL);113_DIAGASSERT(string != NULL);114115if (recursion-- == 0)116return FNM_NORES;117118for (stringstart = string;;) {119switch (c = FOLDCASE(*pattern++, flags)) {120case EOS:121if ((flags & FNM_LEADING_DIR) && *string == '/')122return 0;123return *string == EOS ? 0 : FNM_NOMATCH;124case '?':125if (*string == EOS)126return FNM_NOMATCH;127if (*string == '/' && (flags & FNM_PATHNAME))128return FNM_NOMATCH;129if (*string == '.' && (flags & FNM_PERIOD) &&130(string == stringstart ||131((flags & FNM_PATHNAME) && *(string - 1) == '/')))132return FNM_NOMATCH;133++string;134break;135case '*':136c = FOLDCASE(*pattern, flags);137/* Collapse multiple stars. */138while (c == '*')139c = FOLDCASE(*++pattern, flags);140141if (*string == '.' && (flags & FNM_PERIOD) &&142(string == stringstart ||143((flags & FNM_PATHNAME) && *(string - 1) == '/')))144return FNM_NOMATCH;145146/* Optimize for pattern with * at end or before /. */147if (c == EOS) {148if (flags & FNM_PATHNAME)149return (flags & FNM_LEADING_DIR) ||150strchr(string, '/') == NULL ?1510 : FNM_NOMATCH;152else153return 0;154} else if (c == '/' && flags & FNM_PATHNAME) {155if ((string = strchr(string, '/')) == NULL)156return FNM_NOMATCH;157break;158}159160/* General case, use recursion. */161while ((test = FOLDCASE(*string, flags)) != EOS) {162int e;163switch ((e = fnmatchx(pattern, string,164flags & ~FNM_PERIOD, recursion))) {165case FNM_NOMATCH:166break;167default:168return e;169}170if (test == '/' && flags & FNM_PATHNAME)171break;172++string;173}174return FNM_NOMATCH;175case '[':176if (*string == EOS)177return FNM_NOMATCH;178if (*string == '/' && flags & FNM_PATHNAME)179return FNM_NOMATCH;180if ((pattern = rangematch(pattern,181FOLDCASE(*string, flags), flags)) == NULL)182return FNM_NOMATCH;183++string;184break;185case '\\':186if (!(flags & FNM_NOESCAPE)) {187if ((c = FOLDCASE(*pattern++, flags)) == EOS) {188c = '\\';189--pattern;190}191}192/* FALLTHROUGH */193default:194if (c != FOLDCASE(*string++, flags))195return FNM_NOMATCH;196break;197}198}199/* NOTREACHED */200}201202int203k5_fnmatch(const char *pattern, const char *string, int flags)204{205return fnmatchx(pattern, string, flags, 64);206}207208209