mbox series

[0/3] posix: glob fixes and refactor (1st part)

Message ID 1503426064-2827-1-git-send-email-adhemerval.zanella@linaro.org
Headers show
Series posix: glob fixes and refactor (1st part) | expand

Message

Adhemerval Zanella Netto Aug. 22, 2017, 6:21 p.m. UTC
This is a subset from my previous patch for glob refactor [1] with the
fixes that do not intend to change glob internal semantics or fix any
issue.  They are focus instead on sync with gnulib (with some code
exceptions) and consolidate the implementation to simplify it.

From previous comments I also added a de-couple one for remove non
unix code from glob.c implementation (since the idea is to gnulib
to add simpler wrappers if required).

[1] https://sourceware.org/ml/libc-alpha/2017-08/msg00440.html

Adhemerval Zanella (3):
  posix: Sync glob with gnulib [BZ #1062]
  posix: De-couple code from gnulib
  posix: Consolidate glob implementation

 posix/Makefile                                     |   2 +-
 posix/glob.c                                       | 659 +++++++++------------
 posix/glob_internal.h                              |  57 ++
 posix/glob_pattern_p.c                             |  29 +
 posix/globfree.c                                   |  37 ++
 posix/globfree64.c                                 |  27 +
 posix/globtest.c                                   |   3 +
 sysdeps/gnu/glob64.c                               |  25 -
 sysdeps/unix/sysv/linux/Makefile                   |   2 +-
 sysdeps/unix/sysv/linux/alpha/Makefile             |   4 -
 sysdeps/unix/sysv/linux/alpha/{glob.c => glob64.c} |  11 -
 sysdeps/unix/sysv/linux/alpha/globfree.c           |  36 ++
 sysdeps/unix/sysv/linux/arm/glob64.c               |   1 -
 sysdeps/unix/sysv/linux/glob.c                     |  23 +
 sysdeps/unix/sysv/linux/glob64.c                   |  55 ++
 sysdeps/unix/sysv/linux/globfree.c                 |  23 +
 sysdeps/unix/sysv/linux/globfree64.c               |   0
 sysdeps/unix/sysv/linux/i386/alphasort64.c         |   2 +-
 sysdeps/unix/sysv/linux/i386/getdents64.c          |   2 +-
 sysdeps/unix/sysv/linux/i386/readdir64.c           |   2 +-
 sysdeps/unix/sysv/linux/i386/readdir64_r.c         |   2 +-
 sysdeps/unix/sysv/linux/i386/versionsort64.c       |   2 +-
 sysdeps/unix/sysv/linux/m68k/glob64.c              |   1 -
 sysdeps/unix/sysv/linux/mips/mips64/n64/glob64.c   |   1 -
 sysdeps/unix/sysv/linux/{i386 => }/olddirent.h     |   0
 .../unix/sysv/linux/{i386/glob64.c => oldglob.c}   |  51 +-
 sysdeps/unix/sysv/linux/powerpc/powerpc32/glob64.c |   1 -
 sysdeps/unix/sysv/linux/s390/s390-32/glob64.c      |  20 +
 sysdeps/unix/sysv/linux/s390/s390-32/oldglob.c     |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c     |   1 -
 sysdeps/unix/sysv/linux/wordsize-64/glob64.c       |   2 -
 sysdeps/unix/sysv/linux/x86_64/x32/glob.c          |   1 -
 sysdeps/wordsize-64/glob.c                         |   8 -
 sysdeps/wordsize-64/glob64.c                       |   1 -
 34 files changed, 607 insertions(+), 486 deletions(-)
 create mode 100644 posix/glob_internal.h
 create mode 100644 posix/glob_pattern_p.c
 create mode 100644 posix/globfree.c
 create mode 100644 posix/globfree64.c
 delete mode 100644 sysdeps/gnu/glob64.c
 rename sysdeps/unix/sysv/linux/alpha/{glob.c => glob64.c} (78%)
 create mode 100644 sysdeps/unix/sysv/linux/alpha/globfree.c
 delete mode 100644 sysdeps/unix/sysv/linux/arm/glob64.c
 create mode 100644 sysdeps/unix/sysv/linux/glob.c
 create mode 100644 sysdeps/unix/sysv/linux/glob64.c
 create mode 100644 sysdeps/unix/sysv/linux/globfree.c
 create mode 100644 sysdeps/unix/sysv/linux/globfree64.c
 delete mode 100644 sysdeps/unix/sysv/linux/m68k/glob64.c
 delete mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/glob64.c
 rename sysdeps/unix/sysv/linux/{i386 => }/olddirent.h (100%)
 rename sysdeps/unix/sysv/linux/{i386/glob64.c => oldglob.c} (63%)
 delete mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/glob64.c
 create mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/glob64.c
 create mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/oldglob.c
 delete mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c
 delete mode 100644 sysdeps/unix/sysv/linux/wordsize-64/glob64.c
 delete mode 100644 sysdeps/unix/sysv/linux/x86_64/x32/glob.c
 delete mode 100644 sysdeps/wordsize-64/glob.c
 delete mode 100644 sysdeps/wordsize-64/glob64.c

-- 
2.7.4

Comments

Paul Eggert Aug. 23, 2017, 10 p.m. UTC | #1
Thanks for starting the ball rolling on this. I merged your changes into 
Gnulib and merged the result back into your proposed patchset, resulting 
in the attached followup patch which should make glibc and Gnulib 
identical in the respective files. Please take a look at it and revise 
the proposal accordingly. Most of the changes in this followup patch 
should be clear from its commit message. Some general comments:

* The attached followup patch fixes what appears to be a glitch in your 
merge, which omitted part of glibc commit 
44c637ce806cc41534e89117a93c41fd310e7e3f
dated Thu Oct 20 10:04:41 2016 +0200. Please double-check this.

* For .c files shared with Gnulib, include <config.h> first in every .c 
file, when _LIBC is not defined.

* Avoid changing C99-style decl-after-statement to C89-style 
decl-then-statement.  Gnulib no longer requires this part of C89, and 
leaving the code alone shortens the patch and keeps the code more readable.

* Fix some stray occurrences of grave accent that should be apostrophe.

* White space should use spaces instead of tabs, and should follow GNU 
conventions for indenting.  This is the convention in Gnulib, and as it 
is allowed by glibc it will simplify integration if we use it in files 
shared with Gnulib.

* Avoid some white-space changes from what is in glibc now.
From 6523d315c2bb0a5aa71fcbfb0939e2106951b2f1 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 23 Aug 2017 14:39:46 -0700
Subject: [PATCH] Merge fixes and porting changes from Gnulib
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* posix/flexmember.h: New file, copied from Gnulib.
* posix/glob.c, posix/glob_pattern_p.c, posix/globfree.c:
Include config.h first, if !_LIBC.
* posix/glob.c (POSIX): Remove; no longer needed.
(WINDOWS32): New macro.  Include pwd.h only if not defined.
(FLEXIBLE_ARRAY_MEMBER) [_LIBC]: New macro, defined to nothing.
Include <flexmember.h>.
(size_add_wrapv, glob_use_alloca): Remove unnecessary static decls.
(size_add_wrapv) [__ICC]: Do not use __builtin_add_overflow.
(glob): Properly initialize glob structure with
GLOB_BRACE|GLOB_DOOFFS (bug 20707).
(glob, prefix_array) [__MSDOS__ || WINDOWS32]: Support Microsoft
file name rules.
(DIRSEP_CHAR): Remove macro, replacing it with a local var.
(link_stat) [HAVE_FSTATAT]: Omit flags arg.
(link_stat): Omit unnecessary cast.
(link_stat) [!_LIBC]: Omit unnecessary local.
(glob_in_dir): Do not rely on undefined behavior in accessing
struct members beyond their bounds.  Use a flexible array member
instead.  Fixes the problem problem reported by Tim Rühsen in:
http://lists.gnu.org/archive/html/bug-gnulib/2017-08/msg00144.html
* posix/glob.h [__GLOB_GNULIB]: Do not include sys/cdefs.h.
(__size_t): Remove.  All uses replaced by size_t.
(size_t): Define in the usual way, by defining __need_size_t
and including <stddef.h>.
(glob) [__USE_FILE_OFFSET64 && __GLOB_GNULIB]: Declare.
---
 posix/flexmember.h     |   45 +
 posix/glob.c           | 2174 +++++++++++++++++++++++++-----------------------
 posix/glob.h           |  112 ++-
 posix/glob_internal.h  |   26 +-
 posix/glob_pattern_p.c |    4 +
 posix/globfree.c       |    6 +-
 6 files changed, 1242 insertions(+), 1125 deletions(-)
 create mode 100644 posix/flexmember.hdiff --git a/posix/flexmember.h b/posix/flexmember.h
new file mode 100644
index 0000000000..107c1f09e9
--- /dev/null
+++ b/posix/flexmember.h
@@ -0,0 +1,45 @@
+/* Sizes of structs with flexible array members.
+
+   Copyright 2016-2017 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.
+
+   Written by Paul Eggert.  */
+
+#include <stddef.h>
+
+/* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below.
+   On older platforms without _Alignof, use a pessimistic bound that is
+   safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1.
+   On newer platforms, use _Alignof to get a tighter bound.  */
+
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
+# define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1))
+#else
+# define FLEXALIGNOF(type) _Alignof (type)
+#endif
+
+/* Upper bound on the size of a struct of type TYPE with a flexible
+   array member named MEMBER that is followed by N bytes of other data.
+   This is not simply sizeof (TYPE) + N, since it may require
+   alignment on unusually picky C11 platforms, and
+   FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms.
+   Yield a value less than N if and only if arithmetic overflow occurs.  */
+
+#define FLEXSIZEOF(type, member, n) \
+   ((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \
+    & ~ (FLEXALIGNOF (type) - 1))
diff --git a/posix/glob.c b/posix/glob.c
index 6abfb69c5a..a4aa3d8702 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -15,7 +15,12 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _LIBC
+# include <config.h>
+#endif
+
 #include <glob.h>
+
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -23,13 +28,15 @@
 #include <stddef.h>
 #include <stdint.h>
 #include <assert.h>
-
 #include <unistd.h>
-#if !defined POSIX && defined _POSIX_VERSION
-# define POSIX
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WINDOWS32
 #endif
 
-#include <pwd.h>
+#ifndef WINDOWS32
+# include <pwd.h>
+#endif
 
 #include <errno.h>
 #ifndef __set_errno
@@ -43,17 +50,18 @@
 
 #ifdef _LIBC
 # undef strdup
-# define strdup(str)		__strdup (str)
-# define sysconf(id)		__sysconf (id)
-# define closedir(dir)		__closedir (dir)
-# define opendir(name)		__opendir (name)
-# define readdir(str)		__readdir64 (str)
+# define strdup(str) __strdup (str)
+# define sysconf(id) __sysconf (id)
+# define closedir(dir) __closedir (dir)
+# define opendir(name) __opendir (name)
+# define readdir(str) __readdir64 (str)
 # define getpwnam_r(name, bufp, buf, len, res) \
     __getpwnam_r (name, bufp, buf, len, res)
 # ifndef __stat64
-#  define __stat64(fname, buf)	__xstat64 (_STAT_VER, fname, buf)
+#  define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
 # endif
-# define struct_stat64		struct stat64
+# define struct_stat64          struct stat64
+# define FLEXIBLE_ARRAY_MEMBER
 #else /* !_LIBC */
 # define __getlogin_r(buf, len) getlogin_r (buf, len)
 # define __stat64(fname, buf)   stat (fname, buf)
@@ -69,17 +77,18 @@
 
 #include <fnmatch.h>
 
+#include <flexmember.h>
 #include <glob_internal.h>
 
 #ifdef _SC_GETPW_R_SIZE_MAX
-# define GETPW_R_SIZE_MAX()	sysconf (_SC_GETPW_R_SIZE_MAX)
+# define GETPW_R_SIZE_MAX()     sysconf (_SC_GETPW_R_SIZE_MAX)
 #else
-# define GETPW_R_SIZE_MAX()	(-1)
+# define GETPW_R_SIZE_MAX()     (-1)
 #endif
 #ifdef _SC_LOGIN_NAME_MAX
-# define GET_LOGIN_NAME_MAX()	sysconf (_SC_LOGIN_NAME_MAX)
+# define GET_LOGIN_NAME_MAX()   sysconf (_SC_LOGIN_NAME_MAX)
 #else
-# define GET_LOGIN_NAME_MAX()	(-1)
+# define GET_LOGIN_NAME_MAX()   (-1)
 #endif
 
 static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
@@ -89,15 +98,15 @@ static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
 struct readdir_result
 {
   const char *name;
-# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
+#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
   uint8_t type;
-# endif
+#endif
   bool skip_entry;
 };
 
-# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
+#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
 /* Initializer based on the d_type member of struct dirent.  */
-#  define D_TYPE_TO_RESULT(source) (source)->d_type,
+# define D_TYPE_TO_RESULT(source) (source)->d_type,
 
 /* True if the directory entry D might be a symbolic link.  */
 static bool
@@ -112,8 +121,8 @@ readdir_result_might_be_dir (struct readdir_result d)
 {
   return d.type == DT_DIR || readdir_result_might_be_symlink (d);
 }
-# else /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
-#  define D_TYPE_TO_RESULT(source)
+#else /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
+# define D_TYPE_TO_RESULT(source)
 
 /* If we do not have type information, symbolic links and directories
    are always a possibility.  */
@@ -130,30 +139,30 @@ readdir_result_might_be_dir (struct readdir_result d)
   return true;
 }
 
-# endif /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
+#endif /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
 
-# if defined _LIBC || defined D_INO_IN_DIRENT
+#if defined _LIBC || defined D_INO_IN_DIRENT
 /* Initializer for skip_entry.  POSIX does not require that the d_ino
    field be present, and some systems do not provide it. */
-#  define D_INO_TO_RESULT(source) false,
-# else
-#  define D_INO_TO_RESULT(source) (source)->d_ino == 0,
-# endif
+# define D_INO_TO_RESULT(source) false,
+#else
+# define D_INO_TO_RESULT(source) (source)->d_ino == 0,
+#endif
 
 /* Construct an initializer for a struct readdir_result object from a
    struct dirent *.  No copy of the name is made.  */
-# define READDIR_RESULT_INITIALIZER(source) \
-  {					   \
-    source->d_name,			   \
-    D_TYPE_TO_RESULT (source)		   \
-    D_INO_TO_RESULT (source)		   \
+#define READDIR_RESULT_INITIALIZER(source) \
+  {                                        \
+    source->d_name,                        \
+    D_TYPE_TO_RESULT (source)              \
+    D_INO_TO_RESULT (source)               \
   }
 
 /* Call gl_readdir on STREAM.  This macro can be overridden to reduce
    type safety if an old interface version needs to be supported.  */
-# ifndef GL_READDIR
-#  define GL_READDIR(pglob, stream) ((pglob)->gl_readdir (stream))
-# endif
+#ifndef GL_READDIR
+# define GL_READDIR(pglob, stream) ((pglob)->gl_readdir (stream))
+#endif
 
 /* Extract name and type from directory entry.  No copy of the name is
    made.  If SOURCE is NULL, result name is NULL.  Keep in sync with
@@ -170,7 +179,7 @@ convert_dirent (const struct dirent *source)
   return result;
 }
 
-# ifndef COMPILE_GLOB64
+#ifndef COMPILE_GLOB64
 /* Like convert_dirent, but works on struct dirent64 instead.  Keep in
    sync with convert_dirent above.  */
 static struct readdir_result
@@ -184,45 +193,41 @@ convert_dirent64 (const struct dirent64 *source)
   struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
   return result;
 }
-# endif
+#endif
 
-# ifndef _LIBC
+#ifndef _LIBC
 /* The results of opendir() in this file are not used with dirfd and fchdir,
    and we do not leak fds to any single-threaded code that could use stdio,
    therefore save some unnecessary recursion in fchdir.c and opendir_safer.c.
    FIXME - if the kernel ever adds support for multi-thread safety for
    avoiding standard fds, then we should use opendir_safer.  */
-#  ifdef GNULIB_defined_opendir
-#   undef opendir
-#  endif
-#  ifdef GNULIB_defined_closedir
-#   undef closedir
-#  endif
+# ifdef GNULIB_defined_opendir
+#  undef opendir
+# endif
+# ifdef GNULIB_defined_closedir
+#  undef closedir
+# endif
 
 /* Just use malloc.  */
-#  define __libc_use_alloca(n) false
-#  define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0)
-#  define extend_alloca_account(buf, len, newlen, avar) \
+# define __libc_use_alloca(n) false
+# define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0)
+# define extend_alloca_account(buf, len, newlen, avar) \
     ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0)
