]> git.saurik.com Git - apple/libc.git/blobdiff - gen/FreeBSD/glob.c
Libc-825.24.tar.gz
[apple/libc.git] / gen / FreeBSD / glob.c
index a289d90a3d091867aa40388dd7ccd90064565e87..e519cc607d8950665e569ba49696c5b60c156673 100644 (file)
@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)glob.c    8.3 (Berkeley) 10/13/93";
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD: src/lib/libc/gen/glob.c,v 1.28 2010/05/12 17:44:00 gordon Exp $");
 
+#include "xlocale_private.h"
+
 /*
  * glob(3) -- a superset of the one defined in POSIX 1003.2.
  *
@@ -89,6 +91,19 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/glob.c,v 1.28 2010/05/12 17:44:00 gordon Ex
 
 #include "collate.h"
 
+#define GLOB_LIMIT_STRING      65536   /* number of readdirs */
+#define GLOB_LIMIT_STAT                128     /* number of stat system calls */
+#define GLOB_LIMIT_READDIR     16384   /* total buffer size of path strings */
+#define GLOB_LIMIT_PATH                1024    /* number of path elements */
+#define GLOB_LIMIT_BRACE       128     /* Number of brace calls */
+
+struct glob_limit {
+       size_t l_string;
+       size_t l_stat;  
+       size_t l_readdir;       
+       size_t l_brace;
+};
+
 #define        DOLLAR          '$'
 #define        DOT             '.'
 #define        EOS             '\0'
@@ -139,62 +154,64 @@ typedef char Char;
 #define        ismeta(c)       (((c)&M_QUOTE) != 0)
 
 
-static int      compare(const void *, const void *);
-static int      g_Ctoc(const Char *, char *, size_t);
-static int      g_lstat(Char *, struct stat *, glob_t *);
-static DIR     *g_opendir(Char *, glob_t *);
-static const Char *g_strchr(const Char *, wchar_t);
+#define compare                __gl_compare
+#define g_Ctoc         __gl_g_Ctoc
+#define g_strchr       __gl_g_strchr
+#define globextend     __gl_globextend
+#define globtilde      __gl_globtilde
+#define match          __gl_match
+__private_extern__ int  compare(const void *, const void *);
+__private_extern__ int  g_Ctoc(const Char *, char *, size_t, locale_t);
+__private_extern__ const Char *g_strchr(const Char *, wchar_t);
+__private_extern__ int  globextend(const Char *, glob_t *, struct glob_limit *, locale_t);
+__private_extern__ const Char *        
+                globtilde(const Char *, Char *, size_t, glob_t *);
+__private_extern__ int  match(Char *, Char *, Char *, locale_t);
+
+
+static int      g_lstat(Char *, struct stat *, glob_t *, locale_t);
+static DIR     *g_opendir(Char *, glob_t *, locale_t);
 #ifdef notdef
 static Char    *g_strcat(Char *, const Char *);
 #endif
-static int      g_stat(Char *, struct stat *, glob_t *);
-static int      glob0(const Char *, glob_t *, size_t *);
-static int      glob1(Char *, glob_t *, size_t *);
-static int      glob2(Char *, Char *, Char *, Char *, glob_t *, size_t *);
-static int      glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, size_t *);
-static int      globextend(const Char *, glob_t *, size_t *);
-static const Char *    
-                globtilde(const Char *, Char *, size_t, glob_t *);
-static int      globexp1(const Char *, glob_t *, size_t *);
-static int      globexp2(const Char *, const Char *, glob_t *, int *, size_t *);
-static int      match(Char *, Char *, Char *);
+static int      g_stat(Char *, struct stat *, glob_t *, locale_t);
+static int      glob0(const Char *, glob_t *, struct glob_limit *, locale_t);
+static int      glob1(Char *, glob_t *, struct glob_limit *, locale_t);
+static int      glob2(Char *, Char *, Char *, Char *, glob_t *, struct glob_limit *, locale_t);
+static int      glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, struct glob_limit *, locale_t);
+static int      globexp1(const Char *, glob_t *, struct glob_limit *, locale_t);
+static int      globexp2(const Char *, const Char *, glob_t *, int *, struct glob_limit *, locale_t);
 #ifdef DEBUG
 static void     qprintf(const char *, Char *);
 #endif
 
