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