/* * Again, mimic gtar: inclusions are always anchored (have to match * the beginning of the path) even though exclusions are not anchored. */ static int match_inclusion(struct match *match, const char *pathname) { #if 0 return (lafe_pathmatch(match->pattern, pathname, 0)); #else return (lafe_pathmatch(match->pattern, pathname, PATHMATCH_NO_ANCHOR_END)); #endif }
/* * This is a little odd, but it matches the default behavior of * gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar' * */ static int match_exclusion(struct match *match, const char *pathname) { return (lafe_pathmatch(match->pattern, pathname, PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); }
static int pm(const char *p, const char *s, int flags) { const char *end; /* * Ignore leading './', './/', '././', etc. */ if (s[0] == '.' && s[1] == '/') s = pm_slashskip(s + 1); if (p[0] == '.' && p[1] == '/') p = pm_slashskip(p + 1); for (;;) { switch (*p) { case '\0': if (s[0] == '/') { if (flags & PATHMATCH_NO_ANCHOR_END) return (1); /* "dir" == "dir/" == "dir/." */ s = pm_slashskip(s); } return (*s == '\0'); case '?': /* ? always succeeds, unless we hit end of 's' */ if (*s == '\0') return (0); break; case '*': /* "*" == "**" == "***" ... */ while (*p == '*') ++p; /* Trailing '*' always succeeds. */ if (*p == '\0') return (1); while (*s) { if (lafe_pathmatch(p, s, flags)) return (1); ++s; } return (0); case '[': /* * Find the end of the [...] character class, * ignoring \] that might occur within the class. */ end = p + 1; while (*end != '\0' && *end != ']') { if (*end == '\\' && end[1] != '\0') ++end; ++end; } if (*end == ']') { /* We found [...], try to match it. */ if (!pm_list(p + 1, end, *s, flags)) return (0); p = end; /* Jump to trailing ']' char. */ break; } else /* No final ']', so just match '['. */ if (*p != *s) return (0); break; case '\\': /* Trailing '\\' matches itself. */ if (p[1] == '\0') { if (*s != '\\') return (0); } else { ++p; if (*p != *s) return (0); } break; case '/': if (*s != '/' && *s != '\0') return (0); /* Note: pattern "/\./" won't match "/"; * pm_slashskip() correctly stops at backslash. */ p = pm_slashskip(p); s = pm_slashskip(s); if (*p == '\0' && (flags & PATHMATCH_NO_ANCHOR_END)) return (1); --p; /* Counteract the increment below. */ --s; break; case '$': /* '$' is special only at end of pattern and only * if PATHMATCH_NO_ANCHOR_END is specified. */ if (p[1] == '\0' && (flags & PATHMATCH_NO_ANCHOR_END)){ /* "dir" == "dir/" == "dir/." */ return (*pm_slashskip(s) == '\0'); } /* Otherwise, '$' is not special. */ /* FALL THROUGH */ default: if (*p != *s) return (0); break; } ++p; ++s; } }