-int
-glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob)
+static int
+__glob(const char *pattern, glob_t *pglob)
 {
        const char *patnext;
-       size_t limit;
+       struct glob_limit limit = { 0, 0, 0, 0 };
        Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot;
        mbstate_t mbs;
        wchar_t wc;
        size_t clen;
+       locale_t loc = __current_locale();
+       int mb_cur_max = MB_CUR_MAX_L(loc);
 
        patnext = pattern;
-       if (!(flags & GLOB_APPEND)) {
+       if (!(pglob->gl_flags & GLOB_APPEND)) {
                pglob->gl_pathc = 0;
                pglob->gl_pathv = NULL;
-               if (!(flags & GLOB_DOOFFS))
+               if (!(pglob->gl_flags & GLOB_DOOFFS))
                        pglob->gl_offs = 0;
        }
-       if (flags & GLOB_LIMIT) {
-               limit = pglob->gl_matchc;
-               if (limit == 0)
-                       limit = ARG_MAX;
-       } else
-               limit = 0;
-       pglob->gl_flags = flags & ~GLOB_MAGCHAR;
-       pglob->gl_errfunc = errfunc;
        pglob->gl_matchc = 0;
 
        bufnext = patbuf;
        bufend = bufnext + MAXPATHLEN - 1;
-       if (flags & GLOB_NOESCAPE) {
+       if (pglob->gl_flags & GLOB_NOESCAPE) {
                memset(&mbs, 0, sizeof(mbs));
-               while (bufend - bufnext >= MB_CUR_MAX) {
-                       clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs);
+               while (bufend - bufnext >= mb_cur_max) {
+                       clen = mbrtowc_l(&wc, patnext, MB_LEN_MAX, &mbs, loc);
                        if (clen == (size_t)-1 || clen == (size_t)-2)
                                return (GLOB_NOMATCH);
                        else if (clen == 0)
@@ -205,7 +222,7 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *
        } else {
                /* Protect the quoted characters. */
                memset(&mbs, 0, sizeof(mbs));
-               while (bufend - bufnext >= MB_CUR_MAX) {
+               while (bufend - bufnext >= mb_cur_max) {
                        if (*patnext == QUOTE) {
                                if (*++patnext == EOS) {
                                        *bufnext++ = QUOTE | M_PROTECT;
@@ -214,7 +231,7 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *
                                prot = M_PROTECT;
                        } else
                                prot = 0;
-                       clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs);
+                       clen = mbrtowc_l(&wc, patnext, MB_LEN_MAX, &mbs, loc);
                        if (clen == (size_t)-1 || clen == (size_t)-2)
                                return (GLOB_NOMATCH);
                        else if (clen == 0)
@@ -225,11 +242,34 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *
        }
        *bufnext = EOS;
 
-       if (flags & GLOB_BRACE)
-           return globexp1(patbuf, pglob, &limit);
+       if (pglob->gl_flags & GLOB_BRACE)
+           return globexp1(patbuf, pglob, &limit, loc);
        else
-           return glob0(patbuf, pglob, &limit);
+           return glob0(patbuf, pglob, &limit, loc);
+}
+
+int
+glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob)
+{
+#ifdef __BLOCKS__
+       pglob->gl_flags = flags & ~(GLOB_MAGCHAR | _GLOB_ERR_BLOCK);
+#else /* !__BLOCKS__ */
+       pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+#endif /* __BLOCKS__ */
+       pglob->gl_errfunc = errfunc;
+       return __glob(pattern, pglob);
+}
+
+#ifdef __BLOCKS__
+int
+glob_b(const char *pattern, int flags, int (^errblk)(const char *, int), glob_t *pglob)
+{
+       pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+       pglob->gl_flags |= _GLOB_ERR_BLOCK;
+       pglob->gl_errblk = errblk;
+       return __glob(pattern, pglob);
 }
+#endif /* __BLOCKS__ */
 
 /*
  * Expand recursively a glob {} pattern. When there is no more expansion
@@ -237,20 +277,26 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *
  * characters
  */
 static int
-globexp1(const Char *pattern, glob_t *pglob, size_t *limit)
+globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit, locale_t loc)
 {
        const Char* ptr = pattern;
        int rv;
 
+       if ((pglob->gl_flags & GLOB_LIMIT) &&
+           limit->l_brace++ >= GLOB_LIMIT_BRACE) {
+               errno = 0;
+               return GLOB_NOSPACE;
+       }
+
        /* Protect a single {}, for find(1), like csh */
        if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
-               return glob0(pattern, pglob, limit);
+               return glob0(pattern, pglob, limit, loc);
 
        while ((ptr = g_strchr(ptr, LBRACE)) != NULL)
-               if (!globexp2(ptr, pattern, pglob, &rv, limit))
+               if (!globexp2(ptr, pattern, pglob, &rv, limit, loc))
                        return rv;
 
-       return glob0(pattern, pglob, limit);
+       return glob0(pattern, pglob, limit, loc);
 }
 
 
@@ -260,7 +306,7 @@ globexp1(const Char *pattern, glob_t *pglob, size_t *limit)
  * If it fails then it tries to glob the rest of the pattern and returns.
  */
 static int
-globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, size_t *limit)
+globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, struct glob_limit *limit, locale_t loc)
 {
        int     i;
        Char   *lm, *ls;
@@ -297,7 +343,7 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, size_t *l
 
        /* Non matching braces; just glob the pattern */
        if (i != 0 || *pe == EOS) {
-               *rv = glob0(patbuf, pglob, limit);
+               *rv = glob0(patbuf, pglob, limit, loc);
                return 0;
        }
 
@@ -344,7 +390,7 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, size_t *l
 #ifdef DEBUG
                                qprintf("globexp2:", patbuf);
 #endif
-                               *rv = globexp1(patbuf, pglob, limit);
+                               *rv = globexp1(patbuf, pglob, limit, loc);
 
                                /* move after the comma, to the next string */
                                pl = pm + 1;
@@ -360,10 +406,11 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, size_t *l
 
 
 
+#ifndef BUILDING_VARIANT
 /*
  * expand tilde from the passwd file.
  */
-static const Char *
+__private_extern__ const Char *
 globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
 {
        struct passwd *pwd;
@@ -421,6 +468,7 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
 
        return patbuf;
 }
+#endif /* BUILDING_VARIANT */
 
 
 /*
@@ -430,7 +478,7 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
  * if things went well, nonzero if errors occurred.
  */
 static int
-glob0(const Char *pattern, glob_t *pglob, size_t *limit)
+glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit, locale_t loc)
 {
        const Char *qpatnext;
        int err;
@@ -443,6 +491,10 @@ glob0(const Char *pattern, glob_t *pglob, size_t *limit)
 
        /* We don't need to check for buffer overflow any more. */
        while ((c = *qpatnext++) != EOS) {
+               if (c & M_PROTECT) {
+                       *bufnext++ = CHAR(c);
+                       continue;
+               } /* else */
                switch (c) {
                case LBRACKET:
                        c = *qpatnext;
@@ -493,7 +545,7 @@ glob0(const Char *pattern, glob_t *pglob, size_t *limit)
        qprintf("glob0:", patbuf);
 #endif
 
-       if ((err = glob1(patbuf, pglob, limit)) != 0)
+       if ((err = glob1(patbuf, pglob, limit, loc)) != 0)
                return(err);
 
        /*
@@ -506,7 +558,7 @@ glob0(const Char *pattern, glob_t *pglob, size_t *limit)
                if (((pglob->gl_flags & GLOB_NOCHECK) ||
                    ((pglob->gl_flags & GLOB_NOMAGIC) &&
                        !(pglob->gl_flags & GLOB_MAGCHAR))))
-                       return(globextend(pattern, pglob, limit));
+                       return(globextend(pattern, pglob, limit, loc));
                else
                        return(GLOB_NOMATCH);
        }
@@ -516,14 +568,16 @@ glob0(const Char *pattern, glob_t *pglob, size_t *limit)
        return(0);
 }
 
-static int
+#ifndef BUILDING_VARIANT
+__private_extern__ int
 compare(const void *p, const void *q)
 {
-       return(strcmp(*(char **)p, *(char **)q));
+       return(strcoll(*(char **)p, *(char **)q));
 }
+#endif /* BUILDING_VARIANT */
 
 static int
-glob1(Char *pattern, glob_t *pglob, size_t *limit)
+glob1(Char *pattern, glob_t *pglob, struct glob_limit *limit, locale_t loc)
 {
        Char pathbuf[MAXPATHLEN];
 
@@ -531,7 +585,7 @@ glob1(Char *pattern, glob_t *pglob, size_t *limit)
        if (*pattern == EOS)
                return(0);
        return(glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1,
-           pattern, pglob, limit));
+           pattern, pglob, limit, loc));
 }
 
 /*
@@ -541,7 +595,7 @@ glob1(Char *pattern, glob_t *pglob, size_t *limit)
  */
 static int
 glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern,
-      glob_t *pglob, size_t *limit)
+      glob_t *pglob, struct glob_limit *limit, locale_t loc)
 {
        struct stat sb;
        Char *p, *q;
@@ -554,13 +608,20 @@ glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern,
        for (anymeta = 0;;) {
                if (*pattern == EOS) {          /* End of pattern? */
                        *pathend = EOS;
-                       if (g_lstat(pathbuf, &sb, pglob))
+                       if (g_lstat(pathbuf, &sb, pglob, loc))
                                return(0);
 
+                       if ((pglob->gl_flags & GLOB_LIMIT) &&
+                           limit->l_stat++ >= GLOB_LIMIT_STAT) {
+                               errno = 0;
+                               *pathend++ = SEP;
+                               *pathend = EOS;
+                               return GLOB_NOSPACE;
+                       }
                        if (((pglob->gl_flags & GLOB_MARK) &&
                            pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
                            || (S_ISLNK(sb.st_mode) &&
-                           (g_stat(pathbuf, &sb, pglob) == 0) &&
+                           (g_stat(pathbuf, &sb, pglob, loc) == 0) &&
                            S_ISDIR(sb.st_mode)))) {
                                if (pathend + 1 > pathend_last)
                                        return (GLOB_ABORTED);
@@ -568,7 +629,7 @@ glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern,
                                *pathend = EOS;
                        }
                        ++pglob->gl_matchc;
-                       return(globextend(pathbuf, pglob, limit));
+                       return(globextend(pathbuf, pglob, limit, loc));
                }
 
                /* Find end of next segment, copy tentatively to pathend. */
@@ -592,7 +653,7 @@ glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern,
                        }
                } else                  /* Need expansion, recurse. */
                        return(glob3(pathbuf, pathend, pathend_last, pattern, p,
-                           pglob, limit));
+                           pglob, limit, loc));
        }
        /* NOTREACHED */
 }
