From ee74a442e8b9403f02f7e933260625acf145ad08 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Tue, 12 May 1998 12:22:17 +0000 Subject: Update. 1998-05-12 12:15 Ulrich Drepper * posix/glob.c: Move to ... * sysdeps/generic/glob.c: ...here. * posix/glob.h (glob_t): Use correct types for gl_pathc and gl_offs elements. * sysdeps/unix/sysv/linux/alpha/glob.c: New file. * sysdeps/unix/sysv/linux/alpha/oldglob.c: New file. * sysdeps/unix/sysv/linux/alpha/Dist: Add oldglob.c. * sysdeps/unix/sysv/linux/alpha/Makefile: Compile oldglob in posix subdir. * libc.map [GLIBC_2.1]: Add glob and globfree. 1998-05-12 Ulrich Drepper * sunrpc/Makefile (generated): Restore old list. 1998-05-11 Andreas Jaeger * rt/Makefile (tests): Define only if we have a thread library. * nis/ypclnt.c: Add: #include . 1998-05-10 15:39 Zack Weinberg * configure.in: Define and substitute RELEASE as well as VERSION. * config.make.in: Add RELEASE and VERSION to be substituted. * Makeconfig: Delete all references to version.mk. * Make-dist: Likewise. * MakeTAGS: Likewise. * elf/Makefile: Likewise. 1998-05-10 Thorsten Kukuk * nis/ypclnt.c: Move "(none)" domainname check from __yp_check to yp_get_default_domain. 1998-05-12 Ulrich Drepper * sysdeps/posix/profil.c (__profil): Don't define act and timer variables as static. Patch by Joe Keane . 1998-05-12 Wolfram Gloger * malloc/malloc.c: Fix for NO_THREADS case. Remove statfs and fstatfs. and pwrite as EXTRA. * sysdeps/unix/sysv/linux/sparc/sparc64/syscalls.list: Likewise. --- .cvsignore | 2 +- ChangeLog | 53 +- Make-dist | 1 - MakeTAGS | 3 - Makeconfig | 14 - config.make.in | 3 + configure | 5 +- configure.in | 4 +- elf/Makefile | 4 +- libc.map | 2 +- malloc/malloc.c | 20 +- nis/ypclnt.c | 9 +- posix/glob.c | 1114 ------------------------------- posix/glob.h | 6 +- rt/Makefile | 4 +- sunrpc/Makefile | 3 +- sysdeps/generic/glob.c | 1114 +++++++++++++++++++++++++++++++ sysdeps/unix/sysv/linux/alpha/Dist | 1 + sysdeps/unix/sysv/linux/alpha/Makefile | 4 + sysdeps/unix/sysv/linux/alpha/glob.c | 30 + sysdeps/unix/sysv/linux/alpha/oldglob.c | 94 +++ 21 files changed, 1337 insertions(+), 1153 deletions(-) delete mode 100644 posix/glob.c create mode 100644 sysdeps/generic/glob.c create mode 100644 sysdeps/unix/sysv/linux/alpha/glob.c create mode 100644 sysdeps/unix/sysv/linux/alpha/oldglob.c diff --git a/.cvsignore b/.cvsignore index b907f7a024..9140e6d68e 100644 --- a/.cvsignore +++ b/.cvsignore @@ -22,4 +22,4 @@ releases crypt linuxthreads -aio +libc.prj .libc.prcs_aux diff --git a/ChangeLog b/ChangeLog index b76a5c406b..ef8d9a1c22 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,57 @@ +1998-05-12 12:15 Ulrich Drepper + + * posix/glob.c: Move to ... + * sysdeps/generic/glob.c: ...here. + * posix/glob.h (glob_t): Use correct types for gl_pathc and gl_offs + elements. + * sysdeps/unix/sysv/linux/alpha/glob.c: New file. + * sysdeps/unix/sysv/linux/alpha/oldglob.c: New file. + * sysdeps/unix/sysv/linux/alpha/Dist: Add oldglob.c. + * sysdeps/unix/sysv/linux/alpha/Makefile: Compile oldglob in posix + subdir. + * libc.map [GLIBC_2.1]: Add glob and globfree. + +1998-05-12 Ulrich Drepper + + * sunrpc/Makefile (generated): Restore old list. + +1998-05-11 Andreas Jaeger + + * rt/Makefile (tests): Define only if we have a thread library. + + * nis/ypclnt.c: Add: #include . + +1998-05-10 15:39 Zack Weinberg + + * configure.in: Define and substitute RELEASE as well as + VERSION. + * config.make.in: Add RELEASE and VERSION to be substituted. + * Makeconfig: Delete all references to version.mk. + * Make-dist: Likewise. + * MakeTAGS: Likewise. + * elf/Makefile: Likewise. + +1998-05-10 Thorsten Kukuk + + * nis/ypclnt.c: Move "(none)" domainname check from __yp_check to + yp_get_default_domain. + +1998-05-12 Ulrich Drepper + + * sysdeps/posix/profil.c (__profil): Don't define act and timer + variables as static. Patch by Joe Keane . + +1998-05-12 Wolfram Gloger + + * malloc/malloc.c: Fix for NO_THREADS case. + 1998-05-11 18:02 Richard Henderson * sysdeps/unix/sysv/linux/alpha/Makefile (sysdep_routines): - Remove statfs and fstatfs. + Remove statfs and fstatfs. * sysdeps/unix/sysv/linux/alpha/syscalls.list: Don't mark pread - and pwrite as EXTRA. - * sysdeps/unix/sysv/linux/sparc/sparc64/syscalls.list: Likewise. + and pwrite as EXTRA. + * sysdeps/unix/sysv/linux/sparc/sparc64/syscalls.list: Likewise. 1998-05-09 Ulrich Drepper diff --git a/Make-dist b/Make-dist index 293598febc..13df78abce 100644 --- a/Make-dist +++ b/Make-dist @@ -132,7 +132,6 @@ foo:=$(shell echo '+tsrcs=$(+tsrcs)'>&2) foo:=$(shell echo foobie, dammit! >&2) ifndef tardir --include $(common-objpfx)version.mk export tardir := glibc-$(version) endif diff --git a/MakeTAGS b/MakeTAGS index 57d7a5b766..b4320ee896 100644 --- a/MakeTAGS +++ b/MakeTAGS @@ -163,9 +163,6 @@ $P/subdirs.pot: $(subdirs:%=$P/%.pot) do sed "/^#:/s% % $$d/%g" $P/$$d.pot; done) > $@.new mv -f $@.new $@ -# Get $(version) defined. -include $(common-objpfx)version.mk - # Combine all the messages into the final sorted template translation file. # The following code requires GNU date. $P/libc.pot: $(all-pot) diff --git a/Makeconfig b/Makeconfig index 1948e79512..8cdf8c6a76 100644 --- a/Makeconfig +++ b/Makeconfig @@ -657,15 +657,6 @@ ifndef BUILD_CC BUILD_CC = $(CC) endif -# Figure out the version numbers from version.h. - -$(common-objpfx)version.mk: $(..)version.h $(..)Makeconfig - sed -n -e 's/^.*RELEASE.*"\([^"]*\)".*$$/release=\1/p' \ - -e 's/^.*VERSION.*"\([^"]*\)".*$$/version=\1/p' \ - < $< > $@-new - mv -f $@-new $@ - -common-generated += version.mk ifeq (yes, $(build-shared)) @@ -704,11 +695,6 @@ endif postclean-generated += soversions.mk -ifndef avoid-generated -# Get $(version) defined with the release version number. --include $(common-objpfx)version.mk -endif - # Generate the header containing the names of all shared libraries. # We use a stamp file to avoid uncessary recompilations. before-compile += $(common-objpfx)gnu/lib-names.h diff --git a/config.make.in b/config.make.in index 1838b5da1d..d23ee8dbd8 100644 --- a/config.make.in +++ b/config.make.in @@ -2,6 +2,9 @@ # From $Id$. # Don't edit this file. Put configuration parameters in configparms instead. +version = @VERSION@ +release = @RELEASE@ + # Installation prefixes. install_root = prefix = @prefix@ diff --git a/configure b/configure index 66db82f857..5e6f231bd1 100755 --- a/configure +++ b/configure @@ -2870,7 +2870,9 @@ else config_makefile=Makefile fi -VERSION=`sed -e 's/^#define VERSION "\([^"]*\)"/\1/p' -e d < $srcdir/version.h` +VERSION=`sed -n -e 's/^#define VERSION "\([^"]*\)"/\1/p' < $srcdir/version.h` +RELEASE=`sed -n -e 's/^#define RELEASE "\([^"]*\)"/\1/p' < $srcdir/version.h` + trap '' 1 2 15 @@ -3067,6 +3069,7 @@ s%@static_nss@%$static_nss%g s%@nopic_initfini@%$nopic_initfini%g s%@DEFINES@%$DEFINES%g s%@VERSION@%$VERSION%g +s%@RELEASE@%$RELEASE%g CEOF EOF diff --git a/configure.in b/configure.in index 3c711edd80..d04c18b0b3 100644 --- a/configure.in +++ b/configure.in @@ -1159,8 +1159,10 @@ else config_makefile=Makefile fi -VERSION=`sed -e 's/^#define VERSION "\([^"]*\)"/\1/p' -e d < $srcdir/version.h` +VERSION=`sed -n -e 's/^#define VERSION "\([^"]*\)"/\1/p' < $srcdir/version.h` +RELEASE=`sed -n -e 's/^#define RELEASE "\([^"]*\)"/\1/p' < $srcdir/version.h` AC_SUBST(VERSION) +AC_SUBST(RELEASE) AC_OUTPUT(config.make glibcbug ${config_makefile} ${config_uname}, , [echo '$config_vars' >> config.make; test -d bits || mkdir bits]) diff --git a/elf/Makefile b/elf/Makefile index 2c164158b3..2f2e4b1934 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -191,8 +191,8 @@ sed $($(ldd-shell)-ldd-rewrite) < $< | sed -f $(ldd-rewrite-script) > $@.new endef endif -$(objpfx)ldd: ldd.$(ldd-shell).in $(common-objpfx)version.mk \ - $(common-objpfx)soversions.mk $(common-objpfx)config.make +$(objpfx)ldd: ldd.$(ldd-shell).in $(common-objpfx)soversions.mk \ + $(common-objpfx)config.make $(gen-ldd) chmod 555 $@.new mv -f $@.new $@ diff --git a/libc.map b/libc.map index 2d77216648..5f50ad43b1 100644 --- a/libc.map +++ b/libc.map @@ -470,7 +470,7 @@ GLIBC_2.1 { __key_gendes_LOCAL; # chown interface change. - chown; + chown; glob; globfree; # Change in pthread_attr_t. pthread_attr_init; diff --git a/malloc/malloc.c b/malloc/malloc.c index 78e6b399b2..4306a0a12f 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -1195,11 +1195,13 @@ static Void_t* realloc_check(Void_t* oldmem, size_t bytes, const Void_t *caller); static Void_t* memalign_check(size_t alignment, size_t bytes, const Void_t *caller); +#ifndef NO_THREADS static Void_t* malloc_starter(size_t sz, const Void_t *caller); static void free_starter(Void_t* mem, const Void_t *caller); static Void_t* malloc_atfork(size_t sz, const Void_t *caller); static void free_atfork(Void_t* mem, const Void_t *caller); #endif +#endif #else @@ -1216,11 +1218,13 @@ static Void_t* malloc_check(); static void free_check(); static Void_t* realloc_check(); static Void_t* memalign_check(); +#ifndef NO_THREADS static Void_t* malloc_starter(); static void free_starter(); static Void_t* malloc_atfork(); static void free_atfork(); #endif +#endif #endif @@ -1533,6 +1537,8 @@ static unsigned long max_mmapped_mem = 0; int __malloc_initialized = -1; +#ifndef NO_THREADS + /* The following two functions are registered via thread_atfork() to make sure that the mutexes remain in a consistent state in the fork()ed version of a thread. Also adapt the malloc and free hooks @@ -1605,6 +1611,8 @@ ptmalloc_init_all __MALLOC_P((void)) (void)mutex_init(&list_lock); } +#endif + /* Initialization routine. */ #if defined(_LIBC) #if 0 @@ -1624,6 +1632,7 @@ ptmalloc_init __MALLOC_P((void)) if(__malloc_initialized >= 0) return; __malloc_initialized = 0; +#ifndef NO_THREADS #if defined _LIBC || defined MALLOC_HOOKS /* With some threads implementations, creating thread-specific data or initializing a mutex may call malloc() itself. Provide a @@ -1633,18 +1642,17 @@ ptmalloc_init __MALLOC_P((void)) __malloc_hook = malloc_starter; __free_hook = free_starter; #endif -#if defined _LIBC && !defined NO_THREADS +#ifdef _LIBC /* Initialize the pthreads interface. */ if (__pthread_initialize != NULL) __pthread_initialize(); #endif -#ifndef NO_THREADS mutex_init(&main_arena.mutex); mutex_init(&list_lock); tsd_key_create(&arena_key, NULL); tsd_setspecific(arena_key, (Void_t *)&main_arena); thread_atfork(ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_init_all); -#endif +#endif /* !defined NO_THREADS */ #if defined _LIBC || defined MALLOC_HOOKS if((s = getenv("MALLOC_TRIM_THRESHOLD_"))) mALLOPt(M_TRIM_THRESHOLD, atoi(s)); @@ -1655,8 +1663,10 @@ ptmalloc_init __MALLOC_P((void)) if((s = getenv("MALLOC_MMAP_MAX_"))) mALLOPt(M_MMAP_MAX, atoi(s)); s = getenv("MALLOC_CHECK_"); +#ifndef NO_THREADS __malloc_hook = save_malloc_hook; __free_hook = save_free_hook; +#endif if(s) { if(s[0]) mALLOPt(M_CHECK_ACTION, (int)(s[0] - '0')); __malloc_check_init(); @@ -4431,6 +4441,8 @@ memalign_check(alignment, bytes, caller) return chunk2mem_check(p, bytes); } +#ifndef NO_THREADS + /* The following hooks are used when the global initialization in ptmalloc_init() hasn't completed yet. */ @@ -4525,6 +4537,8 @@ free_atfork(mem, caller) Void_t* mem; const Void_t *caller; (void)mutex_unlock(&ar_ptr->mutex); } +#endif + #endif /* defined _LIBC || defined MALLOC_HOOKS */ diff --git a/nis/ypclnt.c b/nis/ypclnt.c index 2d76daded9..e8c016d028 100644 --- a/nis/ypclnt.c +++ b/nis/ypclnt.c @@ -17,6 +17,7 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include #include #include @@ -379,6 +380,12 @@ yp_get_default_domain (char **outdomain) { if (getdomainname (__ypdomainname, NIS_MAXNAMELEN)) result = YPERR_NODOM; + else if (strcmp (__ypdomainname, "(none)") == 0) + { + /* If domainname is not set, some Systems will return "(none)" */ + __ypdomainname[0] = '\0'; + result = YPERR_NODOM; + } else *outdomain = __ypdomainname; } @@ -398,8 +405,6 @@ __yp_check (char **domain) if (__ypdomainname[0] == '\0') if (yp_get_default_domain (&unused)) return 0; - else if (strcmp (__ypdomainname, "(none)") == 0) - return 0; if (domain) *domain = __ypdomainname; diff --git a/posix/glob.c b/posix/glob.c deleted file mode 100644 index 29697f4c55..0000000000 --- a/posix/glob.c +++ /dev/null @@ -1,1114 +0,0 @@ -/* Copyright (C) 1991,92,93,94,95,96,97,98 Free Software Foundation, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; see the file COPYING.LIB. If not, - write to the Free 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 -#endif - -/* Enable GNU extensions in glob.h. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#include -#include -#include - -/* Outcomment the following line for production quality code. */ -/* #define NDEBUG 1 */ -#include - -#include /* 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 -# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION -# define ELIDE_CODE -# endif -#endif - -#ifndef ELIDE_CODE - -#if defined STDC_HEADERS || defined __GNU_LIBRARY__ -# include -#endif - -#if defined HAVE_UNISTD_H || defined _LIBC -# include -# ifndef POSIX -# ifdef _POSIX_VERSION -# define POSIX -# endif -# endif -#endif - -#if !defined _AMIGA && !defined VMS && !defined WINDOWS32 -# include -#endif - -#if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS -extern int errno; -#endif -#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 -# define NAMLEN(dirent) strlen((dirent)->d_name) -#else -# define dirent direct -# define NAMLEN(dirent) (dirent)->d_namlen -# ifdef HAVE_SYS_NDIR_H -# include -# endif -# ifdef HAVE_SYS_DIR_H -# include -# endif -# ifdef HAVE_NDIR_H -# include -# endif -# ifdef HAVE_VMSDIR_H -# include "vmsdir.h" -# endif /* HAVE_VMSDIR_H */ -#endif - - -/* In GNU systems, 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. */ -#ifdef _DIRENT_HAVE_D_TYPE -# define HAVE_D_TYPE 1 -#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 */ - -#if defined STDC_HEADERS || defined __GNU_LIBRARY__ -# include -# include -# define ANSI_STRING -#else /* No standard headers. */ - -extern char *getenv (); - -# ifdef HAVE_STRING_H -# include -# define ANSI_STRING -# else -# include -# endif -# ifdef HAVE_MEMORY_H -# include -# endif - -extern char *malloc (), *realloc (); -extern void free (); - -extern void qsort (); -extern void abort (), exit (); - -#endif /* Standard headers. */ - -#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 -# 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 -# else /* Not HAVE_ALLOCA_H. */ -# ifndef _AIX -# ifdef WINDOWS32 -# include -# 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 - -#if !(defined STDC_HEADERS || defined __GNU_LIBRARY__) -# undef size_t -# define size_t unsigned int -#endif - -/* Some system header files erroneously define these. - We want our own definitions from to take precedence. */ -#undef FNM_PATHNAME -#undef FNM_NOESCAPE -#undef FNM_PERIOD -#include - -/* Some system header files erroneously define these. - We want our own definitions from to take precedence. */ -#undef GLOB_ERR -#undef GLOB_MARK -#undef GLOB_NOSORT -#undef GLOB_DOOFFS -#undef GLOB_NOCHECK -#undef GLOB_APPEND -#undef GLOB_NOESCAPE -#undef GLOB_PERIOD -#include - -static -#if __GNUC__ - 0 >= 2 -inline -#endif -const char *next_brace_sub __P ((const char *begin)); -static int glob_in_dir __P ((const char *pattern, const char *directory, - int flags, - int (*errfunc) __P ((const char *, int)), - glob_t *pglob)); -static int prefix_array __P ((const char *prefix, char **array, size_t n)); -static int collated_compare __P ((const __ptr_t, const __ptr_t)); - - -/* Find the end of the sub-pattern in a brace expression. We define - this as an inline function if the compiler permits. */ -static -#if __GNUC__ - 0 >= 2 -inline -#endif -const char * -next_brace_sub (begin) - const char *begin; -{ - unsigned int depth = 0; - const char *cp = begin; - - while (1) - { - if (depth == 0) - { - if (*cp != ',' && *cp != '}' && *cp != '\0') - { - if (*cp == '{') - ++depth; - ++cp; - continue; - } - } - else - { - while (*cp != '\0' && (*cp != '}' || depth > 0)) - { - if (*cp == '}') - --depth; - ++cp; - } - if (*cp == '\0') - /* An incorrectly terminated brace expression. */ - return NULL; - - continue; - } - break; - } - - return cp; -} - -/* 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 -glob (pattern, flags, errfunc, pglob) - const char *pattern; - int flags; - int (*errfunc) __P ((const char *, int)); - glob_t *pglob; -{ - const char *filename; - char *dirname; - size_t dirlen; - int status; - int oldcount; - - if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) - { - __set_errno (EINVAL); - return -1; - } - - if (flags & GLOB_BRACE) - { - const char *begin = strchr (pattern, '{'); - if (begin != NULL) - { - /* Allocate working buffer large enough for our work. Note that - we have at least an opening and closing brace. */ - int 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 = (char *) malloc (strlen (pattern) - 1); - if (onealt == NULL) - { - if (!(flags & GLOB_APPEND)) - globfree (pglob); - return GLOB_NOSPACE; - } -#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. */ - next = next_brace_sub (begin + 1); - 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); - 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. */ -#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)) - | 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); - return result; - } - - if (*next == '}') - /* We saw the last entry. */ - break; - - p = next + 1; - next = next_brace_sub (p); - 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 (filename == NULL) - { - filename = pattern; -#ifdef _AMIGA - dirname = (char *) ""; -#else - dirname = (char *) "."; -#endif - dirlen = 0; - } - else if (filename == pattern) - { - /* "/pattern". */ - dirname = (char *) "/"; - dirlen = 1; - ++filename; - } - else - { - dirlen = filename - pattern; - dirname = (char *) __alloca (dirlen + 1); -#ifdef HAVE_MEMPCPY - *((char *) mempcpy (dirname, pattern, dirlen)) = '\0'; -#else - memcpy (dirname, pattern, dirlen); - dirname[dirlen] = '\0'; -#endif - ++filename; - } - - if (filename[0] == '\0' && 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; - pglob->gl_pathv = NULL; - } - - oldcount = pglob->gl_pathc; - -#ifndef VMS - if ((flags & GLOB_TILDE) && dirname[0] == '~') - { - if (dirname[1] == '\0' || dirname[1] == '/') - { - /* Look up home directory. */ - 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; -# if defined HAVE_GETLOGIN_R || defined _LIBC - extern int getlogin_r __P ((char *, size_t)); - size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1; - char *name; - - if (buflen == 0) - /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try - a moderate value. */ - buflen = 16; - name = (char *) __alloca (buflen); - - success = getlogin_r (name, buflen) >= 0; -# else - extern char *getlogin __P ((void)); - char *name; - - success = (name = getlogin ()) != NULL; -# endif - if (success) - { -# if defined HAVE_GETPWNAM_R || defined _LIBC - size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX); - char *pwtmpbuf; - struct passwd pwbuf, *p; - - pwtmpbuf = (char *) __alloca (pwbuflen); - - success = (__getpwnam_r (name, &pwbuf, pwtmpbuf, - pwbuflen, &p) >= 0); -# else - struct passwd *p = getpwnam (name); - success = p != NULL; -# endif - if (success) - home_dir = p->pw_dir; - } - } - if (home_dir == NULL || home_dir[0] == '\0') - home_dir = (char *) "~"; /* 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 = (char *) __alloca (home_len + dirlen); -# ifdef HAVE_MEMPCPY - 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; - } - } -# if !defined _AMIGA && !defined WINDOWS32 - else - { - char *end_name = strchr (dirname, '/'); - char *user_name; - char *home_dir; - - if (end_name == NULL) - user_name = dirname + 1; - else - { - user_name = (char *) __alloca (end_name - dirname); -# ifdef HAVE_MEMPCPY - *((char *) mempcpy (user_name, dirname + 1, end_name - dirname)) - = '\0'; -# else - memcpy (user_name, dirname + 1, end_name - dirname); - user_name[end_name - dirname - 1] = '\0'; -# endif - } - - /* Look up specific user's home directory. */ - { -# if defined HAVE_GETPWNAM_R || defined _LIBC - size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); - char *pwtmpbuf = (char *) __alloca (buflen); - struct passwd pwbuf, *p; - if (__getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) >= 0) - home_dir = p->pw_dir; - else - home_dir = NULL; -# else - struct passwd *p = getpwnam (user_name); - if (p != NULL) - home_dir = p->pw_dir; - else - home_dir = NULL; -# endif - } - /* 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 = (char *) __alloca (home_len + rest_len + 1); -# ifdef HAVE_MEMPCPY - *((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; - } - } -# endif /* Not Amiga && not WINDOWS32. */ - } -#endif /* Not VMS. */ - - 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; - register int i; - - status = glob (dirname, - ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE)) - | 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 oldcount; - -#ifdef SHELL - { - /* Make globbing interruptible in the bash shell. */ - extern int interrupt_state; - - if (interrupt_state) - { - globfree (&dirs); - globfree (&files); - return GLOB_ABORTED; - } - } -#endif /* SHELL. */ - - oldcount = pglob->gl_pathc; - status = glob_in_dir (filename, dirs.gl_pathv[i], - ((flags | GLOB_APPEND) - & ~(GLOB_NOCHECK | GLOB_ERR)), - errfunc, pglob); - if (status == GLOB_NOMATCH) - /* No matches in this directory. Try the next. */ - continue; - - if (status != 0) - { - globfree (&dirs); - globfree (pglob); - return status; - } - - /* Stick the directory on the front of each name. */ - if (prefix_array (dirs.gl_pathv[i], - &pglob->gl_pathv[oldcount], - pglob->gl_pathc - oldcount)) - { - globfree (&dirs); - globfree (pglob); - return GLOB_NOSPACE; - } - } - - flags |= GLOB_MAGCHAR; - - if (pglob->gl_pathc == oldcount) - /* No matches. */ - if (flags & GLOB_NOCHECK) - { - size_t len = strlen (pattern) + 1; - char *patcopy = (char *) malloc (len); - if (patcopy == NULL) - return GLOB_NOSPACE; - memcpy (patcopy, pattern, len); - - pglob->gl_pathv - = (char **) realloc (pglob->gl_pathv, - (pglob->gl_pathc + - ((flags & GLOB_DOOFFS) ? - pglob->gl_offs : 0) + - 1 + 1) * - sizeof (char *)); - if (pglob->gl_pathv == NULL) - { - free (patcopy); - return GLOB_NOSPACE; - } - - if (flags & GLOB_DOOFFS) - while (pglob->gl_pathc < pglob->gl_offs) - pglob->gl_pathv[pglob->gl_pathc++] = NULL; - - pglob->gl_pathv[pglob->gl_pathc++] = patcopy; - pglob->gl_pathv[pglob->gl_pathc] = NULL; - pglob->gl_flags = flags; - } - else - return GLOB_NOMATCH; - } - else - { - 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[oldcount], - pglob->gl_pathc - oldcount)) - { - globfree (pglob); - return GLOB_NOSPACE; - } - } - } - - if (flags & GLOB_MARK) - { - /* Append slashes to directory names. */ - int i; - struct stat st; - for (i = oldcount; i < pglob->gl_pathc; ++i) - if (((flags & GLOB_ALTDIRFUNC) ? - (*pglob->gl_stat) (pglob->gl_pathv[i], &st) : - __stat (pglob->gl_pathv[i], &st)) == 0 && - S_ISDIR (st.st_mode)) - { - size_t len = strlen (pglob->gl_pathv[i]) + 2; - char *new = realloc (pglob->gl_pathv[i], len); - if (new == NULL) - { - globfree (pglob); - 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], - pglob->gl_pathc - oldcount, - sizeof (char *), collated_compare); - - return 0; -} - - -/* Free storage allocated in PGLOB by a previous `glob' call. */ -void -globfree (pglob) - register glob_t *pglob; -{ - if (pglob->gl_pathv != NULL) - { - register int i; - for (i = 0; i < pglob->gl_pathc; ++i) - if (pglob->gl_pathv[i] != NULL) - free ((__ptr_t) pglob->gl_pathv[i]); - free ((__ptr_t) pglob->gl_pathv); - } -} - - -/* Do a collated comparison of A and B. */ -static int -collated_compare (a, b) - const __ptr_t a; - const __ptr_t 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 (dirname, array, n) - const char *dirname; - char **array; - size_t n; -{ - register size_t i; - size_t dirlen = strlen (dirname); - - 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; - - for (i = 0; i < n; ++i) - { - size_t eltlen = strlen (array[i]) + 1; - char *new = (char *) malloc (dirlen + 1 + eltlen); - if (new == NULL) - { - while (i > 0) - free ((__ptr_t) array[--i]); - return 1; - } - -#ifdef HAVE_MEMPCPY - { - char *endp = (char *) mempcpy (new, dirname, dirlen); - *endp++ = '/'; - mempcpy (endp, array[i], eltlen); - } -#else - memcpy (new, dirname, dirlen); - new[dirlen] = '/'; - memcpy (&new[dirlen + 1], array[i], eltlen); -#endif - free ((__ptr_t) array[i]); - array[i] = new; - } - - return 0; -} - - -/* 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; -{ - 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 - - -/* 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 (pattern, directory, flags, errfunc, pglob) - const char *pattern; - const char *directory; - int flags; - int (*errfunc) __P ((const char *, int)); - glob_t *pglob; -{ - __ptr_t stream; - - struct globlink - { - struct globlink *next; - char *name; - }; - struct globlink *names = NULL; - size_t nfound; - int meta; - int save; - - stream = ((flags & GLOB_ALTDIRFUNC) ? - (*pglob->gl_opendir) (directory) : - (__ptr_t) opendir (directory)); - if (stream == NULL) - { - if ((errfunc != NULL && (*errfunc) (directory, errno)) || - (flags & GLOB_ERR)) - return GLOB_ABORTED; - nfound = 0; - meta = 0; - } - else if (pattern[0] == '\0') - { - /* This is a special case for matching directories like in - "*a/". */ - names = (struct globlink *) __alloca (sizeof (struct globlink)); - names->name = (char *) malloc (1); - if (names->name == NULL) - goto memory_error; - names->name[0] = '\0'; - names->next = NULL; - nfound = 1; - meta = 0; - } - else - { - nfound = 0; - meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)); - if(meta) - flags |= GLOB_MAGCHAR; - - while (1) - { - const char *name; - size_t len; - struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ? - (*pglob->gl_readdir) (stream) : - readdir ((DIR *) stream)); - 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) - continue; -#endif - - name = d->d_name; - - if ((!meta && strcmp (pattern, name) == 0) - || fnmatch (pattern, name, - (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) | - ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) -#if defined _AMIGA || defined VMS - | FNM_CASEFOLD -#endif - ) == 0) - { - struct globlink *new - = (struct globlink *) __alloca (sizeof (struct globlink)); - len = NAMLEN (d); - new->name = (char *) malloc (len + 1); - 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 - new->next = names; - names = new; - ++nfound; - if (!meta) - break; - } - } - } - - if (nfound == 0 && (flags & GLOB_NOMAGIC) && !meta) - flags |= GLOB_NOCHECK; - - if (nfound == 0 && (flags & GLOB_NOCHECK)) - { - size_t len = strlen (pattern); - nfound = 1; - names = (struct globlink *) __alloca (sizeof (struct globlink)); - names->next = NULL; - names->name = (char *) 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) - { - pglob->gl_pathv - = (char **) realloc (pglob->gl_pathv, - (pglob->gl_pathc + - ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + - nfound + 1) * - sizeof (char *)); - if (pglob->gl_pathv == NULL) - goto memory_error; - - if (flags & GLOB_DOOFFS) - while (pglob->gl_pathc < pglob->gl_offs) - pglob->gl_pathv[pglob->gl_pathc++] = NULL; - - for (; names != NULL; names = names->next) - pglob->gl_pathv[pglob->gl_pathc++] = names->name; - pglob->gl_pathv[pglob->gl_pathc] = NULL; - - pglob->gl_flags = flags; - } - - save = errno; - if (flags & GLOB_ALTDIRFUNC) - (*pglob->gl_closedir) (stream); - else - closedir ((DIR *) 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 ((DIR *) stream); - __set_errno (save); - } - while (names != NULL) - { - if (names->name != NULL) - free ((__ptr_t) names->name); - names = names->next; - } - return GLOB_NOSPACE; -} - -#endif /* Not ELIDE_CODE. */ diff --git a/posix/glob.h b/posix/glob.h index a546c865f2..fd8255cd53 100644 --- a/posix/glob.h +++ b/posix/glob.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 92, 95, 96, 97, 98 Free Software Foundation, Inc. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -92,9 +92,9 @@ struct stat; #endif typedef struct { - int 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. */ - int 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 diff --git a/rt/Makefile b/rt/Makefile index 748050a74d..bc8f9234bf 100644 --- a/rt/Makefile +++ b/rt/Makefile @@ -30,8 +30,6 @@ librt-routines := aio_cancel aio_error aio_fsync aio_misc aio_read \ librt-map := librt.map -tests := tst-aio - # Make sure that everything is distributed independent of configuration. distribute := aio_misc.h $(librt-routines:=.c) $(librt-map) @@ -39,6 +37,8 @@ include ../Makeconfig ifeq ($(have-thread-library),yes) +tests := tst-aio + extra-libs := librt extra-libs-others := $(extra-libs) diff --git a/sunrpc/Makefile b/sunrpc/Makefile index 2cdcbb9595..a6101cfc6b 100644 --- a/sunrpc/Makefile +++ b/sunrpc/Makefile @@ -55,8 +55,7 @@ headers = $(addprefix rpc/,auth.h auth_unix.h clnt.h netdb.h pmap_clnt.h \ $(rpcsvc:%=rpcsvc/%) install-others = $(inst_sysconfdir)/rpc generated = $(rpcsvc:%.x=rpcsvc/%.h) $(rpcsvc:%.x=x%.c) $(rpcsvc:%.x=x%.stmp) \ - rpc-proto.c rpc-proto.d rpcgen -generated-dirs = rpcsvc + $(rpcsvc:%.x=rpcsvc/%.stmp) $rpc-proto.c rpc-proto.d rpcgen routines := auth_none auth_unix authuxprot bindrsvprt \ clnt_gen clnt_perr clnt_raw clnt_simp clnt_tcp \ diff --git a/sysdeps/generic/glob.c b/sysdeps/generic/glob.c new file mode 100644 index 0000000000..29697f4c55 --- /dev/null +++ b/sysdeps/generic/glob.c @@ -0,0 +1,1114 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,98 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. If not, + write to the Free 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 +#endif + +/* Enable GNU extensions in glob.h. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#include +#include +#include + +/* Outcomment the following line for production quality code. */ +/* #define NDEBUG 1 */ +#include + +#include /* 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 +# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION +# define ELIDE_CODE +# endif +#endif + +#ifndef ELIDE_CODE + +#if defined STDC_HEADERS || defined __GNU_LIBRARY__ +# include +#endif + +#if defined HAVE_UNISTD_H || defined _LIBC +# include +# ifndef POSIX +# ifdef _POSIX_VERSION +# define POSIX +# endif +# endif +#endif + +#if !defined _AMIGA && !defined VMS && !defined WINDOWS32 +# include +#endif + +#if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS +extern int errno; +#endif +#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 +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif +# ifdef HAVE_VMSDIR_H +# include "vmsdir.h" +# endif /* HAVE_VMSDIR_H */ +#endif + + +/* In GNU systems, 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. */ +#ifdef _DIRENT_HAVE_D_TYPE +# define HAVE_D_TYPE 1 +#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 */ + +#if defined STDC_HEADERS || defined __GNU_LIBRARY__ +# include +# include +# define ANSI_STRING +#else /* No standard headers. */ + +extern char *getenv (); + +# ifdef HAVE_STRING_H +# include +# define ANSI_STRING +# else +# include +# endif +# ifdef HAVE_MEMORY_H +# include +# endif + +extern char *malloc (), *realloc (); +extern void free (); + +extern void qsort (); +extern void abort (), exit (); + +#endif /* Standard headers. */ + +#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 +# 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 +# else /* Not HAVE_ALLOCA_H. */ +# ifndef _AIX +# ifdef WINDOWS32 +# include +# 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 + +#if !(defined STDC_HEADERS || defined __GNU_LIBRARY__) +# undef size_t +# define size_t unsigned int +#endif + +/* Some system header files erroneously define these. + We want our own definitions from to take precedence. */ +#undef FNM_PATHNAME +#undef FNM_NOESCAPE +#undef FNM_PERIOD +#include + +/* Some system header files erroneously define these. + We want our own definitions from to take precedence. */ +#undef GLOB_ERR +#undef GLOB_MARK +#undef GLOB_NOSORT +#undef GLOB_DOOFFS +#undef GLOB_NOCHECK +#undef GLOB_APPEND +#undef GLOB_NOESCAPE +#undef GLOB_PERIOD +#include + +static +#if __GNUC__ - 0 >= 2 +inline +#endif +const char *next_brace_sub __P ((const char *begin)); +static int glob_in_dir __P ((const char *pattern, const char *directory, + int flags, + int (*errfunc) __P ((const char *, int)), + glob_t *pglob)); +static int prefix_array __P ((const char *prefix, char **array, size_t n)); +static int collated_compare __P ((const __ptr_t, const __ptr_t)); + + +/* Find the end of the sub-pattern in a brace expression. We define + this as an inline function if the compiler permits. */ +static +#if __GNUC__ - 0 >= 2 +inline +#endif +const char * +next_brace_sub (begin) + const char *begin; +{ + unsigned int depth = 0; + const char *cp = begin; + + while (1) + { + if (depth == 0) + { + if (*cp != ',' && *cp != '}' && *cp != '\0') + { + if (*cp == '{') + ++depth; + ++cp; + continue; + } + } + else + { + while (*cp != '\0' && (*cp != '}' || depth > 0)) + { + if (*cp == '}') + --depth; + ++cp; + } + if (*cp == '\0') + /* An incorrectly terminated brace expression. */ + return NULL; + + continue; + } + break; + } + + return cp; +} + +/* 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 +glob (pattern, flags, errfunc, pglob) + const char *pattern; + int flags; + int (*errfunc) __P ((const char *, int)); + glob_t *pglob; +{ + const char *filename; + char *dirname; + size_t dirlen; + int status; + int oldcount; + + if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) + { + __set_errno (EINVAL); + return -1; + } + + if (flags & GLOB_BRACE) + { + const char *begin = strchr (pattern, '{'); + if (begin != NULL) + { + /* Allocate working buffer large enough for our work. Note that + we have at least an opening and closing brace. */ + int 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 = (char *) malloc (strlen (pattern) - 1); + if (onealt == NULL) + { + if (!(flags & GLOB_APPEND)) + globfree (pglob); + return GLOB_NOSPACE; + } +#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. */ + next = next_brace_sub (begin + 1); + 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); + 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. */ +#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)) + | 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); + return result; + } + + if (*next == '}') + /* We saw the last entry. */ + break; + + p = next + 1; + next = next_brace_sub (p); + 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 (filename == NULL) + { + filename = pattern; +#ifdef _AMIGA + dirname = (char *) ""; +#else + dirname = (char *) "."; +#endif + dirlen = 0; + } + else if (filename == pattern) + { + /* "/pattern". */ + dirname = (char *) "/"; + dirlen = 1; + ++filename; + } + else + { + dirlen = filename - pattern; + dirname = (char *) __alloca (dirlen + 1); +#ifdef HAVE_MEMPCPY + *((char *) mempcpy (dirname, pattern, dirlen)) = '\0'; +#else + memcpy (dirname, pattern, dirlen); + dirname[dirlen] = '\0'; +#endif + ++filename; + } + + if (filename[0] == '\0' && 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; + pglob->gl_pathv = NULL; + } + + oldcount = pglob->gl_pathc; + +#ifndef VMS + if ((flags & GLOB_TILDE) && dirname[0] == '~') + { + if (dirname[1] == '\0' || dirname[1] == '/') + { + /* Look up home directory. */ + 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; +# if defined HAVE_GETLOGIN_R || defined _LIBC + extern int getlogin_r __P ((char *, size_t)); + size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1; + char *name; + + if (buflen == 0) + /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try + a moderate value. */ + buflen = 16; + name = (char *) __alloca (buflen); + + success = getlogin_r (name, buflen) >= 0; +# else + extern char *getlogin __P ((void)); + char *name; + + success = (name = getlogin ()) != NULL; +# endif + if (success) + { +# if defined HAVE_GETPWNAM_R || defined _LIBC + size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX); + char *pwtmpbuf; + struct passwd pwbuf, *p; + + pwtmpbuf = (char *) __alloca (pwbuflen); + + success = (__getpwnam_r (name, &pwbuf, pwtmpbuf, + pwbuflen, &p) >= 0); +# else + struct passwd *p = getpwnam (name); + success = p != NULL; +# endif + if (success) + home_dir = p->pw_dir; + } + } + if (home_dir == NULL || home_dir[0] == '\0') + home_dir = (char *) "~"; /* 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 = (char *) __alloca (home_len + dirlen); +# ifdef HAVE_MEMPCPY + 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; + } + } +# if !defined _AMIGA && !defined WINDOWS32 + else + { + char *end_name = strchr (dirname, '/'); + char *user_name; + char *home_dir; + + if (end_name == NULL) + user_name = dirname + 1; + else + { + user_name = (char *) __alloca (end_name - dirname); +# ifdef HAVE_MEMPCPY + *((char *) mempcpy (user_name, dirname + 1, end_name - dirname)) + = '\0'; +# else + memcpy (user_name, dirname + 1, end_name - dirname); + user_name[end_name - dirname - 1] = '\0'; +# endif + } + + /* Look up specific user's home directory. */ + { +# if defined HAVE_GETPWNAM_R || defined _LIBC + size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); + char *pwtmpbuf = (char *) __alloca (buflen); + struct passwd pwbuf, *p; + if (__getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) >= 0) + home_dir = p->pw_dir; + else + home_dir = NULL; +# else + struct passwd *p = getpwnam (user_name); + if (p != NULL) + home_dir = p->pw_dir; + else + home_dir = NULL; +# endif + } + /* 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 = (char *) __alloca (home_len + rest_len + 1); +# ifdef HAVE_MEMPCPY + *((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; + } + } +# endif /* Not Amiga && not WINDOWS32. */ + } +#endif /* Not VMS. */ + + 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; + register int i; + + status = glob (dirname, + ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE)) + | 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 oldcount; + +#ifdef SHELL + { + /* Make globbing interruptible in the bash shell. */ + extern int interrupt_state; + + if (interrupt_state) + { + globfree (&dirs); + globfree (&files); + return GLOB_ABORTED; + } + } +#endif /* SHELL. */ + + oldcount = pglob->gl_pathc; + status = glob_in_dir (filename, dirs.gl_pathv[i], + ((flags | GLOB_APPEND) + & ~(GLOB_NOCHECK | GLOB_ERR)), + errfunc, pglob); + if (status == GLOB_NOMATCH) + /* No matches in this directory. Try the next. */ + continue; + + if (status != 0) + { + globfree (&dirs); + globfree (pglob); + return status; + } + + /* Stick the directory on the front of each name. */ + if (prefix_array (dirs.gl_pathv[i], + &pglob->gl_pathv[oldcount], + pglob->gl_pathc - oldcount)) + { + globfree (&dirs); + globfree (pglob); + return GLOB_NOSPACE; + } + } + + flags |= GLOB_MAGCHAR; + + if (pglob->gl_pathc == oldcount) + /* No matches. */ + if (flags & GLOB_NOCHECK) + { + size_t len = strlen (pattern) + 1; + char *patcopy = (char *) malloc (len); + if (patcopy == NULL) + return GLOB_NOSPACE; + memcpy (patcopy, pattern, len); + + pglob->gl_pathv + = (char **) realloc (pglob->gl_pathv, + (pglob->gl_pathc + + ((flags & GLOB_DOOFFS) ? + pglob->gl_offs : 0) + + 1 + 1) * + sizeof (char *)); + if (pglob->gl_pathv == NULL) + { + free (patcopy); + return GLOB_NOSPACE; + } + + if (flags & GLOB_DOOFFS) + while (pglob->gl_pathc < pglob->gl_offs) + pglob->gl_pathv[pglob->gl_pathc++] = NULL; + + pglob->gl_pathv[pglob->gl_pathc++] = patcopy; + pglob->gl_pathv[pglob->gl_pathc] = NULL; + pglob->gl_flags = flags; + } + else + return GLOB_NOMATCH; + } + else + { + 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[oldcount], + pglob->gl_pathc - oldcount)) + { + globfree (pglob); + return GLOB_NOSPACE; + } + } + } + + if (flags & GLOB_MARK) + { + /* Append slashes to directory names. */ + int i; + struct stat st; + for (i = oldcount; i < pglob->gl_pathc; ++i) + if (((flags & GLOB_ALTDIRFUNC) ? + (*pglob->gl_stat) (pglob->gl_pathv[i], &st) : + __stat (pglob->gl_pathv[i], &st)) == 0 && + S_ISDIR (st.st_mode)) + { + size_t len = strlen (pglob->gl_pathv[i]) + 2; + char *new = realloc (pglob->gl_pathv[i], len); + if (new == NULL) + { + globfree (pglob); + 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], + pglob->gl_pathc - oldcount, + sizeof (char *), collated_compare); + + return 0; +} + + +/* Free storage allocated in PGLOB by a previous `glob' call. */ +void +globfree (pglob) + register glob_t *pglob; +{ + if (pglob->gl_pathv != NULL) + { + register int i; + for (i = 0; i < pglob->gl_pathc; ++i) + if (pglob->gl_pathv[i] != NULL) + free ((__ptr_t) pglob->gl_pathv[i]); + free ((__ptr_t) pglob->gl_pathv); + } +} + + +/* Do a collated comparison of A and B. */ +static int +collated_compare (a, b) + const __ptr_t a; + const __ptr_t 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 (dirname, array, n) + const char *dirname; + char **array; + size_t n; +{ + register size_t i; + size_t dirlen = strlen (dirname); + + 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; + + for (i = 0; i < n; ++i) + { + size_t eltlen = strlen (array[i]) + 1; + char *new = (char *) malloc (dirlen + 1 + eltlen); + if (new == NULL) + { + while (i > 0) + free ((__ptr_t) array[--i]); + return 1; + } + +#ifdef HAVE_MEMPCPY + { + char *endp = (char *) mempcpy (new, dirname, dirlen); + *endp++ = '/'; + mempcpy (endp, array[i], eltlen); + } +#else + memcpy (new, dirname, dirlen); + new[dirlen] = '/'; + memcpy (&new[dirlen + 1], array[i], eltlen); +#endif + free ((__ptr_t) array[i]); + array[i] = new; + } + + return 0; +} + + +/* 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; +{ + 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 + + +/* 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 (pattern, directory, flags, errfunc, pglob) + const char *pattern; + const char *directory; + int flags; + int (*errfunc) __P ((const char *, int)); + glob_t *pglob; +{ + __ptr_t stream; + + struct globlink + { + struct globlink *next; + char *name; + }; + struct globlink *names = NULL; + size_t nfound; + int meta; + int save; + + stream = ((flags & GLOB_ALTDIRFUNC) ? + (*pglob->gl_opendir) (directory) : + (__ptr_t) opendir (directory)); + if (stream == NULL) + { + if ((errfunc != NULL && (*errfunc) (directory, errno)) || + (flags & GLOB_ERR)) + return GLOB_ABORTED; + nfound = 0; + meta = 0; + } + else if (pattern[0] == '\0') + { + /* This is a special case for matching directories like in + "*a/". */ + names = (struct globlink *) __alloca (sizeof (struct globlink)); + names->name = (char *) malloc (1); + if (names->name == NULL) + goto memory_error; + names->name[0] = '\0'; + names->next = NULL; + nfound = 1; + meta = 0; + } + else + { + nfound = 0; + meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)); + if(meta) + flags |= GLOB_MAGCHAR; + + while (1) + { + const char *name; + size_t len; + struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ? + (*pglob->gl_readdir) (stream) : + readdir ((DIR *) stream)); + 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) + continue; +#endif + + name = d->d_name; + + if ((!meta && strcmp (pattern, name) == 0) + || fnmatch (pattern, name, + (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) | + ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) +#if defined _AMIGA || defined VMS + | FNM_CASEFOLD +#endif + ) == 0) + { + struct globlink *new + = (struct globlink *) __alloca (sizeof (struct globlink)); + len = NAMLEN (d); + new->name = (char *) malloc (len + 1); + 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 + new->next = names; + names = new; + ++nfound; + if (!meta) + break; + } + } + } + + if (nfound == 0 && (flags & GLOB_NOMAGIC) && !meta) + flags |= GLOB_NOCHECK; + + if (nfound == 0 && (flags & GLOB_NOCHECK)) + { + size_t len = strlen (pattern); + nfound = 1; + names = (struct globlink *) __alloca (sizeof (struct globlink)); + names->next = NULL; + names->name = (char *) 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) + { + pglob->gl_pathv + = (char **) realloc (pglob->gl_pathv, + (pglob->gl_pathc + + ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + + nfound + 1) * + sizeof (char *)); + if (pglob->gl_pathv == NULL) + goto memory_error; + + if (flags & GLOB_DOOFFS) + while (pglob->gl_pathc < pglob->gl_offs) + pglob->gl_pathv[pglob->gl_pathc++] = NULL; + + for (; names != NULL; names = names->next) + pglob->gl_pathv[pglob->gl_pathc++] = names->name; + pglob->gl_pathv[pglob->gl_pathc] = NULL; + + pglob->gl_flags = flags; + } + + save = errno; + if (flags & GLOB_ALTDIRFUNC) + (*pglob->gl_closedir) (stream); + else + closedir ((DIR *) 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 ((DIR *) stream); + __set_errno (save); + } + while (names != NULL) + { + if (names->name != NULL) + free ((__ptr_t) names->name); + names = names->next; + } + return GLOB_NOSPACE; +} + +#endif /* Not ELIDE_CODE. */ diff --git a/sysdeps/unix/sysv/linux/alpha/Dist b/sysdeps/unix/sysv/linux/alpha/Dist index 6ced71e65d..d20860445c 100644 --- a/sysdeps/unix/sysv/linux/alpha/Dist +++ b/sysdeps/unix/sysv/linux/alpha/Dist @@ -10,6 +10,7 @@ kernel_sigaction.h kernel_stat.h kernel_termios.h net/route.h +oldglob.c rt_sigaction.S sizes.h sys/acct.h diff --git a/sysdeps/unix/sysv/linux/alpha/Makefile b/sysdeps/unix/sysv/linux/alpha/Makefile index 15ba1c7316..fbbc56ecd3 100644 --- a/sysdeps/unix/sysv/linux/alpha/Makefile +++ b/sysdeps/unix/sysv/linux/alpha/Makefile @@ -1,3 +1,7 @@ +ifeq ($(subdir),posix) +sysdep_routines += oldglob +endif + ifeq ($(subdir),misc) sysdep_headers += alpha/ptrace.h alpha/regdef.h diff --git a/sysdeps/unix/sysv/linux/alpha/glob.c b/sysdeps/unix/sysv/linux/alpha/glob.c new file mode 100644 index 0000000000..7bd516191d --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/glob.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* For Linux/Alpha we have to make the glob symbols versioned. */ +#define glob(pattern, flags, errfunc, pglob) \ + __new_glob (pattern, flags, errfunc, pglob) \ +#define globfree(pglob) \ + __new_globfree (pglob) + +#include_next + +#undef glob +#undef globfree + +default_symbol_version(__new_glob, glob, GLIBC_2.1) +default_symbol_version(__new_globfree, globfree, GLIBC_2.1) diff --git a/sysdeps/unix/sysv/linux/alpha/oldglob.c b/sysdeps/unix/sysv/linux/alpha/oldglob.c new file mode 100644 index 0000000000..97284ab3e9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/oldglob.c @@ -0,0 +1,94 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file contains only wrappers around the real glob functions. It + became necessary since the glob_t structure changed. */ +#include + +#if defined PIC && DO_VERSIONING + +/* This is the old structure. The difference is that the gl_pathc and + gl_offs elements have type `int'. */ +typedef struct + { + int gl_pathc; /* Count of paths matched by the pattern. */ + char **gl_pathv; /* List of matched pathnames. */ + int 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) __P ((void *)); + struct dirent *(*gl_readdir) __P ((void *)); + __ptr_t (*gl_opendir) __P ((__const char *)); + int (*gl_lstat) __P ((__const char *, struct stat *)); + int (*gl_stat) __P ((__const char *, struct stat *)); + } old_glob_t; + + +int +__old_glob (const char *pattern, int flags, + int (*errfunc) __P ((const char *, int)), + old_glob_t *pglob) +{ + glob_t correct; + int result; + + /* Construct an object of correct type. */ + correct.gl_pathc = pglob->gl_pathc; + correct.gl_pathv = pglob->gl_pathv; + correct.gl_offs = pglob->gl_offs; + correct.gl_flags = pglob->gl_flags; + correct.gl_closedir = pglob->gl_closedir; + correct.gl_readdir = pglob->gl_readdir; + correct.gl_opendir = pglob->gl_opendir; + correct.gl_lstat = pglob->gl_lstat; + correct.gl_stat = pglob->gl_stat; + + result = glob (pattern, flags, errfunc, &correct); + + /* And convert it back. */ + pglob->gl_pathc = correct.gl_pathc; + pglob->gl_pathv = correct.gl_pathv; + pglob->gl_offs = correct.gl_offs; + pglob->gl_flags = correct.gl_flags; + pglob->gl_closedir = correct.gl_closedir; + pglob->gl_readdir = correct.gl_readdir; + pglob->gl_opendir = correct.gl_opendir; + pglob->gl_lstat = correct.gl_lstat; + pglob->gl_stat = correct.gl_stat; + + return result; +} +symbol_version(__old_glob, glob, GLIBC_2.0) + + +/* Free storage allocated in PGLOB by a previous `glob' call. */ +void +__old_globfree (old_glob_t *pglob) +{ + glob_t correct; + + /* We only need these two symbols. */ + correct.gl_pathc = pglob->gl_pathc; + correct.gl_pathv = pglob->gl_pathv; + + globfree (&correct); +} +symbol_version(__old_globfree, globfree, GLIBC_2.0) + +#endif -- cgit v1.2.1