bcc1e3
This is a rebase of posix/glob.c from upstream (gnulib->glibc->rhel).
bcc1e3
bcc1e3
Relevent upstream commits:
bcc1e3
bcc1e3
7c477b57a31487eda516db02b9e04f22d1a6e6af posix/glob.c: update from gnulib
bcc1e3
  (This is the master commit to which we're syncing)
bcc1e3
bcc1e3
gnulib commit 98f034a0c2ba8917c96f363de1a8d66244e411da
bcc1e3
  (This is the gnulib commit to which glibc upstream sync'd)
bcc1e3
bcc1e3
Additional glibc upstream commits of note:
bcc1e3
84f7ce84474c1648ce96884f1c91ca7b97ca3fc2 posix: Add glob64 with 64-bit time_t support
bcc1e3
  (just posix/glob.c and sysdeps/gnu/glob64-lstat-compat.c)
bcc1e3
9a7ab0769b295cbf5232140401742a8f34bda3de hurd: Fix glob lstat compatibility
bcc1e3
4883360415f1ed772ba44decc501d59deb17bdf0 posix: Sync glob code with gnulib
bcc1e3
04986243d1af37ac0177ed2f9db0a066ebd2b212 Remove internal usage of extensible stat functions
bcc1e3
ddc650e9b3dc916eab417ce9f79e67337b05035c Fix use-after-free in glob when expanding ~user (bug 25414)
bcc1e3
bcc1e3
bcc1e3
diff -rup a/posix/glob-lstat-compat.c b/posix/glob-lstat-compat.c
bcc1e3
--- a/posix/glob-lstat-compat.c	2018-08-01 01:10:47.000000000 -0400
bcc1e3
+++ b/posix/glob-lstat-compat.c	2022-05-02 22:49:06.504676711 -0400
bcc1e3
@@ -28,7 +28,8 @@
bcc1e3
 # define GLOB_ATTRIBUTE attribute_compat_text_section
bcc1e3
 
bcc1e3
 /* Avoid calling gl_lstat with GLOB_ALTDIRFUNC.  */
bcc1e3
-# define GLOB_NO_LSTAT
bcc1e3
+# define GLOB_LSTAT   gl_stat
bcc1e3
+# define GLOB_LSTAT64 __stat64
bcc1e3
 
bcc1e3
 # include <posix/glob.c>
bcc1e3
 
bcc1e3
diff -rup a/posix/glob.c b/posix/glob.c
bcc1e3
--- a/posix/glob.c	2022-05-03 14:37:52.959042051 -0400
bcc1e3
+++ b/posix/glob.c	2022-05-02 22:49:18.655134696 -0400
bcc1e3
@@ -1,4 +1,4 @@
bcc1e3
-/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
bcc1e3
+/* Copyright (C) 1991-2022 Free Software Foundation, Inc.
bcc1e3
    This file is part of the GNU C Library.
bcc1e3
 
bcc1e3
    The GNU C Library is free software; you can redistribute it and/or
bcc1e3
@@ -13,11 +13,22 @@
bcc1e3
 
bcc1e3
    You should have received a copy of the GNU Lesser General Public
bcc1e3
    License along with the GNU C Library; if not, see
bcc1e3
-   <http://www.gnu.org/licenses/>.  */
bcc1e3
+   <https://www.gnu.org/licenses/>.  */
bcc1e3
+
bcc1e3
+#ifndef _LIBC
bcc1e3
+
bcc1e3
+/* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
bcc1e3
+   optimizes away the pattern == NULL test below.  */
bcc1e3
+# define _GL_ARG_NONNULL(params)
bcc1e3
+
bcc1e3
+# include <libc-config.h>
bcc1e3
+
bcc1e3
+#endif
bcc1e3
 
bcc1e3
 #include <glob.h>
bcc1e3
 
bcc1e3
 #include <errno.h>
bcc1e3
+#include <fcntl.h>
bcc1e3
 #include <sys/types.h>
bcc1e3
 #include <sys/stat.h>
bcc1e3
 #include <stdbool.h>
bcc1e3
@@ -26,7 +37,7 @@
bcc1e3
 #include <assert.h>
bcc1e3
 #include <unistd.h>
bcc1e3
 
bcc1e3
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
bcc1e3
+#if defined _WIN32 && ! defined __CYGWIN__
bcc1e3
 # define WINDOWS32
bcc1e3
 #endif
bcc1e3
 
bcc1e3
@@ -46,30 +57,38 @@
bcc1e3
 # define sysconf(id) __sysconf (id)
bcc1e3
 # define closedir(dir) __closedir (dir)
bcc1e3
 # define opendir(name) __opendir (name)
bcc1e3
+# undef dirfd
bcc1e3
+# define dirfd(str) __dirfd (str)
bcc1e3
 # define readdir(str) __readdir64 (str)
bcc1e3
 # define getpwnam_r(name, bufp, buf, len, res) \
bcc1e3
     __getpwnam_r (name, bufp, buf, len, res)
bcc1e3
-# ifndef __lstat64
bcc1e3
-#  define __lstat64(fname, buf) __lxstat64 (_STAT_VER, fname, buf)
bcc1e3
+# define FLEXIBLE_ARRAY_MEMBER
bcc1e3
+# ifndef struct_stat
bcc1e3
+#  define struct_stat           struct stat
bcc1e3
 # endif
bcc1e3
-# ifndef __stat64
bcc1e3
-#  define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
bcc1e3
+# ifndef struct_stat64
bcc1e3
+#  define struct_stat64         struct stat64
bcc1e3
+# endif
bcc1e3
+# ifndef GLOB_LSTAT
bcc1e3
+#  define GLOB_LSTAT            gl_lstat
bcc1e3
+# endif
bcc1e3
+# ifndef GLOB_FSTATAT64
bcc1e3
+#  define GLOB_FSTATAT64        __fstatat64
bcc1e3
 # endif
bcc1e3
-# define struct_stat64		struct stat64
bcc1e3
-# define FLEXIBLE_ARRAY_MEMBER
bcc1e3
 # include <shlib-compat.h>
bcc1e3
 #else /* !_LIBC */
bcc1e3
 # define __glob                 glob
bcc1e3
 # define __getlogin_r(buf, len) getlogin_r (buf, len)
bcc1e3
-# define __lstat64(fname, buf)  lstat (fname, buf)
bcc1e3
-# define __stat64(fname, buf)   stat (fname, buf)
bcc1e3
 # define __fxstatat64(_, d, f, st, flag) fstatat (d, f, st, flag)
bcc1e3
-# define struct_stat64          struct stat
bcc1e3
 # ifndef __MVS__
bcc1e3
 #  define __alloca              alloca
bcc1e3
 # endif
bcc1e3
 # define __readdir              readdir
bcc1e3
 # define COMPILE_GLOB64
bcc1e3
+# define struct_stat            struct stat
bcc1e3
+# define struct_stat64          struct stat
bcc1e3
+# define GLOB_LSTAT             gl_lstat
bcc1e3
+# define GLOB_FSTATAT64         fstatat
bcc1e3
 #endif /* _LIBC */
bcc1e3
 
bcc1e3
 #include <fnmatch.h>
bcc1e3
@@ -80,7 +99,9 @@
bcc1e3
 
bcc1e3
 static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
bcc1e3
 
bcc1e3
-typedef uint_fast8_t dirent_type;
bcc1e3
+/* The type of ((struct dirent *) 0)->d_type is 'unsigned char' on most
bcc1e3
+   platforms, but 'unsigned int' in the mingw from mingw.org.  */
bcc1e3
+typedef uint_fast32_t dirent_type;
bcc1e3
 
bcc1e3
 #if !defined _LIBC && !defined HAVE_STRUCT_DIRENT_D_TYPE
bcc1e3
 /* Any distinct values will do here.
bcc1e3
@@ -119,9 +140,9 @@ readdir_result_type (struct readdir_resu
bcc1e3
 /* Construct an initializer for a struct readdir_result object from a
bcc1e3
    struct dirent *.  No copy of the name is made.  */
bcc1e3
 #define READDIR_RESULT_INITIALIZER(source) \
bcc1e3
-  {					   \
bcc1e3
-    source->d_name,			   \
bcc1e3
-    D_TYPE_TO_RESULT (source)		   \
bcc1e3
+  {                                        \
bcc1e3
+    source->d_name,                        \
bcc1e3
+    D_TYPE_TO_RESULT (source)              \
bcc1e3
   }
bcc1e3
 
bcc1e3
 /* Call gl_readdir on STREAM.  This macro can be overridden to reduce
bcc1e3
@@ -186,22 +207,15 @@ glob_lstat (glob_t *pglob, int flags, co
bcc1e3
 {
bcc1e3
 /* Use on glob-lstat-compat.c to provide a compat symbol which does not
bcc1e3
    use lstat / gl_lstat.  */
bcc1e3
-#ifdef GLOB_NO_LSTAT
bcc1e3
-# define GL_LSTAT gl_stat
bcc1e3
-# define LSTAT64 __stat64
bcc1e3
-#else
bcc1e3
-# define GL_LSTAT gl_lstat
bcc1e3
-# define LSTAT64 __lstat64
bcc1e3
-#endif
bcc1e3
-
bcc1e3
   union
bcc1e3
   {
bcc1e3
-    struct stat st;
bcc1e3
+    struct_stat st;
bcc1e3
     struct_stat64 st64;
bcc1e3
   } ust;
bcc1e3
   return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
bcc1e3
-          ? pglob->GL_LSTAT (fullname, &ust.st)
bcc1e3
-          : LSTAT64 (fullname, &ust.st64));
bcc1e3
+          ? pglob->GLOB_LSTAT (fullname, &ust.st)
bcc1e3
+          : GLOB_FSTATAT64 (AT_FDCWD, fullname, &ust.st64,
bcc1e3
+                            AT_SYMLINK_NOFOLLOW));
bcc1e3
 }
bcc1e3
 
bcc1e3
 /* Set *R = A + B.  Return true if the answer is mathematically
bcc1e3
@@ -211,7 +225,7 @@ glob_lstat (glob_t *pglob, int flags, co
bcc1e3
 static bool
bcc1e3
 size_add_wrapv (size_t a, size_t b, size_t *r)
bcc1e3
 {
bcc1e3
-#if 5 <= __GNUC__ && !defined __ICC
bcc1e3
+#if 7 <= __GNUC__ && !defined __ICC
bcc1e3
   return __builtin_add_overflow (a, b, r);
bcc1e3
 #else
bcc1e3
   *r = a + b;
bcc1e3
@@ -228,8 +242,8 @@ glob_use_alloca (size_t alloca_used, siz
bcc1e3
 }
bcc1e3
 
bcc1e3
 static int glob_in_dir (const char *pattern, const char *directory,
bcc1e3
-			int flags, int (*errfunc) (const char *, int),
bcc1e3
-			glob_t *pglob, size_t alloca_used);
bcc1e3
+                        int flags, int (*errfunc) (const char *, int),
bcc1e3
+                        glob_t *pglob, size_t alloca_used);
bcc1e3
 static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL;
bcc1e3
 static int collated_compare (const void *, const void *) __THROWNL;
bcc1e3
 
bcc1e3
@@ -239,11 +253,12 @@ static int collated_compare (const void
bcc1e3
 static bool
bcc1e3
 is_dir (char const *filename, int flags, glob_t const *pglob)
bcc1e3
 {
bcc1e3
-  struct stat st;
bcc1e3
+  struct_stat st;
bcc1e3
   struct_stat64 st64;
bcc1e3
   return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
bcc1e3
           ? pglob->gl_stat (filename, &st) == 0 && S_ISDIR (st.st_mode)
bcc1e3
-          : __stat64 (filename, &st64) == 0 && S_ISDIR (st64.st_mode));
bcc1e3
+          : (GLOB_FSTATAT64 (AT_FDCWD, filename, &st64, 0) == 0
bcc1e3
+             && S_ISDIR (st64.st_mode)));
bcc1e3
 }
bcc1e3
 
bcc1e3
 /* Find the end of the sub-pattern in a brace expression.  */
bcc1e3
@@ -254,17 +269,17 @@ next_brace_sub (const char *cp, int flag
bcc1e3
   while (*cp != '\0')
bcc1e3
     if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\')
bcc1e3
       {
bcc1e3
-	if (*++cp == '\0')
bcc1e3
-	  break;
bcc1e3
-	++cp;
bcc1e3
+        if (*++cp == '\0')
bcc1e3
+          break;
bcc1e3
+        ++cp;
bcc1e3
       }
bcc1e3
     else
bcc1e3
       {
bcc1e3
-	if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
bcc1e3
-	  break;
bcc1e3
+        if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
bcc1e3
+          break;
bcc1e3
 
bcc1e3
-	if (*cp++ == '{')
bcc1e3
-	  depth++;
bcc1e3
+        if (*cp++ == '{')
bcc1e3
+          depth++;
bcc1e3
       }
bcc1e3
 
bcc1e3
   return *cp != '\0' ? cp : NULL;
bcc1e3
@@ -285,7 +300,7 @@ next_brace_sub (const char *cp, int flag
bcc1e3
 int
bcc1e3
 GLOB_ATTRIBUTE
bcc1e3
 __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
bcc1e3
-	glob_t *pglob)
bcc1e3
+        glob_t *pglob)
bcc1e3
 {
bcc1e3
   const char *filename;
bcc1e3
   char *dirname = NULL;
bcc1e3
@@ -319,22 +334,22 @@ __glob (const char *pattern, int flags,
bcc1e3
     {
bcc1e3
       pglob->gl_pathc = 0;
bcc1e3
       if (!(flags & GLOB_DOOFFS))
bcc1e3
-	pglob->gl_pathv = NULL;
bcc1e3
+        pglob->gl_pathv = NULL;
bcc1e3
       else
bcc1e3
-	{
bcc1e3
-	  size_t i;
bcc1e3
+        {
bcc1e3
+          size_t i;
bcc1e3
 
bcc1e3
-	  if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
bcc1e3
-	    return GLOB_NOSPACE;
bcc1e3
+          if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
bcc1e3
+            return GLOB_NOSPACE;
bcc1e3
 
bcc1e3
-	  pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
bcc1e3
-					      * sizeof (char *));
bcc1e3
-	  if (pglob->gl_pathv == NULL)
bcc1e3
-	    return GLOB_NOSPACE;
bcc1e3
-
bcc1e3
-	  for (i = 0; i <= pglob->gl_offs; ++i)
bcc1e3
-	    pglob->gl_pathv[i] = NULL;
bcc1e3
-	}
bcc1e3
+          pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
bcc1e3
+                                              * sizeof (char *));
bcc1e3
+          if (pglob->gl_pathv == NULL)
bcc1e3
+            return GLOB_NOSPACE;
bcc1e3
+
bcc1e3
+          for (i = 0; i <= pglob->gl_offs; ++i)
bcc1e3
+            pglob->gl_pathv[i] = NULL;
bcc1e3
+        }
bcc1e3
     }
