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