VirtualBox

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

Last change on this file since 2989 was 2702, checked in by bird, 11 years ago

kmk/WindowsNT: Avoiding unnecessary stat() calls. Reimplemented stat(), lstat(), fstat(), opendir(), readdir(), and closedir() using native NT APIs.

  • Property svn:eol-style set to native
File size: 35.7 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#ifdef KMK
810 || (flags & GLOB_ALTDIRFUNC
811 ? (*pglob->gl_isdir) (dirname)
812 : __stat (dirname, &st) == 0 && S_ISDIR (st.st_mode))
813#else
814 || (((flags & GLOB_ALTDIRFUNC)
815 ? (*pglob->gl_stat) (dirname, &st)
816 : __stat (dirname, &st)) == 0
817 && S_ISDIR (st.st_mode))
818#endif
819 )
820 {
821 pglob->gl_pathv
822 = (char **) realloc (pglob->gl_pathv,
823 (pglob->gl_pathc +
824 ((flags & GLOB_DOOFFS) ?
825 pglob->gl_offs : 0) +
826 1 + 1) *
827 sizeof (char *));
828 if (pglob->gl_pathv == NULL)
829 return GLOB_NOSPACE;
830
831 if (flags & GLOB_DOOFFS)
832 while (pglob->gl_pathc < pglob->gl_offs)
833 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
834
835#if defined HAVE_STRDUP || defined _LIBC
836 pglob->gl_pathv[pglob->gl_pathc] = strdup (dirname);
837#else
838 {
839 size_t len = strlen (dirname) + 1;
840 char *dircopy = malloc (len);
841 if (dircopy != NULL)
842 pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname,
843 len);
844 }
845#endif
846 if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
847 {
848 free (pglob->gl_pathv);
849 return GLOB_NOSPACE;
850 }
851 pglob->gl_pathv[++pglob->gl_pathc] = NULL;
852 pglob->gl_flags = flags;
853
854 return 0;
855 }
856
857 /* Not found. */
858 return GLOB_NOMATCH;
859 }
860
861 if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
862 {
863 /* The directory name contains metacharacters, so we
864 have to glob for the directory, and then glob for
865 the pattern in each directory found. */
866 glob_t dirs;
867 register __size_t i; /* bird: correct type. */
868
869 status = glob (dirname,
870 ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE))
871 | GLOB_NOSORT | GLOB_ONLYDIR),
872 errfunc, &dirs);
873 if (status != 0)
874 return status;
875
876 /* We have successfully globbed the preceding directory name.
877 For each name we found, call glob_in_dir on it and FILENAME,
878 appending the results to PGLOB. */
879 for (i = 0; i < dirs.gl_pathc; ++i)
880 {
881 int old_pathc;
882
883#ifdef SHELL
884 {
885 /* Make globbing interruptible in the bash shell. */
886 extern int interrupt_state;
887
888 if (interrupt_state)
889 {
890 globfree (&dirs);
891 globfree (&files);
892 return GLOB_ABORTED;
893 }
894 }
895#endif /* SHELL. */
896
897 old_pathc = pglob->gl_pathc;
898 status = glob_in_dir (filename, dirs.gl_pathv[i],
899 ((flags | GLOB_APPEND)
900 & ~(GLOB_NOCHECK | GLOB_ERR)),
901 errfunc, pglob);
902 if (status == GLOB_NOMATCH)
903 /* No matches in this directory. Try the next. */
904 continue;
905
906 if (status != 0)
907 {
908 globfree (&dirs);
909 globfree (pglob);
910 return status;
911 }
912
913 /* Stick the directory on the front of each name. */
914 if (prefix_array (dirs.gl_pathv[i],
915 &pglob->gl_pathv[old_pathc],
916 pglob->gl_pathc - old_pathc))
917 {
918 globfree (&dirs);
919 globfree (pglob);
920 return GLOB_NOSPACE;
921 }
922 }
923
924 flags |= GLOB_MAGCHAR;
925
926 /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
927 But if we have not found any matching entry and thie GLOB_NOCHECK
928 flag was set we must return the list consisting of the disrectory
929 names followed by the filename. */
930 if (pglob->gl_pathc == oldcount)
931 {
932 /* No matches. */
933 if (flags & GLOB_NOCHECK)
934 {
935 size_t filename_len = strlen (filename) + 1;
936 char **new_pathv;
937 struct stat st;
938
939 /* This is an pessimistic guess about the size. */
940 pglob->gl_pathv
941 = (char **) realloc (pglob->gl_pathv,
942 (pglob->gl_pathc +
943 ((flags & GLOB_DOOFFS) ?
944 pglob->gl_offs : 0) +
945 dirs.gl_pathc + 1) *
946 sizeof (char *));
947 if (pglob->gl_pathv == NULL)
948 {
949 globfree (&dirs);
950 return GLOB_NOSPACE;
951 }
952
953 if (flags & GLOB_DOOFFS)
954 while (pglob->gl_pathc < pglob->gl_offs)
955 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
956
957 for (i = 0; i < dirs.gl_pathc; ++i)
958 {
959 const char *dir = dirs.gl_pathv[i];
960 size_t dir_len = strlen (dir);
961
962 /* First check whether this really is a directory. */
963#ifdef KMK
964 if (flags & GLOB_ALTDIRFUNC
965 ? !pglob->gl_isdir (dir)
966 : __stat (dir, &st) != 0 || !S_ISDIR (st.st_mode))
967#else
968 if (((flags & GLOB_ALTDIRFUNC)
969 ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0
970 || !S_ISDIR (st.st_mode))
971#endif
972 /* No directory, ignore this entry. */
973 continue;
974
975 pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1
976 + filename_len);
977 if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
978 {
979 globfree (&dirs);
980 globfree (pglob);
981 return GLOB_NOSPACE;
982 }
983
984#ifdef HAVE_MEMPCPY
985 mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc],
986 dir, dir_len),
987 "/", 1),
988 filename, filename_len);
989#else
990 memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len);
991 pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/';
992 memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1],
993 filename, filename_len);
994#endif
995 ++pglob->gl_pathc;
996 }
997
998 pglob->gl_pathv[pglob->gl_pathc] = NULL;
999 pglob->gl_flags = flags;
1000
1001 /* Now we know how large the gl_pathv vector must be. */
1002 new_pathv = (char **) realloc (pglob->gl_pathv,
1003 ((pglob->gl_pathc + 1)
1004 * sizeof (char *)));
1005 if (new_pathv != NULL)
1006 pglob->gl_pathv = new_pathv;
1007 }
1008 else
1009 return GLOB_NOMATCH;
1010 }
1011
1012 globfree (&dirs);
1013 }
1014 else
1015 {
1016 status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
1017 if (status != 0)
1018 return status;
1019
1020 if (dirlen > 0)
1021 {
1022 /* Stick the directory on the front of each name. */
1023 __size_t ignore = oldcount; /* bird: correct type. */
1024
1025 if ((flags & GLOB_DOOFFS) && ignore < pglob->gl_offs)
1026 ignore = pglob->gl_offs;
1027
1028 if (prefix_array (dirname,
1029 &pglob->gl_pathv[ignore],
1030 pglob->gl_pathc - ignore))
1031 {
1032 globfree (pglob);
1033 return GLOB_NOSPACE;
1034 }
1035 }
1036 }
1037
1038 if (flags & GLOB_MARK)
1039 {
1040 /* Append slashes to directory names. */
1041 __size_t i; /* bird: correct type. */
1042 struct stat st;
1043 for (i = oldcount; i < pglob->gl_pathc; ++i)
1044#ifdef KMK
1045 if (flags & GLOB_ALTDIRFUNC
1046 ? pglob->gl_isdir (pglob->gl_pathv[i])
1047 : __stat (pglob->gl_pathv[i], &st) == 0 && S_ISDIR (st.st_mode) )
1048#else
1049 if (((flags & GLOB_ALTDIRFUNC)
1050 ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st)
1051 : __stat (pglob->gl_pathv[i], &st)) == 0
1052 && S_ISDIR (st.st_mode))
1053#endif
1054 {
1055 size_t len = strlen (pglob->gl_pathv[i]) + 2;
1056 char *new = realloc (pglob->gl_pathv[i], len);
1057 if (new == NULL)
1058 {
1059 globfree (pglob);
1060 return GLOB_NOSPACE;
1061 }
1062 strcpy (&new[len - 2], "/");
1063 pglob->gl_pathv[i] = new;
1064 }
1065 }
1066
1067 if (!(flags & GLOB_NOSORT))
1068 {
1069 /* Sort the vector. */
1070 int non_sort = oldcount;
1071
1072 if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount)
1073 non_sort = pglob->gl_offs;
1074
1075 qsort ((__ptr_t) &pglob->gl_pathv[non_sort],
1076 pglob->gl_pathc - non_sort,
1077 sizeof (char *), collated_compare);
1078 }
1079
1080 return 0;
1081}
1082
1083
1084/* Free storage allocated in PGLOB by a previous `glob' call. */
1085void
1086globfree (pglob)
1087 register glob_t *pglob;
1088{
1089 if (pglob->gl_pathv != NULL)
1090 {
1091 register __size_t i; /* bird: correct type */
1092 for (i = 0; i < pglob->gl_pathc; ++i)
1093 if (pglob->gl_pathv[i] != NULL)
1094 free ((__ptr_t) pglob->gl_pathv[i]);
1095 free ((__ptr_t) pglob->gl_pathv);
1096 }
1097}
1098
1099
1100/* Do a collated comparison of A and B. */
1101static int
1102collated_compare (a, b)
1103 const __ptr_t a;
1104 const __ptr_t b;
1105{
1106 const char *const s1 = *(const char *const * const) a;
1107 const char *const s2 = *(const char *const * const) b;
1108
1109 if (s1 == s2)
1110 return 0;
1111 if (s1 == NULL)
1112 return 1;
1113 if (s2 == NULL)
1114 return -1;
1115 return strcoll (s1, s2);
1116}
1117
1118
1119/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
1120 elements in place. Return nonzero if out of memory, zero if successful.
1121 A slash is inserted between DIRNAME and each elt of ARRAY,
1122 unless DIRNAME is just "/". Each old element of ARRAY is freed. */
1123static int
1124prefix_array (dirname, array, n)
1125 const char *dirname;
1126 char **array;
1127 size_t n;
1128{
1129 register size_t i;
1130 size_t dirlen = strlen (dirname);
1131#if defined __MSDOS__ || defined WINDOWS32
1132 int sep_char = '/';
1133# define DIRSEP_CHAR sep_char
1134#else
1135# define DIRSEP_CHAR '/'
1136#endif
1137
1138 if (dirlen == 1 && dirname[0] == '/')
1139 /* DIRNAME is just "/", so normal prepending would get us "//foo".
1140 We want "/foo" instead, so don't prepend any chars from DIRNAME. */
1141 dirlen = 0;
1142#if defined __MSDOS__ || defined WINDOWS32
1143 else if (dirlen > 1)
1144 {
1145 if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
1146 /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */
1147 --dirlen;
1148 else if (dirname[dirlen - 1] == ':')
1149 {
1150 /* DIRNAME is "d:". Use `:' instead of `/'. */
1151 --dirlen;
1152 sep_char = ':';
1153 }
1154 }
1155#endif
1156
1157 for (i = 0; i < n; ++i)
1158 {
1159 size_t eltlen = strlen (array[i]) + 1;
1160 char *new = (char *) malloc (dirlen + 1 + eltlen);
1161 if (new == NULL)
1162 {
1163 while (i > 0)
1164 free ((__ptr_t) array[--i]);
1165 return 1;
1166 }
1167
1168#ifdef HAVE_MEMPCPY
1169 {
1170 char *endp = (char *) mempcpy (new, dirname, dirlen);
1171 *endp++ = DIRSEP_CHAR;
1172 mempcpy (endp, array[i], eltlen);
1173 }
1174#else
1175 memcpy (new, dirname, dirlen);
1176 new[dirlen] = DIRSEP_CHAR;
1177 memcpy (&new[dirlen + 1], array[i], eltlen);
1178#endif
1179 free ((__ptr_t) array[i]);
1180 array[i] = new;
1181 }
1182
1183 return 0;
1184}
1185
1186
1187/* We must not compile this function twice. */
1188#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
1189/* Return nonzero if PATTERN contains any metacharacters.
1190 Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
1191int
1192__glob_pattern_p (pattern, quote)
1193 const char *pattern;
1194 int quote;
1195{
1196 register const char *p;
1197 int open = 0;
1198
1199 for (p = pattern; *p != '\0'; ++p)
1200 switch (*p)
1201 {
1202 case '?':
1203 case '*':
1204 return 1;
1205
1206 case '\\':
1207 if (quote && p[1] != '\0')
1208 ++p;
1209 break;
1210
1211 case '[':
1212 open = 1;
1213 break;
1214
1215 case ']':
1216 if (open)
1217 return 1;
1218 break;
1219 }
1220
1221 return 0;
1222}
1223# ifdef _LIBC
1224weak_alias (__glob_pattern_p, glob_pattern_p)
1225# endif
1226#endif
1227
1228
1229/* Like `glob', but PATTERN is a final pathname component,
1230 and matches are searched for in DIRECTORY.
1231 The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
1232 The GLOB_APPEND flag is assumed to be set (always appends). */
1233static int
1234glob_in_dir (pattern, directory, flags, errfunc, pglob)
1235 const char *pattern;
1236 const char *directory;
1237 int flags;
1238 int (*errfunc) __P ((const char *, int));
1239 glob_t *pglob;
1240{
1241 __ptr_t stream = NULL;
1242
1243 struct globlink
1244 {
1245 struct globlink *next;
1246 char *name;
1247 };
1248 struct globlink *names = NULL;
1249 size_t nfound;
1250 int meta;
1251 int save;
1252
1253#ifdef VMS
1254 if (*directory == 0)
1255 directory = "[]";
1256#endif
1257 meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
1258 if (meta == 0)
1259 {
1260 if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))
1261 /* We need not do any tests. The PATTERN contains no meta
1262 characters and we must not return an error therefore the
1263 result will always contain exactly one name. */
1264 flags |= GLOB_NOCHECK;
1265 else
1266 {
1267 /* Since we use the normal file functions we can also use stat()
1268 to verify the file is there. */
1269 struct stat st;
1270 size_t patlen = strlen (pattern);
1271 size_t dirlen = strlen (directory);
1272 char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
1273
1274# ifdef HAVE_MEMPCPY
1275 mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
1276 "/", 1),
1277 pattern, patlen + 1);
1278# else
1279 memcpy (fullname, directory, dirlen);
1280 fullname[dirlen] = '/';
1281 memcpy (&fullname[dirlen + 1], pattern, patlen + 1);
1282# endif
1283# ifdef KMK
1284 if (flags & GLOB_ALTDIRFUNC ? pglob->gl_exists (fullname) : __stat (fullname, &st) == 0)
1285# else
1286 if (((flags & GLOB_ALTDIRFUNC)
1287 ? (*pglob->gl_stat) (fullname, &st)
1288 : __stat (fullname, &st)) == 0)
1289# endif
1290 /* We found this file to be existing. Now tell the rest
1291 of the function to copy this name into the result. */
1292 flags |= GLOB_NOCHECK;
1293 }
1294
1295 nfound = 0;
1296 }
1297 else
1298 {
1299 if (pattern[0] == '\0')
1300 {
1301 /* This is a special case for matching directories like in
1302 "*a/". */
1303 names = (struct globlink *) __alloca (sizeof (struct globlink));
1304 names->name = (char *) malloc (1);
1305 if (names->name == NULL)
1306 goto memory_error;
1307 names->name[0] = '\0';
1308 names->next = NULL;
1309 nfound = 1;
1310 meta = 0;
1311 }
1312 else
1313 {
1314 stream = ((flags & GLOB_ALTDIRFUNC)
1315 ? (*pglob->gl_opendir) (directory)
1316 : (__ptr_t) opendir (directory));
1317 if (stream == NULL)
1318 {
1319 if (errno != ENOTDIR
1320 && ((errfunc != NULL && (*errfunc) (directory, errno))
1321 || (flags & GLOB_ERR)))
1322 return GLOB_ABORTED;
1323 nfound = 0;
1324 meta = 0;
1325 }
1326 else
1327 {
1328 int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
1329 | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
1330#if defined HAVE_CASE_INSENSITIVE_FS
1331 | FNM_CASEFOLD
1332#endif
1333 );
1334 nfound = 0;
1335 flags |= GLOB_MAGCHAR;
1336
1337 while (1)
1338 {
1339 const char *name;
1340 size_t len;
1341 struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
1342 ? (*pglob->gl_readdir) (stream)
1343 : readdir ((DIR *) stream));
1344 if (d == NULL)
1345 break;
1346 if (! REAL_DIR_ENTRY (d))
1347 continue;
1348
1349#ifdef HAVE_D_TYPE
1350 /* If we shall match only directories use the information
1351 provided by the dirent call if possible. */
1352 if ((flags & GLOB_ONLYDIR)
1353 && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
1354 continue;
1355#endif
1356
1357 name = d->d_name;
1358
1359 if (fnmatch (pattern, name, fnm_flags) == 0)
1360 {
1361 struct globlink *new = (struct globlink *)
1362 __alloca (sizeof (struct globlink));
1363 len = NAMLEN (d);
1364 new->name = (char *) malloc (len + 1);
1365 if (new->name == NULL)
1366 goto memory_error;
1367#ifdef HAVE_MEMPCPY
1368 *((char *) mempcpy ((__ptr_t) new->name, name, len))
1369 = '\0';
1370#else
1371 memcpy ((__ptr_t) new->name, name, len);
1372 new->name[len] = '\0';
1373#endif
1374 new->next = names;
1375 names = new;
1376 ++nfound;
1377 }
1378 }
1379 }
1380 }
1381 }
1382
1383 if (nfound == 0 && (flags & GLOB_NOCHECK))
1384 {
1385 size_t len = strlen (pattern);
1386 nfound = 1;
1387 names = (struct globlink *) __alloca (sizeof (struct globlink));
1388 names->next = NULL;
1389 names->name = (char *) malloc (len + 1);
1390 if (names->name == NULL)
1391 goto memory_error;
1392#ifdef HAVE_MEMPCPY
1393 *((char *) mempcpy (names->name, pattern, len)) = '\0';
1394#else
1395 memcpy (names->name, pattern, len);
1396 names->name[len] = '\0';
1397#endif
1398 }
1399
1400 if (nfound != 0)
1401 {
1402 pglob->gl_pathv
1403 = (char **) realloc (pglob->gl_pathv,
1404 (pglob->gl_pathc +
1405 ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
1406 nfound + 1) *
1407 sizeof (char *));
1408 if (pglob->gl_pathv == NULL)
1409 goto memory_error;
1410
1411 if (flags & GLOB_DOOFFS)
1412 while (pglob->gl_pathc < pglob->gl_offs)
1413 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
1414
1415 for (; names != NULL; names = names->next)
1416 pglob->gl_pathv[pglob->gl_pathc++] = names->name;
1417 pglob->gl_pathv[pglob->gl_pathc] = NULL;
1418
1419 pglob->gl_flags = flags;
1420 }
1421
1422 save = errno;
1423 if (stream != NULL)
1424 {
1425 if (flags & GLOB_ALTDIRFUNC)
1426 (*pglob->gl_closedir) (stream);
1427 else
1428 closedir ((DIR *) stream);
1429 }
1430 __set_errno (save);
1431
1432 return nfound == 0 ? GLOB_NOMATCH : 0;
1433
1434 memory_error:
1435 {
1436 int save = errno;
1437 if (flags & GLOB_ALTDIRFUNC)
1438 (*pglob->gl_closedir) (stream);
1439 else
1440 closedir ((DIR *) stream);
1441 __set_errno (save);
1442 }
1443 while (names != NULL)
1444 {
1445 if (names->name != NULL)
1446 free ((__ptr_t) names->name);
1447 names = names->next;
1448 }
1449 return GLOB_NOSPACE;
1450}
1451
1452#endif /* Not ELIDE_CODE. */
Note: See TracBrowser for help on using the repository browser.

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