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