bcc1e3
 
bcc1e3
   if (flags & GLOB_BRACE)
bcc1e3
@@ -342,129 +357,129 @@ __glob (const char *pattern, int flags,
bcc1e3
       const char *begin;
bcc1e3
 
bcc1e3
       if (flags & GLOB_NOESCAPE)
bcc1e3
-	begin = strchr (pattern, '{');
bcc1e3
+        begin = strchr (pattern, '{');
bcc1e3
       else
bcc1e3
-	{
bcc1e3
-	  begin = pattern;
bcc1e3
-	  while (1)
bcc1e3
-	    {
bcc1e3
-	      if (*begin == '\0')
bcc1e3
-		{
bcc1e3
-		  begin = NULL;
bcc1e3
-		  break;
bcc1e3
-		}
bcc1e3
-
bcc1e3
-	      if (*begin == '\\' && begin[1] != '\0')
bcc1e3
-		++begin;
bcc1e3
-	      else if (*begin == '{')
bcc1e3
-		break;
bcc1e3
-
bcc1e3
-	      ++begin;
bcc1e3
-	    }
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          begin = pattern;
bcc1e3
+          while (1)
bcc1e3
+            {
bcc1e3
+              if (*begin == '\0')
bcc1e3
+                {
bcc1e3
+                  begin = NULL;
bcc1e3
+                  break;
bcc1e3
+                }
bcc1e3
+
bcc1e3
+              if (*begin == '\\' && begin[1] != '\0')
bcc1e3
+                ++begin;
bcc1e3
+              else if (*begin == '{')
bcc1e3
+                break;
bcc1e3
+
bcc1e3
+              ++begin;
bcc1e3
+            }
bcc1e3
+        }
bcc1e3
 
bcc1e3
       if (begin != NULL)
bcc1e3
-	{
bcc1e3
-	  /* Allocate working buffer large enough for our work.  Note that
bcc1e3
-	    we have at least an opening and closing brace.  */
bcc1e3
-	  size_t firstc;
bcc1e3
-	  char *alt_start;
bcc1e3
-	  const char *p;
bcc1e3
-	  const char *next;
bcc1e3
-	  const char *rest;
bcc1e3
-	  size_t rest_len;
bcc1e3
-	  char *onealt;
bcc1e3
-	  size_t pattern_len = strlen (pattern) - 1;
bcc1e3
-	  int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
bcc1e3
-	  if (alloca_onealt)
bcc1e3
-	    onealt = alloca_account (pattern_len, alloca_used);
bcc1e3
-	  else
bcc1e3
-	    {
bcc1e3
-	      onealt = malloc (pattern_len);
bcc1e3
-	      if (onealt == NULL)
bcc1e3
-		return GLOB_NOSPACE;
bcc1e3
-	    }
bcc1e3
-
bcc1e3
-	  /* We know the prefix for all sub-patterns.  */
bcc1e3
-	  alt_start = mempcpy (onealt, pattern, begin - pattern);
bcc1e3
-
bcc1e3
-	  /* Find the first sub-pattern and at the same time find the
bcc1e3
-	     rest after the closing brace.  */
bcc1e3
-	  next = next_brace_sub (begin + 1, flags);
bcc1e3
-	  if (next == NULL)
bcc1e3
-	    {
bcc1e3
-	      /* It is an invalid expression.  */
bcc1e3
-	    illegal_brace:
bcc1e3
-	      if (__glibc_unlikely (!alloca_onealt))
bcc1e3
-		free (onealt);
bcc1e3
-	      flags &= ~GLOB_BRACE;
bcc1e3
-	      goto no_brace;
bcc1e3
-	    }
bcc1e3
-
bcc1e3
-	  /* Now find the end of the whole brace expression.  */
bcc1e3
-	  rest = next;
bcc1e3
-	  while (*rest != '}')
bcc1e3
-	    {
bcc1e3
-	      rest = next_brace_sub (rest + 1, flags);
bcc1e3
-	      if (rest == NULL)
bcc1e3
-		/* It is an illegal expression.  */
bcc1e3
-		goto illegal_brace;
bcc1e3
-	    }
bcc1e3
-	  /* Please note that we now can be sure the brace expression
bcc1e3
-	     is well-formed.  */
bcc1e3
-	  rest_len = strlen (++rest) + 1;
bcc1e3
-
bcc1e3
-	  /* We have a brace expression.  BEGIN points to the opening {,
bcc1e3
-	     NEXT points past the terminator of the first element, and END
bcc1e3
-	     points past the final }.  We will accumulate result names from
bcc1e3
-	     recursive runs for each brace alternative in the buffer using
bcc1e3
-	     GLOB_APPEND.  */
bcc1e3
-	  firstc = pglob->gl_pathc;
bcc1e3
-
bcc1e3
-	  p = begin + 1;
bcc1e3
-	  while (1)
bcc1e3
-	    {
bcc1e3
-	      int result;
bcc1e3
-
bcc1e3
-	      /* Construct the new glob expression.  */
bcc1e3
-	      mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
bcc1e3
-
bcc1e3
-	      result = __glob (onealt,
bcc1e3
-			       ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
bcc1e3
-				| GLOB_APPEND),
bcc1e3
-			       errfunc, pglob);
bcc1e3
-
bcc1e3
-	      /* If we got an error, return it.  */
bcc1e3
-	      if (result && result != GLOB_NOMATCH)
bcc1e3
-		{
bcc1e3
-		  if (__glibc_unlikely (!alloca_onealt))
bcc1e3
-		    free (onealt);
bcc1e3
-		  if (!(flags & GLOB_APPEND))
bcc1e3
-		    {
bcc1e3
-		      globfree (pglob);
bcc1e3
-		      pglob->gl_pathc = 0;
bcc1e3
-		    }
bcc1e3
-		  return result;
bcc1e3
-		}
bcc1e3
-
bcc1e3
-	      if (*next == '}')
bcc1e3
-		/* We saw the last entry.  */
bcc1e3
-		break;
bcc1e3
-
bcc1e3
-	      p = next + 1;
bcc1e3
-	      next = next_brace_sub (p, flags);
bcc1e3
-	      assert (next != NULL);
bcc1e3
-	    }
bcc1e3
-
bcc1e3
-	  if (__glibc_unlikely (!alloca_onealt))
bcc1e3
-	    free (onealt);
bcc1e3
-
bcc1e3
-	  if (pglob->gl_pathc != firstc)
bcc1e3
-	    /* We found some entries.  */
bcc1e3
-	    return 0;
bcc1e3
-	  else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
bcc1e3
-	    return GLOB_NOMATCH;
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          /* Allocate working buffer large enough for our work.  Note that
bcc1e3
+             we have at least an opening and closing brace.  */
bcc1e3
+          size_t firstc;
bcc1e3
+          char *alt_start;
bcc1e3
+          const char *p;
bcc1e3
+          const char *next;
bcc1e3
+          const char *rest;
bcc1e3
+          size_t rest_len;
bcc1e3
+          char *onealt;
bcc1e3
+          size_t pattern_len = strlen (pattern) - 1;
bcc1e3
+          int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
bcc1e3
+          if (alloca_onealt)
bcc1e3
+            onealt = alloca_account (pattern_len, alloca_used);
bcc1e3
+          else
bcc1e3
+            {
bcc1e3
+              onealt = malloc (pattern_len);
bcc1e3
+              if (onealt == NULL)
bcc1e3
+                return GLOB_NOSPACE;
bcc1e3
+            }
bcc1e3
+
bcc1e3
+          /* We know the prefix for all sub-patterns.  */
bcc1e3
+          alt_start = mempcpy (onealt, pattern, begin - pattern);
bcc1e3
+
bcc1e3
+          /* Find the first sub-pattern and at the same time find the
bcc1e3
+             rest after the closing brace.  */
bcc1e3
+          next = next_brace_sub (begin + 1, flags);
bcc1e3
+          if (next == NULL)
bcc1e3
+            {
bcc1e3
+              /* It is an invalid expression.  */
bcc1e3
+            illegal_brace:
bcc1e3
+              if (__glibc_unlikely (!alloca_onealt))
bcc1e3
+                free (onealt);
bcc1e3
+              flags &= ~GLOB_BRACE;
bcc1e3
+              goto no_brace;
bcc1e3
+            }
bcc1e3
+
bcc1e3
+          /* Now find the end of the whole brace expression.  */
bcc1e3
+          rest = next;
bcc1e3
+          while (*rest != '}')
bcc1e3
+            {
bcc1e3
+              rest = next_brace_sub (rest + 1, flags);
bcc1e3
+              if (rest == NULL)
bcc1e3
+                /* It is an illegal expression.  */
bcc1e3
+                goto illegal_brace;
bcc1e3
+            }
bcc1e3
+          /* Please note that we now can be sure the brace expression
bcc1e3
+             is well-formed.  */
bcc1e3
+          rest_len = strlen (++rest) + 1;
bcc1e3
+
bcc1e3
+          /* We have a brace expression.  BEGIN points to the opening {,
bcc1e3
+             NEXT points past the terminator of the first element, and END
bcc1e3
+             points past the final }.  We will accumulate result names from
bcc1e3
+             recursive runs for each brace alternative in the buffer using
bcc1e3
+             GLOB_APPEND.  */
bcc1e3
+          firstc = pglob->gl_pathc;
bcc1e3
+
bcc1e3
+          p = begin + 1;
bcc1e3
+          while (1)
bcc1e3
+            {
bcc1e3
+              int result;
bcc1e3
+
bcc1e3
+              /* Construct the new glob expression.  */
bcc1e3
+              mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
bcc1e3
+
bcc1e3
+              result = __glob (onealt,
bcc1e3
+                               ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
bcc1e3
+                                | GLOB_APPEND),
bcc1e3
+                               errfunc, pglob);
bcc1e3
+
bcc1e3
+              /* If we got an error, return it.  */
bcc1e3
+              if (result && result != GLOB_NOMATCH)
bcc1e3
+                {
bcc1e3
+                  if (__glibc_unlikely (!alloca_onealt))
bcc1e3
+                    free (onealt);
bcc1e3
+                  if (!(flags & GLOB_APPEND))
bcc1e3
+                    {
bcc1e3
+                      globfree (pglob);
bcc1e3
+                      pglob->gl_pathc = 0;
bcc1e3
+                    }
bcc1e3
+                  return result;
bcc1e3
+                }
bcc1e3
+
bcc1e3
+              if (*next == '}')
bcc1e3
+                /* We saw the last entry.  */
bcc1e3
+                break;
bcc1e3
+
bcc1e3
+              p = next + 1;
bcc1e3
+              next = next_brace_sub (p, flags);
bcc1e3
+              assert (next != NULL);
bcc1e3
+            }
bcc1e3
+
bcc1e3
+          if (__glibc_unlikely (!alloca_onealt))
bcc1e3
+            free (onealt);
bcc1e3
+
bcc1e3
+          if (pglob->gl_pathc != firstc)
bcc1e3
+            /* We found some entries.  */
bcc1e3
+            return 0;
bcc1e3
+          else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
bcc1e3
+            return GLOB_NOMATCH;
bcc1e3
+        }
bcc1e3
     }
bcc1e3
 
bcc1e3
  no_brace:
