Added a command-line override for daemon config parameters:
[rsync/rsync.git] / exclude.c
index 4c7a847..9672bf9 100644 (file)
--- a/exclude.c
+++ b/exclude.c
@@ -22,7 +22,6 @@
 
 #include "rsync.h"
 
-extern int verbose;
 extern int am_server;
 extern int am_sender;
 extern int eol_nulls;
@@ -37,7 +36,7 @@ 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;
 
@@ -52,6 +51,8 @@ struct filter_list_struct daemon_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
@@ -119,9 +120,9 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
 {
        struct filter_struct *ret;
        const char *cp;
-       unsigned int pre_len, slash_cnt = 0;
+       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,
@@ -166,7 +167,15 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
        } else
                pre_len = 0;
 
-       if (!(ret->pattern = new_array(char, pre_len + pat_len + 1)))
+       /* 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
+               suf_len = 0;
+
+       if (!(ret->pattern = new_array(char, pre_len + pat_len + suf_len + 1)))
                out_of_memory("add_rule");
        if (pre_len) {
                memcpy(ret->pattern, dirbuf + module_dirlen, pre_len);
@@ -177,6 +186,11 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
        }
        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;
@@ -317,12 +331,13 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
 
        /* 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);
+               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);
        }
 
@@ -439,7 +454,7 @@ 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) {
+               if (DEBUG_GTE(FILTER, 2)) {
                        rprintf(FINFO, "[%s] pushing filter list%s\n",
                                who_am_i(), lp->debug_type);
                }
@@ -479,7 +494,7 @@ void pop_local_filters(void *mem)
                struct filter_struct *ex = mergelist_parents[i];
                struct filter_list_struct *lp = ex->u.mergelist;
 
-               if (verbose > 2) {
+               if (DEBUG_GTE(FILTER, 2)) {
                        rprintf(FINFO, "[%s] popping filter list%s\n",
                                who_am_i(), lp->debug_type);
                }
@@ -605,7 +620,7 @@ static int rule_matches(const char *fname, struct filter_struct *ex, int name_is
 }
 
 
-static void report_filter_result(char const *name,
+static void report_filter_result(enum logcode code, char const *name,
                                  struct filter_struct const *ent,
                                  int name_is_dir, const char *type)
 {
@@ -613,11 +628,11 @@ static void report_filter_result(char const *name,
         * 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);
@@ -629,7 +644,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, const 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;
 
@@ -637,22 +653,22 @@ int check_filter(struct filter_list_struct *listp, const char *name, int name_is
                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;
                }
        }
@@ -956,7 +972,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);
@@ -1021,7 +1037,7 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
                if (daemon_filter_list.head) {
                        strlcpy(line, fname, sizeof line);
                        clean_fname(line, CFN_COLLAPSE_DOT_DOT_DIRS);
-                       if (check_filter(&daemon_filter_list, line, 0) < 0)
+                       if (check_filter(&daemon_filter_list, FLOG, line, 0) < 0)
                                fp = NULL;
                        else
                                fp = fopen(line, "rb");
@@ -1030,7 +1046,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]");