-# endif
+#endif
 
 /* Set *R = A + B.  Return true if the answer is mathematically
    incorrect due to overflow; in this case, *R is the low order
-   bits of the correct answer..  */
-
-static bool size_add_wrapv (size_t a, size_t b, size_t *r);
-static bool glob_use_alloca (size_t alloca_used, size_t len);
+   bits of the correct answer.  */
 
-/* We must not compile this function twice.  */
 static bool
 size_add_wrapv (size_t a, size_t b, size_t *r)
 {
-# if 5 <= __GNUC__
+#if 5 <= __GNUC__ && !defined __ICC
   return __builtin_add_overflow (a, b, r);
-# else
+#else
   *r = a + b;
   return *r < a;
-# endif
+#endif
 }
 
 static bool
@@ -230,12 +235,12 @@ glob_use_alloca (size_t alloca_used, size_t len)
 {
   size_t size;
   return (!size_add_wrapv (alloca_used, len, &size)
-	  && __libc_use_alloca (size));
+          && __libc_use_alloca (size));
 }
 
 static int glob_in_dir (const char *pattern, const char *directory,
-			int flags, int (*errfunc) (const char *, int),
-			glob_t *pglob, size_t alloca_used);
+                        int flags, int (*errfunc) (const char *, int),
+                        glob_t *pglob, size_t alloca_used);
 extern int __glob_pattern_type (const char *pattern, int quote)
     attribute_hidden;
 
@@ -251,17 +256,17 @@ next_brace_sub (const char *cp, int flags)
   while (*cp != '\0')
     if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\')
       {
-	if (*++cp == '\0')
-	  break;
-	++cp;
+        if (*++cp == '\0')
+          break;
+        ++cp;
       }
     else
       {
-	if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
-	  break;
+        if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
+          break;
 
-	if (*cp++ == '{')
-	  depth++;
+        if (*cp++ == '{')
+          depth++;
       }
 
   return *cp != '\0' ? cp : NULL;
@@ -315,22 +320,22 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
     {
       pglob->gl_pathc = 0;
       if (!(flags & GLOB_DOOFFS))
-	pglob->gl_pathv = NULL;
+        pglob->gl_pathv = NULL;
       else
-	{
-	  size_t i;
+        {
+          size_t i;
 
-	  if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
-	    return GLOB_NOSPACE;
+          if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
+            return GLOB_NOSPACE;
 
-	  pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
-					      * sizeof (char *));
-	  if (pglob->gl_pathv == NULL)
-	    return GLOB_NOSPACE;
+          pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
+                                              * sizeof (char *));
+          if (pglob->gl_pathv == NULL)
+            return GLOB_NOSPACE;
 
-	  for (i = 0; i <= pglob->gl_offs; ++i)
-	    pglob->gl_pathv[i] = NULL;
-	}
+          for (i = 0; i <= pglob->gl_offs; ++i)
+            pglob->gl_pathv[i] = NULL;
+        }
     }
 
   if (flags & GLOB_BRACE)
@@ -338,171 +343,176 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
       const char *begin;
 
       if (flags & GLOB_NOESCAPE)
-	begin = strchr (pattern, '{');
+        begin = strchr (pattern, '{');
       else
-	{
-	  begin = pattern;
-	  while (1)
-	    {
-	      if (*begin == '\0')
-		{
-		  begin = NULL;
-		  break;
-		}
-
-	      if (*begin == '\\' && begin[1] != '\0')
-		++begin;
-	      else if (*begin == '{')
-		break;
-
-	      ++begin;
-	    }
-	}
+        {
+          begin = pattern;
+          while (1)
+            {
+              if (*begin == '\0')
+                {
+                  begin = NULL;
+                  break;
+                }
+
+              if (*begin == '\\' && begin[1] != '\0')
+                ++begin;
+              else if (*begin == '{')
+                break;
+
+              ++begin;
+            }
+        }
 
       if (begin != NULL)
-	{
-	  /* Allocate working buffer large enough for our work.  Note that
-	     we have at least an opening and closing brace.  */
-	  size_t firstc;
-	  char *alt_start;
-	  const char *p;
-	  const char *next;
-	  const char *rest;
-	  size_t rest_len;
-	  char *onealt;
-	  size_t pattern_len = strlen (pattern) - 1;
-	  int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
-	  if (alloca_onealt)
-	    onealt = alloca_account (pattern_len, alloca_used);
-	  else
-	    {
-	      onealt = malloc (pattern_len);
-	      if (onealt == NULL)
-		{
-		  if (!(flags & GLOB_APPEND))
-		    {
-		      pglob->gl_pathc = 0;
-		      pglob->gl_pathv = NULL;
-		    }
-		  return GLOB_NOSPACE;
-		}
-	    }
-
-	  /* We know the prefix for all sub-patterns.  */
-	  alt_start = mempcpy (onealt, pattern, begin - pattern);
-
-	  /* Find the first sub-pattern and at the same time find the
-	     rest after the closing brace.  */
-	  next = next_brace_sub (begin + 1, flags);
-	  if (next == NULL)
-	    {
-	      /* It is an invalid expression.  */
-	    illegal_brace:
-	      if (__glibc_unlikely (!alloca_onealt))
-		free (onealt);
-	      return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
-	    }
-
-	  /* Now find the end of the whole brace expression.  */
-	  rest = next;
-	  while (*rest != '}')
-	    {
-	      rest = next_brace_sub (rest + 1, flags);
-	      if (rest == NULL)
-		/* It is an illegal expression.  */
-		goto illegal_brace;
-	    }
-	  /* Please note that we now can be sure the brace expression
-	     is well-formed.  */
-	  rest_len = strlen (++rest) + 1;
-
-	  /* We have a brace expression.  BEGIN points to the opening {,
-	     NEXT points past the terminator of the first element, and END
-	     points past the final }.  We will accumulate result names from
-	     recursive runs for each brace alternative in the buffer using
-	     GLOB_APPEND.  */
-	  firstc = pglob->gl_pathc;
-
-	  p = begin + 1;
-	  while (1)
-	    {
-	      int result;
-
-	      /* Construct the new glob expression.  */
-	      mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
-
-	      result = glob (onealt,
-			     ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
-			      | GLOB_APPEND), errfunc, pglob);
-
-	      /* If we got an error, return it.  */
-	      if (result && result != GLOB_NOMATCH)
-		{
-		  if (__glibc_unlikely (!alloca_onealt))
-		    free (onealt);
-		  if (!(flags & GLOB_APPEND))
-		    {
-		      globfree (pglob);
-		      pglob->gl_pathc = 0;
-		    }
-		  return result;
-		}
-
-	      if (*next == '}')
-		/* We saw the last entry.  */
-		break;
-
-	      p = next + 1;
-	      next = next_brace_sub (p, flags);
-	      assert (next != NULL);
-	    }
-
-	  if (__glibc_unlikely (!alloca_onealt))
-	    free (onealt);
-
-	  if (pglob->gl_pathc != firstc)
-	    /* We found some entries.  */
-	    return 0;
-	  else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
-	    return GLOB_NOMATCH;
-	}
+        {
+          /* Allocate working buffer large enough for our work.  Note that
+             we have at least an opening and closing brace.  */
+          size_t firstc;
+          char *alt_start;
+          const char *p;
+          const char *next;
+          const char *rest;
+          size_t rest_len;
+          char *onealt;
+          size_t pattern_len = strlen (pattern) - 1;
+          int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
+          if (alloca_onealt)
+            onealt = alloca_account (pattern_len, alloca_used);
+          else
+            {
+              onealt = malloc (pattern_len);
+              if (onealt == NULL)
+                return GLOB_NOSPACE;
+            }
+
+          /* We know the prefix for all sub-patterns.  */
+          alt_start = mempcpy (onealt, pattern, begin - pattern);
+
+          /* Find the first sub-pattern and at the same time find the
+             rest after the closing brace.  */
+          next = next_brace_sub (begin + 1, flags);
+          if (next == NULL)
+            {
+              /* It is an invalid expression.  */
+            illegal_brace:
+              if (__glibc_unlikely (!alloca_onealt))
+                free (onealt);
+              flags &= ~GLOB_BRACE;
+              goto no_brace;
+            }
+
+          /* Now find the end of the whole brace expression.  */
+          rest = next;
+          while (*rest != '}')
+            {
+              rest = next_brace_sub (rest + 1, flags);
+              if (rest == NULL)
+                /* It is an illegal expression.  */
+                goto illegal_brace;
+            }
+          /* Please note that we now can be sure the brace expression
+             is well-formed.  */
+          rest_len = strlen (++rest) + 1;
+
+          /* We have a brace expression.  BEGIN points to the opening {,
+             NEXT points past the terminator of the first element, and END
+             points past the final }.  We will accumulate result names from
+             recursive runs for each brace alternative in the buffer using
+             GLOB_APPEND.  */
+          firstc = pglob->gl_pathc;
+
+          p = begin + 1;
+          while (1)
+            {
+              int result;
+
+              /* Construct the new glob expression.  */
+              mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
+
+              result = glob (onealt,
+                             ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
+                              | GLOB_APPEND), errfunc, pglob);
+
+              /* If we got an error, return it.  */
+              if (result && result != GLOB_NOMATCH)
+                {
+                  if (__glibc_unlikely (!alloca_onealt))
+                    free (onealt);
+                  if (!(flags & GLOB_APPEND))
+                    {
+                      globfree (pglob);
+                      pglob->gl_pathc = 0;
+                    }
+                  return result;
+                }
+
+              if (*next == '}')
+                /* We saw the last entry.  */
+                break;
+
+              p = next + 1;
+              next = next_brace_sub (p, flags);
+              assert (next != NULL);
+            }
+
+          if (__glibc_unlikely (!alloca_onealt))
+            free (onealt);
+
+          if (pglob->gl_pathc != firstc)
+            /* We found some entries.  */
+            return 0;
+          else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
+            return GLOB_NOMATCH;
+        }
     }
 
