wildcards

Wayne Davison wayned at users.sourceforge.net
Mon May 13 13:47:01 EST 2002


Here's a more complex version of the wildcard change that attempts to
count slashes in the pattern (if it does not contain "**" anywhere) and
to match at the appropriate level.

In trying to think up patterns where this might mess up, the only thing
I thought of was something like this:

     foo/b[^/]r/baz

My code would mess this up by counting 3 slashes.

This patch is not based on the previous one, but on CVS.

Note that neither this patch nor my previous one makes "**/foo" match
the file matched by "/foo" (which one might expect it to do).  We could
add some extra code to make this happen, if desired.

Optimization note:  I noticed that both this patch and my previous one
were only checking for "**" at the start of the pattern to trigger the
loop-skipping optimization.  I should really change that to check for
any leading "*" because of the code's limitation of treating "*" like
"**" when "**" is on the line somewhere.

..wayne..

---8<------8<------8<------8<---cut here--->8------>8------>8------>8---
Index: exclude.c
--- exclude.c	2002/04/11 02:25:53	1.44
+++ exclude.c	2002/05/13 20:30:33
@@ -35,6 +35,7 @@
 static struct exclude_struct *make_exclude(const char *pattern, int include)
 {
 	struct exclude_struct *ret;
+	char *cp;
 
 	ret = (struct exclude_struct *)malloc(sizeof(*ret));
 	if (!ret) out_of_memory("make_exclude");
@@ -55,7 +56,7 @@
 	if (!ret->pattern) out_of_memory("make_exclude");
 
 	if (strpbrk(pattern, "*[?")) {
-	    ret->regular_exp = 1;
+	    ret->wild_exp = 1;
 	    ret->fnmatch_flags = FNM_PATHNAME;
 	    if (strstr(pattern, "**")) {
 		    static int tested;
@@ -66,6 +67,8 @@
 			    }
 		    }
 		    ret->fnmatch_flags = 0;
+		    if (strncmp(pattern, "**", 2) == 0)
+			    ret->wild_exp = -1;
 	    }
 	}
 
@@ -74,9 +77,8 @@
 		ret->directory = 1;
 	}
 
-	if (!strchr(ret->pattern,'/')) {
-		ret->local = 1;
-	}
+	for (cp = ret->pattern; (cp = strchr(cp, '/')) != NULL; cp++)
+		ret->slash_cnt++;
 
 	return ret;
 }
@@ -95,7 +97,7 @@
 	int match_start=0;
 	char *pattern = ex->pattern;
 
-	if (ex->local && (p=strrchr(name,'/')))
+	if (!ex->slash_cnt && (p=strrchr(name,'/')))
 		name = p+1;
 
 	if (!name[0]) return 0;
@@ -107,9 +109,24 @@
 		pattern++;
 	}
 
-	if (ex->regular_exp) {
+	if (ex->wild_exp) {
+		if (!match_start && ex->slash_cnt && ex->fnmatch_flags != 0) {
+			int cnt = ex->slash_cnt + 1;
+			for (p = name + strlen(name) - 1; p >= name; p--) {
+				if (*p == '/' && !--cnt)
+					break;
+			}
+			name = p+1;
+		}
 		if (fnmatch(pattern, name, ex->fnmatch_flags) == 0) {
 			return 1;
+		}
+		if (!ex->fnmatch_flags && !match_start && ex->wild_exp > 0) {
+			while ((name = strchr(name, '/')) != NULL) {
+				name++;
+				if (fnmatch(pattern, name, ex->fnmatch_flags) == 0)
+					return 1;
+			}
 		}
 	} else {
 		int l1 = strlen(name);
Index: rsync.h
--- rsync.h	2002/04/11 02:18:51	1.131
+++ rsync.h	2002/05/13 20:30:34
@@ -392,11 +392,11 @@
 
 struct exclude_struct {
 	char *pattern;
-	int regular_exp;
+	int wild_exp;
 	int fnmatch_flags;
 	int include;
 	int directory;
-	int local;
+	int slash_cnt;
 };
 
 struct stats {
---8<------8<------8<------8<---cut here--->8------>8------>8------>8---





More information about the rsync mailing list