VirtualBox

source: kBuild/trunk/src/gmake/glob/glob.c@ 507

Last change on this file since 507 was 507, checked in by bird, 18 years ago

Fixed MSC warnings.

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