1d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich/* $OpenBSD: fnmatch.c,v 1.16 2011/12/06 11:47:46 stsp Exp $ */ 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich/* Copyright (c) 2011, VMware, Inc. 4d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * All rights reserved. 5d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without 7d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * modification, are permitted provided that the following conditions are met: 8d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * * Redistributions of source code must retain the above copyright 9d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * notice, this list of conditions and the following disclaimer. 10d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * * Redistributions in binary form must reproduce the above copyright 11d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * notice, this list of conditions and the following disclaimer in the 12d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * documentation and/or other materials provided with the distribution. 13d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * * Neither the name of the VMware, Inc. nor the names of its contributors 14d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * may be used to endorse or promote products derived from this software 15d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * without specific prior written permission. 16d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 17d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE FOR 21d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 30d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * Copyright (c) 2008 Todd C. Miller <millert@openbsd.org> 31d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 32d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * Permission to use, copy, modify, and distribute this software for any 33d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * purpose with or without fee is hereby granted, provided that the above 34d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * copyright notice and this permission notice appear in all copies. 35d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 36d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 37d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 38d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 39d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 40d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 41d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 42d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 43d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 44d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 45d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich/* Authored by William A. Rowe Jr. <wrowe; apache.org, vmware.com>, April 2011 46d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 47d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * Derived from The Open Group Base Specifications Issue 7, IEEE Std 1003.1-2008 48d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * as described in; 49d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * http://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html 50d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 51d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * Filename pattern matches defined in section 2.13, "Pattern Matching Notation" 52d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * from chapter 2. "Shell Command Language" 53d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13 54d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * where; 1. A bracket expression starting with an unquoted <circumflex> '^' 55d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * character CONTINUES to specify a non-matching list; 2. an explicit <period> '.' 56d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading 57d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * <period> in a filename; 3. a <left-square-bracket> '[' which does not introduce 58d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * a valid bracket expression is treated as an ordinary character; 4. a differing 59d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * number of consecutive slashes within pattern and string will NOT match; 60d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 5. a trailing '\' in FNM_ESCAPE mode is treated as an ordinary '\' character. 61d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 62d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * Bracket expansion defined in section 9.3.5, "RE Bracket Expression", 63d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * from chapter 9, "Regular Expressions" 64d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05 65d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * with no support for collating symbols, equivalence class expressions or 66d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * character class expressions. A partial range expression with a leading 67d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * hyphen following a valid range expression will match only the ordinary 68d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * <hyphen> and the ending character (e.g. "[a-m-z]" will match characters 69d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 'a' through 'm', a <hyphen> '-', or a 'z'). 70d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 71d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * Supports BSD extensions FNM_LEADING_DIR to match pattern to the end of one 72d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * path segment of string, and FNM_CASEFOLD to ignore alpha case. 73d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 74d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * NOTE: Only POSIX/C single byte locales are correctly supported at this time. 75d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * Notably, non-POSIX locales with FNM_CASEFOLD produce undefined results, 76d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * particularly in ranges of mixed case (e.g. "[A-z]") or spanning alpha and 77d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * nonalpha characters within a range. 78d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 79d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * XXX comments below indicate porting required for multi-byte character sets 80d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * and non-POSIX locale collation orders; requires mbr* APIs to track shift 81d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * state of pattern and string (rewinding pattern and string repeatedly). 82d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 83d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * Certain parts of the code assume 0x00-0x3F are unique with any MBCS (e.g. 84d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * UTF-8, SHIFT-JIS, etc). Any implementation allowing '\' as an alternate 85d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * path delimiter must be aware that 0x5C is NOT unique within SHIFT-JIS. 861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <fnmatch.h> 89d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich#include <string.h> 90d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich#include <ctype.h> 91d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich#include <limits.h> 92d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 93d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich#include "charclass.h" 94d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 95d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich#define RANGE_MATCH 1 96d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich#define RANGE_NOMATCH 0 97d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich#define RANGE_ERROR (-1) 981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 99d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevichstatic int 100d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevichclassmatch(const char *pattern, char test, int foldcase, const char **ep) 101d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich{ 102d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich struct cclass *cc; 103d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const char *colon; 104d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich size_t len; 105d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich int rval = RANGE_NOMATCH; 106d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const char * const mismatch = pattern; 107d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 108d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (*pattern != '[' || pattern[1] != ':') { 109d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich *ep = mismatch; 110d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return(RANGE_ERROR); 111d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 113d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich pattern += 2; 1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 115d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if ((colon = strchr(pattern, ':')) == NULL || colon[1] != ']') { 116d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich *ep = mismatch; 117d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return(RANGE_ERROR); 118d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 119d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich *ep = colon + 2; 120d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich len = (size_t)(colon - pattern); 1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 122d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (foldcase && strncmp(pattern, "upper:]", 7) == 0) 123d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich pattern = "lower:]"; 124d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich for (cc = cclasses; cc->name != NULL; cc++) { 125d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (!strncmp(pattern, cc->name, len) && cc->name[len] == '\0') { 126d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (cc->isctype((unsigned char)test)) 127d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich rval = RANGE_MATCH; 128d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich break; 129d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 130d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 131d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (cc->name == NULL) { 132d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* invalid character class, treat as normal text */ 133d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich *ep = mismatch; 134d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich rval = RANGE_ERROR; 135d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 136d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return(rval); 137d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich} 138d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 139d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich/* Most MBCS/collation/case issues handled here. Wildcard '*' is not handled. 140d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * EOS '\0' and the FNM_PATHNAME '/' delimiters are not advanced over, 141d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * however the "\/" sequence is advanced to '/'. 142d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 143d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * Both pattern and string are **char to support pointer increment of arbitrary 144d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * multibyte characters for the given locale, in a later iteration of this code 145d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 146d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevichstatic int fnmatch_ch(const char **pattern, const char **string, int flags) 1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 148d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const char * const mismatch = *pattern; 149d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const int nocase = !!(flags & FNM_CASEFOLD); 150d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const int escape = !(flags & FNM_NOESCAPE); 151d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const int slash = !!(flags & FNM_PATHNAME); 152d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich int result = FNM_NOMATCH; 153d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const char *startch; 154d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich int negate; 155d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 156d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (**pattern == '[') 157d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich { 158d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++*pattern; 159d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 160d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Handle negation, either leading ! or ^ operators (never both) */ 161d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich negate = ((**pattern == '!') || (**pattern == '^')); 162d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (negate) 163d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++*pattern; 164d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 165d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* ']' is an ordinary character at the start of the range pattern */ 166d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (**pattern == ']') 167d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich goto leadingclosebrace; 168d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 169d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich while (**pattern) 170d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich { 171d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (**pattern == ']') { 172d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++*pattern; 173d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* XXX: Fix for MBCS character width */ 174d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++*string; 175d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return (result ^ negate); 176d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 177d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 178d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (escape && (**pattern == '\\')) { 179d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++*pattern; 180d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 181d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Patterns must be terminated with ']', not EOS */ 182d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (!**pattern) 183d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich break; 184d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 185d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 186d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Patterns must be terminated with ']' not '/' */ 187d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (slash && (**pattern == '/')) 188d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich break; 189d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 190d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Match character classes. */ 191d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (classmatch(*pattern, **string, nocase, pattern) 192d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich == RANGE_MATCH) { 193d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich result = 0; 194d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich continue; 195d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 196d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 197d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevichleadingclosebrace: 198d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Look at only well-formed range patterns; 199d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * "x-]" is not allowed unless escaped ("x-\]") 200d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * XXX: Fix for locale/MBCS character width 201d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 202d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (((*pattern)[1] == '-') && ((*pattern)[2] != ']')) 203d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich { 204d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich startch = *pattern; 205d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich *pattern += (escape && ((*pattern)[2] == '\\')) ? 3 : 2; 206d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 207d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* NOT a properly balanced [expr] pattern, EOS terminated 208d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * or ranges containing a slash in FNM_PATHNAME mode pattern 209d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * fall out to to the rewind and test '[' literal code path 210d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 211d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (!**pattern || (slash && (**pattern == '/'))) 212d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich break; 213d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 214d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* XXX: handle locale/MBCS comparison, advance by MBCS char width */ 215d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if ((**string >= *startch) && (**string <= **pattern)) 216d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich result = 0; 217d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich else if (nocase && (isupper(**string) || isupper(*startch) 218d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich || isupper(**pattern)) 219d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich && (tolower(**string) >= tolower(*startch)) 220d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich && (tolower(**string) <= tolower(**pattern))) 221d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich result = 0; 222d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 223d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++*pattern; 224d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich continue; 225d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 226d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 227d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* XXX: handle locale/MBCS comparison, advance by MBCS char width */ 228d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if ((**string == **pattern)) 229d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich result = 0; 230d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich else if (nocase && (isupper(**string) || isupper(**pattern)) 231d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich && (tolower(**string) == tolower(**pattern))) 232d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich result = 0; 233d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 234d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++*pattern; 235d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 236d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 237d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* NOT a properly balanced [expr] pattern; Rewind 238d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * and reset result to test '[' literal 239d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 240d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich *pattern = mismatch; 241d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich result = FNM_NOMATCH; 242d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 243d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich else if (**pattern == '?') { 244d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Optimize '?' match before unescaping **pattern */ 245d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (!**string || (slash && (**string == '/'))) 246d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return FNM_NOMATCH; 247d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich result = 0; 248d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich goto fnmatch_ch_success; 249d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 250d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich else if (escape && (**pattern == '\\') && (*pattern)[1]) { 251d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++*pattern; 252d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 253d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 254d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* XXX: handle locale/MBCS comparison, advance by the MBCS char width */ 255d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (**string == **pattern) 256d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich result = 0; 257d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich else if (nocase && (isupper(**string) || isupper(**pattern)) 258d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich && (tolower(**string) == tolower(**pattern))) 259d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich result = 0; 260d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 261d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Refuse to advance over trailing slash or nulls 262d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 263d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (!**string || !**pattern || (slash && ((**string == '/') || (**pattern == '/')))) 264d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return result; 265d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 266d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevichfnmatch_ch_success: 267d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++*pattern; 268d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++*string; 269d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return result; 2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 272d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 273d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevichint fnmatch(const char *pattern, const char *string, int flags) 2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 275d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich static const char dummystring[2] = {' ', 0}; 276d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const int escape = !(flags & FNM_NOESCAPE); 277d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const int slash = !!(flags & FNM_PATHNAME); 278d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const int leading_dir = !!(flags & FNM_LEADING_DIR); 279d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const char *strendseg; 280d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const char *dummyptr; 281d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const char *matchptr; 282d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich int wild; 283d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* For '*' wild processing only; surpress 'used before initialization' 284d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * warnings with dummy initialization values; 285d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 286d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const char *strstartseg = NULL; 287d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich const char *mismatch = NULL; 288d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich int matchlen = 0; 289d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 290d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (strnlen(pattern, PATH_MAX) == PATH_MAX || 291d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich strnlen(string, PATH_MAX) == PATH_MAX) 292d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return (FNM_NOMATCH); 293d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 294d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (*pattern == '*') 295d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich goto firstsegment; 296d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 297d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich while (*pattern && *string) 298d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich { 299d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Pre-decode "\/" which has no special significance, and 300d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * match balanced slashes, starting a new segment pattern 301d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 302d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (slash && escape && (*pattern == '\\') && (pattern[1] == '/')) 303d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++pattern; 304d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (slash && (*pattern == '/') && (*string == '/')) { 305d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++pattern; 306d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++string; 307d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 308d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 309d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevichfirstsegment: 310d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* At the beginning of each segment, validate leading period behavior. 3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 312d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if ((flags & FNM_PERIOD) && (*string == '.')) 313d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich { 314d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (*pattern == '.') 3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ++pattern; 316d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich else if (escape && (*pattern == '\\') && (pattern[1] == '.')) 317d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich pattern += 2; 318d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich else 319d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return FNM_NOMATCH; 320d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++string; 321d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 323d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Determine the end of string segment 324d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * 325d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * Presumes '/' character is unique, not composite in any MBCS encoding 326d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 327d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (slash) { 328d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich strendseg = strchr(string, '/'); 329d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (!strendseg) 330d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich strendseg = strchr(string, '\0'); 331d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 332d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich else { 333d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich strendseg = strchr(string, '\0'); 334d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 336d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Allow pattern '*' to be consumed even with no remaining string to match 3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 338d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich while (*pattern) 339d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich { 340d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if ((string > strendseg) 341d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich || ((string == strendseg) && (*pattern != '*'))) 342d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich break; 343d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 344d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (slash && ((*pattern == '/') 345d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich || (escape && (*pattern == '\\') 346d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich && (pattern[1] == '/')))) 347d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich break; 348d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 349d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Reduce groups of '*' and '?' to n '?' matches 350d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * followed by one '*' test for simplicity 351d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 352d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich for (wild = 0; ((*pattern == '*') || (*pattern == '?')); ++pattern) 353d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich { 354d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (*pattern == '*') { 355d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich wild = 1; 356d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 357d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich else if (string < strendseg) { /* && (*pattern == '?') */ 358d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* XXX: Advance 1 char for MBCS locale */ 359d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++string; 360d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 361d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich else { /* (string >= strendseg) && (*pattern == '?') */ 362d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return FNM_NOMATCH; 363d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 364d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 365d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 366d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (wild) 367d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich { 368d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich strstartseg = string; 369d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich mismatch = pattern; 370d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 371d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Count fixed (non '*') char matches remaining in pattern 372d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * excluding '/' (or "\/") and '*' 373d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 374d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich for (matchptr = pattern, matchlen = 0; 1; ++matchlen) 375d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich { 376d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if ((*matchptr == '\0') 377d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich || (slash && ((*matchptr == '/') 378d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich || (escape && (*matchptr == '\\') 379d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich && (matchptr[1] == '/'))))) 380d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich { 381d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Compare precisely this many trailing string chars, 382d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * the resulting match needs no wildcard loop 383d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 384d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* XXX: Adjust for MBCS */ 385d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (string + matchlen > strendseg) 386d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return FNM_NOMATCH; 387d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 388d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich string = strendseg - matchlen; 389d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich wild = 0; 390d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich break; 391d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 392d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 393d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (*matchptr == '*') 394d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich { 395d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Ensure at least this many trailing string chars remain 396d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * for the first comparison 397d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 398d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* XXX: Adjust for MBCS */ 399d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (string + matchlen > strendseg) 400d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return FNM_NOMATCH; 401d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 402d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Begin first wild comparison at the current position */ 403d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich break; 404d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 405d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 406d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Skip forward in pattern by a single character match 407d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * Use a dummy fnmatch_ch() test to count one "[range]" escape 408d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 409d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* XXX: Adjust for MBCS */ 410d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (escape && (*matchptr == '\\') && matchptr[1]) { 411d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich matchptr += 2; 412d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 413d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich else if (*matchptr == '[') { 414d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich dummyptr = dummystring; 415d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich fnmatch_ch(&matchptr, &dummyptr, flags); 416d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 417d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich else { 418d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich ++matchptr; 419d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 420d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 421d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 422d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 423d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Incrementally match string against the pattern 424d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 425d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich while (*pattern && (string < strendseg)) 426d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich { 427d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Success; begin a new wild pattern search 428d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 429d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (*pattern == '*') 430d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich break; 431d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 432d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (slash && ((*string == '/') 433d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich || (*pattern == '/') 434d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich || (escape && (*pattern == '\\') 435d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich && (pattern[1] == '/')))) 436d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich break; 437d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 438d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Compare ch's (the pattern is advanced over "\/" to the '/', 439d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * but slashes will mismatch, and are not consumed) 440d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 441d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (!fnmatch_ch(&pattern, &string, flags)) 442d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich continue; 443d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 444d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Failed to match, loop against next char offset of string segment 445d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich * until not enough string chars remain to match the fixed pattern 446d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 447d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (wild) { 448d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* XXX: Advance 1 char for MBCS locale */ 449d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich string = ++strstartseg; 450d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (string + matchlen > strendseg) 451d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return FNM_NOMATCH; 452d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 453d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich pattern = mismatch; 454d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich continue; 455d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 456d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich else 457d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return FNM_NOMATCH; 458d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 459d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 460d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 461d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (*string && !((slash || leading_dir) && (*string == '/'))) 462d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return FNM_NOMATCH; 463d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 464d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (*pattern && !(slash && ((*pattern == '/') 465d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich || (escape && (*pattern == '\\') 466d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich && (pattern[1] == '/'))))) 467d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return FNM_NOMATCH; 468d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 469d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (leading_dir && !*pattern && *string == '/') 470d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return 0; 471d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich } 472d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 473d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* Where both pattern and string are at EOS, declare success 474d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich */ 475d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich if (!*string && !*pattern) 476d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return 0; 477d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich 478d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich /* pattern didn't match to the end of string */ 479d1860ad8ddccc17c31783d08a518380d0f205702Nick Kralevich return FNM_NOMATCH; 4801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 481