VirtualBox

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

Last change on this file since 2634 was 2591, checked in by bird, 13 years ago

kmk: Merged in changes from GNU make 3.82. Previous GNU make base version was gnumake-2008-10-28-CVS.

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

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