A little tidying up to follow my preferred style.
[rsync/rsync.git] / exclude.c
index 729cf97..c0dc3bd 100644 (file)
--- a/exclude.c
+++ b/exclude.c
@@ -4,7 +4,7 @@
  * Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
  * Copyright (C) 1996 Paul Mackerras
  * Copyright (C) 2002 Martin Pool
- * Copyright (C) 2003-2007 Wayne Davison
+ * Copyright (C) 2003-2008 Wayne Davison
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include "rsync.h"
 
-extern int verbose;
 extern int am_server;
 extern int am_sender;
 extern int eol_nulls;
-extern int recurse;
 extern int io_error;
 extern int local_server;
 extern int prune_empty_dirs;
@@ -38,13 +36,13 @@ extern int sanitize_paths;
 extern int protocol_version;
 extern int module_id;
 
-extern char curr_dir[];
+extern char curr_dir[MAXPATHLEN];
 extern unsigned int curr_dir_len;
 extern unsigned int module_dirlen;
 
-struct filter_list_struct filter_list = { 0, 0, "" };
-struct filter_list_struct cvs_filter_list = { 0, 0, " [global CVS]" };
-struct filter_list_struct server_filter_list = { 0, 0, " [daemon]" };
+struct filter_list_struct filter_list = { .debug_type = "" };
+struct filter_list_struct cvs_filter_list = { .debug_type = " [global CVS]" };
+struct filter_list_struct daemon_filter_list = { .debug_type = " [daemon]" };
 
 /* Need room enough for ":MODS " prefix plus some room to grow. */
 #define MAX_RULE_PREFIX (16)
@@ -53,6 +51,8 @@ struct filter_list_struct server_filter_list = { 0, 0, " [daemon]" };
 #define MODIFIERS_INCL_EXCL "/!Crsp"
 #define MODIFIERS_HIDE_PROTECT "/!p"
 
+#define SLASH_WILD3_SUFFIX "/***"
+
 /* The dirbuf is set by push_local_filters() to the current subdirectory
  * relative to curr_dir that is being processed.  The path always has a
  * trailing slash appended, and the variable dirbuf_len contains the length
@@ -102,17 +102,54 @@ static int mergelist_size = 0;
  * values (so we can pop back to them later) and set the tail to NULL.
  */
 