@@ -600,7 +661,7 @@ glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern,
 static int
 glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
       Char *pattern, Char *restpattern,
-      glob_t *pglob, size_t *limit)
+      glob_t *pglob, struct glob_limit *limit, locale_t loc)
 {
        struct dirent *dp;
        DIR *dirp;
@@ -620,15 +681,22 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
        *pathend = EOS;
        errno = 0;
 
-       if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
+       if ((dirp = g_opendir(pathbuf, pglob, loc)) == NULL) {
                /* TODO: don't call for ENOENT or ENOTDIR? */
                if (pglob->gl_errfunc) {
-                       if (g_Ctoc(pathbuf, buf, sizeof(buf)))
+                       if (g_Ctoc(pathbuf, buf, sizeof(buf), loc))
                                return (GLOB_ABORTED);
-                       if (pglob->gl_errfunc(buf, errno) ||
-                           pglob->gl_flags & GLOB_ERR)
+#ifdef __BLOCKS__
+                       if (pglob->gl_flags & _GLOB_ERR_BLOCK) {
+                               if (pglob->gl_errblk(buf, errno))
+                                       return (GLOB_ABORTED);
+                       } else
+#endif /* __BLOCKS__ */
+                       if (pglob->gl_errfunc(buf, errno))
                                return (GLOB_ABORTED);
                }
+               if (pglob->gl_flags & GLOB_ERR)
+                       return (GLOB_ABORTED);
                return(0);
        }
 
@@ -646,6 +714,14 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
                size_t clen;
                mbstate_t mbs;
 
+               if ((pglob->gl_flags & GLOB_LIMIT) &&
+                   limit->l_readdir++ >= GLOB_LIMIT_READDIR) {
+                       errno = 0;
+                       *pathend++ = SEP;
+                       *pathend = EOS;
+                       return GLOB_NOSPACE;
+               }
+
                /* Initial DOT must be matched literally. */
                if (dp->d_name[0] == DOT && *pattern != DOT)
                        continue;
@@ -653,7 +729,7 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
                dc = pathend;
                sc = dp->d_name;
                while (dc < pathend_last) {
-                       clen = mbrtowc(&wc, sc, MB_LEN_MAX, &mbs);
+                       clen = mbrtowc_l(&wc, sc, MB_LEN_MAX, &mbs, loc);
                        if (clen == (size_t)-1 || clen == (size_t)-2) {
                                wc = *sc;
                                clen = 1;
@@ -663,12 +739,12 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
                                break;
                        sc += clen;
                }
-               if (!match(pathend, pattern, restpattern)) {
+               if (!match(pathend, pattern, restpattern, loc)) {
                        *pathend = EOS;
                        continue;
                }
                err = glob2(pathbuf, --dc, pathend_last, restpattern,
-                   pglob, limit);
+                   pglob, limit, loc);
                if (err)
                        break;
        }
@@ -681,6 +757,7 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
 }
 
 