bcc1e3
@@ -486,33 +501,33 @@ __glob (const char *pattern, int flags,
bcc1e3
   if (filename == NULL)
bcc1e3
     {
bcc1e3
       /* This can mean two things: a simple name or "~name".  The latter
bcc1e3
-	 case is nothing but a notation for a directory.  */
bcc1e3
+         case is nothing but a notation for a directory.  */
bcc1e3
       if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
bcc1e3
-	{
bcc1e3
-	  dirname = (char *) pattern;
bcc1e3
-	  dirlen = strlen (pattern);
bcc1e3
-
bcc1e3
-	  /* Set FILENAME to NULL as a special flag.  This is ugly but
bcc1e3
-	     other solutions would require much more code.  We test for
bcc1e3
-	     this special case below.  */
bcc1e3
-	  filename = NULL;
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          dirname = (char *) pattern;
bcc1e3
+          dirlen = strlen (pattern);
bcc1e3
+
bcc1e3
+          /* Set FILENAME to NULL as a special flag.  This is ugly but
bcc1e3
+             other solutions would require much more code.  We test for
bcc1e3
+             this special case below.  */
bcc1e3
+          filename = NULL;
bcc1e3
+        }
bcc1e3
       else
bcc1e3
-	{
bcc1e3
-	  if (__glibc_unlikely (pattern[0] == '\0'))
bcc1e3
-	    {
bcc1e3
-	      dirs.gl_pathv = NULL;
bcc1e3
-	      goto no_matches;
bcc1e3
-	    }
bcc1e3
-
bcc1e3
-	  filename = pattern;
bcc1e3
-	  dirname = (char *) ".";
bcc1e3
-	  dirlen = 0;
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          if (__glibc_unlikely (pattern[0] == '\0'))
bcc1e3
+            {
bcc1e3
+              dirs.gl_pathv = NULL;
bcc1e3
+              goto no_matches;
bcc1e3
+            }
bcc1e3
+
bcc1e3
+          filename = pattern;
bcc1e3
+          dirname = (char *) ".";
bcc1e3
+          dirlen = 0;
bcc1e3
+        }
bcc1e3
     }
bcc1e3
   else if (filename == pattern
bcc1e3
-	   || (filename == pattern + 1 && pattern[0] == '\\'
bcc1e3
-	       && (flags & GLOB_NOESCAPE) == 0))
bcc1e3
+           || (filename == pattern + 1 && pattern[0] == '\\'
bcc1e3
+               && (flags & GLOB_NOESCAPE) == 0))
bcc1e3
     {
bcc1e3
       /* "/pattern" or "\\/pattern".  */
bcc1e3
       dirname = (char *) "/";
bcc1e3
@@ -525,32 +540,32 @@ __glob (const char *pattern, int flags,
bcc1e3
       dirlen = filename - pattern;
bcc1e3
 #if defined __MSDOS__ || defined WINDOWS32
bcc1e3
       if (*filename == ':'
bcc1e3
-	  || (filename > pattern + 1 && filename[-1] == ':'))
bcc1e3
-	{
bcc1e3
-	  char *drive_spec;
bcc1e3
-
bcc1e3
-	  ++dirlen;
bcc1e3
-	  drive_spec = __alloca (dirlen + 1);
bcc1e3
-	  *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
bcc1e3
-	  /* For now, disallow wildcards in the drive spec, to
bcc1e3
-	     prevent infinite recursion in glob.  */
bcc1e3
-	  if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
bcc1e3
-	    return GLOB_NOMATCH;
bcc1e3
-	  /* If this is "d:pattern", we need to copy ':' to DIRNAME
bcc1e3
-	     as well.  If it's "d:/pattern", don't remove the slash
bcc1e3
-	     from "d:/", since "d:" and "d:/" are not the same.*/
bcc1e3
-	}
bcc1e3
+          || (filename > pattern + 1 && filename[-1] == ':'))
bcc1e3
+        {
bcc1e3
+          char *drive_spec;
bcc1e3
+
bcc1e3
+          ++dirlen;
bcc1e3
+          drive_spec = __alloca (dirlen + 1);
bcc1e3
+          *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
bcc1e3
+          /* For now, disallow wildcards in the drive spec, to
bcc1e3
+             prevent infinite recursion in glob.  */
bcc1e3
+          if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
bcc1e3
+            return GLOB_NOMATCH;
bcc1e3
+          /* If this is "d:pattern", we need to copy ':' to DIRNAME
bcc1e3
+             as well.  If it's "d:/pattern", don't remove the slash
bcc1e3
+             from "d:/", since "d:" and "d:/" are not the same.*/
bcc1e3
+        }
bcc1e3
 #endif
bcc1e3
 
bcc1e3
       if (glob_use_alloca (alloca_used, dirlen + 1))
bcc1e3
-	newp = alloca_account (dirlen + 1, alloca_used);
bcc1e3
+        newp = alloca_account (dirlen + 1, alloca_used);
bcc1e3
       else
bcc1e3
-	{
bcc1e3
-	  newp = malloc (dirlen + 1);
bcc1e3
-	  if (newp == NULL)
bcc1e3
-	    return GLOB_NOSPACE;
bcc1e3
-	  malloc_dirname = 1;
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          newp = malloc (dirlen + 1);
bcc1e3
+          if (newp == NULL)
bcc1e3
+            return GLOB_NOSPACE;
bcc1e3
+          malloc_dirname = 1;
bcc1e3
+        }
bcc1e3
       *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
bcc1e3
       dirname = newp;
bcc1e3
       ++filename;
bcc1e3
@@ -566,363 +581,383 @@ __glob (const char *pattern, int flags,
bcc1e3
 
bcc1e3
       if (filename[0] == '\0' && dirlen > 1 && !drive_root)
bcc1e3
         /* "pattern/".  Expand "pattern", appending slashes.  */
bcc1e3
-	{
bcc1e3
-	  int orig_flags = flags;
bcc1e3
-	  if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
bcc1e3
-	    {
bcc1e3
-	      /* "pattern\\/".  Remove the final backslash if it hasn't
bcc1e3
-		 been quoted.  */
bcc1e3
-	      char *p = (char *) &dirname[dirlen - 1];
bcc1e3
-
bcc1e3
-	      while (p > dirname && p[-1] == '\\') --p;
bcc1e3
-	      if ((&dirname[dirlen] - p) & 1)
bcc1e3
-		{
bcc1e3
-		  *(char *) &dirname[--dirlen] = '\0';
bcc1e3
-		  flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
bcc1e3
-		}
bcc1e3
-	    }
bcc1e3
-	  int val = __glob (dirname, flags | GLOB_MARK, errfunc, pglob);
bcc1e3
-	  if (val == 0)
bcc1e3
-	    pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
bcc1e3
-			       | (flags & GLOB_MARK));
bcc1e3
-	  else if (val == GLOB_NOMATCH && flags != orig_flags)
bcc1e3
-	    {
bcc1e3
-	      /* Make sure globfree (&dirs); is a nop.  */
bcc1e3
-	      dirs.gl_pathv = NULL;
bcc1e3
-	      flags = orig_flags;
bcc1e3
-	      oldcount = pglob->gl_pathc + pglob->gl_offs;
bcc1e3
-	      goto no_matches;
bcc1e3
-	    }
bcc1e3
-	  retval = val;
bcc1e3
-	  goto out;
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          int orig_flags = flags;
bcc1e3
+          if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
bcc1e3
+            {
bcc1e3
+              /* "pattern\\/".  Remove the final backslash if it hasn't
bcc1e3
+                 been quoted.  */
bcc1e3
+              char *p = (char *) &dirname[dirlen - 1];
bcc1e3
+
bcc1e3
+              while (p > dirname && p[-1] == '\\') --p;
bcc1e3
+              if ((&dirname[dirlen] - p) & 1)
bcc1e3
+                {
bcc1e3
+                  *(char *) &dirname[--dirlen] = '\0';
bcc1e3
+                  flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
bcc1e3
+                }
bcc1e3
+            }
bcc1e3
+          int val = __glob (dirname, flags | GLOB_MARK, errfunc, pglob);
bcc1e3
+          if (val == 0)
bcc1e3
+            pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
bcc1e3
+                               | (flags & GLOB_MARK));
bcc1e3
+          else if (val == GLOB_NOMATCH && flags != orig_flags)
bcc1e3
+            {
bcc1e3
+              /* Make sure globfree (&dirs); is a nop.  */
bcc1e3
+              dirs.gl_pathv = NULL;
bcc1e3
+              flags = orig_flags;
bcc1e3
+              oldcount = pglob->gl_pathc + pglob->gl_offs;
bcc1e3
+              goto no_matches;
bcc1e3
+            }
bcc1e3
+          retval = val;
bcc1e3
+          goto out;
bcc1e3
+        }
bcc1e3
     }
bcc1e3
 
bcc1e3
   if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
