diff options
Diffstat (limited to 'lib/util/unix_match.c')
-rw-r--r-- | lib/util/unix_match.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/lib/util/unix_match.c b/lib/util/unix_match.c new file mode 100644 index 0000000..38edc18 --- /dev/null +++ b/lib/util/unix_match.c @@ -0,0 +1,183 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Jeremy Allison 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include <talloc.h> +#include "lib/util/talloc_stack.h" +#include "lib/util/charset/charset.h" +#include "lib/util/unix_match.h" + +/********************************************************* + Recursive routine that is called by unix_wild_match. +*********************************************************/ + +static bool unix_do_match(const char *regexp, const char *str) +{ + const char *p; + + for( p = regexp; *p && *str; ) { + + switch(*p) { + case '?': + str++; + p++; + break; + + case '*': + + /* + * Look for a character matching + * the one after the '*'. + */ + p++; + if(!*p) { + return true; /* Automatic match */ + } + while(*str) { + + while(*str && (*p != *str)) { + str++; + } + + /* + * Patch from weidel@multichart.de. + * In the case of the regexp + * '*XX*' we want to ensure there are + * at least 2 'X' characters in the + * string after the '*' for a match to + * be made. + */ + + { + int matchcount=0; + + /* + * Eat all the characters that + * match, but count how many + * there were. + */ + + while(*str && (*p == *str)) { + str++; + matchcount++; + } + + /* + * Now check that if the regexp + * had n identical characters + * that matchcount had at least + * that many matches. + */ + + while (*(p+1) && (*(p+1)==*p)) { + p++; + matchcount--; + } + + if ( matchcount <= 0 ) { + return false; + } + } + + /* + * We've eaten the match char + * after the '*' + */ + str--; + + if(unix_do_match(p, str)) { + return true; + } + + if(!*str) { + return false; + } else { + str++; + } + } + return false; + + default: + if(*str != *p) { + return false; + } + str++; + p++; + break; + } + } + + if(!*p && !*str) { + return true; + } + + if (!*p && str[0] == '.' && str[1] == 0) { + return true; + } + + if (!*str && *p == '?') { + while (*p == '?') { + p++; + } + return(!*p); + } + + if(!*str && (*p == '*' && p[1] == '\0')) { + return true; + } + + return false; +} + +/******************************************************************* + Simple case insensitive interface to a UNIX wildcard matcher. + Returns True if match, False if not. +*******************************************************************/ + +bool unix_wild_match(const char *pattern, const char *string) +{ + TALLOC_CTX *ctx = talloc_stackframe(); + char *p2; + char *s2; + char *p; + bool ret = false; + + p2 = strlower_talloc(ctx, pattern); + s2 = strlower_talloc(ctx, string); + if (!p2 || !s2) { + TALLOC_FREE(ctx); + return false; + } + + /* Remove any *? and ** from the pattern as they are meaningless */ + for(p = p2; *p; p++) { + while( *p == '*' && (p[1] == '?' ||p[1] == '*')) { + memmove(&p[1], &p[2], strlen(&p[2])+1); + } + } + + if (p2[0] == '*' && p2[1] == '\0') { + TALLOC_FREE(ctx); + return true; + } + + ret = unix_do_match(p2, s2); + TALLOC_FREE(ctx); + return ret; +} |