+#ifndef BUILDING_VARIANT
 /*
  * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
  * add the new item, and update gl_pathc.
@@ -695,20 +772,18 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
  *     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 *limit)
+__private_extern__ int
+globextend(const Char *path, glob_t *pglob, struct glob_limit *limit, locale_t loc)
 {
        char **pathv;
        size_t i, newsize, len;
        char *copy;
        const Char *p;
 
-       if (*limit && pglob->gl_pathc > *limit) {
-               errno = 0;
-               return (GLOB_NOSPACE);
-       }
-
        newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
+       if ((pglob->gl_flags & GLOB_LIMIT) &&
+           newsize > GLOB_LIMIT_PATH * sizeof(*pathv))
+               goto nospace;
        pathv = pglob->gl_pathv ?
                    realloc((char *)pglob->gl_pathv, newsize) :
                    malloc(newsize);
@@ -730,24 +805,33 @@ globextend(const Char *path, glob_t *pglob, size_t *limit)
 
        for (p = path; *p++;)
                continue;
-       len = MB_CUR_MAX * (size_t)(p - path);  /* XXX overallocation */
+       len = MB_CUR_MAX_L(loc) * (size_t)(p - path);   /* XXX overallocation */
+       limit->l_string += len;
        if ((copy = malloc(len)) != NULL) {
-               if (g_Ctoc(path, copy, len)) {
+               if (g_Ctoc(path, copy, len, loc)) {
                        free(copy);
                        return (GLOB_NOSPACE);
                }
                pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
        }
        pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+
+       if ((pglob->gl_flags & GLOB_LIMIT) &&
+           (newsize + limit->l_string) >= GLOB_LIMIT_STRING)
+               goto nospace;
+
        return(copy == NULL ? GLOB_NOSPACE : 0);
+nospace:
+       errno = 0;
+       return GLOB_NOSPACE;
 }
 
 /*
  * pattern matching function for filenames.  Each occurrence of the *
  * pattern causes a recursion level.
  */