bcc1e3
     {
bcc1e3
       if (dirname[1] == '\0' || dirname[1] == '/'
bcc1e3
-	  || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\'
bcc1e3
-	      && (dirname[2] == '\0' || dirname[2] == '/')))
bcc1e3
-	{
bcc1e3
-	  /* Look up home directory.  */
bcc1e3
-	  char *home_dir = getenv ("HOME");
bcc1e3
-	  int malloc_home_dir = 0;
bcc1e3
-	  if (home_dir == NULL || home_dir[0] == '\0')
bcc1e3
-	    {
bcc1e3
+          || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\'
bcc1e3
+              && (dirname[2] == '\0' || dirname[2] == '/')))
bcc1e3
+        {
bcc1e3
+          /* Look up home directory.  */
bcc1e3
+          char *home_dir = getenv ("HOME");
bcc1e3
+          int malloc_home_dir = 0;
bcc1e3
+          if (home_dir == NULL || home_dir[0] == '\0')
bcc1e3
+            {
bcc1e3
 #ifdef WINDOWS32
bcc1e3
-	      /* Windows NT defines HOMEDRIVE and HOMEPATH.  But give
bcc1e3
-		 preference to HOME, because the user can change HOME.  */
bcc1e3
-	      const char *home_drive = getenv ("HOMEDRIVE");
bcc1e3
-	      const char *home_path = getenv ("HOMEPATH");
bcc1e3
-
bcc1e3
-	      if (home_drive != NULL && home_path != NULL)
bcc1e3
-		{
bcc1e3
-		  size_t home_drive_len = strlen (home_drive);
bcc1e3
-		  size_t home_path_len = strlen (home_path);
bcc1e3
-		  char *mem = alloca (home_drive_len + home_path_len + 1);
bcc1e3
-
bcc1e3
-		  memcpy (mem, home_drive, home_drive_len);
bcc1e3
-		  memcpy (mem + home_drive_len, home_path, home_path_len + 1);
bcc1e3
-		  home_dir = mem;
bcc1e3
-		}
bcc1e3
-	      else
bcc1e3
-		home_dir = "c:/users/default"; /* poor default */
bcc1e3
+              /* Windows NT defines HOMEDRIVE and HOMEPATH.  But give
bcc1e3
+                 preference to HOME, because the user can change HOME.  */
bcc1e3
+              const char *home_drive = getenv ("HOMEDRIVE");
bcc1e3
+              const char *home_path = getenv ("HOMEPATH");
bcc1e3
+
bcc1e3
+              if (home_drive != NULL && home_path != NULL)
bcc1e3
+                {
bcc1e3
+                  size_t home_drive_len = strlen (home_drive);
bcc1e3
+                  size_t home_path_len = strlen (home_path);
bcc1e3
+                  char *mem = alloca (home_drive_len + home_path_len + 1);
bcc1e3
+
bcc1e3
+                  memcpy (mem, home_drive, home_drive_len);
bcc1e3
+                  memcpy (mem + home_drive_len, home_path, home_path_len + 1);
bcc1e3
+                  home_dir = mem;
bcc1e3
+                }
bcc1e3
+              else
bcc1e3
+                home_dir = "c:/users/default"; /* poor default */
bcc1e3
 #else
bcc1e3
-	      int err;
bcc1e3
-	      struct passwd *p;
bcc1e3
-	      struct passwd pwbuf;
bcc1e3
-	      struct scratch_buffer s;
bcc1e3
-	      scratch_buffer_init (&s);
bcc1e3
-	      while (true)
bcc1e3
-		{
bcc1e3
-		  p = NULL;
bcc1e3
-		  err = __getlogin_r (s.data, s.length);
bcc1e3
-		  if (err == 0)
bcc1e3
-		    {
bcc1e3
+              int err;
bcc1e3
+              struct passwd *p;
bcc1e3
+              struct passwd pwbuf;
bcc1e3
+              struct scratch_buffer s;
bcc1e3
+              scratch_buffer_init (&s);
bcc1e3
+              while (true)
bcc1e3
+                {
bcc1e3
+                  p = NULL;
bcc1e3
+                  err = __getlogin_r (s.data, s.length);
bcc1e3
+                  if (err == 0)
bcc1e3
+                    {
bcc1e3
 # if defined HAVE_GETPWNAM_R || defined _LIBC
bcc1e3
-		      size_t ssize = strlen (s.data) + 1;
bcc1e3
-		      char *sdata = s.data;
bcc1e3
-		      err = getpwnam_r (sdata, &pwbuf, sdata + ssize,
bcc1e3
-					s.length - ssize, &p);
bcc1e3
+                      size_t ssize = strlen (s.data) + 1;
bcc1e3
+                      char *sdata = s.data;
bcc1e3
+                      err = getpwnam_r (sdata, &pwbuf, sdata + ssize,
bcc1e3
+                                        s.length - ssize, &p);
bcc1e3
 # else
bcc1e3
-		      p = getpwnam (s.data);
bcc1e3
-		      if (p == NULL)
bcc1e3
-			err = errno;
bcc1e3
+                      p = getpwnam (s.data);
bcc1e3
+                      if (p == NULL)
bcc1e3
+                        err = errno;
bcc1e3
 # endif
bcc1e3
-		    }
bcc1e3
-		  if (err != ERANGE)
bcc1e3
-		    break;
bcc1e3
-		  if (!scratch_buffer_grow (&s))
bcc1e3
-		    {
bcc1e3
-		      retval = GLOB_NOSPACE;
bcc1e3
-		      goto out;
bcc1e3
-		    }
bcc1e3
-		}
bcc1e3
-	      if (err == 0)
bcc1e3
-		{
bcc1e3
-		  home_dir = strdup (p->pw_dir);
bcc1e3
-		  malloc_home_dir = 1;
bcc1e3
-		}
bcc1e3
-	      scratch_buffer_free (&s);
bcc1e3
-	      if (err == 0 && home_dir == NULL)
bcc1e3
-		{
bcc1e3
-		  retval = GLOB_NOSPACE;
bcc1e3
-		  goto out;
bcc1e3
-		}
bcc1e3
+                    }
bcc1e3
+                  if (err != ERANGE)
bcc1e3
+                    break;
bcc1e3
+                  if (!scratch_buffer_grow (&s))
bcc1e3
+                    {
bcc1e3
+                      retval = GLOB_NOSPACE;
bcc1e3
+                      goto out;
bcc1e3
+                    }
bcc1e3
+                }
bcc1e3
+              if (err == 0)
bcc1e3
+                {
bcc1e3
+                  home_dir = strdup (p->pw_dir);
bcc1e3
+                  malloc_home_dir = 1;
bcc1e3
+                }
bcc1e3
+              scratch_buffer_free (&s);
bcc1e3
+              if (err == 0 && home_dir == NULL)
bcc1e3
+                {
bcc1e3
+                  retval = GLOB_NOSPACE;
bcc1e3
+                  goto out;
bcc1e3
+                }
bcc1e3
 #endif /* WINDOWS32 */
bcc1e3
-	    }
bcc1e3
-	  if (home_dir == NULL || home_dir[0] == '\0')
bcc1e3
-	    {
bcc1e3
-	      if (__glibc_unlikely (malloc_home_dir))
bcc1e3
-		free (home_dir);
bcc1e3
-	      if (flags & GLOB_TILDE_CHECK)
bcc1e3
-		{
bcc1e3
-		  retval = GLOB_NOMATCH;
bcc1e3
-		  goto out;
bcc1e3
-		}
bcc1e3
-	      else
bcc1e3
-		{
bcc1e3
-		  home_dir = (char *) "~"; /* No luck.  */
bcc1e3
-		  malloc_home_dir = 0;
bcc1e3
-		}
bcc1e3
-	    }
bcc1e3
-	  /* Now construct the full directory.  */
bcc1e3
-	  if (dirname[1] == '\0')
bcc1e3
-	    {
bcc1e3
-	      if (__glibc_unlikely (malloc_dirname))
bcc1e3
-		free (dirname);
bcc1e3
-
bcc1e3
-	      dirname = home_dir;
bcc1e3
-	      dirlen = strlen (dirname);
bcc1e3
-	      malloc_dirname = malloc_home_dir;
bcc1e3
-	    }
bcc1e3
-	  else
bcc1e3
-	    {
bcc1e3
-	      char *newp;
bcc1e3
-	      size_t home_len = strlen (home_dir);
bcc1e3
-	      int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
bcc1e3
-	      if (use_alloca)
bcc1e3
-		newp = alloca_account (home_len + dirlen, alloca_used);
bcc1e3
-	      else
bcc1e3
-		{
bcc1e3
-		  newp = malloc (home_len + dirlen);
bcc1e3
-		  if (newp == NULL)
bcc1e3
-		    {
bcc1e3
-		      if (__glibc_unlikely (malloc_home_dir))
bcc1e3
-			free (home_dir);
bcc1e3
-		      retval = GLOB_NOSPACE;
bcc1e3
-		      goto out;
bcc1e3
-		    }
bcc1e3
-		}
bcc1e3
-
bcc1e3
-	      mempcpy (mempcpy (newp, home_dir, home_len),
bcc1e3
-		       &dirname[1], dirlen);
bcc1e3
-
bcc1e3
-	      if (__glibc_unlikely (malloc_dirname))
bcc1e3
-		free (dirname);
bcc1e3
-
bcc1e3
-	      dirname = newp;
bcc1e3
-	      dirlen += home_len - 1;
bcc1e3
-	      malloc_dirname = !use_alloca;
bcc1e3
-
bcc1e3
-	      if (__glibc_unlikely (malloc_home_dir))
bcc1e3
-		free (home_dir);
bcc1e3
-	    }
bcc1e3
-	  dirname_modified = 1;
bcc1e3
-	}
bcc1e3
+            }
bcc1e3
+          if (home_dir == NULL || home_dir[0] == '\0')
bcc1e3
+            {
bcc1e3
+              if (__glibc_unlikely (malloc_home_dir))
bcc1e3
+                free (home_dir);
bcc1e3
+              if (flags & GLOB_TILDE_CHECK)
bcc1e3
+                {
bcc1e3
+                  retval = GLOB_NOMATCH;
bcc1e3
+                  goto out;
bcc1e3
+                }
bcc1e3
+              else
bcc1e3
+                {
bcc1e3
+                  home_dir = (char *) "~"; /* No luck.  */
bcc1e3
+                  malloc_home_dir = 0;
bcc1e3
+                }
bcc1e3
+            }
bcc1e3
+          /* Now construct the full directory.  */
bcc1e3
+          if (dirname[1] == '\0')
bcc1e3
+            {
bcc1e3
+              if (__glibc_unlikely (malloc_dirname))
bcc1e3
+                free (dirname);
bcc1e3
+
bcc1e3
+              dirname = home_dir;
bcc1e3
+              dirlen = strlen (dirname);
bcc1e3
+              malloc_dirname = malloc_home_dir;
bcc1e3
+            }
bcc1e3
+          else
bcc1e3
+            {
bcc1e3
+              char *newp;
bcc1e3
+              size_t home_len = strlen (home_dir);
bcc1e3
+              int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
bcc1e3
+              if (use_alloca)
bcc1e3
+                newp = alloca_account (home_len + dirlen, alloca_used);
bcc1e3
+              else
bcc1e3
+                {
bcc1e3
+                  newp = malloc (home_len + dirlen);
bcc1e3
+                  if (newp == NULL)
bcc1e3
+                    {
bcc1e3
+                      if (__glibc_unlikely (malloc_home_dir))
bcc1e3
+                        free (home_dir);
bcc1e3
+                      retval = GLOB_NOSPACE;
bcc1e3
+                      goto out;
bcc1e3
+                    }
bcc1e3
+                }
bcc1e3
+
bcc1e3
+              mempcpy (mempcpy (newp, home_dir, home_len),
bcc1e3
+                       &dirname[1], dirlen);
bcc1e3
+
bcc1e3
+              if (__glibc_unlikely (malloc_dirname))
bcc1e3
+                free (dirname);
bcc1e3
+
bcc1e3
+              dirname = newp;
bcc1e3
+              dirlen += home_len - 1;
bcc1e3
+              malloc_dirname = !use_alloca;
bcc1e3
+
bcc1e3
+              if (__glibc_unlikely (malloc_home_dir))
bcc1e3
+                free (home_dir);
bcc1e3
+            }
bcc1e3
+          dirname_modified = 1;
bcc1e3
+        }
bcc1e3
       else
bcc1e3
-	{
bcc1e3
+        {
bcc1e3
 #ifndef WINDOWS32
bcc1e3
-	  char *end_name = strchr (dirname, '/');
bcc1e3
-	  char *user_name;
bcc1e3
-	  int malloc_user_name = 0;
bcc1e3
-	  char *unescape = NULL;
bcc1e3
-
bcc1e3
-	  if (!(flags & GLOB_NOESCAPE))
bcc1e3
-	    {
bcc1e3
-	      if (end_name == NULL)
bcc1e3
-		{
bcc1e3
-		  unescape = strchr (dirname, '\\');
bcc1e3
-		  if (unescape)
bcc1e3
-		    end_name = strchr (unescape, '\0');
bcc1e3
-		}
bcc1e3
-	      else
bcc1e3
-		unescape = memchr (dirname, '\\', end_name - dirname);
bcc1e3
-	    }
bcc1e3
-	  if (end_name == NULL)
bcc1e3
-	    user_name = dirname + 1;
bcc1e3
-	  else
bcc1e3
-	    {
bcc1e3
-	      char *newp;
bcc1e3
-	      if (glob_use_alloca (alloca_used, end_name - dirname))
bcc1e3
-		newp = alloca_account (end_name - dirname, alloca_used);
bcc1e3
-	      else
bcc1e3
-		{
bcc1e3
-		  newp = malloc (end_name - dirname);
bcc1e3
-		  if (newp == NULL)
bcc1e3
-		    {
bcc1e3
-		      retval = GLOB_NOSPACE;
bcc1e3
-		      goto out;
bcc1e3
-		    }
bcc1e3
-		  malloc_user_name = 1;
bcc1e3
-		}
bcc1e3
-	      if (unescape != NULL)
bcc1e3
-		{
bcc1e3
-		  char *p = mempcpy (newp, dirname + 1,
bcc1e3
-				     unescape - dirname - 1);
bcc1e3
-		  char *q = unescape;
bcc1e3
-		  while (q != end_name)
bcc1e3
-		    {
bcc1e3
-		      if (*q == '\\')
bcc1e3
-			{
bcc1e3
-			  if (q + 1 == end_name)
bcc1e3
-			    {
bcc1e3
-			      /* "~fo\\o\\" unescape to user_name "foo\\",
bcc1e3
-				 but "~fo\\o\\/" unescape to user_name
bcc1e3
-				 "foo".  */
bcc1e3
-			      if (filename == NULL)
bcc1e3
-				*p++ = '\\';
bcc1e3
-			      break;
bcc1e3
-			    }
bcc1e3
-			  ++q;
bcc1e3
-			}
bcc1e3
-		      *p++ = *q++;
bcc1e3
-		    }
bcc1e3
-		  *p = '\0';
bcc1e3
-		}
bcc1e3
-	      else
bcc1e3
-		*((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1))
bcc1e3
-		  = '\0';
bcc1e3
-	      user_name = newp;
bcc1e3
-	    }
bcc1e3
-
bcc1e3
-	  /* Look up specific user's home directory.  */
bcc1e3
-	  {
bcc1e3
-	    struct passwd *p;
bcc1e3
-	    struct scratch_buffer pwtmpbuf;
bcc1e3
-	    scratch_buffer_init (&pwtmpbuf);
bcc1e3
+          /* Recognize ~user as a shorthand for the specified user's home
bcc1e3
+             directory.  */
bcc1e3
+          char *end_name = strchr (dirname, '/');
bcc1e3
+          char *user_name;
bcc1e3
+          int malloc_user_name = 0;
bcc1e3
+          char *unescape = NULL;
bcc1e3
+
bcc1e3
+          if (!(flags & GLOB_NOESCAPE))
bcc1e3
+            {
bcc1e3
+              if (end_name == NULL)
bcc1e3
+                {
bcc1e3
+                  unescape = strchr (dirname, '\\');
bcc1e3
+                  if (unescape)
bcc1e3
+                    end_name = strchr (unescape, '\0');
bcc1e3
+                }
bcc1e3
+              else
bcc1e3
+                unescape = memchr (dirname, '\\', end_name - dirname);
bcc1e3
+            }
bcc1e3
+          if (end_name == NULL)
bcc1e3
+            user_name = dirname + 1;
bcc1e3
+          else
bcc1e3
+            {
bcc1e3
+              char *newp;
bcc1e3
+              if (glob_use_alloca (alloca_used, end_name - dirname))
bcc1e3
+                newp = alloca_account (end_name - dirname, alloca_used);
bcc1e3
+              else
bcc1e3
+                {
bcc1e3
+                  newp = malloc (end_name - dirname);
bcc1e3
+                  if (newp == NULL)
bcc1e3
+                    {
bcc1e3
+                      retval = GLOB_NOSPACE;
bcc1e3
+                      goto out;
bcc1e3
+                    }
bcc1e3
+                  malloc_user_name = 1;
bcc1e3
+                }
bcc1e3
+              if (unescape != NULL)
bcc1e3
+                {
bcc1e3
+                  char *p = mempcpy (newp, dirname + 1,
bcc1e3
+                                     unescape - dirname - 1);
bcc1e3
+                  char *q = unescape;
bcc1e3
+                  while (q != end_name)
bcc1e3
+                    {
bcc1e3
+                      if (*q == '\\')
bcc1e3
+                        {
bcc1e3
+                          if (q + 1 == end_name)
bcc1e3
+                            {
bcc1e3
+                              /* "~fo\\o\\" unescape to user_name "foo\\",
bcc1e3
+                                 but "~fo\\o\\/" unescape to user_name
bcc1e3
+                                 "foo".  */
bcc1e3
+                              if (filename == NULL)
bcc1e3
+                                *p++ = '\\';
bcc1e3
+                              break;
bcc1e3
+                            }
bcc1e3
+                          ++q;
bcc1e3
+                        }
bcc1e3
+                      *p++ = *q++;
bcc1e3
+                    }
bcc1e3
+                  *p = '\0';
bcc1e3
+                }
bcc1e3
+              else
bcc1e3
+                *((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1))
bcc1e3
+                  = '\0';
bcc1e3
+              user_name = newp;
bcc1e3
+            }
bcc1e3
+
bcc1e3
+          /* Look up specific user's home directory.  */
bcc1e3
+          {
bcc1e3
+            struct passwd *p;
bcc1e3
+            struct scratch_buffer pwtmpbuf;
bcc1e3
+            scratch_buffer_init (&pwtmpbuf);
bcc1e3
 
bcc1e3
 #  if defined HAVE_GETPWNAM_R || defined _LIBC
bcc1e3
-	    struct passwd pwbuf;
bcc1e3
+            struct passwd pwbuf;
bcc1e3
 
bcc1e3
-	    while (getpwnam_r (user_name, &pwbuf,
bcc1e3
-			       pwtmpbuf.data, pwtmpbuf.length, &p)
bcc1e3
-		   == ERANGE)
bcc1e3
-	      {
bcc1e3
-		if (!scratch_buffer_grow (&pwtmpbuf))
bcc1e3
-		  {
bcc1e3
-		    retval = GLOB_NOSPACE;
bcc1e3
-		    goto out;
bcc1e3
-		  }
bcc1e3
-	      }
bcc1e3
+            while (getpwnam_r (user_name, &pwbuf,
bcc1e3
+                               pwtmpbuf.data, pwtmpbuf.length, &p)
bcc1e3
+                   == ERANGE)
bcc1e3
+              {
bcc1e3
+                if (!scratch_buffer_grow (&pwtmpbuf))
bcc1e3
+                  {
bcc1e3
+                    retval = GLOB_NOSPACE;
bcc1e3
+                    goto out;
bcc1e3
+                  }
bcc1e3
+              }
bcc1e3
 #  else
bcc1e3
-	    p = getpwnam (user_name);
bcc1e3
+            p = getpwnam (user_name);
bcc1e3
 #  endif
bcc1e3
 
bcc1e3
-	    if (__glibc_unlikely (malloc_user_name))
bcc1e3
-	      free (user_name);
bcc1e3
+            if (__glibc_unlikely (malloc_user_name))
bcc1e3
+              free (user_name);
bcc1e3
 
bcc1e3
-	    /* If we found a home directory use this.  */
bcc1e3
-	    if (p != NULL)
bcc1e3
-	      {
bcc1e3
-		size_t home_len = strlen (p->pw_dir);
bcc1e3
-		size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
bcc1e3
-		char *d, *newp;
bcc1e3
-		bool use_alloca = glob_use_alloca (alloca_used,
bcc1e3
-						   home_len + rest_len + 1);
bcc1e3
-
bcc1e3
-		if (use_alloca)
bcc1e3
-		  newp = alloca_account (home_len + rest_len + 1, alloca_used);
bcc1e3
-		else
bcc1e3
-		  {
bcc1e3
-		    newp = malloc (home_len + rest_len + 1);
bcc1e3
-		    if (newp == NULL)
bcc1e3
-		      {
bcc1e3
-			scratch_buffer_free (&pwtmpbuf);
bcc1e3
-			retval = GLOB_NOSPACE;
bcc1e3
-			goto out;
bcc1e3
-		      }
bcc1e3
-		  }
bcc1e3
-		d = mempcpy (newp, p->pw_dir, home_len);
bcc1e3
-		if (end_name != NULL)
bcc1e3
-		  d = mempcpy (d, end_name, rest_len);
bcc1e3
-		*d = '\0';
bcc1e3
-
bcc1e3
-		if (__glibc_unlikely (malloc_dirname))
bcc1e3
-		  free (dirname);
bcc1e3
-		dirname = newp;
bcc1e3
-		malloc_dirname = !use_alloca;
bcc1e3
-
bcc1e3
-		dirlen = home_len + rest_len;
bcc1e3
-		dirname_modified = 1;
bcc1e3
-	      }
bcc1e3
-	    else
bcc1e3
-	      {
bcc1e3
-		if (flags & GLOB_TILDE_CHECK)
bcc1e3
-		  {
bcc1e3
-		    /* We have to regard it as an error if we cannot find the
bcc1e3
-		       home directory.  */
bcc1e3
-		    retval = GLOB_NOMATCH;
bcc1e3
-		    goto out;
bcc1e3
-		  }
bcc1e3
-	      }
bcc1e3
-	    scratch_buffer_free (&pwtmpbuf);
bcc1e3
-	  }
bcc1e3
-#endif /* !WINDOWS32 */
bcc1e3
-	}
bcc1e3
+            /* If we found a home directory use this.  */
bcc1e3
+            if (p != NULL)
bcc1e3
+              {
bcc1e3
+                size_t home_len = strlen (p->pw_dir);
bcc1e3
+                size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
bcc1e3
+                /* dirname contains end_name; we can't free it now.  */
bcc1e3
+                char *prev_dirname =
bcc1e3
+                  (__glibc_unlikely (malloc_dirname) ? dirname : NULL);
bcc1e3
+                char *d;
bcc1e3
+
bcc1e3
+                malloc_dirname = 0;
bcc1e3
+
bcc1e3
+                if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
bcc1e3
+                  dirname = alloca_account (home_len + rest_len + 1,
bcc1e3
+                                            alloca_used);
bcc1e3
+                else
bcc1e3
+                  {
bcc1e3
+                    dirname = malloc (home_len + rest_len + 1);
bcc1e3
+                    if (dirname == NULL)
bcc1e3
+                      {
bcc1e3
+                        free (prev_dirname);
bcc1e3
+                        scratch_buffer_free (&pwtmpbuf);
bcc1e3
+                        retval = GLOB_NOSPACE;
bcc1e3
+                        goto out;
bcc1e3
+                      }
bcc1e3
+                    malloc_dirname = 1;
bcc1e3
+                  }
bcc1e3
+                d = mempcpy (dirname, p->pw_dir, home_len);
bcc1e3
+                if (end_name != NULL)
bcc1e3
+                  d = mempcpy (d, end_name, rest_len);
bcc1e3
+                *d = '\0';
bcc1e3
+
bcc1e3
+                free (prev_dirname);
bcc1e3
+
bcc1e3
+                dirlen = home_len + rest_len;
bcc1e3
+                dirname_modified = 1;
bcc1e3
+              }
bcc1e3
+            else
bcc1e3
+              {
bcc1e3
+                if (flags & GLOB_TILDE_CHECK)
bcc1e3
+                  {
bcc1e3
+                    /* We have to regard it as an error if we cannot find the
bcc1e3
+                       home directory.  */
bcc1e3
+                    retval = GLOB_NOMATCH;
bcc1e3
+                    goto out;
bcc1e3
+                  }
bcc1e3
+              }
bcc1e3
+            scratch_buffer_free (&pwtmpbuf);
bcc1e3
+          }
bcc1e3
+#else /* WINDOWS32 */
bcc1e3
+          /* On native Windows, access to a user's home directory
bcc1e3
+             (via GetUserProfileDirectory) or to a user's environment
bcc1e3
+             variables (via ExpandEnvironmentStringsForUser) requires
bcc1e3
+             the credentials of the user.  Therefore we cannot support
bcc1e3
+             the ~user syntax on this platform.
bcc1e3
+             Handling ~user specially (and treat it like plain ~) if
bcc1e3
+             user is getenv ("USERNAME") would not be a good idea,
bcc1e3
+             since it would make people think that ~user is supported
bcc1e3
+             in general.  */
bcc1e3
+          if (flags & GLOB_TILDE_CHECK)
bcc1e3
+            {
bcc1e3
+              retval = GLOB_NOMATCH;
bcc1e3
+              goto out;
bcc1e3
+            }
bcc1e3
+#endif /* WINDOWS32 */
bcc1e3
+        }
bcc1e3
     }