+ no_brace:
   oldcount = pglob->gl_pathc + pglob->gl_offs;
 
   /* Find the filename.  */
   filename = strrchr (pattern, '/');
+
+#if defined __MSDOS__ || defined WINDOWS32
+  /* The case of "d:pattern".  Since ':' is not allowed in
+     file names, we can safely assume that wherever it
+     happens in pattern, it signals the filename part.  This
+     is so we could some day support patterns like "[a-z]:foo".  */
+  if (filename == NULL)
+    filename = strchr (pattern, ':');
+#endif /* __MSDOS__ || WINDOWS32 */
+
   dirname_modified = 0;
   if (filename == NULL)
     {
       /* This can mean two things: a simple name or "~name".  The latter
-	 case is nothing but a notation for a directory.  */
+         case is nothing but a notation for a directory.  */
       if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
-	{
-	  dirname = (char *) pattern;
-	  dirlen = strlen (pattern);
-
-	  /* Set FILENAME to NULL as a special flag.  This is ugly but
-	     other solutions would require much more code.  We test for
-	     this special case below.  */
-	  filename = NULL;
-	}
+        {
+          dirname = (char *) pattern;
+          dirlen = strlen (pattern);
+
+          /* Set FILENAME to NULL as a special flag.  This is ugly but
+             other solutions would require much more code.  We test for
+             this special case below.  */
+          filename = NULL;
+        }
       else
-	{
-	  if (__glibc_unlikely (pattern[0] == '\0'))
-	    {
-	      dirs.gl_pathv = NULL;
-	      goto no_matches;
-	    }
-
-	  filename = pattern;
-	  dirname = (char *) ".";
-	  dirlen = 0;
-	}
+        {
+          if (__glibc_unlikely (pattern[0] == '\0'))
+            {
+              dirs.gl_pathv = NULL;
+              goto no_matches;
+            }
+
+          filename = pattern;
+          dirname = (char *) ".";
+          dirlen = 0;
+        }
     }
   else if (filename == pattern
-	   || (filename == pattern + 1 && pattern[0] == '\\'
-	       && (flags & GLOB_NOESCAPE) == 0))
+           || (filename == pattern + 1 && pattern[0] == '\\'
+               && (flags & GLOB_NOESCAPE) == 0))
     {
       /* "/pattern" or "\\/pattern".  */
       dirname = (char *) "/";
@@ -513,425 +523,475 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
     {
       char *newp;
       dirlen = filename - pattern;
+
+#if defined __MSDOS__ || defined WINDOWS32
+      if (*filename == ':'
+          || (filename > pattern + 1 && filename[-1] == ':'))
+        {
+          char *drive_spec;
+
+          ++dirlen;
+          drive_spec = __alloca (dirlen + 1);
+          *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
+          /* For now, disallow wildcards in the drive spec, to
+             prevent infinite recursion in glob.  */
+          if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
+            return GLOB_NOMATCH;
+          /* If this is "d:pattern", we need to copy ':' to DIRNAME
+             as well.  If it's "d:/pattern", don't remove the slash
+             from "d:/", since "d:" and "d:/" are not the same.*/
+        }
+#endif
+
       if (glob_use_alloca (alloca_used, dirlen + 1))
-	newp = alloca_account (dirlen + 1, alloca_used);
+        newp = alloca_account (dirlen + 1, alloca_used);
       else
-	{
-	  newp = malloc (dirlen + 1);
-	  if (newp == NULL)
-	    return GLOB_NOSPACE;
-	  malloc_dirname = 1;
-	}
+        {
+          newp = malloc (dirlen + 1);
+          if (newp == NULL)
+            return GLOB_NOSPACE;
+          malloc_dirname = 1;
+        }
       *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
       dirname = newp;
       ++filename;
 
-      if (filename[0] == '\0' && dirlen > 1)
-	/* "pattern/".  Expand "pattern", appending slashes.  */
-	{
-	  int orig_flags = flags;
-          int val;
-	  if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
-	    {
-	      /* "pattern\\/".  Remove the final backslash if it hasn't
-		 been quoted.  */
-	      char *p = (char *) &dirname[dirlen - 1];
-
-	      while (p > dirname && p[-1] == '\\') --p;
-	      if ((&dirname[dirlen] - p) & 1)
-		{
-		  *(char *) &dirname[--dirlen] = '\0';
-		  flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
-		}
-	    }
-	  val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
-	  if (val == 0)
-	    pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
-			       | (flags & GLOB_MARK));
-	  else if (val == GLOB_NOMATCH && flags != orig_flags)
-	    {
-	      /* Make sure globfree (&dirs); is a nop.  */
-	      dirs.gl_pathv = NULL;
-	      flags = orig_flags;
-	      oldcount = pglob->gl_pathc + pglob->gl_offs;
-	      goto no_matches;
-	    }
-	  retval = val;
-	  goto out;
-	}
+#if defined __MSDOS__ || defined WINDOWS32
+      bool drive_root = (dirlen > 1
+                         && (dirname[dirlen - 1] == ':'
+                             || (dirlen > 2 && dirname[dirlen - 2] == ':'
+                                 && dirname[dirlen - 1] == '/')));
+#else
+      bool drive_root = false;
+#endif
+
+      if (filename[0] == '\0' && dirlen > 1 && !drive_root)
+        /* "pattern/".  Expand "pattern", appending slashes.  */
+        {
+          int orig_flags = flags;
+          if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
+            {
+              /* "pattern\\/".  Remove the final backslash if it hasn't
+                 been quoted.  */
+              char *p = (char *) &dirname[dirlen - 1];
+
+              while (p > dirname && p[-1] == '\\') --p;
+              if ((&dirname[dirlen] - p) & 1)
+                {
+                  *(char *) &dirname[--dirlen] = '\0';
+                  flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
+                }
+            }
+          int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
+          if (val == 0)
+            pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
+                               | (flags & GLOB_MARK));
+          else if (val == GLOB_NOMATCH && flags != orig_flags)
+            {
+              /* Make sure globfree (&dirs); is a nop.  */
+              dirs.gl_pathv = NULL;
+              flags = orig_flags;
+              oldcount = pglob->gl_pathc + pglob->gl_offs;
+              goto no_matches;
+            }
+          retval = val;
+          goto out;
+        }
     }
 
   if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
     {
       if (dirname[1] == '\0' || dirname[1] == '/'
-	  || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\'
-	      && (dirname[2] == '\0' || dirname[2] == '/')))
-	{
-	  /* Look up home directory.  */
-	  char *home_dir = getenv ("HOME");
-	  int malloc_home_dir = 0;
-	  if (home_dir == NULL || home_dir[0] == '\0')
-	    {
-	      int success;
-	      char *name;
-	      int malloc_name = 0;
-	      size_t buflen = GET_LOGIN_NAME_MAX () + 1;
-
-	      if (buflen == 0)
-		/* `sysconf' does not support _SC_LOGIN_NAME_MAX.  Try
-		   a moderate value.  */
-		buflen = 20;
-	      if (glob_use_alloca (alloca_used, buflen))
-		name = alloca_account (buflen, alloca_used);
-	      else
-		{
-		  name = malloc (buflen);
-		  if (name == NULL)
-		    {
-		      retval = GLOB_NOSPACE;
-		      goto out;
-		    }
-		  malloc_name = 1;
-		}
-
-	      success = __getlogin_r (name, buflen) == 0;
-	      if (success)
-		{
-		  struct passwd *p;
-		  char *malloc_pwtmpbuf = NULL;
-		  char *pwtmpbuf;
-#   if defined HAVE_GETPWNAM_R || defined _LIBC
-		  long int pwbuflenmax = GETPW_R_SIZE_MAX ();
-		  size_t pwbuflen = pwbuflenmax;
-		  struct passwd pwbuf;
-		  int save = errno;
-
-#    ifndef _LIBC
+          || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\'
+              && (dirname[2] == '\0' || dirname[2] == '/')))
+        {
+          /* Look up home directory.  */
+          char *home_dir = getenv ("HOME");
+          int malloc_home_dir = 0;
+          if (home_dir == NULL || home_dir[0] == '\0')
+            {
+#ifdef WINDOWS32
+              /* Windows NT defines HOMEDRIVE and HOMEPATH.  But give
+                 preference to HOME, because the user can change HOME.  */
+              const char *home_drive = getenv ("HOMEDRIVE");
+              const char *home_path = getenv ("HOMEPATH");
+
+              if (home_drive != NULL && home_path != NULL)
+                {
+                  size_t home_drive_len = strlen (home_drive);
+                  size_t home_path_len = strlen (home_path);
+                  char *mem = alloca (home_drive_len + home_path_len + 1);
+
+                  memcpy (mem, home_drive, home_drive_len);
+                  memcpy (mem + home_drive_len, home_path, home_path_len + 1);
+                  home_dir = mem;
+                }
+              else
+                home_dir = "c:/users/default"; /* poor default */
+#else
+              int success;
+              char *name;
+              int malloc_name = 0;
+              size_t buflen = GET_LOGIN_NAME_MAX () + 1;
+
+              if (buflen == 0)
+                /* 'sysconf' does not support _SC_LOGIN_NAME_MAX.  Try
+                   a moderate value.  */
+                buflen = 20;
+              if (glob_use_alloca (alloca_used, buflen))
+                name = alloca_account (buflen, alloca_used);
+              else
+                {
+                  name = malloc (buflen);
+                  if (name == NULL)
+                    {
+                      retval = GLOB_NOSPACE;
+                      goto out;
+                    }
+                  malloc_name = 1;
+                }
+
+              success = __getlogin_r (name, buflen) == 0;
+              if (success)
+                {
+                  struct passwd *p;
+                  char *malloc_pwtmpbuf = NULL;
+                  char *pwtmpbuf;
+# if defined HAVE_GETPWNAM_R || defined _LIBC
+                  long int pwbuflenmax = GETPW_R_SIZE_MAX ();
+                  size_t pwbuflen = pwbuflenmax;
+                  struct passwd pwbuf;
+                  int save = errno;
+
+#  ifndef _LIBC
                   if (! (0 < pwbuflenmax && pwbuflenmax <= SIZE_MAX))
-		    /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
-		       Try a moderate value.  */
-		    pwbuflen = 1024;
-#    endif
-		  if (glob_use_alloca (alloca_used, pwbuflen))
-		    pwtmpbuf = alloca_account (pwbuflen, alloca_used);
-		  else
-		    {
-		      pwtmpbuf = malloc (pwbuflen);
-		      if (pwtmpbuf == NULL)
-			{
-			  if (__glibc_unlikely (malloc_name))
-			    free (name);
-			  retval = GLOB_NOSPACE;
-			  goto out;
-			}
-		      malloc_pwtmpbuf = pwtmpbuf;
-		    }
-
-		  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
-			 != 0)
-		    {
-		      size_t newlen;
-		      bool v;
-		      if (errno != ERANGE)
-			{
-			  p = NULL;
-			  break;
-			}
-		      v = size_add_wrapv (pwbuflen, pwbuflen, &newlen);
-		      if (!v && malloc_pwtmpbuf == NULL
-			  && glob_use_alloca (alloca_used, newlen))
-			pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
-							  newlen, alloca_used);
-		      else
-			{
-			  char *newp = (v ? NULL
-					: realloc (malloc_pwtmpbuf, newlen));
-			  if (newp == NULL)
-			    {
-			      free (malloc_pwtmpbuf);
-			      if (__glibc_unlikely (malloc_name))
-				free (name);
-			      retval = GLOB_NOSPACE;
-			      goto out;
-			    }
-			  malloc_pwtmpbuf = pwtmpbuf = newp;
-			}
-		      pwbuflen = newlen;
-		      __set_errno (save);
-		    }
-#   else
-		  p = getpwnam (name);
-#   endif
-		  if (__glibc_unlikely (malloc_name))
-		    free (name);
-		  if (p != NULL)
-		    {
-		      if (malloc_pwtmpbuf == NULL)
-			home_dir = p->pw_dir;
-		      else
-			{
-			  size_t home_dir_len = strlen (p->pw_dir) + 1;
-			  if (glob_use_alloca (alloca_used, home_dir_len))
-			    home_dir = alloca_account (home_dir_len,
-						       alloca_used);
-			  else
-			    {
-			      home_dir = malloc (home_dir_len);
-			      if (home_dir == NULL)
-				{
-				  free (pwtmpbuf);
-				  retval = GLOB_NOSPACE;
-				  goto out;
-				}
-			      malloc_home_dir = 1;
-			    }
-			  memcpy (home_dir, p->pw_dir, home_dir_len);
-			}
-		    }
-		  free (malloc_pwtmpbuf);
-		}
-	      else
-		{
-		  if (__glibc_unlikely (malloc_name))
-		    free (name);
-		}
-	    }
-	  if (home_dir == NULL || home_dir[0] == '\0')
-	    {
-	      if (__glibc_unlikely (malloc_home_dir))
-		free (home_dir);
-	      if (flags & GLOB_TILDE_CHECK)
-		{
-		  retval = GLOB_NOMATCH;
-		  goto out;
-		}
-	      else
-		{
-		  home_dir = (char *) "~"; /* No luck.  */
-		  malloc_home_dir = 0;
-		}
-	    }
-	  /* Now construct the full directory.  */
-	  if (dirname[1] == '\0')
-	    {
-	      if (__glibc_unlikely (malloc_dirname))
-		free (dirname);
-
-	      dirname = home_dir;
-	      dirlen = strlen (dirname);
-	      malloc_dirname = malloc_home_dir;
-	    }
-	  else
-	    {
-	      char *newp;
-	      size_t home_len = strlen (home_dir);
-	      int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
-	      if (use_alloca)
-		newp = alloca_account (home_len + dirlen, alloca_used);
-	      else
-		{
-		  newp = malloc (home_len + dirlen);
-		  if (newp == NULL)
-		    {
-		      if (__glibc_unlikely (malloc_home_dir))
-			free (home_dir);
-		      retval = GLOB_NOSPACE;
-		      goto out;
-		    }
-		}
-
-	      mempcpy (mempcpy (newp, home_dir, home_len),
-		       &dirname[1], dirlen);
-
-	      if (__glibc_unlikely (malloc_dirname))
-		free (dirname);
-
-	      dirname = newp;
-	      dirlen += home_len - 1;
-	      malloc_dirname = !use_alloca;
-
-	      if (__glibc_unlikely (malloc_home_dir))
-		free (home_dir);
-	    }
-	  dirname_modified = 1;
-	}
+                    /* 'sysconf' does not support _SC_GETPW_R_SIZE_MAX.
+                       Try a moderate value.  */
+                    pwbuflen = 1024;
+#  endif
+                  if (glob_use_alloca (alloca_used, pwbuflen))
+                    pwtmpbuf = alloca_account (pwbuflen, alloca_used);
+                  else
+                    {
+                      pwtmpbuf = malloc (pwbuflen);
+                      if (pwtmpbuf == NULL)
+                        {
+                          if (__glibc_unlikely (malloc_name))
+                            free (name);
+                          retval = GLOB_NOSPACE;
+                          goto out;
+                        }
+                      malloc_pwtmpbuf = pwtmpbuf;
+                    }
+
+                  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
+                         != 0)
+                    {
+                      size_t newlen;
+                      bool v;
+                      if (errno != ERANGE)
+                        {
+                          p = NULL;
+                          break;
+                        }
+                      v = size_add_wrapv (pwbuflen, pwbuflen, &newlen);
+                      if (!v && malloc_pwtmpbuf == NULL
+                          && glob_use_alloca (alloca_used, newlen))
+                        pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
+                                                          newlen, alloca_used);
+                      else
+                        {
+                          char *newp = (v ? NULL
+                                        : realloc (malloc_pwtmpbuf, newlen));
+                          if (newp == NULL)
+                            {
+                              free (malloc_pwtmpbuf);
+                              if (__glibc_unlikely (malloc_name))
+                                free (name);
+                              retval = GLOB_NOSPACE;
+                              goto out;
+                            }
+                          malloc_pwtmpbuf = pwtmpbuf = newp;
+                        }
+                      pwbuflen = newlen;
+                      __set_errno (save);
+                    }
+# else
+                  p = getpwnam (name);
+# endif
+                  if (__glibc_unlikely (malloc_name))
+                    free (name);
+                  if (p != NULL)
+                    {
+                      if (malloc_pwtmpbuf == NULL)
+                        home_dir = p->pw_dir;
+                      else
+                        {
+                          size_t home_dir_len = strlen (p->pw_dir) + 1;
+                          if (glob_use_alloca (alloca_used, home_dir_len))
+                            home_dir = alloca_account (home_dir_len,
+                                                       alloca_used);
+                          else
+                            {
+                              home_dir = malloc (home_dir_len);
+                              if (home_dir == NULL)
+                                {
+                                  free (pwtmpbuf);
+                                  retval = GLOB_NOSPACE;
+                                  goto out;
+                                }
+                              malloc_home_dir = 1;
+                            }
+                          memcpy (home_dir, p->pw_dir, home_dir_len);
+                        }
+                    }
+                  free (malloc_pwtmpbuf);
+                }
+              else
+                {
+                  if (__glibc_unlikely (malloc_name))
+                    free (name);
+                }
+#endif /* WINDOWS32 */
+            }
+          if (home_dir == NULL || home_dir[0] == '\0')
+            {
+              if (__glibc_unlikely (malloc_home_dir))
+                free (home_dir);
+              if (flags & GLOB_TILDE_CHECK)
+                {
+                  retval = GLOB_NOMATCH;
+                  goto out;
+                }
+              else
+                {
+                  home_dir = (char *) "~"; /* No luck.  */
+                  malloc_home_dir = 0;
+                }
+            }
+          /* Now construct the full directory.  */
+          if (dirname[1] == '\0')
+            {
+              if (__glibc_unlikely (malloc_dirname))
+                free (dirname);
+
+              dirname = home_dir;
+              dirlen = strlen (dirname);
+              malloc_dirname = malloc_home_dir;
+            }
+          else
+            {
+              char *newp;
+              size_t home_len = strlen (home_dir);
+              int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
+              if (use_alloca)
+                newp = alloca_account (home_len + dirlen, alloca_used);
+              else
+                {
+                  newp = malloc (home_len + dirlen);
+                  if (newp == NULL)
+                    {
+                      if (__glibc_unlikely (malloc_home_dir))
+                        free (home_dir);
+                      retval = GLOB_NOSPACE;
+                      goto out;
+                    }
+                }
+
+              mempcpy (mempcpy (newp, home_dir, home_len),
+                       &dirname[1], dirlen);
+
+              if (__glibc_unlikely (malloc_dirname))
+                free (dirname);
+
+              dirname = newp;
+              dirlen += home_len - 1;
+              malloc_dirname = !use_alloca;
+
+              if (__glibc_unlikely (malloc_home_dir))
+                free (home_dir);
+            }
+          dirname_modified = 1;
+        }
       else
