/* an extended version of fnmatch1() which uses rules described in the gtsearch documentation */ static int fnmatch2 (char *patt, char *str, int notused) { int matched; char *p, *p1, *host, *path, *host_pattern, *path_pattern; p = NULL; /* see if patt contains any asterisks or if pattern begins with an asterisk */ if (patt[0] == '*' || strchr (patt, '*') == NULL) { /* see if pattern contains slashes */ p = strchr (patt, '/'); if (p == NULL) { host_pattern = patt; path_pattern = NULL; } else { path_pattern = strdup (p); *p = '\0'; host_pattern = patt; } } /* just an old-style pattern without any new extensions */ else { return fnmatch1 (patt, str, 0); } /* split test string to hostname and path */ p1 = strchr (str, '/'); if (p1 == NULL) { host = str; path = NULL; } else { path = strdup (p1); *p1 = '\0'; host = str; } /* now do the match */ matched = TRUE; if (fnmatch1 (host_pattern, host, 0) != 0) matched = FALSE; if (/*matched &&*/ path != NULL && path_pattern != NULL && fnmatch1 (path_pattern, path, 0) != 0) matched = FALSE; /* cleanup: restore original pattern if screwed, free allocated memory */ if (p != NULL) *p = '/'; if (p1 != NULL) *p1 = '/'; if (path_pattern != NULL) free (path_pattern); if (path != NULL) free (path); return matched ? 0 : FNM1_NOMATCH; }
int fnmatch(const char *pattern, const char *string, int flags) { static const mbstate_t initial; return (fnmatch1(pattern, string, string, flags, initial, initial)); }
void clear_tmp (void) { char sample[MAX_PATH], *p; DIR *d; struct dirent *e; struct stat st; time_t now; time (&now); // find tmp files directory tmpnam1 (sample); p = strrchr (sample, '/'); *p = '\0'; // get list of nftp* files in it d = opendir (sample); if (d == NULL) return; *p = '/'; while (TRUE) { e = readdir (d); if (e == NULL) break; if (strcmp (e->d_name, ".") == 0) continue; if (strcmp (e->d_name, "..") == 0) continue; if (!fnmatch1 ("nftp????.???", e->d_name, 0)) continue; if (strspn (e->d_name, "nftp0123456789.") != strlen (e->d_name)) continue; strcpy (p+1, e->d_name); if (stat (sample, &st)) continue; if (st.st_mtime > now-7*24*60*60) continue; remove (sample); } }
static int fnmatch1(const char *pattern, const char *string, const char *stringstart, int flags, mbstate_t patmbs, mbstate_t strmbs) { char *newp; char c; wchar_t pc, sc; size_t pclen, sclen; for (;;) { pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs); if (pclen == (size_t)-1 || pclen == (size_t)-2) return (FNM_NOMATCH); pattern += pclen; sclen = mbrtowc(&sc, string, MB_LEN_MAX, &strmbs); if (sclen == (size_t)-1 || sclen == (size_t)-2) { sc = (unsigned char)*string; sclen = 1; memset(&strmbs, 0, sizeof(strmbs)); } switch (pc) { case EOS: if ((flags & FNM_LEADING_DIR) && sc == '/') return (0); return (sc == EOS ? 0 : FNM_NOMATCH); case '?': if (sc == EOS) return (FNM_NOMATCH); if (sc == '/' && (flags & FNM_PATHNAME)) return (FNM_NOMATCH); if (sc == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) return (FNM_NOMATCH); string += sclen; break; case '*': c = *pattern; /* Collapse multiple stars. */ while (c == '*') c = *++pattern; if (sc == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) return (FNM_NOMATCH); /* Optimize for pattern with * at end or before /. */ if (c == EOS) if (flags & FNM_PATHNAME) return ((flags & FNM_LEADING_DIR) || strchr(string, '/') == NULL ? 0 : FNM_NOMATCH); else return (0); else if (c == '/' && flags & FNM_PATHNAME) { if ((string = strchr(string, '/')) == NULL) return (FNM_NOMATCH); break; } /* General case, use recursion. */ while (sc != EOS) { if (!fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs)) return (0); sclen = mbrtowc(&sc, string, MB_LEN_MAX, &strmbs); if (sclen == (size_t)-1 || sclen == (size_t)-2) { sc = (unsigned char)*string; sclen = 1; memset(&strmbs, 0, sizeof(strmbs)); } if (sc == '/' && flags & FNM_PATHNAME) break; string += sclen; } return (FNM_NOMATCH); case '[': if (sc == EOS) return (FNM_NOMATCH); if (sc == '/' && (flags & FNM_PATHNAME)) return (FNM_NOMATCH); if (sc == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) return (FNM_NOMATCH); switch (rangematch(pattern, sc, flags, &newp, &patmbs)) { case RANGE_ERROR: goto norm; case RANGE_MATCH: pattern = newp; break; case RANGE_NOMATCH: return (FNM_NOMATCH); } string += sclen; break; case '\\': if (!(flags & FNM_NOESCAPE)) { pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs); if (pclen == (size_t)-1 || pclen == (size_t)-2) return (FNM_NOMATCH); pattern += pclen; } /* FALLTHROUGH */ default: norm: if (pc == sc) ; else if ((flags & FNM_CASEFOLD) && (towlower(pc) == towlower(sc))) ; else return (FNM_NOMATCH); string += sclen; break; } } /* NOTREACHED */ }