bcc1e3
 
bcc1e3
   /* Now test whether we looked for "~" or "~NAME".  In this case we
bcc1e3
      can give the answer now.  */
bcc1e3
   if (filename == NULL)
bcc1e3
     {
bcc1e3
-	size_t newcount = pglob->gl_pathc + pglob->gl_offs;
bcc1e3
-	char **new_gl_pathv;
bcc1e3
+      size_t newcount = pglob->gl_pathc + pglob->gl_offs;
bcc1e3
+      char **new_gl_pathv;
bcc1e3
+
bcc1e3
+      if (newcount > SIZE_MAX / sizeof (char *) - 2)
bcc1e3
+        {
bcc1e3
+        nospace:
bcc1e3
+          free (pglob->gl_pathv);
bcc1e3
+          pglob->gl_pathv = NULL;
bcc1e3
+          pglob->gl_pathc = 0;
bcc1e3
+          retval = GLOB_NOSPACE;
bcc1e3
+          goto out;
bcc1e3
+        }
bcc1e3
 
bcc1e3
-	if (newcount > SIZE_MAX / sizeof (char *) - 2)
bcc1e3
-	  {
bcc1e3
-	  nospace:
bcc1e3
-	    free (pglob->gl_pathv);
bcc1e3
-	    pglob->gl_pathv = NULL;
bcc1e3
-	    pglob->gl_pathc = 0;
bcc1e3
-	    retval = GLOB_NOSPACE;
bcc1e3
-	    goto out;
bcc1e3
-	  }
bcc1e3
-
bcc1e3
-	new_gl_pathv = realloc (pglob->gl_pathv,
bcc1e3
-				(newcount + 2) * sizeof (char *));
bcc1e3
-	if (new_gl_pathv == NULL)
bcc1e3
-	  goto nospace;
bcc1e3
-	pglob->gl_pathv = new_gl_pathv;
bcc1e3
-
bcc1e3
-	if (flags & GLOB_MARK && is_dir (dirname, flags, pglob))
bcc1e3
-	  {
bcc1e3
-	    char *p;
bcc1e3
-	    pglob->gl_pathv[newcount] = malloc (dirlen + 2);
bcc1e3
-	    if (pglob->gl_pathv[newcount] == NULL)
bcc1e3
-	      goto nospace;
bcc1e3
-	    p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
bcc1e3
-	    p[0] = '/';
bcc1e3
-	    p[1] = '\0';
bcc1e3
-	    if (__glibc_unlikely (malloc_dirname))
bcc1e3
-	      free (dirname);
bcc1e3
-	  }
bcc1e3
-	else
bcc1e3
-	  {
bcc1e3
-	    if (__glibc_unlikely (malloc_dirname))
bcc1e3
-	      pglob->gl_pathv[newcount] = dirname;
bcc1e3
-	    else
bcc1e3
-	      {
bcc1e3
-		pglob->gl_pathv[newcount] = strdup (dirname);
bcc1e3
-		if (pglob->gl_pathv[newcount] == NULL)
bcc1e3
-		  goto nospace;
bcc1e3
-	      }
bcc1e3
-	  }
bcc1e3
-	pglob->gl_pathv[++newcount] = NULL;
bcc1e3
-	++pglob->gl_pathc;
bcc1e3
-	pglob->gl_flags = flags;
bcc1e3
+      new_gl_pathv = realloc (pglob->gl_pathv,
bcc1e3
+                              (newcount + 2) * sizeof (char *));
bcc1e3
+      if (new_gl_pathv == NULL)
bcc1e3
+        goto nospace;
bcc1e3
+      pglob->gl_pathv = new_gl_pathv;
bcc1e3
+
bcc1e3
+      if (flags & GLOB_MARK && is_dir (dirname, flags, pglob))
bcc1e3
+        {
bcc1e3
+          char *p;
bcc1e3
+          pglob->gl_pathv[newcount] = malloc (dirlen + 2);
bcc1e3
+          if (pglob->gl_pathv[newcount] == NULL)
bcc1e3
+            goto nospace;
bcc1e3
+          p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
bcc1e3
+          p[0] = '/';
bcc1e3
+          p[1] = '\0';
bcc1e3
+          if (__glibc_unlikely (malloc_dirname))
bcc1e3
+            free (dirname);
bcc1e3
+        }
bcc1e3
+      else
bcc1e3
+        {
bcc1e3
+          if (__glibc_unlikely (malloc_dirname))
bcc1e3
+            pglob->gl_pathv[newcount] = dirname;
bcc1e3
+          else
bcc1e3
+            {
bcc1e3
+              pglob->gl_pathv[newcount] = strdup (dirname);
bcc1e3
+              if (pglob->gl_pathv[newcount] == NULL)
bcc1e3
+                goto nospace;
bcc1e3
+            }
bcc1e3
+        }
bcc1e3
+      pglob->gl_pathv[++newcount] = NULL;
bcc1e3
+      ++pglob->gl_pathc;
bcc1e3
+      pglob->gl_flags = flags;
bcc1e3
 
bcc1e3
-	return 0;
bcc1e3
+      return 0;
bcc1e3
     }
bcc1e3
 
bcc1e3
   meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE));
