initial import
[platform/upstream/glibc.git] / posix / glob.c
1 /* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public License as
5 published by the Free Software Foundation; either version 2 of the
6 License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; see the file COPYING.LIB.  If
15 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
16 Cambridge, MA 02139, USA.  */
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 #include <errno.h>
28 #include <sys/types.h>
29
30
31 /* Comment out all this code if we are using the GNU C Library, and are not
32    actually compiling the library itself.  This code is part of the GNU C
33    Library, but also included in many other GNU distributions.  Compiling
34    and linking in this code is a waste when using the GNU C library
35    (especially if it is a shared library).  Rather than having every GNU
36    program understand `configure --with-gnu-libc' and omit the object files,
37    it is simpler to just do this in the source for each such file.  */
38
39 #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
40
41
42 #ifdef  STDC_HEADERS
43 #include <stddef.h>
44 #endif
45
46 #ifdef  HAVE_UNISTD_H
47 #include <unistd.h>
48 #ifndef POSIX
49 #ifdef  _POSIX_VERSION
50 #define POSIX
51 #endif
52 #endif
53 #endif
54
55 #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
56 extern int errno;
57 #endif
58
59 #ifndef NULL
60 #define NULL    0
61 #endif
62
63
64 #if     defined (POSIX) || defined (HAVE_DIRENT_H) || defined (__GNU_LIBRARY__)
65 #include <dirent.h>
66 #ifndef __GNU_LIBRARY__
67 #define D_NAMLEN(d) strlen((d)->d_name)
68 #else   /* GNU C library.  */
69 #define D_NAMLEN(d) ((d)->d_namlen)
70 #endif  /* Not GNU C library.  */
71 #else   /* Not POSIX or HAVE_DIRENT_H.  */
72 #define direct dirent
73 #define D_NAMLEN(d) ((d)->d_namlen)
74 #ifdef  HAVE_SYS_NDIR_H
75 #include <sys/ndir.h>
76 #endif  /* HAVE_SYS_NDIR_H */
77 #ifdef  HAVE_SYS_DIR_H
78 #include <sys/dir.h>
79 #endif  /* HAVE_SYS_DIR_H */
80 #ifdef HAVE_NDIR_H
81 #include <ndir.h>
82 #endif  /* HAVE_NDIR_H */
83 #endif  /* POSIX or HAVE_DIRENT_H or __GNU_LIBRARY__.  */
84
85 #if defined (POSIX) && !defined (__GNU_LIBRARY__)
86 /* Posix does not require that the d_ino field be present, and some
87    systems do not provide it. */
88 #define REAL_DIR_ENTRY(dp) 1
89 #else
90 #define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
91 #endif /* POSIX */
92
93 #if     (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__))
94 #include <stdlib.h>
95 #include <string.h>
96 #define ANSI_STRING
97 #else   /* No standard headers.  */
98
99 #ifdef HAVE_STRING_H
100 #include <string.h>
101 #define ANSI_STRING
102 #else
103 #include <strings.h>
104 #endif
105 #ifdef  HAVE_MEMORY_H
106 #include <memory.h>
107 #endif
108
109 extern char *malloc (), *realloc ();
110 extern void free ();
111
112 extern void qsort ();
113 extern void abort (), exit ();
114
115 #endif  /* Standard headers.  */
116
117 #ifndef ANSI_STRING
118
119 #ifndef bzero
120 extern void bzero ();
121 #endif
122 #ifndef bcopy
123 extern void bcopy ();
124 #endif
125
126 #define memcpy(d, s, n) bcopy ((s), (d), (n))
127 #define strrchr rindex
128 /* memset is only used for zero here, but let's be paranoid.  */
129 #define memset(s, better_be_zero, n) \
130   ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0)))
131 #endif  /* Not ANSI_STRING.  */
132
133 #ifndef HAVE_STRCOLL
134 #define strcoll strcmp
135 #endif
136
137
138 #ifndef __GNU_LIBRARY__
139 #ifdef  __GNUC__
140 __inline
141 #endif
142 static char *
143 my_realloc (p, n)
144      char *p;
145      unsigned int n;
146 {
147   /* These casts are the for sake of the broken Ultrix compiler,
148      which warns of illegal pointer combinations otherwise.  */
149   if (p == NULL)
150     return (char *) malloc (n);
151   return (char *) realloc (p, n);
152 }
153 #define realloc my_realloc
154 #endif
155
156
157 #if     !defined(__alloca) && !defined(__GNU_LIBRARY__)
158
159 #ifdef  __GNUC__
160 #undef  alloca
161 #define alloca(n)       __builtin_alloca (n)
162 #else   /* Not GCC.  */
163 #if     defined (sparc) || defined (HAVE_ALLOCA_H)
164 #include <alloca.h>
165 #else   /* Not sparc or HAVE_ALLOCA_H.  */
166 #ifndef _AIX
167 extern char *alloca ();
168 #endif  /* Not _AIX.  */
169 #endif  /* sparc or HAVE_ALLOCA_H.  */
170 #endif  /* GCC.  */
171
172 #define __alloca        alloca
173
174 #endif
175
176 #ifndef STDC_HEADERS
177 #undef  size_t
178 #define size_t  unsigned int
179 #endif
180
181 /* Some system header files erroneously define these.
182    We want our own definitions from <fnmatch.h> to take precedence.  */
183 #undef  FNM_PATHNAME
184 #undef  FNM_NOESCAPE
185 #undef  FNM_PERIOD
186 #include <fnmatch.h>
187
188 /* Some system header files erroneously define these.
189    We want our own definitions from <glob.h> to take precedence.  */
190 #undef  GLOB_ERR
191 #undef  GLOB_MARK
192 #undef  GLOB_NOSORT
193 #undef  GLOB_DOOFFS
194 #undef  GLOB_NOCHECK
195 #undef  GLOB_APPEND
196 #undef  GLOB_NOESCAPE
197 #undef  GLOB_PERIOD
198 #include <glob.h>
199 \f
200 __ptr_t (*__glob_opendir_hook) __P ((const char *directory));
201 const char *(*__glob_readdir_hook) __P ((__ptr_t stream));
202 void (*__glob_closedir_hook) __P ((__ptr_t stream));
203
204 static int glob_pattern_p __P ((const char *pattern, int quote));
205 static int glob_in_dir __P ((const char *pattern, const char *directory,
206                              int flags,
207                              int (*errfunc) __P ((const char *, int)),
208                              glob_t *pglob));
209 static int prefix_array __P ((const char *prefix, char **array, size_t n));
210 static int collated_compare __P ((const __ptr_t, const __ptr_t));
211
212 /* Do glob searching for PATTERN, placing results in PGLOB.
213    The bits defined above may be set in FLAGS.
214    If a directory cannot be opened or read and ERRFUNC is not nil,
215    it is called with the pathname that caused the error, and the
216    `errno' value from the failing call; if it returns non-zero
217    `glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
218    If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
219    Otherwise, `glob' returns zero.  */
220 int
221 glob (pattern, flags, errfunc, pglob)
222      const char *pattern;
223      int flags;
224      int (*errfunc) __P ((const char *, int));
225      glob_t *pglob;
226 {
227   const char *filename;
228   char *dirname;
229   size_t dirlen;
230   int status;
231   int oldcount;
232
233   if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
234     {
235       errno = EINVAL;
236       return -1;
237     }
238
239   /* Find the filename.  */
240   filename = strrchr (pattern, '/');
241   if (filename == NULL)
242     {
243       filename = pattern;
244       dirname = (char *) ".";
245       dirlen = 0;
246     }
247   else if (filename == pattern)
248     {
249       /* "/pattern".  */
250       dirname = (char *) "/";
251       dirlen = 1;
252       ++filename;
253     }
254   else
255     {
256       dirlen = filename - pattern;
257       dirname = (char *) __alloca (dirlen + 1);
258       memcpy (dirname, pattern, dirlen);
259       dirname[dirlen] = '\0';
260       ++filename;
261     }
262
263   if (filename[0] == '\0' && dirlen > 1)
264     /* "pattern/".  Expand "pattern", appending slashes.  */
265     {
266       int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
267       if (val == 0)
268         pglob->gl_flags = (pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK);
269       return val;
270     }
271
272   if (!(flags & GLOB_APPEND))
273     {
274       pglob->gl_pathc = 0;
275       pglob->gl_pathv = NULL;
276     }
277
278   oldcount = pglob->gl_pathc;
279
280   if (glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
281     {
282       /* The directory name contains metacharacters, so we
283          have to glob for the directory, and then glob for
284          the pattern in each directory found.  */
285       glob_t dirs;
286       register int i;
287
288       status = glob (dirname,
289                      ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE)) |
290                       GLOB_NOSORT),
291                      errfunc, &dirs);
292       if (status != 0)
293         return status;
294
295       /* We have successfully globbed the preceding directory name.
296          For each name we found, call glob_in_dir on it and FILENAME,
297          appending the results to PGLOB.  */
298       for (i = 0; i < dirs.gl_pathc; ++i)
299         {
300           int oldcount;
301
302 #ifdef  SHELL
303           {
304             /* Make globbing interruptible in the bash shell. */
305             extern int interrupt_state;
306
307             if (interrupt_state)
308               {
309                 globfree (&dirs);
310                 globfree (&files);
311                 return GLOB_ABEND;
312               }
313           }
314 #endif /* SHELL.  */
315
316           oldcount = pglob->gl_pathc;
317           status = glob_in_dir (filename, dirs.gl_pathv[i],
318                                 (flags | GLOB_APPEND) & ~GLOB_NOCHECK,
319                                 errfunc, pglob);
320           if (status == GLOB_NOMATCH)
321             /* No matches in this directory.  Try the next.  */
322             continue;
323
324           if (status != 0)
325             {
326               globfree (&dirs);
327               globfree (pglob);
328               return status;
329             }
330
331           /* Stick the directory on the front of each name.  */
332           if (prefix_array (dirs.gl_pathv[i],
333                             &pglob->gl_pathv[oldcount],
334                             pglob->gl_pathc - oldcount))
335             {
336               globfree (&dirs);
337               globfree (pglob);
338               return GLOB_NOSPACE;
339             }
340         }
341
342       flags |= GLOB_MAGCHAR;
343
344       if (pglob->gl_pathc == oldcount)
345         /* No matches.  */
346         if (flags & GLOB_NOCHECK)
347           {
348             size_t len = strlen (pattern) + 1;
349             char *patcopy = (char *) malloc (len);
350             if (patcopy == NULL)
351               return GLOB_NOSPACE;
352             memcpy (patcopy, pattern, len);
353
354             pglob->gl_pathv
355               = (char **) realloc (pglob->gl_pathv,
356                                    (pglob->gl_pathc +
357                                     ((flags & GLOB_DOOFFS) ?
358                                      pglob->gl_offs : 0) +
359                                     1 + 1) *
360                                    sizeof (char *));
361             if (pglob->gl_pathv == NULL)
362               {
363                 free (patcopy);
364                 return GLOB_NOSPACE;
365               }
366
367             if (flags & GLOB_DOOFFS)
368               while (pglob->gl_pathc < pglob->gl_offs)
369                 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
370
371             pglob->gl_pathv[pglob->gl_pathc++] = patcopy;
372             pglob->gl_pathv[pglob->gl_pathc] = NULL;
373             pglob->gl_flags = flags;
374           }
375         else
376           return GLOB_NOMATCH;
377     }
378   else
379     {
380       status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
381       if (status != 0)
382         return status;
383
384       if (dirlen > 0)
385         {
386           /* Stick the directory on the front of each name.  */
387           if (prefix_array (dirname,
388                             &pglob->gl_pathv[oldcount],
389                             pglob->gl_pathc - oldcount))
390             {
391               globfree (pglob);
392               return GLOB_NOSPACE;
393             }
394         }
395     }
396
397   if (!(flags & GLOB_NOSORT))
398     /* Sort the vector.  */
399     qsort ((__ptr_t) & pglob->gl_pathv[oldcount],
400            pglob->gl_pathc - oldcount,
401            sizeof (char *), collated_compare);
402
403   return 0;
404 }
405
406
407 /* Free storage allocated in PGLOB by a previous `glob' call.  */
408 void
409 globfree (pglob)
410      register glob_t *pglob;
411 {
412   if (pglob->gl_pathv != NULL)
413     {
414       register int i;
415       for (i = 0; i < pglob->gl_pathc; ++i)
416         if (pglob->gl_pathv[i] != NULL)
417           free ((__ptr_t) pglob->gl_pathv[i]);
418       free ((__ptr_t) pglob->gl_pathv);
419     }
420 }
421
422
423 /* Do a collated comparison of A and B.  */
424 static int
425 collated_compare (a, b)
426      const __ptr_t a;
427      const __ptr_t b;
428 {
429   const char *const s1 = *(const char *const * const) a;
430   const char *const s2 = *(const char *const * const) b;
431
432   if (s1 == s2)
433     return 0;
434   if (s1 == NULL)
435     return 1;
436   if (s2 == NULL)
437     return -1;
438   return strcoll (s1, s2);
439 }
440
441
442 /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
443    elements in place.  Return nonzero if out of memory, zero if successful.
444    A slash is inserted between DIRNAME and each elt of ARRAY,
445    unless DIRNAME is just "/".  Each old element of ARRAY is freed.  */
446 static int
447 prefix_array (dirname, array, n)
448      const char *dirname;
449      char **array;
450      size_t n;
451 {
452   register size_t i;
453   size_t dirlen = strlen (dirname);
454
455   if (dirlen == 1 && dirname[0] == '/')
456     /* DIRNAME is just "/", so normal prepending would get us "//foo".
457        We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
458     dirlen = 0;
459
460   for (i = 0; i < n; ++i)
461     {
462       size_t eltlen = strlen (array[i]) + 1;
463       char *new = (char *) malloc (dirlen + 1 + eltlen);
464       if (new == NULL)
465         {
466           while (i > 0)
467             free ((__ptr_t) array[--i]);
468           return 1;
469         }
470
471       memcpy (new, dirname, dirlen);
472       new[dirlen] = '/';
473       memcpy (&new[dirlen + 1], array[i], eltlen);
474       free ((__ptr_t) array[i]);
475       array[i] = new;
476     }
477
478   return 0;
479 }
480
481
482 /* Return nonzero if PATTERN contains any metacharacters.
483    Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
484 static int
485 glob_pattern_p (pattern, quote)
486      const char *pattern;
487      int quote;
488 {
489   register const char *p;
490   int open = 0;
491
492   for (p = pattern; *p != '\0'; ++p)
493     switch (*p)
494       {
495       case '?':
496       case '*':
497         return 1;
498
499       case '\\':
500         if (quote)
501           ++p;
502         break;
503
504       case '[':
505         open = 1;
506         break;
507
508       case ']':
509         if (open)
510           return 1;
511         break;
512       }
513
514   return 0;
515 }
516
517
518 /* Like `glob', but PATTERN is a final pathname component,
519    and matches are searched for in DIRECTORY.
520    The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
521    The GLOB_APPEND flag is assumed to be set (always appends).  */
522 static int
523 glob_in_dir (pattern, directory, flags, errfunc, pglob)
524      const char *pattern;
525      const char *directory;
526      int flags;
527      int (*errfunc) __P ((const char *, int));
528      glob_t *pglob;
529 {
530   __ptr_t stream;
531
532   struct globlink
533     {
534       struct globlink *next;
535       char *name;
536     };
537   struct globlink *names = NULL;
538   size_t nfound = 0;
539
540   if (!glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)))
541     {
542       stream = NULL;
543       flags |= GLOB_NOCHECK;
544     }
545   else
546     {
547       flags |= GLOB_MAGCHAR;
548
549       stream = (__glob_opendir_hook ? (*__glob_opendir_hook) (directory)
550                 : (__ptr_t) opendir (directory));
551       if (stream == NULL)
552         {
553           if ((errfunc != NULL && (*errfunc) (directory, errno)) ||
554               (flags & GLOB_ERR))
555             return GLOB_ABEND;
556         }
557       else
558         while (1)
559           {
560             const char *name;
561             size_t len;
562
563             if (__glob_readdir_hook)
564               {
565                 name = (*__glob_readdir_hook) (stream);
566                 if (name == NULL)
567                   break;
568                 len = 0;
569               }
570             else
571               {
572                 struct dirent *d = readdir ((DIR *) stream);
573                 if (d == NULL)
574                   break;
575                 if (! REAL_DIR_ENTRY (d))
576                   continue;
577                 name = d->d_name;
578 #ifdef  HAVE_D_NAMLEN
579                 len = d->d_namlen;
580 #else
581                 len = 0;
582 #endif
583               }
584                 
585             if (fnmatch (pattern, name,
586                          (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) |
587                          ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)) == 0)
588               {
589                 struct globlink *new
590                   = (struct globlink *) __alloca (sizeof (struct globlink));
591                 if (len == 0)
592                   len = strlen (name);
593                 new->name
594                   = (char *) malloc (len + ((flags & GLOB_MARK) ? 1 : 0) + 1);
595                 if (new->name == NULL)
596                   goto memory_error;
597                 memcpy ((__ptr_t) new->name, name, len);
598                 if (flags & GLOB_MARK)
599                   new->name[len++] = '/';
600                 new->name[len] = '\0';
601                 new->next = names;
602                 names = new;
603                 ++nfound;
604               }
605           }
606     }
607
608   if (nfound == 0 && (flags & GLOB_NOCHECK))
609     {
610       size_t len = strlen (pattern);
611       nfound = 1;
612       names = (struct globlink *) __alloca (sizeof (struct globlink));
613       names->next = NULL;
614       names->name = (char *) malloc (len + ((flags & GLOB_MARK) ? 1 : 0) + 1);
615       if (names->name == NULL)
616         goto memory_error;
617       memcpy (names->name, pattern, len);
618       if (flags & GLOB_MARK)
619         names->name[len++] = '/';
620       names->name[len] = '\0';
621     }
622
623   pglob->gl_pathv
624     = (char **) realloc (pglob->gl_pathv,
625                          (pglob->gl_pathc +
626                           ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
627                           nfound + 1) *
628                          sizeof (char *));
629   if (pglob->gl_pathv == NULL)
630     goto memory_error;
631
632   if (flags & GLOB_DOOFFS)
633     while (pglob->gl_pathc < pglob->gl_offs)
634       pglob->gl_pathv[pglob->gl_pathc++] = NULL;
635
636   for (; names != NULL; names = names->next)
637     pglob->gl_pathv[pglob->gl_pathc++] = names->name;
638   pglob->gl_pathv[pglob->gl_pathc] = NULL;
639
640   pglob->gl_flags = flags;
641
642   if (stream != NULL)
643     {
644       int save = errno;
645       if (__glob_closedir_hook)
646         (*__glob_closedir_hook) (stream);
647       else
648         (void) closedir ((DIR *) stream);
649       errno = save;
650     }
651   return nfound == 0 ? GLOB_NOMATCH : 0;
652
653  memory_error:
654   {
655     int save = errno;
656     if (__glob_closedir_hook)
657       (*__glob_closedir_hook) (stream);
658     else
659       (void) closedir ((DIR *) stream);
660     errno = save;
661   }
662   while (names != NULL)
663     {
664       if (names->name != NULL)
665         free ((__ptr_t) names->name);
666       names = names->next;
667     }
668   return GLOB_NOSPACE;
669 }
670
671 #endif  /* _LIBC or not __GNU_LIBRARY__.  */