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