bcc1e3
@@ -934,135 +969,135 @@ __glob (const char *pattern, int flags,
bcc1e3
   if (meta & (GLOBPAT_SPECIAL | GLOBPAT_BRACKET))
bcc1e3
     {
bcc1e3
       /* The directory name contains metacharacters, so we
bcc1e3
-	 have to glob for the directory, and then glob for
bcc1e3
-	 the pattern in each directory found.  */
bcc1e3
+         have to glob for the directory, and then glob for
bcc1e3
+         the pattern in each directory found.  */
bcc1e3
       size_t i;
bcc1e3
 
bcc1e3
       if (!(flags & GLOB_NOESCAPE) && dirlen > 0 && dirname[dirlen - 1] == '\\')
bcc1e3
-	{
bcc1e3
-	  /* "foo\\/bar".  Remove the final backslash from dirname
bcc1e3
-	     if it has not been quoted.  */
bcc1e3
-	  char *p = (char *) &dirname[dirlen - 1];
bcc1e3
-
bcc1e3
-	  while (p > dirname && p[-1] == '\\') --p;
bcc1e3
-	  if ((&dirname[dirlen] - p) & 1)
bcc1e3
-	    *(char *) &dirname[--dirlen] = '\0';
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          /* "foo\\/bar".  Remove the final backslash from dirname
bcc1e3
+             if it has not been quoted.  */
bcc1e3
+          char *p = (char *) &dirname[dirlen - 1];
bcc1e3
+
bcc1e3
+          while (p > dirname && p[-1] == '\\') --p;
bcc1e3
+          if ((&dirname[dirlen] - p) & 1)
bcc1e3
+            *(char *) &dirname[--dirlen] = '\0';
bcc1e3
+        }
bcc1e3
 
bcc1e3
       if (__glibc_unlikely ((flags & GLOB_ALTDIRFUNC) != 0))
bcc1e3
-	{
bcc1e3
-	  /* Use the alternative access functions also in the recursive
bcc1e3
-	     call.  */
bcc1e3
-	  dirs.gl_opendir = pglob->gl_opendir;
bcc1e3
-	  dirs.gl_readdir = pglob->gl_readdir;
bcc1e3
-	  dirs.gl_closedir = pglob->gl_closedir;
bcc1e3
-	  dirs.gl_stat = pglob->gl_stat;
bcc1e3
-	  dirs.gl_lstat = pglob->gl_lstat;
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          /* Use the alternative access functions also in the recursive
bcc1e3
+             call.  */
bcc1e3
+          dirs.gl_opendir = pglob->gl_opendir;
bcc1e3
+          dirs.gl_readdir = pglob->gl_readdir;
bcc1e3
+          dirs.gl_closedir = pglob->gl_closedir;
bcc1e3
+          dirs.gl_stat = pglob->gl_stat;
bcc1e3
+          dirs.gl_lstat = pglob->gl_lstat;
bcc1e3
+        }
bcc1e3
 
bcc1e3
       status = __glob (dirname,
bcc1e3
-		       ((flags & (GLOB_ERR | GLOB_NOESCAPE | GLOB_ALTDIRFUNC))
bcc1e3
-			| GLOB_NOSORT | GLOB_ONLYDIR),
bcc1e3
-		       errfunc, &dirs);
bcc1e3
+                       ((flags & (GLOB_ERR | GLOB_NOESCAPE | GLOB_ALTDIRFUNC))
bcc1e3
+                        | GLOB_NOSORT | GLOB_ONLYDIR),
bcc1e3
+                       errfunc, &dirs);
bcc1e3
       if (status != 0)
bcc1e3
-	{
bcc1e3
-	  if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
bcc1e3
-	    {
bcc1e3
-	      retval = status;
bcc1e3
-	      goto out;
bcc1e3
-	    }
bcc1e3
-	  goto no_matches;
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
bcc1e3
+            {
bcc1e3
+              retval = status;
bcc1e3
+              goto out;
bcc1e3
+            }
bcc1e3
+          goto no_matches;
bcc1e3
+        }
bcc1e3
 
bcc1e3
       /* We have successfully globbed the preceding directory name.
bcc1e3
-	 For each name we found, call glob_in_dir on it and FILENAME,
bcc1e3
-	 appending the results to PGLOB.  */
bcc1e3
+         For each name we found, call glob_in_dir on it and FILENAME,
bcc1e3
+         appending the results to PGLOB.  */
bcc1e3
       for (i = 0; i < dirs.gl_pathc; ++i)
bcc1e3
-	{
bcc1e3
-	  size_t old_pathc;
bcc1e3
+        {
bcc1e3
+          size_t old_pathc;
bcc1e3
 
bcc1e3
-	  old_pathc = pglob->gl_pathc;
bcc1e3
-	  status = glob_in_dir (filename, dirs.gl_pathv[i],
bcc1e3
-				((flags | GLOB_APPEND)
bcc1e3
-				 & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
bcc1e3
-				errfunc, pglob, alloca_used);
bcc1e3
-	  if (status == GLOB_NOMATCH)
bcc1e3
-	    /* No matches in this directory.  Try the next.  */
bcc1e3
-	    continue;
bcc1e3
-
bcc1e3
-	  if (status != 0)
bcc1e3
-	    {
bcc1e3
-	      globfree (&dirs);
bcc1e3
-	      globfree (pglob);
bcc1e3
-	      pglob->gl_pathc = 0;
bcc1e3
-	      retval = status;
bcc1e3
-	      goto out;
bcc1e3
-	    }
bcc1e3
-
bcc1e3
-	  /* Stick the directory on the front of each name.  */
bcc1e3
-	  if (prefix_array (dirs.gl_pathv[i],
bcc1e3
-			    &pglob->gl_pathv[old_pathc + pglob->gl_offs],
bcc1e3
-			    pglob->gl_pathc - old_pathc))
bcc1e3
-	    {
bcc1e3
-	      globfree (&dirs);
bcc1e3
-	      globfree (pglob);
bcc1e3
-	      pglob->gl_pathc = 0;
bcc1e3
-	      retval = GLOB_NOSPACE;
bcc1e3
-	      goto out;
bcc1e3
-	    }
bcc1e3
-	}
bcc1e3
+          old_pathc = pglob->gl_pathc;
bcc1e3
+          status = glob_in_dir (filename, dirs.gl_pathv[i],
bcc1e3
+                                ((flags | GLOB_APPEND)
bcc1e3
+                                 & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
bcc1e3
+                                errfunc, pglob, alloca_used);
bcc1e3
+          if (status == GLOB_NOMATCH)
bcc1e3
+            /* No matches in this directory.  Try the next.  */
bcc1e3
+            continue;
bcc1e3
+
bcc1e3
+          if (status != 0)
bcc1e3
+            {
bcc1e3
+              globfree (&dirs);
bcc1e3
+              globfree (pglob);
bcc1e3
+              pglob->gl_pathc = 0;
bcc1e3
+              retval = status;
bcc1e3
+              goto out;
bcc1e3
+            }
bcc1e3
+
bcc1e3
+          /* Stick the directory on the front of each name.  */
bcc1e3
+          if (prefix_array (dirs.gl_pathv[i],
bcc1e3
+                            &pglob->gl_pathv[old_pathc + pglob->gl_offs],
bcc1e3
+                            pglob->gl_pathc - old_pathc))
bcc1e3
+            {
bcc1e3
+              globfree (&dirs);
bcc1e3
+              globfree (pglob);
bcc1e3
+              pglob->gl_pathc = 0;
bcc1e3
+              retval = GLOB_NOSPACE;
bcc1e3
+              goto out;
bcc1e3
+            }
bcc1e3
+        }
bcc1e3
 
bcc1e3
       flags |= GLOB_MAGCHAR;
bcc1e3
 
bcc1e3
       /* We have ignored the GLOB_NOCHECK flag in the 'glob_in_dir' calls.
bcc1e3
-	 But if we have not found any matching entry and the GLOB_NOCHECK
bcc1e3
-	 flag was set we must return the input pattern itself.  */
bcc1e3
+         But if we have not found any matching entry and the GLOB_NOCHECK
bcc1e3
+         flag was set we must return the input pattern itself.  */
bcc1e3
       if (pglob->gl_pathc + pglob->gl_offs == oldcount)
bcc1e3
-	{
bcc1e3
-	no_matches:
bcc1e3
-	  /* No matches.  */
bcc1e3
-	  if (flags & GLOB_NOCHECK)
bcc1e3
-	    {
bcc1e3
-	      size_t newcount = pglob->gl_pathc + pglob->gl_offs;
bcc1e3
-	      char **new_gl_pathv;
bcc1e3
-
bcc1e3
-	      if (newcount > SIZE_MAX / sizeof (char *) - 2)
bcc1e3
-		{
bcc1e3
-		nospace2:
bcc1e3
-		  globfree (&dirs);
bcc1e3
-		  retval = GLOB_NOSPACE;
bcc1e3
-		  goto out;
bcc1e3
-		}
bcc1e3
-
bcc1e3
-	      new_gl_pathv = realloc (pglob->gl_pathv,
bcc1e3
-				      (newcount + 2) * sizeof (char *));
bcc1e3
-	      if (new_gl_pathv == NULL)
bcc1e3
-		goto nospace2;
bcc1e3
-	      pglob->gl_pathv = new_gl_pathv;
bcc1e3
-
bcc1e3
-	      pglob->gl_pathv[newcount] = strdup (pattern);
bcc1e3
-	      if (pglob->gl_pathv[newcount] == NULL)
bcc1e3
-		{
bcc1e3
-		  globfree (&dirs);
bcc1e3
-		  globfree (pglob);
bcc1e3
-		  pglob->gl_pathc = 0;
bcc1e3
-		  retval = GLOB_NOSPACE;
bcc1e3
-		  goto out;
bcc1e3
-		}
bcc1e3
-
bcc1e3
-	      ++pglob->gl_pathc;
bcc1e3
-	      ++newcount;
bcc1e3
-
bcc1e3
-	      pglob->gl_pathv[newcount] = NULL;
bcc1e3
-	      pglob->gl_flags = flags;
bcc1e3
-	    }
bcc1e3
-	  else
bcc1e3
-	    {
bcc1e3
-	      globfree (&dirs);
bcc1e3
-	      retval = GLOB_NOMATCH;
bcc1e3
-	      goto out;
bcc1e3
-	    }
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+        no_matches:
bcc1e3
+          /* No matches.  */
bcc1e3
+          if (flags & GLOB_NOCHECK)
bcc1e3
+            {
bcc1e3
+              size_t newcount = pglob->gl_pathc + pglob->gl_offs;
bcc1e3
+              char **new_gl_pathv;
bcc1e3
+
bcc1e3
+              if (newcount > SIZE_MAX / sizeof (char *) - 2)
bcc1e3
+                {
bcc1e3
+                nospace2:
bcc1e3
+                  globfree (&dirs);
bcc1e3
+                  retval = GLOB_NOSPACE;
bcc1e3
+                  goto out;
bcc1e3
+                }
bcc1e3
+
bcc1e3
+              new_gl_pathv = realloc (pglob->gl_pathv,
bcc1e3
+                                      (newcount + 2) * sizeof (char *));
bcc1e3
+              if (new_gl_pathv == NULL)
bcc1e3
+                goto nospace2;
bcc1e3
+              pglob->gl_pathv = new_gl_pathv;
bcc1e3
+
bcc1e3
+              pglob->gl_pathv[newcount] = strdup (pattern);
bcc1e3
+              if (pglob->gl_pathv[newcount] == NULL)
bcc1e3
+                {
bcc1e3
+                  globfree (&dirs);
bcc1e3
+                  globfree (pglob);
bcc1e3
+                  pglob->gl_pathc = 0;
bcc1e3
+                  retval = GLOB_NOSPACE;
bcc1e3
+                  goto out;
bcc1e3
+                }
bcc1e3
+
bcc1e3
+              ++pglob->gl_pathc;
bcc1e3
+              ++newcount;
bcc1e3
+
bcc1e3
+              pglob->gl_pathv[newcount] = NULL;
bcc1e3
+              pglob->gl_flags = flags;
bcc1e3
+            }
bcc1e3
+          else
bcc1e3
+            {
bcc1e3
+              globfree (&dirs);
bcc1e3
+              retval = GLOB_NOMATCH;
bcc1e3
+              goto out;
bcc1e3
+            }
bcc1e3
+        }
bcc1e3
 
bcc1e3
       globfree (&dirs);
bcc1e3
     }
bcc1e3
@@ -1072,57 +1107,57 @@ __glob (const char *pattern, int flags,
bcc1e3
       int orig_flags = flags;
bcc1e3
 
bcc1e3
       if (meta & GLOBPAT_BACKSLASH)
bcc1e3
-	{
bcc1e3
-	  char *p = strchr (dirname, '\\'), *q;
bcc1e3
-	  /* We need to unescape the dirname string.  It is certainly
bcc1e3
-	     allocated by alloca, as otherwise filename would be NULL
bcc1e3
-	     or dirname wouldn't contain backslashes.  */
bcc1e3
-	  q = p;
bcc1e3
-	  do
bcc1e3
-	    {
bcc1e3
-	      if (*p == '\\')
bcc1e3
-		{
bcc1e3
-		  *q = *++p;
bcc1e3
-		  --dirlen;
bcc1e3
-		}
bcc1e3
-	      else
bcc1e3
-		*q = *p;
bcc1e3
-	      ++q;
bcc1e3
-	    }
bcc1e3
-	  while (*p++ != '\0');
bcc1e3
-	  dirname_modified = 1;
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          char *p = strchr (dirname, '\\'), *q;
bcc1e3
+          /* We need to unescape the dirname string.  It is certainly
bcc1e3
+             allocated by alloca, as otherwise filename would be NULL
bcc1e3
+             or dirname wouldn't contain backslashes.  */
bcc1e3
+          q = p;
bcc1e3
+          do
bcc1e3
+            {
bcc1e3
+              if (*p == '\\')
bcc1e3
+                {
bcc1e3
+                  *q = *++p;
bcc1e3
+                  --dirlen;
bcc1e3
+                }
bcc1e3
+              else
bcc1e3
+                *q = *p;
bcc1e3
+              ++q;
bcc1e3
+            }
bcc1e3
+          while (*p++ != '\0');
bcc1e3
+          dirname_modified = 1;
bcc1e3
+        }
bcc1e3
       if (dirname_modified)
bcc1e3
-	flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
bcc1e3
+        flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
bcc1e3
       status = glob_in_dir (filename, dirname, flags, errfunc, pglob,
bcc1e3
-			    alloca_used);
bcc1e3
+                            alloca_used);
bcc1e3
       if (status != 0)
bcc1e3
-	{
bcc1e3
-	  if (status == GLOB_NOMATCH && flags != orig_flags
bcc1e3
-	      && pglob->gl_pathc + pglob->gl_offs == oldcount)
bcc1e3
-	    {
bcc1e3
-	      /* Make sure globfree (&dirs); is a nop.  */
bcc1e3
-	      dirs.gl_pathv = NULL;
bcc1e3
-	      flags = orig_flags;
bcc1e3
-	      goto no_matches;
bcc1e3
-	    }
bcc1e3
-	  retval = status;
bcc1e3
-	  goto out;
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          if (status == GLOB_NOMATCH && flags != orig_flags
bcc1e3
+              && pglob->gl_pathc + pglob->gl_offs == oldcount)
bcc1e3
+            {
bcc1e3
+              /* Make sure globfree (&dirs); is a nop.  */
bcc1e3
+              dirs.gl_pathv = NULL;
bcc1e3
+              flags = orig_flags;
bcc1e3
+              goto no_matches;
bcc1e3
+            }
bcc1e3
+          retval = status;
bcc1e3
+          goto out;
bcc1e3
+        }
bcc1e3
 
bcc1e3
       if (dirlen > 0)
bcc1e3
-	{
bcc1e3
-	  /* Stick the directory on the front of each name.  */
bcc1e3
-	  if (prefix_array (dirname,
bcc1e3
-			    &pglob->gl_pathv[old_pathc + pglob->gl_offs],
bcc1e3
-			    pglob->gl_pathc - old_pathc))
bcc1e3
-	    {
bcc1e3
-	      globfree (pglob);
bcc1e3
-	      pglob->gl_pathc = 0;
bcc1e3
-	      retval = GLOB_NOSPACE;
bcc1e3
-	      goto out;
bcc1e3
-	    }
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          /* Stick the directory on the front of each name.  */
bcc1e3
+          if (prefix_array (dirname,
bcc1e3
+                            &pglob->gl_pathv[old_pathc + pglob->gl_offs],
bcc1e3
+                            pglob->gl_pathc - old_pathc))
bcc1e3
+            {
bcc1e3
+              globfree (pglob);
bcc1e3
+              pglob->gl_pathc = 0;
bcc1e3
+              retval = GLOB_NOSPACE;
bcc1e3
+              goto out;
bcc1e3
+            }
bcc1e3
+        }
bcc1e3
     }
bcc1e3
 
bcc1e3
   if (flags & GLOB_MARK)
bcc1e3
@@ -1131,28 +1166,28 @@ __glob (const char *pattern, int flags,
bcc1e3
       size_t i;
bcc1e3
 
bcc1e3
       for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i)
bcc1e3
-	if (is_dir (pglob->gl_pathv[i], flags, pglob))
bcc1e3
-	  {
bcc1e3
-	    size_t len = strlen (pglob->gl_pathv[i]) + 2;
bcc1e3
-	    char *new = realloc (pglob->gl_pathv[i], len);
bcc1e3
-	    if (new == NULL)
bcc1e3
-	      {
bcc1e3
-		globfree (pglob);
bcc1e3
-		pglob->gl_pathc = 0;
bcc1e3
-		retval = GLOB_NOSPACE;
bcc1e3
-		goto out;
bcc1e3
-	      }
bcc1e3
-	    strcpy (&new[len - 2], "/");
bcc1e3
-	    pglob->gl_pathv[i] = new;
bcc1e3
-	  }
bcc1e3
+        if (is_dir (pglob->gl_pathv[i], flags, pglob))
bcc1e3
+          {
bcc1e3
+            size_t len = strlen (pglob->gl_pathv[i]) + 2;
bcc1e3
+            char *new = realloc (pglob->gl_pathv[i], len);
bcc1e3
+            if (new == NULL)
bcc1e3
+              {
bcc1e3
+                globfree (pglob);
bcc1e3
+                pglob->gl_pathc = 0;
bcc1e3
+                retval = GLOB_NOSPACE;
bcc1e3
+                goto out;
bcc1e3
+              }
bcc1e3
+            strcpy (&new[len - 2], "/");
bcc1e3
+            pglob->gl_pathv[i] = new;
bcc1e3
+          }
bcc1e3
     }
