summaryrefslogtreecommitdiffstats
path: root/lib/util/unix_match.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/util/unix_match.c')
-rw-r--r--lib/util/unix_match.c183
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;
+}