-	{
-	  char *end_name = strchr (dirname, '/');
-	  char *user_name;
-	  int malloc_user_name = 0;
-	  char *unescape = NULL;
-
-	  if (!(flags & GLOB_NOESCAPE))
-	    {
-	      if (end_name == NULL)
-		{
-		  unescape = strchr (dirname, '\\');
-		  if (unescape)
-		    end_name = strchr (unescape, '\0');
-		}
-	      else
-		unescape = memchr (dirname, '\\', end_name - dirname);
-	    }
-	  if (end_name == NULL)
-	    user_name = dirname + 1;
-	  else
-	    {
-	      char *newp;
-	      if (glob_use_alloca (alloca_used, end_name - dirname))
-		newp = alloca_account (end_name - dirname, alloca_used);
-	      else
-		{
-		  newp = malloc (end_name - dirname);
-		  if (newp == NULL)
-		    {
-		      retval = GLOB_NOSPACE;
-		      goto out;
-		    }
-		  malloc_user_name = 1;
-		}
-	      if (unescape != NULL)
-		{
-		  char *p = mempcpy (newp, dirname + 1,
-				     unescape - dirname - 1);
-		  char *q = unescape;
-		  while (*q != '\0')
-		    {
-		      if (*q == '\\')
-			{
-			  if (q[1] == '\0')
-			    {
-			      /* "~fo\\o\\" unescape to user_name "foo\\",
-				 but "~fo\\o\\/" unescape to user_name
-				 "foo".  */
-			      if (filename == NULL)
-				*p++ = '\\';
-			      break;
-			    }
-			  ++q;
-			}
-		      *p++ = *q++;
-		    }
-		  *p = '\0';
-		}
-	      else
-		*((char *) mempcpy (newp, dirname + 1, end_name - dirname))
-		  = '\0';
-	      user_name = newp;
-	    }
-
-	  /* Look up specific user's home directory.  */
-	  {
-	    struct passwd *p;
-	    char *malloc_pwtmpbuf = NULL;
+        {
+#ifndef WINDOWS32
+          char *end_name = strchr (dirname, '/');
+          char *user_name;
+          int malloc_user_name = 0;
+          char *unescape = NULL;
+
+          if (!(flags & GLOB_NOESCAPE))
+            {
+              if (end_name == NULL)
+                {
+                  unescape = strchr (dirname, '\\');
+                  if (unescape)
+                    end_name = strchr (unescape, '\0');
+                }
+              else
+                unescape = memchr (dirname, '\\', end_name - dirname);
+            }
+          if (end_name == NULL)
+            user_name = dirname + 1;
+          else
+            {
+              char *newp;
+              if (glob_use_alloca (alloca_used, end_name - dirname))
+                newp = alloca_account (end_name - dirname, alloca_used);
+              else
+                {
+                  newp = malloc (end_name - dirname);
+                  if (newp == NULL)
+                    {
+                      retval = GLOB_NOSPACE;
+                      goto out;
+                    }
+                  malloc_user_name = 1;
+                }
+              if (unescape != NULL)
+                {
+                  char *p = mempcpy (newp, dirname + 1,
+                                     unescape - dirname - 1);
+                  char *q = unescape;
+                  while (*q != '\0')
+                    {
+                      if (*q == '\\')
+                        {
+                          if (q[1] == '\0')
+                            {
+                              /* "~fo\\o\\" unescape to user_name "foo\\",
+                                 but "~fo\\o\\/" unescape to user_name
+                                 "foo".  */
+                              if (filename == NULL)
+                                *p++ = '\\';
+                              break;
+                            }
+                          ++q;
+                        }
+                      *p++ = *q++;
+                    }
+                  *p = '\0';
+                }
+              else
+                *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
+                  = '\0';
+              user_name = newp;
+            }
+
+          /* Look up specific user's home directory.  */
+          {
+            struct passwd *p;
+            char *malloc_pwtmpbuf = NULL;
 #  if defined HAVE_GETPWNAM_R || defined _LIBC
-	    long int buflenmax = GETPW_R_SIZE_MAX ();
-	    size_t buflen = buflenmax;
-	    char *pwtmpbuf;
-	    struct passwd pwbuf;
-	    int save = errno;
+            long int buflenmax = GETPW_R_SIZE_MAX ();
+            size_t buflen = buflenmax;
+            char *pwtmpbuf;
+            struct passwd pwbuf;
+            int save = errno;
 
 #   ifndef _LIBC
-	    if (! (0 <= buflenmax && buflenmax <= SIZE_MAX))
-	      /* Perhaps 'sysconf' does not support _SC_GETPW_R_SIZE_MAX.  Try a
-		 moderate value.  */
-	      buflen = 1024;
+            if (! (0 <= buflenmax && buflenmax <= SIZE_MAX))
+              /* Perhaps 'sysconf' does not support _SC_GETPW_R_SIZE_MAX.  Try a
+                 moderate value.  */
+              buflen = 1024;
 #   endif
-	    if (glob_use_alloca (alloca_used, buflen))
-	      pwtmpbuf = alloca_account (buflen, alloca_used);
-	    else
-	      {
-		pwtmpbuf = malloc (buflen);
-		if (pwtmpbuf == NULL)
-		  {
-		  nomem_getpw:
-		    if (__glibc_unlikely (malloc_user_name))
-		      free (user_name);
-		    retval = GLOB_NOSPACE;
-		    goto out;
-		  }
-		malloc_pwtmpbuf = pwtmpbuf;
-	      }
-
-	    while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
-	      {
-		size_t newlen;
-		bool v;
-		if (errno != ERANGE)
-		  {
-		    p = NULL;
-		    break;
-		  }
-		v = size_add_wrapv (buflen, buflen, &newlen);
-		if (!v && malloc_pwtmpbuf == NULL
-		    && glob_use_alloca (alloca_used, newlen))
-		  pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
-						    newlen, alloca_used);
-		else
-		  {
-		    char *newp = v ? NULL : realloc (malloc_pwtmpbuf, newlen);
-		    if (newp == NULL)
-		      {
-			free (malloc_pwtmpbuf);
-			goto nomem_getpw;
-		      }
-		    malloc_pwtmpbuf = pwtmpbuf = newp;
-		  }
-		__set_errno (save);
-	      }
+            if (glob_use_alloca (alloca_used, buflen))
+              pwtmpbuf = alloca_account (buflen, alloca_used);
+            else
+              {
+                pwtmpbuf = malloc (buflen);
+                if (pwtmpbuf == NULL)
+                  {
+                  nomem_getpw:
+                    if (__glibc_unlikely (malloc_user_name))
+                      free (user_name);
+                    retval = GLOB_NOSPACE;
+                    goto out;
+                  }
+                malloc_pwtmpbuf = pwtmpbuf;
+              }
+
+            while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
+              {
+                size_t newlen;
+                bool v;
+                if (errno != ERANGE)
+                  {
+                    p = NULL;
+                    break;
+                  }
+                v = size_add_wrapv (buflen, buflen, &newlen);
+                if (!v && malloc_pwtmpbuf == NULL
+                    && glob_use_alloca (alloca_used, newlen))
+                  pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
+                                                    newlen, alloca_used);
+                else
+                  {
+                    char *newp = v ? NULL : realloc (malloc_pwtmpbuf, newlen);
+                    if (newp == NULL)
+                      {
+                        free (malloc_pwtmpbuf);
+                        goto nomem_getpw;
+                      }
+                    malloc_pwtmpbuf = pwtmpbuf = newp;
+                  }
+                __set_errno (save);
+              }
 #  else
-	    p = getpwnam (user_name);
+            p = getpwnam (user_name);
 #  endif
 
-	    if (__glibc_unlikely (malloc_user_name))
-	      free (user_name);
-
-	    /* If we found a home directory use this.  */
-	    if (p != NULL)
-	      {
-		size_t home_len = strlen (p->pw_dir);
-		size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
-
-		if (__glibc_unlikely (malloc_dirname))
-		  free (dirname);
-		malloc_dirname = 0;
-
-		if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
-		  dirname = alloca_account (home_len + rest_len + 1,
-					    alloca_used);
-		else
-		  {
-		    dirname = malloc (home_len + rest_len + 1);
-		    if (dirname == NULL)
-		      {
-			free (malloc_pwtmpbuf);
-			retval = GLOB_NOSPACE;
-			goto out;
-		      }
-		    malloc_dirname = 1;
-		  }
-		*((char *) mempcpy (mempcpy (dirname, p->pw_dir, home_len),
-				    end_name, rest_len)) = '\0';
-
-		dirlen = home_len + rest_len;
-		dirname_modified = 1;
-
-		free (malloc_pwtmpbuf);
-	      }
-	    else
-	      {
-		free (malloc_pwtmpbuf);
-
-		if (flags & GLOB_TILDE_CHECK)
-		  {
-		  /* We have to regard it as an error if we cannot find the
-		     home directory.  */
-		    retval = GLOB_NOMATCH;
-		    goto out;
-		  }
-	      }
-	  }
-	}
+            if (__glibc_unlikely (malloc_user_name))
+              free (user_name);
+
+            /* If we found a home directory use this.  */
+            if (p != NULL)
+              {
+                size_t home_len = strlen (p->pw_dir);
+                size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
+
+                if (__glibc_unlikely (malloc_dirname))
+                  free (dirname);
+                malloc_dirname = 0;
+
+                if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
+                  dirname = alloca_account (home_len + rest_len + 1,
+                                            alloca_used);
+                else
+                  {
+                    dirname = malloc (home_len + rest_len + 1);
+                    if (dirname == NULL)
+                      {
+                        free (malloc_pwtmpbuf);
+                        retval = GLOB_NOSPACE;
+                        goto out;
+                      }
+                    malloc_dirname = 1;
+                  }
+                *((char *) mempcpy (mempcpy (dirname, p->pw_dir, home_len),
+                                    end_name, rest_len)) = '\0';
+
+                dirlen = home_len + rest_len;
+                dirname_modified = 1;
+
+                free (malloc_pwtmpbuf);
+              }
+            else
+              {
+                free (malloc_pwtmpbuf);
+
+                if (flags & GLOB_TILDE_CHECK)
+                  {
+                    /* We have to regard it as an error if we cannot find the
+                       home directory.  */
+                    retval = GLOB_NOMATCH;
+                    goto out;
+                  }
+              }
+          }
+#endif /* !WINDOWS32 */
+        }
     }
 
   /* Now test whether we looked for "~" or "~NAME".  In this case we
@@ -943,59 +1003,59 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
 
       /* Return the directory if we don't check for error or if it exists.  */
       if ((flags & GLOB_NOCHECK)
-	  || (((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
-	       ? ((*pglob->gl_stat) (dirname, &st) == 0
-		  && S_ISDIR (st.st_mode))
-	       : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode)))))
-	{
-	  size_t newcount = pglob->gl_pathc + pglob->gl_offs;
-	  char **new_gl_pathv;
+          || (((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
+               ? ((*pglob->gl_stat) (dirname, &st) == 0
+                  && S_ISDIR (st.st_mode))
+               : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode)))))
+        {
+          size_t newcount = pglob->gl_pathc + pglob->gl_offs;
+          char **new_gl_pathv;
 
           if (newcount > SIZE_MAX / sizeof (char *) - 2)
-	    {
-	    nospace:
-	      free (pglob->gl_pathv);
-	      pglob->gl_pathv = NULL;
-	      pglob->gl_pathc = 0;
-	      retval = GLOB_NOSPACE;
-	      goto out;
-	    }
-
-	  new_gl_pathv = realloc (pglob->gl_pathv,
-				  (newcount + 2) * sizeof (char *));
-	  if (new_gl_pathv == NULL)
-	    goto nospace;
-	  pglob->gl_pathv = new_gl_pathv;
-
-	  if (flags & GLOB_MARK)
-	    {
-	      char *p;
-	      pglob->gl_pathv[newcount] = malloc (dirlen + 2);
-	      if (pglob->gl_pathv[newcount] == NULL)
-		goto nospace;
-	      p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
-	      p[0] = '/';
-	      p[1] = '\0';
-	      if (__glibc_unlikely (malloc_dirname))
-		free (dirname);
-	    }
-	  else
-	    {
-	      if (__glibc_unlikely (malloc_dirname))
-		pglob->gl_pathv[newcount] = dirname;
-	      else
-		{
-		  pglob->gl_pathv[newcount] = strdup (dirname);
-		  if (pglob->gl_pathv[newcount] == NULL)
-		    goto nospace;
-		}
-	    }
-	  pglob->gl_pathv[++newcount] = NULL;
-	  ++pglob->gl_pathc;
-	  pglob->gl_flags = flags;
-
-	  return 0;
-	}
+            {
+            nospace:
+              free (pglob->gl_pathv);
+              pglob->gl_pathv = NULL;
+              pglob->gl_pathc = 0;
+              retval = GLOB_NOSPACE;
+              goto out;
+            }
+
+          new_gl_pathv = realloc (pglob->gl_pathv,
+                                  (newcount + 2) * sizeof (char *));
+          if (new_gl_pathv == NULL)
+            goto nospace;
+          pglob->gl_pathv = new_gl_pathv;
+
+          if (flags & GLOB_MARK)
+            {
+              char *p;
+              pglob->gl_pathv[newcount] = malloc (dirlen + 2);
+              if (pglob->gl_pathv[newcount] == NULL)
+                goto nospace;
+              p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
+              p[0] = '/';
+              p[1] = '\0';
+              if (__glibc_unlikely (malloc_dirname))
+                free (dirname);
+            }
+          else
+            {
+              if (__glibc_unlikely (malloc_dirname))
+                pglob->gl_pathv[newcount] = dirname;
+              else
+                {
+                  pglob->gl_pathv[newcount] = strdup (dirname);
+                  if (pglob->gl_pathv[newcount] == NULL)
+                    goto nospace;
+                }
+            }
+          pglob->gl_pathv[++newcount] = NULL;
+          ++pglob->gl_pathc;
+          pglob->gl_flags = flags;
+
+          return 0;
+        }
 
       /* Not found.  */
       retval = GLOB_NOMATCH;