bcc1e3
 
bcc1e3
   if (!(flags & GLOB_NOSORT))
bcc1e3
     {
bcc1e3
       /* Sort the vector.  */
bcc1e3
       qsort (&pglob->gl_pathv[oldcount],
bcc1e3
-	     pglob->gl_pathc + pglob->gl_offs - oldcount,
bcc1e3
-	     sizeof (char *), collated_compare);
bcc1e3
+             pglob->gl_pathc + pglob->gl_offs - oldcount,
bcc1e3
+             sizeof (char *), collated_compare);
bcc1e3
     }
bcc1e3
 
bcc1e3
  out:
bcc1e3
@@ -1204,14 +1239,14 @@ prefix_array (const char *dirname, char
bcc1e3
   if (dirlen > 1)
bcc1e3
     {
bcc1e3
       if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
bcc1e3
-	/* DIRNAME is "d:/".  Don't prepend the slash from DIRNAME.  */
bcc1e3
-	--dirlen;
bcc1e3
+        /* DIRNAME is "d:/".  Don't prepend the slash from DIRNAME.  */
bcc1e3
+        --dirlen;
bcc1e3
       else if (dirname[dirlen - 1] == ':')
bcc1e3
-	{
bcc1e3
-	  /* DIRNAME is "d:".  Use ':' instead of '/'.  */
bcc1e3
-	  --dirlen;
bcc1e3
-	  dirsep_char = ':';
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          /* DIRNAME is "d:".  Use ':' instead of '/'.  */
bcc1e3
+          --dirlen;
bcc1e3
+          dirsep_char = ':';
bcc1e3
+        }
bcc1e3
     }
bcc1e3
 #endif
bcc1e3
 
bcc1e3
@@ -1220,16 +1255,16 @@ prefix_array (const char *dirname, char
bcc1e3
       size_t eltlen = strlen (array[i]) + 1;
bcc1e3
       char *new = malloc (dirlen + 1 + eltlen);
bcc1e3
       if (new == NULL)
bcc1e3
-	{
bcc1e3
-	  while (i > 0)
bcc1e3
-	    free (array[--i]);
bcc1e3
-	  return 1;
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          while (i > 0)
bcc1e3
+            free (array[--i]);
bcc1e3
+          return 1;
bcc1e3
+        }
bcc1e3
 
bcc1e3
       {
bcc1e3
-	char *endp = mempcpy (new, dirname, dirlen);
bcc1e3
-	*endp++ = dirsep_char;
bcc1e3
-	mempcpy (endp, array[i], eltlen);
bcc1e3
+        char *endp = mempcpy (new, dirname, dirlen);
bcc1e3
+        *endp++ = dirsep_char;
bcc1e3
+        mempcpy (endp, array[i], eltlen);
bcc1e3
       }
bcc1e3
       free (array[i]);
bcc1e3
       array[i] = new;
bcc1e3
@@ -1244,11 +1279,13 @@ prefix_array (const char *dirname, char
bcc1e3
    The GLOB_APPEND flag is assumed to be set (always appends).  */
bcc1e3
 static int
bcc1e3
 glob_in_dir (const char *pattern, const char *directory, int flags,
bcc1e3
-	     int (*errfunc) (const char *, int),
bcc1e3
-	     glob_t *pglob, size_t alloca_used)
bcc1e3
+             int (*errfunc) (const char *, int),
bcc1e3
+             glob_t *pglob, size_t alloca_used)
bcc1e3
 {
bcc1e3
   size_t dirlen = strlen (directory);
bcc1e3
   void *stream = NULL;
bcc1e3
+  struct scratch_buffer s;
bcc1e3
+  scratch_buffer_init (&s);
bcc1e3
 # define GLOBNAMES_MEMBERS(nnames) \
bcc1e3
     struct globnames *next; size_t count; char *name[nnames];
bcc1e3
   struct globnames { GLOBNAMES_MEMBERS (FLEXIBLE_ARRAY_MEMBER) };
bcc1e3
@@ -1273,8 +1310,8 @@ glob_in_dir (const char *pattern, const
bcc1e3
   if (meta == GLOBPAT_NONE && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
bcc1e3
     {
bcc1e3
       /* We need not do any tests.  The PATTERN contains no meta
bcc1e3
-	 characters and we must not return an error therefore the
bcc1e3
-	 result will always contain exactly one name.  */
bcc1e3
+         characters and we must not return an error therefore the
bcc1e3
+         result will always contain exactly one name.  */
bcc1e3
       flags |= GLOB_NOCHECK;
bcc1e3
     }
bcc1e3
   else if (meta == GLOBPAT_NONE)
bcc1e3
@@ -1288,102 +1325,127 @@ glob_in_dir (const char *pattern, const
bcc1e3
       if (alloca_fullname)
bcc1e3
         fullname = alloca_account (fullsize, alloca_used);
bcc1e3
       else
bcc1e3
-	{
bcc1e3
-	  fullname = malloc (fullsize);
bcc1e3
-	  if (fullname == NULL)
bcc1e3
-	    return GLOB_NOSPACE;
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          fullname = malloc (fullsize);
bcc1e3
+          if (fullname == NULL)
bcc1e3
+            return GLOB_NOSPACE;
bcc1e3
+        }
bcc1e3
 
bcc1e3
       mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
bcc1e3
-			"/", 1),
bcc1e3
-	       pattern, patlen + 1);
bcc1e3
+                        "/", 1),
bcc1e3
+               pattern, patlen + 1);
bcc1e3
       if (glob_lstat (pglob, flags, fullname) == 0
bcc1e3
-	  || errno == EOVERFLOW)
bcc1e3
-	/* We found this file to be existing.  Now tell the rest
bcc1e3
-	   of the function to copy this name into the result.  */
bcc1e3
-	flags |= GLOB_NOCHECK;
bcc1e3
+          || errno == EOVERFLOW)
bcc1e3
+        /* We found this file to be existing.  Now tell the rest
bcc1e3
+           of the function to copy this name into the result.  */
bcc1e3
+        flags |= GLOB_NOCHECK;
bcc1e3
 
bcc1e3
       if (__glibc_unlikely (!alloca_fullname))
bcc1e3
-	free (fullname);
bcc1e3
+        free (fullname);
bcc1e3
     }
bcc1e3
   else
bcc1e3
     {
bcc1e3
       stream = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
bcc1e3
-		? (*pglob->gl_opendir) (directory)
bcc1e3
-		: opendir (directory));
bcc1e3
+                ? (*pglob->gl_opendir) (directory)
bcc1e3
+                : opendir (directory));
bcc1e3
       if (stream == NULL)
bcc1e3
-	{
bcc1e3
-	  if (errno != ENOTDIR
bcc1e3
-	      && ((errfunc != NULL && (*errfunc) (directory, errno))
bcc1e3
-		  || (flags & GLOB_ERR)))
bcc1e3
-	    return GLOB_ABORTED;
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+          if (errno != ENOTDIR
bcc1e3
+              && ((errfunc != NULL && (*errfunc) (directory, errno))
bcc1e3
+                  || (flags & GLOB_ERR)))
bcc1e3
+            return GLOB_ABORTED;
bcc1e3
+        }
bcc1e3
       else
