VirtualBox

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

Last change on this file since 2016 was 2001, checked in by bird, 16 years ago

kmk: pedantic warnings.

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