-static int
-match(Char *name, Char *pat, Char *patend)
+__private_extern__ int
+match(Char *name, Char *pat, Char *patend, locale_t loc)
 {
        int ok, negate_range;
        Char c, k;
@@ -759,7 +843,7 @@ match(Char *name, Char *pat, Char *patend)
                        if (pat == patend)
                                return(1);
                        do
-                           if (match(name, pat, patend))
+                           if (match(name, pat, patend, loc))
                                    return(1);
                        while (*name++ != EOS);
                        return(0);
@@ -775,10 +859,10 @@ match(Char *name, Char *pat, Char *patend)
                                ++pat;
                        while (((c = *pat++) & M_MASK) != M_END)
                                if ((*pat & M_MASK) == M_RNG) {
-                                       if (__collate_load_error ?
+                                       if (loc->__collate_load_error ?
                                            CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) :
-                                              __collate_range_cmp(CHAR(c), CHAR(k)) <= 0
-                                           && __collate_range_cmp(CHAR(k), CHAR(pat[1])) <= 0
+                                              __collate_range_cmp(CHAR(c), CHAR(k), loc) <= 0
+                                           && __collate_range_cmp(CHAR(k), CHAR(pat[1]), loc) <= 0
                                           )
                                                ok = 1;
                                        pat += 2;
@@ -812,16 +896,17 @@ globfree(glob_t *pglob)
                pglob->gl_pathv = NULL;
        }
 }
