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 daemon_filter_list = { 0, 0, " [daemon]" };
/* Need room enough for ":MODS " prefix plus some room to grow. */
#define MAX_RULE_PREFIX (16)
#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
{
struct filter_struct *ret;
const char *cp;
- unsigned int ex_len;
+ unsigned int pre_len, suf_len, slash_cnt = 0;
if (verbose > 2) {
rprintf(FINFO, "[%s] add_rule(%s%.*s%s)%s\n",
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;
}
}
- 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;
out_of_memory("add_rule");
}
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;
strlcpy(to, merge_file, *len_ptr + 1);
merge_file = to;
}
- if (!sanitize_path(fn, merge_file, r, dirbuf_depth)) {
+ if (!sanitize_path(fn, merge_file, r, dirbuf_depth, SP_DEFAULT)) {
rprintf(FERROR, "merge-file name overflows: %s\n",
merge_file);
return NULL;
filt_array[cur_depth] = push_local_filters(dname, dlen);
}
-static int rule_matches(char *fname, 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 */
- char *name = fname + (*fname == '/');
+ const char *name = fname + (*fname == '/');
if (!*name)
return 0;
* 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, const char *name, int name_is_dir)
{
struct filter_struct *ent;
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, CFN_COLLAPSE_DOT_DOT_DIRS);
- if (check_filter(&server_filter_list, line, 0) < 0)
+ if (check_filter(&daemon_filter_list, line, 0) < 0)
fp = NULL;
else
fp = fopen(line, "rb");