bcc1e3
-	{
bcc1e3
-	  int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
bcc1e3
-			   | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
bcc1e3
-	  flags |= GLOB_MAGCHAR;
bcc1e3
-
bcc1e3
-	  while (1)
bcc1e3
-	    {
bcc1e3
-	      struct readdir_result d;
bcc1e3
-	      {
bcc1e3
-		if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
bcc1e3
-		  d = convert_dirent (GL_READDIR (pglob, stream));
bcc1e3
-		else
bcc1e3
-		  {
bcc1e3
+        {
bcc1e3
+          int dfd = dirfd (stream);
bcc1e3
+          int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
bcc1e3
+                           | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
bcc1e3
+          flags |= GLOB_MAGCHAR;
bcc1e3
+
bcc1e3
+          while (1)
bcc1e3
+            {
bcc1e3
+              struct readdir_result d;
bcc1e3
+              {
bcc1e3
+                if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
bcc1e3
+                  d = convert_dirent (GL_READDIR (pglob, stream));
bcc1e3
+                else
bcc1e3
+                  {
bcc1e3
 #ifdef COMPILE_GLOB64
bcc1e3
-		    d = convert_dirent (__readdir (stream));
bcc1e3
+                    d = convert_dirent (__readdir (stream));
bcc1e3
 #else
bcc1e3
-		    d = convert_dirent64 (__readdir64 (stream));
bcc1e3
+                    d = convert_dirent64 (__readdir64 (stream));
bcc1e3
 #endif
bcc1e3
-		  }
bcc1e3
-	      }
bcc1e3
-	      if (d.name == NULL)
bcc1e3
-		break;
bcc1e3
-
bcc1e3
-	      /* If we shall match only directories use the information
bcc1e3
-		 provided by the dirent call if possible.  */
bcc1e3
-	      if (flags & GLOB_ONLYDIR)
bcc1e3
-		switch (readdir_result_type (d))
bcc1e3
-		  {
bcc1e3
-		  case DT_DIR: case DT_LNK: case DT_UNKNOWN: break;
bcc1e3
-		  default: continue;
bcc1e3
-		  }
bcc1e3
-
bcc1e3
-	      if (fnmatch (pattern, d.name, fnm_flags) == 0)
bcc1e3
-		{
bcc1e3
-		  if (cur == names->count)
bcc1e3
-		    {
bcc1e3
-		      struct globnames *newnames;
bcc1e3
-		      size_t count = names->count * 2;
bcc1e3
-		      size_t nameoff = offsetof (struct globnames, name);
bcc1e3
-		      size_t size = FLEXSIZEOF (struct globnames, name,
bcc1e3
-						count * sizeof (char *));
bcc1e3
-		      if ((SIZE_MAX - nameoff) / 2 / sizeof (char *)
bcc1e3
-			  < names->count)
bcc1e3
-			goto memory_error;
bcc1e3
-		      if (glob_use_alloca (alloca_used, size))
bcc1e3
-			newnames = names_alloca
bcc1e3
-			  = alloca_account (size, alloca_used);
bcc1e3
-		      else if ((newnames = malloc (size))
bcc1e3
-			       == NULL)
bcc1e3
-			goto memory_error;
bcc1e3
-		      newnames->count = count;
bcc1e3
-		      newnames->next = names;
bcc1e3
-		      names = newnames;
bcc1e3
-		      cur = 0;
bcc1e3
-		    }
bcc1e3
-		  names->name[cur] = strdup (d.name);
bcc1e3
-		  if (names->name[cur] == NULL)
bcc1e3
-		    goto memory_error;
bcc1e3
-		  ++cur;
bcc1e3
-		  ++nfound;
bcc1e3
-		  if (SIZE_MAX - pglob->gl_offs <= nfound)
bcc1e3
-		    goto memory_error;
bcc1e3
-		}
bcc1e3
-	    }
bcc1e3
-	}
bcc1e3
+                  }
bcc1e3
+              }
bcc1e3
+              if (d.name == NULL)
bcc1e3
+                break;
bcc1e3
+
bcc1e3
+              /* If we shall match only directories use the information
bcc1e3
+                 provided by the dirent call if possible.  */
bcc1e3
+              if (flags & GLOB_ONLYDIR)
bcc1e3
+                switch (readdir_result_type (d))
bcc1e3
+                  {
bcc1e3
+                  default: continue;
bcc1e3
+                  case DT_DIR: break;
bcc1e3
+                  case DT_LNK: case DT_UNKNOWN:
bcc1e3
+                    /* The filesystem was too lazy to give us a hint,
bcc1e3
+                       so we have to do it the hard way.  */
bcc1e3
+                    if (__glibc_unlikely (dfd < 0 || flags & GLOB_ALTDIRFUNC))
bcc1e3
+                      {
bcc1e3
+                        size_t namelen = strlen (d.name);
bcc1e3
+                        size_t need = dirlen + 1 + namelen + 1;
bcc1e3
+                        if (s.length < need
bcc1e3
+                            && !scratch_buffer_set_array_size (&s, need, 1))
bcc1e3
+                          goto memory_error;
bcc1e3
+                        char *p = mempcpy (s.data, directory, dirlen);
bcc1e3
+                        *p = '/';
bcc1e3
+                        p += p[-1] != '/';
bcc1e3
+                        memcpy (p, d.name, namelen + 1);
bcc1e3
+                        if (! is_dir (s.data, flags, pglob))
bcc1e3
+                          continue;
bcc1e3
+                      }
bcc1e3
+                    else
bcc1e3
+                      {
bcc1e3
+                        struct_stat64 st64;
bcc1e3
+                        if (! (GLOB_FSTATAT64 (dfd, d.name, &st64, 0) == 0
bcc1e3
+                               && S_ISDIR (st64.st_mode)))
bcc1e3
+                          continue;
bcc1e3
+                      }
bcc1e3
+                  }
bcc1e3
+
bcc1e3
+              if (fnmatch (pattern, d.name, fnm_flags) == 0)
bcc1e3
+                {
bcc1e3
+                  if (cur == names->count)
bcc1e3
+                    {
bcc1e3
+                      struct globnames *newnames;
bcc1e3
+                      size_t count = names->count * 2;
bcc1e3
+                      size_t nameoff = offsetof (struct globnames, name);
bcc1e3
+                      size_t size = FLEXSIZEOF (struct globnames, name,
bcc1e3
+                                                count * sizeof (char *));
bcc1e3
+                      if ((SIZE_MAX - nameoff) / 2 / sizeof (char *)
bcc1e3
+                          < names->count)
bcc1e3
+                        goto memory_error;
bcc1e3
+                      if (glob_use_alloca (alloca_used, size))
bcc1e3
+                        newnames = names_alloca
bcc1e3
+                          = alloca_account (size, alloca_used);
bcc1e3
+                      else if ((newnames = malloc (size))
bcc1e3
+                               == NULL)
bcc1e3
+                        goto memory_error;
bcc1e3
+                      newnames->count = count;
bcc1e3
+                      newnames->next = names;
bcc1e3
+                      names = newnames;
bcc1e3
+                      cur = 0;
bcc1e3
+                    }
bcc1e3
+                  names->name[cur] = strdup (d.name);
bcc1e3
+                  if (names->name[cur] == NULL)
bcc1e3
+                    goto memory_error;
bcc1e3
+                  ++cur;
bcc1e3
+                  ++nfound;
bcc1e3
+                  if (SIZE_MAX - pglob->gl_offs <= nfound)
bcc1e3
+                    goto memory_error;
bcc1e3
+                }
bcc1e3
+            }
bcc1e3
+        }
bcc1e3
     }
bcc1e3
 
bcc1e3
   if (nfound == 0 && (flags & GLOB_NOCHECK))
bcc1e3
@@ -1392,7 +1454,7 @@ glob_in_dir (const char *pattern, const
bcc1e3
       nfound = 1;
bcc1e3
       names->name[cur] = malloc (len + 1);
bcc1e3
       if (names->name[cur] == NULL)
bcc1e3
-	goto memory_error;
bcc1e3
+        goto memory_error;
bcc1e3
       *((char *) mempcpy (names->name[cur++], pattern, len)) = '\0';
bcc1e3
     }
bcc1e3
 
bcc1e3
@@ -1403,82 +1465,83 @@ glob_in_dir (const char *pattern, const
bcc1e3
       result = 0;
bcc1e3
 
bcc1e3
       if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc
bcc1e3
-	  < pglob->gl_offs + nfound + 1)
bcc1e3
-	goto memory_error;
bcc1e3
+          < pglob->gl_offs + nfound + 1)
bcc1e3
+        goto memory_error;
bcc1e3
 
bcc1e3
       new_gl_pathv
bcc1e3
-	= realloc (pglob->gl_pathv,
bcc1e3
-		   (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
bcc1e3
-		    * sizeof (char *));
bcc1e3
+        = realloc (pglob->gl_pathv,
bcc1e3
+                   (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
bcc1e3
+                    * sizeof (char *));
bcc1e3
 
bcc1e3
       if (new_gl_pathv == NULL)
bcc1e3
-	{
bcc1e3
-	memory_error:
bcc1e3
-	  while (1)
bcc1e3
-	    {
bcc1e3
-	      struct globnames *old = names;
bcc1e3
-	      for (size_t i = 0; i < cur; ++i)
bcc1e3
-		free (names->name[i]);
bcc1e3
-	      names = names->next;
bcc1e3
-	      /* NB: we will not leak memory here if we exit without
bcc1e3
-		 freeing the current block assigned to OLD.  At least
bcc1e3
-		 the very first block is always allocated on the stack
bcc1e3
-		 and this is the block assigned to OLD here.  */
bcc1e3
-	      if (names == NULL)
bcc1e3
-		{
bcc1e3
-		  assert (old == init_names);
bcc1e3
-		  break;
bcc1e3
-		}
bcc1e3
-	      cur = names->count;
bcc1e3
-	      if (old == names_alloca)
bcc1e3
-		names_alloca = names;
bcc1e3
-	      else
bcc1e3
-		free (old);
bcc1e3
-	    }
bcc1e3
-	  result = GLOB_NOSPACE;
bcc1e3
-	}
bcc1e3
+        {
bcc1e3
+        memory_error:
bcc1e3
+          while (1)
bcc1e3
+            {
bcc1e3
+              struct globnames *old = names;
bcc1e3
+              for (size_t i = 0; i < cur; ++i)
bcc1e3
+                free (names->name[i]);
bcc1e3
+              names = names->next;
bcc1e3
+              /* NB: we will not leak memory here if we exit without
bcc1e3
+                 freeing the current block assigned to OLD.  At least
bcc1e3
+                 the very first block is always allocated on the stack
bcc1e3
+                 and this is the block assigned to OLD here.  */
bcc1e3
+              if (names == NULL)
bcc1e3
+                {
bcc1e3
+                  assert (old == init_names);
bcc1e3
+                  break;
bcc1e3
+                }
bcc1e3
+              cur = names->count;
bcc1e3
+              if (old == names_alloca)
bcc1e3
+                names_alloca = names;
bcc1e3
+              else
bcc1e3
+                free (old);
bcc1e3
+            }
bcc1e3
+          result = GLOB_NOSPACE;
bcc1e3
+        }
bcc1e3
       else
bcc1e3
-	{
bcc1e3
-	  while (1)
bcc1e3
-	    {
bcc1e3
-	      struct globnames *old = names;
bcc1e3
-	      for (size_t i = 0; i < cur; ++i)
bcc1e3
-		new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++]
bcc1e3
-		  = names->name[i];
bcc1e3
-	      names = names->next;
bcc1e3
-	      /* NB: we will not leak memory here if we exit without
bcc1e3
-		 freeing the current block assigned to OLD.  At least
bcc1e3
-		 the very first block is always allocated on the stack
bcc1e3
-		 and this is the block assigned to OLD here.  */
bcc1e3
-	      if (names == NULL)
bcc1e3
-		{
bcc1e3
-		  assert (old == init_names);
bcc1e3
-		  break;
bcc1e3
-		}
bcc1e3
-	      cur = names->count;
bcc1e3
-	      if (old == names_alloca)
bcc1e3
-		names_alloca = names;
bcc1e3
-	      else
bcc1e3
-		free (old);
bcc1e3
-	    }
bcc1e3
+        {
bcc1e3
+          while (1)
bcc1e3
+            {
bcc1e3
+              struct globnames *old = names;
bcc1e3
+              for (size_t i = 0; i < cur; ++i)
bcc1e3
+                new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++]
bcc1e3
+                  = names->name[i];
bcc1e3
+              names = names->next;
bcc1e3
+              /* NB: we will not leak memory here if we exit without
bcc1e3
+                 freeing the current block assigned to OLD.  At least
bcc1e3
+                 the very first block is always allocated on the stack
bcc1e3
+                 and this is the block assigned to OLD here.  */
bcc1e3
+              if (names == NULL)
bcc1e3
+                {
bcc1e3
+                  assert (old == init_names);
bcc1e3
+                  break;
bcc1e3
+                }
bcc1e3
+              cur = names->count;
bcc1e3
+              if (old == names_alloca)
bcc1e3
+                names_alloca = names;
bcc1e3
+              else
bcc1e3
+                free (old);
bcc1e3
+            }
bcc1e3
 
bcc1e3
-	  pglob->gl_pathv = new_gl_pathv;
bcc1e3
+          pglob->gl_pathv = new_gl_pathv;
bcc1e3
 
bcc1e3
-	  pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
bcc1e3
+          pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
bcc1e3
 
bcc1e3
-	  pglob->gl_flags = flags;
bcc1e3
-	}
bcc1e3
+          pglob->gl_flags = flags;
bcc1e3
+        }
bcc1e3
     }
bcc1e3
 
bcc1e3
   if (stream != NULL)
bcc1e3
     {
bcc1e3
       save = errno;
bcc1e3
       if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
bcc1e3
-	(*pglob->gl_closedir) (stream);
bcc1e3
+        (*pglob->gl_closedir) (stream);
bcc1e3
       else
bcc1e3
-	closedir (stream);
bcc1e3
+        closedir (stream);
bcc1e3
       __set_errno (save);
bcc1e3
     }
bcc1e3
 
bcc1e3
+  scratch_buffer_free (&s);
bcc1e3
   return result;
bcc1e3
 }
bcc1e3
diff -rup a/sysdeps/gnu/glob-lstat-compat.c b/sysdeps/gnu/glob-lstat-compat.c
bcc1e3
--- a/sysdeps/gnu/glob-lstat-compat.c	2018-08-01 01:10:47.000000000 -0400
bcc1e3
+++ b/sysdeps/gnu/glob-lstat-compat.c	2022-05-02 17:51:04.167557574 -0400
bcc1e3
@@ -29,7 +29,8 @@
bcc1e3
 #define GLOB_ATTRIBUTE attribute_compat_text_section
bcc1e3
 
bcc1e3
 /* Avoid calling gl_lstat with GLOB_ALTDIRFUNC.  */
bcc1e3
-#define GLOB_NO_LSTAT
bcc1e3
+#define GLOB_LSTAT   gl_stat
bcc1e3
+#define GLOB_LSTAT64 __stat64
bcc1e3
 
bcc1e3
 #include <posix/glob.c>
bcc1e3
 
bcc1e3
diff -rup a/sysdeps/unix/sysv/linux/glob-lstat-compat.c b/sysdeps/unix/sysv/linux/glob-lstat-compat.c
bcc1e3
--- a/sysdeps/unix/sysv/linux/glob-lstat-compat.c	2018-08-01 01:10:47.000000000 -0400
bcc1e3
+++ b/sysdeps/unix/sysv/linux/glob-lstat-compat.c	2022-05-02 23:05:45.197297341 -0400
bcc1e3
@@ -30,7 +30,12 @@
bcc1e3
 #define GLOB_ATTRIBUTE attribute_compat_text_section
bcc1e3
 
bcc1e3
 /* Avoid calling gl_lstat with GLOB_ALTDIRFUNC.  */
bcc1e3
-#define GLOB_NO_LSTAT
bcc1e3
+# define COMPILE_GLOB64	1
bcc1e3
+# define struct_stat    struct stat
bcc1e3
+# define struct_stat64  struct stat64
bcc1e3
+# define GLOB_LSTAT     gl_stat
bcc1e3
+# define GLOB_STAT64    __stat64
bcc1e3
+# define GLOB_LSTAT64   __stat64
bcc1e3
 
bcc1e3
 #include <posix/glob.c>
bcc1e3