]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/generic/glob.c
Update.
[thirdparty/glibc.git] / sysdeps / generic / glob.c
CommitLineData
460adbb8 1/* Copyright (C) 1991-1999, 2000 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)
460adbb8
UD
251# ifndef __stat64
252# define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
df777c40 253# endif
460adbb8
UD
254# define HAVE_STAT64 1
255#endif
256
257#ifndef HAVE_STAT64
258# define __stat64(fname, buf) __stat (fname, buf)
259/* This is the variable name we are using. */
260# define st64 st
50304ef0
UD
261#endif
262
61eb22d3
UD
263#if !(defined STDC_HEADERS || defined __GNU_LIBRARY__)
264# undef size_t
265# define size_t unsigned int
28f540f4
RM
266#endif
267
268/* Some system header files erroneously define these.
269 We want our own definitions from <fnmatch.h> to take precedence. */
d47aac39
UD
270#ifndef __GNU_LIBRARY__
271# undef FNM_PATHNAME
272# undef FNM_NOESCAPE
273# undef FNM_PERIOD
274#endif
28f540f4
RM
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. */
a53bad16
UD
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
28f540f4 289#include <glob.h>
722c33bb
UD
290
291#ifdef HAVE_GETLOGIN_R
292extern int getlogin_r __P ((char *, size_t));
293#else
294extern char *getlogin __P ((void));
295#endif
28f540f4 296\f
f41c8091
UD
297static
298#if __GNUC__ - 0 >= 2
299inline
300#endif
301const char *next_brace_sub __P ((const char *begin));
28f540f4
RM
302static int glob_in_dir __P ((const char *pattern, const char *directory,
303 int flags,
df777c40 304 int (*errfunc) (const char *, int),
28f540f4
RM
305 glob_t *pglob));
306static int prefix_array __P ((const char *prefix, char **array, size_t n));
307static int collated_compare __P ((const __ptr_t, const __ptr_t));
308
5ae9d168
UD
309
310/* Find the end of the sub-pattern in a brace expression. We define
311 this as an inline function if the compiler permits. */
312static
313#if __GNUC__ - 0 >= 2
314inline
315#endif
316const char *
ca34d7a7
UD
317next_brace_sub (begin)
318 const char *begin;
5ae9d168
UD
319{
320 unsigned int depth = 0;
321 const char *cp = begin;
322
323 while (1)
324 {
325 if (depth == 0)
326 {
327 if (*cp != ',' && *cp != '}' && *cp != '\0')
328 {
329 if (*cp == '{')
330 ++depth;
331 ++cp;
332 continue;
333 }
334 }
335 else
336 {
337 while (*cp != '\0' && (*cp != '}' || depth > 0))
338 {
339 if (*cp == '}')
e7fd8a39 340 --depth;
5ae9d168
UD
341 ++cp;
342 }
343 if (*cp == '\0')
344 /* An incorrectly terminated brace expression. */
345 return NULL;
346
347 continue;
348 }
349 break;
350 }
351
352 return cp;
353}
354
28f540f4
RM
355/* Do glob searching for PATTERN, placing results in PGLOB.
356 The bits defined above may be set in FLAGS.
357 If a directory cannot be opened or read and ERRFUNC is not nil,
358 it is called with the pathname that caused the error, and the
359 `errno' value from the failing call; if it returns non-zero
714a562f 360 `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
28f540f4
RM
361 If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
362 Otherwise, `glob' returns zero. */
363int
364glob (pattern, flags, errfunc, pglob)
365 const char *pattern;
366 int flags;
367 int (*errfunc) __P ((const char *, int));
368 glob_t *pglob;
369{
370 const char *filename;
ec986e23 371 const char *dirname;
28f540f4
RM
372 size_t dirlen;
373 int status;
374 int oldcount;
375
376 if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
377 {
c4029823 378 __set_errno (EINVAL);
28f540f4
RM
379 return -1;
380 }
381
460adbb8
UD
382 if (!(flags & GLOB_DOOFFS))
383 /* Have to do this so `globfree' knows where to start freeing. It
384 also makes all the code that uses gl_offs simpler. */
385 pglob->gl_offs = 0;
386
787e4db9
RM
387 if (flags & GLOB_BRACE)
388 {
389 const char *begin = strchr (pattern, '{');
390 if (begin != NULL)
391 {
5ae9d168
UD
392 /* Allocate working buffer large enough for our work. Note that
393 we have at least an opening and closing brace. */
6025c399 394 int firstc;
5ae9d168
UD
395 char *alt_start;
396 const char *p;
397 const char *next;
398 const char *rest;
399 size_t rest_len;
400#ifdef __GNUC__
401 char onealt[strlen (pattern) - 1];
402#else
403 char *onealt = (char *) malloc (strlen (pattern) - 1);
404 if (onealt == NULL)
405 {
406 if (!(flags & GLOB_APPEND))
407 globfree (pglob);
408 return GLOB_NOSPACE;
409 }
410#endif
411
412 /* We know the prefix for all sub-patterns. */
86187531
UD
413#ifdef HAVE_MEMPCPY
414 alt_start = mempcpy (onealt, pattern, begin - pattern);
415#else
5ae9d168
UD
416 memcpy (onealt, pattern, begin - pattern);
417 alt_start = &onealt[begin - pattern];
86187531 418#endif
5ae9d168
UD
419
420 /* Find the first sub-pattern and at the same time find the
421 rest after the closing brace. */
422 next = next_brace_sub (begin + 1);
423 if (next == NULL)
787e4db9 424 {
5ae9d168
UD
425 /* It is an illegal expression. */
426#ifndef __GNUC__
427 free (onealt);
428#endif
429 return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
430 }
431
432 /* Now find the end of the whole brace expression. */
433 rest = next;
434 while (*rest != '}')
435 {
436 rest = next_brace_sub (rest + 1);
437 if (rest == NULL)
787e4db9 438 {
5ae9d168
UD
439 /* It is an illegal expression. */
440#ifndef __GNUC__
441 free (onealt);
442#endif
443 return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
6025c399 444 }
6025c399 445 }
5ae9d168
UD
446 /* Please note that we now can be sure the brace expression
447 is well-formed. */
448 rest_len = strlen (++rest) + 1;
6025c399
RM
449
450 /* We have a brace expression. BEGIN points to the opening {,
451 NEXT points past the terminator of the first element, and END
452 points past the final }. We will accumulate result names from
453 recursive runs for each brace alternative in the buffer using
454 GLOB_APPEND. */
455
456 if (!(flags & GLOB_APPEND))
457 {
458 /* This call is to set a new vector, so clear out the
459 vector so we can append to it. */
460 pglob->gl_pathc = 0;
461 pglob->gl_pathv = NULL;
462 }
463 firstc = pglob->gl_pathc;
464
6025c399
RM
465 p = begin + 1;
466 while (1)
467 {
6025c399 468 int result;
5ae9d168
UD
469
470 /* Construct the new glob expression. */
dd7d45e8
UD
471#ifdef HAVE_MEMPCPY
472 mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
473#else
5ae9d168
UD
474 memcpy (alt_start, p, next - p);
475 memcpy (&alt_start[next - p], rest, rest_len);
dd7d45e8 476#endif
5ae9d168 477
6025c399 478 result = glob (onealt,
5ae9d168
UD
479 ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC))
480 | GLOB_APPEND), errfunc, pglob);
6025c399
RM
481
482 /* If we got an error, return it. */
483 if (result && result != GLOB_NOMATCH)
787e4db9 484 {
5ae9d168
UD
485#ifndef __GNUC__
486 free (onealt);
487#endif
6025c399
RM
488 if (!(flags & GLOB_APPEND))
489 globfree (pglob);
490 return result;
491 }
492
5ae9d168
UD
493 if (*next == '}')
494 /* We saw the last entry. */
495 break;
496
497 p = next + 1;
498 next = next_brace_sub (p);
499 assert (next != NULL);
787e4db9 500 }
6025c399 501
5ae9d168
UD
502#ifndef __GNUC__
503 free (onealt);
504#endif
505
506 if (pglob->gl_pathc != firstc)
507 /* We found some entries. */
508 return 0;
509 else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
6025c399 510 return GLOB_NOMATCH;
787e4db9
RM
511 }
512 }
513
28f540f4
RM
514 /* Find the filename. */
515 filename = strrchr (pattern, '/');
786a5421
UD
516#if defined __MSDOS__ || defined WINDOWS32
517 /* The case of "d:pattern". Since `:' is not allowed in
518 file names, we can safely assume that wherever it
519 happens in pattern, it signals the filename part. This
520 is so we could some day support patterns like "[a-z]:foo". */
521 if (filename == NULL)
522 filename = strchr (pattern, ':');
523#endif /* __MSDOS__ || WINDOWS32 */
28f540f4
RM
524 if (filename == NULL)
525 {
49c091e5 526 /* This can mean two things: a simple name or "~name". The latter
6c202c68 527 case is nothing but a notation for a directory. */
1bc21e7a 528 if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
6c202c68 529 {
7cabd57c 530 dirname = pattern;
6c202c68
UD
531 dirlen = strlen (pattern);
532
c9243dac 533 /* Set FILENAME to NULL as a special flag. This is ugly but
786a5421 534 other solutions would require much more code. We test for
c9243dac
UD
535 this special case below. */
536 filename = NULL;
6c202c68
UD
537 }
538 else
539 {
540 filename = pattern;
9fb16eea 541#ifdef _AMIGA
ec986e23 542 dirname = "";
9fb16eea 543#else
ec986e23 544 dirname = ".";
9fb16eea 545#endif
6c202c68
UD
546 dirlen = 0;
547 }
28f540f4
RM
548 }
549 else if (filename == pattern)
550 {
551 /* "/pattern". */
ec986e23 552 dirname = "/";
28f540f4
RM
553 dirlen = 1;
554 ++filename;
555 }
556 else
557 {
ec986e23 558 char *newp;
28f540f4 559 dirlen = filename - pattern;
786a5421
UD
560#if defined __MSDOS__ || defined WINDOWS32
561 if (*filename == ':'
562 || (filename > pattern + 1 && filename[-1] == ':'))
563 {
564 char *drive_spec;
565
566 ++dirlen;
567 drive_spec = (char *) __alloca (dirlen + 1);
568#ifdef HAVE_MEMPCPY
569 *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
570#else
571 memcpy (drive_spec, pattern, dirlen);
572 drive_spec[dirlen] = '\0';
573#endif
574 /* For now, disallow wildcards in the drive spec, to
575 prevent infinite recursion in glob. */
576 if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
577 return GLOB_NOMATCH;
578 /* If this is "d:pattern", we need to copy `:' to DIRNAME
579 as well. If it's "d:/pattern", don't remove the slash
580 from "d:/", since "d:" and "d:/" are not the same.*/
581 }
582#endif
ec986e23 583 newp = (char *) __alloca (dirlen + 1);
dd7d45e8 584#ifdef HAVE_MEMPCPY
ec986e23 585 *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
dd7d45e8 586#else
ec986e23
UD
587 memcpy (newp, pattern, dirlen);
588 newp[dirlen] = '\0';
dd7d45e8 589#endif
ec986e23 590 dirname = newp;
28f540f4 591 ++filename;
28f540f4 592
786a5421
UD
593 if (filename[0] == '\0'
594#if defined __MSDOS__ || defined WINDOWS32
595 && dirname[dirlen - 1] != ':'
596 && (dirlen < 3 || dirname[dirlen - 2] != ':'
597 || dirname[dirlen - 1] != '/')
598#endif
599 && dirlen > 1)
6c202c68
UD
600 /* "pattern/". Expand "pattern", appending slashes. */
601 {
602 int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
603 if (val == 0)
604 pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
605 | (flags & GLOB_MARK));
606 return val;
607 }
28f540f4
RM
608 }
609
610 if (!(flags & GLOB_APPEND))
611 {
612 pglob->gl_pathc = 0;
460adbb8
UD
613 if (!(flags & GLOB_DOOFFS))
614 pglob->gl_pathv = NULL;
615 else
616 {
617 int i;
618 pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
619 * sizeof (char *));
620 if (pglob->gl_pathv == NULL)
621 return GLOB_NOSPACE;
622
623 for (i = 0; i <= pglob->gl_offs; ++i)
624 pglob->gl_pathv[i] = NULL;
625 }
28f540f4
RM
626 }
627
460adbb8 628 oldcount = pglob->gl_pathc + pglob->gl_offs;
28f540f4 629
0efef8fc 630#ifndef VMS
1bc21e7a 631 if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
787e4db9 632 {
5ae9d168 633 if (dirname[1] == '\0' || dirname[1] == '/')
787e4db9
RM
634 {
635 /* Look up home directory. */
ec986e23 636 const char *home_dir = getenv ("HOME");
61eb22d3 637# ifdef _AMIGA
5ae9d168
UD
638 if (home_dir == NULL || home_dir[0] == '\0')
639 home_dir = "SYS:";
61eb22d3
UD
640# else
641# ifdef WINDOWS32
5ae9d168
UD
642 if (home_dir == NULL || home_dir[0] == '\0')
643 home_dir = "c:/users/default"; /* poor default */
61eb22d3 644# else
5ae9d168 645 if (home_dir == NULL || home_dir[0] == '\0')
787e4db9 646 {
e4cf5070 647 int success;
ec986e23 648 char *name;
61eb22d3 649# if defined HAVE_GETLOGIN_R || defined _LIBC
e4cf5070 650 size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;
e4cf5070
UD
651
652 if (buflen == 0)
653 /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try
654 a moderate value. */
ec986e23 655 buflen = 20;
ca34d7a7 656 name = (char *) __alloca (buflen);
e4cf5070
UD
657
658 success = getlogin_r (name, buflen) >= 0;
61eb22d3 659# else
e4cf5070 660 success = (name = getlogin ()) != NULL;
61eb22d3 661# endif
e4cf5070 662 if (success)
787e4db9 663 {
ec986e23 664 struct passwd *p;
61eb22d3 665# if defined HAVE_GETPWNAM_R || defined _LIBC
e4cf5070
UD
666 size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
667 char *pwtmpbuf;
ec986e23 668 struct passwd pwbuf;
13f2ac59 669 int save = errno;
e4cf5070 670
ec986e23
UD
671 if (pwbuflen == -1)
672 /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
673 Try a moderate value. */
674 pwbuflen = 1024;
ca34d7a7 675 pwtmpbuf = (char *) __alloca (pwbuflen);
e4cf5070 676
738d1a5a
UD
677 while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
678 != 0)
f6b56b55
UD
679 {
680 if (errno != ERANGE)
681 {
1d863dc0 682 p = NULL;
f6b56b55
UD
683 break;
684 }
685 pwbuflen *= 2;
686 pwtmpbuf = (char *) __alloca (pwbuflen);
13f2ac59 687 __set_errno (save);
f6b56b55 688 }
61eb22d3 689# else
ec986e23 690 p = getpwnam (name);
61eb22d3 691# endif
1d863dc0 692 if (p != NULL)
5ae9d168 693 home_dir = p->pw_dir;
787e4db9
RM
694 }
695 }
5ae9d168 696 if (home_dir == NULL || home_dir[0] == '\0')
6e4c40ba
UD
697 {
698 if (flags & GLOB_TILDE_CHECK)
699 return GLOB_NOMATCH;
700 else
701 home_dir = "~"; /* No luck. */
702 }
61eb22d3
UD
703# endif /* WINDOWS32 */
704# endif
5ae9d168
UD
705 /* Now construct the full directory. */
706 if (dirname[1] == '\0')
707 dirname = home_dir;
708 else
709 {
710 char *newp;
711 size_t home_len = strlen (home_dir);
ca34d7a7 712 newp = (char *) __alloca (home_len + dirlen);
dd7d45e8
UD
713# ifdef HAVE_MEMPCPY
714 mempcpy (mempcpy (newp, home_dir, home_len),
715 &dirname[1], dirlen);
716# else
5ae9d168
UD
717 memcpy (newp, home_dir, home_len);
718 memcpy (&newp[home_len], &dirname[1], dirlen);
dd7d45e8 719# endif
5ae9d168
UD
720 dirname = newp;
721 }
787e4db9 722 }
61eb22d3 723# if !defined _AMIGA && !defined WINDOWS32
787e4db9
RM
724 else
725 {
5ae9d168 726 char *end_name = strchr (dirname, '/');
ec986e23
UD
727 const char *user_name;
728 const char *home_dir;
5ae9d168
UD
729
730 if (end_name == NULL)
731 user_name = dirname + 1;
732 else
733 {
ec986e23
UD
734 char *newp;
735 newp = (char *) __alloca (end_name - dirname);
dd7d45e8 736# ifdef HAVE_MEMPCPY
ec986e23 737 *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
dd7d45e8
UD
738 = '\0';
739# else
ec986e23
UD
740 memcpy (newp, dirname + 1, end_name - dirname);
741 newp[end_name - dirname - 1] = '\0';
dd7d45e8 742# endif
ec986e23 743 user_name = newp;
5ae9d168
UD
744 }
745
787e4db9 746 /* Look up specific user's home directory. */
5ae9d168 747 {
ec986e23 748 struct passwd *p;
61eb22d3 749# if defined HAVE_GETPWNAM_R || defined _LIBC
5ae9d168 750 size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
ec986e23
UD
751 char *pwtmpbuf;
752 struct passwd pwbuf;
13f2ac59 753 int save = errno;
ec986e23
UD
754
755 if (buflen == -1)
756 /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a
757 moderate value. */
758 buflen = 1024;
759 pwtmpbuf = (char *) __alloca (buflen);
760
738d1a5a 761 while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
f6b56b55
UD
762 {
763 if (errno != ERANGE)
764 {
765 p = NULL;
766 break;
767 }
13f2ac59
UD
768 buflen *= 2;
769 pwtmpbuf = __alloca (buflen);
770 __set_errno (save);
f6b56b55 771 }
61eb22d3 772# else
ec986e23 773 p = getpwnam (user_name);
f6b56b55 774# endif
5ae9d168
UD
775 if (p != NULL)
776 home_dir = p->pw_dir;
777 else
778 home_dir = NULL;
5ae9d168
UD
779 }
780 /* If we found a home directory use this. */
781 if (home_dir != NULL)
782 {
783 char *newp;
784 size_t home_len = strlen (home_dir);
785 size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
ca34d7a7 786 newp = (char *) __alloca (home_len + rest_len + 1);
dd7d45e8
UD
787# ifdef HAVE_MEMPCPY
788 *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
789 end_name, rest_len)) = '\0';
790# else
5ae9d168
UD
791 memcpy (newp, home_dir, home_len);
792 memcpy (&newp[home_len], end_name, rest_len);
793 newp[home_len + rest_len] = '\0';
dd7d45e8 794# endif
5ae9d168
UD
795 dirname = newp;
796 }
1bc21e7a
UD
797 else
798 if (flags & GLOB_TILDE_CHECK)
799 /* We have to regard it as an error if we cannot find the
800 home directory. */
801 return GLOB_NOMATCH;
787e4db9 802 }
61eb22d3 803# endif /* Not Amiga && not WINDOWS32. */
787e4db9 804 }
0efef8fc 805#endif /* Not VMS. */
787e4db9 806
c9243dac
UD
807 /* Now test whether we looked for "~" or "~NAME". In this case we
808 can give the answer now. */
809 if (filename == NULL)
810 {
811 struct stat st;
460adbb8
UD
812#ifdef HAVE_STAT64
813 struct stat64 st64;
814#endif
c9243dac
UD
815
816 /* Return the directory if we don't check for error or if it exists. */
817 if ((flags & GLOB_NOCHECK)
818 || (((flags & GLOB_ALTDIRFUNC)
460adbb8
UD
819 ? ((*pglob->gl_stat) (dirname, &st) == 0
820 && S_ISDIR (st.st_mode))
821 : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode)))))
c9243dac 822 {
460adbb8
UD
823 int newcount = pglob->gl_pathc + pglob->gl_offs;
824
c9243dac
UD
825 pglob->gl_pathv
826 = (char **) realloc (pglob->gl_pathv,
460adbb8 827 (newcount + 1 + 1) * sizeof (char *));
c9243dac
UD
828 if (pglob->gl_pathv == NULL)
829 return GLOB_NOSPACE;
830
c9243dac 831#if defined HAVE_STRDUP || defined _LIBC
460adbb8 832 pglob->gl_pathv[newcount] = strdup (dirname);
c9243dac
UD
833#else
834 {
835 size_t len = strlen (dirname) + 1;
836 char *dircopy = malloc (len);
837 if (dircopy != NULL)
460adbb8 838 pglob->gl_pathv[newcount] = memcpy (dircopy, dirname, len);
c9243dac
UD
839 }
840#endif
460adbb8 841 if (pglob->gl_pathv[newcount] == NULL)
c9243dac
UD
842 {
843 free (pglob->gl_pathv);
844 return GLOB_NOSPACE;
845 }
460adbb8
UD
846 pglob->gl_pathv[++newcount] = NULL;
847 ++pglob->gl_pathc;
c9243dac
UD
848 pglob->gl_flags = flags;
849
850 return 0;
851 }
852
853 /* Not found. */
854 return GLOB_NOMATCH;
855 }
856
e7fd8a39 857 if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
28f540f4
RM
858 {
859 /* The directory name contains metacharacters, so we
860 have to glob for the directory, and then glob for
861 the pattern in each directory found. */
862 glob_t dirs;
863 register int i;
864
29332175
UD
865 if ((flags & GLOB_ALTDIRFUNC) != 0)
866 {
867 /* Use the alternative access functions also in the recursive
868 call. */
869 dirs.gl_opendir = pglob->gl_opendir;
870 dirs.gl_readdir = pglob->gl_readdir;
871 dirs.gl_closedir = pglob->gl_closedir;
872 dirs.gl_stat = pglob->gl_stat;
873 dirs.gl_lstat = pglob->gl_lstat;
874 }
875
28f540f4 876 status = glob (dirname,
29332175
UD
877 ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE
878 | GLOB_ALTDIRFUNC))
1cab5444 879 | GLOB_NOSORT | GLOB_ONLYDIR),
28f540f4
RM
880 errfunc, &dirs);
881 if (status != 0)
882 return status;
883
884 /* We have successfully globbed the preceding directory name.
885 For each name we found, call glob_in_dir on it and FILENAME,
886 appending the results to PGLOB. */
887 for (i = 0; i < dirs.gl_pathc; ++i)
888 {
cc60175e 889 int old_pathc;
28f540f4
RM
890
891#ifdef SHELL
892 {
893 /* Make globbing interruptible in the bash shell. */
894 extern int interrupt_state;
895
896 if (interrupt_state)
897 {
898 globfree (&dirs);
899 globfree (&files);
714a562f 900 return GLOB_ABORTED;
28f540f4
RM
901 }
902 }
903#endif /* SHELL. */
904
cc60175e 905 old_pathc = pglob->gl_pathc;
28f540f4 906 status = glob_in_dir (filename, dirs.gl_pathv[i],
460adbb8 907 ((flags | GLOB_APPEND) & ~GLOB_NOCHECK),
28f540f4
RM
908 errfunc, pglob);
909 if (status == GLOB_NOMATCH)
910 /* No matches in this directory. Try the next. */
911 continue;
912
913 if (status != 0)
914 {
915 globfree (&dirs);
916 globfree (pglob);
917 return status;
918 }
919
920 /* Stick the directory on the front of each name. */
921 if (prefix_array (dirs.gl_pathv[i],
460adbb8 922 &pglob->gl_pathv[old_pathc + pglob->gl_offs],
cc60175e 923 pglob->gl_pathc - old_pathc))
28f540f4
RM
924 {
925 globfree (&dirs);
926 globfree (pglob);
927 return GLOB_NOSPACE;
928 }
929 }
930
931 flags |= GLOB_MAGCHAR;
932
e852e889 933 /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
460adbb8 934 But if we have not found any matching entry and the GLOB_NOCHECK
e852e889
UD
935 flag was set we must return the list consisting of the disrectory
936 names followed by the filename. */
460adbb8 937 if (pglob->gl_pathc + pglob->gl_offs == oldcount)
6e4c40ba
UD
938 {
939 /* No matches. */
940 if (flags & GLOB_NOCHECK)
941 {
942 size_t filename_len = strlen (filename) + 1;
943 char **new_pathv;
460adbb8 944 int newcount = pglob->gl_pathc + pglob->gl_offs;
6e4c40ba 945 struct stat st;
460adbb8
UD
946#ifdef HAVE_STAT64
947 struct stat64 st64;
948#endif
6e4c40ba
UD
949
950 /* This is an pessimistic guess about the size. */
951 pglob->gl_pathv
952 = (char **) realloc (pglob->gl_pathv,
460adbb8
UD
953 (newcount + dirs.gl_pathc + 1)
954 * sizeof (char *));
6e4c40ba
UD
955 if (pglob->gl_pathv == NULL)
956 {
957 globfree (&dirs);
958 return GLOB_NOSPACE;
959 }
28f540f4 960
6e4c40ba
UD
961 for (i = 0; i < dirs.gl_pathc; ++i)
962 {
963 const char *dir = dirs.gl_pathv[i];
964 size_t dir_len = strlen (dir);
965
966 /* First check whether this really is a directory. */
967 if (((flags & GLOB_ALTDIRFUNC)
460adbb8
UD
968 ? ((*pglob->gl_stat) (dir, &st) != 0
969 || !S_ISDIR (st.st_mode))
970 : (__stat64 (dir, &st64) != 0
971 || !S_ISDIR (st64.st_mode))))
6e4c40ba
UD
972 /* No directory, ignore this entry. */
973 continue;
974
460adbb8
UD
975 pglob->gl_pathv[newcount] = malloc (dir_len + 1
976 + filename_len);
977 if (pglob->gl_pathv[newcount] == NULL)
6e4c40ba
UD
978 {
979 globfree (&dirs);
980 globfree (pglob);
981 return GLOB_NOSPACE;
982 }
e852e889
UD
983
984#ifdef HAVE_MEMPCPY
460adbb8 985 mempcpy (mempcpy (mempcpy (pglob->gl_pathv[newcount],
6e4c40ba
UD
986 dir, dir_len),
987 "/", 1),
988 filename, filename_len);
e852e889 989#else
460adbb8
UD
990 memcpy (pglob->gl_pathv[newcount], dir, dir_len);
991 pglob->gl_pathv[newcount][dir_len] = '/';
992 memcpy (&pglob->gl_pathv[newcount][dir_len + 1],
6e4c40ba 993 filename, filename_len);
e852e889 994#endif
6e4c40ba 995 ++pglob->gl_pathc;
460adbb8 996 ++newcount;
6e4c40ba 997 }
e852e889 998
460adbb8 999 pglob->gl_pathv[newcount] = NULL;
6e4c40ba 1000 pglob->gl_flags = flags;
e852e889 1001
6e4c40ba
UD
1002 /* Now we know how large the gl_pathv vector must be. */
1003 new_pathv = (char **) realloc (pglob->gl_pathv,
460adbb8 1004 ((newcount + 1)
6e4c40ba
UD
1005 * sizeof (char *)));
1006 if (new_pathv != NULL)
1007 pglob->gl_pathv = new_pathv;
1008 }
1009 else
1010 return GLOB_NOMATCH;
1011 }
e852e889
UD
1012
1013 globfree (&dirs);
28f540f4
RM
1014 }
1015 else
1016 {
460adbb8
UD
1017 int old_pathc = pglob->gl_pathc;
1018
28f540f4
RM
1019 status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
1020 if (status != 0)
1021 return status;
1022
1023 if (dirlen > 0)
1024 {
1025 /* Stick the directory on the front of each name. */
1026 if (prefix_array (dirname,
460adbb8
UD
1027 &pglob->gl_pathv[old_pathc + pglob->gl_offs],
1028 pglob->gl_pathc - old_pathc))
28f540f4
RM
1029 {
1030 globfree (pglob);
1031 return GLOB_NOSPACE;
1032 }
1033 }
1034 }
1035
bf3ccd1a
RM
1036 if (flags & GLOB_MARK)
1037 {
c043db7a 1038 /* Append slashes to directory names. */
bf3ccd1a
RM
1039 int i;
1040 struct stat st;
460adbb8
UD
1041#ifdef HAVE_STAT64
1042 struct stat64 st64;
1043#endif
1044
1045 for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i)
a9ddb793 1046 if (((flags & GLOB_ALTDIRFUNC)
460adbb8
UD
1047 ? ((*pglob->gl_stat) (pglob->gl_pathv[i], &st) == 0
1048 && S_ISDIR (st.st_mode))
1049 : (__stat64 (pglob->gl_pathv[i], &st64) == 0
1050 && S_ISDIR (st64.st_mode))))
a993273c
RM
1051 {
1052 size_t len = strlen (pglob->gl_pathv[i]) + 2;
1053 char *new = realloc (pglob->gl_pathv[i], len);
1054 if (new == NULL)
1055 {
1056 globfree (pglob);
1057 return GLOB_NOSPACE;
1058 }
1059 strcpy (&new[len - 2], "/");
1060 pglob->gl_pathv[i] = new;
1061 }
bf3ccd1a
RM
1062 }
1063
28f540f4 1064 if (!(flags & GLOB_NOSORT))
cc60175e
UD
1065 {
1066 /* Sort the vector. */
460adbb8
UD
1067 qsort ((__ptr_t) &pglob->gl_pathv[oldcount],
1068 pglob->gl_pathc + pglob->gl_offs - oldcount,
cc60175e
UD
1069 sizeof (char *), collated_compare);
1070 }
28f540f4
RM
1071
1072 return 0;
1073}
1074
1075
1076/* Free storage allocated in PGLOB by a previous `glob' call. */
1077void
1078globfree (pglob)
1079 register glob_t *pglob;
1080{
1081 if (pglob->gl_pathv != NULL)
1082 {
1083 register int i;
1084 for (i = 0; i < pglob->gl_pathc; ++i)
460adbb8
UD
1085 if (pglob->gl_pathv[pglob->gl_offs + i] != NULL)
1086 free ((__ptr_t) pglob->gl_pathv[pglob->gl_offs + i]);
28f540f4
RM
1087 free ((__ptr_t) pglob->gl_pathv);
1088 }
1089}
1090
1091
1092/* Do a collated comparison of A and B. */
1093static int
1094collated_compare (a, b)
1095 const __ptr_t a;
1096 const __ptr_t b;
1097{
1098 const char *const s1 = *(const char *const * const) a;
1099 const char *const s2 = *(const char *const * const) b;
1100
1101 if (s1 == s2)
1102 return 0;
1103 if (s1 == NULL)
1104 return 1;
1105 if (s2 == NULL)
1106 return -1;
1107 return strcoll (s1, s2);
1108}
1109
1110
1111/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
1112 elements in place. Return nonzero if out of memory, zero if successful.
1113 A slash is inserted between DIRNAME and each elt of ARRAY,
1114 unless DIRNAME is just "/". Each old element of ARRAY is freed. */
1115static int
1116prefix_array (dirname, array, n)
1117 const char *dirname;
1118 char **array;
1119 size_t n;
1120{
1121 register size_t i;
1122 size_t dirlen = strlen (dirname);
786a5421
UD
1123#if defined __MSDOS__ || defined WINDOWS32
1124 int sep_char = '/';
1125# define DIRSEP_CHAR sep_char
1126#else
1127# define DIRSEP_CHAR '/'
1128#endif
28f540f4
RM
1129
1130 if (dirlen == 1 && dirname[0] == '/')
1131 /* DIRNAME is just "/", so normal prepending would get us "//foo".
1132 We want "/foo" instead, so don't prepend any chars from DIRNAME. */
1133 dirlen = 0;
786a5421
UD
1134#if defined __MSDOS__ || defined WINDOWS32
1135 else if (dirlen > 1)
1136 {
ea1bfb07 1137 if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
786a5421
UD
1138 /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */
1139 --dirlen;
1140 else if (dirname[dirlen - 1] == ':')
1141 {
1142 /* DIRNAME is "d:". Use `:' instead of `/'. */
1143 --dirlen;
1144 sep_char = ':';
1145 }
1146 }
1147#endif
28f540f4
RM
1148
1149 for (i = 0; i < n; ++i)
1150 {
1151 size_t eltlen = strlen (array[i]) + 1;
1152 char *new = (char *) malloc (dirlen + 1 + eltlen);
1153 if (new == NULL)
1154 {
1155 while (i > 0)
1156 free ((__ptr_t) array[--i]);
1157 return 1;
1158 }
1159
dd7d45e8
UD
1160#ifdef HAVE_MEMPCPY
1161 {
1162 char *endp = (char *) mempcpy (new, dirname, dirlen);
786a5421 1163 *endp++ = DIRSEP_CHAR;
dd7d45e8
UD
1164 mempcpy (endp, array[i], eltlen);
1165 }
1166#else
28f540f4 1167 memcpy (new, dirname, dirlen);
786a5421 1168 new[dirlen] = DIRSEP_CHAR;
28f540f4 1169 memcpy (&new[dirlen + 1], array[i], eltlen);
dd7d45e8 1170#endif
28f540f4
RM
1171 free ((__ptr_t) array[i]);
1172 array[i] = new;
1173 }
1174
1175 return 0;
1176}
1177
1178
a5f4e34a 1179/* We must not compile this function twice. */
1f539fd1 1180#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
28f540f4
RM
1181/* Return nonzero if PATTERN contains any metacharacters.
1182 Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
e7fd8a39
UD
1183int
1184__glob_pattern_p (pattern, quote)
28f540f4
RM
1185 const char *pattern;
1186 int quote;
1187{
1188 register const char *p;
1189 int open = 0;
1190
1191 for (p = pattern; *p != '\0'; ++p)
1192 switch (*p)
1193 {
1194 case '?':
1195 case '*':
1196 return 1;
1197
1198 case '\\':
299a95b9 1199 if (quote && p[1] != '\0')
28f540f4
RM
1200 ++p;
1201 break;
1202
1203 case '[':
1204 open = 1;
1205 break;
1206
1207 case ']':
1208 if (open)
1209 return 1;
1210 break;
1211 }
1212
1213 return 0;
1214}
a5f4e34a 1215# ifdef _LIBC
e7fd8a39 1216weak_alias (__glob_pattern_p, glob_pattern_p)
a5f4e34a 1217# endif
e7fd8a39 1218#endif
28f540f4
RM
1219
1220
1221/* Like `glob', but PATTERN is a final pathname component,
1222 and matches are searched for in DIRECTORY.
1223 The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
1224 The GLOB_APPEND flag is assumed to be set (always appends). */
1225static int
1226glob_in_dir (pattern, directory, flags, errfunc, pglob)
1227 const char *pattern;
1228 const char *directory;
1229 int flags;
1230 int (*errfunc) __P ((const char *, int));
1231 glob_t *pglob;
1232{
a9ddb793 1233 __ptr_t stream = NULL;
28f540f4
RM
1234 struct globlink
1235 {
1236 struct globlink *next;
1237 char *name;
1238 };
1239 struct globlink *names = NULL;
86187531
UD
1240 size_t nfound;
1241 int meta;
1242 int save;
1243
a9ddb793 1244 meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
460adbb8 1245 if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
28f540f4 1246 {
460adbb8
UD
1247 /* We need not do any tests. The PATTERN contains no meta
1248 characters and we must not return an error therefore the
1249 result will always contain exactly one name. */
1250 flags |= GLOB_NOCHECK;
1251 nfound = 0;
1252 }
1253 else if (meta == 0 &&
1254 ((flags & GLOB_NOESCAPE) || strchr(pattern, '\\') == NULL))
1255 {
1256 /* Since we use the normal file functions we can also use stat()
1257 to verify the file is there. */
1258 struct stat st;
1259# ifdef HAVE_STAT64
1260 struct stat64 st64;
1261# endif
1262 size_t patlen = strlen (pattern);
1263 size_t dirlen = strlen (directory);
1264 char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
a9ddb793
UD
1265
1266# ifdef HAVE_MEMPCPY
460adbb8
UD
1267 mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
1268 "/", 1),
1269 pattern, patlen + 1);
a9ddb793 1270# else
460adbb8
UD
1271 memcpy (fullname, directory, dirlen);
1272 fullname[dirlen] = '/';
1273 memcpy (&fullname[dirlen + 1], pattern, patlen + 1);
a9ddb793 1274# endif
460adbb8
UD
1275 if (((flags & GLOB_ALTDIRFUNC)
1276 ? (*pglob->gl_stat) (fullname, &st)
1277 : __stat64 (fullname, &st64)) == 0)
1278 /* We found this file to be existing. Now tell the rest
1279 of the function to copy this name into the result. */
1280 flags |= GLOB_NOCHECK;
a9ddb793 1281
86187531 1282 nfound = 0;
28f540f4
RM
1283 }
1284 else
1285 {
a9ddb793 1286 if (pattern[0] == '\0')
28f540f4 1287 {
a9ddb793
UD
1288 /* This is a special case for matching directories like in
1289 "*a/". */
1290 names = (struct globlink *) __alloca (sizeof (struct globlink));
1291 names->name = (char *) malloc (1);
1292 if (names->name == NULL)
1293 goto memory_error;
1294 names->name[0] = '\0';
1295 names->next = NULL;
1296 nfound = 1;
1297 meta = 0;
1298 }
1299 else
1300 {
1301 stream = ((flags & GLOB_ALTDIRFUNC)
1302 ? (*pglob->gl_opendir) (directory)
1303 : (__ptr_t) opendir (directory));
1304 if (stream == NULL)
1305 {
64736128
UD
1306 if (errno != ENOTDIR
1307 && ((errfunc != NULL && (*errfunc) (directory, errno))
1308 || (flags & GLOB_ERR)))
a9ddb793
UD
1309 return GLOB_ABORTED;
1310 nfound = 0;
1311 meta = 0;
1312 }
1313 else
1314 {
1315 int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
1316 | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
1317#if defined _AMIGA || defined VMS
1318 | FNM_CASEFOLD
1319#endif
1320 );
1321 nfound = 0;
1322 flags |= GLOB_MAGCHAR;
1323
1324 while (1)
1325 {
1326 const char *name;
1327 size_t len;
1328 struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
1329 ? (*pglob->gl_readdir) (stream)
1330 : readdir ((DIR *) stream));
1331 if (d == NULL)
1332 break;
1333 if (! REAL_DIR_ENTRY (d))
1334 continue;
787e4db9 1335
1cab5444 1336#ifdef HAVE_D_TYPE
a9ddb793
UD
1337 /* If we shall match only directories use the information
1338 provided by the dirent call if possible. */
1339 if ((flags & GLOB_ONLYDIR)
1340 && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
1341 continue;
1cab5444
UD
1342#endif
1343
a9ddb793 1344 name = d->d_name;
86187531 1345
a9ddb793
UD
1346 if (fnmatch (pattern, name, fnm_flags) == 0)
1347 {
1348 struct globlink *new = (struct globlink *)
1349 __alloca (sizeof (struct globlink));
1350 len = NAMLEN (d);
1351 new->name = (char *) malloc (len + 1);
1352 if (new->name == NULL)
1353 goto memory_error;
dd7d45e8 1354#ifdef HAVE_MEMPCPY
a9ddb793
UD
1355 *((char *) mempcpy ((__ptr_t) new->name, name, len))
1356 = '\0';
dd7d45e8 1357#else
a9ddb793
UD
1358 memcpy ((__ptr_t) new->name, name, len);
1359 new->name[len] = '\0';
dd7d45e8 1360#endif
a9ddb793
UD
1361 new->next = names;
1362 names = new;
1363 ++nfound;
1364 }
1365 }
86187531
UD
1366 }
1367 }
28f540f4
RM
1368 }
1369
1370 if (nfound == 0 && (flags & GLOB_NOCHECK))
1371 {
1372 size_t len = strlen (pattern);
1373 nfound = 1;
1374 names = (struct globlink *) __alloca (sizeof (struct globlink));
1375 names->next = NULL;
a993273c 1376 names->name = (char *) malloc (len + 1);
28f540f4
RM
1377 if (names->name == NULL)
1378 goto memory_error;
dd7d45e8
UD
1379#ifdef HAVE_MEMPCPY
1380 *((char *) mempcpy (names->name, pattern, len)) = '\0';
1381#else
28f540f4 1382 memcpy (names->name, pattern, len);
28f540f4 1383 names->name[len] = '\0';
dd7d45e8 1384#endif
28f540f4
RM
1385 }
1386
61eb22d3
UD
1387 if (nfound != 0)
1388 {
1389 pglob->gl_pathv
1390 = (char **) realloc (pglob->gl_pathv,
460adbb8
UD
1391 (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
1392 * sizeof (char *));
61eb22d3
UD
1393 if (pglob->gl_pathv == NULL)
1394 goto memory_error;
28f540f4 1395
61eb22d3 1396 for (; names != NULL; names = names->next)
460adbb8
UD
1397 pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc++] = names->name;
1398 pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
28f540f4 1399
61eb22d3
UD
1400 pglob->gl_flags = flags;
1401 }
28f540f4 1402
86187531 1403 save = errno;
a9ddb793 1404 if (stream != NULL)
6e4c40ba
UD
1405 {
1406 if (flags & GLOB_ALTDIRFUNC)
1407 (*pglob->gl_closedir) (stream);
1408 else
1409 closedir ((DIR *) stream);
1410 }
86187531
UD
1411 __set_errno (save);
1412
28f540f4
RM
1413 return nfound == 0 ? GLOB_NOMATCH : 0;
1414
1415 memory_error:
1416 {
1417 int save = errno;
787e4db9
RM
1418 if (flags & GLOB_ALTDIRFUNC)
1419 (*pglob->gl_closedir) (stream);
28f540f4 1420 else
faf92f2a 1421 closedir ((DIR *) stream);
c4029823 1422 __set_errno (save);
28f540f4
RM
1423 }
1424 while (names != NULL)
1425 {
1426 if (names->name != NULL)
1427 free ((__ptr_t) names->name);
1428 names = names->next;
1429 }
1430 return GLOB_NOSPACE;
1431}
1432
787e4db9 1433#endif /* Not ELIDE_CODE. */