LCOV - code coverage report
Current view: top level - openssh-6.6p1/openbsd-compat - glob.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 189 365 51.8 %
Date: 2014-08-01 Functions: 14 17 82.4 %
Branches: 148 423 35.0 %

           Branch data     Line data    Source code
       1                 :            : /*      $OpenBSD: glob.c,v 1.38 2011/09/22 06:27:29 djm Exp $ */
       2                 :            : /*
       3                 :            :  * Copyright (c) 1989, 1993
       4                 :            :  *      The Regents of the University of California.  All rights reserved.
       5                 :            :  *
       6                 :            :  * This code is derived from software contributed to Berkeley by
       7                 :            :  * Guido van Rossum.
       8                 :            :  *
       9                 :            :  * Redistribution and use in source and binary forms, with or without
      10                 :            :  * modification, are permitted provided that the following conditions
      11                 :            :  * are met:
      12                 :            :  * 1. Redistributions of source code must retain the above copyright
      13                 :            :  *    notice, this list of conditions and the following disclaimer.
      14                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      15                 :            :  *    notice, this list of conditions and the following disclaimer in the
      16                 :            :  *    documentation and/or other materials provided with the distribution.
      17                 :            :  * 3. Neither the name of the University nor the names of its contributors
      18                 :            :  *    may be used to endorse or promote products derived from this software
      19                 :            :  *    without specific prior written permission.
      20                 :            :  *
      21                 :            :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      22                 :            :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23                 :            :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24                 :            :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      25                 :            :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26                 :            :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27                 :            :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28                 :            :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29                 :            :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30                 :            :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31                 :            :  * SUCH DAMAGE.
      32                 :            :  */
      33                 :            : 
      34                 :            : /* OPENBSD ORIGINAL: lib/libc/gen/glob.c */
      35                 :            : 
      36                 :            : /*
      37                 :            :  * glob(3) -- a superset of the one defined in POSIX 1003.2.
      38                 :            :  *
      39                 :            :  * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
      40                 :            :  *
      41                 :            :  * Optional extra services, controlled by flags not defined by POSIX:
      42                 :            :  *
      43                 :            :  * GLOB_QUOTE:
      44                 :            :  *      Escaping convention: \ inhibits any special meaning the following
      45                 :            :  *      character might have (except \ at end of string is retained).
      46                 :            :  * GLOB_MAGCHAR:
      47                 :            :  *      Set in gl_flags if pattern contained a globbing character.
      48                 :            :  * GLOB_NOMAGIC:
      49                 :            :  *      Same as GLOB_NOCHECK, but it will only append pattern if it did
      50                 :            :  *      not contain any magic characters.  [Used in csh style globbing]
      51                 :            :  * GLOB_ALTDIRFUNC:
      52                 :            :  *      Use alternately specified directory access functions.
      53                 :            :  * GLOB_TILDE:
      54                 :            :  *      expand ~user/foo to the /home/dir/of/user/foo
      55                 :            :  * GLOB_BRACE:
      56                 :            :  *      expand {1,2}{a,b} to 1a 1b 2a 2b
      57                 :            :  * gl_matchc:
      58                 :            :  *      Number of matches in the current invocation of glob.
      59                 :            :  */
      60                 :            : 
      61                 :            : #include "includes.h"
      62                 :            : 
      63                 :            : #include <sys/types.h>
      64                 :            : #include <sys/stat.h>
      65                 :            : 
      66                 :            : #include <dirent.h>
      67                 :            : #include <ctype.h>
      68                 :            : #include <errno.h>
      69                 :            : #include <limits.h>
      70                 :            : #include <pwd.h>
      71                 :            : #include <stdlib.h>
      72                 :            : #include <string.h>
      73                 :            : #include <unistd.h>
      74                 :            : 
      75                 :            : #if !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || \
      76                 :            :     !defined(GLOB_HAS_GL_MATCHC) || !defined(GLOB_HAS_GL_STATV) || \
      77                 :            :     !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \
      78                 :            :     defined(BROKEN_GLOB)
      79                 :            : 
      80                 :            : #include "charclass.h"
      81                 :            : 
      82                 :            : #define DOLLAR          '$'
      83                 :            : #define DOT             '.'
      84                 :            : #define EOS             '\0'
      85                 :            : #define LBRACKET        '['
      86                 :            : #define NOT             '!'
      87                 :            : #define QUESTION        '?'
      88                 :            : #define QUOTE           '\\'
      89                 :            : #define RANGE           '-'
      90                 :            : #define RBRACKET        ']'
      91                 :            : #define SEP             '/'
      92                 :            : #define STAR            '*'
      93                 :            : #define TILDE           '~'
      94                 :            : #define UNDERSCORE      '_'
      95                 :            : #define LBRACE          '{'
      96                 :            : #define RBRACE          '}'
      97                 :            : #define SLASH           '/'
      98                 :            : #define COMMA           ','
      99                 :            : 
     100                 :            : #ifndef DEBUG
     101                 :            : 
     102                 :            : #define M_QUOTE         0x8000
     103                 :            : #define M_PROTECT       0x4000
     104                 :            : #define M_MASK          0xffff
     105                 :            : #define M_ASCII         0x00ff
     106                 :            : 
     107                 :            : typedef u_short Char;
     108                 :            : 
     109                 :            : #else
     110                 :            : 
     111                 :            : #define M_QUOTE         0x80
     112                 :            : #define M_PROTECT       0x40
     113                 :            : #define M_MASK          0xff
     114                 :            : #define M_ASCII         0x7f
     115                 :            : 
     116                 :            : typedef char Char;
     117                 :            : 
     118                 :            : #endif
     119                 :            : 
     120                 :            : 
     121                 :            : #define CHAR(c)         ((Char)((c)&M_ASCII))
     122                 :            : #define META(c)         ((Char)((c)|M_QUOTE))
     123                 :            : #define M_ALL           META('*')
     124                 :            : #define M_END           META(']')
     125                 :            : #define M_NOT           META('!')
     126                 :            : #define M_ONE           META('?')
     127                 :            : #define M_RNG           META('-')
     128                 :            : #define M_SET           META('[')
     129                 :            : #define M_CLASS         META(':')
     130                 :            : #define ismeta(c)       (((c)&M_QUOTE) != 0)
     131                 :            : 
     132                 :            : #define GLOB_LIMIT_MALLOC       65536
     133                 :            : #define GLOB_LIMIT_STAT         128
     134                 :            : #define GLOB_LIMIT_READDIR      16384
     135                 :            : 
     136                 :            : /* Limit of recursion during matching attempts. */
     137                 :            : #define GLOB_LIMIT_RECUR        64
     138                 :            : 
     139                 :            : struct glob_lim {
     140                 :            :         size_t  glim_malloc;
     141                 :            :         size_t  glim_stat;
     142                 :            :         size_t  glim_readdir;
     143                 :            : };
     144                 :            : 
     145                 :            : struct glob_path_stat {
     146                 :            :         char            *gps_path;
     147                 :            :         struct stat     *gps_stat;
     148                 :            : };
     149                 :            : 
     150                 :            : static int       compare(const void *, const void *);
     151                 :            : static int       compare_gps(const void *, const void *);
     152                 :            : static int       g_Ctoc(const Char *, char *, u_int);
     153                 :            : static int       g_lstat(Char *, struct stat *, glob_t *);
     154                 :            : static DIR      *g_opendir(Char *, glob_t *);
     155                 :            : static Char     *g_strchr(const Char *, int);
     156                 :            : static int       g_strncmp(const Char *, const char *, size_t);
     157                 :            : static int       g_stat(Char *, struct stat *, glob_t *);
     158                 :            : static int       glob0(const Char *, glob_t *, struct glob_lim *);
     159                 :            : static int       glob1(Char *, Char *, glob_t *, struct glob_lim *);
     160                 :            : static int       glob2(Char *, Char *, Char *, Char *, Char *, Char *,
     161                 :            :                     glob_t *, struct glob_lim *);
     162                 :            : static int       glob3(Char *, Char *, Char *, Char *, Char *,
     163                 :            :                     Char *, Char *, glob_t *, struct glob_lim *);
     164                 :            : static int       globextend(const Char *, glob_t *, struct glob_lim *,
     165                 :            :                     struct stat *);
     166                 :            : static const Char *
     167                 :            :                  globtilde(const Char *, Char *, size_t, glob_t *);
     168                 :            : static int       globexp1(const Char *, glob_t *, struct glob_lim *);
     169                 :            : static int       globexp2(const Char *, const Char *, glob_t *,
     170                 :            :                     struct glob_lim *);
     171                 :            : static int       match(Char *, Char *, Char *, int);
     172                 :            : #ifdef DEBUG
     173                 :            : static void      qprintf(const char *, Char *);
     174                 :            : #endif
     175                 :            : 
     176                 :            : int
     177                 :        108 : glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
     178                 :            :     glob_t *pglob)
     179                 :            : {
     180                 :            :         const u_char *patnext;
     181                 :            :         int c;
     182                 :            :         Char *bufnext, *bufend, patbuf[MAXPATHLEN];
     183                 :        108 :         struct glob_lim limit = { 0, 0, 0 };
     184                 :            : 
     185         [ +  - ]:        108 :         if (strnlen(pattern, PATH_MAX) == PATH_MAX)
     186                 :            :                 return(GLOB_NOMATCH);
     187                 :            : 
     188                 :        108 :         patnext = (u_char *) pattern;
     189         [ +  - ]:        108 :         if (!(flags & GLOB_APPEND)) {
     190                 :        108 :                 pglob->gl_pathc = 0;
     191                 :        108 :                 pglob->gl_pathv = NULL;
     192                 :        108 :                 pglob->gl_statv = NULL;
     193         [ +  - ]:        108 :                 if (!(flags & GLOB_DOOFFS))
     194                 :        108 :                         pglob->gl_offs = 0;
     195                 :            :         }
     196                 :        108 :         pglob->gl_flags = flags & ~GLOB_MAGCHAR;
     197                 :        108 :         pglob->gl_errfunc = errfunc;
     198                 :        108 :         pglob->gl_matchc = 0;
     199                 :            : 
     200 [ +  - ][ +  - ]:        108 :         if (pglob->gl_offs < 0 || pglob->gl_pathc < 0 ||
                 [ +  - ]
     201 [ +  - ][ +  - ]:        108 :             pglob->gl_offs >= INT_MAX || pglob->gl_pathc >= INT_MAX ||
     202                 :        108 :             pglob->gl_pathc >= INT_MAX - pglob->gl_offs - 1)
     203                 :            :                 return GLOB_NOSPACE;
     204                 :            : 
     205                 :        108 :         bufnext = patbuf;
     206                 :        108 :         bufend = bufnext + MAXPATHLEN - 1;
     207         [ +  - ]:        108 :         if (flags & GLOB_NOESCAPE)
     208 [ #  # ][ #  # ]:          0 :                 while (bufnext < bufend && (c = *patnext++) != EOS)
     209                 :          0 :                         *bufnext++ = c;
     210                 :            :         else {
     211                 :            :                 /* Protect the quoted characters. */
     212 [ +  - ][ +  + ]:       4325 :                 while (bufnext < bufend && (c = *patnext++) != EOS)
     213         [ +  + ]:       4217 :                         if (c == QUOTE) {
     214         [ -  + ]:          9 :                                 if ((c = *patnext++) == EOS) {
     215                 :          0 :                                         c = QUOTE;
     216                 :          0 :                                         --patnext;
     217                 :            :                                 }
     218                 :          9 :                                 *bufnext++ = c | M_PROTECT;
     219                 :            :                         } else
     220                 :       4217 :                                 *bufnext++ = c;
     221                 :            :         }
     222                 :        108 :         *bufnext = EOS;
     223                 :            : 
     224         [ +  + ]:        108 :         if (flags & GLOB_BRACE)
     225                 :         24 :                 return globexp1(patbuf, pglob, &limit);
     226                 :            :         else
     227                 :         84 :                 return glob0(patbuf, pglob, &limit);
     228                 :            : }
     229                 :            : 
     230                 :            : /*
     231                 :            :  * Expand recursively a glob {} pattern. When there is no more expansion
     232                 :            :  * invoke the standard globbing routine to glob the rest of the magic
     233                 :            :  * characters
     234                 :            :  */
     235                 :            : static int
     236                 :         24 : globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
     237                 :            : {
     238                 :         24 :         const Char* ptr = pattern;
     239                 :            : 
     240                 :            :         /* Protect a single {}, for find(1), like csh */
     241 [ -  + ][ #  # ]:         24 :         if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
                 [ #  # ]
     242                 :         24 :                 return glob0(pattern, pglob, limitp);
     243                 :            : 
     244         [ -  + ]:         24 :         if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
     245                 :          0 :                 return globexp2(ptr, pattern, pglob, limitp);
     246                 :            : 
     247                 :         24 :         return glob0(pattern, pglob, limitp);
     248                 :            : }
     249                 :            : 
     250                 :            : 
     251                 :            : /*
     252                 :            :  * Recursive brace globbing helper. Tries to expand a single brace.
     253                 :            :  * If it succeeds then it invokes globexp1 with the new pattern.
     254                 :            :  * If it fails then it tries to glob the rest of the pattern and returns.
     255                 :            :  */
     256                 :            : static int
     257                 :          0 : globexp2(const Char *ptr, const Char *pattern, glob_t *pglob,
     258                 :            :     struct glob_lim *limitp)
     259                 :            : {
     260                 :            :         int     i, rv;
     261                 :            :         Char   *lm, *ls;
     262                 :            :         const Char *pe, *pm, *pl;
     263                 :            :         Char    patbuf[MAXPATHLEN];
     264                 :            : 
     265                 :            :         /* copy part up to the brace */
     266         [ #  # ]:          0 :         for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
     267                 :            :                 ;
     268                 :          0 :         *lm = EOS;
     269                 :          0 :         ls = lm;
     270                 :            : 
     271                 :            :         /* Find the balanced brace */
     272         [ #  # ]:          0 :         for (i = 0, pe = ++ptr; *pe; pe++)
     273         [ #  # ]:          0 :                 if (*pe == LBRACKET) {
     274                 :            :                         /* Ignore everything between [] */
     275         [ #  # ]:          0 :                         for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
     276                 :            :                                 ;
     277         [ #  # ]:          0 :                         if (*pe == EOS) {
     278                 :            :                                 /*
     279                 :            :                                  * We could not find a matching RBRACKET.
     280                 :            :                                  * Ignore and just look for RBRACE
     281                 :            :                                  */
     282                 :          0 :                                 pe = pm;
     283                 :            :                         }
     284         [ #  # ]:          0 :                 } else if (*pe == LBRACE)
     285                 :          0 :                         i++;
     286         [ #  # ]:          0 :                 else if (*pe == RBRACE) {
     287         [ #  # ]:          0 :                         if (i == 0)
     288                 :            :                                 break;
     289                 :          0 :                         i--;
     290                 :            :                 }
     291                 :            : 
     292                 :            :         /* Non matching braces; just glob the pattern */
     293 [ #  # ][ #  # ]:          0 :         if (i != 0 || *pe == EOS)
     294                 :          0 :                 return glob0(patbuf, pglob, limitp);
     295                 :            : 
     296         [ #  # ]:          0 :         for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
     297   [ #  #  #  #  :          0 :                 switch (*pm) {
                      # ]
     298                 :            :                 case LBRACKET:
     299                 :            :                         /* Ignore everything between [] */
     300         [ #  # ]:          0 :                         for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
     301                 :            :                                 ;
     302         [ #  # ]:          0 :                         if (*pm == EOS) {
     303                 :            :                                 /*
     304                 :            :                                  * We could not find a matching RBRACKET.
     305                 :            :                                  * Ignore and just look for RBRACE
     306                 :            :                                  */
     307                 :          0 :                                 pm = pl;
     308                 :            :                         }
     309                 :            :                         break;
     310                 :            : 
     311                 :            :                 case LBRACE:
     312                 :          0 :                         i++;
     313                 :          0 :                         break;
     314                 :            : 
     315                 :            :                 case RBRACE:
     316         [ #  # ]:          0 :                         if (i) {
     317                 :          0 :                                 i--;
     318                 :          0 :                                 break;
     319                 :            :                         }
     320                 :            :                         /* FALLTHROUGH */
     321                 :            :                 case COMMA:
     322 [ #  # ][ #  # ]:          0 :                         if (i && *pm == COMMA)
     323                 :            :                                 break;
     324                 :            :                         else {
     325                 :            :                                 /* Append the current string */
     326         [ #  # ]:          0 :                                 for (lm = ls; (pl < pm); *lm++ = *pl++)
     327                 :            :                                         ;
     328                 :            : 
     329                 :            :                                 /*
     330                 :            :                                  * Append the rest of the pattern after the
     331                 :            :                                  * closing brace
     332                 :            :                                  */
     333         [ #  # ]:          0 :                                 for (pl = pe + 1; (*lm++ = *pl++) != EOS; )
     334                 :            :                                         ;
     335                 :            : 
     336                 :            :                                 /* Expand the current pattern */
     337                 :            : #ifdef DEBUG
     338                 :            :                                 qprintf("globexp2:", patbuf);
     339                 :            : #endif
     340                 :          0 :                                 rv = globexp1(patbuf, pglob, limitp);
     341         [ #  # ]:          0 :                                 if (rv && rv != GLOB_NOMATCH)
     342                 :            :                                         return rv;
     343                 :            : 
     344                 :            :                                 /* move after the comma, to the next string */
     345                 :          0 :                                 pl = pm + 1;
     346                 :            :                         }
     347                 :          0 :                         break;
     348                 :            : 
     349                 :            :                 default:
     350                 :            :                         break;
     351                 :            :                 }
     352                 :            :         }
     353                 :            :         return 0;
     354                 :            : }
     355                 :            : 
     356                 :            : 
     357                 :            : 
     358                 :            : /*
     359                 :            :  * expand tilde from the passwd file.
     360                 :            :  */
     361                 :            : static const Char *
     362                 :        216 : globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
     363                 :            : {
     364                 :            :         struct passwd *pwd;
     365                 :            :         char *h;
     366                 :            :         const Char *p;
     367                 :            :         Char *b, *eb;
     368                 :            : 
     369 [ -  + ][ #  # ]:        108 :         if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
     370                 :            :                 return pattern;
     371                 :            : 
     372                 :            :         /* Copy up to the end of the string or / */
     373                 :          0 :         eb = &patbuf[patbuf_len - 1];
     374         [ #  # ]:          0 :         for (p = pattern + 1, h = (char *) patbuf;
     375 [ #  # ][ #  # ]:          0 :             h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
     376                 :            :                 ;
     377                 :            : 
     378                 :          0 :         *h = EOS;
     379                 :            : 
     380                 :            : #if 0
     381                 :            :         if (h == (char *)eb)
     382                 :            :                 return what;
     383                 :            : #endif
     384                 :            : 
     385         [ #  # ]:          0 :         if (((char *) patbuf)[0] == EOS) {
     386                 :            :                 /*
     387                 :            :                  * handle a plain ~ or ~/ by expanding $HOME
     388                 :            :                  * first and then trying the password file
     389                 :            :                  */
     390                 :            : #if 0
     391                 :            :                 if (issetugid() != 0 || (h = getenv("HOME")) == NULL) {
     392                 :            : #endif
     393 [ #  # ][ #  # ]:          0 :                 if ((getuid() != geteuid()) || (h = getenv("HOME")) == NULL) {
     394         [ #  # ]:          0 :                         if ((pwd = getpwuid(getuid())) == NULL)
     395                 :            :                                 return pattern;
     396                 :            :                         else
     397                 :          0 :                                 h = pwd->pw_dir;
     398                 :            :                 }
     399                 :            :         } else {
     400                 :            :                 /*
     401                 :            :                  * Expand a ~user
     402                 :            :                  */
     403         [ #  # ]:          0 :                 if ((pwd = getpwnam((char*) patbuf)) == NULL)
     404                 :            :                         return pattern;
     405                 :            :                 else
     406                 :          0 :                         h = pwd->pw_dir;
     407                 :            :         }
     408                 :            : 
     409                 :            :         /* Copy the home directory */
     410 [ #  # ][ #  # ]:          0 :         for (b = patbuf; b < eb && *h; *b++ = *h++)
     411                 :            :                 ;
     412                 :            : 
     413                 :            :         /* Append the rest of the pattern */
     414 [ #  # ][ #  # ]:          0 :         while (b < eb && (*b++ = *p++) != EOS)
     415                 :            :                 ;
     416                 :          0 :         *b = EOS;
     417                 :            : 
     418                 :            :         return patbuf;
     419                 :            : }
     420                 :            : 
     421                 :            : static int
     422                 :            : g_strncmp(const Char *s1, const char *s2, size_t n)
     423                 :            : {
     424                 :            :         int rv = 0;
     425                 :            : 
     426         [ #  # ]:          0 :         while (n--) {
     427                 :          0 :                 rv = *(Char *)s1 - *(const unsigned char *)s2++;
     428         [ #  # ]:          0 :                 if (rv)
     429                 :            :                         break;
     430         [ #  # ]:          0 :                 if (*s1++ == '\0')
     431                 :            :                         break;
     432                 :            :         }
     433                 :            :         return rv;
     434                 :            : }
     435                 :            : 
     436                 :            : static int
     437                 :          0 : g_charclass(const Char **patternp, Char **bufnextp)
     438                 :            : {
     439                 :          0 :         const Char *pattern = *patternp + 1;
     440                 :          0 :         Char *bufnext = *bufnextp;
     441                 :            :         const Char *colon;
     442                 :            :         struct cclass *cc;
     443                 :            :         size_t len;
     444                 :            : 
     445 [ #  # ][ #  # ]:          0 :         if ((colon = g_strchr(pattern, ':')) == NULL || colon[1] != ']')
     446                 :            :                 return 1;       /* not a character class */
     447                 :            : 
     448                 :          0 :         len = (size_t)(colon - pattern);
     449         [ #  # ]:          0 :         for (cc = cclasses; cc->name != NULL; cc++) {
     450 [ #  # ][ #  # ]:          0 :                 if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == '\0')
     451                 :            :                         break;
     452                 :            :         }
     453         [ #  # ]:          0 :         if (cc->name == NULL)
     454                 :            :                 return -1;      /* invalid character class */
     455                 :          0 :         *bufnext++ = M_CLASS;
     456                 :          0 :         *bufnext++ = (Char)(cc - &cclasses[0]);
     457                 :          0 :         *bufnextp = bufnext;
     458                 :          0 :         *patternp += len + 3;
     459                 :            : 
     460                 :          0 :         return 0;
     461                 :            : }
     462                 :            : 
     463                 :            : /*
     464                 :            :  * The main glob() routine: compiles the pattern (optionally processing
     465                 :            :  * quotes), calls glob1() to do the real pattern matching, and finally
     466                 :            :  * sorts the list (unless unsorted operation is requested).  Returns 0
     467                 :            :  * if things went well, nonzero if errors occurred.  It is not an error
     468                 :            :  * to find no matches.
     469                 :            :  */
     470                 :            : static int
     471                 :        108 : glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
     472                 :            : {
     473                 :            :         const Char *qpatnext;
     474                 :            :         int c, err, oldpathc;
     475                 :            :         Char *bufnext, patbuf[MAXPATHLEN];
     476                 :            : 
     477                 :        108 :         qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
     478                 :        108 :         oldpathc = pglob->gl_pathc;
     479                 :        108 :         bufnext = patbuf;
     480                 :            : 
     481                 :            :         /* We don't need to check for buffer overflow any more. */
     482         [ +  + ]:       4325 :         while ((c = *qpatnext++) != EOS) {
     483   [ -  +  +  + ]:       4217 :                 switch (c) {
     484                 :            :                 case LBRACKET:
     485                 :          0 :                         c = *qpatnext;
     486         [ #  # ]:          0 :                         if (c == NOT)
     487                 :          0 :                                 ++qpatnext;
     488 [ #  # ][ #  # ]:          0 :                         if (*qpatnext == EOS ||
     489                 :          0 :                             g_strchr(qpatnext+1, RBRACKET) == NULL) {
     490                 :          0 :                                 *bufnext++ = LBRACKET;
     491         [ #  # ]:          0 :                                 if (c == NOT)
     492                 :          0 :                                         --qpatnext;
     493                 :            :                                 break;
     494                 :            :                         }
     495                 :          0 :                         *bufnext++ = M_SET;
     496         [ #  # ]:          0 :                         if (c == NOT)
     497                 :          0 :                                 *bufnext++ = M_NOT;
     498                 :          0 :                         c = *qpatnext++;
     499                 :            :                         do {
     500 [ #  # ][ #  # ]:          0 :                                 if (c == LBRACKET && *qpatnext == ':') {
     501                 :            :                                         do {
     502                 :          0 :                                                 err = g_charclass(&qpatnext,
     503                 :            :                                                     &bufnext);
     504         [ #  # ]:          0 :                                                 if (err)
     505                 :            :                                                         break;
     506                 :          0 :                                                 c = *qpatnext++;
     507 [ #  # ][ #  # ]:          0 :                                         } while (c == LBRACKET && *qpatnext == ':');
     508 [ #  # ][ #  # ]:          0 :                                         if (err == -1 &&
     509                 :          0 :                                             !(pglob->gl_flags & GLOB_NOCHECK))
     510                 :            :                                                 return GLOB_NOMATCH;
     511         [ #  # ]:          0 :                                         if (c == RBRACKET)
     512                 :            :                                                 break;
     513                 :            :                                 }
     514                 :          0 :                                 *bufnext++ = CHAR(c);
     515 [ #  # ][ #  # ]:          0 :                                 if (*qpatnext == RANGE &&
     516                 :          0 :                                     (c = qpatnext[1]) != RBRACKET) {
     517                 :          0 :                                         *bufnext++ = M_RNG;
     518                 :          0 :                                         *bufnext++ = CHAR(c);
     519                 :          0 :                                         qpatnext += 2;
     520                 :            :                                 }
     521         [ #  # ]:          0 :                         } while ((c = *qpatnext++) != RBRACKET);
     522                 :          0 :                         pglob->gl_flags |= GLOB_MAGCHAR;
     523                 :          0 :                         *bufnext++ = M_END;
     524                 :          0 :                         break;
     525                 :            :                 case QUESTION:
     526                 :          2 :                         pglob->gl_flags |= GLOB_MAGCHAR;
     527                 :          2 :                         *bufnext++ = M_ONE;
     528                 :          2 :                         break;
     529                 :            :                 case STAR:
     530                 :          8 :                         pglob->gl_flags |= GLOB_MAGCHAR;
     531                 :            :                         /* collapse adjacent stars to one,
     532                 :            :                          * to avoid exponential behavior
     533                 :            :                          */
     534 [ +  - ][ +  - ]:          8 :                         if (bufnext == patbuf || bufnext[-1] != M_ALL)
     535                 :          8 :                                 *bufnext++ = M_ALL;
     536                 :            :                         break;
     537                 :            :                 default:
     538                 :       4207 :                         *bufnext++ = CHAR(c);
     539                 :       4217 :                         break;
     540                 :            :                 }
     541                 :            :         }
     542                 :        108 :         *bufnext = EOS;
     543                 :            : #ifdef DEBUG
     544                 :            :         qprintf("glob0:", patbuf);
     545                 :            : #endif
     546                 :            : 
     547         [ +  - ]:        108 :         if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, limitp)) != 0)
     548                 :            :                 return(err);
     549                 :            : 
     550                 :            :         /*
     551                 :            :          * If there was no match we are going to append the pattern
     552                 :            :          * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
     553                 :            :          * and the pattern did not contain any magic characters
     554                 :            :          * GLOB_NOMAGIC is there just for compatibility with csh.
     555                 :            :          */
     556         [ +  + ]:        108 :         if (pglob->gl_pathc == oldpathc) {
     557 [ +  + ][ -  + ]:          6 :                 if ((pglob->gl_flags & GLOB_NOCHECK) ||
     558                 :          3 :                     ((pglob->gl_flags & GLOB_NOMAGIC) &&
     559                 :            :                     !(pglob->gl_flags & GLOB_MAGCHAR)))
     560                 :          3 :                         return(globextend(pattern, pglob, limitp, NULL));
     561                 :            :                 else
     562                 :            :                         return(GLOB_NOMATCH);
     563                 :            :         }
     564         [ +  + ]:        102 :         if (!(pglob->gl_flags & GLOB_NOSORT)) {
     565         [ -  + ]:         78 :                 if ((pglob->gl_flags & GLOB_KEEPSTAT)) {
     566                 :            :                         /* Keep the paths and stat info synced during sort */
     567                 :            :                         struct glob_path_stat *path_stat;
     568                 :            :                         int i;
     569                 :          0 :                         int n = pglob->gl_pathc - oldpathc;
     570                 :          0 :                         int o = pglob->gl_offs + oldpathc;
     571                 :            : 
     572         [ #  # ]:          0 :                         if ((path_stat = calloc(n, sizeof(*path_stat))) == NULL)
     573                 :            :                                 return GLOB_NOSPACE;
     574         [ #  # ]:          0 :                         for (i = 0; i < n; i++) {
     575                 :          0 :                                 path_stat[i].gps_path = pglob->gl_pathv[o + i];
     576                 :          0 :                                 path_stat[i].gps_stat = pglob->gl_statv[o + i];
     577                 :            :                         }
     578                 :          0 :                         qsort(path_stat, n, sizeof(*path_stat), compare_gps);
     579         [ #  # ]:          0 :                         for (i = 0; i < n; i++) {
     580                 :          0 :                                 pglob->gl_pathv[o + i] = path_stat[i].gps_path;
     581                 :          0 :                                 pglob->gl_statv[o + i] = path_stat[i].gps_stat;
     582                 :            :                         }
     583                 :          0 :                         free(path_stat);
     584                 :            :                 } else {
     585                 :         78 :                         qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
     586                 :         78 :                             pglob->gl_pathc - oldpathc, sizeof(char *),
     587                 :            :                             compare);
     588                 :            :                 }
     589                 :            :         }
     590                 :            :         return(0);
     591                 :            : }
     592                 :            : 
     593                 :            : static int
     594                 :        173 : compare(const void *p, const void *q)
     595                 :            : {
     596                 :        173 :         return(strcmp(*(char **)p, *(char **)q));
     597                 :            : }
     598                 :            : 
     599                 :            : static int
     600                 :          0 : compare_gps(const void *_p, const void *_q)
     601                 :            : {
     602                 :          0 :         const struct glob_path_stat *p = (const struct glob_path_stat *)_p;
     603                 :          0 :         const struct glob_path_stat *q = (const struct glob_path_stat *)_q;
     604                 :            : 
     605                 :          0 :         return(strcmp(p->gps_path, q->gps_path));
     606                 :            : }
     607                 :            : 
     608                 :            : static int
     609                 :        108 : glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp)
     610                 :            : {
     611                 :            :         Char pathbuf[MAXPATHLEN];
     612                 :            : 
     613                 :            :         /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
     614         [ +  - ]:        108 :         if (*pattern == EOS)
     615                 :            :                 return(0);
     616                 :        108 :         return(glob2(pathbuf, pathbuf+MAXPATHLEN-1,
     617                 :            :             pathbuf, pathbuf+MAXPATHLEN-1,
     618                 :            :             pattern, pattern_last, pglob, limitp));
     619                 :            : }
     620                 :            : 
     621                 :            : /*
     622                 :            :  * The functions glob2 and glob3 are mutually recursive; there is one level
     623                 :            :  * of recursion for each segment in the pattern that contains one or more
     624                 :            :  * meta characters.
     625                 :            :  */
     626                 :            : static int
     627                 :        181 : glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
     628                 :            :     Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp)
     629                 :            : {
     630                 :            :         struct stat sb;
     631                 :            :         Char *p, *q;
     632                 :            :         int anymeta;
     633                 :            : 
     634                 :            :         /*
     635                 :            :          * Loop over pattern segments until end of pattern or until
     636                 :            :          * segment with meta character found.
     637                 :            :          */
     638                 :        181 :         for (anymeta = 0;;) {
     639         [ +  + ]:        909 :                 if (*pattern == EOS) {          /* End of pattern? */
     640                 :        171 :                         *pathend = EOS;
     641         [ +  + ]:        171 :                         if (g_lstat(pathbuf, &sb, pglob))
     642                 :            :                                 return(0);
     643                 :            : 
     644 [ -  + ][ #  # ]:        165 :                         if ((pglob->gl_flags & GLOB_LIMIT) &&
     645                 :          0 :                             limitp->glim_stat++ >= GLOB_LIMIT_STAT) {
     646                 :          0 :                                 errno = 0;
     647                 :          0 :                                 *pathend++ = SEP;
     648                 :          0 :                                 *pathend = EOS;
     649                 :          0 :                                 return(GLOB_NOSPACE);
     650                 :            :                         }
     651                 :            : 
     652 [ +  + ][ +  - ]:        165 :                         if (((pglob->gl_flags & GLOB_MARK) &&
     653 [ +  + ][ +  + ]:        150 :                             pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
     654         [ +  - ]:         10 :                             (S_ISLNK(sb.st_mode) &&
     655         [ -  + ]:         20 :                             (g_stat(pathbuf, &sb, pglob) == 0) &&
     656                 :         10 :                             S_ISDIR(sb.st_mode)))) {
     657         [ +  - ]:         10 :                                 if (pathend+1 > pathend_last)
     658                 :            :                                         return (1);
     659                 :         10 :                                 *pathend++ = SEP;
     660                 :         10 :                                 *pathend = EOS;
     661                 :            :                         }
     662                 :        165 :                         ++pglob->gl_matchc;
     663                 :        165 :                         return(globextend(pathbuf, pglob, limitp, &sb));
     664                 :            :                 }
     665                 :            : 
     666                 :            :                 /* Find end of next segment, copy tentatively to pathend. */
     667                 :            :                 q = pathend;
     668                 :            :                 p = pattern;
     669         [ +  + ]:       4325 :                 while (*p != EOS && *p != SEP) {
     670         [ +  + ]:       3587 :                         if (ismeta(*p))
     671                 :         10 :                                 anymeta = 1;
     672         [ +  - ]:       3587 :                         if (q+1 > pathend_last)
     673                 :            :                                 return (1);
     674                 :       3587 :                         *q++ = *p++;
     675                 :            :                 }
     676                 :            : 
     677         [ +  + ]:        738 :                 if (!anymeta) {         /* No expansion, do next segment. */
     678                 :            :                         pathend = q;
     679                 :            :                         pattern = p;
     680         [ +  + ]:       1358 :                         while (*pattern == SEP) {
     681         [ +  - ]:        630 :                                 if (pathend+1 > pathend_last)
     682                 :            :                                         return (1);
     683                 :        630 :                                 *pathend++ = *pattern++;
     684                 :            :                         }
     685                 :            :                 } else
     686                 :            :                         /* Need expansion, recurse. */
     687                 :         10 :                         return(glob3(pathbuf, pathbuf_last, pathend,
     688                 :            :                             pathend_last, pattern, p, pattern_last,
     689                 :            :                             pglob, limitp));
     690                 :            :         }
     691                 :            :         /* NOTREACHED */
     692                 :            : }
     693                 :            : 
     694                 :            : static int
     695                 :         10 : glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
     696                 :            :     Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob,
     697                 :            :     struct glob_lim *limitp)
     698                 :            : {
     699                 :            :         struct dirent *dp;
     700                 :            :         DIR *dirp;
     701                 :            :         int err;
     702                 :            :         char buf[MAXPATHLEN];
     703                 :            : 
     704                 :            :         /*
     705                 :            :          * The readdirfunc declaration can't be prototyped, because it is
     706                 :            :          * assigned, below, to two functions which are prototyped in glob.h
     707                 :            :          * and dirent.h as taking pointers to differently typed opaque
     708                 :            :          * structures.
     709                 :            :          */
     710                 :            :         struct dirent *(*readdirfunc)(void *);
     711                 :            : 
     712         [ +  - ]:         10 :         if (pathend > pathend_last)
     713                 :            :                 return (1);
     714                 :         10 :         *pathend = EOS;
     715                 :         10 :         errno = 0;
     716                 :            : 
     717         [ -  + ]:         10 :         if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
     718                 :            :                 /* TODO: don't call for ENOENT or ENOTDIR? */
     719         [ #  # ]:          0 :                 if (pglob->gl_errfunc) {
     720         [ #  # ]:          0 :                         if (g_Ctoc(pathbuf, buf, sizeof(buf)))
     721                 :            :                                 return(GLOB_ABORTED);
     722 [ #  # ][ #  # ]:          0 :                         if (pglob->gl_errfunc(buf, errno) ||
     723                 :          0 :                             pglob->gl_flags & GLOB_ERR)
     724                 :            :                                 return(GLOB_ABORTED);
     725                 :            :                 }
     726                 :            :                 return(0);
     727                 :            :         }
     728                 :            : 
     729                 :         10 :         err = 0;
     730                 :            : 
     731                 :            :         /* Search directory for matching names. */
     732         [ +  + ]:         10 :         if (pglob->gl_flags & GLOB_ALTDIRFUNC)
     733                 :         10 :                 readdirfunc = pglob->gl_readdir;
     734                 :            :         else
     735                 :            :                 readdirfunc = (struct dirent *(*)(void *))readdir;
     736         [ +  + ]:       1235 :         while ((dp = (*readdirfunc)(dirp))) {
     737                 :            :                 u_char *sc;
     738                 :            :                 Char *dc;
     739                 :            : 
     740 [ -  + ][ #  # ]:       1225 :                 if ((pglob->gl_flags & GLOB_LIMIT) &&
     741                 :          0 :                     limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) {
     742                 :          0 :                         errno = 0;
     743                 :          0 :                         *pathend++ = SEP;
     744                 :          0 :                         *pathend = EOS;
     745                 :          0 :                         err = GLOB_NOSPACE;
     746                 :          0 :                         break;
     747                 :            :                 }
     748                 :            : 
     749                 :            :                 /* Initial DOT must be matched literally. */
     750 [ +  + ][ +  - ]:       1225 :                 if (dp->d_name[0] == DOT && *pattern != DOT)
     751                 :         20 :                         continue;
     752                 :       1205 :                 dc = pathend;
     753                 :       1205 :                 sc = (u_char *) dp->d_name;
     754 [ +  - ][ +  + ]:       9811 :                 while (dc < pathend_last && (*dc++ = *sc++) != EOS)
     755                 :            :                         ;
     756         [ -  + ]:       1205 :                 if (dc >= pathend_last) {
     757                 :          0 :                         *dc = EOS;
     758                 :          0 :                         err = 1;
     759                 :          0 :                         break;
     760                 :            :                 }
     761                 :            : 
     762         [ +  + ]:       1205 :                 if (!match(pathend, pattern, restpattern, GLOB_LIMIT_RECUR)) {
     763                 :       1132 :                         *pathend = EOS;
     764                 :       1132 :                         continue;
     765                 :            :                 }
     766                 :         73 :                 err = glob2(pathbuf, pathbuf_last, --dc, pathend_last,
     767                 :            :                     restpattern, restpattern_last, pglob, limitp);
     768         [ +  - ]:       1225 :                 if (err)
     769                 :            :                         break;
     770                 :            :         }
     771                 :            : 
     772         [ +  + ]:         10 :         if (pglob->gl_flags & GLOB_ALTDIRFUNC)
     773                 :          6 :                 (*pglob->gl_closedir)(dirp);
     774                 :            :         else
     775                 :          4 :                 closedir(dirp);
     776                 :         10 :         return(err);
     777                 :            : }
     778                 :            : 
     779                 :            : 
     780                 :            : /*
     781                 :            :  * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
     782                 :            :  * add the new item, and update gl_pathc.
     783                 :            :  *
     784                 :            :  * This assumes the BSD realloc, which only copies the block when its size
     785                 :            :  * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
     786                 :            :  * behavior.
     787                 :            :  *
     788                 :            :  * Return 0 if new item added, error code if memory couldn't be allocated.
     789                 :            :  *
     790                 :            :  * Invariant of the glob_t structure:
     791                 :            :  *      Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
     792                 :            :  *      gl_pathv points to (gl_offs + gl_pathc + 1) items.
     793                 :            :  */
     794                 :            : static int
     795                 :        168 : globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp,
     796                 :            :     struct stat *sb)
     797                 :            : {
     798                 :            :         char **pathv;
     799                 :            :         ssize_t i;
     800                 :            :         size_t newn, len;
     801                 :        168 :         char *copy = NULL;
     802                 :            :         const Char *p;
     803                 :            :         struct stat **statv;
     804                 :            : 
     805                 :        168 :         newn = 2 + pglob->gl_pathc + pglob->gl_offs;
     806 [ +  - ][ +  - ]:        168 :         if (pglob->gl_offs >= INT_MAX ||
     807                 :            :             pglob->gl_pathc >= INT_MAX ||
     808                 :            :             newn >= INT_MAX ||
     809         [ -  + ]:        168 :             SIZE_MAX / sizeof(*pathv) <= newn ||
     810                 :            :             SIZE_MAX / sizeof(*statv) <= newn) {
     811                 :            :  nospace:
     812         [ #  # ]:          0 :                 for (i = pglob->gl_offs; i < (ssize_t)(newn - 2); i++) {
     813 [ #  # ][ #  # ]:          0 :                         if (pglob->gl_pathv && pglob->gl_pathv[i])
     814                 :          0 :                                 free(pglob->gl_pathv[i]);
     815 [ #  # ][ #  # ]:          0 :                         if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 &&
     816         [ #  # ]:          0 :                             pglob->gl_pathv && pglob->gl_pathv[i])
     817                 :          0 :                                 free(pglob->gl_statv[i]);
     818                 :            :                 }
     819         [ #  # ]:          0 :                 if (pglob->gl_pathv) {
     820                 :          0 :                         free(pglob->gl_pathv);
     821                 :          0 :                         pglob->gl_pathv = NULL;
     822                 :            :                 }
     823         [ #  # ]:          0 :                 if (pglob->gl_statv) {
     824                 :          0 :                         free(pglob->gl_statv);
     825                 :          0 :                         pglob->gl_statv = NULL;
     826                 :            :                 }
     827                 :            :                 return(GLOB_NOSPACE);
     828                 :            :         }
     829                 :            : 
     830                 :        168 :         pathv = realloc(pglob->gl_pathv, newn * sizeof(*pathv));
     831         [ -  + ]:        168 :         if (pathv == NULL)
     832                 :            :                 goto nospace;
     833 [ +  + ][ -  + ]:        168 :         if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
     834                 :            :                 /* first time around -- clear initial gl_offs items */
     835                 :          0 :                 pathv += pglob->gl_offs;
     836         [ #  # ]:          0 :                 for (i = pglob->gl_offs; --i >= 0; )
     837                 :          0 :                         *--pathv = NULL;
     838                 :            :         }
     839                 :        168 :         pglob->gl_pathv = pathv;
     840                 :            : 
     841         [ +  + ]:        168 :         if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) {
     842                 :         24 :                 statv = realloc(pglob->gl_statv, newn * sizeof(*statv));
     843         [ -  + ]:         24 :                 if (statv == NULL)
     844                 :            :                         goto nospace;
     845 [ +  - ][ -  + ]:         24 :                 if (pglob->gl_statv == NULL && pglob->gl_offs > 0) {
     846                 :            :                         /* first time around -- clear initial gl_offs items */
     847                 :          0 :                         statv += pglob->gl_offs;
     848         [ #  # ]:          0 :                         for (i = pglob->gl_offs; --i >= 0; )
     849                 :          0 :                                 *--statv = NULL;
     850                 :            :                 }
     851                 :         24 :                 pglob->gl_statv = statv;
     852         [ -  + ]:         24 :                 if (sb == NULL)
     853                 :          0 :                         statv[pglob->gl_offs + pglob->gl_pathc] = NULL;
     854                 :            :                 else {
     855                 :         24 :                         limitp->glim_malloc += sizeof(**statv);
     856 [ -  + ][ #  # ]:         24 :                         if ((pglob->gl_flags & GLOB_LIMIT) &&
     857                 :            :                             limitp->glim_malloc >= GLOB_LIMIT_MALLOC) {
     858                 :          0 :                                 errno = 0;
     859                 :            :                                 return(GLOB_NOSPACE);
     860                 :            :                         }
     861         [ +  - ]:         24 :                         if ((statv[pglob->gl_offs + pglob->gl_pathc] =
     862                 :         24 :                             malloc(sizeof(**statv))) == NULL)
     863                 :            :                                 goto copy_error;
     864                 :         24 :                         memcpy(statv[pglob->gl_offs + pglob->gl_pathc], sb,
     865                 :            :                             sizeof(*sb));
     866                 :            :                 }
     867                 :         24 :                 statv[pglob->gl_offs + pglob->gl_pathc + 1] = NULL;
     868                 :            :         }
     869                 :            : 
     870         [ +  + ]:       5047 :         for (p = path; *p++;)
     871                 :            :                 ;
     872                 :        168 :         len = (size_t)(p - path);
     873                 :        168 :         limitp->glim_malloc += len;
     874         [ +  - ]:        168 :         if ((copy = malloc(len)) != NULL) {
     875         [ -  + ]:        336 :                 if (g_Ctoc(path, copy, len)) {
     876                 :          0 :                         free(copy);
     877                 :            :                         return(GLOB_NOSPACE);
     878                 :            :                 }
     879                 :        168 :                 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
     880                 :            :         }
     881                 :        168 :         pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
     882                 :            : 
     883 [ -  + ][ #  # ]:        168 :         if ((pglob->gl_flags & GLOB_LIMIT) &&
     884                 :          0 :             (newn * sizeof(*pathv)) + limitp->glim_malloc >
     885                 :            :             GLOB_LIMIT_MALLOC) {
     886                 :          0 :                 errno = 0;
     887                 :            :                 return(GLOB_NOSPACE);
     888                 :            :         }
     889                 :            :  copy_error:
     890         [ +  - ]:        168 :         return(copy == NULL ? GLOB_NOSPACE : 0);
     891                 :            : }
     892                 :            : 
     893                 :            : 
     894                 :            : /*
     895                 :            :  * pattern matching function for filenames.  Each occurrence of the *
     896                 :            :  * pattern causes a recursion level.
     897                 :            :  */
     898                 :            : static int
     899                 :       1205 : match(Char *name, Char *pat, Char *patend, int recur)
     900                 :            : {
     901                 :            :         int ok, negate_range;
     902                 :            :         Char c, k;
     903                 :            : 
     904         [ +  - ]:       1205 :         if (recur-- == 0)
     905                 :            :                 return(GLOB_NOSPACE);
     906                 :            : 
     907         [ +  + ]:       1348 :         while (pat < patend) {
     908                 :       1322 :                 c = *pat++;
     909   [ +  +  -  + ]:       1322 :                 switch (c & M_MASK) {
     910                 :            :                 case M_ALL:
     911 [ -  + ][ #  # ]:         69 :                         while (pat < patend && (*pat & M_MASK) == M_ALL)
     912                 :          0 :                                 pat++;  /* eat consecutive '*' */
     913         [ -  + ]:         69 :                         if (pat == patend)
     914                 :            :                                 return(1);
     915                 :            :                         do {
     916         [ #  # ]:          0 :                             if (match(name, pat, patend, recur))
     917                 :            :                                     return(1);
     918         [ #  # ]:          0 :                         } while (*name++ != EOS);
     919                 :            :                         return(0);
     920                 :            :                 case M_ONE:
     921         [ +  - ]:         26 :                         if (*name++ == EOS)
     922                 :            :                                 return(0);
     923                 :            :                         break;
     924                 :            :                 case M_SET:
     925                 :          0 :                         ok = 0;
     926         [ #  # ]:          0 :                         if ((k = *name++) == EOS)
     927                 :            :                                 return(0);
     928         [ #  # ]:          0 :                         if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
     929                 :          0 :                                 ++pat;
     930         [ #  # ]:          0 :                         while (((c = *pat++) & M_MASK) != M_END) {
     931         [ #  # ]:          0 :                                 if ((c & M_MASK) == M_CLASS) {
     932                 :          0 :                                         Char idx = *pat & M_MASK;
     933   [ #  #  #  # ]:          0 :                                         if (idx < NCCLASSES &&
     934                 :          0 :                                             cclasses[idx].isctype(k))
     935                 :          0 :                                                 ok = 1;
     936                 :          0 :                                         ++pat;
     937                 :            :                                 }
     938         [ #  # ]:          0 :                                 if ((*pat & M_MASK) == M_RNG) {
     939 [ #  # ][ #  # ]:          0 :                                         if (c <= k && k <= pat[1])
     940                 :          0 :                                                 ok = 1;
     941                 :          0 :                                         pat += 2;
     942         [ #  # ]:          0 :                                 } else if (c == k)
     943                 :          0 :                                         ok = 1;
     944                 :            :                         }
     945         [ #  # ]:          0 :                         if (ok == negate_range)
     946                 :            :                                 return(0);
     947                 :            :                         break;
     948                 :            :                 default:
     949         [ +  + ]:       1253 :                         if (*name++ != c)
     950                 :            :                                 return(0);
     951                 :            :                         break;
     952                 :            :                 }
     953                 :            :         }
     954                 :         26 :         return(*name == EOS);
     955                 :            : }
     956                 :            : 
     957                 :            : /* Free allocated data belonging to a glob_t structure. */
     958                 :            : void
     959                 :        108 : globfree(glob_t *pglob)
     960                 :            : {
     961                 :            :         int i;
     962                 :            :         char **pp;
     963                 :            : 
     964         [ +  + ]:        108 :         if (pglob->gl_pathv != NULL) {
     965                 :        105 :                 pp = pglob->gl_pathv + pglob->gl_offs;
     966         [ +  + ]:        273 :                 for (i = pglob->gl_pathc; i--; ++pp)
     967         [ +  - ]:        168 :                         if (*pp)
     968                 :        168 :                                 free(*pp);
     969                 :        105 :                 free(pglob->gl_pathv);
     970                 :        105 :                 pglob->gl_pathv = NULL;
     971                 :            :         }
     972         [ +  + ]:        108 :         if (pglob->gl_statv != NULL) {
     973         [ +  + ]:         48 :                 for (i = 0; i < pglob->gl_pathc; i++) {
     974         [ +  - ]:         24 :                         if (pglob->gl_statv[i] != NULL)
     975                 :         24 :                                 free(pglob->gl_statv[i]);
     976                 :            :                 }
     977                 :         24 :                 free(pglob->gl_statv);
     978                 :         24 :                 pglob->gl_statv = NULL;
     979                 :            :         }
     980                 :        108 : }
     981                 :            : 
     982                 :            : static DIR *
     983                 :         20 : g_opendir(Char *str, glob_t *pglob)
     984                 :            : {
     985                 :            :         char buf[MAXPATHLEN];
     986                 :            : 
     987         [ -  + ]:         10 :         if (!*str)
     988                 :          0 :                 strlcpy(buf, ".", sizeof buf);
     989                 :            :         else {
     990         [ +  - ]:         10 :                 if (g_Ctoc(str, buf, sizeof(buf)))
     991                 :            :                         return(NULL);
     992                 :            :         }
     993                 :            : 
     994         [ +  + ]:         10 :         if (pglob->gl_flags & GLOB_ALTDIRFUNC)
     995                 :          6 :                 return((*pglob->gl_opendir)(buf));
     996                 :            : 
     997                 :          4 :         return(opendir(buf));
     998                 :            : }
     999                 :            : 
    1000                 :            : static int
    1001                 :        342 : g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
    1002                 :            : {
    1003                 :            :         char buf[MAXPATHLEN];
    1004                 :            : 
    1005         [ +  - ]:        171 :         if (g_Ctoc(fn, buf, sizeof(buf)))
    1006                 :            :                 return(-1);
    1007         [ +  + ]:        171 :         if (pglob->gl_flags & GLOB_ALTDIRFUNC)
    1008                 :        113 :                 return((*pglob->gl_lstat)(buf, sb));
    1009                 :            :         return(lstat(buf, sb));
    1010                 :            : }
    1011                 :            : 
    1012                 :            : static int
    1013                 :         20 : g_stat(Char *fn, struct stat *sb, glob_t *pglob)
    1014                 :            : {
    1015                 :            :         char buf[MAXPATHLEN];
    1016                 :            : 
    1017         [ +  - ]:         10 :         if (g_Ctoc(fn, buf, sizeof(buf)))
    1018                 :            :                 return(-1);
    1019         [ +  + ]:         10 :         if (pglob->gl_flags & GLOB_ALTDIRFUNC)
    1020                 :          6 :                 return((*pglob->gl_stat)(buf, sb));
    1021                 :            :         return(stat(buf, sb));
    1022                 :            : }
    1023                 :            : 
    1024                 :            : static Char *
    1025                 :            : g_strchr(const Char *str, int ch)
    1026                 :            : {
    1027                 :            :         do {
    1028 [ #  # ][ #  # ]:       1116 :                 if (*str == ch)
                 [ +  - ]
    1029                 :            :                         return ((Char *)str);
    1030 [ #  # ][ #  # ]:       1116 :         } while (*str++);
                 [ +  + ]
    1031                 :            :         return (NULL);
    1032                 :            : }
    1033                 :            : 
    1034                 :            : static int
    1035                 :            : g_Ctoc(const Char *str, char *buf, u_int len)
    1036                 :            : {
    1037                 :            : 
    1038 [ +  - ][ +  - ]:      10474 :         while (len--) {
         [ +  - ][ +  - ]
                 [ #  # ]
    1039 [ +  + ][ +  + ]:      10484 :                 if ((*buf++ = *str++) == EOS)
         [ +  + ][ +  + ]
                 [ #  # ]
    1040                 :            :                         return (0);
    1041                 :            :         }
    1042                 :            :         return (1);
    1043                 :            : }
    1044                 :            : 
    1045                 :            : #ifdef DEBUG
    1046                 :            : static void
    1047                 :            : qprintf(const char *str, Char *s)
    1048                 :            : {
    1049                 :            :         Char *p;
    1050                 :            : 
    1051                 :            :         (void)printf("%s:\n", str);
    1052                 :            :         for (p = s; *p; p++)
    1053                 :            :                 (void)printf("%c", CHAR(*p));
    1054                 :            :         (void)printf("\n");
    1055                 :            :         for (p = s; *p; p++)
    1056                 :            :                 (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
    1057                 :            :         (void)printf("\n");
    1058                 :            :         for (p = s; *p; p++)
    1059                 :            :                 (void)printf("%c", ismeta(*p) ? '_' : ' ');
    1060                 :            :         (void)printf("\n");
    1061                 :            : }
    1062                 :            : #endif
    1063                 :            : 
    1064                 :            : #endif /* !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) ||
    1065                 :            :           !defined(GLOB_HAS_GL_MATCHC) || !defined(GLOB_HAS_GL_STATV) */

Generated by: LCOV version 1.9