@@ -1011,136 +1071,136 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
   if (meta & 5)
     {
       /* The directory name contains metacharacters, so we
-	 have to glob for the directory, and then glob for
-	 the pattern in each directory found.  */
+         have to glob for the directory, and then glob for
+         the pattern in each directory found.  */
       size_t i;
 
       if (!(flags & GLOB_NOESCAPE) && dirlen > 0 && dirname[dirlen - 1] == '\\')
-	{
-	  /* "foo\\/bar".  Remove the final backslash from dirname
-	     if it has not been quoted.  */
-	  char *p = (char *) &dirname[dirlen - 1];
+        {
+          /* "foo\\/bar".  Remove the final backslash from dirname
+             if it has not been quoted.  */
+          char *p = (char *) &dirname[dirlen - 1];
 
-	  while (p > dirname && p[-1] == '\\') --p;
-	  if ((&dirname[dirlen] - p) & 1)
-	    *(char *) &dirname[--dirlen] = '\0';
-	}
+          while (p > dirname && p[-1] == '\\') --p;
+          if ((&dirname[dirlen] - p) & 1)
+            *(char *) &dirname[--dirlen] = '\0';
+        }
 
       if (__glibc_unlikely ((flags & GLOB_ALTDIRFUNC) != 0))
-	{
-	  /* Use the alternative access functions also in the recursive
-	     call.  */
-	  dirs.gl_opendir = pglob->gl_opendir;
-	  dirs.gl_readdir = pglob->gl_readdir;
-	  dirs.gl_closedir = pglob->gl_closedir;
-	  dirs.gl_stat = pglob->gl_stat;
-	  dirs.gl_lstat = pglob->gl_lstat;
-	}
+        {
+          /* Use the alternative access functions also in the recursive
+             call.  */
+          dirs.gl_opendir = pglob->gl_opendir;
+          dirs.gl_readdir = pglob->gl_readdir;
+          dirs.gl_closedir = pglob->gl_closedir;
+          dirs.gl_stat = pglob->gl_stat;
+          dirs.gl_lstat = pglob->gl_lstat;
+        }
 
       status = glob (dirname,
-		     ((flags & (GLOB_ERR | GLOB_NOESCAPE
-				| GLOB_ALTDIRFUNC))
-		      | GLOB_NOSORT | GLOB_ONLYDIR),
-		     errfunc, &dirs);
+                     ((flags & (GLOB_ERR | GLOB_NOESCAPE
+                                | GLOB_ALTDIRFUNC))
+                      | GLOB_NOSORT | GLOB_ONLYDIR),
+                     errfunc, &dirs);
       if (status != 0)
-	{
-	  if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
-	    {
-	      retval = status;
-	      goto out;
-	    }
-	  goto no_matches;
-	}
+        {
+          if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
+            {
+              retval = status;
+              goto out;
+            }
+          goto no_matches;
+        }
 
       /* We have successfully globbed the preceding directory name.
-	 For each name we found, call glob_in_dir on it and FILENAME,
-	 appending the results to PGLOB.  */
+         For each name we found, call glob_in_dir on it and FILENAME,
+         appending the results to PGLOB.  */
       for (i = 0; i < dirs.gl_pathc; ++i)
