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