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--- -- To unsubscribe or change options: http://lists.samba.org/mailman/listinfo/rsync Before posting, read: http://www.tuxedo.org/~esr/faqs/smart-questions.html