Do we need excluded_below?

Wayne Davison wayned at samba.org
Fri Mar 21 23:00:40 GMT 2008


On Tue, Mar 18, 2008 at 03:11:06PM -0400, Matt McCutchen wrote:
> rsync-dev -r -vi rsync://user@localhost:3141/module/./secret/ download/

This is now fixed.

> rsync-dev -r -vi --files-from=<(echo secret/) --no-R rsync://user@localhost:3141/module/ download/

I can think of 3 different ways to deal with this.  (1) Don't do
anything, since a daemon exclude should be using a dir/*** rule.  (2)
add path-checking to the file-from arg-reading code, so that every dir
is compared against the exclude list.  (3) Try to get fancy and enhance
an absolute exclude of a directory (whose rule does not have "**" in it
anywhere) to add a rule that excludes each found directory using a
dir/*** rule.  I coded up the latter, and it passes some basic tests
(diff attached).

Thoughts?

> BTW, what is the purpose of leaving the path truncated in
> "filter_server_path"?

Returning an arg that is known to match a daemon exclude ensures that it
will be excluded by the code that parses the args.  If the exclude was a
dir/*** exclude, we could return back the non-truncated arg.

> This makes it possible to distinguish between a nonexistent and
> daemon-excluded dir /secret by trying to pull /secret/X/ and seeing
> whether the path in the error message is truncated.

I've always seen the path truncated in the error, but the error is
sometimes inconsistent.  I.e. a really non-existent directory in a path
sometimes returns a push_dir failure, while the (current) code that
rejects an excluded dir always returns a file-not-found error.  It may
be possible to further conceal this.

..wayne..
-------------- next part --------------
--- a/clientserver.c
+++ b/clientserver.c
@@ -699,6 +699,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
 		}
 	}
 
+	enhance_daemon_excludes();
+
 	if (am_root) {
 		/* XXXX: You could argue that if the daemon is started
 		 * by a non-root user and they explicitly specify a
--- a/exclude.c
+++ b/exclude.c
@@ -651,6 +651,63 @@ int check_filter(struct filter_list_struct *listp, const char *name, int name_is
 	return 0;
 }
 
+/* If an absolute exclude w/o a ** matches a dir, add a trailing slash+***
+ * rule to ensure that the dir's contents stays excluded. */
+int enhance_daemon_excludes(void)
+{
+	struct filter_struct **our_ex_p, *ex, *add, *save = daemon_filter_list.head;
+	int len, argc = 0, maxargs = 0;
+	char *cp, buf[MAXPATHLEN+4], **argv = NULL;
+
+	/* Disable the excludes for our use of glob_expand(). */
+	daemon_filter_list.head = NULL;
+
+	for (our_ex_p = &save; (ex = *our_ex_p) != NULL; our_ex_p = &ex->next) {
+		if (ex->match_flags & (MATCHFLG_WILD2|MATCHFLG_INCLUDE|MATCHFLG_MERGE_FILE|MATCHFLG_PERDIR_MERGE)
+		 || ex->pattern[0] != '/'
+		 || (len = strlcpy(buf, ex->pattern, MAXPATHLEN)) >= MAXPATHLEN)
+			continue;
+		/* We want to find just dirs that match this absolute exclude,
+		 * which we can do by adding a trailing "/." -- but, we also
+		 * want room to add more chars, so use "/./." instead. */
+		if (buf[len-1] != '/')
+			buf[len++] = '/';
+		buf[len++] = '.';
+		buf[len++] = '/';
+		buf[len++] = '.';
+		buf[len] = '\0';
+		argc = 0;
+		if (!glob_expand(buf, &argv, &argc, &maxargs)) {
+			free(argv[0]); /* dump strdup of failed glob string */
+			continue;
+		}
+		while (argc) {
+			if (!(add = new0(struct filter_struct)))
+				out_of_memory("enhance_daemon_excludes");
+			add->pattern = argv[--argc];
+			len = strlen(add->pattern);
+			/* Patterns come back w/o leading slash. */
+			memmove(add->pattern+1, add->pattern, len - 3);
+			/* Use 3-char "./." suffix's space to add back "/"
+			 * prefix and a "**" suffix (flagged as "***"). */
+			add->pattern[0] = '/';
+			add->pattern[len-1] = add->pattern[len-2] = '*';
+			add->match_flags = ex->match_flags|MATCHFLG_WILD|MATCHFLG_WILD2|MATCHFLG_WILD3_SUFFIX;
+			for (cp = add->pattern; (cp = strchr(cp, '/')) != NULL; cp++)
+				add->u.slash_cnt++;
+			add->next = ex;
+			*our_ex_p = add;
+			our_ex_p = &add->next;
+		}
+	}
+
+	glob_expand(NULL, NULL, NULL, NULL);
+
+	daemon_filter_list.head = save;
+
+	return 0;
+}
+
 #define RULE_STRCMP(s,r) rule_strcmp((s), (r), sizeof (r) - 1)
 
 static const uchar *rule_strcmp(const uchar *str, const char *rule, int rule_len)


More information about the rsync mailing list