+#endif /* !BUILDING_VARIANT */
 
 static DIR *
-g_opendir(Char *str, glob_t *pglob)
+g_opendir(Char *str, glob_t *pglob, locale_t loc)
 {
        char buf[MAXPATHLEN];
 
        if (!*str)
                strcpy(buf, ".");
        else {
-               if (g_Ctoc(str, buf, sizeof(buf)))
+               if (g_Ctoc(str, buf, sizeof(buf), loc))
                        return (NULL);
        }
 
@@ -832,11 +917,11 @@ g_opendir(Char *str, glob_t *pglob)
 }
 
 static int
-g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
+g_lstat(Char *fn, struct stat *sb, glob_t *pglob, locale_t loc)
 {
        char buf[MAXPATHLEN];
 
-       if (g_Ctoc(fn, buf, sizeof(buf))) {
+       if (g_Ctoc(fn, buf, sizeof(buf), loc)) {
                errno = ENAMETOOLONG;
                return (-1);
        }
@@ -846,11 +931,11 @@ g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
 }
 
 static int
-g_stat(Char *fn, struct stat *sb, glob_t *pglob)
+g_stat(Char *fn, struct stat *sb, glob_t *pglob, locale_t loc)
 {
        char buf[MAXPATHLEN];
 
-       if (g_Ctoc(fn, buf, sizeof(buf))) {
+       if (g_Ctoc(fn, buf, sizeof(buf), loc)) {
                errno = ENAMETOOLONG;
                return (-1);
        }
@@ -859,7 +944,8 @@ g_stat(Char *fn, struct stat *sb, glob_t *pglob)
        return(stat(buf, sb));
 }
 
-static const Char *
+#ifndef BUILDING_VARIANT
+__private_extern__ const Char *
 g_strchr(const Char *str, wchar_t ch)
 {
 
@@ -870,15 +956,16 @@ g_strchr(const Char *str, wchar_t ch)
        return (NULL);
 }
 
-static int
-g_Ctoc(const Char *str, char *buf, size_t len)
+__private_extern__ int
+g_Ctoc(const Char *str, char *buf, size_t len, locale_t loc)
 {
        mbstate_t mbs;
        size_t clen;
+       int mb_cur_max = MB_CUR_MAX_L(loc);
 
        memset(&mbs, 0, sizeof(mbs));
-       while (len >= MB_CUR_MAX) {
-               clen = wcrtomb(buf, *str, &mbs);
+       while (len >= mb_cur_max) {
+               clen = wcrtomb_l(buf, *str, &mbs, loc);
                if (clen == (size_t)-1)
                        return (1);
                if (*str == L'\0')
@@ -889,6 +976,7 @@ g_Ctoc(const Char *str, char *buf, size_t len)
        }
        return (1);
 }
+#endif /* !BUILDING_VARIANT */
 
 #ifdef DEBUG
 static void