Sat Jul 20 21:55:31 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
[kopensolaris-gnu/glibc.git] / posix / glob.c
1 /* Copyright (C) 1991, 92, 93, 94, 95, 96 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 /* Enable GNU extensions in glob.h.  */
28 #ifndef _GNU_SOURCE
29 #define _GNU_SOURCE     1
30 #endif
31
32 #include <errno.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35
36
37 /* Comment out all this code if we are using the GNU C Library, and are not
38    actually compiling the library itself.  This code is part of the GNU C
39    Library, but also included in many other GNU distributions.  Compiling
40    and linking in this code is a waste when using the GNU C library
41    (especially if it is a shared library).  Rather than having every GNU
42    program understand `configure --with-gnu-libc' and omit the object files,
43    it is simpler to just do this in the source for each such file.  */
44
45 #define GLOB_INTERFACE_VERSION 1
46 #if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
47 #include <gnu-versions.h>
48 #if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
49 #define ELIDE_CODE
50 #endif
51 #endif
52
53 #ifndef ELIDE_CODE
54
55 #ifdef  STDC_HEADERS
56 #include <stddef.h>
57 #endif
58
59 #ifdef  HAVE_UNISTD_H
60 #include <unistd.h>
61 #ifndef POSIX
62 #ifdef  _POSIX_VERSION
63 #define POSIX
64 #endif
65 #endif
66 #endif
67
68 #if !defined (_AMIGA) && !defined (VMS) && !defined(WIN32)
69 #include <pwd.h>
70 #endif
71
72 #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
73 extern int errno;
74 #endif
75
76 #ifndef NULL
77 #define NULL    0
78 #endif
79
80
81 #if defined (HAVE_DIRENT_H) || defined (__GNU_LIBRARY__)
82 # include <dirent.h>
83 # define NAMLEN(dirent) strlen((dirent)->d_name)
84 #else
85 # define dirent direct
86 # define NAMLEN(dirent) (dirent)->d_namlen
87 # ifdef HAVE_SYS_NDIR_H
88 #  include <sys/ndir.h>
89 # endif
90 # ifdef HAVE_SYS_DIR_H
91 #  include <sys/dir.h>
92 # endif
93 # ifdef HAVE_NDIR_H
94 #  include <ndir.h>
95 # endif
96 # ifdef HAVE_VMSDIR_H
97 #  include "vmsdir.h"
98 # endif /* HAVE_VMSDIR_H */
99 #endif
100
101
102 /* In GNU systems, <dirent.h> defines this macro for us.  */
103 #ifdef _D_NAMLEN
104 #undef NAMLEN
105 #define NAMLEN(d) _D_NAMLEN(d)
106 #endif
107
108
109 #if (defined (POSIX) || defined (WIN32)) && !defined (__GNU_LIBRARY__)
110 /* Posix does not require that the d_ino field be present, and some
111    systems do not provide it. */
112 #define REAL_DIR_ENTRY(dp) 1
113 #else
114 #define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
115 #endif /* POSIX */
116
117 #if     (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__))
118 #include <stdlib.h>
119 #include <string.h>
120 #define ANSI_STRING
121 #else   /* No standard headers.  */
122
123 extern char *getenv ();
124
125 #ifdef HAVE_STRING_H
126 #include <string.h>
127 #define ANSI_STRING
128 #else
129 #include <strings.h>
130 #endif
131 #ifdef  HAVE_MEMORY_H
132 #include <memory.h>
133 #endif
134
135 extern char *malloc (), *realloc ();
136 extern void free ();
137
138 extern void qsort ();
139 extern void abort (), exit ();
140
141 #endif  /* Standard headers.  */
142
143 #ifndef ANSI_STRING
144
145 #ifndef bzero
146 extern void bzero ();
147 #endif
148 #ifndef bcopy
149 extern void bcopy ();
150 #endif
151
152 #define memcpy(d, s, n) bcopy ((s), (d), (n))
153 #define strrchr rindex
154 /* memset is only used for zero here, but let's be paranoid.  */
155 #define memset(s, better_be_zero, n) \
156   ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0)))
157 #endif  /* Not ANSI_STRING.  */
158
159 #ifndef HAVE_STRCOLL
160 #define strcoll strcmp
161 #endif
162
163
164 #ifndef __GNU_LIBRARY__
165 #ifdef  __GNUC__
166 __inline
167 #endif
168 #ifndef __SASC
169 #ifdef WIN32
170 static void *
171 #else
172 static char *
173 #endif
174 my_realloc (p, n)
175      char *p;
176      unsigned int n;
177 {
178   /* These casts are the for sake of the broken Ultrix compiler,
179      which warns of illegal pointer combinations otherwise.  */
180   if (p == NULL)
181     return (char *) malloc (n);
182   return (char *) realloc (p, n);
183 }
184 #define realloc my_realloc
185 #endif /* __SASC */
186 #endif /* __GNU_LIBRARY__ */
187
188
189 #if     !defined(__alloca) && !defined(__GNU_LIBRARY__)
190
191 #ifdef  __GNUC__
192 #undef  alloca
193 #define alloca(n)       __builtin_alloca (n)
194 #else   /* Not GCC.  */
195 #ifdef HAVE_ALLOCA_H
196 #include <alloca.h>
197 #else   /* Not HAVE_ALLOCA_H.  */
198 #ifndef _AIX
199 #ifdef WIN32
200 #include <malloc.h>
201 #else
202 extern char *alloca ();
203 #endif /* WIN32 */
204 #endif  /* Not _AIX.  */
205 #endif  /* sparc or HAVE_ALLOCA_H.  */
206 #endif  /* GCC.  */
207
208 #define __alloca        alloca
209
210 #endif
211
212 #ifndef __GNU_LIBRARY__
213 #define __stat stat
214 #ifdef STAT_MACROS_BROKEN
215 #undef S_ISDIR
216 #endif
217 #ifndef S_ISDIR
218 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
219 #endif
220 #endif
221
222 #ifndef STDC_HEADERS
223 #undef  size_t
224 #define size_t  unsigned int
225 #endif
226
227 /* Some system header files erroneously define these.
228    We want our own definitions from <fnmatch.h> to take precedence.  */
229 #undef  FNM_PATHNAME
230 #undef  FNM_NOESCAPE
231 #undef  FNM_PERIOD
232 #include <fnmatch.h>
233
234 /* Some system header files erroneously define these.
235    We want our own definitions from <glob.h> to take precedence.  */
236 #undef  GLOB_ERR
237 #undef  GLOB_MARK
238 #undef  GLOB_NOSORT
239 #undef  GLOB_DOOFFS
240 #undef  GLOB_NOCHECK
241 #undef  GLOB_APPEND
242 #undef  GLOB_NOESCAPE
243 #undef  GLOB_PERIOD
244 #include <glob.h>
245 \f
246 static int glob_pattern_p __P ((const char *pattern, int quote));
247 static int glob_in_dir __P ((const char *pattern, const char *directory,
248                              int flags,
249                              int (*errfunc) __P ((const char *, int)),
250                              glob_t *pglob));
251 static int prefix_array __P ((const char *prefix, char **array, size_t n));
252 static int collated_compare __P ((const __ptr_t, const __ptr_t));
253
254 /* Do glob searching for PATTERN, placing results in PGLOB.
255    The bits defined above may be set in FLAGS.
256    If a directory cannot be opened or read and ERRFUNC is not nil,
257    it is called with the pathname that caused the error, and the
258    `errno' value from the failing call; if it returns non-zero
259    `glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
260    If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
261    Otherwise, `glob' returns zero.  */
262 int
263 glob (pattern, flags, errfunc, pglob)
264      const char *pattern;
265      int flags;
266      int (*errfunc) __P ((const char *, int));
267      glob_t *pglob;
268 {
269   const char *filename;
270   char *dirname;
271   size_t dirlen;
272   int status;
273   int oldcount;
274
275   if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
276     {
277       errno = EINVAL;
278       return -1;
279     }
280
281   if (flags & GLOB_BRACE)
282     {
283       const char *begin = strchr (pattern, '{');
284       if (begin != NULL)
285         {
286           int firstc;
287           size_t restlen;
288           const char *p, *end, *next;
289           unsigned int depth = 0;
290
291           /* Find the end of the brace expression, by counting braces.
292              While we're at it, notice the first comma at top brace level.  */
293           end = begin + 1;
294           next = NULL;
295           while (1)
296             {
297               switch (*end++)
298                 {
299                 case ',':
300                   if (depth == 0 && next == NULL)
301                     next = end;
302                   continue;
303                 case '{':
304                   ++depth;
305                   continue;
306                 case '}':
307                   if (depth-- == 0)
308                     break;
309                   continue;
310                 case '\0':
311                   return glob (pattern, flags &~ GLOB_BRACE, errfunc, pglob);
312                 }
313               break;
314             }
315           restlen = strlen (end) + 1;
316           if (next == NULL)
317             next = end;
318
319           /* We have a brace expression.  BEGIN points to the opening {,
320              NEXT points past the terminator of the first element, and END
321              points past the final }.  We will accumulate result names from
322              recursive runs for each brace alternative in the buffer using
323              GLOB_APPEND.  */
324
325           if (!(flags & GLOB_APPEND))
326             {
327               /* This call is to set a new vector, so clear out the
328                  vector so we can append to it.  */
329               pglob->gl_pathc = 0;
330               pglob->gl_pathv = NULL;
331             }
332           firstc = pglob->gl_pathc;
333
334           /* In this loop P points to the beginning of the current element
335              and NEXT points past its terminator.  */
336           p = begin + 1;
337           while (1)
338             {
339               /* Construct a whole name that is one of the brace
340                  alternatives in a temporary buffer.  */
341               int result;
342               size_t bufsz = (begin - pattern) + (next - 1 - p) + restlen;
343 #ifdef __GNUC__
344               char onealt[bufsz];
345 #else
346               char *onealt = malloc (bufsz);
347               if (onealt == NULL)
348                 {
349                   if (!(flags & GLOB_APPEND))
350                     globfree (pglob);
351                   return GLOB_NOSPACE;
352                 }
353 #endif
354               memcpy (onealt, pattern, begin - pattern);
355               memcpy (&onealt[begin - pattern], p, next - 1 - p);
356               memcpy (&onealt[(begin - pattern) + (next - 1 - p)],
357                       end, restlen);
358               result = glob (onealt,
359                              ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC)) |
360                               GLOB_APPEND), errfunc, pglob);
361 #ifndef __GNUC__
362               free (onealt);
363 #endif
364
365               /* If we got an error, return it.  */
366               if (result && result != GLOB_NOMATCH)
367                 {
368                   if (!(flags & GLOB_APPEND))
369                     globfree (pglob);
370                   return result;
371                 }
372
373               /* Advance past this alternative and process the next.  */
374               p = next;
375               depth = 0;
376             scan:
377               switch (*p++)
378                 {
379                 case ',':
380                   if (depth == 0)
381                     {
382                       /* Found the next alternative.  Loop to glob it.  */
383                       next = p;
384                       continue;
385                     }
386                   goto scan;
387                 case '{':
388                   ++depth;
389                   goto scan;
390                 case '}':
391                   if (depth-- == 0)
392                     /* End of the brace expression.  Break out of the loop.  */
393                     break;
394                   goto scan;
395                 }
396             }
397
398           if (pglob->gl_pathc == firstc &&
399               !(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
400             return GLOB_NOMATCH;
401         }
402     }
403
404   /* Find the filename.  */
405   filename = strrchr (pattern, '/');
406   if (filename == NULL)
407     {
408       filename = pattern;
409 #ifdef _AMIGA
410       dirname = (char *) "";
411 #else
412       dirname = (char *) ".";
413 #endif
414       dirlen = 0;
415     }
416   else if (filename == pattern)
417     {
418       /* "/pattern".  */
419       dirname = (char *) "/";
420       dirlen = 1;
421       ++filename;
422     }
423   else
424     {
425       dirlen = filename - pattern;
426       dirname = (char *) __alloca (dirlen + 1);
427       memcpy (dirname, pattern, dirlen);
428       dirname[dirlen] = '\0';
429       ++filename;
430     }
431
432   if (filename[0] == '\0' && dirlen > 1)
433     /* "pattern/".  Expand "pattern", appending slashes.  */
434     {
435       int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
436       if (val == 0)
437         pglob->gl_flags = (pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK);
438       return val;
439     }
440
441   if (!(flags & GLOB_APPEND))
442     {
443       pglob->gl_pathc = 0;
444       pglob->gl_pathv = NULL;
445     }
446
447   oldcount = pglob->gl_pathc;
448
449 #ifndef VMS
450   if ((flags & GLOB_TILDE) && dirname[0] == '~')
451     {
452       if (dirname[1] == '\0')
453         {
454           /* Look up home directory.  */
455           dirname = getenv ("HOME");
456 #ifdef _AMIGA
457           if (dirname == NULL || dirname[0] == '\0')
458             dirname = "SYS:";
459 #else
460 #ifdef WIN32
461           if (dirname == NULL || dirname[0] == '\0')
462             dirname = "c:/users/default"; /* poor default */
463 #else
464           if (dirname == NULL || dirname[0] == '\0')
465             {
466               extern char *getlogin __P ((void));
467               char *name = getlogin ();
468               if (name != NULL)
469                 {
470                   struct passwd *p = getpwnam (name);
471                   if (p != NULL)
472                     dirname = p->pw_dir;
473                 }
474             }
475           if (dirname == NULL || dirname[0] == '\0')
476             dirname = (char *) "~"; /* No luck.  */
477 #endif /* WIN32 */
478 #endif
479         }
480       else
481         {
482 #ifdef _AMIGA
483           if (dirname == NULL || dirname[0] == '\0')
484             dirname = "SYS:";
485 #else
486 #ifdef WIN32
487           if (dirname == NULL || dirname[0] == '\0')
488             dirname = "c:/users/default"; /* poor default */
489 #else
490           /* Look up specific user's home directory.  */
491           struct passwd *p = getpwnam (dirname + 1);
492           if (p != NULL)
493             dirname = p->pw_dir;
494 #endif /* WIN32 */
495 #endif
496         }
497     }
498 #endif  /* Not VMS.  */
499
500   if (glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
501     {
502       /* The directory name contains metacharacters, so we
503          have to glob for the directory, and then glob for
504          the pattern in each directory found.  */
505       glob_t dirs;
506       register int i;
507
508       status = glob (dirname,
509                      ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE)) |
510                       GLOB_NOSORT),
511                      errfunc, &dirs);
512       if (status != 0)
513         return status;
514
515       /* We have successfully globbed the preceding directory name.
516          For each name we found, call glob_in_dir on it and FILENAME,
517          appending the results to PGLOB.  */
518       for (i = 0; i < dirs.gl_pathc; ++i)
519         {
520           int oldcount;
521
522 #ifdef  SHELL
523           {
524             /* Make globbing interruptible in the bash shell. */
525             extern int interrupt_state;
526
527             if (interrupt_state)
528               {
529                 globfree (&dirs);
530                 globfree (&files);
531                 return GLOB_ABEND;
532               }
533           }
534 #endif /* SHELL.  */
535
536           oldcount = pglob->gl_pathc;
537           status = glob_in_dir (filename, dirs.gl_pathv[i],
538                                 (flags | GLOB_APPEND) & ~GLOB_NOCHECK,
539                                 errfunc, pglob);
540           if (status == GLOB_NOMATCH)
541             /* No matches in this directory.  Try the next.  */
542             continue;
543
544           if (status != 0)
545             {
546               globfree (&dirs);
547               globfree (pglob);
548               return status;
549             }
550
551           /* Stick the directory on the front of each name.  */
552           if (prefix_array (dirs.gl_pathv[i],
553                             &pglob->gl_pathv[oldcount],
554                             pglob->gl_pathc - oldcount))
555             {
556               globfree (&dirs);
557               globfree (pglob);
558               return GLOB_NOSPACE;
559             }
560         }
561
562       flags |= GLOB_MAGCHAR;
563
564       if (pglob->gl_pathc == oldcount)
565         /* No matches.  */
566         if (flags & GLOB_NOCHECK)
567           {
568             size_t len = strlen (pattern) + 1;
569             char *patcopy = (char *) malloc (len);
570             if (patcopy == NULL)
571               return GLOB_NOSPACE;
572             memcpy (patcopy, pattern, len);
573
574             pglob->gl_pathv
575               = (char **) realloc (pglob->gl_pathv,
576                                    (pglob->gl_pathc +
577                                     ((flags & GLOB_DOOFFS) ?
578                                      pglob->gl_offs : 0) +
579                                     1 + 1) *
580                                    sizeof (char *));
581             if (pglob->gl_pathv == NULL)
582               {
583                 free (patcopy);
584                 return GLOB_NOSPACE;
585               }
586
587             if (flags & GLOB_DOOFFS)
588               while (pglob->gl_pathc < pglob->gl_offs)
589                 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
590
591             pglob->gl_pathv[pglob->gl_pathc++] = patcopy;
592             pglob->gl_pathv[pglob->gl_pathc] = NULL;
593             pglob->gl_flags = flags;
594           }
595         else
596           return GLOB_NOMATCH;
597     }
598   else
599     {
600       status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
601       if (status != 0)
602         return status;
603
604       if (dirlen > 0)
605         {
606           /* Stick the directory on the front of each name.  */
607           if (prefix_array (dirname,
608                             &pglob->gl_pathv[oldcount],
609                             pglob->gl_pathc - oldcount))
610             {
611               globfree (pglob);
612               return GLOB_NOSPACE;
613             }
614         }
615     }
616
617   if (flags & GLOB_MARK)
618     {
619       /* Append slashes to directory names.  */
620       int i;
621       struct stat st;
622       for (i = oldcount; i < pglob->gl_pathc; ++i)
623         if (((flags & GLOB_ALTDIRFUNC) ?
624              (*pglob->gl_stat) (pglob->gl_pathv[i], &st) :
625              __stat (pglob->gl_pathv[i], &st)) == 0 &&
626             S_ISDIR (st.st_mode))
627           {
628             size_t len = strlen (pglob->gl_pathv[i]) + 2;
629             char *new = realloc (pglob->gl_pathv[i], len);
630             if (new == NULL)
631               {
632                 globfree (pglob);
633                 return GLOB_NOSPACE;
634               }
635             strcpy (&new[len - 2], "/");
636             pglob->gl_pathv[i] = new;
637           }
638     }
639
640   if (!(flags & GLOB_NOSORT))
641     /* Sort the vector.  */
642     qsort ((__ptr_t) &pglob->gl_pathv[oldcount],
643            pglob->gl_pathc - oldcount,
644            sizeof (char *), collated_compare);
645
646   return 0;
647 }
648
649
650 /* Free storage allocated in PGLOB by a previous `glob' call.  */
651 void
652 globfree (pglob)
653      register glob_t *pglob;
654 {
655   if (pglob->gl_pathv != NULL)
656     {
657       register int i;
658       for (i = 0; i < pglob->gl_pathc; ++i)
659         if (pglob->gl_pathv[i] != NULL)
660           free ((__ptr_t) pglob->gl_pathv[i]);
661       free ((__ptr_t) pglob->gl_pathv);
662     }
663 }
664
665
666 /* Do a collated comparison of A and B.  */
667 static int
668 collated_compare (a, b)
669      const __ptr_t a;
670      const __ptr_t b;
671 {
672   const char *const s1 = *(const char *const * const) a;
673   const char *const s2 = *(const char *const * const) b;
674
675   if (s1 == s2)
676     return 0;
677   if (s1 == NULL)
678     return 1;
679   if (s2 == NULL)
680     return -1;
681   return strcoll (s1, s2);
682 }
683
684
685 /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
686    elements in place.  Return nonzero if out of memory, zero if successful.
687    A slash is inserted between DIRNAME and each elt of ARRAY,
688    unless DIRNAME is just "/".  Each old element of ARRAY is freed.  */
689 static int
690 prefix_array (dirname, array, n)
691      const char *dirname;
692      char **array;
693      size_t n;
694 {
695   register size_t i;
696   size_t dirlen = strlen (dirname);
697
698   if (dirlen == 1 && dirname[0] == '/')
699     /* DIRNAME is just "/", so normal prepending would get us "//foo".
700        We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
701     dirlen = 0;
702
703   for (i = 0; i < n; ++i)
704     {
705       size_t eltlen = strlen (array[i]) + 1;
706       char *new = (char *) malloc (dirlen + 1 + eltlen);
707       if (new == NULL)
708         {
709           while (i > 0)
710             free ((__ptr_t) array[--i]);
711           return 1;
712         }
713
714       memcpy (new, dirname, dirlen);
715       new[dirlen] = '/';
716       memcpy (&new[dirlen + 1], array[i], eltlen);
717       free ((__ptr_t) array[i]);
718       array[i] = new;
719     }
720
721   return 0;
722 }
723
724
725 /* Return nonzero if PATTERN contains any metacharacters.
726    Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
727 static int
728 glob_pattern_p (pattern, quote)
729      const char *pattern;
730      int quote;
731 {
732   register const char *p;
733   int open = 0;
734
735   for (p = pattern; *p != '\0'; ++p)
736     switch (*p)
737       {
738       case '?':
739       case '*':
740         return 1;
741
742       case '\\':
743         if (quote && p[1] != '\0')
744           ++p;
745         break;
746
747       case '[':
748         open = 1;
749         break;
750
751       case ']':
752         if (open)
753           return 1;
754         break;
755       }
756
757   return 0;
758 }
759
760
761 /* Like `glob', but PATTERN is a final pathname component,
762    and matches are searched for in DIRECTORY.
763    The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
764    The GLOB_APPEND flag is assumed to be set (always appends).  */
765 static int
766 glob_in_dir (pattern, directory, flags, errfunc, pglob)
767      const char *pattern;
768      const char *directory;
769      int flags;
770      int (*errfunc) __P ((const char *, int));
771      glob_t *pglob;
772 {
773   __ptr_t stream;
774
775   struct globlink
776     {
777       struct globlink *next;
778       char *name;
779     };
780   struct globlink *names = NULL;
781   size_t nfound = 0;
782
783   if (!glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)))
784     {
785       stream = NULL;
786       flags |= GLOB_NOCHECK;
787     }
788   else
789     {
790       flags |= GLOB_MAGCHAR;
791
792       stream = ((flags & GLOB_ALTDIRFUNC) ?
793                 (*pglob->gl_opendir) (directory) :
794                 (__ptr_t) opendir (directory));
795       if (stream == NULL)
796         {
797           if ((errfunc != NULL && (*errfunc) (directory, errno)) ||
798               (flags & GLOB_ERR))
799             return GLOB_ABEND;
800         }
801       else
802         while (1)
803           {
804             const char *name;
805             size_t len;
806             struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ?
807                                 (*pglob->gl_readdir) (stream) :
808                                 readdir ((DIR *) stream));
809             if (d == NULL)
810               break;
811             if (! REAL_DIR_ENTRY (d))
812               continue;
813
814             name = d->d_name;
815
816             if (fnmatch (pattern, name,
817                          (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) |
818                          ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
819 #ifdef _AMIGA
820                          | FNM_CASEFOLD
821 #endif
822                          ) == 0)
823               {
824                 struct globlink *new
825                   = (struct globlink *) __alloca (sizeof (struct globlink));
826                 len = NAMLEN (d);
827                 new->name
828                   = (char *) malloc (len + 1);
829                 if (new->name == NULL)
830                   goto memory_error;
831                 memcpy ((__ptr_t) new->name, name, len);
832                 new->name[len] = '\0';
833                 new->next = names;
834                 names = new;
835                 ++nfound;
836               }
837           }
838     }
839
840   if (nfound == 0 && (flags & GLOB_NOMAGIC) &&
841       ! glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)))
842     flags |= GLOB_NOCHECK;
843
844   if (nfound == 0 && (flags & GLOB_NOCHECK))
845     {
846       size_t len = strlen (pattern);
847       nfound = 1;
848       names = (struct globlink *) __alloca (sizeof (struct globlink));
849       names->next = NULL;
850       names->name = (char *) malloc (len + 1);
851       if (names->name == NULL)
852         goto memory_error;
853       memcpy (names->name, pattern, len);
854       names->name[len] = '\0';
855     }
856
857   pglob->gl_pathv
858     = (char **) realloc (pglob->gl_pathv,
859                          (pglob->gl_pathc +
860                           ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
861                           nfound + 1) *
862                          sizeof (char *));
863   if (pglob->gl_pathv == NULL)
864     goto memory_error;
865
866   if (flags & GLOB_DOOFFS)
867     while (pglob->gl_pathc < pglob->gl_offs)
868       pglob->gl_pathv[pglob->gl_pathc++] = NULL;
869
870   for (; names != NULL; names = names->next)
871     pglob->gl_pathv[pglob->gl_pathc++] = names->name;
872   pglob->gl_pathv[pglob->gl_pathc] = NULL;
873
874   pglob->gl_flags = flags;
875
876   if (stream != NULL)
877     {
878       int save = errno;
879       if (flags & GLOB_ALTDIRFUNC)
880         (*pglob->gl_closedir) (stream);
881       else
882         closedir ((DIR *) stream);
883       errno = save;
884     }
885   return nfound == 0 ? GLOB_NOMATCH : 0;
886
887  memory_error:
888   {
889     int save = errno;
890     if (flags & GLOB_ALTDIRFUNC)
891       (*pglob->gl_closedir) (stream);
892     else
893       closedir ((DIR *) stream);
894     errno = save;
895   }
896   while (names != NULL)
897     {
898       if (names->name != NULL)
899         free ((__ptr_t) names->name);
900       names = names->next;
901     }
902   return GLOB_NOSPACE;
903 }
904
905 #endif  /* Not ELIDE_CODE.  */
906