169606e3fSchristos /* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
269606e3fSchristos
369606e3fSchristos This library is free software; you can redistribute it and/or
469606e3fSchristos modify it under the terms of the GNU Library General Public License as
569606e3fSchristos published by the Free Software Foundation; either version 2 of the
669606e3fSchristos License, or (at your option) any later version.
769606e3fSchristos
869606e3fSchristos This library is distributed in the hope that it will be useful,
969606e3fSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of
1069606e3fSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1169606e3fSchristos Library General Public License for more details.
1269606e3fSchristos
1369606e3fSchristos You should have received a copy of the GNU Library General Public License
1469606e3fSchristos along with this library; see the file COPYING.LIB. If not, write to the Free
1569606e3fSchristos Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
1669606e3fSchristos USA. */
1769606e3fSchristos
1869606e3fSchristos /* AIX requires this to be the first thing in the file. */
1969606e3fSchristos #if defined _AIX && !defined __GNUC__
2069606e3fSchristos #pragma alloca
2169606e3fSchristos #endif
2269606e3fSchristos
2369606e3fSchristos #ifdef HAVE_CONFIG_H
2469606e3fSchristos # include <config.h>
2569606e3fSchristos #endif
2669606e3fSchristos
2769606e3fSchristos /* Enable GNU extensions in glob.h. */
2869606e3fSchristos #ifndef _GNU_SOURCE
2969606e3fSchristos # define _GNU_SOURCE 1
3069606e3fSchristos #endif
3169606e3fSchristos
3269606e3fSchristos #include <errno.h>
3369606e3fSchristos #include <sys/types.h>
3469606e3fSchristos #include <sys/stat.h>
3569606e3fSchristos
3669606e3fSchristos /* Outcomment the following line for production quality code. */
3769606e3fSchristos /* #define NDEBUG 1 */
3869606e3fSchristos #include <assert.h>
3969606e3fSchristos
4069606e3fSchristos #include <stdio.h> /* Needed on stupid SunOS for assert. */
4169606e3fSchristos
4269606e3fSchristos
4369606e3fSchristos /* Comment out all this code if we are using the GNU C Library, and are not
4469606e3fSchristos actually compiling the library itself. This code is part of the GNU C
4569606e3fSchristos Library, but also included in many other GNU distributions. Compiling
4669606e3fSchristos and linking in this code is a waste when using the GNU C library
4769606e3fSchristos (especially if it is a shared library). Rather than having every GNU
4869606e3fSchristos program understand `configure --with-gnu-libc' and omit the object files,
4969606e3fSchristos it is simpler to just do this in the source for each such file. */
5069606e3fSchristos
5169606e3fSchristos #define GLOB_INTERFACE_VERSION 1
5269606e3fSchristos #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
5369606e3fSchristos # include <gnu-versions.h>
5469606e3fSchristos # if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
5569606e3fSchristos # define ELIDE_CODE
5669606e3fSchristos # endif
5769606e3fSchristos #endif
5869606e3fSchristos
5969606e3fSchristos #ifndef ELIDE_CODE
6069606e3fSchristos
6169606e3fSchristos #if defined STDC_HEADERS || defined __GNU_LIBRARY__
6269606e3fSchristos # include <stddef.h>
6369606e3fSchristos #endif
6469606e3fSchristos
6569606e3fSchristos #if defined HAVE_UNISTD_H || defined _LIBC
6669606e3fSchristos # include <unistd.h>
6769606e3fSchristos # ifndef POSIX
6869606e3fSchristos # ifdef _POSIX_VERSION
6969606e3fSchristos # define POSIX
7069606e3fSchristos # endif
7169606e3fSchristos # endif
7269606e3fSchristos #endif
7369606e3fSchristos
7469606e3fSchristos #if !defined _AMIGA && !defined VMS && !defined WINDOWS32
7569606e3fSchristos # include <pwd.h>
7669606e3fSchristos #endif
7769606e3fSchristos
7869606e3fSchristos #if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS
7969606e3fSchristos extern int errno;
8069606e3fSchristos #endif
8169606e3fSchristos #ifndef __set_errno
8269606e3fSchristos # define __set_errno(val) errno = (val)
8369606e3fSchristos #endif
8469606e3fSchristos
8569606e3fSchristos #ifndef NULL
8669606e3fSchristos # define NULL 0
8769606e3fSchristos #endif
8869606e3fSchristos
8969606e3fSchristos
9069606e3fSchristos #if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
9169606e3fSchristos # include <dirent.h>
9269606e3fSchristos # define NAMLEN(dirent) strlen((dirent)->d_name)
9369606e3fSchristos #else
9469606e3fSchristos # define dirent direct
9569606e3fSchristos # define NAMLEN(dirent) (dirent)->d_namlen
9669606e3fSchristos # ifdef HAVE_SYS_NDIR_H
9769606e3fSchristos # include <sys/ndir.h>
9869606e3fSchristos # endif
9969606e3fSchristos # ifdef HAVE_SYS_DIR_H
10069606e3fSchristos # include <sys/dir.h>
10169606e3fSchristos # endif
10269606e3fSchristos # ifdef HAVE_NDIR_H
10369606e3fSchristos # include <ndir.h>
10469606e3fSchristos # endif
10569606e3fSchristos # ifdef HAVE_VMSDIR_H
10669606e3fSchristos # include "vmsdir.h"
10769606e3fSchristos # endif /* HAVE_VMSDIR_H */
10869606e3fSchristos #endif
10969606e3fSchristos
11069606e3fSchristos
11169606e3fSchristos /* In GNU systems, <dirent.h> defines this macro for us. */
11269606e3fSchristos #ifdef _D_NAMLEN
11369606e3fSchristos # undef NAMLEN
11469606e3fSchristos # define NAMLEN(d) _D_NAMLEN(d)
11569606e3fSchristos #endif
11669606e3fSchristos
11769606e3fSchristos /* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
11869606e3fSchristos if the `d_type' member for `struct dirent' is available. */
11969606e3fSchristos #ifdef _DIRENT_HAVE_D_TYPE
12069606e3fSchristos # define HAVE_D_TYPE 1
12169606e3fSchristos #endif
12269606e3fSchristos
12369606e3fSchristos
12469606e3fSchristos #if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
12569606e3fSchristos /* Posix does not require that the d_ino field be present, and some
12669606e3fSchristos systems do not provide it. */
12769606e3fSchristos # define REAL_DIR_ENTRY(dp) 1
12869606e3fSchristos #else
12969606e3fSchristos # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
13069606e3fSchristos #endif /* POSIX */
13169606e3fSchristos
13269606e3fSchristos #if defined STDC_HEADERS || defined __GNU_LIBRARY__
13369606e3fSchristos # include <stdlib.h>
13469606e3fSchristos # include <string.h>
13569606e3fSchristos # define ANSI_STRING
13669606e3fSchristos #else /* No standard headers. */
13769606e3fSchristos
13869606e3fSchristos extern char *getenv ();
13969606e3fSchristos
14069606e3fSchristos # ifdef HAVE_STRING_H
14169606e3fSchristos # include <string.h>
14269606e3fSchristos # define ANSI_STRING
14369606e3fSchristos # else
14469606e3fSchristos # include <strings.h>
14569606e3fSchristos # endif
14669606e3fSchristos # ifdef HAVE_MEMORY_H
14769606e3fSchristos # include <memory.h>
14869606e3fSchristos # endif
14969606e3fSchristos
15069606e3fSchristos extern char *malloc (), *realloc ();
15169606e3fSchristos extern void free ();
15269606e3fSchristos
15369606e3fSchristos extern void qsort ();
15469606e3fSchristos extern void abort (), exit ();
15569606e3fSchristos
15669606e3fSchristos #endif /* Standard headers. */
15769606e3fSchristos
15869606e3fSchristos #ifndef ANSI_STRING
15969606e3fSchristos
16069606e3fSchristos # ifndef bzero
16169606e3fSchristos extern void bzero ();
16269606e3fSchristos # endif
16369606e3fSchristos # ifndef bcopy
16469606e3fSchristos extern void bcopy ();
16569606e3fSchristos # endif
16669606e3fSchristos
16769606e3fSchristos # define memcpy(d, s, n) bcopy ((s), (d), (n))
16869606e3fSchristos # define strrchr rindex
16969606e3fSchristos /* memset is only used for zero here, but let's be paranoid. */
17069606e3fSchristos # define memset(s, better_be_zero, n) \
17169606e3fSchristos ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0)))
17269606e3fSchristos #endif /* Not ANSI_STRING. */
17369606e3fSchristos
17469606e3fSchristos #if !defined HAVE_STRCOLL && !defined _LIBC
17569606e3fSchristos # define strcoll strcmp
17669606e3fSchristos #endif
17769606e3fSchristos
17869606e3fSchristos #if !defined HAVE_MEMPCPY && __GLIBC__ - 0 == 2 && __GLIBC_MINOR__ >= 1
17969606e3fSchristos # define HAVE_MEMPCPY 1
18069606e3fSchristos # undef mempcpy
18169606e3fSchristos # define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len)
18269606e3fSchristos #endif
18369606e3fSchristos
18469606e3fSchristos #ifndef __GNU_LIBRARY__
18569606e3fSchristos # ifdef __GNUC__
18669606e3fSchristos __inline
18769606e3fSchristos # endif
18869606e3fSchristos # ifndef __SASC
18969606e3fSchristos # ifdef WINDOWS32
19069606e3fSchristos static void *
my_realloc(void * p,unsigned int n)19169606e3fSchristos my_realloc (void *p, unsigned int n)
19269606e3fSchristos # else
19369606e3fSchristos static char *
19469606e3fSchristos my_realloc (p, n)
19569606e3fSchristos char *p;
19669606e3fSchristos unsigned int n;
19769606e3fSchristos # endif
19869606e3fSchristos {
19969606e3fSchristos /* These casts are the for sake of the broken Ultrix compiler,
20069606e3fSchristos which warns of illegal pointer combinations otherwise. */
20169606e3fSchristos if (p == NULL)
20269606e3fSchristos return (char *) malloc (n);
20369606e3fSchristos return (char *) realloc (p, n);
20469606e3fSchristos }
20569606e3fSchristos # define realloc my_realloc
20669606e3fSchristos # endif /* __SASC */
20769606e3fSchristos #endif /* __GNU_LIBRARY__ */
20869606e3fSchristos
20969606e3fSchristos
210*327f8a36Snonaka #if !defined __alloca
21169606e3fSchristos
21269606e3fSchristos # ifdef __GNUC__
21369606e3fSchristos # undef alloca
21469606e3fSchristos # define alloca(n) __builtin_alloca (n)
21569606e3fSchristos # else /* Not GCC. */
21669606e3fSchristos # ifdef HAVE_ALLOCA_H
21769606e3fSchristos # include <alloca.h>
21869606e3fSchristos # else /* Not HAVE_ALLOCA_H. */
21969606e3fSchristos # ifndef _AIX
22069606e3fSchristos # ifdef WINDOWS32
22169606e3fSchristos # include <malloc.h>
22269606e3fSchristos # else
22369606e3fSchristos extern char *alloca ();
22469606e3fSchristos # endif /* WINDOWS32 */
22569606e3fSchristos # endif /* Not _AIX. */
22669606e3fSchristos # endif /* sparc or HAVE_ALLOCA_H. */
22769606e3fSchristos # endif /* GCC. */
22869606e3fSchristos
22969606e3fSchristos # define __alloca alloca
23069606e3fSchristos
23169606e3fSchristos #endif
23269606e3fSchristos
233*327f8a36Snonaka #if !defined __stat
23469606e3fSchristos # define __stat stat
23569606e3fSchristos # ifdef STAT_MACROS_BROKEN
23669606e3fSchristos # undef S_ISDIR
23769606e3fSchristos # endif
23869606e3fSchristos # ifndef S_ISDIR
23969606e3fSchristos # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
24069606e3fSchristos # endif
24169606e3fSchristos #endif
24269606e3fSchristos
24369606e3fSchristos #ifdef _LIBC
24469606e3fSchristos # undef strdup
24569606e3fSchristos # define strdup(str) __strdup (str)
24669606e3fSchristos # define sysconf(id) __sysconf (id)
24769606e3fSchristos # define closedir(dir) __closedir (dir)
24869606e3fSchristos # define opendir(name) __opendir (name)
24969606e3fSchristos # define readdir(str) __readdir (str)
25069606e3fSchristos # define getpwnam_r(name, bufp, buf, len, res) \
25169606e3fSchristos __getpwnam_r (name, bufp, buf, len, res)
25269606e3fSchristos # ifndef __stat
25369606e3fSchristos # define __stat(fname, buf) __xstat (_STAT_VER, fname, buf)
25469606e3fSchristos # endif
25569606e3fSchristos #endif
25669606e3fSchristos
25769606e3fSchristos #if !(defined STDC_HEADERS || defined __GNU_LIBRARY__)
25869606e3fSchristos # undef size_t
25969606e3fSchristos # define size_t unsigned int
26069606e3fSchristos #endif
26169606e3fSchristos
26269606e3fSchristos /* Some system header files erroneously define these.
26369606e3fSchristos We want our own definitions from <fnmatch.h> to take precedence. */
26469606e3fSchristos #ifndef __GNU_LIBRARY__
26569606e3fSchristos # undef FNM_PATHNAME
26669606e3fSchristos # undef FNM_NOESCAPE
26769606e3fSchristos # undef FNM_PERIOD
26869606e3fSchristos #endif
26969606e3fSchristos #include <fnmatch.h>
27069606e3fSchristos
27169606e3fSchristos /* Some system header files erroneously define these.
27269606e3fSchristos We want our own definitions from <glob.h> to take precedence. */
27369606e3fSchristos #ifndef __GNU_LIBRARY__
27469606e3fSchristos # undef GLOB_ERR
27569606e3fSchristos # undef GLOB_MARK
27669606e3fSchristos # undef GLOB_NOSORT
27769606e3fSchristos # undef GLOB_DOOFFS
27869606e3fSchristos # undef GLOB_NOCHECK
27969606e3fSchristos # undef GLOB_APPEND
28069606e3fSchristos # undef GLOB_NOESCAPE
28169606e3fSchristos # undef GLOB_PERIOD
28269606e3fSchristos #endif
28369606e3fSchristos #include <glob.h>
28469606e3fSchristos
28569606e3fSchristos #ifdef HAVE_GETLOGIN_R
28669606e3fSchristos extern int getlogin_r __P ((char *, size_t));
28769606e3fSchristos #else
28869606e3fSchristos extern char *getlogin __P ((void));
28969606e3fSchristos #endif
29069606e3fSchristos
29169606e3fSchristos static
29269606e3fSchristos #if __GNUC__ - 0 >= 2
29369606e3fSchristos inline
29469606e3fSchristos #endif
29569606e3fSchristos const char *next_brace_sub __P ((const char *begin));
29669606e3fSchristos static int glob_in_dir __P ((const char *pattern, const char *directory,
29769606e3fSchristos int flags,
29869606e3fSchristos int (*errfunc) (const char *, int),
29969606e3fSchristos glob_t *pglob));
30069606e3fSchristos static int prefix_array __P ((const char *prefix, char **array, size_t n));
30169606e3fSchristos static int collated_compare __P ((const __ptr_t, const __ptr_t));
30269606e3fSchristos
30369606e3fSchristos #if !defined _LIBC || !defined NO_GLOB_PATTERN_P
30469606e3fSchristos int __glob_pattern_p __P ((const char *pattern, int quote));
30569606e3fSchristos #endif
30669606e3fSchristos
30769606e3fSchristos /* Find the end of the sub-pattern in a brace expression. We define
30869606e3fSchristos this as an inline function if the compiler permits. */
30969606e3fSchristos static
31069606e3fSchristos #if __GNUC__ - 0 >= 2
31169606e3fSchristos inline
31269606e3fSchristos #endif
31369606e3fSchristos const char *
next_brace_sub(begin)31469606e3fSchristos next_brace_sub (begin)
31569606e3fSchristos const char *begin;
31669606e3fSchristos {
31769606e3fSchristos unsigned int depth = 0;
31869606e3fSchristos const char *cp = begin;
31969606e3fSchristos
32069606e3fSchristos while (1)
32169606e3fSchristos {
32269606e3fSchristos if (depth == 0)
32369606e3fSchristos {
32469606e3fSchristos if (*cp != ',' && *cp != '}' && *cp != '\0')
32569606e3fSchristos {
32669606e3fSchristos if (*cp == '{')
32769606e3fSchristos ++depth;
32869606e3fSchristos ++cp;
32969606e3fSchristos continue;
33069606e3fSchristos }
33169606e3fSchristos }
33269606e3fSchristos else
33369606e3fSchristos {
33469606e3fSchristos while (*cp != '\0' && (*cp != '}' || depth > 0))
33569606e3fSchristos {
33669606e3fSchristos if (*cp == '}')
33769606e3fSchristos --depth;
33869606e3fSchristos ++cp;
33969606e3fSchristos }
34069606e3fSchristos if (*cp == '\0')
34169606e3fSchristos /* An incorrectly terminated brace expression. */
34269606e3fSchristos return NULL;
34369606e3fSchristos
34469606e3fSchristos continue;
34569606e3fSchristos }
34669606e3fSchristos break;
34769606e3fSchristos }
34869606e3fSchristos
34969606e3fSchristos return cp;
35069606e3fSchristos }
35169606e3fSchristos
35269606e3fSchristos /* Do glob searching for PATTERN, placing results in PGLOB.
35369606e3fSchristos The bits defined above may be set in FLAGS.
35469606e3fSchristos If a directory cannot be opened or read and ERRFUNC is not nil,
35569606e3fSchristos it is called with the pathname that caused the error, and the
35669606e3fSchristos `errno' value from the failing call; if it returns non-zero
35769606e3fSchristos `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
35869606e3fSchristos If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
35969606e3fSchristos Otherwise, `glob' returns zero. */
36069606e3fSchristos int
glob(pattern,flags,errfunc,pglob)36169606e3fSchristos glob (pattern, flags, errfunc, pglob)
36269606e3fSchristos const char *pattern;
36369606e3fSchristos int flags;
36469606e3fSchristos int (*errfunc) __P ((const char *, int));
36569606e3fSchristos glob_t *pglob;
36669606e3fSchristos {
36769606e3fSchristos const char *filename;
36869606e3fSchristos const char *dirname;
36969606e3fSchristos size_t dirlen;
37069606e3fSchristos int status;
37169606e3fSchristos int oldcount;
37269606e3fSchristos
37369606e3fSchristos if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
37469606e3fSchristos {
37569606e3fSchristos __set_errno (EINVAL);
37669606e3fSchristos return -1;
37769606e3fSchristos }
37869606e3fSchristos
37969606e3fSchristos if (flags & GLOB_BRACE)
38069606e3fSchristos {
38169606e3fSchristos const char *begin = strchr (pattern, '{');
38269606e3fSchristos if (begin != NULL)
38369606e3fSchristos {
38469606e3fSchristos /* Allocate working buffer large enough for our work. Note that
38569606e3fSchristos we have at least an opening and closing brace. */
38669606e3fSchristos int firstc;
38769606e3fSchristos char *alt_start;
38869606e3fSchristos const char *p;
38969606e3fSchristos const char *next;
39069606e3fSchristos const char *rest;
39169606e3fSchristos size_t rest_len;
39269606e3fSchristos #ifdef __GNUC__
39369606e3fSchristos char onealt[strlen (pattern) - 1];
39469606e3fSchristos #else
39569606e3fSchristos char *onealt = (char *) malloc (strlen (pattern) - 1);
39669606e3fSchristos if (onealt == NULL)
39769606e3fSchristos {
39869606e3fSchristos if (!(flags & GLOB_APPEND))
39969606e3fSchristos globfree (pglob);
40069606e3fSchristos return GLOB_NOSPACE;
40169606e3fSchristos }
40269606e3fSchristos #endif
40369606e3fSchristos
40469606e3fSchristos /* We know the prefix for all sub-patterns. */
40569606e3fSchristos #ifdef HAVE_MEMPCPY
40669606e3fSchristos alt_start = mempcpy (onealt, pattern, begin - pattern);
40769606e3fSchristos #else
40869606e3fSchristos memcpy (onealt, pattern, begin - pattern);
40969606e3fSchristos alt_start = &onealt[begin - pattern];
41069606e3fSchristos #endif
41169606e3fSchristos
41269606e3fSchristos /* Find the first sub-pattern and at the same time find the
41369606e3fSchristos rest after the closing brace. */
41469606e3fSchristos next = next_brace_sub (begin + 1);
41569606e3fSchristos if (next == NULL)
41669606e3fSchristos {
41769606e3fSchristos /* It is an illegal expression. */
41869606e3fSchristos #ifndef __GNUC__
41969606e3fSchristos free (onealt);
42069606e3fSchristos #endif
42169606e3fSchristos return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
42269606e3fSchristos }
42369606e3fSchristos
42469606e3fSchristos /* Now find the end of the whole brace expression. */
42569606e3fSchristos rest = next;
42669606e3fSchristos while (*rest != '}')
42769606e3fSchristos {
42869606e3fSchristos rest = next_brace_sub (rest + 1);
42969606e3fSchristos if (rest == NULL)
43069606e3fSchristos {
43169606e3fSchristos /* It is an illegal expression. */
43269606e3fSchristos #ifndef __GNUC__
43369606e3fSchristos free (onealt);
43469606e3fSchristos #endif
43569606e3fSchristos return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
43669606e3fSchristos }
43769606e3fSchristos }
43869606e3fSchristos /* Please note that we now can be sure the brace expression
43969606e3fSchristos is well-formed. */
44069606e3fSchristos rest_len = strlen (++rest) + 1;
44169606e3fSchristos
44269606e3fSchristos /* We have a brace expression. BEGIN points to the opening {,
44369606e3fSchristos NEXT points past the terminator of the first element, and END
44469606e3fSchristos points past the final }. We will accumulate result names from
44569606e3fSchristos recursive runs for each brace alternative in the buffer using
44669606e3fSchristos GLOB_APPEND. */
44769606e3fSchristos
44869606e3fSchristos if (!(flags & GLOB_APPEND))
44969606e3fSchristos {
45069606e3fSchristos /* This call is to set a new vector, so clear out the
45169606e3fSchristos vector so we can append to it. */
45269606e3fSchristos pglob->gl_pathc = 0;
45369606e3fSchristos pglob->gl_pathv = NULL;
45469606e3fSchristos }
45569606e3fSchristos firstc = pglob->gl_pathc;
45669606e3fSchristos
45769606e3fSchristos p = begin + 1;
45869606e3fSchristos while (1)
45969606e3fSchristos {
46069606e3fSchristos int result;
46169606e3fSchristos
46269606e3fSchristos /* Construct the new glob expression. */
46369606e3fSchristos #ifdef HAVE_MEMPCPY
46469606e3fSchristos mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
46569606e3fSchristos #else
46669606e3fSchristos memcpy (alt_start, p, next - p);
46769606e3fSchristos memcpy (&alt_start[next - p], rest, rest_len);
46869606e3fSchristos #endif
46969606e3fSchristos
47069606e3fSchristos result = glob (onealt,
47169606e3fSchristos ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC))
47269606e3fSchristos | GLOB_APPEND), errfunc, pglob);
47369606e3fSchristos
47469606e3fSchristos /* If we got an error, return it. */
47569606e3fSchristos if (result && result != GLOB_NOMATCH)
47669606e3fSchristos {
47769606e3fSchristos #ifndef __GNUC__
47869606e3fSchristos free (onealt);
47969606e3fSchristos #endif
48069606e3fSchristos if (!(flags & GLOB_APPEND))
48169606e3fSchristos globfree (pglob);
48269606e3fSchristos return result;
48369606e3fSchristos }
48469606e3fSchristos
48569606e3fSchristos if (*next == '}')
48669606e3fSchristos /* We saw the last entry. */
48769606e3fSchristos break;
48869606e3fSchristos
48969606e3fSchristos p = next + 1;
49069606e3fSchristos next = next_brace_sub (p);
49169606e3fSchristos assert (next != NULL);
49269606e3fSchristos }
49369606e3fSchristos
49469606e3fSchristos #ifndef __GNUC__
49569606e3fSchristos free (onealt);
49669606e3fSchristos #endif
49769606e3fSchristos
49869606e3fSchristos if (pglob->gl_pathc != firstc)
49969606e3fSchristos /* We found some entries. */
50069606e3fSchristos return 0;
50169606e3fSchristos else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
50269606e3fSchristos return GLOB_NOMATCH;
50369606e3fSchristos }
50469606e3fSchristos }
50569606e3fSchristos
50669606e3fSchristos /* Find the filename. */
50769606e3fSchristos filename = strrchr (pattern, '/');
50869606e3fSchristos #if defined __MSDOS__ || defined WINDOWS32
50969606e3fSchristos /* The case of "d:pattern". Since `:' is not allowed in
51069606e3fSchristos file names, we can safely assume that wherever it
51169606e3fSchristos happens in pattern, it signals the filename part. This
51269606e3fSchristos is so we could some day support patterns like "[a-z]:foo". */
51369606e3fSchristos if (filename == NULL)
51469606e3fSchristos filename = strchr (pattern, ':');
51569606e3fSchristos #endif /* __MSDOS__ || WINDOWS32 */
51669606e3fSchristos if (filename == NULL)
51769606e3fSchristos {
51869606e3fSchristos /* This can mean two things: a simple name or "~name". The later
51969606e3fSchristos case is nothing but a notation for a directory. */
52069606e3fSchristos if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
52169606e3fSchristos {
52269606e3fSchristos dirname = pattern;
52369606e3fSchristos dirlen = strlen (pattern);
52469606e3fSchristos
52569606e3fSchristos /* Set FILENAME to NULL as a special flag. This is ugly but
52669606e3fSchristos other solutions would require much more code. We test for
52769606e3fSchristos this special case below. */
52869606e3fSchristos filename = NULL;
52969606e3fSchristos }
53069606e3fSchristos else
53169606e3fSchristos {
53269606e3fSchristos filename = pattern;
53369606e3fSchristos #ifdef _AMIGA
53469606e3fSchristos dirname = "";
53569606e3fSchristos #else
53669606e3fSchristos dirname = ".";
53769606e3fSchristos #endif
53869606e3fSchristos dirlen = 0;
53969606e3fSchristos }
54069606e3fSchristos }
54169606e3fSchristos else if (filename == pattern)
54269606e3fSchristos {
54369606e3fSchristos /* "/pattern". */
54469606e3fSchristos dirname = "/";
54569606e3fSchristos dirlen = 1;
54669606e3fSchristos ++filename;
54769606e3fSchristos }
54869606e3fSchristos else
54969606e3fSchristos {
55069606e3fSchristos char *newp;
55169606e3fSchristos dirlen = filename - pattern;
55269606e3fSchristos #if defined __MSDOS__ || defined WINDOWS32
55369606e3fSchristos if (*filename == ':'
55469606e3fSchristos || (filename > pattern + 1 && filename[-1] == ':'))
55569606e3fSchristos {
55669606e3fSchristos char *drive_spec;
55769606e3fSchristos
55869606e3fSchristos ++dirlen;
55969606e3fSchristos drive_spec = (char *) __alloca (dirlen + 1);
56069606e3fSchristos #ifdef HAVE_MEMPCPY
56169606e3fSchristos *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
56269606e3fSchristos #else
56369606e3fSchristos memcpy (drive_spec, pattern, dirlen);
56469606e3fSchristos drive_spec[dirlen] = '\0';
56569606e3fSchristos #endif
56669606e3fSchristos /* For now, disallow wildcards in the drive spec, to
56769606e3fSchristos prevent infinite recursion in glob. */
56869606e3fSchristos if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
56969606e3fSchristos return GLOB_NOMATCH;
57069606e3fSchristos /* If this is "d:pattern", we need to copy `:' to DIRNAME
57169606e3fSchristos as well. If it's "d:/pattern", don't remove the slash
57269606e3fSchristos from "d:/", since "d:" and "d:/" are not the same.*/
57369606e3fSchristos }
57469606e3fSchristos #endif
57569606e3fSchristos newp = (char *) __alloca (dirlen + 1);
57669606e3fSchristos #ifdef HAVE_MEMPCPY
57769606e3fSchristos *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
57869606e3fSchristos #else
57969606e3fSchristos memcpy (newp, pattern, dirlen);
58069606e3fSchristos newp[dirlen] = '\0';
58169606e3fSchristos #endif
58269606e3fSchristos dirname = newp;
58369606e3fSchristos ++filename;
58469606e3fSchristos
58569606e3fSchristos if (filename[0] == '\0'
58669606e3fSchristos #if defined __MSDOS__ || defined WINDOWS32
58769606e3fSchristos && dirname[dirlen - 1] != ':'
58869606e3fSchristos && (dirlen < 3 || dirname[dirlen - 2] != ':'
58969606e3fSchristos || dirname[dirlen - 1] != '/')
59069606e3fSchristos #endif
59169606e3fSchristos && dirlen > 1)
59269606e3fSchristos /* "pattern/". Expand "pattern", appending slashes. */
59369606e3fSchristos {
59469606e3fSchristos int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
59569606e3fSchristos if (val == 0)
59669606e3fSchristos pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
59769606e3fSchristos | (flags & GLOB_MARK));
59869606e3fSchristos return val;
59969606e3fSchristos }
60069606e3fSchristos }
60169606e3fSchristos
60269606e3fSchristos if (!(flags & GLOB_APPEND))
60369606e3fSchristos {
60469606e3fSchristos pglob->gl_pathc = 0;
60569606e3fSchristos pglob->gl_pathv = NULL;
60669606e3fSchristos }
60769606e3fSchristos
60869606e3fSchristos oldcount = pglob->gl_pathc;
60969606e3fSchristos
61069606e3fSchristos #ifndef VMS
61169606e3fSchristos if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
61269606e3fSchristos {
61369606e3fSchristos if (dirname[1] == '\0' || dirname[1] == '/')
61469606e3fSchristos {
61569606e3fSchristos /* Look up home directory. */
61669606e3fSchristos #ifdef VMS
61769606e3fSchristos /* This isn't obvious, RTLs of DECC and VAXC know about "HOME" */
61869606e3fSchristos const char *home_dir = getenv ("SYS$LOGIN");
61969606e3fSchristos #else
62069606e3fSchristos const char *home_dir = getenv ("HOME");
62169606e3fSchristos #endif
62269606e3fSchristos # ifdef _AMIGA
62369606e3fSchristos if (home_dir == NULL || home_dir[0] == '\0')
62469606e3fSchristos home_dir = "SYS:";
62569606e3fSchristos # else
62669606e3fSchristos # ifdef WINDOWS32
62769606e3fSchristos if (home_dir == NULL || home_dir[0] == '\0')
62869606e3fSchristos home_dir = "c:/users/default"; /* poor default */
62969606e3fSchristos # else
63069606e3fSchristos # ifdef VMS
63169606e3fSchristos /* Again, this isn't obvious, if "HOME" isn't known "SYS$LOGIN" should be set */
63269606e3fSchristos if (home_dir == NULL || home_dir[0] == '\0')
63369606e3fSchristos home_dir = "SYS$DISK:[]";
63469606e3fSchristos # else
63569606e3fSchristos if (home_dir == NULL || home_dir[0] == '\0')
63669606e3fSchristos {
63769606e3fSchristos int success;
63869606e3fSchristos char *name;
63969606e3fSchristos # if defined HAVE_GETLOGIN_R || defined _LIBC
64069606e3fSchristos size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;
64169606e3fSchristos
64269606e3fSchristos if (buflen == 0)
64369606e3fSchristos /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try
64469606e3fSchristos a moderate value. */
64569606e3fSchristos buflen = 20;
64669606e3fSchristos name = (char *) __alloca (buflen);
64769606e3fSchristos
64869606e3fSchristos success = getlogin_r (name, buflen) >= 0;
64969606e3fSchristos # else
65069606e3fSchristos success = (name = getlogin ()) != NULL;
65169606e3fSchristos # endif
65269606e3fSchristos if (success)
65369606e3fSchristos {
65469606e3fSchristos struct passwd *p;
65569606e3fSchristos # if defined HAVE_GETPWNAM_R || defined _LIBC
65669606e3fSchristos size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
65769606e3fSchristos char *pwtmpbuf;
65869606e3fSchristos struct passwd pwbuf;
65969606e3fSchristos int save = errno;
66069606e3fSchristos
66169606e3fSchristos if (pwbuflen == -1)
66269606e3fSchristos /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
66369606e3fSchristos Try a moderate value. */
66469606e3fSchristos pwbuflen = 1024;
66569606e3fSchristos pwtmpbuf = (char *) __alloca (pwbuflen);
66669606e3fSchristos
66769606e3fSchristos while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
66869606e3fSchristos != 0)
66969606e3fSchristos {
67069606e3fSchristos if (errno != ERANGE)
67169606e3fSchristos {
67269606e3fSchristos p = NULL;
67369606e3fSchristos break;
67469606e3fSchristos }
67569606e3fSchristos pwbuflen *= 2;
67669606e3fSchristos pwtmpbuf = (char *) __alloca (pwbuflen);
67769606e3fSchristos __set_errno (save);
67869606e3fSchristos }
67969606e3fSchristos # else
68069606e3fSchristos p = getpwnam (name);
68169606e3fSchristos # endif
68269606e3fSchristos if (p != NULL)
68369606e3fSchristos home_dir = p->pw_dir;
68469606e3fSchristos }
68569606e3fSchristos }
68669606e3fSchristos if (home_dir == NULL || home_dir[0] == '\0')
68769606e3fSchristos {
68869606e3fSchristos if (flags & GLOB_TILDE_CHECK)
68969606e3fSchristos return GLOB_NOMATCH;
69069606e3fSchristos else
69169606e3fSchristos home_dir = "~"; /* No luck. */
69269606e3fSchristos }
69369606e3fSchristos # endif /* VMS */
69469606e3fSchristos # endif /* WINDOWS32 */
69569606e3fSchristos # endif
69669606e3fSchristos /* Now construct the full directory. */
69769606e3fSchristos if (dirname[1] == '\0')
69869606e3fSchristos dirname = home_dir;
69969606e3fSchristos else
70069606e3fSchristos {
70169606e3fSchristos char *newp;
70269606e3fSchristos size_t home_len = strlen (home_dir);
70369606e3fSchristos newp = (char *) __alloca (home_len + dirlen);
70469606e3fSchristos # ifdef HAVE_MEMPCPY
70569606e3fSchristos mempcpy (mempcpy (newp, home_dir, home_len),
70669606e3fSchristos &dirname[1], dirlen);
70769606e3fSchristos # else
70869606e3fSchristos memcpy (newp, home_dir, home_len);
70969606e3fSchristos memcpy (&newp[home_len], &dirname[1], dirlen);
71069606e3fSchristos # endif
71169606e3fSchristos dirname = newp;
71269606e3fSchristos }
71369606e3fSchristos }
71469606e3fSchristos # if !defined _AMIGA && !defined WINDOWS32 && !defined VMS
71569606e3fSchristos else
71669606e3fSchristos {
71769606e3fSchristos char *end_name = strchr (dirname, '/');
71869606e3fSchristos const char *user_name;
71969606e3fSchristos const char *home_dir;
72069606e3fSchristos
72169606e3fSchristos if (end_name == NULL)
72269606e3fSchristos user_name = dirname + 1;
72369606e3fSchristos else
72469606e3fSchristos {
72569606e3fSchristos char *newp;
72669606e3fSchristos newp = (char *) __alloca (end_name - dirname);
72769606e3fSchristos # ifdef HAVE_MEMPCPY
72869606e3fSchristos *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
72969606e3fSchristos = '\0';
73069606e3fSchristos # else
73169606e3fSchristos memcpy (newp, dirname + 1, end_name - dirname);
73269606e3fSchristos newp[end_name - dirname - 1] = '\0';
73369606e3fSchristos # endif
73469606e3fSchristos user_name = newp;
73569606e3fSchristos }
73669606e3fSchristos
73769606e3fSchristos /* Look up specific user's home directory. */
73869606e3fSchristos {
73969606e3fSchristos struct passwd *p;
74069606e3fSchristos # if defined HAVE_GETPWNAM_R || defined _LIBC
74169606e3fSchristos size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
74269606e3fSchristos char *pwtmpbuf;
74369606e3fSchristos struct passwd pwbuf;
74469606e3fSchristos int save = errno;
74569606e3fSchristos
74669606e3fSchristos if (buflen == -1)
74769606e3fSchristos /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a
74869606e3fSchristos moderate value. */
74969606e3fSchristos buflen = 1024;
75069606e3fSchristos pwtmpbuf = (char *) __alloca (buflen);
75169606e3fSchristos
75269606e3fSchristos while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
75369606e3fSchristos {
75469606e3fSchristos if (errno != ERANGE)
75569606e3fSchristos {
75669606e3fSchristos p = NULL;
75769606e3fSchristos break;
75869606e3fSchristos }
75969606e3fSchristos buflen *= 2;
76069606e3fSchristos pwtmpbuf = __alloca (buflen);
76169606e3fSchristos __set_errno (save);
76269606e3fSchristos }
76369606e3fSchristos # else
76469606e3fSchristos p = getpwnam (user_name);
76569606e3fSchristos # endif
76669606e3fSchristos if (p != NULL)
76769606e3fSchristos home_dir = p->pw_dir;
76869606e3fSchristos else
76969606e3fSchristos home_dir = NULL;
77069606e3fSchristos }
77169606e3fSchristos /* If we found a home directory use this. */
77269606e3fSchristos if (home_dir != NULL)
77369606e3fSchristos {
77469606e3fSchristos char *newp;
77569606e3fSchristos size_t home_len = strlen (home_dir);
77669606e3fSchristos size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
77769606e3fSchristos newp = (char *) __alloca (home_len + rest_len + 1);
77869606e3fSchristos # ifdef HAVE_MEMPCPY
77969606e3fSchristos *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
78069606e3fSchristos end_name, rest_len)) = '\0';
78169606e3fSchristos # else
78269606e3fSchristos memcpy (newp, home_dir, home_len);
78369606e3fSchristos memcpy (&newp[home_len], end_name, rest_len);
78469606e3fSchristos newp[home_len + rest_len] = '\0';
78569606e3fSchristos # endif
78669606e3fSchristos dirname = newp;
78769606e3fSchristos }
78869606e3fSchristos else
78969606e3fSchristos if (flags & GLOB_TILDE_CHECK)
79069606e3fSchristos /* We have to regard it as an error if we cannot find the
79169606e3fSchristos home directory. */
79269606e3fSchristos return GLOB_NOMATCH;
79369606e3fSchristos }
79469606e3fSchristos # endif /* Not Amiga && not WINDOWS32 && not VMS. */
79569606e3fSchristos }
79669606e3fSchristos #endif /* Not VMS. */
79769606e3fSchristos
79869606e3fSchristos /* Now test whether we looked for "~" or "~NAME". In this case we
79969606e3fSchristos can give the answer now. */
80069606e3fSchristos if (filename == NULL)
80169606e3fSchristos {
80269606e3fSchristos struct stat st;
80369606e3fSchristos
80469606e3fSchristos /* Return the directory if we don't check for error or if it exists. */
80569606e3fSchristos if ((flags & GLOB_NOCHECK)
80669606e3fSchristos || (((flags & GLOB_ALTDIRFUNC)
80769606e3fSchristos ? (*pglob->gl_stat) (dirname, &st)
80869606e3fSchristos : __stat (dirname, &st)) == 0
80969606e3fSchristos && S_ISDIR (st.st_mode)))
81069606e3fSchristos {
81169606e3fSchristos pglob->gl_pathv
81269606e3fSchristos = (char **) realloc (pglob->gl_pathv,
81369606e3fSchristos (pglob->gl_pathc +
81469606e3fSchristos ((flags & GLOB_DOOFFS) ?
81569606e3fSchristos pglob->gl_offs : 0) +
81669606e3fSchristos 1 + 1) *
81769606e3fSchristos sizeof (char *));
81869606e3fSchristos if (pglob->gl_pathv == NULL)
81969606e3fSchristos return GLOB_NOSPACE;
82069606e3fSchristos
82169606e3fSchristos if (flags & GLOB_DOOFFS)
82269606e3fSchristos while (pglob->gl_pathc < pglob->gl_offs)
82369606e3fSchristos pglob->gl_pathv[pglob->gl_pathc++] = NULL;
82469606e3fSchristos
82569606e3fSchristos #if defined HAVE_STRDUP || defined _LIBC
82669606e3fSchristos pglob->gl_pathv[pglob->gl_pathc] = strdup (dirname);
82769606e3fSchristos #else
82869606e3fSchristos {
82969606e3fSchristos size_t len = strlen (dirname) + 1;
83069606e3fSchristos char *dircopy = malloc (len);
83169606e3fSchristos if (dircopy != NULL)
83269606e3fSchristos pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname,
83369606e3fSchristos len);
83469606e3fSchristos }
83569606e3fSchristos #endif
83669606e3fSchristos if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
83769606e3fSchristos {
83869606e3fSchristos free (pglob->gl_pathv);
83969606e3fSchristos return GLOB_NOSPACE;
84069606e3fSchristos }
84169606e3fSchristos pglob->gl_pathv[++pglob->gl_pathc] = NULL;
84269606e3fSchristos pglob->gl_flags = flags;
84369606e3fSchristos
84469606e3fSchristos return 0;
84569606e3fSchristos }
84669606e3fSchristos
84769606e3fSchristos /* Not found. */
84869606e3fSchristos return GLOB_NOMATCH;
84969606e3fSchristos }
85069606e3fSchristos
85169606e3fSchristos if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
85269606e3fSchristos {
85369606e3fSchristos /* The directory name contains metacharacters, so we
85469606e3fSchristos have to glob for the directory, and then glob for
85569606e3fSchristos the pattern in each directory found. */
85669606e3fSchristos glob_t dirs;
85769606e3fSchristos register int i;
85869606e3fSchristos
85969606e3fSchristos status = glob (dirname,
86069606e3fSchristos ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE))
86169606e3fSchristos | GLOB_NOSORT | GLOB_ONLYDIR),
86269606e3fSchristos errfunc, &dirs);
86369606e3fSchristos if (status != 0)
86469606e3fSchristos return status;
86569606e3fSchristos
86669606e3fSchristos /* We have successfully globbed the preceding directory name.
86769606e3fSchristos For each name we found, call glob_in_dir on it and FILENAME,
86869606e3fSchristos appending the results to PGLOB. */
86969606e3fSchristos for (i = 0; i < dirs.gl_pathc; ++i)
87069606e3fSchristos {
87169606e3fSchristos int old_pathc;
87269606e3fSchristos
87369606e3fSchristos #ifdef SHELL
87469606e3fSchristos {
87569606e3fSchristos /* Make globbing interruptible in the bash shell. */
87669606e3fSchristos extern int interrupt_state;
87769606e3fSchristos
87869606e3fSchristos if (interrupt_state)
87969606e3fSchristos {
88069606e3fSchristos globfree (&dirs);
88169606e3fSchristos globfree (&files);
88269606e3fSchristos return GLOB_ABORTED;
88369606e3fSchristos }
88469606e3fSchristos }
88569606e3fSchristos #endif /* SHELL. */
88669606e3fSchristos
88769606e3fSchristos old_pathc = pglob->gl_pathc;
88869606e3fSchristos status = glob_in_dir (filename, dirs.gl_pathv[i],
88969606e3fSchristos ((flags | GLOB_APPEND)
89069606e3fSchristos & ~(GLOB_NOCHECK | GLOB_ERR)),
89169606e3fSchristos errfunc, pglob);
89269606e3fSchristos if (status == GLOB_NOMATCH)
89369606e3fSchristos /* No matches in this directory. Try the next. */
89469606e3fSchristos continue;
89569606e3fSchristos
89669606e3fSchristos if (status != 0)
89769606e3fSchristos {
89869606e3fSchristos globfree (&dirs);
89969606e3fSchristos globfree (pglob);
90069606e3fSchristos return status;
90169606e3fSchristos }
90269606e3fSchristos
90369606e3fSchristos /* Stick the directory on the front of each name. */
90469606e3fSchristos if (prefix_array (dirs.gl_pathv[i],
90569606e3fSchristos &pglob->gl_pathv[old_pathc],
90669606e3fSchristos pglob->gl_pathc - old_pathc))
90769606e3fSchristos {
90869606e3fSchristos globfree (&dirs);
90969606e3fSchristos globfree (pglob);
91069606e3fSchristos return GLOB_NOSPACE;
91169606e3fSchristos }
91269606e3fSchristos }
91369606e3fSchristos
91469606e3fSchristos flags |= GLOB_MAGCHAR;
91569606e3fSchristos
91669606e3fSchristos /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
91769606e3fSchristos But if we have not found any matching entry and thie GLOB_NOCHECK
91869606e3fSchristos flag was set we must return the list consisting of the disrectory
91969606e3fSchristos names followed by the filename. */
92069606e3fSchristos if (pglob->gl_pathc == oldcount)
92169606e3fSchristos {
92269606e3fSchristos /* No matches. */
92369606e3fSchristos if (flags & GLOB_NOCHECK)
92469606e3fSchristos {
92569606e3fSchristos size_t filename_len = strlen (filename) + 1;
92669606e3fSchristos char **new_pathv;
92769606e3fSchristos struct stat st;
92869606e3fSchristos
92969606e3fSchristos /* This is an pessimistic guess about the size. */
93069606e3fSchristos pglob->gl_pathv
93169606e3fSchristos = (char **) realloc (pglob->gl_pathv,
93269606e3fSchristos (pglob->gl_pathc +
93369606e3fSchristos ((flags & GLOB_DOOFFS) ?
93469606e3fSchristos pglob->gl_offs : 0) +
93569606e3fSchristos dirs.gl_pathc + 1) *
93669606e3fSchristos sizeof (char *));
93769606e3fSchristos if (pglob->gl_pathv == NULL)
93869606e3fSchristos {
93969606e3fSchristos globfree (&dirs);
94069606e3fSchristos return GLOB_NOSPACE;
94169606e3fSchristos }
94269606e3fSchristos
94369606e3fSchristos if (flags & GLOB_DOOFFS)
94469606e3fSchristos while (pglob->gl_pathc < pglob->gl_offs)
94569606e3fSchristos pglob->gl_pathv[pglob->gl_pathc++] = NULL;
94669606e3fSchristos
94769606e3fSchristos for (i = 0; i < dirs.gl_pathc; ++i)
94869606e3fSchristos {
94969606e3fSchristos const char *dir = dirs.gl_pathv[i];
95069606e3fSchristos size_t dir_len = strlen (dir);
95169606e3fSchristos
95269606e3fSchristos /* First check whether this really is a directory. */
95369606e3fSchristos if (((flags & GLOB_ALTDIRFUNC)
95469606e3fSchristos ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0
95569606e3fSchristos || !S_ISDIR (st.st_mode))
95669606e3fSchristos /* No directory, ignore this entry. */
95769606e3fSchristos continue;
95869606e3fSchristos
95969606e3fSchristos pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1
96069606e3fSchristos + filename_len);
96169606e3fSchristos if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
96269606e3fSchristos {
96369606e3fSchristos globfree (&dirs);
96469606e3fSchristos globfree (pglob);
96569606e3fSchristos return GLOB_NOSPACE;
96669606e3fSchristos }
96769606e3fSchristos
96869606e3fSchristos #ifdef HAVE_MEMPCPY
96969606e3fSchristos mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc],
97069606e3fSchristos dir, dir_len),
97169606e3fSchristos "/", 1),
97269606e3fSchristos filename, filename_len);
97369606e3fSchristos #else
97469606e3fSchristos memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len);
97569606e3fSchristos pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/';
97669606e3fSchristos memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1],
97769606e3fSchristos filename, filename_len);
97869606e3fSchristos #endif
97969606e3fSchristos ++pglob->gl_pathc;
98069606e3fSchristos }
98169606e3fSchristos
98269606e3fSchristos pglob->gl_pathv[pglob->gl_pathc] = NULL;
98369606e3fSchristos pglob->gl_flags = flags;
98469606e3fSchristos
98569606e3fSchristos /* Now we know how large the gl_pathv vector must be. */
98669606e3fSchristos new_pathv = (char **) realloc (pglob->gl_pathv,
98769606e3fSchristos ((pglob->gl_pathc + 1)
98869606e3fSchristos * sizeof (char *)));
98969606e3fSchristos if (new_pathv != NULL)
99069606e3fSchristos pglob->gl_pathv = new_pathv;
99169606e3fSchristos }
99269606e3fSchristos else
99369606e3fSchristos return GLOB_NOMATCH;
99469606e3fSchristos }
99569606e3fSchristos
99669606e3fSchristos globfree (&dirs);
99769606e3fSchristos }
99869606e3fSchristos else
99969606e3fSchristos {
100069606e3fSchristos status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
100169606e3fSchristos if (status != 0)
100269606e3fSchristos return status;
100369606e3fSchristos
100469606e3fSchristos if (dirlen > 0)
100569606e3fSchristos {
100669606e3fSchristos /* Stick the directory on the front of each name. */
100769606e3fSchristos int ignore = oldcount;
100869606e3fSchristos
100969606e3fSchristos if ((flags & GLOB_DOOFFS) && ignore < pglob->gl_offs)
101069606e3fSchristos ignore = pglob->gl_offs;
101169606e3fSchristos
101269606e3fSchristos if (prefix_array (dirname,
101369606e3fSchristos &pglob->gl_pathv[ignore],
101469606e3fSchristos pglob->gl_pathc - ignore))
101569606e3fSchristos {
101669606e3fSchristos globfree (pglob);
101769606e3fSchristos return GLOB_NOSPACE;
101869606e3fSchristos }
101969606e3fSchristos }
102069606e3fSchristos }
102169606e3fSchristos
102269606e3fSchristos if (flags & GLOB_MARK)
102369606e3fSchristos {
102469606e3fSchristos /* Append slashes to directory names. */
102569606e3fSchristos int i;
102669606e3fSchristos struct stat st;
102769606e3fSchristos for (i = oldcount; i < pglob->gl_pathc; ++i)
102869606e3fSchristos if (((flags & GLOB_ALTDIRFUNC)
102969606e3fSchristos ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st)
103069606e3fSchristos : __stat (pglob->gl_pathv[i], &st)) == 0
103169606e3fSchristos && S_ISDIR (st.st_mode))
103269606e3fSchristos {
103369606e3fSchristos size_t len = strlen (pglob->gl_pathv[i]) + 2;
103469606e3fSchristos char *new = realloc (pglob->gl_pathv[i], len);
103569606e3fSchristos if (new == NULL)
103669606e3fSchristos {
103769606e3fSchristos globfree (pglob);
103869606e3fSchristos return GLOB_NOSPACE;
103969606e3fSchristos }
104069606e3fSchristos strcpy (&new[len - 2], "/");
104169606e3fSchristos pglob->gl_pathv[i] = new;
104269606e3fSchristos }
104369606e3fSchristos }
104469606e3fSchristos
104569606e3fSchristos if (!(flags & GLOB_NOSORT))
104669606e3fSchristos {
104769606e3fSchristos /* Sort the vector. */
104869606e3fSchristos int non_sort = oldcount;
104969606e3fSchristos
105069606e3fSchristos if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount)
105169606e3fSchristos non_sort = pglob->gl_offs;
105269606e3fSchristos
105369606e3fSchristos qsort ((__ptr_t) &pglob->gl_pathv[non_sort],
105469606e3fSchristos pglob->gl_pathc - non_sort,
105569606e3fSchristos sizeof (char *), collated_compare);
105669606e3fSchristos }
105769606e3fSchristos
105869606e3fSchristos return 0;
105969606e3fSchristos }
106069606e3fSchristos
106169606e3fSchristos
106269606e3fSchristos /* Free storage allocated in PGLOB by a previous `glob' call. */
106369606e3fSchristos void
globfree(pglob)106469606e3fSchristos globfree (pglob)
106569606e3fSchristos register glob_t *pglob;
106669606e3fSchristos {
106769606e3fSchristos if (pglob->gl_pathv != NULL)
106869606e3fSchristos {
106969606e3fSchristos register int i;
107069606e3fSchristos for (i = 0; i < pglob->gl_pathc; ++i)
107169606e3fSchristos if (pglob->gl_pathv[i] != NULL)
107269606e3fSchristos free ((__ptr_t) pglob->gl_pathv[i]);
107369606e3fSchristos free ((__ptr_t) pglob->gl_pathv);
107469606e3fSchristos }
107569606e3fSchristos }
107669606e3fSchristos
107769606e3fSchristos
107869606e3fSchristos /* Do a collated comparison of A and B. */
107969606e3fSchristos static int
collated_compare(a,b)108069606e3fSchristos collated_compare (a, b)
108169606e3fSchristos const __ptr_t a;
108269606e3fSchristos const __ptr_t b;
108369606e3fSchristos {
108469606e3fSchristos const char *const s1 = *(const char *const * const) a;
108569606e3fSchristos const char *const s2 = *(const char *const * const) b;
108669606e3fSchristos
108769606e3fSchristos if (s1 == s2)
108869606e3fSchristos return 0;
108969606e3fSchristos if (s1 == NULL)
109069606e3fSchristos return 1;
109169606e3fSchristos if (s2 == NULL)
109269606e3fSchristos return -1;
109369606e3fSchristos return strcoll (s1, s2);
109469606e3fSchristos }
109569606e3fSchristos
109669606e3fSchristos
109769606e3fSchristos /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
109869606e3fSchristos elements in place. Return nonzero if out of memory, zero if successful.
109969606e3fSchristos A slash is inserted between DIRNAME and each elt of ARRAY,
110069606e3fSchristos unless DIRNAME is just "/". Each old element of ARRAY is freed. */
110169606e3fSchristos static int
prefix_array(dirname,array,n)110269606e3fSchristos prefix_array (dirname, array, n)
110369606e3fSchristos const char *dirname;
110469606e3fSchristos char **array;
110569606e3fSchristos size_t n;
110669606e3fSchristos {
110769606e3fSchristos register size_t i;
110869606e3fSchristos size_t dirlen = strlen (dirname);
110969606e3fSchristos #if defined __MSDOS__ || defined WINDOWS32
111069606e3fSchristos int sep_char = '/';
111169606e3fSchristos # define DIRSEP_CHAR sep_char
111269606e3fSchristos #else
111369606e3fSchristos # define DIRSEP_CHAR '/'
111469606e3fSchristos #endif
111569606e3fSchristos
111669606e3fSchristos if (dirlen == 1 && dirname[0] == '/')
111769606e3fSchristos /* DIRNAME is just "/", so normal prepending would get us "//foo".
111869606e3fSchristos We want "/foo" instead, so don't prepend any chars from DIRNAME. */
111969606e3fSchristos dirlen = 0;
112069606e3fSchristos #if defined __MSDOS__ || defined WINDOWS32
112169606e3fSchristos else if (dirlen > 1)
112269606e3fSchristos {
112369606e3fSchristos if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
112469606e3fSchristos /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */
112569606e3fSchristos --dirlen;
112669606e3fSchristos else if (dirname[dirlen - 1] == ':')
112769606e3fSchristos {
112869606e3fSchristos /* DIRNAME is "d:". Use `:' instead of `/'. */
112969606e3fSchristos --dirlen;
113069606e3fSchristos sep_char = ':';
113169606e3fSchristos }
113269606e3fSchristos }
113369606e3fSchristos #endif
113469606e3fSchristos
113569606e3fSchristos for (i = 0; i < n; ++i)
113669606e3fSchristos {
113769606e3fSchristos size_t eltlen = strlen (array[i]) + 1;
113869606e3fSchristos char *new = (char *) malloc (dirlen + 1 + eltlen);
113969606e3fSchristos if (new == NULL)
114069606e3fSchristos {
114169606e3fSchristos while (i > 0)
114269606e3fSchristos free ((__ptr_t) array[--i]);
114369606e3fSchristos return 1;
114469606e3fSchristos }
114569606e3fSchristos
114669606e3fSchristos #ifdef HAVE_MEMPCPY
114769606e3fSchristos {
114869606e3fSchristos char *endp = (char *) mempcpy (new, dirname, dirlen);
114969606e3fSchristos *endp++ = DIRSEP_CHAR;
115069606e3fSchristos mempcpy (endp, array[i], eltlen);
115169606e3fSchristos }
115269606e3fSchristos #else
115369606e3fSchristos memcpy (new, dirname, dirlen);
115469606e3fSchristos new[dirlen] = DIRSEP_CHAR;
115569606e3fSchristos memcpy (&new[dirlen + 1], array[i], eltlen);
115669606e3fSchristos #endif
115769606e3fSchristos free ((__ptr_t) array[i]);
115869606e3fSchristos array[i] = new;
115969606e3fSchristos }
116069606e3fSchristos
116169606e3fSchristos return 0;
116269606e3fSchristos }
116369606e3fSchristos
116469606e3fSchristos
116569606e3fSchristos /* We must not compile this function twice. */
116669606e3fSchristos #if !defined _LIBC || !defined NO_GLOB_PATTERN_P
116769606e3fSchristos /* Return nonzero if PATTERN contains any metacharacters.
116869606e3fSchristos Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
116969606e3fSchristos int
__glob_pattern_p(pattern,quote)117069606e3fSchristos __glob_pattern_p (pattern, quote)
117169606e3fSchristos const char *pattern;
117269606e3fSchristos int quote;
117369606e3fSchristos {
117469606e3fSchristos register const char *p;
117569606e3fSchristos int open = 0;
117669606e3fSchristos
117769606e3fSchristos for (p = pattern; *p != '\0'; ++p)
117869606e3fSchristos switch (*p)
117969606e3fSchristos {
118069606e3fSchristos case '?':
118169606e3fSchristos case '*':
118269606e3fSchristos return 1;
118369606e3fSchristos
118469606e3fSchristos case '\\':
118569606e3fSchristos if (quote && p[1] != '\0')
118669606e3fSchristos ++p;
118769606e3fSchristos break;
118869606e3fSchristos
118969606e3fSchristos case '[':
119069606e3fSchristos open = 1;
119169606e3fSchristos break;
119269606e3fSchristos
119369606e3fSchristos case ']':
119469606e3fSchristos if (open)
119569606e3fSchristos return 1;
119669606e3fSchristos break;
119769606e3fSchristos }
119869606e3fSchristos
119969606e3fSchristos return 0;
120069606e3fSchristos }
120169606e3fSchristos # ifdef _LIBC
120269606e3fSchristos weak_alias (__glob_pattern_p, glob_pattern_p)
120369606e3fSchristos # endif
120469606e3fSchristos #endif
120569606e3fSchristos
120669606e3fSchristos
120769606e3fSchristos /* Like `glob', but PATTERN is a final pathname component,
120869606e3fSchristos and matches are searched for in DIRECTORY.
120969606e3fSchristos The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
121069606e3fSchristos The GLOB_APPEND flag is assumed to be set (always appends). */
121169606e3fSchristos static int
121269606e3fSchristos glob_in_dir (pattern, directory, flags, errfunc, pglob)
121369606e3fSchristos const char *pattern;
121469606e3fSchristos const char *directory;
121569606e3fSchristos int flags;
121669606e3fSchristos int (*errfunc) __P ((const char *, int));
121769606e3fSchristos glob_t *pglob;
121869606e3fSchristos {
121969606e3fSchristos __ptr_t stream = NULL;
122069606e3fSchristos
122169606e3fSchristos struct globlink
122269606e3fSchristos {
122369606e3fSchristos struct globlink *next;
122469606e3fSchristos char *name;
122569606e3fSchristos };
122669606e3fSchristos struct globlink *names = NULL;
122769606e3fSchristos size_t nfound;
122869606e3fSchristos int meta;
122969606e3fSchristos int save;
123069606e3fSchristos
123169606e3fSchristos #ifdef VMS
123269606e3fSchristos if (*directory == 0)
123369606e3fSchristos directory = "[]";
123469606e3fSchristos #endif
123569606e3fSchristos meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
123669606e3fSchristos if (meta == 0)
123769606e3fSchristos {
123869606e3fSchristos if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))
123969606e3fSchristos /* We need not do any tests. The PATTERN contains no meta
124069606e3fSchristos characters and we must not return an error therefore the
124169606e3fSchristos result will always contain exactly one name. */
124269606e3fSchristos flags |= GLOB_NOCHECK;
124369606e3fSchristos else
124469606e3fSchristos {
124569606e3fSchristos /* Since we use the normal file functions we can also use stat()
124669606e3fSchristos to verify the file is there. */
124769606e3fSchristos struct stat st;
124869606e3fSchristos size_t patlen = strlen (pattern);
124969606e3fSchristos size_t dirlen = strlen (directory);
125069606e3fSchristos char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
125169606e3fSchristos
125269606e3fSchristos # ifdef HAVE_MEMPCPY
125369606e3fSchristos mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
125469606e3fSchristos "/", 1),
125569606e3fSchristos pattern, patlen + 1);
125669606e3fSchristos # else
125769606e3fSchristos memcpy (fullname, directory, dirlen);
125869606e3fSchristos fullname[dirlen] = '/';
125969606e3fSchristos memcpy (&fullname[dirlen + 1], pattern, patlen + 1);
126069606e3fSchristos # endif
126169606e3fSchristos if (((flags & GLOB_ALTDIRFUNC)
126269606e3fSchristos ? (*pglob->gl_stat) (fullname, &st)
126369606e3fSchristos : __stat (fullname, &st)) == 0)
126469606e3fSchristos /* We found this file to be existing. Now tell the rest
126569606e3fSchristos of the function to copy this name into the result. */
126669606e3fSchristos flags |= GLOB_NOCHECK;
126769606e3fSchristos }
126869606e3fSchristos
126969606e3fSchristos nfound = 0;
127069606e3fSchristos }
127169606e3fSchristos else
127269606e3fSchristos {
127369606e3fSchristos if (pattern[0] == '\0')
127469606e3fSchristos {
127569606e3fSchristos /* This is a special case for matching directories like in
127669606e3fSchristos "*a/". */
127769606e3fSchristos names = (struct globlink *) __alloca (sizeof (struct globlink));
127869606e3fSchristos names->name = (char *) malloc (1);
127969606e3fSchristos if (names->name == NULL)
128069606e3fSchristos goto memory_error;
128169606e3fSchristos names->name[0] = '\0';
128269606e3fSchristos names->next = NULL;
128369606e3fSchristos nfound = 1;
128469606e3fSchristos meta = 0;
128569606e3fSchristos }
128669606e3fSchristos else
128769606e3fSchristos {
128869606e3fSchristos stream = ((flags & GLOB_ALTDIRFUNC)
128969606e3fSchristos ? (*pglob->gl_opendir) (directory)
129069606e3fSchristos : (__ptr_t) opendir (directory));
129169606e3fSchristos if (stream == NULL)
129269606e3fSchristos {
129369606e3fSchristos if (errno != ENOTDIR
129469606e3fSchristos && ((errfunc != NULL && (*errfunc) (directory, errno))
129569606e3fSchristos || (flags & GLOB_ERR)))
129669606e3fSchristos return GLOB_ABORTED;
129769606e3fSchristos nfound = 0;
129869606e3fSchristos meta = 0;
129969606e3fSchristos }
130069606e3fSchristos else
130169606e3fSchristos {
130269606e3fSchristos int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
130369606e3fSchristos | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
130469606e3fSchristos #if defined HAVE_CASE_INSENSITIVE_FS
130569606e3fSchristos | FNM_CASEFOLD
130669606e3fSchristos #endif
130769606e3fSchristos );
130869606e3fSchristos nfound = 0;
130969606e3fSchristos flags |= GLOB_MAGCHAR;
131069606e3fSchristos
131169606e3fSchristos while (1)
131269606e3fSchristos {
131369606e3fSchristos const char *name;
131469606e3fSchristos size_t len;
131569606e3fSchristos struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
131669606e3fSchristos ? (*pglob->gl_readdir) (stream)
131769606e3fSchristos : readdir ((DIR *) stream));
131869606e3fSchristos if (d == NULL)
131969606e3fSchristos break;
132069606e3fSchristos if (! REAL_DIR_ENTRY (d))
132169606e3fSchristos continue;
132269606e3fSchristos
132369606e3fSchristos #ifdef HAVE_D_TYPE
132469606e3fSchristos /* If we shall match only directories use the information
132569606e3fSchristos provided by the dirent call if possible. */
132669606e3fSchristos if ((flags & GLOB_ONLYDIR)
132769606e3fSchristos && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
132869606e3fSchristos continue;
132969606e3fSchristos #endif
133069606e3fSchristos
133169606e3fSchristos name = d->d_name;
133269606e3fSchristos
133369606e3fSchristos if (fnmatch (pattern, name, fnm_flags) == 0)
133469606e3fSchristos {
133569606e3fSchristos struct globlink *new = (struct globlink *)
133669606e3fSchristos __alloca (sizeof (struct globlink));
133769606e3fSchristos len = NAMLEN (d);
133869606e3fSchristos new->name = (char *) malloc (len + 1);
133969606e3fSchristos if (new->name == NULL)
134069606e3fSchristos goto memory_error;
134169606e3fSchristos #ifdef HAVE_MEMPCPY
134269606e3fSchristos *((char *) mempcpy ((__ptr_t) new->name, name, len))
134369606e3fSchristos = '\0';
134469606e3fSchristos #else
134569606e3fSchristos memcpy ((__ptr_t) new->name, name, len);
134669606e3fSchristos new->name[len] = '\0';
134769606e3fSchristos #endif
134869606e3fSchristos new->next = names;
134969606e3fSchristos names = new;
135069606e3fSchristos ++nfound;
135169606e3fSchristos }
135269606e3fSchristos }
135369606e3fSchristos }
135469606e3fSchristos }
135569606e3fSchristos }
135669606e3fSchristos
135769606e3fSchristos if (nfound == 0 && (flags & GLOB_NOCHECK))
135869606e3fSchristos {
135969606e3fSchristos size_t len = strlen (pattern);
136069606e3fSchristos nfound = 1;
136169606e3fSchristos names = (struct globlink *) __alloca (sizeof (struct globlink));
136269606e3fSchristos names->next = NULL;
136369606e3fSchristos names->name = (char *) malloc (len + 1);
136469606e3fSchristos if (names->name == NULL)
136569606e3fSchristos goto memory_error;
136669606e3fSchristos #ifdef HAVE_MEMPCPY
136769606e3fSchristos *((char *) mempcpy (names->name, pattern, len)) = '\0';
136869606e3fSchristos #else
136969606e3fSchristos memcpy (names->name, pattern, len);
137069606e3fSchristos names->name[len] = '\0';
137169606e3fSchristos #endif
137269606e3fSchristos }
137369606e3fSchristos
137469606e3fSchristos if (nfound != 0)
137569606e3fSchristos {
137669606e3fSchristos pglob->gl_pathv
137769606e3fSchristos = (char **) realloc (pglob->gl_pathv,
137869606e3fSchristos (pglob->gl_pathc +
137969606e3fSchristos ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
138069606e3fSchristos nfound + 1) *
138169606e3fSchristos sizeof (char *));
138269606e3fSchristos if (pglob->gl_pathv == NULL)
138369606e3fSchristos goto memory_error;
138469606e3fSchristos
138569606e3fSchristos if (flags & GLOB_DOOFFS)
138669606e3fSchristos while (pglob->gl_pathc < pglob->gl_offs)
138769606e3fSchristos pglob->gl_pathv[pglob->gl_pathc++] = NULL;
138869606e3fSchristos
138969606e3fSchristos for (; names != NULL; names = names->next)
139069606e3fSchristos pglob->gl_pathv[pglob->gl_pathc++] = names->name;
139169606e3fSchristos pglob->gl_pathv[pglob->gl_pathc] = NULL;
139269606e3fSchristos
139369606e3fSchristos pglob->gl_flags = flags;
139469606e3fSchristos }
139569606e3fSchristos
139669606e3fSchristos save = errno;
139769606e3fSchristos if (stream != NULL)
139869606e3fSchristos {
139969606e3fSchristos if (flags & GLOB_ALTDIRFUNC)
140069606e3fSchristos (*pglob->gl_closedir) (stream);
140169606e3fSchristos else
140269606e3fSchristos closedir ((DIR *) stream);
140369606e3fSchristos }
140469606e3fSchristos __set_errno (save);
140569606e3fSchristos
140669606e3fSchristos return nfound == 0 ? GLOB_NOMATCH : 0;
140769606e3fSchristos
140869606e3fSchristos memory_error:
140969606e3fSchristos {
141069606e3fSchristos int save = errno;
141169606e3fSchristos if (flags & GLOB_ALTDIRFUNC)
141269606e3fSchristos (*pglob->gl_closedir) (stream);
141369606e3fSchristos else
141469606e3fSchristos closedir ((DIR *) stream);
141569606e3fSchristos __set_errno (save);
141669606e3fSchristos }
141769606e3fSchristos while (names != NULL)
141869606e3fSchristos {
141969606e3fSchristos if (names->name != NULL)
142069606e3fSchristos free ((__ptr_t) names->name);
142169606e3fSchristos names = names->next;
142269606e3fSchristos }
142369606e3fSchristos return GLOB_NOSPACE;
142469606e3fSchristos }
142569606e3fSchristos
142669606e3fSchristos #endif /* Not ELIDE_CODE. */
1427