-	{
-	  size_t old_pathc;
-
-	  old_pathc = pglob->gl_pathc;
-	  status = glob_in_dir (filename, dirs.gl_pathv[i],
-				((flags | GLOB_APPEND)
-				 & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
-				errfunc, pglob, alloca_used);
-	  if (status == GLOB_NOMATCH)
-	    /* No matches in this directory.  Try the next.  */
-	    continue;
-
-	  if (status != 0)
-	    {
-	      globfree (&dirs);
-	      globfree (pglob);
-	      pglob->gl_pathc = 0;
-	      retval = status;
-	      goto out;
-	    }
-
-	  /* Stick the directory on the front of each name.  */
-	  if (prefix_array (dirs.gl_pathv[i],
-			    &pglob->gl_pathv[old_pathc + pglob->gl_offs],
-			    pglob->gl_pathc - old_pathc))
-	    {
-	      globfree (&dirs);
-	      globfree (pglob);
-	      pglob->gl_pathc = 0;
-	      retval = GLOB_NOSPACE;
-	      goto out;
-	    }
-	}
+        {
+          size_t old_pathc;
+
+          old_pathc = pglob->gl_pathc;
+          status = glob_in_dir (filename, dirs.gl_pathv[i],
+                                ((flags | GLOB_APPEND)
+                                 & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
+                                errfunc, pglob, alloca_used);
+          if (status == GLOB_NOMATCH)
+            /* No matches in this directory.  Try the next.  */
+            continue;
+
+          if (status != 0)
+            {
+              globfree (&dirs);
+              globfree (pglob);
+              pglob->gl_pathc = 0;
+              retval = status;
+              goto out;
+            }
+
+          /* Stick the directory on the front of each name.  */
+          if (prefix_array (dirs.gl_pathv[i],
+                            &pglob->gl_pathv[old_pathc + pglob->gl_offs],
+                            pglob->gl_pathc - old_pathc))
+            {
+              globfree (&dirs);
+              globfree (pglob);
+              pglob->gl_pathc = 0;
+              retval = GLOB_NOSPACE;
+              goto out;
+            }
+        }
 
       flags |= GLOB_MAGCHAR;
 
-      /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
-	 But if we have not found any matching entry and the GLOB_NOCHECK
-	 flag was set we must return the input pattern itself.  */
+      /* We have ignored the GLOB_NOCHECK flag in the 'glob_in_dir' calls.
+         But if we have not found any matching entry and the GLOB_NOCHECK
+         flag was set we must return the input pattern itself.  */
       if (pglob->gl_pathc + pglob->gl_offs == oldcount)
-	{
-	no_matches:
-	  /* No matches.  */
-	  if (flags & GLOB_NOCHECK)
-	    {
-	      size_t newcount = pglob->gl_pathc + pglob->gl_offs;
-	      char **new_gl_pathv;
-
-	      if (newcount > SIZE_MAX / sizeof (char *) - 2)
-		{
-		nospace2:
-		  globfree (&dirs);
-		  retval = GLOB_NOSPACE;
-		  goto out;
-		}
-
-	      new_gl_pathv = realloc (pglob->gl_pathv,
-				      (newcount + 2) * sizeof (char *));
-	      if (new_gl_pathv == NULL)
-		goto nospace2;
-	      pglob->gl_pathv = new_gl_pathv;
-
-	      pglob->gl_pathv[newcount] = strdup (pattern);
-	      if (pglob->gl_pathv[newcount] == NULL)
-		{
-		  globfree (&dirs);
-		  globfree (pglob);
-		  pglob->gl_pathc = 0;
-		  retval = GLOB_NOSPACE;
-		  goto out;
-		}
-
-	      ++pglob->gl_pathc;
-	      ++newcount;
-
-	      pglob->gl_pathv[newcount] = NULL;
-	      pglob->gl_flags = flags;
-	    }
-	  else
-	    {
-	      globfree (&dirs);
-	      retval = GLOB_NOMATCH;
-	      goto out;
-	    }
-	}
+        {
+        no_matches:
+          /* No matches.  */
+          if (flags & GLOB_NOCHECK)
+            {
+              size_t newcount = pglob->gl_pathc + pglob->gl_offs;
+              char **new_gl_pathv;
+
+              if (newcount > SIZE_MAX / sizeof (char *) - 2)
+                {
+                nospace2:
+                  globfree (&dirs);
+                  retval = GLOB_NOSPACE;
+                  goto out;
+                }
+
+              new_gl_pathv = realloc (pglob->gl_pathv,
+                                      (newcount + 2) * sizeof (char *));
+              if (new_gl_pathv == NULL)
+                goto nospace2;
+              pglob->gl_pathv = new_gl_pathv;
+
+              pglob->gl_pathv[newcount] = strdup (pattern);
+              if (pglob->gl_pathv[newcount] == NULL)
+                {
+                  globfree (&dirs);
+                  globfree (pglob);
+                  pglob->gl_pathc = 0;
+                  retval = GLOB_NOSPACE;
+                  goto out;
+                }
+
+              ++pglob->gl_pathc;
+              ++newcount;
+
+              pglob->gl_pathv[newcount] = NULL;
+              pglob->gl_flags = flags;
+            }
+          else
+            {
+              globfree (&dirs);
+              retval = GLOB_NOMATCH;
+              goto out;
+            }
+        }
 
       globfree (&dirs);
     }
@@ -1150,57 +1210,57 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
       int orig_flags = flags;
 
       if (meta & 2)
-	{
-	  char *p = strchr (dirname, '\\'), *q;
-	  /* We need to unescape the dirname string.  It is certainly
-	     allocated by alloca, as otherwise filename would be NULL
-	     or dirname wouldn't contain backslashes.  */
-	  q = p;
-	  do
-	    {
-	      if (*p == '\\')
-		{
-		  *q = *++p;
-		  --dirlen;
-		}
-	      else
-		*q = *p;
-	      ++q;
-	    }
-	  while (*p++ != '\0');
-	  dirname_modified = 1;
-	}
+        {
+          char *p = strchr (dirname, '\\'), *q;
+          /* We need to unescape the dirname string.  It is certainly
+             allocated by alloca, as otherwise filename would be NULL
+             or dirname wouldn't contain backslashes.  */
+          q = p;
+          do
+            {
+              if (*p == '\\')
+                {
+                  *q = *++p;
+                  --dirlen;
+                }
+              else
+                *q = *p;
+              ++q;
+            }
+          while (*p++ != '\0');
+          dirname_modified = 1;
+        }
       if (dirname_modified)
-	flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
+        flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
       status = glob_in_dir (filename, dirname, flags, errfunc, pglob,
-			    alloca_used);
+                            alloca_used);
       if (status != 0)
-	{
-	  if (status == GLOB_NOMATCH && flags != orig_flags
-	      && pglob->gl_pathc + pglob->gl_offs == oldcount)
-	    {
-	      /* Make sure globfree (&dirs); is a nop.  */
-	      dirs.gl_pathv = NULL;
-	      flags = orig_flags;
-	      goto no_matches;
-	    }
-	  retval = status;
-	  goto out;
-	}
+        {
+          if (status == GLOB_NOMATCH && flags != orig_flags
+              && pglob->gl_pathc + pglob->gl_offs == oldcount)
+            {
+              /* Make sure globfree (&dirs); is a nop.  */
+              dirs.gl_pathv = NULL;
+              flags = orig_flags;
+              goto no_matches;
+            }
+          retval = status;
+          goto out;
+        }
 
       if (dirlen > 0)
-	{
-	  /* Stick the directory on the front of each name.  */
-	  if (prefix_array (dirname,
-			    &pglob->gl_pathv[old_pathc + pglob->gl_offs],
-			    pglob->gl_pathc - old_pathc))
-	    {
-	      globfree (pglob);
-	      pglob->gl_pathc = 0;
-	      retval = GLOB_NOSPACE;
-	      goto out;
-	    }
-	}
+        {
+          /* Stick the directory on the front of each name.  */
+          if (prefix_array (dirname,
+                            &pglob->gl_pathv[old_pathc + pglob->gl_offs],
+                            pglob->gl_pathc - old_pathc))
+            {
+              globfree (pglob);
+              pglob->gl_pathc = 0;
+              retval = GLOB_NOSPACE;
+              goto out;
+            }
+        }
     }
 
   if (flags & GLOB_MARK)
@@ -1211,32 +1271,32 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
       struct_stat64 st64;
 
       for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i)
-	if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
-	     ? ((*pglob->gl_stat) (pglob->gl_pathv[i], &st) == 0
-		&& S_ISDIR (st.st_mode))
-	     : (__stat64 (pglob->gl_pathv[i], &st64) == 0
-		&& S_ISDIR (st64.st_mode))))
-	  {
-	    size_t len = strlen (pglob->gl_pathv[i]) + 2;
-	    char *new = realloc (pglob->gl_pathv[i], len);
-	    if (new == NULL)
-	      {
-		globfree (pglob);
-		pglob->gl_pathc = 0;
-		retval = GLOB_NOSPACE;
-		goto out;
-	      }
-	    strcpy (&new[len - 2], "/");
-	    pglob->gl_pathv[i] = new;
-	  }
+        if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
+             ? ((*pglob->gl_stat) (pglob->gl_pathv[i], &st) == 0
+                && S_ISDIR (st.st_mode))
+             : (__stat64 (pglob->gl_pathv[i], &st64) == 0
+                && S_ISDIR (st64.st_mode))))
+          {
+            size_t len = strlen (pglob->gl_pathv[i]) + 2;
+            char *new = realloc (pglob->gl_pathv[i], len);
+            if (new == NULL)
+              {
+                globfree (pglob);
+                pglob->gl_pathc = 0;
+                retval = GLOB_NOSPACE;
+                goto out;
+              }
+            strcpy (&new[len - 2], "/");
+            pglob->gl_pathv[i] = new;
+          }
     }
 
   if (!(flags & GLOB_NOSORT))
     {
       /* Sort the vector.  */
       qsort (&pglob->gl_pathv[oldcount],
-	     pglob->gl_pathc + pglob->gl_offs - oldcount,
-	     sizeof (char *), collated_compare);
+             pglob->gl_pathc + pglob->gl_offs - oldcount,
+             sizeof (char *), collated_compare);
     }
 
  out:
@@ -1276,28 +1336,43 @@ prefix_array (const char *dirname, char **array, size_t n)
 {
   size_t i;
   size_t dirlen = strlen (dirname);
-# define DIRSEP_CHAR '/'
+  char dirsep_char = '/';
 
   if (dirlen == 1 && dirname[0] == '/')
     /* DIRNAME is just "/", so normal prepending would get us "//foo".
        We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
     dirlen = 0;
 
+#if defined __MSDOS__ || defined WINDOWS32
+  if (dirlen > 1)
+    {
+      if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
+        /* DIRNAME is "d:/".  Don't prepend the slash from DIRNAME.  */
+        --dirlen;
+      else if (dirname[dirlen - 1] == ':')
+        {
+          /* DIRNAME is "d:".  Use ':' instead of '/'.  */
+          --dirlen;
+          dirsep_char = ':';
+        }
+    }
+#endif
+
   for (i = 0; i < n; ++i)
     {
       size_t eltlen = strlen (array[i]) + 1;
       char *new = malloc (dirlen + 1 + eltlen);
       if (new == NULL)
-	{
-	  while (i > 0)
-	    free (array[--i]);
-	  return 1;
-	}
+        {
+          while (i > 0)
+            free (array[--i]);
+          return 1;
+        }
 
       {
-	char *endp = mempcpy (new, dirname, dirlen);
-	*endp++ = DIRSEP_CHAR;
-	mempcpy (endp, array[i], eltlen);
+        char *endp = mempcpy (new, dirname, dirlen);
+        *endp++ = dirsep_char;
+        mempcpy (endp, array[i], eltlen);
       }
       free (array[i]);
       array[i] = new;
@@ -1311,21 +1386,18 @@ prefix_array (const char *dirname, char **array, size_t n)
 static int
 __attribute_noinline__
 link_stat (const char *dir, size_t dirlen, const char *fname,
-	       glob_t *pglob
-# ifndef _LIBC
-		, int flags
+           glob_t *pglob
+# if !defined _LIBC && !HAVE_FSTATAT
+           , int flags
 # endif
-		)
+           )
 {
   size_t fnamelen = strlen (fname);
-  char *fullname = (char *) __alloca (dirlen + 1 + fnamelen + 1);
+  char *fullname = __alloca (dirlen + 1 + fnamelen + 1);
   struct stat st;
-# ifndef _LIBC
-  struct_stat64 st64;
-# endif
 
   mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1),
-	   fname, fnamelen + 1);
+           fname, fnamelen + 1);
 
 # if !defined _LIBC && !HAVE_FSTATAT
   if (__builtin_expect ((flags & GLOB_ALTDIRFUNC) == 0, 1))
