VirtualBox

source: kBuild/trunk/src/kmk/glob/glob.c@ 3432

Last change on this file since 3432 was 3153, checked in by bird, 7 years ago

kmk/glob.c: More double underscore fixes. Warning fix.

  • Property svn:eol-style set to native
File size: 36.2 KB
Line 
1/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999 Free
2Software Foundation, Inc.
3
4This library is free software; you can redistribute it and/or
5modify it under the terms of the GNU Library General Public License as
6published by the Free Software Foundation; either version 2 of the
7License, or (at your option) any later version.
8
9This library is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12Library General Public License for more details.
13
14You should have received a copy of the GNU Library General Public License
15along with this library; see the file COPYING.LIB. If not, write to the Free
16Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
17USA. */
18
19/* AIX requires this to be the first thing in the file. */
20#if defined _AIX && !defined __GNUC__
21 #pragma alloca
22#endif
23
24#ifdef HAVE_CONFIG_H
25# include <config.h>
26#endif
27
28/* Enable GNU extensions in glob.h. */
29#ifndef _GNU_SOURCE
30# define _GNU_SOURCE 1
31#endif
32
33#include <errno.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36
37/* Outcomment the following line for production quality code. */
38/* #define NDEBUG 1 */
39#include <assert.h>
40
41#include <stdio.h> /* Needed on stupid SunOS for assert. */
42
43
44/* Comment out all this code if we are using the GNU C Library, and are not
45 actually compiling the library itself. This code is part of the GNU C
46 Library, but also included in many other GNU distributions. Compiling
47 and linking in this code is a waste when using the GNU C library
48 (especially if it is a shared library). Rather than having every GNU
49 program understand `configure --with-gnu-libc' and omit the object files,
50 it is simpler to just do this in the source for each such file. */
51
52#define GLOB_INTERFACE_VERSION 1
53#if 0 /* bird: Apparently this causes trouble for some debian builds. */
54#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
55# include <gnu-versions.h>
56# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
57# define ELIDE_CODE
58# endif
59#endif
60#endif
61
62#ifndef ELIDE_CODE
63
64#if defined STDC_HEADERS || defined __GNU_LIBRARY__
65# include <stddef.h>
66#endif
67
68#if defined HAVE_UNISTD_H || defined _LIBC
69# include <unistd.h>
70# ifndef POSIX
71# ifdef _POSIX_VERSION
72# define POSIX
73# endif
74# endif
75#endif
76
77#if !defined _AMIGA && !defined VMS && !defined WINDOWS32
78# include <pwd.h>
79#endif
80
81#if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS
82extern int errno;
83#endif
84#ifndef __set_errno
85# define __set_errno(val) errno = (val)
86#endif
87
88#ifndef NULL
89# define NULL 0
90#endif
91
92
93#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
94# include <dirent.h>
95# define NAMLEN(dirent) strlen((dirent)->d_name)
96#else
97# define dirent direct
98# define NAMLEN(dirent) (dirent)->d_namlen
99# ifdef HAVE_SYS_NDIR_H
100# include <sys/ndir.h>
101# endif
102# ifdef HAVE_SYS_DIR_H
103# include <sys/dir.h>
104# endif
105# ifdef HAVE_NDIR_H
106# include <ndir.h>
107# endif
108# ifdef HAVE_VMSDIR_H
109# include "vmsdir.h"
110# endif /* HAVE_VMSDIR_H */
111#endif
112
113
114/* In GNU systems, <dirent.h> defines this macro for us. */
115#ifdef _D_NAMLEN
116# undef NAMLEN
117# define NAMLEN(d) _D_NAMLEN(d)
118#endif
119
120/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
121 if the `d_type' member for `struct dirent' is available. */
122#ifdef _DIRENT_HAVE_D_TYPE
123# define HAVE_D_TYPE 1
124#endif
125
126
127#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
128/* Posix does not require that the d_ino field be present, and some
129 systems do not provide it. */
130# define REAL_DIR_ENTRY(dp) 1
131#else
132# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
133#endif /* POSIX */
134
135#if defined STDC_HEADERS || defined __GNU_LIBRARY__
136# include <stdlib.h>
137# include <string.h>
138# define ANSI_STRING
139#else /* No standard headers. */
140
141extern char *getenv ();
142
143# ifdef HAVE_STRING_H
144# include <string.h>
145# define ANSI_STRING
146# else
147# include <strings.h>
148# endif
149# ifdef HAVE_MEMORY_H
150# include <memory.h>
151# endif
152
153extern char *malloc (), *realloc ();
154extern void free ();
155
156extern void qsort ();
157extern void abort (), exit ();
158
159#endif /* Standard headers. */
160
161#ifndef ANSI_STRING
162
163# ifndef bzero
164extern void bzero ();
165# endif
166# ifndef bcopy
167extern void bcopy ();
168# endif
169
170# define memcpy(d, s, n) bcopy ((s), (d), (n))
171# define strrchr rindex
172/* memset is only used for zero here, but let's be paranoid. */
173# define memset(s, better_be_zero, n) \
174 ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0)))
175#endif /* Not ANSI_STRING. */
176
177#if !defined HAVE_STRCOLL && !defined _LIBC
178# define strcoll strcmp
179#endif
180
181#if !defined HAVE_MEMPCPY && __GLIBC__ - 0 == 2 && __GLIBC_MINOR__ >= 1
182# define HAVE_MEMPCPY 1
183#if 0 /* bird: This messes with the electric.c heap (linux/amd64). Probably missing prototype, so int return. */
184# undef mempcpy
185# define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len)
186#endif
187#endif
188
189#if !defined __GNU_LIBRARY__ && !defined __DJGPP__ && !defined ELECTRIC_HEAP && !defined __APPLE__ /* bird (last two) */
190# ifdef __GNUC__
191__inline
192# endif
193# ifndef __SASC
194# ifdef WINDOWS32
195# include <malloc.h>
196static void *
197my_realloc (void *p, unsigned int n)
198# else
199static char *
200my_realloc (p, n)
201 char *p;
202 unsigned int n;
203# endif
204{
205 /* These casts are the for sake of the broken Ultrix compiler,
206 which warns of illegal pointer combinations otherwise. */
207 if (p == NULL)
208 return (char *) malloc (n);
209 return (char *) realloc (p, n);
210}
211# define realloc my_realloc
212# endif /* __SASC */
213#endif /* __GNU_LIBRARY__ || __DJGPP__ */
214
215
216#if !defined __alloca /*&& !defined __GNU_LIBRARY__ - bird: unresolved __alloca symbol if skipping this for gnu libc. duh. */
217
218# ifdef __GNUC__
219# undef alloca
220# define alloca(n) __builtin_alloca (n)
221# else /* Not GCC. */
222# ifdef HAVE_ALLOCA_H
223# include <alloca.h>
224# else /* Not HAVE_ALLOCA_H. */
225# ifndef _AIX
226# ifdef WINDOWS32
227# include <malloc.h>
228# else
229extern char *alloca ();
230# endif /* WINDOWS32 */
231# endif /* Not _AIX. */
232# endif /* sparc or HAVE_ALLOCA_H. */
233# endif /* Not GCC. */
234
235# define __alloca alloca
236
237#endif
238
239#if 1 /*bird: sigh. ndef __GNU_LIBRARY__*/
240# define __stat stat
241# ifdef STAT_MACROS_BROKEN
242# undef S_ISDIR
243# endif
244# ifndef S_ISDIR
245# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
246# endif
247#endif
248
249#ifdef _LIBC
250# ifdef KMK
251# error "_LIBC better not be defined!"
252# endif
253# undef strdup
254# define strdup(str) __strdup (str)
255# define sysconf(id) __sysconf (id)
256# define closedir(dir) __closedir (dir)
257# define opendir(name) __opendir (name)
258# define readdir(str) __readdir (str)
259# define getpwnam_r(name, bufp, buf, len, res) \
260 __getpwnam_r (name, bufp, buf, len, res)
261# ifndef __stat
262# define __stat(fname, buf) __xstat (_STAT_VER, fname, buf)
263# endif
264#endif
265
266#if !(defined STDC_HEADERS || defined __GNU_LIBRARY__)
267# undef size_t
268# define size_t unsigned int
269#endif
270
271/* Some system header files erroneously define these.
272 We want our own definitions from <fnmatch.h> to take precedence. */
273#ifndef __GNU_LIBRARY__
274# undef FNM_PATHNAME
275# undef FNM_NOESCAPE
276# undef FNM_PERIOD
277#endif
278#include <fnmatch.h>
279
280/* Some system header files erroneously define these.
281 We want our own definitions from <glob.h> to take precedence. */
282#ifndef __GNU_LIBRARY__
283# undef GLOB_ERR
284# undef GLOB_MARK
285# undef GLOB_NOSORT
286# undef GLOB_DOOFFS
287# undef GLOB_NOCHECK
288# undef GLOB_APPEND
289# undef GLOB_NOESCAPE
290# undef GLOB_PERIOD
291#endif
292#include <glob.h>
293
294#ifdef HAVE_GETLOGIN_R
295extern int getlogin_r __P ((char *, size_t));
296#else
297extern char *getlogin __P ((void));
298#endif
299
300
301static
302#if __GNUC__ - 0 >= 2
303inline
304#endif
305const char *next_brace_sub __P ((const char *begin));
306static int glob_in_dir __P ((const char *pattern, const char *directory,
307 int flags,
308 int (*errfunc) (const char *, int),
309 glob_t *pglob));
310static int prefix_array __P ((const char *prefix, char **array, size_t n));
311static int collated_compare __P ((const __ptr_t, const __ptr_t));
312
313#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
314int __glob_pattern_p __P ((const char *pattern, int quote));
315#endif
316
317/* Find the end of the sub-pattern in a brace expression. We define
318 this as an inline function if the compiler permits. */
319static
320#if __GNUC__ - 0 >= 2
321inline
322#endif
323const char *
324next_brace_sub (begin)
325 const char *begin;
326{
327 unsigned int depth = 0;
328 const char *cp = begin;
329
330 while (1)
331 {
332 if (depth == 0)
333 {
334 if (*cp != ',' && *cp != '}' && *cp != '\0')
335 {
336 if (*cp == '{')
337 ++depth;
338 ++cp;
339 continue;
340 }
341 }
342 else
343 {
344 while (*cp != '\0' && (*cp != '}' || depth > 0))
345 {
346 if (*cp == '}')
347 --depth;
348 ++cp;
349 }
350 if (*cp == '\0')
351 /* An incorrectly terminated brace expression. */
352 return NULL;
353
354 continue;
355 }
356 break;
357 }
358
359 return cp;
360}
361
362/* Do glob searching for PATTERN, placing results in PGLOB.
363 The bits defined above may be set in FLAGS.
364 If a directory cannot be opened or read and ERRFUNC is not nil,
365 it is called with the pathname that caused the error, and the
366 `errno' value from the failing call; if it returns non-zero
367 `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
368 If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
369 Otherwise, `glob' returns zero. */
370int
371glob (pattern, flags, errfunc, pglob)
372 const char *pattern;
373 int flags;
374 int (*errfunc) __P ((const char *, int));
375 glob_t *pglob;
376{
377 const char *filename;
378 const char *dirname;
379 size_t dirlen;
380 int status;
381 __size_t oldcount; /* bird: correct type. */
382
383 if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
384 {
385 __set_errno (EINVAL);
386 return -1;
387 }
388
389 /* POSIX requires all slashes to be matched. This means that with
390 a trailing slash we must match only directories. */
391 if (pattern[0] && pattern[strlen (pattern) - 1] == '/')
392 flags |= GLOB_ONLYDIR;
393
394 if (flags & GLOB_BRACE)
395 {
396 const char *begin = strchr (pattern, '{');
397 if (begin != NULL)
398 {
399 /* Allocate working buffer large enough for our work. Note that
400 we have at least an opening and closing brace. */
401 size_t firstc; /* bird: correct type. */
402 char *alt_start;
403 const char *p;
404 const char *next;
405 const char *rest;
406 size_t rest_len;
407#ifdef __GNUC__
408 char onealt[strlen (pattern) - 1];
409#else
410 char *onealt = (char *) malloc (strlen (pattern) - 1);
411 if (onealt == NULL)
412 {
413 if (!(flags & GLOB_APPEND))
414 globfree (pglob);
415 return GLOB_NOSPACE;
416 }
417#endif
418
419 /* We know the prefix for all sub-patterns. */
420#ifdef HAVE_MEMPCPY
421 alt_start = mempcpy (onealt, pattern, begin - pattern);
422#else
423 memcpy (onealt, pattern, begin - pattern);
424 alt_start = &onealt[begin - pattern];
425#endif
426
427 /* Find the first sub-pattern and at the same time find the
428 rest after the closing brace. */
429 next = next_brace_sub (begin + 1);
430 if (next == NULL)
431 {
432 /* It is an illegal expression. */
433#ifndef __GNUC__
434 free (onealt);
435#endif
436 return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
437 }
438
439 /* Now find the end of the whole brace expression. */
440 rest = next;
441 while (*rest != '}')
442 {
443 rest = next_brace_sub (rest + 1);
444 if (rest == NULL)
445 {
446 /* It is an illegal expression. */
447#ifndef __GNUC__
448 free (onealt);
449#endif
450 return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
451 }
452 }
453 /* Please note that we now can be sure the brace expression
454 is well-formed. */
455 rest_len = strlen (++rest) + 1;
456
457 /* We have a brace expression. BEGIN points to the opening {,
458 NEXT points past the terminator of the first element, and END
459 points past the final }. We will accumulate result names from
460 recursive runs for each brace alternative in the buffer using
461 GLOB_APPEND. */
462
463 if (!(flags & GLOB_APPEND))
464 {
465 /* This call is to set a new vector, so clear out the
466 vector so we can append to it. */
467 pglob->gl_pathc = 0;
468 pglob->gl_pathv = NULL;
469 }
470 firstc = pglob->gl_pathc;
471
472 p = begin + 1;
473 while (1)
474 {
475 int result;
476
477 /* Construct the new glob expression. */
478#ifdef HAVE_MEMPCPY
479 mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
480#else
481 memcpy (alt_start, p, next - p);
482 memcpy (&alt_start[next - p], rest, rest_len);
483#endif
484
485 result = glob (onealt,
486 ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC))
487 | GLOB_APPEND), errfunc, pglob);
488
489 /* If we got an error, return it. */
490 if (result && result != GLOB_NOMATCH)
491 {
492#ifndef __GNUC__
493 free (onealt);
494#endif
495 if (!(flags & GLOB_APPEND))
496 globfree (pglob);
497 return result;
498 }
499
500 if (*next == '}')
501 /* We saw the last entry. */
502 break;
503
504 p = next + 1;
505 next = next_brace_sub (p);
506 assert (next != NULL);
507 }
508
509#ifndef __GNUC__
510 free (onealt);
511#endif
512
513 if (pglob->gl_pathc != firstc)
514 /* We found some entries. */
515 return 0;
516 else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
517 return GLOB_NOMATCH;
518 }
519 }
520
521 /* Find the filename. */
522 filename = strrchr (pattern, '/');
523#if defined __MSDOS__ || defined WINDOWS32
524 /* The case of "d:pattern". Since `:' is not allowed in
525 file names, we can safely assume that wherever it
526 happens in pattern, it signals the filename part. This
527 is so we could some day support patterns like "[a-z]:foo". */
528 if (filename == NULL)
529 filename = strchr (pattern, ':');
530#endif /* __MSDOS__ || WINDOWS32 */
531 if (filename == NULL)
532 {
533 /* This can mean two things: a simple name or "~name". The later
534 case is nothing but a notation for a directory. */
535 if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
536 {
537 dirname = pattern;
538 dirlen = strlen (pattern);
539
540 /* Set FILENAME to NULL as a special flag. This is ugly but
541 other solutions would require much more code. We test for
542 this special case below. */
543 filename = NULL;
544 }
545 else
546 {
547 filename = pattern;
548#ifdef _AMIGA
549 dirname = "";
550#else
551 dirname = ".";
552#endif
553 dirlen = 0;
554 }
555 }
556 else if (filename == pattern)
557 {
558 /* "/pattern". */
559 dirname = "/";
560 dirlen = 1;
561 ++filename;
562 }
563 else
564 {
565 char *newp;
566 dirlen = filename - pattern;
567#if defined __MSDOS__ || defined WINDOWS32
568 if (*filename == ':'
569 || (filename > pattern + 1 && filename[-1] == ':'))
570 {
571 char *drive_spec;
572
573 ++dirlen;
574 drive_spec = (char *) __alloca (dirlen + 1);
575#ifdef HAVE_MEMPCPY
576 *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
577#else
578 memcpy (drive_spec, pattern, dirlen);
579 drive_spec[dirlen] = '\0';
580#endif
581 /* For now, disallow wildcards in the drive spec, to
582 prevent infinite recursion in glob. */
583 if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
584 return GLOB_NOMATCH;
585 /* If this is "d:pattern", we need to copy `:' to DIRNAME
586 as well. If it's "d:/pattern", don't remove the slash
587 from "d:/", since "d:" and "d:/" are not the same.*/
588 }
589#endif
590 newp = (char *) __alloca (dirlen + 1);
591#ifdef HAVE_MEMPCPY
592 *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
593#else
594 memcpy (newp, pattern, dirlen);
595 newp[dirlen] = '\0';
596#endif
597 dirname = newp;
598 ++filename;
599
600 if (filename[0] == '\0'
601#if defined __MSDOS__ || defined WINDOWS32
602 && dirname[dirlen - 1] != ':'
603 && (dirlen < 3 || dirname[dirlen - 2] != ':'
604 || dirname[dirlen - 1] != '/')
605#endif
606 && dirlen > 1)
607 /* "pattern/". Expand "pattern", appending slashes. */
608 {
609 int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
610 if (val == 0)
611 pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
612 | (flags & GLOB_MARK));
613 return val;
614 }
615 }
616
617 if (!(flags & GLOB_APPEND))
618 {
619 pglob->gl_pathc = 0;
620 pglob->gl_pathv = NULL;
621 }
622
623 oldcount = pglob->gl_pathc;
624
625#ifndef VMS
626 if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
627 {
628 if (dirname[1] == '\0' || dirname[1] == '/')
629 {
630 /* Look up home directory. */
631#ifdef VMS
632/* This isn't obvious, RTLs of DECC and VAXC know about "HOME" */
633 const char *home_dir = getenv ("SYS$LOGIN");
634#else
635 const char *home_dir = getenv ("HOME");
636#endif
637# ifdef _AMIGA
638 if (home_dir == NULL || home_dir[0] == '\0')
639 home_dir = "SYS:";
640# else
641# ifdef WINDOWS32
642 if (home_dir == NULL || home_dir[0] == '\0')
643 home_dir = "c:/users/default"; /* poor default */
644# else
645# ifdef VMS
646/* Again, this isn't obvious, if "HOME" isn't known "SYS$LOGIN" should be set */
647 if (home_dir == NULL || home_dir[0] == '\0')
648 home_dir = "SYS$DISK:[]";
649# else
650 if (home_dir == NULL || home_dir[0] == '\0')
651 {
652 int success;
653 char *name;
654# if defined HAVE_GETLOGIN_R || defined _LIBC
655 size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;
656
657 if (buflen == 0)
658 /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try
659 a moderate value. */
660 buflen = 20;
661 name = (char *) __alloca (buflen);
662
663 success = getlogin_r (name, buflen) >= 0;
664# else
665 success = (name = getlogin ()) != NULL;
666# endif
667 if (success)
668 {
669 struct passwd *p;
670# if defined HAVE_GETPWNAM_R || defined _LIBC
671 size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
672 char *pwtmpbuf;
673 struct passwd pwbuf;
674 int save = errno;
675
676 if (pwbuflen == -1)
677 /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
678 Try a moderate value. */
679 pwbuflen = 1024;
680 pwtmpbuf = (char *) __alloca (pwbuflen);
681
682 while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
683 != 0)
684 {
685 if (errno != ERANGE)
686 {
687 p = NULL;
688 break;
689 }
690 pwbuflen *= 2;
691 pwtmpbuf = (char *) __alloca (pwbuflen);
692 __set_errno (save);
693 }
694# else
695 p = getpwnam (name);
696# endif
697 if (p != NULL)
698 home_dir = p->pw_dir;
699 }
700 }
701 if (home_dir == NULL || home_dir[0] == '\0')
702 {
703 if (flags & GLOB_TILDE_CHECK)
704 return GLOB_NOMATCH;
705 else
706 home_dir = "~"; /* No luck. */
707 }
708# endif /* VMS */
709# endif /* WINDOWS32 */
710# endif
711 /* Now construct the full directory. */
712 if (dirname[1] == '\0')
713 dirname = home_dir;
714 else
715 {
716 char *newp;
717 size_t home_len = strlen (home_dir);
718 newp = (char *) __alloca (home_len + dirlen);
719# ifdef HAVE_MEMPCPY
720 mempcpy (mempcpy (newp, home_dir, home_len),
721 &dirname[1], dirlen);
722# else
723 memcpy (newp, home_dir, home_len);
724 memcpy (&newp[home_len], &dirname[1], dirlen);
725# endif
726 dirname = newp;
727 }
728 }
729# if !defined _AMIGA && !defined WINDOWS32 && !defined VMS
730 else
731 {
732 char *end_name = strchr (dirname, '/');
733 const char *user_name;
734 const char *home_dir;
735
736 if (end_name == NULL)
737 user_name = dirname + 1;
738 else
739 {
740 char *newp;
741 newp = (char *) __alloca (end_name - dirname);
742# ifdef HAVE_MEMPCPY
743 *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
744 = '\0';
745# else
746 memcpy (newp, dirname + 1, end_name - dirname);
747 newp[end_name - dirname - 1] = '\0';
748# endif
749 user_name = newp;
750 }
751
752 /* Look up specific user's home directory. */
753 {
754 struct passwd *p;
755# if defined HAVE_GETPWNAM_R || defined _LIBC
756 size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
757 char *pwtmpbuf;
758 struct passwd pwbuf;
759 int save = errno;
760
761 if (buflen == -1)
762 /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a
763 moderate value. */
764 buflen = 1024;
765 pwtmpbuf = (char *) __alloca (buflen);
766
767 while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
768 {
769 if (errno != ERANGE)
770 {
771 p = NULL;
772 break;
773 }
774 buflen *= 2;
775 pwtmpbuf = __alloca (buflen);
776 __set_errno (save);
777 }
778# else
779 p = getpwnam (user_name);
780# endif
781 if (p != NULL)
782 home_dir = p->pw_dir;
783 else
784 home_dir = NULL;
785 }
786 /* If we found a home directory use this. */
787 if (home_dir != NULL)
788 {
789 char *newp;
790 size_t home_len = strlen (home_dir);
791 size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
792 newp = (char *) __alloca (home_len + rest_len + 1);
793# ifdef HAVE_MEMPCPY
794 *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
795 end_name, rest_len)) = '\0';
796# else
797 memcpy (newp, home_dir, home_len);
798 memcpy (&newp[home_len], end_name, rest_len);
799 newp[home_len + rest_len] = '\0';
800# endif
801 dirname = newp;
802 }
803 else
804 if (flags & GLOB_TILDE_CHECK)
805 /* We have to regard it as an error if we cannot find the
806 home directory. */
807 return GLOB_NOMATCH;
808 }
809# endif /* Not Amiga && not WINDOWS32 && not VMS. */
810 }
811#endif /* Not VMS. */
812
813 /* Now test whether we looked for "~" or "~NAME". In this case we
814 can give the answer now. */
815 if (filename == NULL)
816 {
817 struct stat st;
818
819 /* Return the directory if we don't check for error or if it exists. */
820 if ((flags & GLOB_NOCHECK)
821#ifdef KMK
822 || (flags & GLOB_ALTDIRFUNC
823 ? (*pglob->gl_isdir) (dirname)
824 : __stat (dirname, &st) == 0 && S_ISDIR (st.st_mode))
825#else
826 || (((flags & GLOB_ALTDIRFUNC)
827 ? (*pglob->gl_stat) (dirname, &st)
828 : __stat (dirname, &st)) == 0
829 && S_ISDIR (st.st_mode))
830#endif
831 )
832 {
833 pglob->gl_pathv
834 = (char **) realloc (pglob->gl_pathv,
835 (pglob->gl_pathc +
836 ((flags & GLOB_DOOFFS) ?
837 pglob->gl_offs : 0) +
838 1 + 1) *
839 sizeof (char *));
840 if (pglob->gl_pathv == NULL)
841 return GLOB_NOSPACE;
842
843 if (flags & GLOB_DOOFFS)
844 while (pglob->gl_pathc < pglob->gl_offs)
845 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
846
847#if defined HAVE_STRDUP || defined _LIBC
848 pglob->gl_pathv[pglob->gl_pathc] = strdup (dirname);
849#else
850 {
851 size_t len = strlen (dirname) + 1;
852 char *dircopy = malloc (len);
853 if (dircopy != NULL)
854 pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname,
855 len);
856 }
857#endif
858 if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
859 {
860 free (pglob->gl_pathv);
861 return GLOB_NOSPACE;
862 }
863 pglob->gl_pathv[++pglob->gl_pathc] = NULL;
864 pglob->gl_flags = flags;
865
866 return 0;
867 }
868
869 /* Not found. */
870 return GLOB_NOMATCH;
871 }
872
873 if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
874 {
875 /* The directory name contains metacharacters, so we
876 have to glob for the directory, and then glob for
877 the pattern in each directory found. */
878 glob_t dirs;
879 register __size_t i; /* bird: correct type. */
880
881 status = glob (dirname,
882 ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE))
883 | GLOB_NOSORT | GLOB_ONLYDIR),
884 errfunc, &dirs);
885 if (status != 0)
886 return status;
887
888 /* We have successfully globbed the preceding directory name.
889 For each name we found, call glob_in_dir on it and FILENAME,
890 appending the results to PGLOB. */
891 for (i = 0; i < dirs.gl_pathc; ++i)
892 {
893 int old_pathc;
894
895#ifdef SHELL
896 {
897 /* Make globbing interruptible in the bash shell. */
898 extern int interrupt_state;
899
900 if (interrupt_state)
901 {
902 globfree (&dirs);
903 globfree (&files);
904 return GLOB_ABORTED;
905 }
906 }
907#endif /* SHELL. */
908
909 old_pathc = pglob->gl_pathc;
910 status = glob_in_dir (filename, dirs.gl_pathv[i],
911 ((flags | GLOB_APPEND)
912 & ~(GLOB_NOCHECK | GLOB_ERR)),
913 errfunc, pglob);
914 if (status == GLOB_NOMATCH)
915 /* No matches in this directory. Try the next. */
916 continue;
917
918 if (status != 0)
919 {
920 globfree (&dirs);
921 globfree (pglob);
922 return status;
923 }
924
925 /* Stick the directory on the front of each name. */
926 if (prefix_array (dirs.gl_pathv[i],
927 &pglob->gl_pathv[old_pathc],
928 pglob->gl_pathc - old_pathc))
929 {
930 globfree (&dirs);
931 globfree (pglob);
932 return GLOB_NOSPACE;
933 }
934 }
935
936 flags |= GLOB_MAGCHAR;
937
938 /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
939 But if we have not found any matching entry and thie GLOB_NOCHECK
940 flag was set we must return the list consisting of the disrectory
941 names followed by the filename. */
942 if (pglob->gl_pathc == oldcount)
943 {
944 /* No matches. */
945 if (flags & GLOB_NOCHECK)
946 {
947 size_t filename_len = strlen (filename) + 1;
948 char **new_pathv;
949 struct stat st;
950
951 /* This is an pessimistic guess about the size. */
952 pglob->gl_pathv
953 = (char **) realloc (pglob->gl_pathv,
954 (pglob->gl_pathc +
955 ((flags & GLOB_DOOFFS) ?
956 pglob->gl_offs : 0) +
957 dirs.gl_pathc + 1) *
958 sizeof (char *));
959 if (pglob->gl_pathv == NULL)
960 {
961 globfree (&dirs);
962 return GLOB_NOSPACE;
963 }
964
965 if (flags & GLOB_DOOFFS)
966 while (pglob->gl_pathc < pglob->gl_offs)
967 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
968
969 for (i = 0; i < dirs.gl_pathc; ++i)
970 {
971 const char *dir = dirs.gl_pathv[i];
972 size_t dir_len = strlen (dir);
973
974 /* First check whether this really is a directory. */
975#ifdef KMK
976 if (flags & GLOB_ALTDIRFUNC
977 ? !pglob->gl_isdir (dir)
978 : __stat (dir, &st) != 0 || !S_ISDIR (st.st_mode))
979#else
980 if (((flags & GLOB_ALTDIRFUNC)
981 ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0
982 || !S_ISDIR (st.st_mode))
983#endif
984 /* No directory, ignore this entry. */
985 continue;
986
987 pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1
988 + filename_len);
989 if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
990 {
991 globfree (&dirs);
992 globfree (pglob);
993 return GLOB_NOSPACE;
994 }
995
996#ifdef HAVE_MEMPCPY
997 mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc],
998 dir, dir_len),
999 "/", 1),
1000 filename, filename_len);
1001#else
1002 memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len);
1003 pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/';
1004 memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1],
1005 filename, filename_len);
1006#endif
1007 ++pglob->gl_pathc;
1008 }
1009
1010 pglob->gl_pathv[pglob->gl_pathc] = NULL;
1011 pglob->gl_flags = flags;
1012
1013 /* Now we know how large the gl_pathv vector must be. */
1014 new_pathv = (char **) realloc (pglob->gl_pathv,
1015 ((pglob->gl_pathc + 1)
1016 * sizeof (char *)));
1017 if (new_pathv != NULL)
1018 pglob->gl_pathv = new_pathv;
1019 }
1020 else
1021 return GLOB_NOMATCH;
1022 }
1023
1024 globfree (&dirs);
1025 }
1026 else
1027 {
1028 status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
1029 if (status != 0)
1030 return status;
1031
1032 if (dirlen > 0)
1033 {
1034 /* Stick the directory on the front of each name. */
1035 __size_t ignore = oldcount; /* bird: correct type. */
1036
1037 if ((flags & GLOB_DOOFFS) && ignore < pglob->gl_offs)
1038 ignore = pglob->gl_offs;
1039
1040 if (prefix_array (dirname,
1041 &pglob->gl_pathv[ignore],
1042 pglob->gl_pathc - ignore))
1043 {
1044 globfree (pglob);
1045 return GLOB_NOSPACE;
1046 }
1047 }
1048 }
1049
1050 if (flags & GLOB_MARK)
1051 {
1052 /* Append slashes to directory names. */
1053 __size_t i; /* bird: correct type. */
1054 struct stat st;
1055 for (i = oldcount; i < pglob->gl_pathc; ++i)
1056#ifdef KMK
1057 if (flags & GLOB_ALTDIRFUNC
1058 ? pglob->gl_isdir (pglob->gl_pathv[i])
1059 : __stat (pglob->gl_pathv[i], &st) == 0 && S_ISDIR (st.st_mode) )
1060#else
1061 if (((flags & GLOB_ALTDIRFUNC)
1062 ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st)
1063 : __stat (pglob->gl_pathv[i], &st)) == 0
1064 && S_ISDIR (st.st_mode))
1065#endif
1066 {
1067 size_t len = strlen (pglob->gl_pathv[i]) + 2;
1068 char *new = realloc (pglob->gl_pathv[i], len);
1069 if (new == NULL)
1070 {
1071 globfree (pglob);
1072 return GLOB_NOSPACE;
1073 }
1074 strcpy (&new[len - 2], "/");
1075 pglob->gl_pathv[i] = new;
1076 }
1077 }
1078
1079 if (!(flags & GLOB_NOSORT))
1080 {
1081 /* Sort the vector. */
1082 int non_sort = oldcount;
1083
1084 if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount)
1085 non_sort = pglob->gl_offs;
1086
1087 qsort ((__ptr_t) &pglob->gl_pathv[non_sort],
1088 pglob->gl_pathc - non_sort,
1089 sizeof (char *), collated_compare);
1090 }
1091
1092 return 0;
1093}
1094
1095
1096/* Free storage allocated in PGLOB by a previous `glob' call. */
1097void
1098globfree (pglob)
1099 register glob_t *pglob;
1100{
1101 if (pglob->gl_pathv != NULL)
1102 {
1103 register __size_t i; /* bird: correct type */
1104 for (i = 0; i < pglob->gl_pathc; ++i)
1105 if (pglob->gl_pathv[i] != NULL)
1106 free ((__ptr_t) pglob->gl_pathv[i]);
1107 free ((__ptr_t) pglob->gl_pathv);
1108 }
1109}
1110
1111
1112/* Do a collated comparison of A and B. */
1113static int
1114collated_compare (a, b)
1115 const __ptr_t a;
1116 const __ptr_t b;
1117{
1118 const char *const s1 = *(const char *const * const) a;
1119 const char *const s2 = *(const char *const * const) b;
1120
1121 if (s1 == s2)
1122 return 0;
1123 if (s1 == NULL)
1124 return 1;
1125 if (s2 == NULL)
1126 return -1;
1127 return strcoll (s1, s2);
1128}
1129
1130
1131/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
1132 elements in place. Return nonzero if out of memory, zero if successful.
1133 A slash is inserted between DIRNAME and each elt of ARRAY,
1134 unless DIRNAME is just "/". Each old element of ARRAY is freed. */
1135static int
1136prefix_array (dirname, array, n)
1137 const char *dirname;
1138 char **array;
1139 size_t n;
1140{
1141 register size_t i;
1142 size_t dirlen = strlen (dirname);
1143#if defined __MSDOS__ || defined WINDOWS32
1144 int sep_char = '/';
1145# define DIRSEP_CHAR sep_char
1146#else
1147# define DIRSEP_CHAR '/'
1148#endif
1149
1150 if (dirlen == 1 && dirname[0] == '/')
1151 /* DIRNAME is just "/", so normal prepending would get us "//foo".
1152 We want "/foo" instead, so don't prepend any chars from DIRNAME. */
1153 dirlen = 0;
1154#if defined __MSDOS__ || defined WINDOWS32
1155 else if (dirlen > 1)
1156 {
1157 if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
1158 /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */
1159 --dirlen;
1160 else if (dirname[dirlen - 1] == ':')
1161 {
1162 /* DIRNAME is "d:". Use `:' instead of `/'. */
1163 --dirlen;
1164 sep_char = ':';
1165 }
1166 }
1167#endif
1168
1169 for (i = 0; i < n; ++i)
1170 {
1171 size_t eltlen = strlen (array[i]) + 1;
1172 char *new = (char *) malloc (dirlen + 1 + eltlen);
1173 if (new == NULL)
1174 {
1175 while (i > 0)
1176 free ((__ptr_t) array[--i]);
1177 return 1;
1178 }
1179
1180#ifdef HAVE_MEMPCPY
1181 {
1182 char *endp = (char *) mempcpy (new, dirname, dirlen);
1183 *endp++ = DIRSEP_CHAR;
1184 mempcpy (endp, array[i], eltlen);
1185 }
1186#else
1187 memcpy (new, dirname, dirlen);
1188 new[dirlen] = DIRSEP_CHAR;
1189 memcpy (&new[dirlen + 1], array[i], eltlen);
1190#endif
1191 free ((__ptr_t) array[i]);
1192 array[i] = new;
1193 }
1194
1195 return 0;
1196}
1197
1198
1199/* We must not compile this function twice. */
1200#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
1201/* Return nonzero if PATTERN contains any metacharacters.
1202 Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
1203int
1204__glob_pattern_p (pattern, quote)
1205 const char *pattern;
1206 int quote;
1207{
1208 register const char *p;
1209 int open = 0;
1210
1211 for (p = pattern; *p != '\0'; ++p)
1212 switch (*p)
1213 {
1214 case '?':
1215 case '*':
1216 return 1;
1217
1218 case '\\':
1219 if (quote && p[1] != '\0')
1220 ++p;
1221 break;
1222
1223 case '[':
1224 open = 1;
1225 break;
1226
1227 case ']':
1228 if (open)
1229 return 1;
1230 break;
1231 }
1232
1233 return 0;
1234}
1235# ifdef _LIBC
1236weak_alias (__glob_pattern_p, glob_pattern_p)
1237# endif
1238#endif
1239
1240
1241/* Like `glob', but PATTERN is a final pathname component,
1242 and matches are searched for in DIRECTORY.
1243 The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
1244 The GLOB_APPEND flag is assumed to be set (always appends). */
1245static int
1246glob_in_dir (pattern, directory, flags, errfunc, pglob)
1247 const char *pattern;
1248 const char *directory;
1249 int flags;
1250 int (*errfunc) __P ((const char *, int));
1251 glob_t *pglob;
1252{
1253 __ptr_t stream = NULL;
1254
1255 struct globlink
1256 {
1257 struct globlink *next;
1258 char *name;
1259 };
1260 struct globlink *names = NULL;
1261 size_t nfound;
1262 int meta;
1263 int save;
1264
1265#ifdef VMS
1266 if (*directory == 0)
1267 directory = "[]";
1268#endif
1269 meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
1270 if (meta == 0)
1271 {
1272 if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))
1273 /* We need not do any tests. The PATTERN contains no meta
1274 characters and we must not return an error therefore the
1275 result will always contain exactly one name. */
1276 flags |= GLOB_NOCHECK;
1277 else
1278 {
1279 /* Since we use the normal file functions we can also use stat()
1280 to verify the file is there. */
1281 struct stat st;
1282 size_t patlen = strlen (pattern);
1283 size_t dirlen = strlen (directory);
1284 char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
1285
1286# ifdef HAVE_MEMPCPY
1287 mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
1288 "/", 1),
1289 pattern, patlen + 1);
1290# else
1291 memcpy (fullname, directory, dirlen);
1292 fullname[dirlen] = '/';
1293 memcpy (&fullname[dirlen + 1], pattern, patlen + 1);
1294# endif
1295# ifdef KMK
1296 if (flags & GLOB_ALTDIRFUNC ? pglob->gl_exists (fullname) : __stat (fullname, &st) == 0)
1297# else
1298 if (((flags & GLOB_ALTDIRFUNC)
1299 ? (*pglob->gl_stat) (fullname, &st)
1300 : __stat (fullname, &st)) == 0)
1301# endif
1302 /* We found this file to be existing. Now tell the rest
1303 of the function to copy this name into the result. */
1304 flags |= GLOB_NOCHECK;
1305 }
1306
1307 nfound = 0;
1308 }
1309 else
1310 {
1311 if (pattern[0] == '\0')
1312 {
1313 /* This is a special case for matching directories like in
1314 "*a/". */
1315 names = (struct globlink *) __alloca (sizeof (struct globlink));
1316 names->name = (char *) malloc (1);
1317 if (names->name == NULL)
1318 goto memory_error;
1319 names->name[0] = '\0';
1320 names->next = NULL;
1321 nfound = 1;
1322 meta = 0;
1323 }
1324 else
1325 {
1326 stream = ((flags & GLOB_ALTDIRFUNC)
1327 ? (*pglob->gl_opendir) (directory)
1328 : (__ptr_t) opendir (directory));
1329 if (stream == NULL)
1330 {
1331 if (errno != ENOTDIR
1332 && ((errfunc != NULL && (*errfunc) (directory, errno))
1333 || (flags & GLOB_ERR)))
1334 return GLOB_ABORTED;
1335 nfound = 0;
1336 meta = 0;
1337 }
1338 else
1339 {
1340 int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
1341 | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
1342#if defined HAVE_CASE_INSENSITIVE_FS
1343 | FNM_CASEFOLD
1344#endif
1345 );
1346 nfound = 0;
1347 flags |= GLOB_MAGCHAR;
1348
1349 while (1)
1350 {
1351 const char *name;
1352 size_t len;
1353 struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
1354 ? (*pglob->gl_readdir) (stream)
1355 : readdir ((DIR *) stream));
1356 if (d == NULL)
1357 break;
1358 if (! REAL_DIR_ENTRY (d))
1359 continue;
1360
1361#ifdef HAVE_D_TYPE
1362 /* If we shall match only directories use the information
1363 provided by the dirent call if possible. */
1364 if ((flags & GLOB_ONLYDIR)
1365 && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
1366 continue;
1367#endif
1368
1369 name = d->d_name;
1370
1371 if (fnmatch (pattern, name, fnm_flags) == 0)
1372 {
1373 struct globlink *new = (struct globlink *)
1374 __alloca (sizeof (struct globlink));
1375 len = NAMLEN (d);
1376 new->name = (char *) malloc (len + 1);
1377 if (new->name == NULL)
1378 goto memory_error;
1379#ifdef HAVE_MEMPCPY
1380 *((char *) mempcpy ((__ptr_t) new->name, name, len))
1381 = '\0';
1382#else
1383 memcpy ((__ptr_t) new->name, name, len);
1384 new->name[len] = '\0';
1385#endif
1386 new->next = names;
1387 names = new;
1388 ++nfound;
1389 }
1390 }
1391 }
1392 }
1393 }
1394
1395 if (nfound == 0 && (flags & GLOB_NOCHECK))
1396 {
1397 size_t len = strlen (pattern);
1398 nfound = 1;
1399 names = (struct globlink *) __alloca (sizeof (struct globlink));
1400 names->next = NULL;
1401 names->name = (char *) malloc (len + 1);
1402 if (names->name == NULL)
1403 goto memory_error;
1404#ifdef HAVE_MEMPCPY
1405 *((char *) mempcpy (names->name, pattern, len)) = '\0';
1406#else
1407 memcpy (names->name, pattern, len);
1408 names->name[len] = '\0';
1409#endif
1410 }
1411
1412 if (nfound != 0)
1413 {
1414 pglob->gl_pathv
1415 = (char **) realloc (pglob->gl_pathv,
1416 (pglob->gl_pathc +
1417 ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
1418 nfound + 1) *
1419 sizeof (char *));
1420 if (pglob->gl_pathv == NULL)
1421 goto memory_error;
1422
1423 if (flags & GLOB_DOOFFS)
1424 while (pglob->gl_pathc < pglob->gl_offs)
1425 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
1426
1427 for (; names != NULL; names = names->next)
1428 pglob->gl_pathv[pglob->gl_pathc++] = names->name;
1429 pglob->gl_pathv[pglob->gl_pathc] = NULL;
1430
1431 pglob->gl_flags = flags;
1432 }
1433
1434 save = errno;
1435 if (stream != NULL)
1436 {
1437 if (flags & GLOB_ALTDIRFUNC)
1438 (*pglob->gl_closedir) (stream);
1439 else
1440 closedir ((DIR *) stream);
1441 }
1442 __set_errno (save);
1443
1444 return nfound == 0 ? GLOB_NOMATCH : 0;
1445
1446 memory_error:
1447 {
1448 /*int*/ save = errno;
1449 if (flags & GLOB_ALTDIRFUNC)
1450 (*pglob->gl_closedir) (stream);
1451 else
1452 closedir ((DIR *) stream);
1453 __set_errno (save);
1454 }
1455 while (names != NULL)
1456 {
1457 if (names->name != NULL)
1458 free ((__ptr_t) names->name);
1459 names = names->next;
1460 }
1461 return GLOB_NOSPACE;
1462}
1463
1464#endif /* Not ELIDE_CODE. */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette