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

This is now fixed.

> rsync-dev -r -vi --files-from=<(echo secret/) --no-R rsync://[EMAIL 
> PROTECTED]: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..
--- 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)
-- 
To unsubscribe or change options: https://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.catb.org/~esr/faqs/smart-questions.html

Reply via email to