root/maint/gnulib/lib/glob.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. readdir_result_type
  2. convert_dirent
  3. convert_dirent64
  4. glob_lstat
  5. size_add_wrapv
  6. glob_use_alloca
  7. prefix_array
  8. next_brace_sub
  9. __glob
  10. libc_hidden_ver
  11. prefix_array
  12. glob_in_dir

   1 /* Copyright (C) 1991-2021 Free Software Foundation, Inc.
   2    This file is part of the GNU C Library.
   3 
   4    The GNU C Library is free software; you can redistribute it and/or
   5    modify it under the terms of the GNU Lesser General Public
   6    License as published by the Free Software Foundation; either
   7    version 2.1 of the License, or (at your option) any later version.
   8 
   9    The GNU C Library is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12    Lesser General Public License for more details.
  13 
  14    You should have received a copy of the GNU Lesser General Public
  15    License along with the GNU C Library; if not, see
  16    <https://www.gnu.org/licenses/>.  */
  17 
  18 #ifndef _LIBC
  19 
  20 /* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
  21    optimizes away the pattern == NULL test below.  */
  22 # define _GL_ARG_NONNULL(params)
  23 
  24 # include <libc-config.h>
  25 
  26 #endif
  27 
  28 #include <glob.h>
  29 
  30 #include <errno.h>
  31 #include <sys/types.h>
  32 #include <sys/stat.h>
  33 #include <stdbool.h>
  34 #include <stddef.h>
  35 #include <stdint.h>
  36 #include <assert.h>
  37 #include <unistd.h>
  38 
  39 #if defined _WIN32 && ! defined __CYGWIN__
  40 # define WINDOWS32
  41 #endif
  42 
  43 #ifndef WINDOWS32
  44 # include <pwd.h>
  45 #endif
  46 
  47 #include <errno.h>
  48 #include <dirent.h>
  49 #include <stdlib.h>
  50 #include <string.h>
  51 #include <alloca.h>
  52 
  53 #ifdef _LIBC
  54 # undef strdup
  55 # define strdup(str) __strdup (str)
  56 # define sysconf(id) __sysconf (id)
  57 # define closedir(dir) __closedir (dir)
  58 # define opendir(name) __opendir (name)
  59 # define readdir(str) __readdir64 (str)
  60 # define getpwnam_r(name, bufp, buf, len, res) \
  61     __getpwnam_r (name, bufp, buf, len, res)
  62 # define FLEXIBLE_ARRAY_MEMBER
  63 # ifndef struct_stat
  64 #  define struct_stat           struct stat
  65 # endif
  66 # ifndef struct_stat64
  67 #  define struct_stat64         struct stat64
  68 # endif
  69 # ifndef GLOB_LSTAT
  70 #  define GLOB_LSTAT            gl_lstat
  71 # endif
  72 # ifndef GLOB_STAT64
  73 #  define GLOB_STAT64           __stat64
  74 # endif
  75 # ifndef GLOB_LSTAT64
  76 #  define GLOB_LSTAT64          __lstat64
  77 # endif
  78 # include <shlib-compat.h>
  79 #else /* !_LIBC */
  80 # define __glob                 glob
  81 # define __getlogin_r(buf, len) getlogin_r (buf, len)
  82 # define __fxstatat64(_, d, f, st, flag) fstatat (d, f, st, flag)
  83 # ifndef __MVS__
  84 #  define __alloca              alloca
  85 # endif
  86 # define __readdir              readdir
  87 # define COMPILE_GLOB64
  88 # define struct_stat            struct stat
  89 # define struct_stat64          struct stat
  90 # define GLOB_LSTAT             gl_lstat
  91 # define GLOB_STAT64            stat
  92 # define GLOB_LSTAT64           lstat
  93 #endif /* _LIBC */
  94 
  95 #include <fnmatch.h>
  96 
  97 #include <flexmember.h>
  98 #include <glob_internal.h>
  99 #include <scratch_buffer.h>
 100 
 101 static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
 102 
 103 /* The type of ((struct dirent *) 0)->d_type is 'unsigned char' on most
 104    platforms, but 'unsigned int' in the mingw from mingw.org.  */
 105 typedef uint_fast32_t dirent_type;
 106 
 107 #if !defined _LIBC && !defined HAVE_STRUCT_DIRENT_D_TYPE
 108 /* Any distinct values will do here.
 109    Undef any existing macros out of the way.  */
 110 # undef DT_UNKNOWN
 111 # undef DT_DIR
 112 # undef DT_LNK
 113 # define DT_UNKNOWN 0
 114 # define DT_DIR 1
 115 # define DT_LNK 2
 116 #endif
 117 
 118 /* A representation of a directory entry which does not depend on the
 119    layout of struct dirent, or the size of ino_t.  */
 120 struct readdir_result
 121 {
 122   const char *name;
 123 #if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
 124   dirent_type type;
 125 #endif
 126 };
 127 
 128 /* Initialize and return type member of struct readdir_result.  */
 129 static dirent_type
 130 readdir_result_type (struct readdir_result d)
     /* [previous][next][first][last][top][bottom][index][help] */
 131 {
 132 #if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
 133 # define D_TYPE_TO_RESULT(source) (source)->d_type,
 134   return d.type;
 135 #else
 136 # define D_TYPE_TO_RESULT(source)
 137   return DT_UNKNOWN;
 138 #endif
 139 }
 140 
 141 /* Construct an initializer for a struct readdir_result object from a
 142    struct dirent *.  No copy of the name is made.  */
 143 #define READDIR_RESULT_INITIALIZER(source) \
 144   {                                        \
 145     source->d_name,                        \
 146     D_TYPE_TO_RESULT (source)              \
 147   }
 148 
 149 /* Call gl_readdir on STREAM.  This macro can be overridden to reduce
 150    type safety if an old interface version needs to be supported.  */
 151 #ifndef GL_READDIR
 152 # define GL_READDIR(pglob, stream) ((pglob)->gl_readdir (stream))
 153 #endif
 154 
 155 /* Extract name and type from directory entry.  No copy of the name is
 156    made.  If SOURCE is NULL, result name is NULL.  Keep in sync with
 157    convert_dirent64 below.  */
 158 static struct readdir_result
 159 convert_dirent (const struct dirent *source)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161   if (source == NULL)
 162     {
 163       struct readdir_result result = { NULL, };
 164       return result;
 165     }
 166   struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
 167   return result;
 168 }
 169 
 170 #ifndef COMPILE_GLOB64
 171 /* Like convert_dirent, but works on struct dirent64 instead.  Keep in
 172    sync with convert_dirent above.  */
 173 static struct readdir_result
 174 convert_dirent64 (const struct dirent64 *source)
     /* [previous][next][first][last][top][bottom][index][help] */
 175 {
 176   if (source == NULL)
 177     {
 178       struct readdir_result result = { NULL, };
 179       return result;
 180     }
 181   struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
 182   return result;
 183 }
 184 #endif
 185 
 186 #ifndef _LIBC
 187 /* The results of opendir() in this file are not used with dirfd and fchdir,
 188    and we do not leak fds to any single-threaded code that could use stdio,
 189    therefore save some unnecessary recursion in fchdir.c and opendir_safer.c.
 190    FIXME - if the kernel ever adds support for multi-thread safety for
 191    avoiding standard fds, then we should use opendir_safer.  */
 192 # ifdef GNULIB_defined_opendir
 193 #  undef opendir
 194 # endif
 195 # ifdef GNULIB_defined_closedir
 196 #  undef closedir
 197 # endif
 198 
 199 /* Just use malloc.  */
 200 # define __libc_use_alloca(n) false
 201 # define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0)
 202 # define extend_alloca_account(buf, len, newlen, avar) \
 203     ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0)
 204 #endif
 205 
 206 static int
 207 glob_lstat (glob_t *pglob, int flags, const char *fullname)
     /* [previous][next][first][last][top][bottom][index][help] */
 208 {
 209 /* Use on glob-lstat-compat.c to provide a compat symbol which does not
 210    use lstat / gl_lstat.  */
 211   union
 212   {
 213     struct_stat st;
 214     struct_stat64 st64;
 215   } ust;
 216   return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
 217           ? pglob->GLOB_LSTAT (fullname, &ust.st)
 218           : GLOB_LSTAT64 (fullname, &ust.st64));
 219 }
 220 
 221 /* Set *R = A + B.  Return true if the answer is mathematically
 222    incorrect due to overflow; in this case, *R is the low order
 223    bits of the correct answer.  */
 224 
 225 static bool
 226 size_add_wrapv (size_t a, size_t b, size_t *r)
     /* [previous][next][first][last][top][bottom][index][help] */
 227 {
 228 #if 7 <= __GNUC__ && !defined __ICC
 229   return __builtin_add_overflow (a, b, r);
 230 #else
 231   *r = a + b;
 232   return *r < a;
 233 #endif
 234 }
 235 
 236 static bool
 237 glob_use_alloca (size_t alloca_used, size_t len)
     /* [previous][next][first][last][top][bottom][index][help] */
 238 {
 239   size_t size;
 240   return (!size_add_wrapv (alloca_used, len, &size)
 241           && __libc_use_alloca (size));
 242 }
 243 
 244 static int glob_in_dir (const char *pattern, const char *directory,
 245                         int flags, int (*errfunc) (const char *, int),
 246                         glob_t *pglob, size_t alloca_used);
 247 static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL;
     /* [previous][next][first][last][top][bottom][index][help] */
 248 static int collated_compare (const void *, const void *) __THROWNL;
 249 
 250 
 251 /* Return true if FILENAME is a directory or a symbolic link to a directory.
 252    Use FLAGS and PGLOB to resolve the filename.  */
 253 static bool
 254 is_dir (char const *filename, int flags, glob_t const *pglob)
 255 {
 256   struct_stat st;
 257   struct_stat64 st64;
 258   return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
 259           ? pglob->gl_stat (filename, &st) == 0 && S_ISDIR (st.st_mode)
 260           : GLOB_STAT64 (filename, &st64) == 0 && S_ISDIR (st64.st_mode));
 261 }
 262 
 263 /* Find the end of the sub-pattern in a brace expression.  */
 264 static const char *
 265 next_brace_sub (const char *cp, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 266 {
 267   size_t depth = 0;
 268   while (*cp != '\0')
 269     if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\')
 270       {
 271         if (*++cp == '\0')
 272           break;
 273         ++cp;
 274       }
 275     else
 276       {
 277         if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
 278           break;
 279 
 280         if (*cp++ == '{')
 281           depth++;
 282       }
 283 
 284   return *cp != '\0' ? cp : NULL;
 285 }
 286 
 287 #ifndef GLOB_ATTRIBUTE
 288 # define GLOB_ATTRIBUTE
 289 #endif
 290 
 291 /* Do glob searching for PATTERN, placing results in PGLOB.
 292    The bits defined above may be set in FLAGS.
 293    If a directory cannot be opened or read and ERRFUNC is not nil,
 294    it is called with the pathname that caused the error, and the
 295    'errno' value from the failing call; if it returns non-zero
 296    'glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
 297    If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
 298    Otherwise, 'glob' returns zero.  */
 299 int
 300 GLOB_ATTRIBUTE
 301 __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
     /* [previous][next][first][last][top][bottom][index][help] */
 302         glob_t *pglob)
 303 {
 304   const char *filename;
 305   char *dirname = NULL;
 306   size_t dirlen;
 307   int status;
 308   size_t oldcount;
 309   int meta;
 310   int dirname_modified;
 311   int malloc_dirname = 0;
 312   glob_t dirs;
 313   int retval = 0;
 314   size_t alloca_used = 0;
 315 
 316   if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
 317     {
 318       __set_errno (EINVAL);
 319       return -1;
 320     }
 321 
 322   /* POSIX requires all slashes to be matched.  This means that with
 323      a trailing slash we must match only directories.  */
 324   if (pattern[0] && pattern[strlen (pattern) - 1] == '/')
 325     flags |= GLOB_ONLYDIR;
 326 
 327   if (!(flags & GLOB_DOOFFS))
 328     /* Have to do this so 'globfree' knows where to start freeing.  It
 329        also makes all the code that uses gl_offs simpler. */
 330     pglob->gl_offs = 0;
 331 
 332   if (!(flags & GLOB_APPEND))
 333     {
 334       pglob->gl_pathc = 0;
 335       if (!(flags & GLOB_DOOFFS))
 336         pglob->gl_pathv = NULL;
 337       else
 338         {
 339           size_t i;
 340 
 341           if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
 342             return GLOB_NOSPACE;
 343 
 344           pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
 345                                               * sizeof (char *));
 346           if (pglob->gl_pathv == NULL)
 347             return GLOB_NOSPACE;
 348 
 349           for (i = 0; i <= pglob->gl_offs; ++i)
 350             pglob->gl_pathv[i] = NULL;
 351         }
 352     }
 353 
 354   if (flags & GLOB_BRACE)
 355     {
 356       const char *begin;
 357 
 358       if (flags & GLOB_NOESCAPE)
 359         begin = strchr (pattern, '{');
 360       else
 361         {
 362           begin = pattern;
 363           while (1)
 364             {
 365               if (*begin == '\0')
 366                 {
 367                   begin = NULL;
 368                   break;
 369                 }
 370 
 371               if (*begin == '\\' && begin[1] != '\0')
 372                 ++begin;
 373               else if (*begin == '{')
 374                 break;
 375 
 376               ++begin;
 377             }
 378         }
 379 
 380       if (begin != NULL)
 381         {
 382           /* Allocate working buffer large enough for our work.  Note that
 383              we have at least an opening and closing brace.  */
 384           size_t firstc;
 385           char *alt_start;
 386           const char *p;
 387           const char *next;
 388           const char *rest;
 389           size_t rest_len;
 390           char *onealt;
 391           size_t pattern_len = strlen (pattern) - 1;
 392           int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
 393           if (alloca_onealt)
 394             onealt = alloca_account (pattern_len, alloca_used);
 395           else
 396             {
 397               onealt = malloc (pattern_len);
 398               if (onealt == NULL)
 399                 return GLOB_NOSPACE;
 400             }
 401 
 402           /* We know the prefix for all sub-patterns.  */
 403           alt_start = mempcpy (onealt, pattern, begin - pattern);
 404 
 405           /* Find the first sub-pattern and at the same time find the
 406              rest after the closing brace.  */
 407           next = next_brace_sub (begin + 1, flags);
 408           if (next == NULL)
 409             {
 410               /* It is an invalid expression.  */
 411             illegal_brace:
 412               if (__glibc_unlikely (!alloca_onealt))
 413                 free (onealt);
 414               flags &= ~GLOB_BRACE;
 415               goto no_brace;
 416             }
 417 
 418           /* Now find the end of the whole brace expression.  */
 419           rest = next;
 420           while (*rest != '}')
 421             {
 422               rest = next_brace_sub (rest + 1, flags);
 423               if (rest == NULL)
 424                 /* It is an illegal expression.  */
 425                 goto illegal_brace;
 426             }
 427           /* Please note that we now can be sure the brace expression
 428              is well-formed.  */
 429           rest_len = strlen (++rest) + 1;
 430 
 431           /* We have a brace expression.  BEGIN points to the opening {,
 432              NEXT points past the terminator of the first element, and END
 433              points past the final }.  We will accumulate result names from
 434              recursive runs for each brace alternative in the buffer using
 435              GLOB_APPEND.  */
 436           firstc = pglob->gl_pathc;
 437 
 438           p = begin + 1;
 439           while (1)
 440             {
 441               int result;
 442 
 443               /* Construct the new glob expression.  */
 444               mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
 445 
 446               result = __glob (onealt,
 447                                ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
 448                                 | GLOB_APPEND),
 449                                errfunc, pglob);
 450 
 451               /* If we got an error, return it.  */
 452               if (result && result != GLOB_NOMATCH)
 453                 {
 454                   if (__glibc_unlikely (!alloca_onealt))
 455                     free (onealt);
 456                   if (!(flags & GLOB_APPEND))
 457                     {
 458                       globfree (pglob);
 459                       pglob->gl_pathc = 0;
 460                     }
 461                   return result;
 462                 }
 463 
 464               if (*next == '}')
 465                 /* We saw the last entry.  */
 466                 break;
 467 
 468               p = next + 1;
 469               next = next_brace_sub (p, flags);
 470               assert (next != NULL);
 471             }
 472 
 473           if (__glibc_unlikely (!alloca_onealt))
 474             free (onealt);
 475 
 476           if (pglob->gl_pathc != firstc)
 477             /* We found some entries.  */
 478             return 0;
 479           else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
 480             return GLOB_NOMATCH;
 481         }
 482     }
 483 
 484  no_brace:
 485   oldcount = pglob->gl_pathc + pglob->gl_offs;
 486 
 487   /* Find the filename.  */
 488   filename = strrchr (pattern, '/');
 489 
 490 #if defined __MSDOS__ || defined WINDOWS32
 491   /* The case of "d:pattern".  Since ':' is not allowed in
 492      file names, we can safely assume that wherever it
 493      happens in pattern, it signals the filename part.  This
 494      is so we could some day support patterns like "[a-z]:foo".  */
 495   if (filename == NULL)
 496     filename = strchr (pattern, ':');
 497 #endif /* __MSDOS__ || WINDOWS32 */
 498 
 499   dirname_modified = 0;
 500   if (filename == NULL)
 501     {
 502       /* This can mean two things: a simple name or "~name".  The latter
 503          case is nothing but a notation for a directory.  */
 504       if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
 505         {
 506           dirname = (char *) pattern;
 507           dirlen = strlen (pattern);
 508 
 509           /* Set FILENAME to NULL as a special flag.  This is ugly but
 510              other solutions would require much more code.  We test for
 511              this special case below.  */
 512           filename = NULL;
 513         }
 514       else
 515         {
 516           if (__glibc_unlikely (pattern[0] == '\0'))
 517             {
 518               dirs.gl_pathv = NULL;
 519               goto no_matches;
 520             }
 521 
 522           filename = pattern;
 523           dirname = (char *) ".";
 524           dirlen = 0;
 525         }
 526     }
 527   else if (filename == pattern
 528            || (filename == pattern + 1 && pattern[0] == '\\'
 529                && (flags & GLOB_NOESCAPE) == 0))
 530     {
 531       /* "/pattern" or "\\/pattern".  */
 532       dirname = (char *) "/";
 533       dirlen = 1;
 534       ++filename;
 535     }
 536   else
 537     {
 538       char *newp;
 539       dirlen = filename - pattern;
 540 #if defined __MSDOS__ || defined WINDOWS32
 541       if (*filename == ':'
 542           || (filename > pattern + 1 && filename[-1] == ':'))
 543         {
 544           char *drive_spec;
 545 
 546           ++dirlen;
 547           drive_spec = __alloca (dirlen + 1);
 548           *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
 549           /* For now, disallow wildcards in the drive spec, to
 550              prevent infinite recursion in glob.  */
 551           if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
 552             return GLOB_NOMATCH;
 553           /* If this is "d:pattern", we need to copy ':' to DIRNAME
 554              as well.  If it's "d:/pattern", don't remove the slash
 555              from "d:/", since "d:" and "d:/" are not the same.*/
 556         }
 557 #endif
 558 
 559       if (glob_use_alloca (alloca_used, dirlen + 1))
 560         newp = alloca_account (dirlen + 1, alloca_used);
 561       else
 562         {
 563           newp = malloc (dirlen + 1);
 564           if (newp == NULL)
 565             return GLOB_NOSPACE;
 566           malloc_dirname = 1;
 567         }
 568       *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
 569       dirname = newp;
 570       ++filename;
 571 
 572 #if defined __MSDOS__ || defined WINDOWS32
 573       bool drive_root = (dirlen > 1
 574                          && (dirname[dirlen - 1] == ':'
 575                              || (dirlen > 2 && dirname[dirlen - 2] == ':'
 576                                  && dirname[dirlen - 1] == '/')));
 577 #else
 578       bool drive_root = false;
 579 #endif
 580 
 581       if (filename[0] == '\0' && dirlen > 1 && !drive_root)
 582         /* "pattern/".  Expand "pattern", appending slashes.  */
 583         {
 584           int orig_flags = flags;
 585           if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
 586             {
 587               /* "pattern\\/".  Remove the final backslash if it hasn't
 588                  been quoted.  */
 589               char *p = (char *) &dirname[dirlen - 1];
 590 
 591               while (p > dirname && p[-1] == '\\') --p;
 592               if ((&dirname[dirlen] - p) & 1)
 593                 {
 594                   *(char *) &dirname[--dirlen] = '\0';
 595                   flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
 596                 }
 597             }
 598           int val = __glob (dirname, flags | GLOB_MARK, errfunc, pglob);
 599           if (val == 0)
 600             pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
 601                                | (flags & GLOB_MARK));
 602           else if (val == GLOB_NOMATCH && flags != orig_flags)
 603             {
 604               /* Make sure globfree (&dirs); is a nop.  */
 605               dirs.gl_pathv = NULL;
 606               flags = orig_flags;
 607               oldcount = pglob->gl_pathc + pglob->gl_offs;
 608               goto no_matches;
 609             }
 610           retval = val;
 611           goto out;
 612         }
 613     }
 614 
 615   if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
 616     {
 617       if (dirname[1] == '\0' || dirname[1] == '/'
 618           || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\'
 619               && (dirname[2] == '\0' || dirname[2] == '/')))
 620         {
 621           /* Look up home directory.  */
 622           char *home_dir = getenv ("HOME");
 623           int malloc_home_dir = 0;
 624           if (home_dir == NULL || home_dir[0] == '\0')
 625             {
 626 #ifdef WINDOWS32
 627               /* Windows NT defines HOMEDRIVE and HOMEPATH.  But give
 628                  preference to HOME, because the user can change HOME.  */
 629               const char *home_drive = getenv ("HOMEDRIVE");
 630               const char *home_path = getenv ("HOMEPATH");
 631 
 632               if (home_drive != NULL && home_path != NULL)
 633                 {
 634                   size_t home_drive_len = strlen (home_drive);
 635                   size_t home_path_len = strlen (home_path);
 636                   char *mem = alloca (home_drive_len + home_path_len + 1);
 637 
 638                   memcpy (mem, home_drive, home_drive_len);
 639                   memcpy (mem + home_drive_len, home_path, home_path_len + 1);
 640                   home_dir = mem;
 641                 }
 642               else
 643                 home_dir = "c:/users/default"; /* poor default */
 644 #else
 645               int err;
 646               struct passwd *p;
 647               struct passwd pwbuf;
 648               struct scratch_buffer s;
 649               scratch_buffer_init (&s);
 650               while (true)
 651                 {
 652                   p = NULL;
 653                   err = __getlogin_r (s.data, s.length);
 654                   if (err == 0)
 655                     {
 656 # if defined HAVE_GETPWNAM_R || defined _LIBC
 657                       size_t ssize = strlen (s.data) + 1;
 658                       char *sdata = s.data;
 659                       err = getpwnam_r (sdata, &pwbuf, sdata + ssize,
 660                                         s.length - ssize, &p);
 661 # else
 662                       p = getpwnam (s.data);
 663                       if (p == NULL)
 664                         err = errno;
 665 # endif
 666                     }
 667                   if (err != ERANGE)
 668                     break;
 669                   if (!scratch_buffer_grow (&s))
 670                     {
 671                       retval = GLOB_NOSPACE;
 672                       goto out;
 673                     }
 674                 }
 675               if (err == 0)
 676                 {
 677                   home_dir = strdup (p->pw_dir);
 678                   malloc_home_dir = 1;
 679                 }
 680               scratch_buffer_free (&s);
 681               if (err == 0 && home_dir == NULL)
 682                 {
 683                   retval = GLOB_NOSPACE;
 684                   goto out;
 685                 }
 686 #endif /* WINDOWS32 */
 687             }
 688           if (home_dir == NULL || home_dir[0] == '\0')
 689             {
 690               if (__glibc_unlikely (malloc_home_dir))
 691                 free (home_dir);
 692               if (flags & GLOB_TILDE_CHECK)
 693                 {
 694                   retval = GLOB_NOMATCH;
 695                   goto out;
 696                 }
 697               else
 698                 {
 699                   home_dir = (char *) "~"; /* No luck.  */
 700                   malloc_home_dir = 0;
 701                 }
 702             }
 703           /* Now construct the full directory.  */
 704           if (dirname[1] == '\0')
 705             {
 706               if (__glibc_unlikely (malloc_dirname))
 707                 free (dirname);
 708 
 709               dirname = home_dir;
 710               dirlen = strlen (dirname);
 711               malloc_dirname = malloc_home_dir;
 712             }
 713           else
 714             {
 715               char *newp;
 716               size_t home_len = strlen (home_dir);
 717               int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
 718               if (use_alloca)
 719                 newp = alloca_account (home_len + dirlen, alloca_used);
 720               else
 721                 {
 722                   newp = malloc (home_len + dirlen);
 723                   if (newp == NULL)
 724                     {
 725                       if (__glibc_unlikely (malloc_home_dir))
 726                         free (home_dir);
 727                       retval = GLOB_NOSPACE;
 728                       goto out;
 729                     }
 730                 }
 731 
 732               mempcpy (mempcpy (newp, home_dir, home_len),
 733                        &dirname[1], dirlen);
 734 
 735               if (__glibc_unlikely (malloc_dirname))
 736                 free (dirname);
 737 
 738               dirname = newp;
 739               dirlen += home_len - 1;
 740               malloc_dirname = !use_alloca;
 741 
 742               if (__glibc_unlikely (malloc_home_dir))
 743                 free (home_dir);
 744             }
 745           dirname_modified = 1;
 746         }
 747       else
 748         {
 749 #ifndef WINDOWS32
 750           /* Recognize ~user as a shorthand for the specified user's home
 751              directory.  */
 752           char *end_name = strchr (dirname, '/');
 753           char *user_name;
 754           int malloc_user_name = 0;
 755           char *unescape = NULL;
 756 
 757           if (!(flags & GLOB_NOESCAPE))
 758             {
 759               if (end_name == NULL)
 760                 {
 761                   unescape = strchr (dirname, '\\');
 762                   if (unescape)
 763                     end_name = strchr (unescape, '\0');
 764                 }
 765               else
 766                 unescape = memchr (dirname, '\\', end_name - dirname);
 767             }
 768           if (end_name == NULL)
 769             user_name = dirname + 1;
 770           else
 771             {
 772               char *newp;
 773               if (glob_use_alloca (alloca_used, end_name - dirname))
 774                 newp = alloca_account (end_name - dirname, alloca_used);
 775               else
 776                 {
 777                   newp = malloc (end_name - dirname);
 778                   if (newp == NULL)
 779                     {
 780                       retval = GLOB_NOSPACE;
 781                       goto out;
 782                     }
 783                   malloc_user_name = 1;
 784                 }
 785               if (unescape != NULL)
 786                 {
 787                   char *p = mempcpy (newp, dirname + 1,
 788                                      unescape - dirname - 1);
 789                   char *q = unescape;
 790                   while (q != end_name)
 791                     {
 792                       if (*q == '\\')
 793                         {
 794                           if (q + 1 == end_name)
 795                             {
 796                               /* "~fo\\o\\" unescape to user_name "foo\\",
 797                                  but "~fo\\o\\/" unescape to user_name
 798                                  "foo".  */
 799                               if (filename == NULL)
 800                                 *p++ = '\\';
 801                               break;
 802                             }
 803                           ++q;
 804                         }
 805                       *p++ = *q++;
 806                     }
 807                   *p = '\0';
 808                 }
 809               else
 810                 *((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1))
 811                   = '\0';
 812               user_name = newp;
 813             }
 814 
 815           /* Look up specific user's home directory.  */
 816           {
 817             struct passwd *p;
 818             struct scratch_buffer pwtmpbuf;
 819             scratch_buffer_init (&pwtmpbuf);
 820 
 821 #  if defined HAVE_GETPWNAM_R || defined _LIBC
 822             struct passwd pwbuf;
 823 
 824             while (getpwnam_r (user_name, &pwbuf,
 825                                pwtmpbuf.data, pwtmpbuf.length, &p)
 826                    == ERANGE)
 827               {
 828                 if (!scratch_buffer_grow (&pwtmpbuf))
 829                   {
 830                     retval = GLOB_NOSPACE;
 831                     goto out;
 832                   }
 833               }
 834 #  else
 835             p = getpwnam (user_name);
 836 #  endif
 837 
 838             if (__glibc_unlikely (malloc_user_name))
 839               free (user_name);
 840 
 841             /* If we found a home directory use this.  */
 842             if (p != NULL)
 843               {
 844                 size_t home_len = strlen (p->pw_dir);
 845                 size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
 846                 /* dirname contains end_name; we can't free it now.  */
 847                 char *prev_dirname =
 848                   (__glibc_unlikely (malloc_dirname) ? dirname : NULL);
 849                 char *d;
 850 
 851                 malloc_dirname = 0;
 852 
 853                 if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
 854                   dirname = alloca_account (home_len + rest_len + 1,
 855                                             alloca_used);
 856                 else
 857                   {
 858                     dirname = malloc (home_len + rest_len + 1);
 859                     if (dirname == NULL)
 860                       {
 861                         free (prev_dirname);
 862                         scratch_buffer_free (&pwtmpbuf);
 863                         retval = GLOB_NOSPACE;
 864                         goto out;
 865                       }
 866                     malloc_dirname = 1;
 867                   }
 868                 d = mempcpy (dirname, p->pw_dir, home_len);
 869                 if (end_name != NULL)
 870                   d = mempcpy (d, end_name, rest_len);
 871                 *d = '\0';
 872 
 873                 free (prev_dirname);
 874 
 875                 dirlen = home_len + rest_len;
 876                 dirname_modified = 1;
 877               }
 878             else
 879               {
 880                 if (flags & GLOB_TILDE_CHECK)
 881                   {
 882                     /* We have to regard it as an error if we cannot find the
 883                        home directory.  */
 884                     retval = GLOB_NOMATCH;
 885                     goto out;
 886                   }
 887               }
 888             scratch_buffer_free (&pwtmpbuf);
 889           }
 890 #else /* WINDOWS32 */
 891           /* On native Windows, access to a user's home directory
 892              (via GetUserProfileDirectory) or to a user's environment
 893              variables (via ExpandEnvironmentStringsForUser) requires
 894              the credentials of the user.  Therefore we cannot support
 895              the ~user syntax on this platform.
 896              Handling ~user specially (and treat it like plain ~) if
 897              user is getenv ("USERNAME") would not be a good idea,
 898              since it would make people think that ~user is supported
 899              in general.  */
 900           if (flags & GLOB_TILDE_CHECK)
 901             {
 902               retval = GLOB_NOMATCH;
 903               goto out;
 904             }
 905 #endif /* WINDOWS32 */
 906         }
 907     }
 908 
 909   /* Now test whether we looked for "~" or "~NAME".  In this case we
 910      can give the answer now.  */
 911   if (filename == NULL)
 912     {
 913       size_t newcount = pglob->gl_pathc + pglob->gl_offs;
 914       char **new_gl_pathv;
 915 
 916       if (newcount > SIZE_MAX / sizeof (char *) - 2)
 917         {
 918         nospace:
 919           free (pglob->gl_pathv);
 920           pglob->gl_pathv = NULL;
 921           pglob->gl_pathc = 0;
 922           retval = GLOB_NOSPACE;
 923           goto out;
 924         }
 925 
 926       new_gl_pathv = realloc (pglob->gl_pathv,
 927                               (newcount + 2) * sizeof (char *));
 928       if (new_gl_pathv == NULL)
 929         goto nospace;
 930       pglob->gl_pathv = new_gl_pathv;
 931 
 932       if (flags & GLOB_MARK && is_dir (dirname, flags, pglob))
 933         {
 934           char *p;
 935           pglob->gl_pathv[newcount] = malloc (dirlen + 2);
 936           if (pglob->gl_pathv[newcount] == NULL)
 937             goto nospace;
 938           p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
 939           p[0] = '/';
 940           p[1] = '\0';
 941           if (__glibc_unlikely (malloc_dirname))
 942             free (dirname);
 943         }
 944       else
 945         {
 946           if (__glibc_unlikely (malloc_dirname))
 947             pglob->gl_pathv[newcount] = dirname;
 948           else
 949             {
 950               pglob->gl_pathv[newcount] = strdup (dirname);
 951               if (pglob->gl_pathv[newcount] == NULL)
 952                 goto nospace;
 953             }
 954         }
 955       pglob->gl_pathv[++newcount] = NULL;
 956       ++pglob->gl_pathc;
 957       pglob->gl_flags = flags;
 958 
 959       return 0;
 960     }
 961 
 962   meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE));
 963   /* meta is 1 if correct glob pattern containing metacharacters.
 964      If meta has bit (1 << 2) set, it means there was an unterminated
 965      [ which we handle the same, using fnmatch.  Broken unterminated
 966      pattern bracket expressions ought to be rare enough that it is
 967      not worth special casing them, fnmatch will do the right thing.  */
 968   if (meta & (GLOBPAT_SPECIAL | GLOBPAT_BRACKET))
 969     {
 970       /* The directory name contains metacharacters, so we
 971          have to glob for the directory, and then glob for
 972          the pattern in each directory found.  */
 973       size_t i;
 974 
 975       if (!(flags & GLOB_NOESCAPE) && dirlen > 0 && dirname[dirlen - 1] == '\\')
 976         {
 977           /* "foo\\/bar".  Remove the final backslash from dirname
 978              if it has not been quoted.  */
 979           char *p = (char *) &dirname[dirlen - 1];
 980 
 981           while (p > dirname && p[-1] == '\\') --p;
 982           if ((&dirname[dirlen] - p) & 1)
 983             *(char *) &dirname[--dirlen] = '\0';
 984         }
 985 
 986       if (__glibc_unlikely ((flags & GLOB_ALTDIRFUNC) != 0))
 987         {
 988           /* Use the alternative access functions also in the recursive
 989              call.  */
 990           dirs.gl_opendir = pglob->gl_opendir;
 991           dirs.gl_readdir = pglob->gl_readdir;
 992           dirs.gl_closedir = pglob->gl_closedir;
 993           dirs.gl_stat = pglob->gl_stat;
 994           dirs.gl_lstat = pglob->gl_lstat;
 995         }
 996 
 997       status = __glob (dirname,
 998                        ((flags & (GLOB_ERR | GLOB_NOESCAPE | GLOB_ALTDIRFUNC))
 999                         | GLOB_NOSORT | GLOB_ONLYDIR),
1000                        errfunc, &dirs);
1001       if (status != 0)
1002         {
1003           if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
1004             {
1005               retval = status;
1006               goto out;
1007             }
1008           goto no_matches;
1009         }
1010 
1011       /* We have successfully globbed the preceding directory name.
1012          For each name we found, call glob_in_dir on it and FILENAME,
1013          appending the results to PGLOB.  */
1014       for (i = 0; i < dirs.gl_pathc; ++i)
1015         {
1016           size_t old_pathc;
1017 
1018           old_pathc = pglob->gl_pathc;
1019           status = glob_in_dir (filename, dirs.gl_pathv[i],
1020                                 ((flags | GLOB_APPEND)
1021                                  & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
1022                                 errfunc, pglob, alloca_used);
1023           if (status == GLOB_NOMATCH)
1024             /* No matches in this directory.  Try the next.  */
1025             continue;
1026 
1027           if (status != 0)
1028             {
1029               globfree (&dirs);
1030               globfree (pglob);
1031               pglob->gl_pathc = 0;
1032               retval = status;
1033               goto out;
1034             }
1035 
1036           /* Stick the directory on the front of each name.  */
1037           if (prefix_array (dirs.gl_pathv[i],
1038                             &pglob->gl_pathv[old_pathc + pglob->gl_offs],
1039                             pglob->gl_pathc - old_pathc))
1040             {
1041               globfree (&dirs);
1042               globfree (pglob);
1043               pglob->gl_pathc = 0;
1044               retval = GLOB_NOSPACE;
1045               goto out;
1046             }
1047         }
1048 
1049       flags |= GLOB_MAGCHAR;
1050 
1051       /* We have ignored the GLOB_NOCHECK flag in the 'glob_in_dir' calls.
1052          But if we have not found any matching entry and the GLOB_NOCHECK
1053          flag was set we must return the input pattern itself.  */
1054       if (pglob->gl_pathc + pglob->gl_offs == oldcount)
1055         {
1056         no_matches:
1057           /* No matches.  */
1058           if (flags & GLOB_NOCHECK)
1059             {
1060               size_t newcount = pglob->gl_pathc + pglob->gl_offs;
1061               char **new_gl_pathv;
1062 
1063               if (newcount > SIZE_MAX / sizeof (char *) - 2)
1064                 {
1065                 nospace2:
1066                   globfree (&dirs);
1067                   retval = GLOB_NOSPACE;
1068                   goto out;
1069                 }
1070 
1071               new_gl_pathv = realloc (pglob->gl_pathv,
1072                                       (newcount + 2) * sizeof (char *));
1073               if (new_gl_pathv == NULL)
1074                 goto nospace2;
1075               pglob->gl_pathv = new_gl_pathv;
1076 
1077               pglob->gl_pathv[newcount] = strdup (pattern);
1078               if (pglob->gl_pathv[newcount] == NULL)
1079                 {
1080                   globfree (&dirs);
1081                   globfree (pglob);
1082                   pglob->gl_pathc = 0;
1083                   retval = GLOB_NOSPACE;
1084                   goto out;
1085                 }
1086 
1087               ++pglob->gl_pathc;
1088               ++newcount;
1089 
1090               pglob->gl_pathv[newcount] = NULL;
1091               pglob->gl_flags = flags;
1092             }
1093           else
1094             {
1095               globfree (&dirs);
1096               retval = GLOB_NOMATCH;
1097               goto out;
1098             }
1099         }
1100 
1101       globfree (&dirs);
1102     }
1103   else
1104     {
1105       size_t old_pathc = pglob->gl_pathc;
1106       int orig_flags = flags;
1107 
1108       if (meta & GLOBPAT_BACKSLASH)
1109         {
1110           char *p = strchr (dirname, '\\'), *q;
1111           /* We need to unescape the dirname string.  It is certainly
1112              allocated by alloca, as otherwise filename would be NULL
1113              or dirname wouldn't contain backslashes.  */
1114           q = p;
1115           do
1116             {
1117               if (*p == '\\')
1118                 {
1119                   *q = *++p;
1120                   --dirlen;
1121                 }
1122               else
1123                 *q = *p;
1124               ++q;
1125             }
1126           while (*p++ != '\0');
1127           dirname_modified = 1;
1128         }
1129       if (dirname_modified)
1130         flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
1131       status = glob_in_dir (filename, dirname, flags, errfunc, pglob,
1132                             alloca_used);
1133       if (status != 0)
1134         {
1135           if (status == GLOB_NOMATCH && flags != orig_flags
1136               && pglob->gl_pathc + pglob->gl_offs == oldcount)
1137             {
1138               /* Make sure globfree (&dirs); is a nop.  */
1139               dirs.gl_pathv = NULL;
1140               flags = orig_flags;
1141               goto no_matches;
1142             }
1143           retval = status;
1144           goto out;
1145         }
1146 
1147       if (dirlen > 0)
1148         {
1149           /* Stick the directory on the front of each name.  */
1150           if (prefix_array (dirname,
1151                             &pglob->gl_pathv[old_pathc + pglob->gl_offs],
1152                             pglob->gl_pathc - old_pathc))
1153             {
1154               globfree (pglob);
1155               pglob->gl_pathc = 0;
1156               retval = GLOB_NOSPACE;
1157               goto out;
1158             }
1159         }
1160     }
1161 
1162   if (flags & GLOB_MARK)
1163     {
1164       /* Append slashes to directory names.  */
1165       size_t i;
1166 
1167       for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i)
1168         if (is_dir (pglob->gl_pathv[i], flags, pglob))
1169           {
1170             size_t len = strlen (pglob->gl_pathv[i]) + 2;
1171             char *new = realloc (pglob->gl_pathv[i], len);
1172             if (new == NULL)
1173               {
1174                 globfree (pglob);
1175                 pglob->gl_pathc = 0;
1176                 retval = GLOB_NOSPACE;
1177                 goto out;
1178               }
1179             strcpy (&new[len - 2], "/");
1180             pglob->gl_pathv[i] = new;
1181           }
1182     }
1183 
1184   if (!(flags & GLOB_NOSORT))
1185     {
1186       /* Sort the vector.  */
1187       qsort (&pglob->gl_pathv[oldcount],
1188              pglob->gl_pathc + pglob->gl_offs - oldcount,
1189              sizeof (char *), collated_compare);
1190     }
1191 
1192  out:
1193   if (__glibc_unlikely (malloc_dirname))
1194     free (dirname);
1195 
1196   return retval;
1197 }
1198 #if defined _LIBC && !defined __glob
1199 versioned_symbol (libc, __glob, glob, GLIBC_2_27);
1200 libc_hidden_ver (__glob, glob)
     /* [previous][next][first][last][top][bottom][index][help] */
