15af32e75SAxel Dörfler /* 25af32e75SAxel Dörfler * Copyright (c) 1989, 1993 35af32e75SAxel Dörfler * The Regents of the University of California. All rights reserved. 45af32e75SAxel Dörfler * 55af32e75SAxel Dörfler * This code is derived from software contributed to Berkeley by 65af32e75SAxel Dörfler * Guido van Rossum. 75af32e75SAxel Dörfler * 85af32e75SAxel Dörfler * Redistribution and use in source and binary forms, with or without 95af32e75SAxel Dörfler * modification, are permitted provided that the following conditions 105af32e75SAxel Dörfler * are met: 115af32e75SAxel Dörfler * 1. Redistributions of source code must retain the above copyright 125af32e75SAxel Dörfler * notice, this list of conditions and the following disclaimer. 135af32e75SAxel Dörfler * 2. Redistributions in binary form must reproduce the above copyright 145af32e75SAxel Dörfler * notice, this list of conditions and the following disclaimer in the 155af32e75SAxel Dörfler * documentation and/or other materials provided with the distribution. 165af32e75SAxel Dörfler * 4. Neither the name of the University nor the names of its contributors 175af32e75SAxel Dörfler * may be used to endorse or promote products derived from this software 185af32e75SAxel Dörfler * without specific prior written permission. 195af32e75SAxel Dörfler * 205af32e75SAxel Dörfler * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 215af32e75SAxel Dörfler * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 225af32e75SAxel Dörfler * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 235af32e75SAxel Dörfler * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 245af32e75SAxel Dörfler * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 255af32e75SAxel Dörfler * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 265af32e75SAxel Dörfler * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 275af32e75SAxel Dörfler * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 285af32e75SAxel Dörfler * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 295af32e75SAxel Dörfler * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 305af32e75SAxel Dörfler * SUCH DAMAGE. 315af32e75SAxel Dörfler */ 325af32e75SAxel Dörfler 336e036f04SAxel Dörfler #if defined(LIBC_SCCS) && !defined(lint) 346e036f04SAxel Dörfler static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; 356e036f04SAxel Dörfler #endif /* LIBC_SCCS and not lint */ 366e036f04SAxel Dörfler #include <sys/cdefs.h> 376e036f04SAxel Dörfler //__FBSDID("$FreeBSD: src/lib/libc/gen/glob.c,v 1.27 2008/06/26 07:12:35 mtm Exp $"); 386e036f04SAxel Dörfler 395af32e75SAxel Dörfler /* 405af32e75SAxel Dörfler * glob(3) -- a superset of the one defined in POSIX 1003.2. 415af32e75SAxel Dörfler * 425af32e75SAxel Dörfler * The [!...] convention to negate a range is supported (SysV, Posix, ksh). 435af32e75SAxel Dörfler * 445af32e75SAxel Dörfler * Optional extra services, controlled by flags not defined by POSIX: 455af32e75SAxel Dörfler * 465af32e75SAxel Dörfler * GLOB_QUOTE: 475af32e75SAxel Dörfler * Escaping convention: \ inhibits any special meaning the following 485af32e75SAxel Dörfler * character might have (except \ at end of string is retained). 495af32e75SAxel Dörfler * GLOB_MAGCHAR: 505af32e75SAxel Dörfler * Set in gl_flags if pattern contained a globbing character. 515af32e75SAxel Dörfler * GLOB_NOMAGIC: 525af32e75SAxel Dörfler * Same as GLOB_NOCHECK, but it will only append pattern if it did 535af32e75SAxel Dörfler * not contain any magic characters. [Used in csh style globbing] 545af32e75SAxel Dörfler * GLOB_ALTDIRFUNC: 555af32e75SAxel Dörfler * Use alternately specified directory access functions. 565af32e75SAxel Dörfler * GLOB_TILDE: 575af32e75SAxel Dörfler * expand ~user/foo to the /home/dir/of/user/foo 585af32e75SAxel Dörfler * GLOB_BRACE: 595af32e75SAxel Dörfler * expand {1,2}{a,b} to 1a 1b 2a 2b 605af32e75SAxel Dörfler * gl_matchc: 615af32e75SAxel Dörfler * Number of matches in the current invocation of glob. 625af32e75SAxel Dörfler */ 635af32e75SAxel Dörfler 646e036f04SAxel Dörfler /* 656e036f04SAxel Dörfler * Some notes on multibyte character support: 666e036f04SAxel Dörfler * 1. Patterns with illegal byte sequences match nothing - even if 676e036f04SAxel Dörfler * GLOB_NOCHECK is specified. 686e036f04SAxel Dörfler * 2. Illegal byte sequences in filenames are handled by treating them as 696e036f04SAxel Dörfler * single-byte characters with a value of the first byte of the sequence 706e036f04SAxel Dörfler * cast to wchar_t. 716e036f04SAxel Dörfler * 3. State-dependent encodings are not currently supported. 726e036f04SAxel Dörfler */ 736e036f04SAxel Dörfler 745af32e75SAxel Dörfler #include <sys/param.h> 755af32e75SAxel Dörfler #include <sys/stat.h> 765af32e75SAxel Dörfler 775af32e75SAxel Dörfler #include <ctype.h> 785af32e75SAxel Dörfler #include <dirent.h> 795af32e75SAxel Dörfler #include <errno.h> 805af32e75SAxel Dörfler #include <glob.h> 816e036f04SAxel Dörfler #include <limits.h> 825af32e75SAxel Dörfler #include <pwd.h> 836e036f04SAxel Dörfler #include <stdint.h> 845af32e75SAxel Dörfler #include <stdio.h> 855af32e75SAxel Dörfler #include <stdlib.h> 865af32e75SAxel Dörfler #include <string.h> 875af32e75SAxel Dörfler #include <unistd.h> 886e036f04SAxel Dörfler #include <wchar.h> 895af32e75SAxel Dörfler 906e036f04SAxel Dörfler #ifndef __HAIKU__ 916e036f04SAxel Dörfler # include "collate.h" 926e036f04SAxel Dörfler #endif 935af32e75SAxel Dörfler 945af32e75SAxel Dörfler #define DOLLAR '$' 955af32e75SAxel Dörfler #define DOT '.' 965af32e75SAxel Dörfler #define EOS '\0' 975af32e75SAxel Dörfler #define LBRACKET '[' 985af32e75SAxel Dörfler #define NOT '!' 995af32e75SAxel Dörfler #define QUESTION '?' 1005af32e75SAxel Dörfler #define QUOTE '\\' 1015af32e75SAxel Dörfler #define RANGE '-' 1025af32e75SAxel Dörfler #define RBRACKET ']' 1035af32e75SAxel Dörfler #define SEP '/' 1045af32e75SAxel Dörfler #define STAR '*' 1055af32e75SAxel Dörfler #define TILDE '~' 1065af32e75SAxel Dörfler #define UNDERSCORE '_' 1075af32e75SAxel Dörfler #define LBRACE '{' 1085af32e75SAxel Dörfler #define RBRACE '}' 1095af32e75SAxel Dörfler #define SLASH '/' 1105af32e75SAxel Dörfler #define COMMA ',' 1115af32e75SAxel Dörfler 112*5074333dSAxel Dörfler #if !defined(DEBUG) && !defined(__HAIKU__) 1135af32e75SAxel Dörfler 1146e036f04SAxel Dörfler #define M_QUOTE 0x8000000000ULL 1156e036f04SAxel Dörfler #define M_PROTECT 0x4000000000ULL 1166e036f04SAxel Dörfler #define M_MASK 0xffffffffffULL 1176e036f04SAxel Dörfler #define M_CHAR 0x00ffffffffULL 1185af32e75SAxel Dörfler 1196e036f04SAxel Dörfler typedef uint_fast64_t Char; 1205af32e75SAxel Dörfler 1215af32e75SAxel Dörfler #else 1225af32e75SAxel Dörfler 1235af32e75SAxel Dörfler #define M_QUOTE 0x80 1245af32e75SAxel Dörfler #define M_PROTECT 0x40 1255af32e75SAxel Dörfler #define M_MASK 0xff 1266e036f04SAxel Dörfler #define M_CHAR 0x7f 1275af32e75SAxel Dörfler 1285af32e75SAxel Dörfler typedef char Char; 1295af32e75SAxel Dörfler 1305af32e75SAxel Dörfler #endif 1315af32e75SAxel Dörfler 1325af32e75SAxel Dörfler 1336e036f04SAxel Dörfler #define CHAR(c) ((Char)((c)&M_CHAR)) 1345af32e75SAxel Dörfler #define META(c) ((Char)((c)|M_QUOTE)) 1355af32e75SAxel Dörfler #define M_ALL META('*') 1365af32e75SAxel Dörfler #define M_END META(']') 1375af32e75SAxel Dörfler #define M_NOT META('!') 1385af32e75SAxel Dörfler #define M_ONE META('?') 1395af32e75SAxel Dörfler #define M_RNG META('-') 1405af32e75SAxel Dörfler #define M_SET META('[') 1415af32e75SAxel Dörfler #define ismeta(c) (((c)&M_QUOTE) != 0) 1425af32e75SAxel Dörfler 1435af32e75SAxel Dörfler 1445af32e75SAxel Dörfler static int compare(const void *, const void *); 1456e036f04SAxel Dörfler static int g_Ctoc(const Char *, char *, size_t); 1465af32e75SAxel Dörfler static int g_lstat(Char *, struct stat *, glob_t *); 1475af32e75SAxel Dörfler static DIR *g_opendir(Char *, glob_t *); 1486e036f04SAxel Dörfler static const Char *g_strchr(const Char *, wchar_t); 1495af32e75SAxel Dörfler #ifdef notdef 1505af32e75SAxel Dörfler static Char *g_strcat(Char *, const Char *); 1515af32e75SAxel Dörfler #endif 1525af32e75SAxel Dörfler static int g_stat(Char *, struct stat *, glob_t *); 1536e036f04SAxel Dörfler static int glob0(const Char *, glob_t *, size_t *); 1546e036f04SAxel Dörfler static int glob1(Char *, glob_t *, size_t *); 1556e036f04SAxel Dörfler static int glob2(Char *, Char *, Char *, Char *, glob_t *, size_t *); 1566e036f04SAxel Dörfler static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, size_t *); 1576e036f04SAxel Dörfler static int globextend(const Char *, glob_t *, size_t *); 1585af32e75SAxel Dörfler static const Char * 1595af32e75SAxel Dörfler globtilde(const Char *, Char *, size_t, glob_t *); 1606e036f04SAxel Dörfler static int globexp1(const Char *, glob_t *, size_t *); 1616e036f04SAxel Dörfler static int globexp2(const Char *, const Char *, glob_t *, int *, size_t *); 1625af32e75SAxel Dörfler static int match(Char *, Char *, Char *); 1635af32e75SAxel Dörfler #ifdef DEBUG 1645af32e75SAxel Dörfler static void qprintf(const char *, Char *); 1655af32e75SAxel Dörfler #endif 1665af32e75SAxel Dörfler 167*5074333dSAxel Dörfler #ifdef __HAIKU__ 168*5074333dSAxel Dörfler # warning glob() wants to use wide character functions 169*5074333dSAxel Dörfler 170*5074333dSAxel Dörfler static size_t 171*5074333dSAxel Dörfler my_wcrtomb(char* to, char wchar, mbstate_t* state) 172*5074333dSAxel Dörfler { 173*5074333dSAxel Dörfler *to = wchar; 174*5074333dSAxel Dörfler return 1; 175*5074333dSAxel Dörfler } 176*5074333dSAxel Dörfler 177*5074333dSAxel Dörfler static size_t 178*5074333dSAxel Dörfler my_mbrtowc(wchar_t* to, const char* string, size_t len, mbstate_t* state) 179*5074333dSAxel Dörfler { 180*5074333dSAxel Dörfler if (!string[0]) 181*5074333dSAxel Dörfler return 0; 182*5074333dSAxel Dörfler *to = *string; 183*5074333dSAxel Dörfler return 1; 184*5074333dSAxel Dörfler } 185*5074333dSAxel Dörfler 186*5074333dSAxel Dörfler # define wcrtomb my_wcrtomb 187*5074333dSAxel Dörfler # define mbrtowc my_mbrtowc 188*5074333dSAxel Dörfler #endif 189*5074333dSAxel Dörfler 190*5074333dSAxel Dörfler 1915af32e75SAxel Dörfler int 1925af32e75SAxel Dörfler glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) 1935af32e75SAxel Dörfler { 1946e036f04SAxel Dörfler const char *patnext; 1956e036f04SAxel Dörfler size_t limit; 1966e036f04SAxel Dörfler Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot; 1976e036f04SAxel Dörfler mbstate_t mbs; 1986e036f04SAxel Dörfler wchar_t wc; 1996e036f04SAxel Dörfler size_t clen; 2005af32e75SAxel Dörfler 2016e036f04SAxel Dörfler patnext = pattern; 2025af32e75SAxel Dörfler if (!(flags & GLOB_APPEND)) { 2035af32e75SAxel Dörfler pglob->gl_pathc = 0; 2045af32e75SAxel Dörfler pglob->gl_pathv = NULL; 2055af32e75SAxel Dörfler if (!(flags & GLOB_DOOFFS)) 2065af32e75SAxel Dörfler pglob->gl_offs = 0; 2075af32e75SAxel Dörfler } 2085af32e75SAxel Dörfler if (flags & GLOB_LIMIT) { 2095af32e75SAxel Dörfler limit = pglob->gl_matchc; 2105af32e75SAxel Dörfler if (limit == 0) 2115af32e75SAxel Dörfler limit = ARG_MAX; 2125af32e75SAxel Dörfler } else 2135af32e75SAxel Dörfler limit = 0; 2145af32e75SAxel Dörfler pglob->gl_flags = flags & ~GLOB_MAGCHAR; 2155af32e75SAxel Dörfler pglob->gl_errfunc = errfunc; 2165af32e75SAxel Dörfler pglob->gl_matchc = 0; 2175af32e75SAxel Dörfler 2185af32e75SAxel Dörfler bufnext = patbuf; 2195af32e75SAxel Dörfler bufend = bufnext + MAXPATHLEN - 1; 2205af32e75SAxel Dörfler if (flags & GLOB_NOESCAPE) { 2216e036f04SAxel Dörfler memset(&mbs, 0, sizeof(mbs)); 2226e036f04SAxel Dörfler while (bufend - bufnext >= MB_CUR_MAX) { 2236e036f04SAxel Dörfler clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs); 2246e036f04SAxel Dörfler if (clen == (size_t)-1 || clen == (size_t)-2) 2256e036f04SAxel Dörfler return (GLOB_NOMATCH); 2266e036f04SAxel Dörfler else if (clen == 0) 2276e036f04SAxel Dörfler break; 2286e036f04SAxel Dörfler *bufnext++ = wc; 2296e036f04SAxel Dörfler patnext += clen; 2306e036f04SAxel Dörfler } 2315af32e75SAxel Dörfler } else { 2325af32e75SAxel Dörfler /* Protect the quoted characters. */ 2336e036f04SAxel Dörfler memset(&mbs, 0, sizeof(mbs)); 2346e036f04SAxel Dörfler while (bufend - bufnext >= MB_CUR_MAX) { 2356e036f04SAxel Dörfler if (*patnext == QUOTE) { 2366e036f04SAxel Dörfler if (*++patnext == EOS) { 2376e036f04SAxel Dörfler *bufnext++ = QUOTE | M_PROTECT; 2386e036f04SAxel Dörfler continue; 2395af32e75SAxel Dörfler } 2406e036f04SAxel Dörfler prot = M_PROTECT; 2416e036f04SAxel Dörfler } else 2426e036f04SAxel Dörfler prot = 0; 2436e036f04SAxel Dörfler clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs); 2446e036f04SAxel Dörfler if (clen == (size_t)-1 || clen == (size_t)-2) 2456e036f04SAxel Dörfler return (GLOB_NOMATCH); 2466e036f04SAxel Dörfler else if (clen == 0) 2476e036f04SAxel Dörfler break; 2486e036f04SAxel Dörfler *bufnext++ = wc | prot; 2496e036f04SAxel Dörfler patnext += clen; 2505af32e75SAxel Dörfler } 2515af32e75SAxel Dörfler } 2525af32e75SAxel Dörfler *bufnext = EOS; 2535af32e75SAxel Dörfler 2545af32e75SAxel Dörfler if (flags & GLOB_BRACE) 2555af32e75SAxel Dörfler return globexp1(patbuf, pglob, &limit); 2566e036f04SAxel Dörfler else 2575af32e75SAxel Dörfler return glob0(patbuf, pglob, &limit); 2585af32e75SAxel Dörfler } 2595af32e75SAxel Dörfler 2605af32e75SAxel Dörfler /* 2615af32e75SAxel Dörfler * Expand recursively a glob {} pattern. When there is no more expansion 2625af32e75SAxel Dörfler * invoke the standard globbing routine to glob the rest of the magic 2635af32e75SAxel Dörfler * characters 2645af32e75SAxel Dörfler */ 2655af32e75SAxel Dörfler static int 2666e036f04SAxel Dörfler globexp1(const Char *pattern, glob_t *pglob, size_t *limit) 2675af32e75SAxel Dörfler { 2685af32e75SAxel Dörfler const Char* ptr = pattern; 2695af32e75SAxel Dörfler int rv; 2705af32e75SAxel Dörfler 2715af32e75SAxel Dörfler /* Protect a single {}, for find(1), like csh */ 2725af32e75SAxel Dörfler if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) 2735af32e75SAxel Dörfler return glob0(pattern, pglob, limit); 2745af32e75SAxel Dörfler 2756e036f04SAxel Dörfler while ((ptr = g_strchr(ptr, LBRACE)) != NULL) 2765af32e75SAxel Dörfler if (!globexp2(ptr, pattern, pglob, &rv, limit)) 2775af32e75SAxel Dörfler return rv; 2785af32e75SAxel Dörfler 2795af32e75SAxel Dörfler return glob0(pattern, pglob, limit); 2805af32e75SAxel Dörfler } 2815af32e75SAxel Dörfler 2825af32e75SAxel Dörfler 2835af32e75SAxel Dörfler /* 2845af32e75SAxel Dörfler * Recursive brace globbing helper. Tries to expand a single brace. 2855af32e75SAxel Dörfler * If it succeeds then it invokes globexp1 with the new pattern. 2865af32e75SAxel Dörfler * If it fails then it tries to glob the rest of the pattern and returns. 2875af32e75SAxel Dörfler */ 2885af32e75SAxel Dörfler static int 2896e036f04SAxel Dörfler globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, size_t *limit) 2905af32e75SAxel Dörfler { 2915af32e75SAxel Dörfler int i; 2925af32e75SAxel Dörfler Char *lm, *ls; 2936e036f04SAxel Dörfler const Char *pe, *pm, *pm1, *pl; 2945af32e75SAxel Dörfler Char patbuf[MAXPATHLEN]; 2955af32e75SAxel Dörfler 2965af32e75SAxel Dörfler /* copy part up to the brace */ 2975af32e75SAxel Dörfler for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) 2985af32e75SAxel Dörfler continue; 2995af32e75SAxel Dörfler *lm = EOS; 3005af32e75SAxel Dörfler ls = lm; 3015af32e75SAxel Dörfler 3025af32e75SAxel Dörfler /* Find the balanced brace */ 3036e036f04SAxel Dörfler for (i = 0, pe = ++ptr; *pe; pe++) 3045af32e75SAxel Dörfler if (*pe == LBRACKET) { 3055af32e75SAxel Dörfler /* Ignore everything between [] */ 3065af32e75SAxel Dörfler for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) 3075af32e75SAxel Dörfler continue; 3085af32e75SAxel Dörfler if (*pe == EOS) { 3095af32e75SAxel Dörfler /* 3105af32e75SAxel Dörfler * We could not find a matching RBRACKET. 3115af32e75SAxel Dörfler * Ignore and just look for RBRACE 3125af32e75SAxel Dörfler */ 3135af32e75SAxel Dörfler pe = pm; 3145af32e75SAxel Dörfler } 3155af32e75SAxel Dörfler } 3165af32e75SAxel Dörfler else if (*pe == LBRACE) 3175af32e75SAxel Dörfler i++; 3185af32e75SAxel Dörfler else if (*pe == RBRACE) { 3195af32e75SAxel Dörfler if (i == 0) 3205af32e75SAxel Dörfler break; 3215af32e75SAxel Dörfler i--; 3225af32e75SAxel Dörfler } 3235af32e75SAxel Dörfler 3245af32e75SAxel Dörfler /* Non matching braces; just glob the pattern */ 3255af32e75SAxel Dörfler if (i != 0 || *pe == EOS) { 3265af32e75SAxel Dörfler *rv = glob0(patbuf, pglob, limit); 3275af32e75SAxel Dörfler return 0; 3285af32e75SAxel Dörfler } 3295af32e75SAxel Dörfler 3306e036f04SAxel Dörfler for (i = 0, pl = pm = ptr; pm <= pe; pm++) 3315af32e75SAxel Dörfler switch (*pm) { 3325af32e75SAxel Dörfler case LBRACKET: 3335af32e75SAxel Dörfler /* Ignore everything between [] */ 3346e036f04SAxel Dörfler for (pm1 = pm++; *pm != RBRACKET && *pm != EOS; pm++) 3355af32e75SAxel Dörfler continue; 3365af32e75SAxel Dörfler if (*pm == EOS) { 3375af32e75SAxel Dörfler /* 3385af32e75SAxel Dörfler * We could not find a matching RBRACKET. 3395af32e75SAxel Dörfler * Ignore and just look for RBRACE 3405af32e75SAxel Dörfler */ 3416e036f04SAxel Dörfler pm = pm1; 3425af32e75SAxel Dörfler } 3435af32e75SAxel Dörfler break; 3445af32e75SAxel Dörfler 3455af32e75SAxel Dörfler case LBRACE: 3465af32e75SAxel Dörfler i++; 3475af32e75SAxel Dörfler break; 3485af32e75SAxel Dörfler 3495af32e75SAxel Dörfler case RBRACE: 3505af32e75SAxel Dörfler if (i) { 3515af32e75SAxel Dörfler i--; 3525af32e75SAxel Dörfler break; 3535af32e75SAxel Dörfler } 3545af32e75SAxel Dörfler /* FALLTHROUGH */ 3555af32e75SAxel Dörfler case COMMA: 3565af32e75SAxel Dörfler if (i && *pm == COMMA) 3575af32e75SAxel Dörfler break; 3585af32e75SAxel Dörfler else { 3595af32e75SAxel Dörfler /* Append the current string */ 3605af32e75SAxel Dörfler for (lm = ls; (pl < pm); *lm++ = *pl++) 3615af32e75SAxel Dörfler continue; 3625af32e75SAxel Dörfler /* 3635af32e75SAxel Dörfler * Append the rest of the pattern after the 3645af32e75SAxel Dörfler * closing brace 3655af32e75SAxel Dörfler */ 3665af32e75SAxel Dörfler for (pl = pe + 1; (*lm++ = *pl++) != EOS;) 3675af32e75SAxel Dörfler continue; 3685af32e75SAxel Dörfler 3695af32e75SAxel Dörfler /* Expand the current pattern */ 3705af32e75SAxel Dörfler #ifdef DEBUG 3715af32e75SAxel Dörfler qprintf("globexp2:", patbuf); 3725af32e75SAxel Dörfler #endif 3735af32e75SAxel Dörfler *rv = globexp1(patbuf, pglob, limit); 3745af32e75SAxel Dörfler 3755af32e75SAxel Dörfler /* move after the comma, to the next string */ 3765af32e75SAxel Dörfler pl = pm + 1; 3775af32e75SAxel Dörfler } 3785af32e75SAxel Dörfler break; 3795af32e75SAxel Dörfler 3805af32e75SAxel Dörfler default: 3815af32e75SAxel Dörfler break; 3825af32e75SAxel Dörfler } 3835af32e75SAxel Dörfler *rv = 0; 3845af32e75SAxel Dörfler return 0; 3855af32e75SAxel Dörfler } 3865af32e75SAxel Dörfler 3875af32e75SAxel Dörfler 3886e036f04SAxel Dörfler 3895af32e75SAxel Dörfler /* 3905af32e75SAxel Dörfler * expand tilde from the passwd file. 3915af32e75SAxel Dörfler */ 3925af32e75SAxel Dörfler static const Char * 3935af32e75SAxel Dörfler globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) 3945af32e75SAxel Dörfler { 3955af32e75SAxel Dörfler struct passwd *pwd; 3965af32e75SAxel Dörfler char *h; 3975af32e75SAxel Dörfler const Char *p; 3985af32e75SAxel Dörfler Char *b, *eb; 3995af32e75SAxel Dörfler 4005af32e75SAxel Dörfler if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) 4015af32e75SAxel Dörfler return pattern; 4025af32e75SAxel Dörfler 4035af32e75SAxel Dörfler /* 4045af32e75SAxel Dörfler * Copy up to the end of the string or / 4055af32e75SAxel Dörfler */ 4065af32e75SAxel Dörfler eb = &patbuf[patbuf_len - 1]; 4075af32e75SAxel Dörfler for (p = pattern + 1, h = (char *) patbuf; 4085af32e75SAxel Dörfler h < (char *)eb && *p && *p != SLASH; *h++ = *p++) 4095af32e75SAxel Dörfler continue; 4105af32e75SAxel Dörfler 4115af32e75SAxel Dörfler *h = EOS; 4125af32e75SAxel Dörfler 4135af32e75SAxel Dörfler if (((char *) patbuf)[0] == EOS) { 4145af32e75SAxel Dörfler /* 4155af32e75SAxel Dörfler * handle a plain ~ or ~/ by expanding $HOME first (iff 4165af32e75SAxel Dörfler * we're not running setuid or setgid) and then trying 4175af32e75SAxel Dörfler * the password file 4185af32e75SAxel Dörfler */ 4195af32e75SAxel Dörfler if ( 4206e036f04SAxel Dörfler #ifndef __HAIKU__ 4216e036f04SAxel Dörfler issetugid() != 0 || 4226e036f04SAxel Dörfler #endif 4235af32e75SAxel Dörfler (h = getenv("HOME")) == NULL) { 4245af32e75SAxel Dörfler if (((h = getlogin()) != NULL && 4255af32e75SAxel Dörfler (pwd = getpwnam(h)) != NULL) || 4265af32e75SAxel Dörfler (pwd = getpwuid(getuid())) != NULL) 4275af32e75SAxel Dörfler h = pwd->pw_dir; 4285af32e75SAxel Dörfler else 4295af32e75SAxel Dörfler return pattern; 4305af32e75SAxel Dörfler } 4315af32e75SAxel Dörfler } 4325af32e75SAxel Dörfler else { 4335af32e75SAxel Dörfler /* 4345af32e75SAxel Dörfler * Expand a ~user 4355af32e75SAxel Dörfler */ 4365af32e75SAxel Dörfler if ((pwd = getpwnam((char*) patbuf)) == NULL) 4375af32e75SAxel Dörfler return pattern; 4385af32e75SAxel Dörfler else 4395af32e75SAxel Dörfler h = pwd->pw_dir; 4405af32e75SAxel Dörfler } 4415af32e75SAxel Dörfler 4425af32e75SAxel Dörfler /* Copy the home directory */ 4435af32e75SAxel Dörfler for (b = patbuf; b < eb && *h; *b++ = *h++) 4445af32e75SAxel Dörfler continue; 4455af32e75SAxel Dörfler 4465af32e75SAxel Dörfler /* Append the rest of the pattern */ 4475af32e75SAxel Dörfler while (b < eb && (*b++ = *p++) != EOS) 4485af32e75SAxel Dörfler continue; 4495af32e75SAxel Dörfler *b = EOS; 4505af32e75SAxel Dörfler 4515af32e75SAxel Dörfler return patbuf; 4525af32e75SAxel Dörfler } 4535af32e75SAxel Dörfler 4545af32e75SAxel Dörfler 4555af32e75SAxel Dörfler /* 4565af32e75SAxel Dörfler * The main glob() routine: compiles the pattern (optionally processing 4575af32e75SAxel Dörfler * quotes), calls glob1() to do the real pattern matching, and finally 4585af32e75SAxel Dörfler * sorts the list (unless unsorted operation is requested). Returns 0 4595af32e75SAxel Dörfler * if things went well, nonzero if errors occurred. 4605af32e75SAxel Dörfler */ 4615af32e75SAxel Dörfler static int 4626e036f04SAxel Dörfler glob0(const Char *pattern, glob_t *pglob, size_t *limit) 4635af32e75SAxel Dörfler { 4645af32e75SAxel Dörfler const Char *qpatnext; 4656e036f04SAxel Dörfler int c, err; 4666e036f04SAxel Dörfler size_t oldpathc; 4675af32e75SAxel Dörfler Char *bufnext, patbuf[MAXPATHLEN]; 4685af32e75SAxel Dörfler 4695af32e75SAxel Dörfler qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); 4705af32e75SAxel Dörfler oldpathc = pglob->gl_pathc; 4715af32e75SAxel Dörfler bufnext = patbuf; 4725af32e75SAxel Dörfler 4735af32e75SAxel Dörfler /* We don't need to check for buffer overflow any more. */ 4745af32e75SAxel Dörfler while ((c = *qpatnext++) != EOS) { 4755af32e75SAxel Dörfler switch (c) { 4765af32e75SAxel Dörfler case LBRACKET: 4775af32e75SAxel Dörfler c = *qpatnext; 4785af32e75SAxel Dörfler if (c == NOT) 4795af32e75SAxel Dörfler ++qpatnext; 4805af32e75SAxel Dörfler if (*qpatnext == EOS || 4816e036f04SAxel Dörfler g_strchr(qpatnext+1, RBRACKET) == NULL) { 4825af32e75SAxel Dörfler *bufnext++ = LBRACKET; 4835af32e75SAxel Dörfler if (c == NOT) 4845af32e75SAxel Dörfler --qpatnext; 4855af32e75SAxel Dörfler break; 4865af32e75SAxel Dörfler } 4875af32e75SAxel Dörfler *bufnext++ = M_SET; 4885af32e75SAxel Dörfler if (c == NOT) 4895af32e75SAxel Dörfler *bufnext++ = M_NOT; 4905af32e75SAxel Dörfler c = *qpatnext++; 4915af32e75SAxel Dörfler do { 4925af32e75SAxel Dörfler *bufnext++ = CHAR(c); 4935af32e75SAxel Dörfler if (*qpatnext == RANGE && 4945af32e75SAxel Dörfler (c = qpatnext[1]) != RBRACKET) { 4955af32e75SAxel Dörfler *bufnext++ = M_RNG; 4965af32e75SAxel Dörfler *bufnext++ = CHAR(c); 4975af32e75SAxel Dörfler qpatnext += 2; 4985af32e75SAxel Dörfler } 4995af32e75SAxel Dörfler } while ((c = *qpatnext++) != RBRACKET); 5005af32e75SAxel Dörfler pglob->gl_flags |= GLOB_MAGCHAR; 5015af32e75SAxel Dörfler *bufnext++ = M_END; 5025af32e75SAxel Dörfler break; 5035af32e75SAxel Dörfler case QUESTION: 5045af32e75SAxel Dörfler pglob->gl_flags |= GLOB_MAGCHAR; 5055af32e75SAxel Dörfler *bufnext++ = M_ONE; 5065af32e75SAxel Dörfler break; 5075af32e75SAxel Dörfler case STAR: 5085af32e75SAxel Dörfler pglob->gl_flags |= GLOB_MAGCHAR; 5095af32e75SAxel Dörfler /* collapse adjacent stars to one, 5105af32e75SAxel Dörfler * to avoid exponential behavior 5115af32e75SAxel Dörfler */ 5125af32e75SAxel Dörfler if (bufnext == patbuf || bufnext[-1] != M_ALL) 5135af32e75SAxel Dörfler *bufnext++ = M_ALL; 5145af32e75SAxel Dörfler break; 5155af32e75SAxel Dörfler default: 5165af32e75SAxel Dörfler *bufnext++ = CHAR(c); 5175af32e75SAxel Dörfler break; 5185af32e75SAxel Dörfler } 5195af32e75SAxel Dörfler } 5205af32e75SAxel Dörfler *bufnext = EOS; 5215af32e75SAxel Dörfler #ifdef DEBUG 5225af32e75SAxel Dörfler qprintf("glob0:", patbuf); 5235af32e75SAxel Dörfler #endif 5245af32e75SAxel Dörfler 5255af32e75SAxel Dörfler if ((err = glob1(patbuf, pglob, limit)) != 0) 5265af32e75SAxel Dörfler return(err); 5275af32e75SAxel Dörfler 5285af32e75SAxel Dörfler /* 5295af32e75SAxel Dörfler * If there was no match we are going to append the pattern 5305af32e75SAxel Dörfler * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified 5315af32e75SAxel Dörfler * and the pattern did not contain any magic characters 5325af32e75SAxel Dörfler * GLOB_NOMAGIC is there just for compatibility with csh. 5335af32e75SAxel Dörfler */ 5345af32e75SAxel Dörfler if (pglob->gl_pathc == oldpathc) { 5355af32e75SAxel Dörfler if (((pglob->gl_flags & GLOB_NOCHECK) || 5365af32e75SAxel Dörfler ((pglob->gl_flags & GLOB_NOMAGIC) && 5375af32e75SAxel Dörfler !(pglob->gl_flags & GLOB_MAGCHAR)))) 5386e036f04SAxel Dörfler return(globextend(pattern, pglob, limit)); 5395af32e75SAxel Dörfler else 5406e036f04SAxel Dörfler return(GLOB_NOMATCH); 5415af32e75SAxel Dörfler } 5425af32e75SAxel Dörfler if (!(pglob->gl_flags & GLOB_NOSORT)) 5435af32e75SAxel Dörfler qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, 5445af32e75SAxel Dörfler pglob->gl_pathc - oldpathc, sizeof(char *), compare); 5456e036f04SAxel Dörfler return(0); 5465af32e75SAxel Dörfler } 5475af32e75SAxel Dörfler 5485af32e75SAxel Dörfler static int 5495af32e75SAxel Dörfler compare(const void *p, const void *q) 5505af32e75SAxel Dörfler { 5516e036f04SAxel Dörfler return(strcmp(*(char **)p, *(char **)q)); 5525af32e75SAxel Dörfler } 5535af32e75SAxel Dörfler 5545af32e75SAxel Dörfler static int 5556e036f04SAxel Dörfler glob1(Char *pattern, glob_t *pglob, size_t *limit) 5565af32e75SAxel Dörfler { 5575af32e75SAxel Dörfler Char pathbuf[MAXPATHLEN]; 5585af32e75SAxel Dörfler 5595af32e75SAxel Dörfler /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ 5605af32e75SAxel Dörfler if (*pattern == EOS) 5616e036f04SAxel Dörfler return(0); 5626e036f04SAxel Dörfler return(glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1, 5636e036f04SAxel Dörfler pattern, pglob, limit)); 5645af32e75SAxel Dörfler } 5655af32e75SAxel Dörfler 5665af32e75SAxel Dörfler /* 5675af32e75SAxel Dörfler * The functions glob2 and glob3 are mutually recursive; there is one level 5685af32e75SAxel Dörfler * of recursion for each segment in the pattern that contains one or more 5695af32e75SAxel Dörfler * meta characters. 5705af32e75SAxel Dörfler */ 5715af32e75SAxel Dörfler static int 5726e036f04SAxel Dörfler glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern, 5736e036f04SAxel Dörfler glob_t *pglob, size_t *limit) 5745af32e75SAxel Dörfler { 5755af32e75SAxel Dörfler struct stat sb; 5765af32e75SAxel Dörfler Char *p, *q; 5775af32e75SAxel Dörfler int anymeta; 5785af32e75SAxel Dörfler 5795af32e75SAxel Dörfler /* 5805af32e75SAxel Dörfler * Loop over pattern segments until end of pattern or until 5815af32e75SAxel Dörfler * segment with meta character found. 5825af32e75SAxel Dörfler */ 5835af32e75SAxel Dörfler for (anymeta = 0;;) { 5845af32e75SAxel Dörfler if (*pattern == EOS) { /* End of pattern? */ 5855af32e75SAxel Dörfler *pathend = EOS; 5865af32e75SAxel Dörfler if (g_lstat(pathbuf, &sb, pglob)) 5875af32e75SAxel Dörfler return(0); 5885af32e75SAxel Dörfler 5895af32e75SAxel Dörfler if (((pglob->gl_flags & GLOB_MARK) && 5905af32e75SAxel Dörfler pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) 5915af32e75SAxel Dörfler || (S_ISLNK(sb.st_mode) && 5925af32e75SAxel Dörfler (g_stat(pathbuf, &sb, pglob) == 0) && 5935af32e75SAxel Dörfler S_ISDIR(sb.st_mode)))) { 5945af32e75SAxel Dörfler if (pathend + 1 > pathend_last) 5956e036f04SAxel Dörfler return (GLOB_ABORTED); 5965af32e75SAxel Dörfler *pathend++ = SEP; 5975af32e75SAxel Dörfler *pathend = EOS; 5985af32e75SAxel Dörfler } 5995af32e75SAxel Dörfler ++pglob->gl_matchc; 6006e036f04SAxel Dörfler return(globextend(pathbuf, pglob, limit)); 6015af32e75SAxel Dörfler } 6025af32e75SAxel Dörfler 6035af32e75SAxel Dörfler /* Find end of next segment, copy tentatively to pathend. */ 6045af32e75SAxel Dörfler q = pathend; 6055af32e75SAxel Dörfler p = pattern; 6065af32e75SAxel Dörfler while (*p != EOS && *p != SEP) { 6075af32e75SAxel Dörfler if (ismeta(*p)) 6085af32e75SAxel Dörfler anymeta = 1; 6095af32e75SAxel Dörfler if (q + 1 > pathend_last) 6106e036f04SAxel Dörfler return (GLOB_ABORTED); 6115af32e75SAxel Dörfler *q++ = *p++; 6125af32e75SAxel Dörfler } 6135af32e75SAxel Dörfler 6145af32e75SAxel Dörfler if (!anymeta) { /* No expansion, do next segment. */ 6155af32e75SAxel Dörfler pathend = q; 6165af32e75SAxel Dörfler pattern = p; 6175af32e75SAxel Dörfler while (*pattern == SEP) { 6185af32e75SAxel Dörfler if (pathend + 1 > pathend_last) 6196e036f04SAxel Dörfler return (GLOB_ABORTED); 6205af32e75SAxel Dörfler *pathend++ = *pattern++; 6215af32e75SAxel Dörfler } 6225af32e75SAxel Dörfler } else /* Need expansion, recurse. */ 6236e036f04SAxel Dörfler return(glob3(pathbuf, pathend, pathend_last, pattern, p, 6246e036f04SAxel Dörfler pglob, limit)); 6255af32e75SAxel Dörfler } 6265af32e75SAxel Dörfler /* NOTREACHED */ 6275af32e75SAxel Dörfler } 6285af32e75SAxel Dörfler 6295af32e75SAxel Dörfler static int 6306e036f04SAxel Dörfler glob3(Char *pathbuf, Char *pathend, Char *pathend_last, 6316e036f04SAxel Dörfler Char *pattern, Char *restpattern, 6326e036f04SAxel Dörfler glob_t *pglob, size_t *limit) 6335af32e75SAxel Dörfler { 6345af32e75SAxel Dörfler struct dirent *dp; 6355af32e75SAxel Dörfler DIR *dirp; 6365af32e75SAxel Dörfler int err; 6375af32e75SAxel Dörfler char buf[MAXPATHLEN]; 6385af32e75SAxel Dörfler 6395af32e75SAxel Dörfler /* 6405af32e75SAxel Dörfler * The readdirfunc declaration can't be prototyped, because it is 6415af32e75SAxel Dörfler * assigned, below, to two functions which are prototyped in glob.h 6425af32e75SAxel Dörfler * and dirent.h as taking pointers to differently typed opaque 6435af32e75SAxel Dörfler * structures. 6445af32e75SAxel Dörfler */ 6455af32e75SAxel Dörfler struct dirent *(*readdirfunc)(); 6465af32e75SAxel Dörfler 6475af32e75SAxel Dörfler if (pathend > pathend_last) 6486e036f04SAxel Dörfler return (GLOB_ABORTED); 6495af32e75SAxel Dörfler *pathend = EOS; 6505af32e75SAxel Dörfler errno = 0; 6515af32e75SAxel Dörfler 6525af32e75SAxel Dörfler if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { 6535af32e75SAxel Dörfler /* TODO: don't call for ENOENT or ENOTDIR? */ 6545af32e75SAxel Dörfler if (pglob->gl_errfunc) { 6555af32e75SAxel Dörfler if (g_Ctoc(pathbuf, buf, sizeof(buf))) 6566e036f04SAxel Dörfler return (GLOB_ABORTED); 6575af32e75SAxel Dörfler if (pglob->gl_errfunc(buf, errno) || 6585af32e75SAxel Dörfler pglob->gl_flags & GLOB_ERR) 6596e036f04SAxel Dörfler return (GLOB_ABORTED); 6605af32e75SAxel Dörfler } 6616e036f04SAxel Dörfler return(0); 6625af32e75SAxel Dörfler } 6635af32e75SAxel Dörfler 6645af32e75SAxel Dörfler err = 0; 6655af32e75SAxel Dörfler 6665af32e75SAxel Dörfler /* Search directory for matching names. */ 6675af32e75SAxel Dörfler if (pglob->gl_flags & GLOB_ALTDIRFUNC) 6685af32e75SAxel Dörfler readdirfunc = pglob->gl_readdir; 6695af32e75SAxel Dörfler else 6705af32e75SAxel Dörfler readdirfunc = readdir; 6715af32e75SAxel Dörfler while ((dp = (*readdirfunc)(dirp))) { 6726e036f04SAxel Dörfler char *sc; 6735af32e75SAxel Dörfler Char *dc; 6746e036f04SAxel Dörfler wchar_t wc; 6756e036f04SAxel Dörfler size_t clen; 6766e036f04SAxel Dörfler mbstate_t mbs; 6775af32e75SAxel Dörfler 6785af32e75SAxel Dörfler /* Initial DOT must be matched literally. */ 6795af32e75SAxel Dörfler if (dp->d_name[0] == DOT && *pattern != DOT) 6805af32e75SAxel Dörfler continue; 6816e036f04SAxel Dörfler memset(&mbs, 0, sizeof(mbs)); 6825af32e75SAxel Dörfler dc = pathend; 6836e036f04SAxel Dörfler sc = dp->d_name; 6846e036f04SAxel Dörfler while (dc < pathend_last) { 6856e036f04SAxel Dörfler clen = mbrtowc(&wc, sc, MB_LEN_MAX, &mbs); 6866e036f04SAxel Dörfler if (clen == (size_t)-1 || clen == (size_t)-2) { 6876e036f04SAxel Dörfler wc = *sc; 6886e036f04SAxel Dörfler clen = 1; 6896e036f04SAxel Dörfler memset(&mbs, 0, sizeof(mbs)); 6906e036f04SAxel Dörfler } 6916e036f04SAxel Dörfler if ((*dc++ = wc) == EOS) 6926e036f04SAxel Dörfler break; 6936e036f04SAxel Dörfler sc += clen; 6946e036f04SAxel Dörfler } 6955af32e75SAxel Dörfler if (!match(pathend, pattern, restpattern)) { 6965af32e75SAxel Dörfler *pathend = EOS; 6975af32e75SAxel Dörfler continue; 6985af32e75SAxel Dörfler } 6995af32e75SAxel Dörfler err = glob2(pathbuf, --dc, pathend_last, restpattern, 7005af32e75SAxel Dörfler pglob, limit); 7015af32e75SAxel Dörfler if (err) 7025af32e75SAxel Dörfler break; 7035af32e75SAxel Dörfler } 7045af32e75SAxel Dörfler 7055af32e75SAxel Dörfler if (pglob->gl_flags & GLOB_ALTDIRFUNC) 7065af32e75SAxel Dörfler (*pglob->gl_closedir)(dirp); 7075af32e75SAxel Dörfler else 7085af32e75SAxel Dörfler closedir(dirp); 7096e036f04SAxel Dörfler return(err); 7105af32e75SAxel Dörfler } 7115af32e75SAxel Dörfler 7125af32e75SAxel Dörfler 7135af32e75SAxel Dörfler /* 7145af32e75SAxel Dörfler * Extend the gl_pathv member of a glob_t structure to accomodate a new item, 7155af32e75SAxel Dörfler * add the new item, and update gl_pathc. 7165af32e75SAxel Dörfler * 7175af32e75SAxel Dörfler * This assumes the BSD realloc, which only copies the block when its size 7185af32e75SAxel Dörfler * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic 7195af32e75SAxel Dörfler * behavior. 7205af32e75SAxel Dörfler * 7215af32e75SAxel Dörfler * Return 0 if new item added, error code if memory couldn't be allocated. 7225af32e75SAxel Dörfler * 7235af32e75SAxel Dörfler * Invariant of the glob_t structure: 7245af32e75SAxel Dörfler * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and 7255af32e75SAxel Dörfler * gl_pathv points to (gl_offs + gl_pathc + 1) items. 7265af32e75SAxel Dörfler */ 7275af32e75SAxel Dörfler static int 7286e036f04SAxel Dörfler globextend(const Char *path, glob_t *pglob, size_t *limit) 7295af32e75SAxel Dörfler { 7305af32e75SAxel Dörfler char **pathv; 7316e036f04SAxel Dörfler size_t i, newsize, len; 7325af32e75SAxel Dörfler char *copy; 7335af32e75SAxel Dörfler const Char *p; 7345af32e75SAxel Dörfler 7355af32e75SAxel Dörfler if (*limit && pglob->gl_pathc > *limit) { 7365af32e75SAxel Dörfler errno = 0; 7376e036f04SAxel Dörfler return (GLOB_NOSPACE); 7385af32e75SAxel Dörfler } 7395af32e75SAxel Dörfler 7405af32e75SAxel Dörfler newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); 7415af32e75SAxel Dörfler pathv = pglob->gl_pathv ? 7425af32e75SAxel Dörfler realloc((char *)pglob->gl_pathv, newsize) : 7435af32e75SAxel Dörfler malloc(newsize); 7445af32e75SAxel Dörfler if (pathv == NULL) { 7455af32e75SAxel Dörfler if (pglob->gl_pathv) { 7465af32e75SAxel Dörfler free(pglob->gl_pathv); 7475af32e75SAxel Dörfler pglob->gl_pathv = NULL; 7485af32e75SAxel Dörfler } 7496e036f04SAxel Dörfler return(GLOB_NOSPACE); 7505af32e75SAxel Dörfler } 7515af32e75SAxel Dörfler 7525af32e75SAxel Dörfler if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { 7535af32e75SAxel Dörfler /* first time around -- clear initial gl_offs items */ 7545af32e75SAxel Dörfler pathv += pglob->gl_offs; 7556e036f04SAxel Dörfler for (i = pglob->gl_offs + 1; --i > 0; ) 7565af32e75SAxel Dörfler *--pathv = NULL; 7575af32e75SAxel Dörfler } 7585af32e75SAxel Dörfler pglob->gl_pathv = pathv; 7595af32e75SAxel Dörfler 7605af32e75SAxel Dörfler for (p = path; *p++;) 7615af32e75SAxel Dörfler continue; 7626e036f04SAxel Dörfler len = MB_CUR_MAX * (size_t)(p - path); /* XXX overallocation */ 7635af32e75SAxel Dörfler if ((copy = malloc(len)) != NULL) { 7645af32e75SAxel Dörfler if (g_Ctoc(path, copy, len)) { 7655af32e75SAxel Dörfler free(copy); 7666e036f04SAxel Dörfler return (GLOB_NOSPACE); 7675af32e75SAxel Dörfler } 7685af32e75SAxel Dörfler pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; 7695af32e75SAxel Dörfler } 7705af32e75SAxel Dörfler pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; 7716e036f04SAxel Dörfler return(copy == NULL ? GLOB_NOSPACE : 0); 7725af32e75SAxel Dörfler } 7735af32e75SAxel Dörfler 7745af32e75SAxel Dörfler /* 7755af32e75SAxel Dörfler * pattern matching function for filenames. Each occurrence of the * 7765af32e75SAxel Dörfler * pattern causes a recursion level. 7775af32e75SAxel Dörfler */ 7785af32e75SAxel Dörfler static int 7795af32e75SAxel Dörfler match(Char *name, Char *pat, Char *patend) 7805af32e75SAxel Dörfler { 7815af32e75SAxel Dörfler int ok, negate_range; 7825af32e75SAxel Dörfler Char c, k; 7835af32e75SAxel Dörfler 7845af32e75SAxel Dörfler while (pat < patend) { 7855af32e75SAxel Dörfler c = *pat++; 7865af32e75SAxel Dörfler switch (c & M_MASK) { 7875af32e75SAxel Dörfler case M_ALL: 7885af32e75SAxel Dörfler if (pat == patend) 7896e036f04SAxel Dörfler return(1); 7905af32e75SAxel Dörfler do 7915af32e75SAxel Dörfler if (match(name, pat, patend)) 7926e036f04SAxel Dörfler return(1); 7935af32e75SAxel Dörfler while (*name++ != EOS); 7946e036f04SAxel Dörfler return(0); 7955af32e75SAxel Dörfler case M_ONE: 7965af32e75SAxel Dörfler if (*name++ == EOS) 7976e036f04SAxel Dörfler return(0); 7985af32e75SAxel Dörfler break; 7995af32e75SAxel Dörfler case M_SET: 8005af32e75SAxel Dörfler ok = 0; 8015af32e75SAxel Dörfler if ((k = *name++) == EOS) 8026e036f04SAxel Dörfler return(0); 8035af32e75SAxel Dörfler if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) 8045af32e75SAxel Dörfler ++pat; 8055af32e75SAxel Dörfler while (((c = *pat++) & M_MASK) != M_END) 8065af32e75SAxel Dörfler if ((*pat & M_MASK) == M_RNG) { 8075af32e75SAxel Dörfler if ( 8086e036f04SAxel Dörfler #ifndef __HAIKU__ 8096e036f04SAxel Dörfler __collate_load_error ? 8106e036f04SAxel Dörfler #endif 8115af32e75SAxel Dörfler CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) 8126e036f04SAxel Dörfler #ifndef __HAIKU__ 8136e036f04SAxel Dörfler : 8146e036f04SAxel Dörfler __collate_range_cmp(CHAR(c), CHAR(k)) <= 0 8156e036f04SAxel Dörfler && __collate_range_cmp(CHAR(k), CHAR(pat[1])) <= 0 8166e036f04SAxel Dörfler #endif 8175af32e75SAxel Dörfler ) 8185af32e75SAxel Dörfler ok = 1; 8195af32e75SAxel Dörfler pat += 2; 8205af32e75SAxel Dörfler } else if (c == k) 8215af32e75SAxel Dörfler ok = 1; 8225af32e75SAxel Dörfler if (ok == negate_range) 8236e036f04SAxel Dörfler return(0); 8245af32e75SAxel Dörfler break; 8255af32e75SAxel Dörfler default: 8265af32e75SAxel Dörfler if (*name++ != c) 8276e036f04SAxel Dörfler return(0); 8285af32e75SAxel Dörfler break; 8295af32e75SAxel Dörfler } 8305af32e75SAxel Dörfler } 8316e036f04SAxel Dörfler return(*name == EOS); 8325af32e75SAxel Dörfler } 8335af32e75SAxel Dörfler 8345af32e75SAxel Dörfler /* Free allocated data belonging to a glob_t structure. */ 8355af32e75SAxel Dörfler void 8365af32e75SAxel Dörfler globfree(glob_t *pglob) 8375af32e75SAxel Dörfler { 8386e036f04SAxel Dörfler size_t i; 8395af32e75SAxel Dörfler char **pp; 8405af32e75SAxel Dörfler 8415af32e75SAxel Dörfler if (pglob->gl_pathv != NULL) { 8425af32e75SAxel Dörfler pp = pglob->gl_pathv + pglob->gl_offs; 8435af32e75SAxel Dörfler for (i = pglob->gl_pathc; i--; ++pp) 8445af32e75SAxel Dörfler if (*pp) 8455af32e75SAxel Dörfler free(*pp); 8465af32e75SAxel Dörfler free(pglob->gl_pathv); 8475af32e75SAxel Dörfler pglob->gl_pathv = NULL; 8485af32e75SAxel Dörfler } 8495af32e75SAxel Dörfler } 8505af32e75SAxel Dörfler 8515af32e75SAxel Dörfler static DIR * 8525af32e75SAxel Dörfler g_opendir(Char *str, glob_t *pglob) 8535af32e75SAxel Dörfler { 8545af32e75SAxel Dörfler char buf[MAXPATHLEN]; 8555af32e75SAxel Dörfler 8565af32e75SAxel Dörfler if (!*str) 8575af32e75SAxel Dörfler strcpy(buf, "."); 8585af32e75SAxel Dörfler else { 8595af32e75SAxel Dörfler if (g_Ctoc(str, buf, sizeof(buf))) 8606e036f04SAxel Dörfler return (NULL); 8615af32e75SAxel Dörfler } 8625af32e75SAxel Dörfler 8635af32e75SAxel Dörfler if (pglob->gl_flags & GLOB_ALTDIRFUNC) 8646e036f04SAxel Dörfler return((*pglob->gl_opendir)(buf)); 8655af32e75SAxel Dörfler 8666e036f04SAxel Dörfler return(opendir(buf)); 8675af32e75SAxel Dörfler } 8685af32e75SAxel Dörfler 8695af32e75SAxel Dörfler static int 8705af32e75SAxel Dörfler g_lstat(Char *fn, struct stat *sb, glob_t *pglob) 8715af32e75SAxel Dörfler { 8725af32e75SAxel Dörfler char buf[MAXPATHLEN]; 8735af32e75SAxel Dörfler 8745af32e75SAxel Dörfler if (g_Ctoc(fn, buf, sizeof(buf))) { 8755af32e75SAxel Dörfler errno = ENAMETOOLONG; 8766e036f04SAxel Dörfler return (-1); 8775af32e75SAxel Dörfler } 8785af32e75SAxel Dörfler if (pglob->gl_flags & GLOB_ALTDIRFUNC) 8796e036f04SAxel Dörfler return((*pglob->gl_lstat)(buf, sb)); 8806e036f04SAxel Dörfler return(lstat(buf, sb)); 8815af32e75SAxel Dörfler } 8825af32e75SAxel Dörfler 8835af32e75SAxel Dörfler static int 8845af32e75SAxel Dörfler g_stat(Char *fn, struct stat *sb, glob_t *pglob) 8855af32e75SAxel Dörfler { 8865af32e75SAxel Dörfler char buf[MAXPATHLEN]; 8875af32e75SAxel Dörfler 8885af32e75SAxel Dörfler if (g_Ctoc(fn, buf, sizeof(buf))) { 8895af32e75SAxel Dörfler errno = ENAMETOOLONG; 8906e036f04SAxel Dörfler return (-1); 8915af32e75SAxel Dörfler } 8925af32e75SAxel Dörfler if (pglob->gl_flags & GLOB_ALTDIRFUNC) 8936e036f04SAxel Dörfler return((*pglob->gl_stat)(buf, sb)); 8946e036f04SAxel Dörfler return(stat(buf, sb)); 8955af32e75SAxel Dörfler } 8965af32e75SAxel Dörfler 8976e036f04SAxel Dörfler static const Char * 8986e036f04SAxel Dörfler g_strchr(const Char *str, wchar_t ch) 8995af32e75SAxel Dörfler { 9006e036f04SAxel Dörfler 9015af32e75SAxel Dörfler do { 9025af32e75SAxel Dörfler if (*str == ch) 9036e036f04SAxel Dörfler return (str); 9045af32e75SAxel Dörfler } while (*str++); 9056e036f04SAxel Dörfler return (NULL); 9065af32e75SAxel Dörfler } 9075af32e75SAxel Dörfler 9085af32e75SAxel Dörfler static int 9096e036f04SAxel Dörfler g_Ctoc(const Char *str, char *buf, size_t len) 9105af32e75SAxel Dörfler { 9116e036f04SAxel Dörfler mbstate_t mbs; 9126e036f04SAxel Dörfler size_t clen; 9135af32e75SAxel Dörfler 9146e036f04SAxel Dörfler memset(&mbs, 0, sizeof(mbs)); 9156e036f04SAxel Dörfler while (len >= MB_CUR_MAX) { 9166e036f04SAxel Dörfler clen = wcrtomb(buf, *str, &mbs); 9176e036f04SAxel Dörfler if (clen == (size_t)-1) 9186e036f04SAxel Dörfler return (1); 9196e036f04SAxel Dörfler if (*str == L'\0') 9206e036f04SAxel Dörfler return (0); 9216e036f04SAxel Dörfler str++; 9226e036f04SAxel Dörfler buf += clen; 9236e036f04SAxel Dörfler len -= clen; 9245af32e75SAxel Dörfler } 9256e036f04SAxel Dörfler return (1); 9265af32e75SAxel Dörfler } 9275af32e75SAxel Dörfler 9285af32e75SAxel Dörfler #ifdef DEBUG 9295af32e75SAxel Dörfler static void 9305af32e75SAxel Dörfler qprintf(const char *str, Char *s) 9315af32e75SAxel Dörfler { 9325af32e75SAxel Dörfler Char *p; 9335af32e75SAxel Dörfler 9346e036f04SAxel Dörfler (void)printf("%s:\n", str); 9355af32e75SAxel Dörfler for (p = s; *p; p++) 9366e036f04SAxel Dörfler (void)printf("%c", CHAR(*p)); 9376e036f04SAxel Dörfler (void)printf("\n"); 9385af32e75SAxel Dörfler for (p = s; *p; p++) 9396e036f04SAxel Dörfler (void)printf("%c", *p & M_PROTECT ? '"' : ' '); 9406e036f04SAxel Dörfler (void)printf("\n"); 9415af32e75SAxel Dörfler for (p = s; *p; p++) 9426e036f04SAxel Dörfler (void)printf("%c", ismeta(*p) ? '_' : ' '); 9436e036f04SAxel Dörfler (void)printf("\n"); 9445af32e75SAxel Dörfler } 9455af32e75SAxel Dörfler #endif 946