Re: New GNULIB glob module?
Derek Price <[email protected]> Tue, 24 May 2005 11:02:09 -0400
| Newsgroups | gmane.comp.lib.gnulib.bugs,gmane.comp.version-control.cvs.bugs |
|---|---|
| Organization | Get CVS Support from Ximbiot <http://ximbiot.com>! |
| Message-ID | <[email protected]> |
This is a multi-part message in MIME format. --------------060701020108000301020206 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Paul Eggert wrote: >Derek Price <[email protected]> writes: > > > >>all the HAVE_.*64 stuff in glob.c shouldn't be necessary when !_LIBC. >> >> > >Yes, that's correct; it should just invoke stat, opendir, etc., without >worrying about their 64-bit variants. I thought it already did that? >If not, where does it not do it? > > No, we were detecting `struct dirent64' and the `stat64' function in glob.m4 and using the 64 bit functions based on those. (On HP-UX, the stat64 function was found but it had a different proto or something from the one glob.c expected.) I've now rewritten glob.c to only use the 64 bit functions when !_LIBC and removed the checks in glob.m4 for the 64 bit objects. >>Also, this particular bit in glob_.h would need to be used when !_LIBC >>as well, since user-space programs compiling against the glob.h system >>header from glibc would want glob64 used as compile-time magic, correct? >> >> > >Sorry, you've lost me here (I don't know what "this particular bit" >is). If !_LIBC, then glob_.h should simply declare glob and globfree, >using the standard (i.e., non-64-bit) type names. These functions > > I was referring to the REDIRECT_NTH stuff only being compiled when !_LIBC. Since this glob_.h is intended to sometimes be installed as <glob.h>, I thought perhaps there was some background magic happening in that file when <glob.h> is included by an application, not just when libc was being compiled (I believe _LIBC is set in the latter and not the former case). If so, my protection of those lines when !_LIBC may be incorrect. I've now also protected the `#ifdef __LARGEFILE64' stuff with an additional `&& defined _LIBC', which prevents struct glob64_t and the glob64 and globfree64 functions from being defined/declared when !_LIBC. This may also be incorrect when glob_.h is installed as a system header, but should be right for GNULIB. >GNU programmers have access to the source code, so we can simply >recompile it to use 64-bit interfaces uniformly, which we can then >simply call via their usual names stat, open, etc. > > I've rewritten glob.c so. I've attached three patches this time. The first two are as before (glob8.diff is the complete patch to install this new glob module into GNULIB & glob-glibc2gnulib8.diff is the diff of glob_.h and glob.c against their original glibc sources). The final patch contains, basically, the differences between my 7 & 8 patch set, for your reference, since I have made a few minor changes here in the CVS CVS which were necessary for porting to various systems and I did not discuss them with you. I believe the offending systems were Solaris 5.8, a BSD/BSD-OS or two, and HP-UX. I fixed the Solaris and BSD, but the jury is still out on the HP-UX. It needed the 64bit-clean fix which I just wrote and I won't know for a day or two if it compiles there in nightly testing. Regards, Derek --------------060701020108000301020206 Content-Type: text/plain; name="glob8.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="glob8.diff" Index: config/srclist.txt =================================================================== RCS file: /cvsroot/gnulib/gnulib/config/srclist.txt,v retrieving revision 1.62 diff -u -p -r1.62 srclist.txt --- config/srclist.txt 10 May 2005 20:44:25 -0000 1.62 +++ config/srclist.txt 24 May 2005 14:43:20 -0000 @@ -111,6 +111,7 @@ $LIBCSRC/sysdeps/generic/memmem.c lib gp #$LIBCSRC/misc/error.h lib gpl #$LIBCSRC/misc/getpass.c lib gpl #$LIBCSRC/misc/mkstemp.c lib gpl +#$LIBCSRC/posix/glob.h lib gpl (glob_.h in gnulib) #$LIBCSRC/posix/fnmatch.c lib gpl #$LIBCSRC/posix/fnmatch.h lib gpl (fnmatch_.h in gnulib) #$LIBCSRC/posix/fnmatch_loop.c lib gpl @@ -119,6 +120,7 @@ $LIBCSRC/sysdeps/generic/memmem.c lib gp #$LIBCSRC/stdlib/rpmatch.c lib gpl #$LIBCSRC/string/strndup.c lib gpl #$LIBCSRC/string/strverscmp.c lib gpl +#$LIBCSRC/sysdeps/generic/glob.c lib gpl #$LIBCSRC/sysdeps/generic/memchr.c lib gpl #$LIBCSRC/sysdeps/generic/memcmp.c lib gpl #$LIBCSRC/sysdeps/generic/memrchr.c lib gpl Index: lib/glob.c =================================================================== RCS file: lib/glob.c diff -N lib/glob.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/glob.c 24 May 2005 14:43:21 -0000 @@ -0,0 +1,1295 @@ +/* Copyright (C) 1991-2002, 2003, 2004, 2005 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <glob.h> + +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stddef.h> + +/* Outcomment the following line for production quality code. */ +/* #define NDEBUG 1 */ +#include <assert.h> + +#include <stdio.h> /* Needed on stupid SunOS for assert. */ + +#if !defined _LIBC || !defined GLOB_ONLY_P +#if defined HAVE_UNISTD_H || defined _LIBC +# include <unistd.h> +# ifndef POSIX +# ifdef _POSIX_VERSION +# define POSIX +# endif +# endif +#else +/* Is there really a case where the getlogin or getlogin_r proto can come from + somewhere other than <unistd.h>? */ +# ifdef HAVE_GETLOGIN_R +extern int getlogin_r (char *, size_t); +# else +extern char *getlogin (void); +# endif +#endif + +#include <pwd.h> + +#include <errno.h> +#ifndef __set_errno +# define __set_errno(val) errno = (val) +#endif + +#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ +# include <dirent.h> +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# ifdef HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# endif +# ifdef HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif +# ifdef HAVE_NDIR_H +# include <ndir.h> +# endif +# ifdef HAVE_VMSDIR_H +# include "vmsdir.h" +# endif /* HAVE_VMSDIR_H */ +#endif + + +/* In GNU systems, <dirent.h> defines this macro for us. */ +#ifdef _D_NAMLEN +# undef NAMLEN +# define NAMLEN(d) _D_NAMLEN(d) +#endif + +/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available + if the `d_type' member for `struct dirent' is available. + HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */ +#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE +# define HAVE_D_TYPE 1 + +/* True if the directory entry D must be of type T. */ +# define DIRENT_MUST_BE(d, t) ((d)->d_type == (t)) + +/* True if the directory entry D might be a symbolic link. */ +# define DIRENT_MIGHT_BE_SYMLINK(d) \ + ((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK) + +/* True if the directory entry D might be a directory. */ +# define DIRENT_MIGHT_BE_DIR(d) \ + ((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d)) + +#else /* !HAVE_D_TYPE */ +# define DIRENT_MUST_BE(d, t) false +# define DIRENT_MIGHT_BE_SYMLINK(d) true +# define DIRENT_MIGHT_BE_DIR(d) true +#endif /* HAVE_D_TYPE */ + +/* If the system has the `struct dirent64' type we use it internally. */ +#if defined _LIBC && !defined COMPILE_GLOB64 +# if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ +# define CONVERT_D_NAMLEN(d64, d32) +# else +# define CONVERT_D_NAMLEN(d64, d32) \ + (d64)->d_namlen = (d32)->d_namlen; +# endif + +# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ +# define CONVERT_D_INO(d64, d32) +# else +# define CONVERT_D_INO(d64, d32) \ + (d64)->d_ino = (d32)->d_ino; +# endif + +# ifdef HAVE_D_TYPE +# define CONVERT_D_TYPE(d64, d32) \ + (d64)->d_type = (d32)->d_type; +# else +# define CONVERT_D_TYPE(d64, d32) +# endif + +# define CONVERT_DIRENT_DIRENT64(d64, d32) \ + memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \ + CONVERT_D_NAMLEN (d64, d32) \ + CONVERT_D_INO (d64, d32) \ + CONVERT_D_TYPE (d64, d32) +#endif + + +#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ +/* Posix does not require that the d_ino field be present, and some + systems do not provide it. */ +# define REAL_DIR_ENTRY(dp) 1 +#else +# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) +#endif /* POSIX */ + +#include <stdlib.h> +#include <string.h> + +/* NAME_MAX is usually defined in <dirent.h> or <limits.h>. */ +#include <limits.h> +#ifndef NAME_MAX +# define NAME_MAX (sizeof (((struct dirent *) 0)->d_name)) +#endif + +#include <alloca.h> + +#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 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 +#else /* !_LIBC */ +# ifdef HAVE___POSIX_GETPWNAM_R + /* Solaris. */ +# define getpwnam_r(name, bufp, buf, len, res) \ + __posix_getpwnam_r (name, bufp, buf, len, res) +# endif +# include "mempcpy.h" +# include "stat-macros.h" +# include "strdup.h" +# define __stat64(fname, buf) stat (fname, buf) +# define stat64 stat +# define __stat(fname, buf) stat (fname, buf) +# define __alloca alloca +# define __readdir readdir +# define __readdir64 readdir64 +#endif /* _LIBC */ + +#include <stdbool.h> +#include <fnmatch.h> + +#ifdef _SC_GETPW_R_SIZE_MAX +# define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX) +#else +# define GETPW_R_SIZE_MAX() (-1) +#endif + +static const char *next_brace_sub (const char *begin, int flags) __THROW; + +#endif /* !defined _LIBC || !defined GLOB_ONLY_P */ + +static int glob_in_dir (const char *pattern, const char *directory, + int flags, int (*errfunc) (const char *, int), + glob_t *pglob); + +#if !defined _LIBC || !defined GLOB_ONLY_P +static int prefix_array (const char *prefix, char **array, size_t n) __THROW; +static int collated_compare (const void *, const void *) __THROW; + + +/* Find the end of the sub-pattern in a brace expression. */ +static const char * +next_brace_sub (const char *cp, int flags) +{ + unsigned int depth = 0; + while (*cp != '\0') + if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\') + { + if (*++cp == '\0') + break; + ++cp; + } + else + { + if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0)) + break; + + if (*cp++ == '{') + depth++; + } + + return *cp != '\0' ? cp : NULL; +} + +#endif /* !defined _LIBC || !defined GLOB_ONLY_P */ + +/* 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, + 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_ABORTED; if it returns zero, the error is ignored. + If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. + Otherwise, `glob' returns zero. */ +int +#ifdef GLOB_ATTRIBUTE +GLOB_ATTRIBUTE +#endif +glob (const char *pattern, int flags, + int (*errfunc) (const char *, int), + glob_t *pglob) +{ + const char *filename; + const char *dirname; + size_t dirlen; + int status; + size_t oldcount; + + if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) + { + __set_errno (EINVAL); + return -1; + } + + if (!(flags & GLOB_DOOFFS)) + /* Have to do this so `globfree' knows where to start freeing. It + also makes all the code that uses gl_offs simpler. */ + pglob->gl_offs = 0; + + if (flags & GLOB_BRACE) + { + const char *begin; + + if (flags & GLOB_NOESCAPE) + 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; + } + } + + 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; +#ifdef __GNUC__ + char onealt[strlen (pattern) - 1]; +#else + char *onealt = malloc (strlen (pattern) - 1); + if (onealt == NULL) + { + if (!(flags & GLOB_APPEND)) + { + pglob->gl_pathc = 0; + pglob->gl_pathv = NULL; + } + return GLOB_NOSPACE; + } +#endif + + /* 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 illegal expression. */ +#ifndef __GNUC__ + free (onealt); +#endif + 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. */ +#ifndef __GNUC__ + free (onealt); +#endif + return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); + } + } + /* 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. */ + + 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; + 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) + { +#ifndef __GNUC__ + free (onealt); +#endif + 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); + } + +#ifndef __GNUC__ + free (onealt); +#endif + + if (pglob->gl_pathc != firstc) + /* We found some entries. */ + return 0; + else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) + return GLOB_NOMATCH; + } + } + + /* 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 */ + if (filename == NULL) + { + /* This can mean two things: a simple name or "~name". The latter + case is nothing but a notation for a directory. */ + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') + { + dirname = 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 + { + filename = pattern; +#ifdef _AMIGA + dirname = ""; +#else + dirname = "."; +#endif + dirlen = 0; + } + } + else if (filename == pattern) + { + /* "/pattern". */ + dirname = "/"; + dirlen = 1; + ++filename; + } + else + { + 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 + newp = __alloca (dirlen + 1); + *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; + dirname = newp; + ++filename; + + if (filename[0] == '\0' +#if defined __MSDOS__ || defined WINDOWS32 + && dirname[dirlen - 1] != ':' + && (dirlen < 3 || dirname[dirlen - 2] != ':' + || dirname[dirlen - 1] != '/') +#endif + && dirlen > 1) + /* "pattern/". Expand "pattern", appending slashes. */ + { + int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); + if (val == 0) + pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) + | (flags & GLOB_MARK)); + return val; + } + } + + if (!(flags & GLOB_APPEND)) + { + pglob->gl_pathc = 0; + if (!(flags & GLOB_DOOFFS)) + pglob->gl_pathv = NULL; + else + { + size_t i; + 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; + } + } + + oldcount = pglob->gl_pathc + pglob->gl_offs; + +#ifndef VMS + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') + { + if (dirname[1] == '\0' || dirname[1] == '/') + { + /* Look up home directory. */ + const char *home_dir = getenv ("HOME"); +# ifdef _AMIGA + if (home_dir == NULL || home_dir[0] == '\0') + home_dir = "SYS:"; +# else +# ifdef WINDOWS32 + if (home_dir == NULL || home_dir[0] == '\0') + home_dir = "c:/users/default"; /* poor default */ +# else + if (home_dir == NULL || home_dir[0] == '\0') + { + int success; + char *name; +# if defined HAVE_GETLOGIN_R || defined _LIBC + size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1; + + if (buflen == 0) + /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try + a moderate value. */ + buflen = 20; + name = __alloca (buflen); + + success = getlogin_r (name, buflen) >= 0; +# else + success = (name = getlogin ()) != NULL; +# endif + if (success) + { + struct passwd *p; +# if defined HAVE_GETPWNAM_R || defined _LIBC + long int pwbuflen = GETPW_R_SIZE_MAX (); + char *pwtmpbuf; + struct passwd pwbuf; + int save = errno; + +# ifndef _LIBC + if (pwbuflen == -1) + /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. + Try a moderate value. */ + pwbuflen = 1024; +# endif + pwtmpbuf = __alloca (pwbuflen); + + while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) + != 0) + { + if (errno != ERANGE) + { + p = NULL; + break; + } +# ifdef _LIBC + pwtmpbuf = extend_alloca (pwtmpbuf, pwbuflen, + 2 * pwbuflen); +# else + pwbuflen *= 2; + pwtmpbuf = __alloca (pwbuflen); +# endif + __set_errno (save); + } +# else + p = getpwnam (name); +# endif + if (p != NULL) + home_dir = p->pw_dir; + } + } + if (home_dir == NULL || home_dir[0] == '\0') + { + if (flags & GLOB_TILDE_CHECK) + return GLOB_NOMATCH; + else + home_dir = "~"; /* No luck. */ + } +# endif /* WINDOWS32 */ +# endif + /* Now construct the full directory. */ + if (dirname[1] == '\0') + dirname = home_dir; + else + { + char *newp; + size_t home_len = strlen (home_dir); + newp = __alloca (home_len + dirlen); + mempcpy (mempcpy (newp, home_dir, home_len), + &dirname[1], dirlen); + dirname = newp; + } + } +# if !defined _AMIGA && !defined WINDOWS32 + else + { + char *end_name = strchr (dirname, '/'); + const char *user_name; + const char *home_dir; + + if (end_name == NULL) + user_name = dirname + 1; + else + { + char *newp; + newp = __alloca (end_name - dirname); + *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) + = '\0'; + user_name = newp; + } + + /* Look up specific user's home directory. */ + { + struct passwd *p; +# if defined HAVE_GETPWNAM_R || defined _LIBC + long int buflen = GETPW_R_SIZE_MAX (); + char *pwtmpbuf; + struct passwd pwbuf; + int save = errno; + +# ifndef _LIBC + if (buflen == -1) + /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a + moderate value. */ + buflen = 1024; +# endif + pwtmpbuf = __alloca (buflen); + + while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0) + { + if (errno != ERANGE) + { + p = NULL; + break; + } +# ifdef _LIBC + pwtmpbuf = extend_alloca (pwtmpbuf, buflen, 2 * buflen); +# else + buflen *= 2; + pwtmpbuf = __alloca (buflen); +# endif + __set_errno (save); + } +# else + p = getpwnam (user_name); +# endif + if (p != NULL) + home_dir = p->pw_dir; + else + home_dir = NULL; + } + /* If we found a home directory use this. */ + if (home_dir != NULL) + { + char *newp; + size_t home_len = strlen (home_dir); + size_t rest_len = end_name == NULL ? 0 : strlen (end_name); + newp = __alloca (home_len + rest_len + 1); + *((char *) mempcpy (mempcpy (newp, home_dir, home_len), + end_name, rest_len)) = '\0'; + dirname = newp; + } + else + if (flags & GLOB_TILDE_CHECK) + /* We have to regard it as an error if we cannot find the + home directory. */ + return GLOB_NOMATCH; + } +# endif /* Not Amiga && not WINDOWS32. */ + } +#endif /* Not VMS. */ + + /* Now test whether we looked for "~" or "~NAME". In this case we + can give the answer now. */ + if (filename == NULL) + { + struct stat st; + struct stat64 st64; + + /* Return the directory if we don't check for error or if it exists. */ + if ((flags & GLOB_NOCHECK) + || (((flags & GLOB_ALTDIRFUNC) + ? ((*pglob->gl_stat) (dirname, &st) == 0 + && S_ISDIR (st.st_mode)) + : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode))))) + { + int newcount = pglob->gl_pathc + pglob->gl_offs; + char **new_gl_pathv; + + new_gl_pathv + = realloc (pglob->gl_pathv, (newcount + 1 + 1) * sizeof (char *)); + if (new_gl_pathv == NULL) + { + nospace: + free (pglob->gl_pathv); + pglob->gl_pathv = NULL; + pglob->gl_pathc = 0; + return GLOB_NOSPACE; + } + pglob->gl_pathv = new_gl_pathv; + + 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. */ + return GLOB_NOMATCH; + } + + if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE))) + { + /* The directory name contains metacharacters, so we + have to glob for the directory, and then glob for + the pattern in each directory found. */ + glob_t dirs; + size_t i; + + if ((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; + } + + status = glob (dirname, + ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE + | GLOB_ALTDIRFUNC)) + | GLOB_NOSORT | GLOB_ONLYDIR), + errfunc, &dirs); + if (status != 0) + return status; + + /* 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 (i = 0; i < dirs.gl_pathc; ++i) + { + int old_pathc; + +#ifdef SHELL + { + /* Make globbing interruptible in the bash shell. */ + extern int interrupt_state; + + if (interrupt_state) + { + globfree (&dirs); + return GLOB_ABORTED; + } + } +#endif /* SHELL. */ + + old_pathc = pglob->gl_pathc; + status = glob_in_dir (filename, dirs.gl_pathv[i], + ((flags | GLOB_APPEND) + & ~(GLOB_NOCHECK | GLOB_NOMAGIC)), + errfunc, pglob); + if (status == GLOB_NOMATCH) + /* No matches in this directory. Try the next. */ + continue; + + if (status != 0) + { + globfree (&dirs); + globfree (pglob); + pglob->gl_pathc = 0; + return status; + } + + /* 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; + return GLOB_NOSPACE; + } + } + + 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. */ + if (pglob->gl_pathc + pglob->gl_offs == oldcount) + { + /* No matches. */ + if (flags & GLOB_NOCHECK) + { + int newcount = pglob->gl_pathc + pglob->gl_offs; + char **new_gl_pathv; + + new_gl_pathv = realloc (pglob->gl_pathv, + (newcount + 2) * sizeof (char *)); + if (new_gl_pathv == NULL) + { + globfree (&dirs); + return GLOB_NOSPACE; + } + 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; + return GLOB_NOSPACE; + } + + ++pglob->gl_pathc; + ++newcount; + + pglob->gl_pathv[newcount] = NULL; + pglob->gl_flags = flags; + } + else + { + globfree (&dirs); + return GLOB_NOMATCH; + } + } + + globfree (&dirs); + } + else + { + int old_pathc = pglob->gl_pathc; + + status = glob_in_dir (filename, dirname, flags, errfunc, pglob); + if (status != 0) + return status; + + 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; + return GLOB_NOSPACE; + } + } + } + + if (!(flags & GLOB_NOSORT)) + { + /* Sort the vector. */ + qsort (&pglob->gl_pathv[oldcount], + pglob->gl_pathc + pglob->gl_offs - oldcount, + sizeof (char *), collated_compare); + } + + return 0; +} +#if defined _LIBC && !defined glob +libc_hidden_def (glob) +#endif + + +#if !defined _LIBC || !defined GLOB_ONLY_P + +/* Free storage allocated in PGLOB by a previous `glob' call. */ +void +globfree (register glob_t *pglob) +{ + if (pglob->gl_pathv != NULL) + { + size_t i; + for (i = 0; i < pglob->gl_pathc; ++i) + if (pglob->gl_pathv[pglob->gl_offs + i] != NULL) + 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) +{ + const char *const s1 = *(const char *const * const) a; + const char *const s2 = *(const char *const * const) b; + + if (s1 == s2) + return 0; + if (s1 == NULL) + return 1; + if (s2 == NULL) + return -1; + return strcoll (s1, s2); +} + + +/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's + elements in place. Return nonzero if out of memory, zero if successful. + A slash is inserted between DIRNAME and each elt of ARRAY, + unless DIRNAME is just "/". Each old element of ARRAY is freed. */ +static int +prefix_array (const char *dirname, char **array, size_t n) +{ + register 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 + + 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 (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; + sep_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; + } + + { + char *endp = mempcpy (new, dirname, dirlen); + *endp++ = DIRSEP_CHAR; + mempcpy (endp, array[i], eltlen); + } + free (array[i]); + array[i] = new; + } + + return 0; +} + + +/* We must not compile this function twice. */ +#if !defined _LIBC || !defined NO_GLOB_PATTERN_P +/* 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) +{ + register const char *p; + int open = 0; + + for (p = pattern; *p != '\0'; ++p) + switch (*p) + { + case '?': + case '*': + return 1; + + case '\\': + if (quote && p[1] != '\0') + ++p; + break; + + case '[': + open = 1; + break; + + case ']': + if (open) + return 1; + break; + } + + return 0; +} +# ifdef _LIBC +weak_alias (__glob_pattern_p, glob_pattern_p) +# endif +#endif + +#endif /* !GLOB_ONLY_P */ + + +/* We put this in a separate function mainly to allow the memory + allocated with alloca to be recycled. */ +#if !defined _LIBC || !defined GLOB_ONLY_P +static bool +is_dir_p (const char *dir, size_t dirlen, const char *fname, + glob_t *pglob, int flags) +{ + size_t fnamelen = strlen (fname); + char *fullname = __alloca (dirlen + 1 + fnamelen + 1); + struct stat st; + struct stat64 st64; + + mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1), + fname, fnamelen + 1); + + return ((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_stat) (fullname, &st) == 0 && S_ISDIR (st.st_mode) + : __stat64 (fullname, &st64) == 0 && S_ISDIR (st64.st_mode)); +} +#endif + + +/* 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 dirlen = strlen (directory); + void *stream = NULL; + struct globlink + { + struct globlink *next; + char *name; + }; + struct globlink *names = NULL; + size_t nfound; + int meta; + int save; + + meta = __glob_pattern_p (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. */ + flags |= GLOB_NOCHECK; + nfound = 0; + } + else if (meta == 0 && + ((flags & GLOB_NOESCAPE) || strchr (pattern, '\\') == NULL)) + { + /* Since we use the normal file functions we can also use stat() + to verify the file is there. */ + struct stat st; + struct stat64 st64; + size_t patlen = strlen (pattern); + char *fullname = __alloca (dirlen + 1 + patlen + 1); + + mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), + "/", 1), + pattern, patlen + 1); + if (((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_stat) (fullname, &st) + : __stat64 (fullname, &st64)) == 0) + /* We found this file to be existing. Now tell the rest + of the function to copy this name into the result. */ + flags |= GLOB_NOCHECK; + + nfound = 0; + } + else + { + if (pattern[0] == '\0') + { + /* This is a special case for matching directories like in + "*a/". */ + names = __alloca (sizeof (struct globlink)); + names->name = malloc (1); + if (names->name == NULL) + goto memory_error; + names->name[0] = '\0'; + names->next = NULL; + nfound = 1; + meta = 0; + } + else + { + stream = ((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_opendir) (directory) + : opendir (directory)); + if (stream == NULL) + { + if (errno != ENOTDIR + && ((errfunc != NULL && (*errfunc) (directory, errno)) + || (flags & GLOB_ERR))) + return GLOB_ABORTED; + nfound = 0; + meta = 0; + } + else + { + int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) + | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) +#if defined _AMIGA || defined VMS + | FNM_CASEFOLD +#endif + ); + nfound = 0; + flags |= GLOB_MAGCHAR; + + while (1) + { + const char *name; + size_t len; +#if defined _LIBC && !defined COMPILE_GLOB64 + struct dirent64 *d; + union + { + struct dirent64 d64; + char room [offsetof (struct dirent64, d_name[0]) + + NAME_MAX + 1]; + } + d64buf; + + if (flags & GLOB_ALTDIRFUNC) + { + struct dirent *d32 = (*pglob->gl_readdir) (stream); + if (d32 != NULL) + { + CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32); + d = &d64buf.d64; + } + else + d = NULL; + } + else + d = __readdir64 (stream); +#else + struct dirent *d = ((flags & GLOB_ALTDIRFUNC) + ? ((*pglob->gl_readdir) (stream)) + : __readdir (stream)); +#endif + if (d == NULL) + break; + if (! REAL_DIR_ENTRY (d)) + continue; + + /* If we shall match only directories use the information + provided by the dirent call if possible. */ + if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d)) + continue; + + name = d->d_name; + + if (fnmatch (pattern, name, fnm_flags) == 0) + { + /* ISDIR will often be incorrectly set to false + when not in GLOB_ONLYDIR || GLOB_MARK mode, but we + don't care. It won't be used and we save the + expensive call to stat. */ + int need_dir_test = + (GLOB_MARK | (DIRENT_MIGHT_BE_SYMLINK (d) + ? GLOB_ONLYDIR : 0)); + bool isdir = (DIRENT_MUST_BE (d, DT_DIR) + || ((flags & need_dir_test) + && is_dir_p (directory, dirlen, name, + pglob, flags))); + + /* In GLOB_ONLYDIR mode, skip non-dirs. */ + if ((flags & GLOB_ONLYDIR) && !isdir) + continue; + + { + struct globlink *new = + __alloca (sizeof (struct globlink)); + char *p; + len = NAMLEN (d); + new->name = + malloc (len + 1 + ((flags & GLOB_MARK) && isdir)); + if (new->name == NULL) + goto memory_error; + p = mempcpy (new->name, name, len); + if ((flags & GLOB_MARK) && isdir) + *p++ = '/'; + *p = '\0'; + new->next = names; + names = new; + ++nfound; + } + } + } + } + } + } + + if (nfound == 0 && (flags & GLOB_NOCHECK)) + { + size_t len = strlen (pattern); + nfound = 1; + names = __alloca (sizeof (struct globlink)); + names->next = NULL; + names->name = malloc (len + 1); + if (names->name == NULL) + goto memory_error; + *((char *) mempcpy (names->name, pattern, len)) = '\0'; + } + + if (nfound != 0) + { + char **new_gl_pathv; + + new_gl_pathv + = realloc (pglob->gl_pathv, + (pglob->gl_pathc + pglob->gl_offs + nfound + 1) + * sizeof (char *)); + if (new_gl_pathv == NULL) + goto memory_error; + pglob->gl_pathv = new_gl_pathv; + + for (; names != NULL; names = names->next) + pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc++] = names->name; + pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; + + pglob->gl_flags = flags; + } + + save = errno; + if (stream != NULL) + { + if (flags & GLOB_ALTDIRFUNC) + (*pglob->gl_closedir) (stream); + else + closedir (stream); + } + __set_errno (save); + + return nfound == 0 ? GLOB_NOMATCH : 0; + + memory_error: + { + int save = errno; + if (flags & GLOB_ALTDIRFUNC) + (*pglob->gl_closedir) (stream); + else + closedir (stream); + __set_errno (save); + } + while (names != NULL) + { + if (names->name != NULL) + free (names->name); + names = names->next; + } + return GLOB_NOSPACE; +} Index: lib/glob_.h =================================================================== RCS file: lib/glob_.h diff -N lib/glob_.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/glob_.h 24 May 2005 14:43:21 -0000 @@ -0,0 +1,219 @@ +/* Copyright (C) 1991,92,95-98,2000,2001,2004 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GLOB_H +#define _GLOB_H 1 + +#if defined _LIBC || HAVE_SYS_CDEFS_H +# include <sys/cdefs.h> +#endif + +/* We need `size_t' for the following definitions. */ +#ifdef _LIBC +__BEGIN_DECLS + +# ifndef __size_t +typedef __SIZE_TYPE__ __size_t; +# ifdef __USE_XOPEN +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 +#else /* !_LIBC */ +# include <stddef.h> +# undef __size_t +# define __size_t size_t +/* The following are necessary with MSVC and who knows where else. */ +# ifndef __const +# define __const const +# endif +# ifndef __restrict +# define __restrict restrict +# endif +# ifndef __USE_GNU +# define __USE_GNU 1 +# endif +#endif /* _LIBC */ + +/* 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_BSD || defined __USE_GNU +# 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_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) +#else +# 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. */ +#ifdef __USE_GNU +/* Previous versions of this file defined GLOB_ABEND instead of + GLOB_ABORTED. Provide a compatibility definition here. */ +# define GLOB_ABEND GLOB_ABORTED +#endif + +/* Structure describing a globbing run. */ +#ifdef __USE_GNU +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. */ + + /* If the GLOB_ALTDIRFUNC flag is set, the following functions + are used instead of the normal file access functions. */ + void (*gl_closedir) (void *); +#ifdef __USE_GNU + struct dirent *(*gl_readdir) (void *); +#else + void *(*gl_readdir) (void *); +#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); +#else + int (*gl_lstat) (__const char *__restrict, void *__restrict); + int (*gl_stat) (__const char *__restrict, void *__restrict); +#endif + } glob_t; + +#if defined _LIBC && defined __USE_LARGEFILE64 +# ifdef __USE_GNU +struct stat64; +# endif +typedef struct + { + __size_t gl_pathc; + char **gl_pathv; + __size_t gl_offs; + int gl_flags; + + /* If the GLOB_ALTDIRFUNC flag is set, the following functions + are used instead of the normal file access functions. */ + void (*gl_closedir) (void *); +# ifdef __USE_GNU + struct dirent64 *(*gl_readdir) (void *); +# else + void *(*gl_readdir) (void *); +# 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); +# else + int (*gl_lstat) (__const char *__restrict, void *__restrict); + int (*gl_stat) (__const char *__restrict, void *__restrict); +# endif + } glob64_t; +#endif + +#ifdef GLOB_PREFIX +# define __GLOB_CONCAT(x, y) x ## y +# define __GLOB_XCONCAT(x, y) __GLOB_CONCAT (x, y) +# define __GLOB_ID(y) __GLOB_XCONCAT (GLOB_PREFIX, y) +# define glob __GLOB_ID (glob) +# define globfree __GLOB_ID (globfree) +# define glob_pattern_p __GLOB_ID (glob_pattern_p) +#endif + +#ifndef _LIBC +# define __glob_pattern_p glob_pattern_p +#endif + +#ifndef __THROW +# define __THROW +#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, + 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. + If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. + Otherwise, `glob' returns zero. */ +#if !defined _LIBC || !defined __USE_FILE_OFFSET64 +extern int glob (__const char *__restrict __pattern, int __flags, + int (*__errfunc) (__const char *, int), + glob_t *__restrict __pglob) __THROW; + +/* 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); + +extern void __REDIRECT_NTH (globfree, (glob_t *__pglob), globfree64); +#endif + +#if defined _LIBC && defined __USE_LARGEFILE64 +extern int glob64 (__const char *__restrict __pattern, int __flags, + int (*__errfunc) (__const char *, int), + glob64_t *__restrict __pglob) __THROW; + +extern void globfree64 (glob64_t *__pglob) __THROW; +#endif + + +#ifdef __USE_GNU +/* Return nonzero if PATTERN contains any metacharacters. + Metacharacters can be quoted with backslashes if QUOTE is nonzero. + + 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; +#endif + +#ifdef _LIBC +__END_DECLS +#endif + +#endif /* glob.h */ Index: m4/glob.m4 =================================================================== RCS file: m4/glob.m4 diff -N m4/glob.m4 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ m4/glob.m4 24 May 2005 14:43:21 -0000 @@ -0,0 +1,45 @@ +# glob.m4 serial 1 +dnl Copyright (C) 2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# The glob module assumes you want GNU glob, with glob_pattern_p etc, +# rather than vanilla POSIX glob. This means your your code should +# always include <glob.h> for the glob prototypes. + +AC_DEFUN([gl_GLOB_SUBSTITUTE], +[ + gl_PREREQ_GLOB + + GLOB_H=glob.h + AC_LIBOBJ([glob]) + AC_DEFINE([GLOB_PREFIX], [[rpl_]], + [Define to rpl_ if the glob replacement functions and variables + should be used.]) + AC_SUBST([GLOB_H]) +]) + +AC_DEFUN([gl_GLOB], +[ GLOB_H= + AC_CHECK_HEADERS([glob.h], [], [GLOB_H=glob.h]) + + if test -z "$GLOB_H"; then + AC_COMPILE_IFELSE( +[[#include <gnu-versions.h> +char a[_GNU_GLOB_INTERFACE_VERSION == 1 ? 1 : -1];]], + [], [GLOB_H=glob.h]) + fi + + if test -n "$GLOB_H"; then + gl_GLOB_SUBSTITUTE + fi +]) + +# Prerequisites of lib/glob.*. +AC_DEFUN([gl_PREREQ_GLOB], +[ AC_REQUIRE([gl_CHECK_TYPE_STRUCT_DIRENT_D_TYPE])dnl + AC_REQUIRE([AC_HEADER_DIRENT])dnl + AC_CHECK_HEADERS_ONCE([sys/cdefs.h unistd.h])dnl + AC_CHECK_FUNCS_ONCE([getlogin_r __posix_getpwnam_r getpwnam_r])dnl + :]) Index: modules/glob =================================================================== RCS file: modules/glob diff -N modules/glob --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/glob 24 May 2005 14:43:21 -0000 @@ -0,0 +1,43 @@ +Description: +Search for files and directories with paths matching a pattern. + +Files: +lib/glob_.h +lib/glob.c +m4/d-type.m4 +m4/glob.m4 + +Depends-on: +alloca +extensions +fnmatch +mempcpy +restrict +stat-macros +stdbool +strdup + +configure.ac: +gl_GLOB + +Makefile.am: +BUILT_SOURCES += $(GLOB_H) +EXTRA_DIST += glob_.h + +# We need the following in order to create an <glob.h> when the system +# doesn't have one that works with the given compiler. +all-local $(lib_OBJECTS): $(GLOB_H) +glob.h: glob_.h + cp $(srcdir)/glob_.h $@-t + mv $@-t $@ +MOSTLYCLEANFILES += glob.h glob.h-t + +Include: +<glob.h> + +License: +LGPL + +Maintainer: +all, glibc + --------------060701020108000301020206 Content-Type: text/plain; name="glob-glibc2gnulib8.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="glob-glibc2gnulib8.diff" --- ../glibc-2.3.5/sysdeps/generic/glob.c 2004-10-27 14:21:02.000000000 -0400 +++ lib/glob.c 2005-05-24 10:12:03.000000000 -0400 @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1991-2002, 2003, 2004, 2005 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 @@ -16,23 +16,16 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -/* AIX requires this to be the first thing in the file. */ -#if defined _AIX && !defined __GNUC__ - #pragma alloca -#endif - #ifdef HAVE_CONFIG_H # include <config.h> #endif -/* Enable GNU extensions in glob.h. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif +#include <glob.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> +#include <stddef.h> /* Outcomment the following line for production quality code. */ /* #define NDEBUG 1 */ @@ -40,30 +33,7 @@ #include <stdio.h> /* Needed on stupid SunOS for assert. */ - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#define GLOB_INTERFACE_VERSION 1 -#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 -# include <gnu-versions.h> -# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION -# define ELIDE_CODE -# endif -#endif - -#ifndef ELIDE_CODE #if !defined _LIBC || !defined GLOB_ONLY_P - -#if defined STDC_HEADERS || defined __GNU_LIBRARY__ -# include <stddef.h> -#endif - #if defined HAVE_UNISTD_H || defined _LIBC # include <unistd.h> # ifndef POSIX @@ -71,24 +41,23 @@ # define POSIX # endif # endif +#else +/* Is there really a case where the getlogin or getlogin_r proto can come from + somewhere other than <unistd.h>? */ +# ifdef HAVE_GETLOGIN_R +extern int getlogin_r (char *, size_t); +# else +extern char *getlogin (void); +# endif #endif -#if !defined _AMIGA && !defined VMS && !defined WINDOWS32 -# include <pwd.h> -#endif +#include <pwd.h> -#if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS -extern int errno; -#endif +#include <errno.h> #ifndef __set_errno # define __set_errno(val) errno = (val) #endif -#ifndef NULL -# define NULL 0 -#endif - - #if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ # include <dirent.h> # define NAMLEN(dirent) strlen((dirent)->d_name) @@ -117,17 +86,30 @@ #endif /* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available - if the `d_type' member for `struct dirent' is available. */ -#ifdef _DIRENT_HAVE_D_TYPE + if the `d_type' member for `struct dirent' is available. + HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */ +#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE # define HAVE_D_TYPE 1 -#endif -#if _LIBC -# define HAVE_DIRENT64 1 -#endif +/* True if the directory entry D must be of type T. */ +# define DIRENT_MUST_BE(d, t) ((d)->d_type == (t)) + +/* True if the directory entry D might be a symbolic link. */ +# define DIRENT_MIGHT_BE_SYMLINK(d) \ + ((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK) + +/* True if the directory entry D might be a directory. */ +# define DIRENT_MIGHT_BE_DIR(d) \ + ((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d)) + +#else /* !HAVE_D_TYPE */ +# define DIRENT_MUST_BE(d, t) false +# define DIRENT_MIGHT_BE_SYMLINK(d) true +# define DIRENT_MIGHT_BE_DIR(d) true +#endif /* HAVE_D_TYPE */ /* If the system has the `struct dirent64' type we use it internally. */ -#if defined HAVE_DIRENT64 && !defined COMPILE_GLOB64 +#if defined _LIBC && !defined COMPILE_GLOB64 # if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ # define CONVERT_D_NAMLEN(d64, d32) # else @@ -165,126 +147,18 @@ # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) #endif /* POSIX */ -#if defined STDC_HEADERS || defined __GNU_LIBRARY__ -# include <stdlib.h> -# include <string.h> -# define ANSI_STRING -#else /* No standard headers. */ - -extern char *getenv (); - -# ifdef HAVE_STRING_H -# include <string.h> -# define ANSI_STRING -# else -# include <strings.h> -# endif -# ifdef HAVE_MEMORY_H -# include <memory.h> -# endif - -extern char *malloc (), *realloc (); -extern void free (); - -extern void qsort (); -extern void abort (), exit (); - -#endif /* Standard headers. */ +#include <stdlib.h> +#include <string.h> /* NAME_MAX is usually defined in <dirent.h> or <limits.h>. */ -#if defined HAVE_LIMITS_H || defined __GNU_LIBRARY__ -# include <limits.h> -#endif +#include <limits.h> #ifndef NAME_MAX # define NAME_MAX (sizeof (((struct dirent *) 0)->d_name)) #endif -#ifndef ANSI_STRING - -# ifndef bzero -extern void bzero (); -# endif -# ifndef bcopy -extern void bcopy (); -# endif - -# define memcpy(d, s, n) bcopy ((s), (d), (n)) -# define strrchr rindex -/* memset is only used for zero here, but let's be paranoid. */ -# define memset(s, better_be_zero, n) \ - ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0))) -#endif /* Not ANSI_STRING. */ - -#if !defined HAVE_STRCOLL && !defined _LIBC -# define strcoll strcmp -#endif - -#if !defined HAVE_MEMPCPY && __GLIBC__ - 0 == 2 && __GLIBC_MINOR__ >= 1 -# define HAVE_MEMPCPY 1 -# undef mempcpy -# define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len) -#endif - -#ifndef __GNU_LIBRARY__ -# ifdef __GNUC__ -__inline -# endif -# ifndef __SASC -# ifdef WINDOWS32 -static void * -# else -static char * -# endif -my_realloc (p, n) - char *p; - unsigned int n; -{ - /* These casts are the for sake of the broken Ultrix compiler, - which warns of illegal pointer combinations otherwise. */ - if (p == NULL) - return (char *) malloc (n); - return (char *) realloc (p, n); -} -# define realloc my_realloc -# endif /* __SASC */ -#endif /* __GNU_LIBRARY__ */ - - -#if !defined __alloca && !defined __GNU_LIBRARY__ - -# ifdef __GNUC__ -# undef alloca -# define alloca(n) __builtin_alloca (n) -# else /* Not GCC. */ -# ifdef HAVE_ALLOCA_H -# include <alloca.h> -# else /* Not HAVE_ALLOCA_H. */ -# ifndef _AIX -# ifdef WINDOWS32 -# include <malloc.h> -# else -extern char *alloca (); -# endif /* WINDOWS32 */ -# endif /* Not _AIX. */ -# endif /* sparc or HAVE_ALLOCA_H. */ -# endif /* GCC. */ - -# define __alloca alloca - -#endif - -#ifndef __GNU_LIBRARY__ -# define __stat stat -# ifdef STAT_MACROS_BROKEN -# undef S_ISDIR -# endif -# ifndef S_ISDIR -# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) -# endif -#endif +#include <alloca.h> #ifdef _LIBC -# include <alloca.h> # undef strdup # define strdup(str) __strdup (str) # define sysconf(id) __sysconf (id) @@ -296,52 +170,35 @@ # ifndef __stat64 # define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf) # endif -# define HAVE_STAT64 1 -#endif - -#ifndef HAVE_STAT64 -# define __stat64(fname, buf) __stat (fname, buf) -/* This is the variable name we are using. */ -# define st64 st -#endif - -#if !(defined STDC_HEADERS || defined __GNU_LIBRARY__) -# undef size_t -# define size_t unsigned int -#endif +#else /* !_LIBC */ +# ifdef HAVE___POSIX_GETPWNAM_R + /* Solaris. */ +# define getpwnam_r(name, bufp, buf, len, res) \ + __posix_getpwnam_r (name, bufp, buf, len, res) +# endif +# include "mempcpy.h" +# include "stat-macros.h" +# include "strdup.h" +# define __stat64(fname, buf) stat (fname, buf) +# define stat64 stat +# define __stat(fname, buf) stat (fname, buf) +# define __alloca alloca +# define __readdir readdir +# define __readdir64 readdir64 +#endif /* _LIBC */ -/* Some system header files erroneously define these. - We want our own definitions from <fnmatch.h> to take precedence. */ -#ifndef __GNU_LIBRARY__ -# undef FNM_PATHNAME -# undef FNM_NOESCAPE -# undef FNM_PERIOD -#endif +#include <stdbool.h> #include <fnmatch.h> -/* Some system header files erroneously define these. - We want our own definitions from <glob.h> to take precedence. */ -#ifndef __GNU_LIBRARY__ -# undef GLOB_ERR -# undef GLOB_MARK -# undef GLOB_NOSORT -# undef GLOB_DOOFFS -# undef GLOB_NOCHECK -# undef GLOB_APPEND -# undef GLOB_NOESCAPE -# undef GLOB_PERIOD -#endif -#include <glob.h> - -#ifdef HAVE_GETLOGIN_R -extern int getlogin_r (char *, size_t); +#ifdef _SC_GETPW_R_SIZE_MAX +# define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX) #else -extern char *getlogin (void); +# define GETPW_R_SIZE_MAX() (-1) #endif static const char *next_brace_sub (const char *begin, int flags) __THROW; -#endif /* GLOB_ONLY_P */ +#endif /* !defined _LIBC || !defined GLOB_ONLY_P */ static int glob_in_dir (const char *pattern, const char *directory, int flags, int (*errfunc) (const char *, int), @@ -349,14 +206,12 @@ #if !defined _LIBC || !defined GLOB_ONLY_P static int prefix_array (const char *prefix, char **array, size_t n) __THROW; -static int collated_compare (const __ptr_t, const __ptr_t) __THROW; +static int collated_compare (const void *, const void *) __THROW; /* Find the end of the sub-pattern in a brace expression. */ static const char * -next_brace_sub (cp, flags) - const char *cp; - int flags; +next_brace_sub (const char *cp, int flags) { unsigned int depth = 0; while (*cp != '\0') @@ -378,7 +233,7 @@ return *cp != '\0' ? cp : NULL; } -#endif /* !GLOB_ONLY_P */ +#endif /* !defined _LIBC || !defined GLOB_ONLY_P */ /* Do glob searching for PATTERN, placing results in PGLOB. The bits defined above may be set in FLAGS. @@ -392,11 +247,9 @@ #ifdef GLOB_ATTRIBUTE GLOB_ATTRIBUTE #endif -glob (pattern, flags, errfunc, pglob) - const char *pattern; - int flags; - int (*errfunc) (const char *, int); - glob_t *pglob; +glob (const char *pattern, int flags, + int (*errfunc) (const char *, int), + glob_t *pglob) { const char *filename; const char *dirname; @@ -454,7 +307,7 @@ #ifdef __GNUC__ char onealt[strlen (pattern) - 1]; #else - char *onealt = (char *) malloc (strlen (pattern) - 1); + char *onealt = malloc (strlen (pattern) - 1); if (onealt == NULL) { if (!(flags & GLOB_APPEND)) @@ -467,12 +320,7 @@ #endif /* We know the prefix for all sub-patterns. */ -#ifdef HAVE_MEMPCPY alt_start = mempcpy (onealt, pattern, begin - pattern); -#else - memcpy (onealt, pattern, begin - pattern); - alt_start = &onealt[begin - pattern]; -#endif /* Find the first sub-pattern and at the same time find the rest after the closing brace. */ @@ -525,12 +373,7 @@ int result; /* Construct the new glob expression. */ -#ifdef HAVE_MEMPCPY mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len); -#else - memcpy (alt_start, p, next - p); - memcpy (&alt_start[next - p], rest, rest_len); -#endif result = glob (onealt, ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC)) @@ -624,13 +467,8 @@ char *drive_spec; ++dirlen; - drive_spec = (char *) __alloca (dirlen + 1); -#ifdef HAVE_MEMPCPY + drive_spec = __alloca (dirlen + 1); *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0'; -#else - memcpy (drive_spec, pattern, dirlen); - drive_spec[dirlen] = '\0'; -#endif /* For now, disallow wildcards in the drive spec, to prevent infinite recursion in glob. */ if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE))) @@ -640,13 +478,8 @@ from "d:/", since "d:" and "d:/" are not the same.*/ } #endif - newp = (char *) __alloca (dirlen + 1); -#ifdef HAVE_MEMPCPY + newp = __alloca (dirlen + 1); *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; -#else - memcpy (newp, pattern, dirlen); - newp[dirlen] = '\0'; -#endif dirname = newp; ++filename; @@ -675,8 +508,7 @@ else { size_t i; - pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1) - * sizeof (char *)); + pglob->gl_pathv = malloc ((pglob->gl_offs + 1) * sizeof (char *)); if (pglob->gl_pathv == NULL) return GLOB_NOSPACE; @@ -713,7 +545,7 @@ /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try a moderate value. */ buflen = 20; - name = (char *) __alloca (buflen); + name = __alloca (buflen); success = getlogin_r (name, buflen) >= 0; # else @@ -723,7 +555,7 @@ { struct passwd *p; # if defined HAVE_GETPWNAM_R || defined _LIBC - long int pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX); + long int pwbuflen = GETPW_R_SIZE_MAX (); char *pwtmpbuf; struct passwd pwbuf; int save = errno; @@ -734,7 +566,7 @@ Try a moderate value. */ pwbuflen = 1024; # endif - pwtmpbuf = (char *) __alloca (pwbuflen); + pwtmpbuf = __alloca (pwbuflen); while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) != 0) @@ -749,7 +581,7 @@ 2 * pwbuflen); # else pwbuflen *= 2; - pwtmpbuf = (char *) __alloca (pwbuflen); + pwtmpbuf = __alloca (pwbuflen); # endif __set_errno (save); } @@ -776,14 +608,9 @@ { char *newp; size_t home_len = strlen (home_dir); - newp = (char *) __alloca (home_len + dirlen); -# ifdef HAVE_MEMPCPY + newp = __alloca (home_len + dirlen); mempcpy (mempcpy (newp, home_dir, home_len), &dirname[1], dirlen); -# else - memcpy (newp, home_dir, home_len); - memcpy (&newp[home_len], &dirname[1], dirlen); -# endif dirname = newp; } } @@ -799,14 +626,9 @@ else { char *newp; - newp = (char *) __alloca (end_name - dirname); -# ifdef HAVE_MEMPCPY + newp = __alloca (end_name - dirname); *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) = '\0'; -# else - memcpy (newp, dirname + 1, end_name - dirname); - newp[end_name - dirname - 1] = '\0'; -# endif user_name = newp; } @@ -814,7 +636,7 @@ { struct passwd *p; # if defined HAVE_GETPWNAM_R || defined _LIBC - long int buflen = sysconf (_SC_GETPW_R_SIZE_MAX); + long int buflen = GETPW_R_SIZE_MAX (); char *pwtmpbuf; struct passwd pwbuf; int save = errno; @@ -825,7 +647,7 @@ moderate value. */ buflen = 1024; # endif - pwtmpbuf = (char *) __alloca (buflen); + pwtmpbuf = __alloca (buflen); while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0) { @@ -856,15 +678,9 @@ char *newp; size_t home_len = strlen (home_dir); size_t rest_len = end_name == NULL ? 0 : strlen (end_name); - newp = (char *) __alloca (home_len + rest_len + 1); -# ifdef HAVE_MEMPCPY + newp = __alloca (home_len + rest_len + 1); *((char *) mempcpy (mempcpy (newp, home_dir, home_len), end_name, rest_len)) = '\0'; -# else - memcpy (newp, home_dir, home_len); - memcpy (&newp[home_len], end_name, rest_len); - newp[home_len + rest_len] = '\0'; -# endif dirname = newp; } else @@ -882,9 +698,7 @@ if (filename == NULL) { struct stat st; -#ifdef HAVE_STAT64 struct stat64 st64; -#endif /* Return the directory if we don't check for error or if it exists. */ if ((flags & GLOB_NOCHECK) @@ -897,8 +711,7 @@ char **new_gl_pathv; new_gl_pathv - = (char **) realloc (pglob->gl_pathv, - (newcount + 1 + 1) * sizeof (char *)); + = realloc (pglob->gl_pathv, (newcount + 1 + 1) * sizeof (char *)); if (new_gl_pathv == NULL) { nospace: @@ -909,16 +722,7 @@ } pglob->gl_pathv = new_gl_pathv; -#if defined HAVE_STRDUP || defined _LIBC pglob->gl_pathv[newcount] = strdup (dirname); -#else - { - size_t len = strlen (dirname) + 1; - char *dircopy = (char *) malloc (len); - if (dircopy != NULL) - pglob->gl_pathv[newcount] = memcpy (dircopy, dirname, len); - } -#endif if (pglob->gl_pathv[newcount] == NULL) goto nospace; pglob->gl_pathv[++newcount] = NULL; @@ -1021,9 +825,8 @@ int newcount = pglob->gl_pathc + pglob->gl_offs; char **new_gl_pathv; - new_gl_pathv = (char **) realloc (pglob->gl_pathv, - (newcount + 2) - * sizeof (char *)); + new_gl_pathv = realloc (pglob->gl_pathv, + (newcount + 2) * sizeof (char *)); if (new_gl_pathv == NULL) { globfree (&dirs); @@ -1031,7 +834,7 @@ } pglob->gl_pathv = new_gl_pathv; - pglob->gl_pathv[newcount] = __strdup (pattern); + pglob->gl_pathv[newcount] = strdup (pattern); if (pglob->gl_pathv[newcount] == NULL) { globfree (&dirs); @@ -1077,39 +880,10 @@ } } - if (flags & GLOB_MARK) - { - /* Append slashes to directory names. */ - size_t i; - struct stat st; -#ifdef HAVE_STAT64 - struct stat64 st64; -#endif - - for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i) - if (((flags & GLOB_ALTDIRFUNC) - ? ((*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; - return GLOB_NOSPACE; - } - strcpy (&new[len - 2], "/"); - pglob->gl_pathv[i] = new; - } - } - if (!(flags & GLOB_NOSORT)) { /* Sort the vector. */ - qsort ((__ptr_t) &pglob->gl_pathv[oldcount], + qsort (&pglob->gl_pathv[oldcount], pglob->gl_pathc + pglob->gl_offs - oldcount, sizeof (char *), collated_compare); } @@ -1125,16 +899,15 @@ /* Free storage allocated in PGLOB by a previous `glob' call. */ void -globfree (pglob) - register glob_t *pglob; +globfree (register glob_t *pglob) { if (pglob->gl_pathv != NULL) { size_t i; for (i = 0; i < pglob->gl_pathc; ++i) if (pglob->gl_pathv[pglob->gl_offs + i] != NULL) - free ((__ptr_t) pglob->gl_pathv[pglob->gl_offs + i]); - free ((__ptr_t) pglob->gl_pathv); + free (pglob->gl_pathv[pglob->gl_offs + i]); + free (pglob->gl_pathv); pglob->gl_pathv = NULL; } } @@ -1145,9 +918,7 @@ /* Do a collated comparison of A and B. */ static int -collated_compare (a, b) - const __ptr_t a; - const __ptr_t b; +collated_compare (const void *a, const void *b) { const char *const s1 = *(const char *const * const) a; const char *const s2 = *(const char *const * const) b; @@ -1167,10 +938,7 @@ A slash is inserted between DIRNAME and each elt of ARRAY, unless DIRNAME is just "/". Each old element of ARRAY is freed. */ static int -prefix_array (dirname, array, n) - const char *dirname; - char **array; - size_t n; +prefix_array (const char *dirname, char **array, size_t n) { register size_t i; size_t dirlen = strlen (dirname); @@ -1203,26 +971,20 @@ for (i = 0; i < n; ++i) { size_t eltlen = strlen (array[i]) + 1; - char *new = (char *) malloc (dirlen + 1 + eltlen); + char *new = malloc (dirlen + 1 + eltlen); if (new == NULL) { while (i > 0) - free ((__ptr_t) array[--i]); + free (array[--i]); return 1; } -#ifdef HAVE_MEMPCPY { - char *endp = (char *) mempcpy (new, dirname, dirlen); + char *endp = mempcpy (new, dirname, dirlen); *endp++ = DIRSEP_CHAR; mempcpy (endp, array[i], eltlen); } -#else - memcpy (new, dirname, dirlen); - new[dirlen] = DIRSEP_CHAR; - memcpy (&new[dirlen + 1], array[i], eltlen); -#endif - free ((__ptr_t) array[i]); + free (array[i]); array[i] = new; } @@ -1235,9 +997,7 @@ /* Return nonzero if PATTERN contains any metacharacters. Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ int -__glob_pattern_p (pattern, quote) - const char *pattern; - int quote; +__glob_pattern_p (const char *pattern, int quote) { register const char *p; int open = 0; @@ -1277,27 +1037,21 @@ /* We put this in a separate function mainly to allow the memory allocated with alloca to be recycled. */ #if !defined _LIBC || !defined GLOB_ONLY_P -static int -link_exists_p (const char *dir, size_t dirlen, const char *fname, - glob_t *pglob, int flags) +static bool +is_dir_p (const char *dir, size_t dirlen, const char *fname, + glob_t *pglob, int flags) { size_t fnamelen = strlen (fname); - char *fullname = (char *) __alloca (dirlen + 1 + fnamelen + 1); + char *fullname = __alloca (dirlen + 1 + fnamelen + 1); struct stat st; struct stat64 st64; -# ifdef HAVE_MEMPCPY mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1), fname, fnamelen + 1); -# else - memcpy (fullname, dir, dirlen); - fullname[dirlen] = '/'; - memcpy (&fullname[dirlen + 1], fname, fnamelen + 1); -# endif - return (((flags & GLOB_ALTDIRFUNC) - ? (*pglob->gl_stat) (fullname, &st) - : __stat64 (fullname, &st64)) == 0); + return ((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_stat) (fullname, &st) == 0 && S_ISDIR (st.st_mode) + : __stat64 (fullname, &st64) == 0 && S_ISDIR (st64.st_mode)); } #endif @@ -1307,15 +1061,12 @@ 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 (pattern, directory, flags, errfunc, pglob) - const char *pattern; - const char *directory; - int flags; - int (*errfunc) (const char *, int); - glob_t *pglob; +glob_in_dir (const char *pattern, const char *directory, int flags, + int (*errfunc) (const char *, int), + glob_t *pglob) { size_t dirlen = strlen (directory); - __ptr_t stream = NULL; + void *stream = NULL; struct globlink { struct globlink *next; @@ -1341,21 +1092,13 @@ /* Since we use the normal file functions we can also use stat() to verify the file is there. */ struct stat st; -# ifdef HAVE_STAT64 struct stat64 st64; -# endif size_t patlen = strlen (pattern); - char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1); + char *fullname = __alloca (dirlen + 1 + patlen + 1); -# ifdef HAVE_MEMPCPY mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), "/", 1), pattern, patlen + 1); -# else - memcpy (fullname, directory, dirlen); - fullname[dirlen] = '/'; - memcpy (&fullname[dirlen + 1], pattern, patlen + 1); -# endif if (((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_stat) (fullname, &st) : __stat64 (fullname, &st64)) == 0) @@ -1371,8 +1114,8 @@ { /* This is a special case for matching directories like in "*a/". */ - names = (struct globlink *) __alloca (sizeof (struct globlink)); - names->name = (char *) malloc (1); + names = __alloca (sizeof (struct globlink)); + names->name = malloc (1); if (names->name == NULL) goto memory_error; names->name[0] = '\0'; @@ -1384,7 +1127,7 @@ { stream = ((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_opendir) (directory) - : (__ptr_t) opendir (directory)); + : opendir (directory)); if (stream == NULL) { if (errno != ENOTDIR @@ -1409,7 +1152,7 @@ { const char *name; size_t len; -#if defined HAVE_DIRENT64 && !defined COMPILE_GLOB64 +#if defined _LIBC && !defined COMPILE_GLOB64 struct dirent64 *d; union { @@ -1431,54 +1174,55 @@ d = NULL; } else - d = __readdir64 ((DIR *) stream); + d = __readdir64 (stream); #else struct dirent *d = ((flags & GLOB_ALTDIRFUNC) - ? ((struct dirent *) - (*pglob->gl_readdir) (stream)) - : __readdir ((DIR *) stream)); + ? ((*pglob->gl_readdir) (stream)) + : __readdir (stream)); #endif if (d == NULL) break; if (! REAL_DIR_ENTRY (d)) continue; -#ifdef HAVE_D_TYPE /* If we shall match only directories use the information provided by the dirent call if possible. */ - if ((flags & GLOB_ONLYDIR) - && d->d_type != DT_UNKNOWN - && d->d_type != DT_DIR - && d->d_type != DT_LNK) + if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d)) continue; -#endif name = d->d_name; if (fnmatch (pattern, name, fnm_flags) == 0) { - /* If the file we found is a symlink we have to - make sure the target file exists. */ - if ( -#ifdef HAVE_D_TYPE - (d->d_type != DT_UNKNOWN && d->d_type != DT_LNK) || -#endif - link_exists_p (directory, dirlen, name, pglob, - flags)) + /* ISDIR will often be incorrectly set to false + when not in GLOB_ONLYDIR || GLOB_MARK mode, but we + don't care. It won't be used and we save the + expensive call to stat. */ + int need_dir_test = + (GLOB_MARK | (DIRENT_MIGHT_BE_SYMLINK (d) + ? GLOB_ONLYDIR : 0)); + bool isdir = (DIRENT_MUST_BE (d, DT_DIR) + || ((flags & need_dir_test) + && is_dir_p (directory, dirlen, name, + pglob, flags))); + + /* In GLOB_ONLYDIR mode, skip non-dirs. */ + if ((flags & GLOB_ONLYDIR) && !isdir) + continue; + { - struct globlink *new = (struct globlink *) + struct globlink *new = __alloca (sizeof (struct globlink)); + char *p; len = NAMLEN (d); - new->name = (char *) malloc (len + 1); + new->name = + malloc (len + 1 + ((flags & GLOB_MARK) && isdir)); if (new->name == NULL) goto memory_error; -#ifdef HAVE_MEMPCPY - *((char *) mempcpy ((__ptr_t) new->name, name, len)) - = '\0'; -#else - memcpy ((__ptr_t) new->name, name, len); - new->name[len] = '\0'; -#endif + p = mempcpy (new->name, name, len); + if ((flags & GLOB_MARK) && isdir) + *p++ = '/'; + *p = '\0'; new->next = names; names = new; ++nfound; @@ -1493,17 +1237,12 @@ { size_t len = strlen (pattern); nfound = 1; - names = (struct globlink *) __alloca (sizeof (struct globlink)); + names = __alloca (sizeof (struct globlink)); names->next = NULL; - names->name = (char *) malloc (len + 1); + names->name = malloc (len + 1); if (names->name == NULL) goto memory_error; -#ifdef HAVE_MEMPCPY *((char *) mempcpy (names->name, pattern, len)) = '\0'; -#else - memcpy (names->name, pattern, len); - names->name[len] = '\0'; -#endif } if (nfound != 0) @@ -1511,9 +1250,9 @@ char **new_gl_pathv; new_gl_pathv - = (char **) 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) goto memory_error; pglob->gl_pathv = new_gl_pathv; @@ -1531,7 +1270,7 @@ if (flags & GLOB_ALTDIRFUNC) (*pglob->gl_closedir) (stream); else - closedir ((DIR *) stream); + closedir (stream); } __set_errno (save); @@ -1543,16 +1282,14 @@ if (flags & GLOB_ALTDIRFUNC) (*pglob->gl_closedir) (stream); else - closedir ((DIR *) stream); + closedir (stream); __set_errno (save); } while (names != NULL) { if (names->name != NULL) - free ((__ptr_t) names->name); + free (names->name); names = names->next; } return GLOB_NOSPACE; } - -#endif /* Not ELIDE_CODE. */ --- ../glibc-2.3.5/posix/glob.h 2004-09-16 20:55:15.000000000 -0400 +++ lib/glob_.h 2005-05-24 10:05:53.000000000 -0400 @@ -19,29 +19,40 @@ #ifndef _GLOB_H #define _GLOB_H 1 -#include <sys/cdefs.h> +#if defined _LIBC || HAVE_SYS_CDEFS_H +# include <sys/cdefs.h> +#endif +/* We need `size_t' for the following definitions. */ +#ifdef _LIBC __BEGIN_DECLS -/* We need `size_t' for the following definitions. */ -#ifndef __size_t -# if defined __GNUC__ && __GNUC__ >= 2 +# ifndef __size_t typedef __SIZE_TYPE__ __size_t; # ifdef __USE_XOPEN typedef __SIZE_TYPE__ size_t; # endif # else -# include <stddef.h> -# 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 +#else /* !_LIBC */ +# include <stddef.h> # undef __size_t -# define __size_t size_t -#endif +# define __size_t size_t +/* The following are necessary with MSVC and who knows where else. */ +# ifndef __const +# define __const const +# endif +# ifndef __restrict +# define __restrict restrict +# endif +# ifndef __USE_GNU +# define __USE_GNU 1 +# endif +#endif /* _LIBC */ /* Bits set in the FLAGS argument to `glob'. */ #define GLOB_ERR (1 << 0)/* Return on read errors. */ @@ -112,7 +123,7 @@ #endif } glob_t; -#ifdef __USE_LARGEFILE64 +#if defined _LIBC && defined __USE_LARGEFILE64 # ifdef __USE_GNU struct stat64; # endif @@ -142,9 +153,21 @@ } glob64_t; #endif -#if __USE_FILE_OFFSET64 && __GNUC__ < 2 -# define glob glob64 -# define globfree globfree64 +#ifdef GLOB_PREFIX +# define __GLOB_CONCAT(x, y) x ## y +# define __GLOB_XCONCAT(x, y) __GLOB_CONCAT (x, y) +# define __GLOB_ID(y) __GLOB_XCONCAT (GLOB_PREFIX, y) +# define glob __GLOB_ID (glob) +# define globfree __GLOB_ID (globfree) +# define glob_pattern_p __GLOB_ID (glob_pattern_p) +#endif + +#ifndef _LIBC +# define __glob_pattern_p glob_pattern_p +#endif + +#ifndef __THROW +# define __THROW #endif /* Do glob searching for PATTERN, placing results in PGLOB. @@ -155,7 +178,7 @@ `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 +#if !defined _LIBC || !defined __USE_FILE_OFFSET64 extern int glob (__const char *__restrict __pattern, int __flags, int (*__errfunc) (__const char *, int), glob_t *__restrict __pglob) __THROW; @@ -171,7 +194,7 @@ extern void __REDIRECT_NTH (globfree, (glob_t *__pglob), globfree64); #endif -#ifdef __USE_LARGEFILE64 +#if defined _LIBC && defined __USE_LARGEFILE64 extern int glob64 (__const char *__restrict __pattern, int __flags, int (*__errfunc) (__const char *, int), glob64_t *__restrict __pglob) __THROW; @@ -189,6 +212,8 @@ extern int glob_pattern_p (__const char *__pattern, int __quote) __THROW; #endif +#ifdef _LIBC __END_DECLS +#endif #endif /* glob.h */ --------------060701020108000301020206 Content-Type: text/plain; name="glob.7-8.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="glob.7-8.diff" Index: lib/glob.c =================================================================== RCS file: /cvs/ccvs/lib/glob.c,v retrieving revision 1.8 diff -u -p -r1.8 glob.c --- lib/glob.c 18 May 2005 18:49:21 -0000 1.8 +++ lib/glob.c 24 May 2005 14:47:45 -0000 @@ -41,6 +41,14 @@ # define POSIX # endif # endif +#else +/* Is there really a case where the getlogin or getlogin_r proto can come from + somewhere other than <unistd.h>? */ +# ifdef HAVE_GETLOGIN_R +extern int getlogin_r (char *, size_t); +# else +extern char *getlogin (void); +# endif #endif #include <pwd.h> @@ -100,12 +108,8 @@ # define DIRENT_MIGHT_BE_DIR(d) true #endif /* HAVE_D_TYPE */ -#if _LIBC -# define HAVE_STRUCT_DIRENT64 1 -#endif - /* If the system has the `struct dirent64' type we use it internally. */ -#if defined HAVE_STRUCT_DIRENT64 && !defined COMPILE_GLOB64 +#if defined _LIBC && !defined COMPILE_GLOB64 # if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ # define CONVERT_D_NAMLEN(d64, d32) # else @@ -152,8 +156,9 @@ # define NAME_MAX (sizeof (((struct dirent *) 0)->d_name)) #endif +#include <alloca.h> + #ifdef _LIBC -# include <alloca.h> # undef strdup # define strdup(str) __strdup (str) # define sysconf(id) __sysconf (id) @@ -165,37 +170,26 @@ # ifndef __stat64 # define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf) # endif -# define HAVE_STAT64 1 #else /* !_LIBC */ +# ifdef HAVE___POSIX_GETPWNAM_R + /* Solaris. */ +# define getpwnam_r(name, bufp, buf, len, res) \ + __posix_getpwnam_r (name, bufp, buf, len, res) +# endif # include "mempcpy.h" # include "stat-macros.h" # include "strdup.h" +# define __stat64(fname, buf) stat (fname, buf) +# define stat64 stat +# define __stat(fname, buf) stat (fname, buf) +# define __alloca alloca +# define __readdir readdir +# define __readdir64 readdir64 #endif /* _LIBC */ #include <stdbool.h> -#include <alloca.h> #include <fnmatch.h> -#ifndef HAVE_STAT64 -# define __stat64(fname, buf) __stat (fname, buf) -# define stat64 stat -#elif !defined _LIBC -# define __stat64 stat64 -#endif - -#ifndef _LIBC -# define __stat stat -# define __alloca alloca -# define __readdir readdir -# define __readdir64 readdir64 -#endif - -#ifdef HAVE_GETLOGIN_R -extern int getlogin_r (char *, size_t); -#else -extern char *getlogin (void); -#endif - #ifdef _SC_GETPW_R_SIZE_MAX # define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX) #else @@ -1158,7 +1152,7 @@ glob_in_dir (const char *pattern, const { const char *name; size_t len; -#if defined HAVE_STRUCT_DIRENT64 && !defined COMPILE_GLOB64 +#if defined _LIBC && !defined COMPILE_GLOB64 struct dirent64 *d; union { Index: lib/glob_.h =================================================================== RCS file: /cvs/ccvs/lib/glob_.h,v retrieving revision 1.7 diff -u -p -r1.7 glob_.h --- lib/glob_.h 18 May 2005 16:17:15 -0000 1.7 +++ lib/glob_.h 24 May 2005 14:58:54 -0000 @@ -123,7 +123,7 @@ typedef struct #endif } glob_t; -#ifdef __USE_LARGEFILE64 +#if defined _LIBC && defined __USE_LARGEFILE64 # ifdef __USE_GNU struct stat64; # endif @@ -194,7 +194,7 @@ extern int __REDIRECT_NTH (glob, (__cons extern void __REDIRECT_NTH (globfree, (glob_t *__pglob), globfree64); #endif -#ifdef __USE_LARGEFILE64 +#if defined _LIBC && defined __USE_LARGEFILE64 extern int glob64 (__const char *__restrict __pattern, int __flags, int (*__errfunc) (__const char *, int), glob64_t *__restrict __pglob) __THROW; Index: m4/glob.m4 =================================================================== RCS file: /cvs/ccvs/m4/glob.m4,v retrieving revision 1.5 diff -u -p -r1.5 glob.m4 --- m4/glob.m4 18 May 2005 16:16:44 -0000 1.5 +++ m4/glob.m4 24 May 2005 15:01:25 -0000 @@ -40,7 +40,6 @@ char a[_GNU_GLOB_INTERFACE_VERSION == 1 AC_DEFUN([gl_PREREQ_GLOB], [ AC_REQUIRE([gl_CHECK_TYPE_STRUCT_DIRENT_D_TYPE])dnl AC_REQUIRE([AC_HEADER_DIRENT])dnl - AC_CHECK_HEADERS_ONCE([sys/cdefs.h])dnl - AC_CHECK_FUNCS_ONCE([getlogin_r getpwnam_r stat64])dnl - AC_CHECK_TYPES([struct dirent64])dnl + AC_CHECK_HEADERS_ONCE([sys/cdefs.h unistd.h])dnl + AC_CHECK_FUNCS_ONCE([getlogin_r __posix_getpwnam_r getpwnam_r])dnl :]) --------------060701020108000301020206 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ bug-gnulib mailing list [email protected] http://lists.gnu.org/mailman/listinfo/bug-gnulib --------------060701020108000301020206--