+ /* The pattern matches only at the start of the path or name. */
+ slash_handling = 0;
+ }
+
+ if (ex->match_flags & MATCHFLG_WILD) {
+ if (wildmatch_array(pattern, strings, slash_handling))
+ return ret_match;
+ } else if (str_cnt > 1) {
+ if (litmatch_array(pattern, strings, slash_handling))
+ return ret_match;
+ } else if (anchored_match) {
+ if (strcmp(name, pattern) == 0)
+ return ret_match;
+ } else {
+ int l1 = strlen(name);
+ int l2 = strlen(pattern);
+ if (l2 <= l1 &&
+ strcmp(name+(l1-l2),pattern) == 0 &&
+ (l1==l2 || name[l1-(l2+1)] == '/')) {
+ return ret_match;
+ }
+ }
+
+ return !ret_match;
+}
+
+
+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 (DEBUG_GTE(FILTER, 1)) {
+ static char *actions[2][2]
+ = { {"show", "hid"}, {"risk", "protect"} };
+ const char *w = who_am_i();
+ 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);
+ }
+}
+
+
+/*
+ * 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, enum logcode code,
+ const char *name, int name_is_dir)
+{
+ struct filter_struct *ent;
+
+ for (ent = listp->head; ent; ent = ent->next) {
+ if (ignore_perishable && ent->match_flags & MATCHFLG_PERISHABLE)
+ continue;
+ if (ent->match_flags & MATCHFLG_PERDIR_MERGE) {
+ 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, code, name,
+ name_is_dir);
+ if (rc)
+ return rc;
+ continue;
+ }
+ if (rule_matches(name, ent, name_is_dir)) {
+ report_filter_result(code, name, ent, name_is_dir,
+ listp->debug_type);
+ return ent->match_flags & MATCHFLG_INCLUDE ? 1 : -1;
+ }
+ }
+
+ return 0;