diff --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
+ .
+
+ Written by Paul Eggert. */
+
+#include
+
+/* 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
. */
+#ifndef _LIBC
+# include
+#endif
+
#include
+
#include
#include
#include
@@ -23,13 +28,15 @@
#include
#include
#include
-
#include
-#if !defined POSIX && defined _POSIX_VERSION
-# define POSIX
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WINDOWS32
#endif
-#include
+#ifndef WINDOWS32
+# include
+#endif
#include
#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
+#include
#include
#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
. */
-#ifndef _GLOB_H
-#define _GLOB_H 1
+#ifndef _GLOB_H
+#define _GLOB_H 1
-#include
+#ifndef __GLOB_GNULIB
+# include
+#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
-/* 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
. */
+#ifndef _LIBC
+# include
+#endif
+
#include
#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
. */
+#ifndef _LIBC
+# include
+#endif
+
#include
#include
@@ -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;
}