>From 8256f693f56140a3f7cbaeb81bc82ed03916687a Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 23 Aug 2017 10:45:42 -0700 Subject: [PATCH 1/2] glob: merge from glibc with Zanella glob changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge glob from glibc, with changes for glob proposed by Adhemerval Zanella in the thread starting here: https://sourceware.org/ml/libc-alpha/2017-08/msg01079.html plus some fixes for this merge. * lib/flexmember.h: Change license wording to something that works unchanged in Glibc, since this code might be used in Glibc and this will minimize 'diff' output. * lib/glob_internal.h, lib/glob_pattern_p.c, lib/globfree.c: New files, ported from glibc. * lib/glob_pattern_p.c, lib/globfree.c, lib/glob.c [!_LIBC]: Include first. * lib/glob-libc.h (_Restrict_): Remove. All uses replaced with __restrict. (__size_t): Remove. All uses replaced by size_t. (size_t): Define by defining __need_size_t and including . This should work even in non-glibc platforms, where any name pollution is OK. Use __USE_MISC instead of __USE_BSD || __USE_GNU. (struct stat64): Don’t worry about __GLOB_GNULIB. (glob, globfree, glob_pattern_p): Remove macros for __USE_FILE_OFFSET64 && __GNUC__ < 2 && !defined __GLOB_GNULIB case. Remove _GL_ARG_NONNULL as GNU behavior is to accept NULL but set errno. * lib/glob.c (_GL_ARG_NONNULL) [!_LIBC]: Remove. All uses removed since the glibc behavior works on null pointers. Do not include stdio.h; old SunOS is irrelevant now. Do not worry about GLOB_ONLY_P as we now mimic glibc here. Include glob_internal.h. (D_INO_TO_RESULT): Depend on (_LIBC || D_INO_IN_DIRENT), not ((POSIX || WINDOWS32) && !__GNU_LIBRARY__). The latter probably worked only coincidentally. (attribute_hidden, __attribute_noinline__, __glibc_unlikely): Remove macros; now done in glob.in.h. (size_add_wrapv): Do not use __builtin_add_overflow if __ICC. (glob): Properly initialize glob structure with GLOB_BRACE|GLOB_DOOFFS (bug 20707). Remove old code using SHELL since Bash no longer uses this. (glob, prefix_array): Separate MS code better. (glob, glob_in_dir): Use C99 decls before statements when glibc does. (glob_in_dir): Remove old Amiga and VMS code. (globfree, __glob_pattern_type, __glob_pattern_p): Move to separate files. * lib/glob.in.h (attribute_hidden, __attribute_noinline__) (__glibc_unlikely): Move here from glob.c. (__restrict): New macro here, replacing the _Restrict_ in glob.c. (weak_alias): New macro. (__size_t): Remove. All uses replaced by size_t. * modules/d-ino (License): Now LGPLv2+, for compatibility with glob. * modules/flexmember (License): Now LGPLv2+, which it should have been anyway since flexmember.h is not unlimited-license. * modules/glob (Files): Add +lib/glob_internal.h, lib/glob_pattern_p.c, lib/globfree.c. (Depends-on): Remove snippet/arg-nonnull. --- ChangeLog | 53 +++++++++ lib/flexmember.h | 21 ++-- lib/glob-libc.h | 115 ++++++------------ lib/glob.c | 321 +++++++++++++-------------------------------------- lib/glob.in.h | 31 ++++- lib/glob_internal.h | 57 +++++++++ lib/glob_pattern_p.c | 33 ++++++ lib/globfree.c | 41 +++++++ modules/d-ino | 2 +- modules/flexmember | 2 +- modules/glob | 10 +- 11 files changed, 352 insertions(+), 334 deletions(-) create mode 100644 lib/glob_internal.h create mode 100644 lib/glob_pattern_p.c create mode 100644 lib/globfree.c diff --git a/ChangeLog b/ChangeLog index 3753cb2a5..4dddaae0b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,56 @@ +2017-08-23 Paul Eggert + + glob: merge from glibc with Zanella glob changes + Merge glob from glibc, with changes for glob proposed + by Adhemerval Zanella in the thread starting here: + https://sourceware.org/ml/libc-alpha/2017-08/msg01079.html + plus some fixes for this merge. + * lib/glob_internal.h, lib/glob_pattern_p.c, lib/globfree.c: + New files, ported from glibc. + * lib/glob-libc.h (_Restrict_): Remove. All uses replaced + with __restrict. + (__size_t): Remove. All uses replaced by size_t. + (size_t): Define by defining __need_size_t and including . + This should work even in non-glibc platforms, where any name + pollution is OK. + Use __USE_MISC instead of __USE_BSD || __USE_GNU. + (struct stat64): Don’t worry about __GLOB_GNULIB. + (glob, globfree, glob_pattern_p): Remove macros for + __USE_FILE_OFFSET64 && __GNUC__ < 2 && !defined __GLOB_GNULIB + case. Remove _GL_ARG_NONNULL as GNU behavior is to accept NULL + but set errno. + * lib/glob.c (_GL_ARG_NONNULL) [!_LIBC]: Remove. All uses + removed since the glibc behavior works on null pointers. + Do not include stdio.h; old SunOS is irrelevant now. + Do not worry about GLOB_ONLY_P as we now mimic glibc here. + Include glob_internal.h. + (D_INO_TO_RESULT): Depend on (_LIBC || D_INO_IN_DIRENT), not + ((POSIX || WINDOWS32) && !__GNU_LIBRARY__). The latter probably + worked only coincidentally. + (attribute_hidden, __attribute_noinline__, __glibc_unlikely): + Remove macros; now done in glob.in.h. + (size_add_wrapv): Do not use __builtin_add_overflow if __ICC. + (glob): Properly initialize glob structure with + GLOB_BRACE|GLOB_DOOFFS (bug 20707). + Remove old code using SHELL since Bash no longer + uses this. + (glob, prefix_array): Separate MS code better. + (glob, glob_in_dir): Use C99 decls before statements when glibc + does. + (glob_in_dir): Remove old Amiga and VMS code. + (globfree, __glob_pattern_type, __glob_pattern_p): Move to + separate files. + * lib/glob.in.h (attribute_hidden, __attribute_noinline__) + (__glibc_unlikely): + Move here from glob.c. + (__restrict): New macro here, replacing the _Restrict_ in glob.c. + (weak_alias): New macro. + (__size_t): Remove. All uses replaced by size_t. + * modules/d-ino (License): Now LGPLv2+, for compatibility with glob. + * modules/glob (Files): Add +lib/glob_internal.h, + lib/glob_pattern_p.c, lib/globfree.c. + (Depends-on): Remove snippet/arg-nonnull. + 2017-08-22 Paul Eggert glob: port to clang's Undefined Sanitizer diff --git a/lib/flexmember.h b/lib/flexmember.h index c71ea6510..ceca74c2c 100644 --- a/lib/flexmember.h +++ b/lib/flexmember.h @@ -2,18 +2,21 @@ Copyright 2016-2017 Free Software Foundation, Inc. - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + This file is part of the GNU C Library. - This program is distributed in the hope that it will be useful, + 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 General Public License for more details. + 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 General Public License - along with this program. If not, see . + 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. */ diff --git a/lib/glob-libc.h b/lib/glob-libc.h index d54043144..bd413bc45 100644 --- a/lib/glob-libc.h +++ b/lib/glob-libc.h @@ -1,19 +1,19 @@ -/* Copyright (C) 1991-1992, 1995-1998, 2000-2001, 2004-2007, 2009-2017 Free - Software Foundation, Inc. +/* Copyright (C) 1991-2017 Free Software Foundation, Inc. This file is part of the GNU C Library. - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + 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. - This program is distributed in the hope that it will be useful, + 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 General Public License for more details. + 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 General Public License - along with this program. If not, see . */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ #ifndef _GLOB_H #define _GLOB_H 1 @@ -22,42 +22,10 @@ # include #endif -/* GCC 2.95 and later have "__restrict"; C99 compilers have - "restrict", and "configure" may have defined "restrict". - Other compilers use __restrict, __restrict__, and _Restrict, and - 'configure' might #define 'restrict' to those words, so pick a - different name. */ -#ifndef _Restrict_ -# if 199901L <= __STDC_VERSION__ -# define _Restrict_ restrict -# elif 2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__) -# define _Restrict_ __restrict -# else -# define _Restrict_ -# endif -#endif - __BEGIN_DECLS -/* We need 'size_t' for the following definitions. */ -#ifndef __size_t -# if defined __GNUC__ && __GNUC__ >= 2 -typedef __SIZE_TYPE__ __size_t; -# ifdef __USE_XOPEN -typedef __SIZE_TYPE__ size_t; -# endif -# else -# include -# ifndef __size_t -# define __size_t size_t -# endif -# 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. */ @@ -69,7 +37,7 @@ typedef __SIZE_TYPE__ size_t; #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_BSD || defined __USE_GNU +#if !defined __USE_POSIX2 || defined __USE_MISC # 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". */ @@ -105,9 +73,9 @@ struct stat; #endif typedef struct { - __size_t gl_pathc; /* Count of paths matched by the pattern. */ + 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'. */ + 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 @@ -120,23 +88,23 @@ typedef struct #endif void *(*gl_opendir) (const char *); #ifdef __USE_GNU - int (*gl_lstat) (const char *_Restrict_, struct stat *_Restrict_); - int (*gl_stat) (const char *_Restrict_, struct stat *_Restrict_); + int (*gl_lstat) (const char *__restrict, struct stat *__restrict); + int (*gl_stat) (const char *__restrict, struct stat *__restrict); #else - int (*gl_lstat) (const char *_Restrict_, void *_Restrict_); - int (*gl_stat) (const char *_Restrict_, void *_Restrict_); + int (*gl_lstat) (const char *__restrict, void *__restrict); + int (*gl_stat) (const char *__restrict, void *__restrict); #endif } glob_t; -#if defined __USE_LARGEFILE64 && !defined __GLOB_GNULIB +#ifdef __USE_LARGEFILE64 # ifdef __USE_GNU 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 @@ -149,20 +117,15 @@ typedef struct # endif void *(*gl_opendir) (const char *); # ifdef __USE_GNU - int (*gl_lstat) (const char *_Restrict_, struct stat64 *_Restrict_); - int (*gl_stat) (const char *_Restrict_, struct stat64 *_Restrict_); + int (*gl_lstat) (const char *__restrict, struct stat64 *__restrict); + int (*gl_stat) (const char *__restrict, struct stat64 *__restrict); # else - int (*gl_lstat) (const char *_Restrict_, void *_Restrict_); - int (*gl_stat) (const char *_Restrict_, void *_Restrict_); + int (*gl_lstat) (const char *__restrict, void *__restrict); + int (*gl_stat) (const char *__restrict, void *__restrict); # endif } glob64_t; #endif -#if defined __USE_FILE_OFFSET64 && __GNUC__ < 2 && !defined __GLOB_GNULIB -# define glob glob64 -# define globfree globfree64 -#endif - /* Do glob searching for PATTERN, placing results in PGLOB. The bits defined above may be set in FLAGS. If a directory cannot be opened or read and ERRFUNC is not nil, @@ -171,29 +134,28 @@ typedef struct '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 || __GNUC__ < 2 || defined __GLOB_GNULIB -extern int glob (const char *_Restrict_ __pattern, int __flags, +#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 _GL_ARG_NONNULL ((1, 4)); + glob_t *__restrict __pglob) __THROW; /* Free storage allocated in PGLOB by a previous 'glob' call. */ -extern void globfree (glob_t *__pglob) __THROW _GL_ARG_NONNULL ((1)); +extern void globfree (glob_t *__pglob) __THROW; #else -extern int __REDIRECT_NTH (glob, (const char *_Restrict_ __pattern, +extern int __REDIRECT_NTH (glob, (const char *__restrict __pattern, int __flags, int (*__errfunc) (const char *, int), - glob_t *_Restrict_ __pglob), glob64); + glob_t *__restrict __pglob), glob64); extern void __REDIRECT_NTH (globfree, (glob_t *__pglob), globfree64); #endif -#if defined __USE_LARGEFILE64 && !defined __GLOB_GNULIB -extern int glob64 (const char *_Restrict_ __pattern, int __flags, +#ifdef __USE_LARGEFILE64 +extern int glob64 (const char *__restrict __pattern, int __flags, int (*__errfunc) (const char *, int), - glob64_t *_Restrict_ __pglob) - __THROW _GL_ARG_NONNULL ((1, 4)); + glob64_t *__restrict __pglob) __THROW; -extern void globfree64 (glob64_t *__pglob) __THROW _GL_ARG_NONNULL ((1)); +extern void globfree64 (glob64_t *__pglob) __THROW; #endif @@ -203,8 +165,7 @@ extern void globfree64 (glob64_t *__pglob) __THROW _GL_ARG_NONNULL ((1)); This function is not part of the interface specified by POSIX.2 but several programs want to use it. */ -extern int glob_pattern_p (const char *__pattern, int __quote) - __THROW _GL_ARG_NONNULL ((1)); +extern int glob_pattern_p (const char *__pattern, int __quote) __THROW; #endif __END_DECLS diff --git a/lib/glob.c b/lib/glob.c index 2a7cc8705..a4aa3d870 100644 --- a/lib/glob.c +++ b/lib/glob.c @@ -16,9 +16,6 @@ . */ #ifndef _LIBC -/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc - optimizes away the pattern == NULL || pglob == NULL tests below. */ -# define _GL_ARG_NONNULL(params) # include #endif @@ -30,19 +27,8 @@ #include #include #include - -/* Outcomment the following line for production quality code. */ -/* #define NDEBUG 1 */ #include - -#include /* Needed on stupid SunOS for assert. */ - -#ifndef GLOB_ONLY_P - #include -#if !defined POSIX && defined _POSIX_VERSION -# define POSIX -#endif #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ # define WINDOWS32 @@ -70,7 +56,7 @@ # 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) + __getpwnam_r (name, bufp, buf, len, res) # ifndef __stat64 # define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf) # endif @@ -91,7 +77,8 @@ #include -#include "flexmember.h" +#include +#include #ifdef _SC_GETPW_R_SIZE_MAX # define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX) @@ -111,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 @@ -134,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. */ @@ -152,15 +139,15 @@ 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 POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ +#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. */ @@ -171,8 +158,6 @@ readdir_result_might_be_dir (struct readdir_result d) D_INO_TO_RESULT (source) \ } -#endif /* !defined GLOB_ONLY_P */ - /* 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 @@ -190,11 +175,8 @@ convert_dirent (const struct dirent *source) struct readdir_result result = { NULL, }; return result; } - else - { - struct readdir_result result = READDIR_RESULT_INITIALIZER (source); - return result; - } + struct readdir_result result = READDIR_RESULT_INITIALIZER (source); + return result; } #ifndef COMPILE_GLOB64 @@ -208,31 +190,11 @@ convert_dirent64 (const struct dirent64 *source) struct readdir_result result = { NULL, }; return result; } - else - { - struct readdir_result result = READDIR_RESULT_INITIALIZER (source); - return result; - } + struct readdir_result result = READDIR_RESULT_INITIALIZER (source); + return result; } #endif - -#ifndef attribute_hidden -# define attribute_hidden -#endif - -#ifndef __attribute_noinline__ -# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 1) -# define __attribute_noinline__ /* Ignore */ -#else -# define __attribute_noinline__ __attribute__ ((__noinline__)) -# endif -#endif - -#ifndef __glibc_unlikely -# define __glibc_unlikely(expr) __builtin_expect (expr, 0) -#endif - #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, @@ -255,12 +217,12 @@ convert_dirent64 (const struct dirent64 *source) /* 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.. */ + bits of the correct answer. */ 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 *r = a + b; @@ -282,7 +244,6 @@ static int glob_in_dir (const char *pattern, const char *directory, extern int __glob_pattern_type (const char *pattern, int quote) attribute_hidden; -#ifndef GLOB_ONLY_P static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL; static int collated_compare (const void *, const void *) __THROWNL; @@ -311,7 +272,6 @@ next_brace_sub (const char *cp, int flags) return *cp != '\0' ? cp : NULL; } -#endif /* !defined GLOB_ONLY_P */ /* Do glob searching for PATTERN, placing results in PGLOB. The bits defined above may be set in FLAGS. @@ -356,6 +316,28 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), also makes all the code that uses gl_offs simpler. */ pglob->gl_offs = 0; + if (!(flags & GLOB_APPEND)) + { + pglob->gl_pathc = 0; + if (!(flags & GLOB_DOOFFS)) + pglob->gl_pathv = NULL; + else + { + size_t i; + + 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; + + for (i = 0; i <= pglob->gl_offs; ++i) + pglob->gl_pathv[i] = NULL; + } + } + if (flags & GLOB_BRACE) { const char *begin; @@ -385,7 +367,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (begin != NULL) { /* Allocate working buffer large enough for our work. Note that - we have at least an opening and closing brace. */ + we have at least an opening and closing brace. */ size_t firstc; char *alt_start; const char *p; @@ -401,14 +383,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), { onealt = malloc (pattern_len); if (onealt == NULL) - { - if (!(flags & GLOB_APPEND)) - { - pglob->gl_pathc = 0; - pglob->gl_pathv = NULL; - } - return GLOB_NOSPACE; - } + return GLOB_NOSPACE; } /* We know the prefix for all sub-patterns. */ @@ -423,7 +398,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), illegal_brace: if (__glibc_unlikely (!alloca_onealt)) free (onealt); - return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); + flags &= ~GLOB_BRACE; + goto no_brace; } /* Now find the end of the whole brace expression. */ @@ -444,14 +420,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), points past the final }. We will accumulate result names from recursive runs for each brace alternative in the buffer using GLOB_APPEND. */ - - if (!(flags & GLOB_APPEND)) - { - /* This call is to set a new vector, so clear out the - vector so we can append to it. */ - pglob->gl_pathc = 0; - pglob->gl_pathv = NULL; - } firstc = pglob->gl_pathc; p = begin + 1; @@ -499,31 +467,12 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } } - if (!(flags & GLOB_APPEND)) - { - pglob->gl_pathc = 0; - if (!(flags & GLOB_DOOFFS)) - pglob->gl_pathv = NULL; - else - { - size_t i; - - if (pglob->gl_offs >= SIZE_MAX / sizeof (char *)) - return GLOB_NOSPACE; - - pglob->gl_pathv = 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; - } - } - + 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 @@ -532,6 +481,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (filename == NULL) filename = strchr (pattern, ':'); #endif /* __MSDOS__ || WINDOWS32 */ + dirname_modified = 0; if (filename == NULL) { @@ -556,11 +506,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } filename = pattern; -#ifdef _AMIGA - dirname = (char *) ""; -#else dirname = (char *) "."; -#endif dirlen = 0; } } @@ -577,6 +523,7 @@ 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] == ':')) @@ -595,6 +542,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), 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); else @@ -608,17 +556,19 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), dirname = newp; ++filename; - if (filename[0] == '\0' #if defined __MSDOS__ || defined WINDOWS32 - && dirname[dirlen - 1] != ':' - && (dirlen < 3 || dirname[dirlen - 2] != ':' - || dirname[dirlen - 1] != '/') + bool drive_root = (dirlen > 1 + && (dirname[dirlen - 1] == ':' + || (dirlen > 2 && dirname[dirlen - 2] == ':' + && dirname[dirlen - 1] == '/'))); +#else + bool drive_root = false; #endif - && dirlen > 1) + + if (filename[0] == '\0' && dirlen > 1 && !drive_root) /* "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 @@ -632,7 +582,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC); } } - val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); + int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); if (val == 0) pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK)); @@ -658,15 +608,11 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), /* Look up home directory. */ char *home_dir = getenv ("HOME"); int malloc_home_dir = 0; -# ifdef _AMIGA - if (home_dir == NULL || home_dir[0] == '\0') - home_dir = "SYS:"; -# else -# ifdef WINDOWS32 - /* Windows NT defines HOMEDRIVE and HOMEPATH. But give preference - to HOME, because the user can change HOME. */ 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"); @@ -682,10 +628,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } else home_dir = "c:/users/default"; /* poor default */ - } -# else - if (home_dir == NULL || home_dir[0] == '\0') - { +#else int success; char *name; int malloc_name = 0; @@ -714,18 +657,18 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), struct passwd *p; char *malloc_pwtmpbuf = NULL; char *pwtmpbuf; -# if defined HAVE_GETPWNAM_R || defined _LIBC +# 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 +# ifndef _LIBC if (! (0 < pwbuflenmax && pwbuflenmax <= SIZE_MAX)) - /* Perhaps 'sysconf' does not support _SC_GETPW_R_SIZE_MAX. + /* 'sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a moderate value. */ pwbuflen = 1024; -# endif +# endif if (glob_use_alloca (alloca_used, pwbuflen)) pwtmpbuf = alloca_account (pwbuflen, alloca_used); else @@ -773,9 +716,9 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), pwbuflen = newlen; __set_errno (save); } -# else +# else p = getpwnam (name); -# endif +# endif if (__glibc_unlikely (malloc_name)) free (name); if (p != NULL) @@ -809,6 +752,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (__glibc_unlikely (malloc_name)) free (name); } +#endif /* WINDOWS32 */ } if (home_dir == NULL || home_dir[0] == '\0') { @@ -825,8 +769,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), malloc_home_dir = 0; } } -# endif /* WINDOWS32 */ -# endif /* Now construct the full directory. */ if (dirname[1] == '\0') { @@ -871,9 +813,9 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } dirname_modified = 1; } -# if !defined _AMIGA && !defined WINDOWS32 else { +#ifndef WINDOWS32 char *end_name = strchr (dirname, '/'); char *user_name; int malloc_user_name = 0; @@ -1048,8 +990,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } } } +#endif /* !WINDOWS32 */ } -# endif /* Not Amiga && not WINDOWS32. */ } /* Now test whether we looked for "~" or "~NAME". In this case we @@ -1177,20 +1119,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), { size_t old_pathc; -#ifdef SHELL - { - /* Make globbing interruptible in the bash shell. */ - extern int interrupt_state; - - if (interrupt_state) - { - globfree (&dirs); - retval = GLOB_ABORTED; - goto out; - } - } -#endif /* SHELL. */ - old_pathc = pglob->gl_pathc; status = glob_in_dir (filename, dirs.gl_pathv[i], ((flags | GLOB_APPEND) @@ -1382,26 +1310,6 @@ libc_hidden_def (glob) #endif -#ifndef GLOB_ONLY_P - -/* Free storage allocated in PGLOB by a previous 'glob' call. */ -void -globfree (glob_t *pglob) -{ - if (pglob->gl_pathv != NULL) - { - 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_pathv = NULL; - } -} -#if defined _LIBC && !defined globfree -libc_hidden_def (globfree) -#endif - - /* Do a collated comparison of A and B. */ static int collated_compare (const void *a, const void *b) @@ -1428,19 +1336,15 @@ prefix_array (const char *dirname, char **array, size_t n) { size_t i; size_t dirlen = strlen (dirname); -#if defined __MSDOS__ || defined WINDOWS32 - int sep_char = '/'; -# define DIRSEP_CHAR sep_char -#else -# define DIRSEP_CHAR '/' -#endif + 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 - else if (dirlen > 1) + if (dirlen > 1) { if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':') /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */ @@ -1449,7 +1353,7 @@ prefix_array (const char *dirname, char **array, size_t n) { /* DIRNAME is "d:". Use ':' instead of '/'. */ --dirlen; - sep_char = ':'; + dirsep_char = ':'; } } #endif @@ -1467,7 +1371,7 @@ prefix_array (const char *dirname, char **array, size_t n) { char *endp = mempcpy (new, dirname, dirlen); - *endp++ = DIRSEP_CHAR; + *endp++ = dirsep_char; mempcpy (endp, array[i], eltlen); } free (array[i]); @@ -1477,57 +1381,6 @@ prefix_array (const char *dirname, char **array, size_t n) return 0; } - -/* We must not compile this function twice. */ -#ifndef NO_GLOB_PATTERN_P -int -__glob_pattern_type (const char *pattern, int quote) -{ - const char *p; - int ret = 0; - - for (p = pattern; *p != '\0'; ++p) - switch (*p) - { - case '?': - case '*': - return 1; - - case '\\': - if (quote) - { - if (p[1] != '\0') - ++p; - ret |= 2; - } - break; - - case '[': - ret |= 4; - break; - - case ']': - if (ret & 4) - return 1; - break; - } - - return ret; -} - -/* Return nonzero if PATTERN contains any metacharacters. - Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ -int -__glob_pattern_p (const char *pattern, int quote) -{ - return __glob_pattern_type (pattern, quote) == 1; -} -# ifdef _LIBC -weak_alias (__glob_pattern_p, glob_pattern_p) -# endif -#endif - - /* We put this in a separate function mainly to allow the memory allocated with alloca to be recycled. */ static int @@ -1577,8 +1430,6 @@ link_exists_p (int dfd, const char *dir, size_t dirlen, const char *fname, # endif return status == 0 || errno == EOVERFLOW; } -#endif /* !defined GLOB_ONLY_P */ - /* Like 'glob', but PATTERN is a final pathname component, and matches are searched for in DIRECTORY. @@ -1675,11 +1526,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags, 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) -#if defined _AMIGA || defined VMS - | FNM_CASEFOLD -#endif - ); + | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)); flags |= GLOB_MAGCHAR; while (1) @@ -1772,7 +1619,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags, new_gl_pathv = realloc (pglob->gl_pathv, (pglob->gl_pathc + pglob->gl_offs + nfound + 1) - * sizeof (char *)); + * sizeof (char *)); if (new_gl_pathv == NULL) { @@ -1780,8 +1627,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags, while (1) { struct globnames *old = names; - size_t i; - for (i = 0; i < cur; ++i) + 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 @@ -1806,8 +1652,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags, while (1) { struct globnames *old = names; - size_t i; - for (i = 0; i < cur; ++i) + for (size_t i = 0; i < cur; ++i) new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++] = names->name[i]; names = names->next; diff --git a/lib/glob.in.h b/lib/glob.in.h index 09d2b156b..5eb65a0c1 100644 --- a/lib/glob.in.h +++ b/lib/glob.in.h @@ -47,19 +47,40 @@ # define __THROWNL #endif -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ +#define attribute_hidden -/* The definition of _GL_ARG_NONNULL is copied here. */ +#ifndef __attribute_noinline__ +# if 3 < __GNUC__ + (1 <= __GNUC_MINOR__) +# define __attribute_noinline__ __attribute__ ((__noinline__)) +#else +# define __attribute_noinline__ /* Ignore */ +# endif +#endif -/* The definition of _GL_WARN_ON_USE is copied here. */ +#if __GNUC__ < 3 +# define __glibc_unlikely(cond) (cond) +#else +# define __glibc_unlikely(cond) __builtin_expect ((cond), 0) +#endif -#ifndef __size_t -# define __size_t size_t +/* GCC 2.95 and later have "__restrict", and C99 compilers have + "restrict". */ +#if ! (defined __restrict || 2 < __GNUC__ + (95 <= __GNUC_MINOR__)) +# if 199901L <= __STDC_VERSION__ +# define __restrict restrict +# else +# define __restrict +# endif #endif + #ifndef __USE_GNU # define __USE_GNU 1 #endif +#ifndef weak_alias +# define weak_alias(name, alias) +#endif + #define glob rpl_glob #define globfree rpl_globfree diff --git a/lib/glob_internal.h b/lib/glob_internal.h new file mode 100644 index 000000000..12c93660b --- /dev/null +++ b/lib/glob_internal.h @@ -0,0 +1,57 @@ +/* Shared definition for glob and glob_pattern_p. + Copyright (C) 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 + . */ + +#ifndef GLOB_INTERNAL_H +# define GLOB_INTERNAL_H + +static inline int +__glob_pattern_type (const char *pattern, int quote) +{ + const char *p; + int ret = 0; + + for (p = pattern; *p != '\0'; ++p) + switch (*p) + { + case '?': + case '*': + return 1; + + case '\\': + if (quote) + { + if (p[1] != '\0') + ++p; + ret |= 2; + } + break; + + case '[': + ret |= 4; + break; + + case ']': + if (ret & 4) + return 1; + break; + } + + return ret; +} + +#endif /* GLOB_INTERNAL_H */ diff --git a/lib/glob_pattern_p.c b/lib/glob_pattern_p.c new file mode 100644 index 000000000..a17d33718 --- /dev/null +++ b/lib/glob_pattern_p.c @@ -0,0 +1,33 @@ +/* Return nonzero if PATTERN contains any metacharacters. + Copyright (C) 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 + . */ + +#ifndef _LIBC +# include +#endif + +#include +#include "glob_internal.h" + +/* Return nonzero if PATTERN contains any metacharacters. + Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ +int +__glob_pattern_p (const char *pattern, int quote) +{ + return __glob_pattern_type (pattern, quote) == 1; +} +weak_alias (__glob_pattern_p, glob_pattern_p) diff --git a/lib/globfree.c b/lib/globfree.c new file mode 100644 index 000000000..042e29d9b --- /dev/null +++ b/lib/globfree.c @@ -0,0 +1,41 @@ +/* Frees the dynamically allocated storage from an earlier call to glob. + Copyright (C) 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 + . */ + +#ifndef _LIBC +# include +#endif + +#include +#include + +/* Free storage allocated in PGLOB by a previous `glob' call. */ +void +globfree (glob_t *pglob) +{ + if (pglob->gl_pathv != NULL) + { + 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_pathv = NULL; + } +} +#ifndef globfree +libc_hidden_def (globfree) +#endif diff --git a/modules/d-ino b/modules/d-ino index e8d6abafa..fdc6b41bf 100644 --- a/modules/d-ino +++ b/modules/d-ino @@ -14,7 +14,7 @@ Makefile.am: Include: License: -LGPL +LGPLv2+ Maintainer: Jim Meyering diff --git a/modules/flexmember b/modules/flexmember index 510767619..2afdc93ef 100644 --- a/modules/flexmember +++ b/modules/flexmember @@ -15,7 +15,7 @@ Makefile.am: Include: License: -unlimited +LGPLv2+ Maintainer: Paul Eggert, Jim Meyering diff --git a/modules/glob b/modules/glob index 29df7ab89..0d64124c1 100644 --- a/modules/glob +++ b/modules/glob @@ -6,17 +6,20 @@ Files: lib/glob.in.h lib/glob-libc.h lib/glob.c +lib/glob_internal.h +lib/glob_pattern_p.c +lib/globfree.c m4/glob.m4 Depends-on: extensions largefile -snippet/arg-nonnull snippet/c++defs snippet/warn-on-use alloca [test -n "$GLOB_H"] builtin-expect [test -n "$GLOB_H"] closedir [test -n "$GLOB_H"] +d-ino [test -n "$GLOB_H"] d-type [test -n "$GLOB_H"] dirfd [test -n "$GLOB_H"] flexmember [test -n "$GLOB_H"] @@ -37,6 +40,8 @@ configure.ac: gl_GLOB if test -n "$GLOB_H"; then AC_LIBOBJ([glob]) + AC_LIBOBJ([glob_pattern_p]) + AC_LIBOBJ([globfree]) gl_PREREQ_GLOB fi @@ -46,12 +51,11 @@ BUILT_SOURCES += $(GLOB_H) # We need the following in order to create when the system # doesn't have one that works with the given compiler. if GL_GENERATE_GLOB_H -glob.h: glob.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) +glob.h: glob.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) $(AM_V_GEN)rm -f address@hidden $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''HAVE_SYS_CDEFS_H''@|$(HAVE_SYS_CDEFS_H)|g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ - -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ < $(srcdir)/glob.in.h; \ } > address@hidden && \ -- 2.13.5