140087Sbostic /* 240087Sbostic * Copyright (c) 1989 The Regents of the University of California. 340087Sbostic * All rights reserved. 440087Sbostic * 540087Sbostic * This code is derived from software contributed to Berkeley by 640087Sbostic * Guido van Rossum. 740087Sbostic * 842625Sbostic * %sccs.include.redist.c% 940087Sbostic */ 1040087Sbostic 1140087Sbostic #if defined(LIBC_SCCS) && !defined(lint) 12*50050Sbostic static char sccsid[] = "@(#)glob.c 5.10 (Berkeley) 06/17/91"; 1340087Sbostic #endif /* LIBC_SCCS and not lint */ 1440087Sbostic 1540087Sbostic /* 16*50050Sbostic * glob(3) -- a superset of the one defined in POSIX 1003.2. 1740087Sbostic * 1840087Sbostic * The [!...] convention to negate a range is supported (SysV, Posix, ksh). 1940087Sbostic * 2040087Sbostic * Optional extra services, controlled by flags not defined by POSIX: 2147590Sbostic * 2247590Sbostic * GLOB_QUOTE: 2347590Sbostic * Escaping convention: \ inhibits any special meaning the following 2447590Sbostic * character might have (except \ at end of string is retained). 2547590Sbostic * GLOB_MAGCHAR: 2648540Sbostic * Set in gl_flags if pattern contained a globbing character. 2747590Sbostic * gl_matchc: 2847590Sbostic * Number of matches in the current invocation of glob. 2940087Sbostic */ 3040087Sbostic 3148540Sbostic #include <sys/cdefs.h> 3240087Sbostic #include <sys/param.h> 3340087Sbostic #include <sys/stat.h> 3440087Sbostic #include <dirent.h> 3540087Sbostic #include <glob.h> 3640087Sbostic #include <ctype.h> 3740087Sbostic #include <errno.h> 3840087Sbostic #include <string.h> 3940087Sbostic #include <stdio.h> 4046597Sdonn #include <stdlib.h> 4140087Sbostic 4240087Sbostic #define DOLLAR '$' 4340087Sbostic #define DOT '.' 4440087Sbostic #define EOS '\0' 4540087Sbostic #define LBRACKET '[' 4640087Sbostic #define NOT '!' 4740087Sbostic #define QUESTION '?' 4840087Sbostic #define QUOTE '\\' 4940087Sbostic #define RANGE '-' 5040087Sbostic #define RBRACKET ']' 5140087Sbostic #define SEP '/' 5240087Sbostic #define STAR '*' 5340087Sbostic #define TILDE '~' 5440087Sbostic #define UNDERSCORE '_' 5540087Sbostic 5650049Sbostic #define M_QUOTE 0x8000 5750049Sbostic #define M_PROTECT 0x4000 5848540Sbostic #define M_MASK 0xffff 5948540Sbostic 6050049Sbostic #define META(c) ((c)|M_QUOTE) 6140087Sbostic #define M_ALL META('*') 6240087Sbostic #define M_END META(']') 6340087Sbostic #define M_NOT META('!') 6440087Sbostic #define M_ONE META('?') 6540087Sbostic #define M_RNG META('-') 6640087Sbostic #define M_SET META('[') 6750049Sbostic #define ismeta(c) (((c)&M_QUOTE) != 0) 6840087Sbostic 69*50050Sbostic typedef u_short Char; 7050049Sbostic 71*50050Sbostic static int compare __P((const void *, const void *)); 72*50050Sbostic static void g_Ctoc __P((Char *, char *)); 73*50050Sbostic static int g_lstat __P((Char *, struct stat *)); 74*50050Sbostic static DIR *g_opendir __P((Char *)); 75*50050Sbostic static Char *g_strchr __P((Char *, int)); 76*50050Sbostic static int g_stat __P((Char *, struct stat *)); 77*50050Sbostic static int glob1 __P((Char *, glob_t *)); 78*50050Sbostic static int glob2 __P((Char *, Char *, Char *, glob_t *)); 79*50050Sbostic static int glob3 __P((Char *, Char *, Char *, Char *, glob_t *)); 80*50050Sbostic static int globextend __P((Char *, glob_t *)); 81*50050Sbostic static int match __P((Char *, Char *, Char *)); 8250049Sbostic #ifdef DEBUG 83*50050Sbostic static void qprintf __P((Char *)); 8450049Sbostic #endif 8550049Sbostic 8640087Sbostic /* 8740087Sbostic * The main glob() routine: compiles the pattern (optionally processing 8840087Sbostic * quotes), calls glob1() to do the real pattern matching, and finally 8940087Sbostic * sorts the list (unless unsorted operation is requested). Returns 0 9040087Sbostic * if things went well, nonzero if errors occurred. It is not an error 9140087Sbostic * to find no matches. 9240087Sbostic */ 9340087Sbostic glob(pattern, flags, errfunc, pglob) 9446597Sdonn const char *pattern; 95*50050Sbostic int flags, (*errfunc) __P((char *, int)); 9640087Sbostic glob_t *pglob; 9740087Sbostic { 98*50050Sbostic const char *compilepat, *patnext; 9940087Sbostic int err, oldpathc; 100*50050Sbostic Char *bufnext, *bufend, *compilebuf, *qpatnext, patbuf[MAXPATHLEN+1]; 10148540Sbostic char c; 10240087Sbostic 10340087Sbostic patnext = pattern; 10440087Sbostic if (!(flags & GLOB_APPEND)) { 10540087Sbostic pglob->gl_pathc = 0; 10640087Sbostic pglob->gl_pathv = NULL; 10740087Sbostic if (!(flags & GLOB_DOOFFS)) 10840087Sbostic pglob->gl_offs = 0; 10940087Sbostic } 11047590Sbostic pglob->gl_flags = flags & ~GLOB_MAGCHAR; 11140087Sbostic pglob->gl_errfunc = errfunc; 11240087Sbostic oldpathc = pglob->gl_pathc; 11347590Sbostic pglob->gl_matchc = 0; 11440087Sbostic 11540087Sbostic bufnext = patbuf; 11650049Sbostic bufend = bufnext + MAXPATHLEN; 117*50050Sbostic compilebuf = bufnext; 118*50050Sbostic compilepat = patnext; 11950049Sbostic if (flags & GLOB_QUOTE) { 120*50050Sbostic /* Protect the quoted characters. */ 12150049Sbostic while (bufnext < bufend && (c = *patnext++) != EOS) 12250049Sbostic if (c == QUOTE) { 12350049Sbostic if ((c = *patnext++) == EOS) { 12450049Sbostic c = QUOTE; 12550049Sbostic --patnext; 12650049Sbostic } 12750049Sbostic *bufnext++ = c | M_PROTECT; 12850049Sbostic } 12950049Sbostic else 13050049Sbostic *bufnext++ = c; 13150049Sbostic } 13250049Sbostic else 13350049Sbostic while (bufnext < bufend && (c = *patnext++) != EOS) 13450049Sbostic *bufnext++ = c; 13550049Sbostic *bufnext = EOS; 13640087Sbostic 13750049Sbostic bufnext = patbuf; 13850049Sbostic qpatnext = patbuf; 139*50050Sbostic /* We don't need to check for buffer overflow any more. */ 14050049Sbostic while ((c = *qpatnext++) != EOS) { 14140087Sbostic switch (c) { 14240087Sbostic case LBRACKET: 14347590Sbostic pglob->gl_flags |= GLOB_MAGCHAR; 14450049Sbostic c = *qpatnext; 14540087Sbostic if (c == NOT) 14650049Sbostic ++qpatnext; 14750049Sbostic if (*qpatnext == EOS || 148*50050Sbostic g_strchr(qpatnext+1, RBRACKET) == NULL) { 14940087Sbostic *bufnext++ = LBRACKET; 15040087Sbostic if (c == NOT) 15150049Sbostic --qpatnext; 15240087Sbostic break; 15340087Sbostic } 15440087Sbostic *bufnext++ = M_SET; 15540087Sbostic if (c == NOT) 15640087Sbostic *bufnext++ = M_NOT; 15750049Sbostic c = *qpatnext++; 15840087Sbostic do { 15940087Sbostic *bufnext++ = c; 16050049Sbostic if (*qpatnext == RANGE && 16150049Sbostic (c = qpatnext[1]) != RBRACKET) { 16240087Sbostic *bufnext++ = M_RNG; 16340087Sbostic *bufnext++ = c; 16450049Sbostic qpatnext += 2; 16540087Sbostic } 16650049Sbostic } while ((c = *qpatnext++) != RBRACKET); 16740087Sbostic *bufnext++ = M_END; 16840087Sbostic break; 16940087Sbostic case QUESTION: 17047590Sbostic pglob->gl_flags |= GLOB_MAGCHAR; 17140087Sbostic *bufnext++ = M_ONE; 17240087Sbostic break; 17340087Sbostic case STAR: 17447590Sbostic pglob->gl_flags |= GLOB_MAGCHAR; 17540087Sbostic *bufnext++ = M_ALL; 17640087Sbostic break; 17740087Sbostic default: 17840087Sbostic *bufnext++ = c; 17940087Sbostic break; 18040087Sbostic } 18140087Sbostic } 18240087Sbostic *bufnext = EOS; 18350049Sbostic #ifdef DEBUG 18450049Sbostic qprintf(patbuf); 18550049Sbostic #endif 18640087Sbostic 18740087Sbostic if ((err = glob1(patbuf, pglob)) != 0) 18840087Sbostic return(err); 18940087Sbostic 19040087Sbostic if (pglob->gl_pathc == oldpathc && flags & GLOB_NOCHECK) { 19148540Sbostic if (!(flags & GLOB_QUOTE)) { 192*50050Sbostic Char *dp = compilebuf; 19348540Sbostic const char *sp = compilepat; 19448540Sbostic while (*dp++ = (u_char)*sp++); 19548540Sbostic } 19640087Sbostic else { 19740087Sbostic /* 198*50050Sbostic * Copy pattern, interpreting quotes; this is slightly 19940087Sbostic * different than the interpretation of quotes above 20040087Sbostic * -- which should prevail? 20140087Sbostic */ 20240087Sbostic while (*compilepat != EOS) { 20340087Sbostic if (*compilepat == QUOTE) { 20440087Sbostic if (*++compilepat == EOS) 20540087Sbostic --compilepat; 20640087Sbostic } 20748540Sbostic *compilebuf++ = (u_char)*compilepat++; 20840087Sbostic } 20940087Sbostic *compilebuf = EOS; 21040087Sbostic } 21140087Sbostic return(globextend(patbuf, pglob)); 21248540Sbostic } else if (!(flags & GLOB_NOSORT)) 213*50050Sbostic qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, 214*50050Sbostic pglob->gl_pathc - oldpathc, sizeof(char *), compare); 21540087Sbostic return(0); 21640087Sbostic } 21740087Sbostic 218*50050Sbostic static int 219*50050Sbostic compare(p, q) 220*50050Sbostic const void *p, *q; 221*50050Sbostic { 222*50050Sbostic return(strcmp(*(char **)p, *(char **)q)); 223*50050Sbostic } 224*50050Sbostic 22540087Sbostic static 22640087Sbostic glob1(pattern, pglob) 227*50050Sbostic Char *pattern; 22840087Sbostic glob_t *pglob; 22940087Sbostic { 230*50050Sbostic Char pathbuf[MAXPATHLEN+1]; 23140087Sbostic 232*50050Sbostic /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ 23340087Sbostic if (*pattern == EOS) 23440087Sbostic return(0); 23540087Sbostic return(glob2(pathbuf, pathbuf, pattern, pglob)); 23640087Sbostic } 23740087Sbostic 23840087Sbostic /* 239*50050Sbostic * The functions glob2 and glob3 are mutually recursive; there is one level 240*50050Sbostic * of recursion for each segment in the pattern that contains one or more 241*50050Sbostic * meta characters. 24240087Sbostic */ 24340087Sbostic static 24440087Sbostic glob2(pathbuf, pathend, pattern, pglob) 245*50050Sbostic Char *pathbuf, *pathend, *pattern; 24640087Sbostic glob_t *pglob; 24740087Sbostic { 248*50050Sbostic struct stat sb; 249*50050Sbostic Char *p, *q; 25048540Sbostic int anymeta; 25140087Sbostic 25240087Sbostic /* 253*50050Sbostic * Loop over pattern segments until end of pattern or until 25440087Sbostic * segment with meta character found. 25540087Sbostic */ 25648357Sbostic for (anymeta = 0;;) { 257*50050Sbostic if (*pattern == EOS) { /* End of pattern? */ 25840087Sbostic *pathend = EOS; 259*50050Sbostic if (g_stat(pathbuf, &sb)) 26048357Sbostic return(0); 26148540Sbostic 26248540Sbostic if (((pglob->gl_flags & GLOB_MARK) && 263*50050Sbostic pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) 264*50050Sbostic || (S_ISLNK(sb.st_mode) && 265*50050Sbostic (g_stat(pathbuf, &sb) == 0) && 266*50050Sbostic S_ISDIR(sb.st_mode)))) { 26740087Sbostic *pathend++ = SEP; 26840087Sbostic *pathend = EOS; 26940087Sbostic } 27047590Sbostic ++pglob->gl_matchc; 27140087Sbostic return(globextend(pathbuf, pglob)); 27240087Sbostic } 27340087Sbostic 274*50050Sbostic /* Find end of next segment, copy tentatively to pathend. */ 27540087Sbostic q = pathend; 27640087Sbostic p = pattern; 27740087Sbostic while (*p != EOS && *p != SEP) { 27840087Sbostic if (ismeta(*p)) 27940087Sbostic anymeta = 1; 28040087Sbostic *q++ = *p++; 28140087Sbostic } 28240087Sbostic 283*50050Sbostic if (!anymeta) { /* No expansion, do next segment. */ 28440087Sbostic pathend = q; 28540087Sbostic pattern = p; 28640087Sbostic while (*pattern == SEP) 28740087Sbostic *pathend++ = *pattern++; 288*50050Sbostic } else /* Need expansion, recurse. */ 28940087Sbostic return(glob3(pathbuf, pathend, pattern, p, pglob)); 29040087Sbostic } 29140087Sbostic /* NOTREACHED */ 29240087Sbostic } 29340087Sbostic 29440087Sbostic static 29540087Sbostic glob3(pathbuf, pathend, pattern, restpattern, pglob) 296*50050Sbostic Char *pathbuf, *pathend, *pattern, *restpattern; 29740087Sbostic glob_t *pglob; 29840087Sbostic { 299*50050Sbostic register struct dirent *dp; 30040087Sbostic DIR *dirp; 30140087Sbostic int len, err; 30240087Sbostic 30340087Sbostic *pathend = EOS; 30440087Sbostic errno = 0; 30548540Sbostic 306*50050Sbostic if (!(dirp = g_opendir(pathbuf))) 307*50050Sbostic /* TODO: don't call for ENOENT or ENOTDIR? */ 30840087Sbostic if (pglob->gl_errfunc && 30940087Sbostic (*pglob->gl_errfunc)(pathbuf, errno) || 31040087Sbostic (pglob->gl_flags & GLOB_ERR)) 31140087Sbostic return(GLOB_ABEND); 31240087Sbostic else 31340087Sbostic return(0); 31440087Sbostic 31540087Sbostic err = 0; 31640087Sbostic 317*50050Sbostic /* Search directory for matching names. */ 31840087Sbostic while ((dp = readdir(dirp))) { 31948540Sbostic register char *sc; 320*50050Sbostic register Char *dc; 321*50050Sbostic 322*50050Sbostic /* Initial DOT must be matched literally. */ 32340087Sbostic if (dp->d_name[0] == DOT && *pattern != DOT) 32440087Sbostic continue; 32548540Sbostic for (sc = dp->d_name, dc = pathend; 32648540Sbostic *dc++ = (u_char)*sc++;); 32748540Sbostic if (!match(pathend, pattern, restpattern)) { 32848540Sbostic *pathend = EOS; 32940087Sbostic continue; 33048540Sbostic } 33148540Sbostic err = glob2(pathbuf, --dc, restpattern, pglob); 33240087Sbostic if (err) 33340087Sbostic break; 33440087Sbostic } 335*50050Sbostic 336*50050Sbostic /* TODO: check error from readdir? */ 33740087Sbostic (void)closedir(dirp); 33840087Sbostic return(err); 33940087Sbostic } 34040087Sbostic 34140087Sbostic 34240087Sbostic /* 34340087Sbostic * Extend the gl_pathv member of a glob_t structure to accomodate a new item, 34440087Sbostic * add the new item, and update gl_pathc. 34540087Sbostic * 34640087Sbostic * This assumes the BSD realloc, which only copies the block when its size 34740087Sbostic * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic 34840087Sbostic * behavior. 34940087Sbostic * 35040087Sbostic * Return 0 if new item added, error code if memory couldn't be allocated. 35140087Sbostic * 35240087Sbostic * Invariant of the glob_t structure: 35340087Sbostic * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and 354*50050Sbostic * gl_pathv points to (gl_offs + gl_pathc + 1) items. 35540087Sbostic */ 35648540Sbostic static int 35740087Sbostic globextend(path, pglob) 358*50050Sbostic Char *path; 35940087Sbostic glob_t *pglob; 36040087Sbostic { 36140087Sbostic register char **pathv; 36240087Sbostic register int i; 36348540Sbostic u_int newsize; 36440087Sbostic char *copy; 365*50050Sbostic Char *p; 36640087Sbostic 36740087Sbostic newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); 36848540Sbostic pathv = (char **)realloc((char *)pglob->gl_pathv, newsize); 36940087Sbostic if (pathv == NULL) 37040087Sbostic return(GLOB_NOSPACE); 37140087Sbostic 37240087Sbostic if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { 37340087Sbostic /* first time around -- clear initial gl_offs items */ 37440087Sbostic pathv += pglob->gl_offs; 37540087Sbostic for (i = pglob->gl_offs; --i >= 0; ) 37640087Sbostic *--pathv = NULL; 37740087Sbostic } 37840087Sbostic pglob->gl_pathv = pathv; 37940087Sbostic 38048540Sbostic for (p = path; *p++;); 38148540Sbostic if ((copy = malloc(p - path)) != NULL) { 382*50050Sbostic g_Ctoc(path, copy); 38340087Sbostic pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; 38440087Sbostic } 38540087Sbostic pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; 386*50050Sbostic return(copy == NULL ? GLOB_NOSPACE : 0); 38740087Sbostic } 38840087Sbostic 38940087Sbostic 39040087Sbostic /* 39140087Sbostic * pattern matching function for filenames. Each occurrence of the * 39240087Sbostic * pattern causes a recursion level. 39340087Sbostic */ 39448540Sbostic static 39540087Sbostic match(name, pat, patend) 396*50050Sbostic register Char *name, *pat, *patend; 39740087Sbostic { 39848540Sbostic int ok, negate_range; 399*50050Sbostic Char c, k; 40040087Sbostic 40140087Sbostic while (pat < patend) { 40240087Sbostic c = *pat++; 40348540Sbostic switch (c & M_MASK) { 40440087Sbostic case M_ALL: 40540087Sbostic if (pat == patend) 40640087Sbostic return(1); 407*50050Sbostic for (; *name != EOS; ++name) 40840087Sbostic if (match(name, pat, patend)) 40940087Sbostic return(1); 41040087Sbostic return(0); 41140087Sbostic case M_ONE: 41240087Sbostic if (*name++ == EOS) 41340087Sbostic return(0); 41440087Sbostic break; 41540087Sbostic case M_SET: 41640087Sbostic ok = 0; 41740087Sbostic k = *name++; 41848540Sbostic if (negate_range = ((*pat & M_MASK) == M_NOT)) 41940087Sbostic ++pat; 420*50050Sbostic while (((c = *pat++) & M_MASK) != M_END) 42148540Sbostic if ((*pat & M_MASK) == M_RNG) { 42240087Sbostic if (c <= k && k <= pat[1]) 42340087Sbostic ok = 1; 42440087Sbostic pat += 2; 425*50050Sbostic } else if (c == k) 42640087Sbostic ok = 1; 42740087Sbostic if (ok == negate_range) 42840087Sbostic return(0); 42940087Sbostic break; 43040087Sbostic default: 43140087Sbostic if (*name++ != c) 43240087Sbostic return(0); 43340087Sbostic break; 43440087Sbostic } 43540087Sbostic } 43640087Sbostic return(*name == EOS); 43740087Sbostic } 43840087Sbostic 439*50050Sbostic /* Free allocated data belonging to a glob_t structure. */ 44040087Sbostic void 44140087Sbostic globfree(pglob) 44240087Sbostic glob_t *pglob; 44340087Sbostic { 44440087Sbostic register int i; 44540087Sbostic register char **pp; 44640087Sbostic 44740087Sbostic if (pglob->gl_pathv != NULL) { 44840087Sbostic pp = pglob->gl_pathv + pglob->gl_offs; 44940087Sbostic for (i = pglob->gl_pathc; i--; ++pp) 45040087Sbostic if (*pp) 451*50050Sbostic free(*pp); 45250049Sbostic free(pglob->gl_pathv); 45340087Sbostic } 45440087Sbostic } 455*50050Sbostic 456*50050Sbostic static DIR * 457*50050Sbostic g_opendir(str) 458*50050Sbostic register Char *str; 459*50050Sbostic { 460*50050Sbostic char buf[MAXPATHLEN]; 461*50050Sbostic 462*50050Sbostic if (!*str) 463*50050Sbostic return(opendir(".")); 464*50050Sbostic g_Ctoc(str, buf); 465*50050Sbostic return(opendir(buf)); 466*50050Sbostic } 467*50050Sbostic 468*50050Sbostic static int 469*50050Sbostic g_lstat(fn, sb) 470*50050Sbostic register Char *fn; 471*50050Sbostic struct stat *sb; 472*50050Sbostic { 473*50050Sbostic char buf[MAXPATHLEN]; 474*50050Sbostic 475*50050Sbostic g_Ctoc(fn, buf); 476*50050Sbostic return(lstat(buf, sb)); 477*50050Sbostic } 478*50050Sbostic 479*50050Sbostic static int 480*50050Sbostic g_stat(fn, sb) 481*50050Sbostic register Char *fn; 482*50050Sbostic struct stat *sb; 483*50050Sbostic { 484*50050Sbostic char buf[MAXPATHLEN]; 485*50050Sbostic 486*50050Sbostic g_Ctoc(fn, buf); 487*50050Sbostic return(stat(buf, sb)); 488*50050Sbostic } 489*50050Sbostic 490*50050Sbostic static Char * 491*50050Sbostic g_strchr(str, ch) 492*50050Sbostic Char *str; 493*50050Sbostic int ch; 494*50050Sbostic { 495*50050Sbostic do { 496*50050Sbostic if (*str == ch) 497*50050Sbostic return (str); 498*50050Sbostic } while (*str++); 499*50050Sbostic return (NULL); 500*50050Sbostic } 501*50050Sbostic 502*50050Sbostic static void 503*50050Sbostic g_Ctoc(str, buf) 504*50050Sbostic register Char *str; 505*50050Sbostic char *buf; 506*50050Sbostic { 507*50050Sbostic register char *dc; 508*50050Sbostic 509*50050Sbostic for (dc = buf; *dc++ = *str++;); 510*50050Sbostic } 511*50050Sbostic 512*50050Sbostic #ifdef DEBUG 513*50050Sbostic static void 514*50050Sbostic qprintf(s) 515*50050Sbostic register Char *s; 516*50050Sbostic { 517*50050Sbostic register Char *p; 518*50050Sbostic 519*50050Sbostic for (p = s; *p; p++) 520*50050Sbostic (void)printf("%c", *p & 0xff); 521*50050Sbostic (void)printf("\n"); 522*50050Sbostic for (p = s; *p; p++) 523*50050Sbostic (void)printf("%c", *p & M_PROTECT ? '"' : ' '); 524*50050Sbostic (void)printf("\n"); 525*50050Sbostic for (p = s; *p; p++) 526*50050Sbostic (void)printf("%c", *p & M_META ? '_' : ' '); 527*50050Sbostic (void)printf("\n"); 528*50050Sbostic } 529*50050Sbostic #endif 530