1201 #endif
1202 
1203 
1204 /* Do a collated comparison of A and B.  */
1205 static int
1206 collated_compare (const void *a, const void *b)
1207 {
1208   char *const *ps1 = a; char *s1 = *ps1;
1209   char *const *ps2 = b; char *s2 = *ps2;
1210 
1211   if (s1 == s2)
1212     return 0;
1213   if (s1 == NULL)
1214     return 1;
1215   if (s2 == NULL)
1216     return -1;
1217   return strcoll (s1, s2);
1218 }
1219 
1220 
1221 /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
1222    elements in place.  Return nonzero if out of memory, zero if successful.
1223    A slash is inserted between DIRNAME and each elt of ARRAY,
1224    unless DIRNAME is just "/".  Each old element of ARRAY is freed.  */
1225 static int
1226 prefix_array (const char *dirname, char **array, size_t n)
     /* [previous][next][first][last][top][bottom][index][help] */
1227 {
1228   size_t i;
1229   size_t dirlen = strlen (dirname);
1230   char dirsep_char = '/';
1231 
1232   if (dirlen == 1 && dirname[0] == '/')
1233     /* DIRNAME is just "/", so normal prepending would get us "//foo".
1234        We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
1235     dirlen = 0;
1236 
1237 #if defined __MSDOS__ || defined WINDOWS32
1238   if (dirlen > 1)
1239     {
1240       if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
1241         /* DIRNAME is "d:/".  Don't prepend the slash from DIRNAME.  */
1242         --dirlen;
1243       else if (dirname[dirlen - 1] == ':')
1244         {
1245           /* DIRNAME is "d:".  Use ':' instead of '/'.  */
1246           --dirlen;
1247           dirsep_char = ':';
1248         }
1249     }
1250 #endif
1251 
1252   for (i = 0; i < n; ++i)
1253     {
1254       size_t eltlen = strlen (array[i]) + 1;
1255       char *new = malloc (dirlen + 1 + eltlen);
1256       if (new == NULL)
1257         {
1258           while (i > 0)
1259             free (array[--i]);
1260           return 1;
1261         }
1262 
1263       {
1264         char *endp = mempcpy (new, dirname, dirlen);
1265         *endp++ = dirsep_char;
1266         mempcpy (endp, array[i], eltlen);
1267       }
1268       free (array[i]);
1269       array[i] = new;
1270     }
1271 
1272   return 0;
1273 }
1274 
1275 /* Like 'glob', but PATTERN is a final pathname component,
1276    and matches are searched for in DIRECTORY.
1277    The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
1278    The GLOB_APPEND flag is assumed to be set (always appends).  */
1279 static int
1280 glob_in_dir (const char *pattern, const char *directory, int flags,
     /* [previous][next][first][last][top][bottom][index][help] */
1281              int (*errfunc) (const char *, int),
1282              glob_t *pglob, size_t alloca_used)
1283 {
1284   size_t dirlen = strlen (directory);
1285   void *stream = NULL;
1286 # define GLOBNAMES_MEMBERS(nnames) \
1287     struct globnames *next; size_t count; char *name[nnames];
1288   struct globnames { GLOBNAMES_MEMBERS (FLEXIBLE_ARRAY_MEMBER) };
1289   struct { GLOBNAMES_MEMBERS (64) } init_names_buf;
1290   struct globnames *init_names = (struct globnames *) &init_names_buf;
1291   struct globnames *names = init_names;
1292   struct globnames *names_alloca = init_names;
1293   size_t nfound = 0;
1294   size_t cur = 0;
1295   int meta;
1296   int save;
1297   int result;
1298 
1299   alloca_used += sizeof init_names_buf;
1300 
1301   init_names->next = NULL;
1302   init_names->count = ((sizeof init_names_buf
1303                         - offsetof (struct globnames, name))
1304                        / sizeof init_names->name[0]);
1305 
1306   meta = __glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE));
1307   if (meta == GLOBPAT_NONE && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
1308     {
1309       /* We need not do any tests.  The PATTERN contains no meta
1310          characters and we must not return an error therefore the
1311          result will always contain exactly one name.  */
1312       flags |= GLOB_NOCHECK;
1313     }
1314   else if (meta == GLOBPAT_NONE)
1315     {
1316       size_t patlen = strlen (pattern);
1317       size_t fullsize;
1318       bool alloca_fullname
1319         = (! size_add_wrapv (dirlen + 1, patlen + 1, &fullsize)
1320            && glob_use_alloca (alloca_used, fullsize));
1321       char *fullname;
1322       if (alloca_fullname)
1323         fullname = alloca_account (fullsize, alloca_used);
1324       else
1325         {
1326           fullname = malloc (fullsize);
1327           if (fullname == NULL)
1328             return GLOB_NOSPACE;
1329         }
1330 
1331       mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
1332                         "/", 1),
1333                pattern, patlen + 1);
1334       if (glob_lstat (pglob, flags, fullname) == 0
1335           || errno == EOVERFLOW)
1336         /* We found this file to be existing.  Now tell the rest
1337            of the function to copy this name into the result.  */
1338         flags |= GLOB_NOCHECK;
1339 
1340       if (__glibc_unlikely (!alloca_fullname))
1341         free (fullname);
1342     }
1343   else
1344     {
1345       stream = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
1346                 ? (*pglob->gl_opendir) (directory)
1347                 : opendir (directory));
1348       if (stream == NULL)
1349         {
1350           if (errno != ENOTDIR
1351               && ((errfunc != NULL && (*errfunc) (directory, errno))
1352                   || (flags & GLOB_ERR)))
1353             return GLOB_ABORTED;
1354         }
1355       else
1356         {
1357           int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
1358                            | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
1359           flags |= GLOB_MAGCHAR;
1360 
1361           while (1)
1362             {
1363               struct readdir_result d;
1364               {
1365                 if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
1366                   d = convert_dirent (GL_READDIR (pglob, stream));
1367                 else
1368                   {
1369 #ifdef COMPILE_GLOB64
1370                     d = convert_dirent (__readdir (stream));
1371 #else
1372                     d = convert_dirent64 (__readdir64 (stream));
1373 #endif
1374                   }
1375               }
1376               if (d.name == NULL)
1377                 break;
1378 
1379               /* If we shall match only directories use the information
1380                  provided by the dirent call if possible.  */
1381               if (flags & GLOB_ONLYDIR)
1382                 switch (readdir_result_type (d))
1383                   {
1384                   case DT_DIR: case DT_LNK: case DT_UNKNOWN: break;
1385                   default: continue;
1386                   }
1387 
1388               if (fnmatch (pattern, d.name, fnm_flags) == 0)
1389                 {
1390                   if (cur == names->count)
1391                     {
1392                       struct globnames *newnames;
1393                       size_t count = names->count * 2;
1394                       size_t nameoff = offsetof (struct globnames, name);
1395                       size_t size = FLEXSIZEOF (struct globnames, name,
1396                                                 count * sizeof (char *));
1397                       if ((SIZE_MAX - nameoff) / 2 / sizeof (char *)
1398                           < names->count)
1399                         goto memory_error;
1400                       if (glob_use_alloca (alloca_used, size))
1401                         newnames = names_alloca
1402                           = alloca_account (size, alloca_used);
1403                       else if ((newnames = malloc (size))
1404                                == NULL)
1405                         goto memory_error;
1406                       newnames->count = count;
1407                       newnames->next = names;
1408                       names = newnames;
1409                       cur = 0;
1410                     }
1411                   names->name[cur] = strdup (d.name);
1412                   if (names->name[cur] == NULL)
1413                     goto memory_error;
1414                   ++cur;
1415                   ++nfound;
1416                   if (SIZE_MAX - pglob->gl_offs <= nfound)
1417                     goto memory_error;
1418                 }
1419             }
1420         }
1421     }
1422 
1423   if (nfound == 0 && (flags & GLOB_NOCHECK))
1424     {
1425       size_t len = strlen (pattern);
1426       nfound = 1;
1427       names->name[cur] = malloc (len + 1);
1428       if (names->name[cur] == NULL)
1429         goto memory_error;
1430       *((char *) mempcpy (names->name[cur++], pattern, len)) = '\0';
1431     }
1432 
1433   result = GLOB_NOMATCH;
1434   if (nfound != 0)
1435     {
1436       char **new_gl_pathv;
1437       result = 0;
1438 
1439       if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc
1440           < pglob->gl_offs + nfound + 1)
1441         goto memory_error;
1442 
1443       new_gl_pathv
1444         = realloc (pglob->gl_pathv,
1445                    (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
1446                     * sizeof (char *));
1447 
1448       if (new_gl_pathv == NULL)
1449         {
1450         memory_error:
1451           while (1)
1452             {
1453               struct globnames *old = names;
1454               for (size_t i = 0; i < cur; ++i)
1455                 free (names->name[i]);
1456               names = names->next;
1457               /* NB: we will not leak memory here if we exit without
1458                  freeing the current block assigned to OLD.  At least
1459                  the very first block is always allocated on the stack
1460                  and this is the block assigned to OLD here.  */
1461               if (names == NULL)
1462                 {
1463                   assert (old == init_names);
1464                   break;
1465                 }
1466               cur = names->count;
1467               if (old == names_alloca)
1468                 names_alloca = names;
1469               else
1470                 free (old);
1471             }
1472           result = GLOB_NOSPACE;
1473         }
1474       else
1475         {
1476           while (1)
1477             {
1478               struct globnames *old = names;
1479               for (size_t i = 0; i < cur; ++i)
1480                 new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++]
1481                   = names->name[i];
1482               names = names->next;
1483               /* NB: we will not leak memory here if we exit without
1484                  freeing the current block assigned to OLD.  At least
1485                  the very first block is always allocated on the stack
1486                  and this is the block assigned to OLD here.  */
1487               if (names == NULL)
1488                 {
1489                   assert (old == init_names);
1490                   break;
1491                 }
1492               cur = names->count;
1493               if (old == names_alloca)
1494                 names_alloca = names;
1495               else
1496                 free (old);
1497             }
1498 
1499           pglob->gl_pathv = new_gl_pathv;
1500 
1501           pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
1502 
1503           pglob->gl_flags = flags;
1504         }
1505     }
1506 
1507   if (stream != NULL)
1508     {
1509       save = errno;
1510       if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
1511         (*pglob->gl_closedir) (stream);
1512       else
1513         closedir (stream);
1514       __set_errno (save);
1515     }
1516 
1517   return result;
1518 }

/* [previous][next][first][last][top][bottom][index][help] */