📄 bsd-glob.c
字号:
qpatnext = pattern;#endif oldpathc = pglob->gl_pathc; bufnext = patbuf; /* We don't need to check for buffer overflow any more. */ while ((c = *qpatnext++) != EOS) { switch (c) { case LBRACKET: c = *qpatnext; if (c == NOT) ++qpatnext; if (*qpatnext == EOS || g_strchr((const Char *) qpatnext + 1, RBRACKET) == NULL) { *bufnext++ = LBRACKET; if (c == NOT) --qpatnext; break; } *bufnext++ = M_SET; if (c == NOT) *bufnext++ = M_NOT; c = *qpatnext++; do { *bufnext++ = CHAR(c); if (*qpatnext == RANGE && (c = qpatnext[1]) != RBRACKET) { *bufnext++ = M_RNG; *bufnext++ = CHAR(c); qpatnext += 2; } } while ((c = *qpatnext++) != RBRACKET); pglob->gl_flags |= GLOB_MAGCHAR; *bufnext++ = M_END; break; case QUESTION: pglob->gl_flags |= GLOB_MAGCHAR; *bufnext++ = M_ONE; break; case STAR: pglob->gl_flags |= GLOB_MAGCHAR; /* collapse adjacent stars to one, * to avoid exponential behavior */ if (bufnext == patbuf || bufnext[-1] != M_ALL) { *bufnext++ = M_ALL; } break; default: *bufnext++ = CHAR(c); break; } } *bufnext = EOS; if ((err = glob1(patbuf, patbuf + MAXPATHLEN, pglob, &limit)) != 0) { return (err); } /* * If there was no match we are going to append the pattern * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified * and the pattern did not contain any magic characters * GLOB_NOMAGIC is there just for compatibility with csh. */ if (pglob->gl_pathc == oldpathc) { return (GLOB_NOMATCH); } if (!(pglob->gl_flags & GLOB_NOSORT)) { qsort(pglob->gl_pathv + oldpathc, (size_t) (pglob->gl_pathc - oldpathc), sizeof (char *), compare); } return 0;}static int compare(const void *p, const void *q){ return (strcmp(*(const char **) p, *(const char **) q));}static intglob1(Char * pattern, Char * pattern_last, glob_t * pglob, size_t * limitp){ Char pathbuf[MAXPATHLEN + 1]; /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ if (*pattern == EOS) { return 0; } return (glob2(pathbuf, pathbuf + MAXPATHLEN, pathbuf, pathbuf + MAXPATHLEN, pattern, pattern_last, pglob, limitp, 0));}/* * The functions glob2 and glob3 are mutually recursive; there is one level * of recursion for each segment in the pattern that contains one or more * meta characters. */static intglob2(Char * pathbuf, Char * pathbuf_last, Char * pathend, Char * pathend_last, Char * pattern, Char * pattern_last, glob_t * pglob, size_t * limitp, int recursion){ struct stat sb; Char *p, *q; int anymeta; if (pglob->gl_maxdepth > 0 && recursion > pglob->gl_maxdepth) { errno = 0; return (GLOB_NOSPACE); } /* * Loop over pattern segments until end of pattern or until * segment with meta character found. */ for (anymeta = 0;;) { if (*pattern == EOS) { /* End of pattern? */ *pathend = EOS; if (g_lstat(pathbuf, &sb)) return 0; ++pglob->gl_matchc; return (globextend(pathbuf, pglob, limitp)); } /* Find end of next segment, copy tentatively to pathend. */ q = pathend; p = pattern; while (*p != EOS && *p != SEP) { if (ismeta(*p)) anymeta = 1; if (q + 1 > pathend_last) return 1; *q++ = *p++; } if (!anymeta) { /* No expansion, do next segment. */ pathend = q; pattern = p; while (*pattern == SEP) { if (pathend + 1 > pathend_last) return 1; *pathend++ = *pattern++; } } else /* Need expansion, recurse. */ return (glob3(pathbuf, pathbuf_last, pathend, pathend_last, pattern, p, pattern_last, pglob, limitp, recursion + 1)); } /* NOTREACHED */}static intglob3(Char * pathbuf, Char * pathbuf_last, Char * pathend, Char * pathend_last, Char * pattern, Char * restpattern, Char * restpattern_last, glob_t * pglob, size_t * limitp, int recursion){ register struct dirent *dp; DIR *dirp; int err; char buf[MAXPATHLEN + 1]; if (pathend > pathend_last) return 1; *pathend = EOS; errno = 0; if (pglob->gl_maxdepth > 0 && recursion > pglob->gl_maxdepth) { return (GLOB_NOSPACE); } if ((dirp = g_opendir(pathbuf)) == NULL) { /* TODO: don't call for ENOENT or ENOTDIR? */ if (pglob->gl_errfunc) { if (g_Ctoc(pathbuf, buf, sizeof (buf))) { return (GLOB_ABORTED); } if (pglob->gl_errfunc(buf, errno) || pglob->gl_flags & GLOB_ERR) { return (GLOB_ABORTED); } } return 0; } err = 0; while ((dp = (*readdir) (dirp))) { register unsigned char *sc; register Char *dc; /* Initial DOT must be matched literally. */ if (dp->d_name[0] == DOT && *pattern != DOT) { continue; }#ifndef GLOB_UNPRINTABLE if (checkprintable(dp->d_name) != 0) { continue; }#endif dc = pathend; sc = (unsigned char *) dp->d_name; while (dc < pathend_last && (*dc++ = *sc++) != EOS); if (dc >= pathend_last) { *dc = EOS; err = 1; break; } if (!match(pathend, pattern, restpattern)) { *pathend = EOS; continue; } err = glob2(pathbuf, pathbuf_last, --dc, pathend_last, restpattern, restpattern_last, pglob, limitp, recursion + 1); if (err) break; } closedir(dirp); return (err);}/* * Extend the gl_pathv member of a glob_t structure to accommodate a new item, * add the new item, and update gl_pathc. * * This assumes the BSD realloc, which only copies the block when its size * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic * behavior. * * Return 0 if new item added, error code if memory couldn't be allocated. * * Invariant of the glob_t structure: * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and * gl_pathv points to (gl_offs + gl_pathc + 1) items. */static int globextend(const Char * path, glob_t * pglob, size_t * limitp){ register char **pathv; unsigned int newsize; size_t len; char *copy; const Char *p; if (pglob->gl_maxfiles != (unsigned long) -1) { if (pglob->gl_maxfiles == 0) { return 0; } pglob->gl_maxfiles--; } newsize = sizeof (*pathv) * (2 + pglob->gl_pathc); pathv = pglob->gl_pathv ? realloc((char *) pglob->gl_pathv, newsize) : malloc(newsize); if (pathv == NULL) { free(pglob->gl_pathv); pglob->gl_pathv = NULL; return (GLOB_NOSPACE); } pglob->gl_pathv = pathv; for (p = path; *p++;); len = (size_t) (p - path); *limitp += len; if ((copy = malloc(len)) != NULL) { if (g_Ctoc(path, copy, len)) { free(copy); return (GLOB_NOSPACE); } pathv[pglob->gl_pathc++] = copy; } pathv[pglob->gl_pathc] = NULL;#ifdef USELESS_FOR_PUREFTPD if ((pglob->gl_flags & GLOB_LIMIT) && newsize + *limitp >= ARG_MAX) { errno = 0; return (GLOB_NOSPACE); }#endif return (copy == NULL ? GLOB_NOSPACE : 0);}/* * pattern matching function for filenames. Each occurrence of the * * pattern causes a recursion level. */static intmatch(register Char * name, register Char * pat, register Char * patend){ int ok, negate_range; Char c, k; while (pat < patend) { c = *pat++; switch (c & M_MASK) { case M_ALL: if (pat == patend) return 1; do { if (match(name, pat, patend)) { return 1; } } while (*name++ != EOS); return 0; case M_ONE: if (*name++ == EOS) { return 0; } break; case M_SET: ok = 0; if ((k = *name++) == EOS) return 0; if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) { ++pat; } while (((c = *pat++) & M_MASK) != M_END) { if ((*pat & M_MASK) == M_RNG) { if (c <= k && k <= pat[1]) ok = 1; pat += 2; } else if (c == k) { ok = 1; } } if (ok == negate_range) { return 0; } break; default: if (*name++ != c) { return 0; } break; } } return (*name == EOS);}/* Free allocated data belonging to a glob_t structure. */void globfree(glob_t * pglob){ register int i; register char **pp; if (pglob->gl_pathv != NULL) { pp = pglob->gl_pathv; for (i = pglob->gl_pathc; i--; ++pp) { free(*pp); } free(pglob->gl_pathv); pglob->gl_pathv = NULL; }}static DIR *g_opendir(register Char * str){ char buf[MAXPATHLEN + 1]; if (!*str) { buf[0] = '.'; buf[1] = 0; /* safe : sizeof buf > 2 */ } else { if (g_Ctoc(str, buf, sizeof (buf))) return NULL; } return (opendir(buf));}static int g_lstat(register Char * fn, struct stat *sb){ char buf[MAXPATHLEN + 1]; if (g_Ctoc(fn, buf, sizeof (buf))) return -1; return (lstat(buf, sb));}static const Char *g_strchr(const Char * str, int ch){ do { if (*str == (Char) ch) return (str); } while (*str++); return NULL;}static int g_Ctoc(register const Char * str, char *buf, unsigned int len){ while (len--) { if ((*buf++ = (char) *str++) == EOS) return 0; } return 1;}#elseextern signed char v6ready;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -