+static int check_one_exclude(char *name, struct exclude_struct *ex,
+ int name_is_dir)
+{
+ char *p;
+ int match_start = 0;
+ char *pattern = ex->pattern;
+
+ /* If the pattern does not have any slashes AND it does not have
+ * a "**" (which could match a slash), then we just match the
+ * name portion of the path. */
+ if (!ex->slash_cnt && !(ex->match_flags & MATCHFLG_WILD2)) {
+ if ((p = strrchr(name,'/')) != NULL)
+ name = p+1;
+ }
+ else if (ex->match_flags & MATCHFLG_ABS_PATH && *name != '/') {
+ static char full_name[MAXPATHLEN];
+ int plus = curr_dir[1] == '\0'? 1 : 0;
+ pathjoin(full_name, sizeof full_name, curr_dir+plus, name);
+ name = full_name;
+ }
+
+ if (!name[0]) return 0;
+
+ if (ex->match_flags & MATCHFLG_DIRECTORY && !name_is_dir)
+ return 0;
+
+ if (*pattern == '/') {
+ match_start = 1;
+ pattern++;
+ if (*name == '/')
+ name++;
+ }
+
+ if (ex->match_flags & MATCHFLG_WILD) {
+ /* A non-anchored match with an infix slash and no "**"
+ * needs to match the last slash_cnt+1 name elements. */
+ if (!match_start && ex->slash_cnt
+ && !(ex->match_flags & MATCHFLG_WILD2)) {
+ int cnt = ex->slash_cnt + 1;
+ for (p = name + strlen(name) - 1; p >= name; p--) {
+ if (*p == '/' && !--cnt)
+ break;
+ }
+ name = p+1;
+ }
+ if (wildmatch(pattern, name))
+ return 1;
+ if (ex->match_flags & MATCHFLG_WILD2_PREFIX) {
+ /* If the **-prefixed pattern has a '/' as the next
+ * character, then try to match the rest of the
+ * pattern at the root. */
+ if (pattern[2] == '/' && wildmatch(pattern+3, name))
+ return 1;
+ }
+ else if (!match_start && ex->match_flags & MATCHFLG_WILD2) {
+ /* A non-anchored match with an infix or trailing "**"
+ * (but not a prefixed "**") needs to try matching
+ * after every slash. */
+ while ((name = strchr(name, '/')) != NULL) {
+ name++;
+ if (wildmatch(pattern, name))
+ return 1;
+ }
+ }
+ } else if (match_start) {
+ if (strcmp(name,pattern) == 0)
+ return 1;
+ } 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 1;
+ }
+ }
+
+ return 0;