/* Scan the list and let the last match determine the fate. * Return 1 for exclude, 0 for include and -1 for undecided. */ int excluded_from_list(const char *pathname, int pathlen, const char *basename, int *dtype, struct exclude_list *el) { int i; if (el->nr) { for (i = el->nr - 1; 0 <= i; i--) { struct exclude *x = el->excludes[i]; const char *exclude = x->pattern; int to_exclude = x->to_exclude; if (x->flags & EXC_FLAG_MUSTBEDIR) { if (*dtype == DT_UNKNOWN) *dtype = get_dtype(NULL, pathname, pathlen); if (*dtype != DT_DIR) continue; } if (x->flags & EXC_FLAG_NODIR) { /* match basename */ if (x->flags & EXC_FLAG_NOWILDCARD) { if (!strcmp_icase(exclude, basename)) return to_exclude; } else if (x->flags & EXC_FLAG_ENDSWITH) { if (x->patternlen - 1 <= pathlen && !strcmp_icase(exclude + 1, pathname + pathlen - x->patternlen + 1)) return to_exclude; } else { if (fnmatch_icase(exclude, basename, 0) == 0) return to_exclude; } } else { /* match with FNM_PATHNAME: * exclude has base (baselen long) implicitly * in front of it. */ int baselen = x->baselen; if (*exclude == '/') exclude++; if (pathlen < baselen || (baselen && pathname[baselen-1] != '/') || strncmp_icase(pathname, x->base, baselen)) continue; if (x->flags & EXC_FLAG_NOWILDCARD) { if (!strcmp_icase(exclude, pathname + baselen)) return to_exclude; } else { if (fnmatch_icase(exclude, pathname+baselen, FNM_PATHNAME) == 0) return to_exclude; } } } } return -1; /* undecided */ }
/* * Does 'match' match the given name? * A match is found if * * (1) the 'match' string is leading directory of 'name', or * (2) the 'match' string is a wildcard and matches 'name', or * (3) the 'match' string is exactly the same as 'name'. * * and the return value tells which case it was. * * It returns 0 when there is no match. */ static int match_one(const char *match, const char *name, int namelen) { int matchlen; int literal = limit_pathspec_to_literal(); /* If the match was just the prefix, we matched */ if (!*match) return MATCHED_RECURSIVELY; if (ignore_case) { for (;;) { unsigned char c1 = tolower(*match); unsigned char c2 = tolower(*name); if (c1 == '\0' || (!literal && is_glob_special(c1))) break; if (c1 != c2) return 0; match++; name++; namelen--; } } else { for (;;) { unsigned char c1 = *match; unsigned char c2 = *name; if (c1 == '\0' || (!literal && is_glob_special(c1))) break; if (c1 != c2) return 0; match++; name++; namelen--; } } /* * If we don't match the matchstring exactly, * we need to match by fnmatch */ matchlen = strlen(match); if (strncmp_icase(match, name, matchlen)) { if (literal) return 0; return !fnmatch_icase(match, name, 0) ? MATCHED_FNMATCH : 0; } if (namelen == matchlen) return MATCHED_EXACTLY; if (match[matchlen-1] == '/' || name[matchlen] == '/') return MATCHED_RECURSIVELY; return 0; }
int match_pathname(const char *pathname, int pathlen, const char *base, int baselen, const char *pattern, int prefix, int patternlen, int flags) { const char *name; int namelen; /* * match with FNM_PATHNAME; the pattern has base implicitly * in front of it. */ if (*pattern == '/') { pattern++; prefix--; } /* * baselen does not count the trailing slash. base[] may or * may not end with a trailing slash though. */ if (pathlen < baselen + 1 || (baselen && pathname[baselen] != '/') || strncmp_icase(pathname, base, baselen)) return 0; namelen = baselen ? pathlen - baselen - 1 : pathlen; name = pathname + pathlen - namelen; if (prefix) { /* * if the non-wildcard part is longer than the * remaining pathname, surely it cannot match. */ if (prefix > namelen) return 0; if (strncmp_icase(pattern, name, prefix)) return 0; pattern += prefix; name += prefix; namelen -= prefix; } return fnmatch_icase(pattern, name, FNM_PATHNAME) == 0; }
int match_basename(const char *basename, int basenamelen, const char *pattern, int prefix, int patternlen, int flags) { if (prefix == patternlen) { if (!strcmp_icase(pattern, basename)) return 1; } else if (flags & EXC_FLAG_ENDSWITH) { if (patternlen - 1 <= basenamelen && !strcmp_icase(pattern + 1, basename + basenamelen - patternlen + 1)) return 1; } else { if (fnmatch_icase(pattern, basename, 0) == 0) return 1; } return 0; }