1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Guido van Rossum. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #if defined(LIBC_SCCS) && !defined(lint) 38 static char sccsid[] = "@(#)fnmatch.c 5.4 (Berkeley) 2/23/91"; 39 #endif /* LIBC_SCCS and not lint */ 40 41 /* 42 * Function fnmatch() as proposed in Posix 1003.2 B.6 (rev. 9). 43 * Compares a filename or pathname to a pattern. 44 */ 45 46 #include <unistd.h> 47 #include <string.h> 48 49 #define EOS '\0' 50 51 static char * 52 rangematch(pattern, test) 53 register char *pattern, test; 54 { 55 register char c, c2; 56 int negate, ok; 57 58 if (negate = (*pattern == '!')) 59 ++pattern; 60 61 /* 62 * TO DO: quoting 63 */ 64 65 for (ok = 0; (c = *pattern++) != ']';) { 66 if (c == EOS) 67 return(NULL); /* illegal pattern */ 68 if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']') { 69 if (c <= test && test <= c2) 70 ok = 1; 71 pattern += 2; 72 } 73 else if (c == test) 74 ok = 1; 75 } 76 return(ok == negate ? NULL : pattern); 77 } 78 79 fnmatch(pattern, string, flags) 80 register const char *pattern; 81 register const char *string; 82 int flags; 83 { 84 register char c; 85 char test, *rangematch(); 86 87 for (;;) 88 switch (c = *pattern++) { 89 case EOS: 90 return(!(*string == EOS)); 91 case '?': 92 if (((test = *string++) == EOS) || 93 ((test == '/') && (flags & FNM_PATHNAME))) 94 return(1); 95 break; 96 case '*': 97 c = *pattern; 98 /* collapse multiple stars */ 99 while (c == '*') 100 c = *++pattern; 101 102 /* optimize for pattern with * at end or before / */ 103 if (c == EOS) 104 if (flags & FNM_PATHNAME) 105 return(index(string, '/') != NULL); 106 else 107 return(0); 108 else if ((c == '/') && (flags & FNM_PATHNAME)) { 109 if ((string = index(string, '/')) == NULL) 110 return(1); 111 break; 112 } 113 114 /* general case, use recursion */ 115 while ((test = *string) != EOS) { 116 if (!fnmatch(pattern, string, flags)) 117 return(0); 118 if (test == '/' && flags & FNM_PATHNAME) 119 break; 120 ++string; 121 } 122 return(1); 123 case '[': 124 if ((test = *string++) == EOS || 125 test == '/' && flags & FNM_PATHNAME) 126 return(1); 127 if ((pattern = rangematch(pattern, test)) == NULL) 128 return(1); 129 break; 130 case '\\': 131 if (flags & FNM_QUOTE) { 132 if ((c = *pattern++) == EOS) { 133 c = '\\'; 134 --pattern; 135 } 136 if (c != *string++) 137 return(1); 138 break; 139 } 140 /* FALLTHROUGH */ 141 default: 142 if (c != *string++) 143 return(1); 144 break; 145 } 146 } 147