@@ -1359,167 +1431,169 @@ link_exists_p (int dfd, const char *dir, size_t dirlen, const char *fname,
   return status == 0 || errno == EOVERFLOW;
 }
 
-/* Like `glob', but PATTERN is a final pathname component,
+/* Like 'glob', but PATTERN is a final pathname component,
    and matches are searched for in DIRECTORY.
    The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
    The GLOB_APPEND flag is assumed to be set (always appends).  */
 static int
 glob_in_dir (const char *pattern, const char *directory, int flags,
-	     int (*errfunc) (const char *, int),
-	     glob_t *pglob, size_t alloca_used)
+             int (*errfunc) (const char *, int),
+             glob_t *pglob, size_t alloca_used)
 {
   size_t dirlen = strlen (directory);
   void *stream = NULL;
-  struct globnames
-    {
-      struct globnames *next;
-      size_t count;
-      char *name[64];
-    };
-#define INITIAL_COUNT sizeof (init_names.name) / sizeof (init_names.name[0])
-  struct globnames init_names;
-  struct globnames *names = &init_names;
-  struct globnames *names_alloca = &init_names;
+# define GLOBNAMES_MEMBERS(nnames) \
+    struct globnames *next; size_t count; char *name[nnames];
+  struct globnames { GLOBNAMES_MEMBERS (FLEXIBLE_ARRAY_MEMBER) };
+  struct { GLOBNAMES_MEMBERS (64) } init_names_buf;
+  struct globnames *init_names = (struct globnames *) &init_names_buf;
+  struct globnames *names = init_names;
+  struct globnames *names_alloca = init_names;
   size_t nfound = 0;
   size_t cur = 0;
   int meta;
   int save;
   int result;
 
-  alloca_used += sizeof (init_names);
+  alloca_used += sizeof init_names_buf;
 
-  init_names.next = NULL;
-  init_names.count = INITIAL_COUNT;
+  init_names->next = NULL;
+  init_names->count = ((sizeof init_names_buf
+                        - offsetof (struct globnames, name))
+                       / sizeof init_names->name[0]);
 
   meta = __glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE));
   if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
     {
       /* We need not do any tests.  The PATTERN contains no meta
-	 characters and we must not return an error therefore the
-	 result will always contain exactly one name.  */
+         characters and we must not return an error therefore the
+         result will always contain exactly one name.  */
       flags |= GLOB_NOCHECK;
     }
   else if (meta == 0)
     {
       /* Since we use the normal file functions we can also use stat()
-	 to verify the file is there.  */
+         to verify the file is there.  */
       union
       {
-	struct stat st;
-	struct_stat64 st64;
+        struct stat st;
+        struct_stat64 st64;
       } ust;
       size_t patlen = strlen (pattern);
       size_t fullsize;
       bool alloca_fullname
-	= (! size_add_wrapv (dirlen + 1, patlen + 1, &fullsize)
-	   && glob_use_alloca (alloca_used, fullsize));
+        = (! size_add_wrapv (dirlen + 1, patlen + 1, &fullsize)
+           && glob_use_alloca (alloca_used, fullsize));
       char *fullname;
       if (alloca_fullname)
-	fullname = alloca_account (fullsize, alloca_used);
+        fullname = alloca_account (fullsize, alloca_used);
       else
-	{
-	  fullname = malloc (fullsize);
-	  if (fullname == NULL)
-	    return GLOB_NOSPACE;
-	}
+        {
+          fullname = malloc (fullsize);
+          if (fullname == NULL)
+            return GLOB_NOSPACE;
+        }
 
       mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
-			"/", 1),
-	       pattern, patlen + 1);
+                        "/", 1),
+               pattern, patlen + 1);
       if (((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
-	   ? (*pglob->gl_stat) (fullname, &ust.st)
-	   : __stat64 (fullname, &ust.st64))
-	  == 0)
-	  || errno == EOVERFLOW)
-	/* We found this file to be existing.  Now tell the rest
-	   of the function to copy this name into the result.  */
-	flags |= GLOB_NOCHECK;
+            ? (*pglob->gl_stat) (fullname, &ust.st)
+            : __stat64 (fullname, &ust.st64))
+           == 0)
+          || errno == EOVERFLOW)
+        /* We found this file to be existing.  Now tell the rest
+           of the function to copy this name into the result.  */
+        flags |= GLOB_NOCHECK;
 
       if (__glibc_unlikely (!alloca_fullname))
-	free (fullname);
+        free (fullname);
     }
   else
     {
       stream = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
-		? (*pglob->gl_opendir) (directory)
-		: opendir (directory));
+                ? (*pglob->gl_opendir) (directory)
+                : opendir (directory));
       if (stream == NULL)
-	{
-	  if (errno != ENOTDIR
-	      && ((errfunc != NULL && (*errfunc) (directory, errno))
-		  || (flags & GLOB_ERR)))
-	    return GLOB_ABORTED;
-	}
+        {
+          if (errno != ENOTDIR
+              && ((errfunc != NULL && (*errfunc) (directory, errno))
+                  || (flags & GLOB_ERR)))
+            return GLOB_ABORTED;
+        }
       else
-	{
-	  int dfd = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
-		     ? -1 : dirfd ((DIR *) stream));
-	  int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
-			   | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
-	  flags |= GLOB_MAGCHAR;
-
-	  while (1)
-	    {
-	      struct readdir_result d;
-	      {
-		if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
-		  d = convert_dirent (GL_READDIR (pglob, stream));
-		else
-		  {
+        {
+          int dfd = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
+                     ? -1 : dirfd ((DIR *) stream));
+          int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
+                           | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
+          flags |= GLOB_MAGCHAR;
+
+          while (1)
+            {
+              struct readdir_result d;
+              {
+                if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
+                  d = convert_dirent (GL_READDIR (pglob, stream));
+                else
+                  {
 #ifdef COMPILE_GLOB64
-		    d = convert_dirent (__readdir (stream));
+                    d = convert_dirent (__readdir (stream));
 #else
-		    d = convert_dirent64 (__readdir64 (stream));
+                    d = convert_dirent64 (__readdir64 (stream));
 #endif
-		  }
-	      }
-	      if (d.name == NULL)
-		break;
-	      if (d.skip_entry)
-		continue;
-
-	      /* If we shall match only directories use the information
-		 provided by the dirent call if possible.  */
-	      if ((flags & GLOB_ONLYDIR) && !readdir_result_might_be_dir (d))
-		continue;
-
-	      if (fnmatch (pattern, d.name, fnm_flags) == 0)
-		{
-		  /* If the file we found is a symlink we have to
-		     make sure the target file exists.  */
-		  if (!readdir_result_might_be_symlink (d)
-		      || link_exists_p (dfd, directory, dirlen, d.name,
-					pglob, flags))
-		    {
-		      if (cur == names->count)
-			{
-			  struct globnames *newnames;
-			  size_t count = names->count * 2;
-			  size_t size = (sizeof (struct globnames)
-					 + ((count - INITIAL_COUNT)
-					    * sizeof (char *)));
-			  if (glob_use_alloca (alloca_used, size))
-			    newnames = names_alloca
-			      = alloca_account (size, alloca_used);
-			  else if ((newnames = malloc (size))
-				   == NULL)
-			    goto memory_error;
-			  newnames->count = count;
-			  newnames->next = names;
-			  names = newnames;
-			  cur = 0;
-			}
-		      names->name[cur] = strdup (d.name);
-		      if (names->name[cur] == NULL)
-			goto memory_error;
-		      ++cur;
-		      ++nfound;
-		      if (SIZE_MAX - pglob->gl_offs <= nfound)
-			goto memory_error;
-		    }
-		}
-	    }
-	}
+                  }
+              }
+              if (d.name == NULL)
+                break;
+              if (d.skip_entry)
+                continue;
+
+              /* If we shall match only directories use the information
+                 provided by the dirent call if possible.  */
+              if ((flags & GLOB_ONLYDIR) && !readdir_result_might_be_dir (d))
+                continue;
+
+              if (fnmatch (pattern, d.name, fnm_flags) == 0)
+                {
+                  /* If the file we found is a symlink we have to
+                     make sure the target file exists.  */
+                  if (!readdir_result_might_be_symlink (d)
+                      || link_exists_p (dfd, directory, dirlen, d.name,
+                                        pglob, flags))
+                    {
+                      if (cur == names->count)
+                        {
+                          struct globnames *newnames;
+                          size_t count = names->count * 2;
+                          size_t nameoff = offsetof (struct globnames, name);
+                          size_t size = FLEXSIZEOF (struct globnames, name,
+                                                    count * sizeof (char *));
+                          if ((SIZE_MAX - nameoff) / 2 / sizeof (char *)
+                              < names->count)
+                            goto memory_error;
+                          if (glob_use_alloca (alloca_used, size))
+                            newnames = names_alloca
+                              = alloca_account (size, alloca_used);
+                          else if ((newnames = malloc (size))
+                                   == NULL)
+                            goto memory_error;
+                          newnames->count = count;
+                          newnames->next = names;
+                          names = newnames;
+                          cur = 0;
+                        }
+                      names->name[cur] = strdup (d.name);
+                      if (names->name[cur] == NULL)
+                        goto memory_error;
+                      ++cur;
+                      ++nfound;
+                      if (SIZE_MAX - pglob->gl_offs <= nfound)
+                        goto memory_error;
+                    }
+                }
+            }
+        }
     }
 
   if (nfound == 0 && (flags & GLOB_NOCHECK))
@@ -1528,7 +1602,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
       nfound = 1;
       names->name[cur] = malloc (len + 1);
       if (names->name[cur] == NULL)
-	goto memory_error;
+        goto memory_error;
       *((char *) mempcpy (names->name[cur++], pattern, len)) = '\0';
     }
 
@@ -1540,81 +1614,79 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
 
       if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc
           < pglob->gl_offs + nfound + 1)
-	goto memory_error;
+        goto memory_error;
 
       new_gl_pathv
-	= realloc (pglob->gl_pathv,
-		   (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
-		    * sizeof (char *));
+        = realloc (pglob->gl_pathv,
+                   (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
+                    * sizeof (char *));
 
       if (new_gl_pathv == NULL)
-	{
-	memory_error:
-	  while (1)
-	    {
-	      struct globnames *old = names;
-	      size_t i;
-	      for (i = 0; i < cur; ++i)
-		free (names->name[i]);
-	      names = names->next;
-	      /* NB: we will not leak memory here if we exit without
-		 freeing the current block assigned to OLD.  At least
-		 the very first block is always allocated on the stack
-		 and this is the block assigned to OLD here.  */
-	      if (names == NULL)
-		{
-		  assert (old == &init_names);
-		  break;
-		}
-	      cur = names->count;
-	      if (old == names_alloca)
-		names_alloca = names;
-	      else
-		free (old);
-	    }
-	  result = GLOB_NOSPACE;
-	}
+        {
+        memory_error:
+          while (1)
+            {
+              struct globnames *old = names;
+              for (size_t i = 0; i < cur; ++i)
+                free (names->name[i]);
+              names = names->next;
+              /* NB: we will not leak memory here if we exit without
+                 freeing the current block assigned to OLD.  At least
+                 the very first block is always allocated on the stack
+                 and this is the block assigned to OLD here.  */
+              if (names == NULL)
+                {
+                  assert (old == init_names);
+                  break;
+                }
+              cur = names->count;
+              if (old == names_alloca)
+                names_alloca = names;
+              else
+                free (old);
+            }
+          result = GLOB_NOSPACE;
+        }
       else
-	{
-	  while (1)
-	    {
-	      struct globnames *old = names;
-	      size_t i;
-	      for (i = 0; i < cur; ++i)
-		new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++]
-		  = names->name[i];
-	      names = names->next;
-	      /* NB: we will not leak memory here if we exit without
-		 freeing the current block assigned to OLD.  At least
-		 the very first block is always allocated on the stack
-		 and this is the block assigned to OLD here.  */
-	      if (names == NULL)
-		{
-		  assert (old == &init_names);
-		  break;
-		}
-	      cur = names->count;
-	      if (old == names_alloca)
-		names_alloca = names;
-	      else
-		free (old);
-	    }
-
-	  pglob->gl_pathv = new_gl_pathv;
-
-	  pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
-
-	  pglob->gl_flags = flags;
-	}
+        {
+          while (1)
+            {
+              struct globnames *old = names;
+              for (size_t i = 0; i < cur; ++i)
+                new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++]
+                  = names->name[i];
+              names = names->next;
+              /* NB: we will not leak memory here if we exit without
+                 freeing the current block assigned to OLD.  At least
+                 the very first block is always allocated on the stack
+                 and this is the block assigned to OLD here.  */
+              if (names == NULL)
+                {
+                  assert (old == init_names);
+                  break;
+                }
+              cur = names->count;
+              if (old == names_alloca)
+                names_alloca = names;
+              else
+                free (old);
+            }
+
+          pglob->gl_pathv = new_gl_pathv;
+
+          pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+
+          pglob->gl_flags = flags;
+        }
     }
 
   if (stream != NULL)
     {
       save = errno;
       if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
-	(*pglob->gl_closedir) (stream);
+        (*pglob->gl_closedir) (stream);
       else
-	closedir (stream);
+        closedir (stream);
       __set_errno (save);
     }
 