-static void free_filter(struct filter_struct *ex)
+static void teardown_mergelist(struct filter_struct *ex)
 {
-       if (ex->match_flags & MATCHFLG_PERDIR_MERGE) {
-               free(ex->u.mergelist->debug_type);
-               free(ex->u.mergelist);
-               mergelist_cnt--;
+       if (DEBUG_GTE(FILTER, 2)) {
+               rprintf(FINFO, "[%s] deactivating mergelist #%d%s\n",
+                       who_am_i(), mergelist_cnt - 1,
+                       ex->u.mergelist->debug_type);
        }
+
+       /* We should deactivate mergelists in LIFO order. */
+       assert(mergelist_cnt > 0);
+       assert(ex == mergelist_parents[mergelist_cnt - 1]);
+
+       /* The parent_dirscan filters should have been freed. */
+       assert(ex->u.mergelist->parent_dirscan_head == NULL);
+
+       free(ex->u.mergelist->debug_type);
+       free(ex->u.mergelist);
+       mergelist_cnt--;
+}
+
+static void free_filter(struct filter_struct *ex)
+{
+       if (ex->match_flags & MATCHFLG_PERDIR_MERGE)
+               teardown_mergelist(ex);
        free(ex->pattern);
        free(ex);
 }
 
+static void free_filters(struct filter_struct *head)
+{
+       struct filter_struct *rev_head = NULL;
+
+       /* Reverse the list so we deactivate mergelists in the proper LIFO
+        * order. */
+       while (head) {
+               struct filter_struct *next = head->next;
+               head->next = rev_head;
+               rev_head = head;
+               head = next;
+       }
+
+       while (rev_head) {
+               struct filter_struct *prev = rev_head->next;
+               free_filter(rev_head);
+               rev_head = prev;
+       }
+}
+
 /* Build a filter structure given a filter pattern.  The value in "pat"
  * is not null-terminated. */
 static void add_rule(struct filter_list_struct *listp, const char *pat,
@@ -120,9 +157,9 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
 {
        struct filter_struct *ret;
        const char *cp;
-       unsigned int ex_len;
+       unsigned int pre_len, suf_len, slash_cnt = 0;
 
-       if (verbose > 2) {
+       if (DEBUG_GTE(FILTER, 2)) {
                rprintf(FINFO, "[%s] add_rule(%s%.*s%s)%s\n",
                        who_am_i(), get_rule_prefix(mflags, pat, 0, NULL),
                        (int)pat_len, pat,
@@ -146,22 +183,51 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
        if (!(ret = new0(struct filter_struct)))
                out_of_memory("add_rule");
 
+       if (pat_len > 1 && pat[pat_len-1] == '/') {
+               pat_len--;
+               mflags |= MATCHFLG_DIRECTORY;
+       }
+
+       for (cp = pat; cp < pat + pat_len; cp++) {
+               if (*cp == '/')
+                       slash_cnt++;
+       }
+
        if (!(mflags & (MATCHFLG_ABS_PATH | MATCHFLG_MERGE_FILE))
         && ((xflags & (XFLG_ANCHORED2ABS|XFLG_ABS_IF_SLASH) && *pat == '/')
-         || (xflags & XFLG_ABS_IF_SLASH && strchr(pat, '/') != NULL))) {
+         || (xflags & XFLG_ABS_IF_SLASH && slash_cnt))) {
                mflags |= MATCHFLG_ABS_PATH;
                if (*pat == '/')
-                       ex_len = dirbuf_len - module_dirlen - 1;
+                       pre_len = dirbuf_len - module_dirlen - 1;
                else
-                       ex_len = 0;
+                       pre_len = 0;
+       } else
+               pre_len = 0;
+
+       /* The daemon wants dir-exclude rules to get an appended "/" + "***". */
+       if (xflags & XFLG_DIR2WILD3
+        && BITS_SETnUNSET(mflags, MATCHFLG_DIRECTORY, MATCHFLG_INCLUDE)) {
+               mflags &= ~MATCHFLG_DIRECTORY;
+               suf_len = sizeof SLASH_WILD3_SUFFIX - 1;
        } else
-               ex_len = 0;
-       if (!(ret->pattern = new_array(char, ex_len + pat_len + 1)))
+               suf_len = 0;
+
+       if (!(ret->pattern = new_array(char, pre_len + pat_len + suf_len + 1)))
                out_of_memory("add_rule");
-       if (ex_len)
-               memcpy(ret->pattern, dirbuf + module_dirlen, ex_len);
-       strlcpy(ret->pattern + ex_len, pat, pat_len + 1);
-       pat_len += ex_len;
+       if (pre_len) {
+               memcpy(ret->pattern, dirbuf + module_dirlen, pre_len);
+               for (cp = ret->pattern; cp < ret->pattern + pre_len; cp++) {
+                       if (*cp == '/')
+                               slash_cnt++;
+               }
+       }
+       strlcpy(ret->pattern + pre_len, pat, pat_len + 1);
+       pat_len += pre_len;
+       if (suf_len) {
+               memcpy(ret->pattern + pat_len, SLASH_WILD3_SUFFIX, suf_len+1);
+               pat_len += suf_len;
+               slash_cnt++;
+       }
 
        if (strpbrk(ret->pattern, "*[?")) {
                mflags |= MATCHFLG_WILD;
@@ -179,11 +245,6 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
                }
        }
 
-       if (pat_len > 1 && ret->pattern[pat_len-1] == '/') {
-               ret->pattern[pat_len-1] = 0;
-               mflags |= MATCHFLG_DIRECTORY;
-       }
-
        if (mflags & MATCHFLG_PERDIR_MERGE) {
                struct filter_list_struct *lp;
                unsigned int len;
@@ -213,7 +274,7 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
 
                if (!(lp = new_array(struct filter_list_struct, 1)))
                        out_of_memory("add_rule");
-               lp->head = lp->tail = NULL;
+               lp->head = lp->tail = lp->parent_dirscan_head = NULL;
                if (asprintf(&lp->debug_type, " [per-dir %s]", cp) < 0)
                        out_of_memory("add_rule");
                ret->u.mergelist = lp;
@@ -226,11 +287,13 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
                        if (!mergelist_parents)
                                out_of_memory("add_rule");
                }
+               if (DEBUG_GTE(FILTER, 2)) {
+                       rprintf(FINFO, "[%s] activating mergelist #%d%s\n",
+                               who_am_i(), mergelist_cnt, lp->debug_type);
+               }
                mergelist_parents[mergelist_cnt++] = ret;
-       } else {
-               for (cp = ret->pattern; (cp = strchr(cp, '/')) != NULL; cp++)
-                       ret->u.slash_cnt++;
-       }
+       } else
+               ret->u.slash_cnt = slash_cnt;
 
        ret->match_flags = mflags;
 
@@ -247,14 +310,10 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
 static void clear_filter_list(struct filter_list_struct *listp)
 {
        if (listp->tail) {
-               struct filter_struct *ent, *next;
                /* Truncate any inherited items from the local list. */
                listp->tail->next = NULL;
                /* Now free everything that is left. */
-               for (ent = listp->head; ent; ent = next) {
-                       next = ent->next;
-                       free_filter(ent);
-               }
+               free_filters(listp->head);
        }
 
        listp->head = listp->tail = NULL;
@@ -296,7 +355,7 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
                        strlcpy(to, merge_file, *len_ptr + 1);
                        merge_file = to;
                }
-               if (!sanitize_path(fn, merge_file, r, dirbuf_depth, NULL)) {
+               if (!sanitize_path(fn, merge_file, r, dirbuf_depth, SP_DEFAULT)) {
                        rprintf(FERROR, "merge-file name overflows: %s\n",
                                merge_file);
                        return NULL;
@@ -304,18 +363,19 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
                fn_len = strlen(fn);
        } else {
                strlcpy(fn, merge_file, len_ptr ? *len_ptr + 1 : MAXPATHLEN);
-               fn_len = clean_fname(fn, 1);
+               fn_len = clean_fname(fn, CFN_COLLAPSE_DOT_DOT_DIRS);
        }
 
        /* If the name isn't in buf yet, it's wasn't absolute. */
        if (fn != buf) {
-               if (dirbuf_len + fn_len >= MAXPATHLEN) {
+               int d_len = dirbuf_len - prefix_skip;
+               if (d_len + fn_len >= MAXPATHLEN) {
                        rprintf(FERROR, "merge-file name overflows: %s\n", fn);
                        return NULL;
                }
-               memcpy(buf, dirbuf + prefix_skip, dirbuf_len - prefix_skip);
-               memcpy(buf + dirbuf_len - prefix_skip, fn, fn_len + 1);
-               fn_len = clean_fname(buf, 1);
+               memcpy(buf, dirbuf + prefix_skip, d_len);
+               memcpy(buf + d_len, fn, fn_len + 1);
+               fn_len = clean_fname(buf, CFN_COLLAPSE_DOT_DOT_DIRS);
        }
 
        if (len_ptr)
@@ -337,7 +397,7 @@ void set_filter_dir(const char *dir, unsigned int dirlen)
                len = 0;
        memcpy(dirbuf + len, dir, dirlen);
        dirbuf[dirlen + len] = '\0';
-       dirbuf_len = clean_fname(dirbuf, 1);
+       dirbuf_len = clean_fname(dirbuf, CFN_COLLAPSE_DOT_DOT_DIRS);
        if (dirbuf_len > 1 && dirbuf[dirbuf_len-1] == '.'
            && dirbuf[dirbuf_len-2] == '/')
                dirbuf_len -= 2;
@@ -353,7 +413,7 @@ void set_filter_dir(const char *dir, unsigned int dirlen)
  * parent directory of the first transfer dir.  If it does, we scan all the
  * dirs from that point through the parent dir of the transfer dir looking
  * for the per-dir merge-file in each one. */
-static BOOL setup_merge_file(struct filter_struct *ex,
+static BOOL setup_merge_file(int mergelist_num, struct filter_struct *ex,
                             struct filter_list_struct *lp)
 {
        char buf[MAXPATHLEN];
@@ -363,6 +423,10 @@ static BOOL setup_merge_file(struct filter_struct *ex,
        if (!(x = parse_merge_name(pat, NULL, 0)) || *x != '/')
                return 0;
 
+       if (DEBUG_GTE(FILTER, 2)) {
+               rprintf(FINFO, "[%s] performing parent_dirscan for mergelist #%d%s\n",
+                       who_am_i(), mergelist_num, lp->debug_type);
+       }
        y = strrchr(x, '/');
        *y = '\0';
        ex->pattern = strdup(y+1);
@@ -373,7 +437,7 @@ static BOOL setup_merge_file(struct filter_struct *ex,
        else
                pathjoin(buf, MAXPATHLEN, dirbuf, x);
 
-       len = clean_fname(buf, 1);
+       len = clean_fname(buf, CFN_COLLAPSE_DOT_DOT_DIRS);
        if (len != 1 && len < MAXPATHLEN-1) {
                buf[len++] = '/';
                buf[len] = '\0';
@@ -391,37 +455,63 @@ static BOOL setup_merge_file(struct filter_struct *ex,
                dirbuf_len = y - dirbuf;
                strlcpy(x, ex->pattern, MAXPATHLEN - (x - buf));
                parse_filter_file(lp, buf, ex->match_flags, XFLG_ANCHORED2ABS);
-               if (ex->match_flags & MATCHFLG_NO_INHERIT)
+               if (ex->match_flags & MATCHFLG_NO_INHERIT) {
+                       /* Free the undesired rules to clean up any per-dir
+                        * mergelists they defined.  Otherwise pop_local_filters
+                        * may crash trying to restore nonexistent state for
+                        * those mergelists. */
+                       free_filters(lp->head);
                        lp->head = NULL;
+               }
                lp->tail = NULL;
                strlcpy(y, save, MAXPATHLEN);
                while ((*x++ = *y++) != '/') {}
        }
+       /* Save current head for freeing when the mergelist becomes inactive. */
+       lp->parent_dirscan_head = lp->head;
        parent_dirscan = False;
+       if (DEBUG_GTE(FILTER, 2)) {
+               rprintf(FINFO, "[%s] completed parent_dirscan for mergelist #%d%s\n",
+                       who_am_i(), mergelist_num, lp->debug_type);
+       }
        free(pat);
        return 1;
 }
 
+struct local_filter_state {
+       int mergelist_cnt;
+       struct filter_list_struct mergelists[0];
+};
+
 /* Each time rsync changes to a new directory it call this function to
  * handle all the per-dir merge-files.  The "dir" value is the current path
  * relative to curr_dir (which might not be null-terminated).  We copy it
  * into dirbuf so that we can easily append a file name on the end. */
 void *push_local_filters(const char *dir, unsigned int dirlen)
 {
-       struct filter_list_struct *ap, *push;
+       struct local_filter_state *push;
        int i;
 
        set_filter_dir(dir, dirlen);
+       if (DEBUG_GTE(FILTER, 2)) {
+               rprintf(FINFO, "[%s] pushing local filters for %s\n",
+                       who_am_i(), dirbuf);
+       }
 
-       if (!mergelist_cnt)
+       if (!mergelist_cnt) {
+               /* No old state to save and no new merge files to push. */
                return NULL;
+       }
 
-       push = new_array(struct filter_list_struct, mergelist_cnt);
+       push = (struct local_filter_state *)new_array(char,
+                         sizeof (struct local_filter_state)
+                       + mergelist_cnt * sizeof (struct filter_list_struct));
        if (!push)
                out_of_memory("push_local_filters");
 
-       for (i = 0, ap = push; i < mergelist_cnt; i++) {
-               memcpy(ap++, mergelist_parents[i]->u.mergelist,
+       push->mergelist_cnt = mergelist_cnt;
+       for (i = 0; i < mergelist_cnt; i++) {
+               memcpy(&push->mergelists[i], mergelist_parents[i]->u.mergelist,
                       sizeof (struct filter_list_struct));
        }
 
@@ -431,9 +521,9 @@ void *push_local_filters(const char *dir, unsigned int dirlen)
                struct filter_struct *ex = mergelist_parents[i];
                struct filter_list_struct *lp = ex->u.mergelist;
 
-               if (verbose > 2) {
-                       rprintf(FINFO, "[%s] pushing filter list%s\n",
-                               who_am_i(), lp->debug_type);
+               if (DEBUG_GTE(FILTER, 2)) {
+                       rprintf(FINFO, "[%s] pushing mergelist #%d%s\n",
+                               who_am_i(), i, lp->debug_type);
                }
 
                lp->tail = NULL; /* Switch any local rules to inherited. */
@@ -442,7 +532,7 @@ void *push_local_filters(const char *dir, unsigned int dirlen)
 
                if (ex->match_flags & MATCHFLG_FINISH_SETUP) {
                        ex->match_flags &= ~MATCHFLG_FINISH_SETUP;
-                       if (setup_merge_file(ex, lp))
+                       if (setup_merge_file(i, ex, lp))
                                set_filter_dir(dir, dirlen);
                }
 
@@ -452,7 +542,7 @@ void *push_local_filters(const char *dir, unsigned int dirlen)
                                          XFLG_ANCHORED2ABS);
                } else {
                        io_error |= IOERR_GENERAL;
-                       rprintf(FINFO,
+                       rprintf(FERROR,
                            "cannot add local filter rules in long-named directory: %s\n",
                            full_fname(dirbuf));
                }
@@ -464,26 +554,52 @@ void *push_local_filters(const char *dir, unsigned int dirlen)
 
 void pop_local_filters(void *mem)
 {
-       struct filter_list_struct *ap, *pop = (struct filter_list_struct*)mem;
+       struct local_filter_state *pop = (struct local_filter_state *)mem;
        int i;
+       int old_mergelist_cnt = pop ? pop->mergelist_cnt : 0;
+
+       if (DEBUG_GTE(FILTER, 2))
+               rprintf(FINFO, "[%s] popping local filters\n", who_am_i());
 
        for (i = mergelist_cnt; i-- > 0; ) {
                struct filter_struct *ex = mergelist_parents[i];
                struct filter_list_struct *lp = ex->u.mergelist;
 
-               if (verbose > 2) {
-                       rprintf(FINFO, "[%s] popping filter list%s\n",
-                               who_am_i(), lp->debug_type);
+               if (DEBUG_GTE(FILTER, 2)) {
+                       rprintf(FINFO, "[%s] popping mergelist #%d%s\n",
+                               who_am_i(), i, lp->debug_type);
                }
 
                clear_filter_list(lp);
+
+               if (i >= old_mergelist_cnt) {
+                       /* This mergelist does not exist in the state to be
+                        * restored.  Free its parent_dirscan list to clean up
+                        * any per-dir mergelists defined there so we don't
+                        * crash trying to restore nonexistent state for them
+                        * below.  (Counterpart to setup_merge_file call in
+                        * push_local_filters.  Must be done here, not in
+                        * free_filter, for LIFO order.) */
+                       if (DEBUG_GTE(FILTER, 2)) {
+                               rprintf(FINFO, "[%s] freeing parent_dirscan filters of mergelist #%d%s\n",
+                                       who_am_i(), i, ex->u.mergelist->debug_type);
+                       }
+                       free_filters(lp->parent_dirscan_head);
+                       lp->parent_dirscan_head = NULL;
+               }
        }
 
-       if (!pop)
+       /* If we cleaned things up properly, the only still-active mergelists
+        * should be those with a state to be restored. */
+       assert(mergelist_cnt == old_mergelist_cnt);
+
+       if (!pop) {
+               /* No state to restore. */
                return;
+       }
 
-       for (i = 0, ap = pop; i < mergelist_cnt; i++) {
-               memcpy(mergelist_parents[i]->u.mergelist, ap++,
+       for (i = 0; i < mergelist_cnt; i++) {
+               memcpy(mergelist_parents[i]->u.mergelist, &pop->mergelists[i],
                       sizeof (struct filter_list_struct));
        }
 
@@ -518,15 +634,14 @@ void change_local_filter_dir(const char *dname, int dlen, int dir_depth)
        filt_array[cur_depth] = push_local_filters(dname, dlen);
 }
 
-static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
+static int rule_matches(const char *fname, struct filter_struct *ex, int name_is_dir)
 {
        int slash_handling, str_cnt = 0, anchored_match = 0;
        int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
        char *p, *pattern = ex->pattern;
        const char *strings[16]; /* more than enough */
+       const char *name = fname + (*fname == '/');
 
-       if (*name == '/')
-               name++;
        if (!*name)
                return 0;
 
@@ -536,13 +651,13 @@ static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
                 * just match the name portion of the path. */
                if ((p = strrchr(name,'/')) != NULL)
                        name = p+1;
-       } else if (ex->match_flags & MATCHFLG_ABS_PATH && *name != '/'
+       } else if (ex->match_flags & MATCHFLG_ABS_PATH && *fname != '/'
            && curr_dir_len > module_dirlen + 1) {
                /* If we're matching against an absolute-path pattern,
                 * we need to prepend our full path info. */
                strings[str_cnt++] = curr_dir + module_dirlen + 1;
                strings[str_cnt++] = "/";
-       } else if (ex->match_flags & MATCHFLG_WILD2_PREFIX && *name != '/') {
+       } else if (ex->match_flags & MATCHFLG_WILD2_PREFIX && *fname != '/') {
                /* Allow "**"+"/" to match at the start of the string. */
                strings[str_cnt++] = "/";
        }
@@ -598,19 +713,19 @@ static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
 }
 
 
-static void report_filter_result(char const *name,
-                                 struct filter_struct const *ent,
-                                 int name_is_dir, const char *type)
+static void report_filter_result(enum logcode code, char const *name,
+                                struct filter_struct const *ent,
+                                int name_is_dir, const char *type)
 {
        /* If a trailing slash is present to match only directories,
         * then it is stripped out by add_rule().  So as a special
         * case we add it back in here. */
 
-       if (verbose >= 2) {
+       if (DEBUG_GTE(FILTER, 1)) {
                static char *actions[2][2]
                    = { {"show", "hid"}, {"risk", "protect"} };
                const char *w = who_am_i();
-               rprintf(FINFO, "[%s] %sing %s %s because of pattern %s%s%s\n",
+               rprintf(code, "[%s] %sing %s %s because of pattern %s%s%s\n",
                    w, actions[*w!='s'][!(ent->match_flags&MATCHFLG_INCLUDE)],
                    name_is_dir ? "directory" : "file", name, ent->pattern,
                    ent->match_flags & MATCHFLG_DIRECTORY ? "/" : "", type);
@@ -622,7 +737,8 @@ static void report_filter_result(char const *name,
  * Return -1 if file "name" is defined to be excluded by the specified
  * exclude list, 1 if it is included, and 0 if it was not matched.
  */
-int check_filter(struct filter_list_struct *listp, char *name, int name_is_dir)
+int check_filter(struct filter_list_struct *listp, enum logcode code,
+                const char *name, int name_is_dir)
 {
        struct filter_struct *ent;
 
@@ -630,22 +746,22 @@ int check_filter(struct filter_list_struct *listp, char *name, int name_is_dir)
                if (ignore_perishable && ent->match_flags & MATCHFLG_PERISHABLE)
                        continue;
                if (ent->match_flags & MATCHFLG_PERDIR_MERGE) {
-                       int rc = check_filter(ent->u.mergelist, name,
+                       int rc = check_filter(ent->u.mergelist, code, name,
                                              name_is_dir);
                        if (rc)
                                return rc;
                        continue;
                }
                if (ent->match_flags & MATCHFLG_CVS_IGNORE) {
-                       int rc = check_filter(&cvs_filter_list, name,
+                       int rc = check_filter(&cvs_filter_list, code, name,
                                              name_is_dir);
                        if (rc)
                                return rc;
                        continue;
                }
                if (rule_matches(name, ent, name_is_dir)) {
-                       report_filter_result(name, ent, name_is_dir,
-                                             listp->debug_type);
+                       report_filter_result(code, name, ent, name_is_dir,
+                                            listp->debug_type);
                        return ent->match_flags & MATCHFLG_INCLUDE ? 1 : -1;
                }
        }
@@ -900,7 +1016,7 @@ static char default_cvsignore[] =
        " *.a *.olb *.o *.obj *.so *.exe"
        " *.Z *.elc *.ln core"
        /* The rest we added to suit ourself. */
-       " .svn/ .bzr/";
+       " .svn/ .git/ .bzr/";
 
 static void get_cvs_excludes(uint32 mflags)
 {
@@ -949,7 +1065,7 @@ void parse_rule(struct filter_list_struct *listp, const char *pattern,
                }
 
                if (new_mflags & MATCHFLG_CLEAR_LIST) {
-                       if (verbose > 2) {
+                       if (DEBUG_GTE(FILTER, 2)) {
                                rprintf(FINFO,
                                        "[%s] clearing filter list%s\n",
                                        who_am_i(), listp->debug_type);
@@ -1011,10 +1127,10 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
                return;
 
        if (*fname != '-' || fname[1] || am_server) {
-               if (server_filter_list.head) {
+               if (daemon_filter_list.head) {
                        strlcpy(line, fname, sizeof line);
-                       clean_fname(line, 1);
-                       if (check_filter(&server_filter_list, line, 0) < 0)
+                       clean_fname(line, CFN_COLLAPSE_DOT_DOT_DIRS);
+                       if (check_filter(&daemon_filter_list, FLOG, line, 0) < 0)
                                fp = NULL;
                        else
                                fp = fopen(line, "rb");
@@ -1023,7 +1139,7 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
        } else
                fp = stdin;
 
-       if (verbose > 2) {
+       if (DEBUG_GTE(FILTER, 2)) {
                rprintf(FINFO, "[%s] parse_filter_file(%s,%x,%x)%s\n",
                        who_am_i(), fname, mflags, xflags,
                        fp ? "" : " [not found]");