source: trunk/src/kmk/glob/glob.c@ 3152

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

glob.c: Apparently the mempcpy stuff doesn't work, guess missing prototype due to assumption about being inside glibc.

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