diff --git a/posix/glob.h b/posix/glob.h
index b5bd9ac189..bd413bc457 100644
--- a/posix/glob.h
+++ b/posix/glob.h
@@ -15,60 +15,52 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#ifndef	_GLOB_H
-#define	_GLOB_H	1
+#ifndef _GLOB_H
+#define _GLOB_H 1
 
-#include <sys/cdefs.h>
+#ifndef __GLOB_GNULIB
+# include <sys/cdefs.h>
+#endif
 
 __BEGIN_DECLS
 
-/* We need `size_t' for the following definitions.  */
-#ifndef __size_t
-typedef __SIZE_TYPE__ __size_t;
-# if defined __USE_XOPEN || defined __USE_XOPEN2K8
-typedef __SIZE_TYPE__ size_t;
-# endif
-#else
-/* The GNU CC stddef.h version defines __size_t as empty.  We need a real
-   definition.  */
-# undef __size_t
-# define __size_t size_t
-#endif
+#define __need_size_t
+#include <stddef.h>
 
-/* Bits set in the FLAGS argument to `glob'.  */
-#define	GLOB_ERR	(1 << 0)/* Return on read errors.  */
-#define	GLOB_MARK	(1 << 1)/* Append a slash to each name.  */
-#define	GLOB_NOSORT	(1 << 2)/* Don't sort the names.  */
-#define	GLOB_DOOFFS	(1 << 3)/* Insert PGLOB->gl_offs NULLs.  */
-#define	GLOB_NOCHECK	(1 << 4)/* If nothing matches, return the pattern.  */
-#define	GLOB_APPEND	(1 << 5)/* Append to results of a previous call.  */
-#define	GLOB_NOESCAPE	(1 << 6)/* Backslashes don't quote metacharacters.  */
-#define	GLOB_PERIOD	(1 << 7)/* Leading `.' can be matched by metachars.  */
+/* Bits set in the FLAGS argument to 'glob'.  */
+#define GLOB_ERR        (1 << 0)/* Return on read errors.  */
+#define GLOB_MARK       (1 << 1)/* Append a slash to each name.  */
+#define GLOB_NOSORT     (1 << 2)/* Don't sort the names.  */
+#define GLOB_DOOFFS     (1 << 3)/* Insert PGLOB->gl_offs NULLs.  */
+#define GLOB_NOCHECK    (1 << 4)/* If nothing matches, return the pattern.  */
+#define GLOB_APPEND     (1 << 5)/* Append to results of a previous call.  */
+#define GLOB_NOESCAPE   (1 << 6)/* Backslashes don't quote metacharacters.  */
+#define GLOB_PERIOD     (1 << 7)/* Leading '.' can be matched by metachars.  */
 
 #if !defined __USE_POSIX2 || defined __USE_MISC
-# define GLOB_MAGCHAR	 (1 << 8)/* Set in gl_flags if any metachars seen.  */
+# define GLOB_MAGCHAR    (1 << 8)/* Set in gl_flags if any metachars seen.  */
 # define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions.  */
-# define GLOB_BRACE	 (1 << 10)/* Expand "{a,b}" to "a" "b".  */
-# define GLOB_NOMAGIC	 (1 << 11)/* If no magic chars, return the pattern.  */
-# define GLOB_TILDE	 (1 << 12)/* Expand ~user and ~ to home directories. */
-# define GLOB_ONLYDIR	 (1 << 13)/* Match only directories.  */
+# define GLOB_BRACE      (1 << 10)/* Expand "{a,b}" to "a" "b".  */
+# define GLOB_NOMAGIC    (1 << 11)/* If no magic chars, return the pattern.  */
+# define GLOB_TILDE      (1 << 12)/* Expand ~user and ~ to home directories. */
+# define GLOB_ONLYDIR    (1 << 13)/* Match only directories.  */
 # define GLOB_TILDE_CHECK (1 << 14)/* Like GLOB_TILDE but return an error
-				      if the user name is not available.  */
-# define __GLOB_FLAGS	(GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
-			 GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \
-			 GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE|     \
-			 GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK)
+                                      if the user name is not available.  */
+# define __GLOB_FLAGS   (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
+                         GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \
+                         GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE|     \
+                         GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK)
 #else
-# define __GLOB_FLAGS	(GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
-			 GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \
-			 GLOB_PERIOD)
+# define __GLOB_FLAGS   (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
+                         GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \
+                         GLOB_PERIOD)
 #endif
 
-/* Error returns from `glob'.  */
-#define	GLOB_NOSPACE	1	/* Ran out of memory.  */
-#define	GLOB_ABORTED	2	/* Read error.  */
-#define	GLOB_NOMATCH	3	/* No matches found.  */
-#define GLOB_NOSYS	4	/* Not implemented.  */
+/* Error returns from 'glob'.  */
+#define GLOB_NOSPACE    1       /* Ran out of memory.  */
+#define GLOB_ABORTED    2       /* Read error.  */
+#define GLOB_NOMATCH    3       /* No matches found.  */
+#define GLOB_NOSYS      4       /* Not implemented.  */
 #ifdef __USE_GNU
 /* Previous versions of this file defined GLOB_ABEND instead of
    GLOB_ABORTED.  Provide a compatibility definition here.  */
@@ -81,10 +73,10 @@ struct stat;
 #endif
 typedef struct
   {
-    __size_t gl_pathc;		/* Count of paths matched by the pattern.  */
-    char **gl_pathv;		/* List of matched pathnames.  */
-    __size_t gl_offs;		/* Slots to reserve in `gl_pathv'.  */
-    int gl_flags;		/* Set to FLAGS, maybe | GLOB_MAGCHAR.  */
+    size_t gl_pathc;          /* Count of paths matched by the pattern.  */
+    char **gl_pathv;            /* List of matched pathnames.  */
+    size_t gl_offs;           /* Slots to reserve in 'gl_pathv'.  */
+    int gl_flags;               /* Set to FLAGS, maybe | GLOB_MAGCHAR.  */
 
     /* If the GLOB_ALTDIRFUNC flag is set, the following functions
        are used instead of the normal file access functions.  */
@@ -110,9 +102,9 @@ struct stat64;
 # endif
 typedef struct
   {
-    __size_t gl_pathc;
+    size_t gl_pathc;
     char **gl_pathv;
-    __size_t gl_offs;
+    size_t gl_offs;
     int gl_flags;
 
     /* If the GLOB_ALTDIRFUNC flag is set, the following functions
@@ -138,30 +130,30 @@ typedef struct
    The bits defined above may be set in FLAGS.
    If a directory cannot be opened or read and ERRFUNC is not nil,
    it is called with the pathname that caused the error, and the
-   `errno' value from the failing call; if it returns non-zero
-   `glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
+   'errno' value from the failing call; if it returns non-zero
+   'glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
    If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
-   Otherwise, `glob' returns zero.  */
-#if !defined __USE_FILE_OFFSET64
+   Otherwise, 'glob' returns zero.  */
+#if !defined __USE_FILE_OFFSET64 || defined __GLOB_GNULIB
 extern int glob (const char *__restrict __pattern, int __flags,
-		 int (*__errfunc) (const char *, int),
-		 glob_t *__restrict __pglob) __THROW;
+                 int (*__errfunc) (const char *, int),
+                 glob_t *__restrict __pglob) __THROW;
 
-/* Free storage allocated in PGLOB by a previous `glob' call.  */
+/* Free storage allocated in PGLOB by a previous 'glob' call.  */
 extern void globfree (glob_t *__pglob) __THROW;
 #else
 extern int __REDIRECT_NTH (glob, (const char *__restrict __pattern,
-				  int __flags,
-				  int (*__errfunc) (const char *, int),
-				  glob_t *__restrict __pglob), glob64);
+                                  int __flags,
+                                  int (*__errfunc) (const char *, int),
+                                  glob_t *__restrict __pglob), glob64);
 
 extern void __REDIRECT_NTH (globfree, (glob_t *__pglob), globfree64);
 #endif
 
 #ifdef __USE_LARGEFILE64
 extern int glob64 (const char *__restrict __pattern, int __flags,
-		   int (*__errfunc) (const char *, int),
-		   glob64_t *__restrict __pglob) __THROW;
+                   int (*__errfunc) (const char *, int),
+                   glob64_t *__restrict __pglob) __THROW;
 
 extern void globfree64 (glob64_t *__pglob) __THROW;
 #endif
diff --git a/posix/glob_internal.h b/posix/glob_internal.h
index d989a98edf..12c93660b7 100644
--- a/posix/glob_internal.h
+++ b/posix/glob_internal.h
@@ -30,25 +30,25 @@ __glob_pattern_type (const char *pattern, int quote)
       {
       case '?':
       case '*':
-	return 1;
+        return 1;
 
       case '\\':
-	if (quote)
-	  {
-	    if (p[1] != '\0')
-	      ++p;
-	    ret |= 2;
-	  }
-	break;
+        if (quote)
+          {
+            if (p[1] != '\0')
+              ++p;
+            ret |= 2;
+          }
+        break;
 
       case '[':
-	ret |= 4;
-	break;
+        ret |= 4;
+        break;
 
       case ']':
-	if (ret & 4)
-	  return 1;
-	break;
+        if (ret & 4)
+          return 1;
+        break;
       }
 
   return ret;
diff --git a/posix/glob_pattern_p.c b/posix/glob_pattern_p.c
index 6e451f2b77..a17d337182 100644
--- a/posix/glob_pattern_p.c
+++ b/posix/glob_pattern_p.c
@@ -16,6 +16,10 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _LIBC
+# include <config.h>
+#endif
+
 #include <glob.h>
 #include "glob_internal.h"
 
diff --git a/posix/globfree.c b/posix/globfree.c
index 4ebd142faa..042e29d9b0 100644
--- a/posix/globfree.c
+++ b/posix/globfree.c
@@ -16,6 +16,10 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _LIBC
+# include <config.h>
+#endif
+
 #include <glob.h>
 #include <stdlib.h>
 
@@ -27,7 +31,7 @@ globfree (glob_t *pglob)
     {
       size_t i;
       for (i = 0; i < pglob->gl_pathc; ++i)
-	free (pglob->gl_pathv[pglob->gl_offs + i]);
+        free (pglob->gl_pathv[pglob->gl_offs + i]);
       free (pglob->gl_pathv);
       pglob->gl_pathv = NULL;
     }

Adhemerval Zanella Netto Aug. 30, 2017, 9:20 p.m. UTC | #2
On 23/08/2017 19:00, Paul Eggert wrote:
> Thanks for starting the ball rolling on this. I merged your changes into Gnulib and merged the result back into your proposed patchset, resulting in the attached followup patch which should make glibc and Gnulib identical in the respective files. Please take a look at it and revise the proposal accordingly. Most of the changes in this followup patch should be clear from its commit message. Some general comments:



Thanks for follows this up on gnulib side.  I think to simplify the
patch I will regenerate first part (posix: Sync glob with gnulib [BZ #1062])
again current gnulib just to avoid two patch where one should do it.

> 

> * The attached followup patch fixes what appears to be a glitch in your merge, which omitted part of glibc commit 44c637ce806cc41534e89117a93c41fd310e7e3f

> dated Thu Oct 20 10:04:41 2016 +0200. Please double-check this.


I will do it.

> 

> * For .c files shared with Gnulib, include <config.h> first in every .c file, when _LIBC is not defined.


Right.

> 

> * Avoid changing C99-style decl-after-statement to C89-style decl-then-statement.  Gnulib no longer requires this part of C89, and leaving the code alone shortens the patch and keeps the code more readable.


Ack.

> 

> * Fix some stray occurrences of grave accent that should be apostrophe.


Ack.

> 

> * White space should use spaces instead of tabs, and should follow GNU conventions for indenting.  This is the convention in Gnulib, and as it is allowed by glibc it will simplify integration if we use it in files shared with Gnulib.

> 

> * Avoid some white-space changes from what is in glibc now.

> 


I think it would be better to divide it in twofold: one patch to sync the code
changes from gnulib and another one to actually change the indentation.