]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/generic/glob.c
Update.
[thirdparty/glibc.git] / sysdeps / generic / glob.c
CommitLineData
fb973e7f 1/* Copyright (C) 1991,92,93,94,95,96,97,98 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
180# define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len)
181#endif
182
28f540f4
RM
183
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
UD
242#ifdef _LIBC
243# define sysconf(id) __sysconf (id)
244# define closedir(dir) __closedir (dir)
245# define opendir(name) __opendir (name)
246# define readdir(str) __readdir (str)
247#endif
248
61eb22d3
UD
249#if !(defined STDC_HEADERS || defined __GNU_LIBRARY__)
250# undef size_t
251# define size_t unsigned int
28f540f4
RM
252#endif
253
254/* Some system header files erroneously define these.
255 We want our own definitions from <fnmatch.h> to take precedence. */
d47aac39
UD
256#ifndef __GNU_LIBRARY__
257# undef FNM_PATHNAME
258# undef FNM_NOESCAPE
259# undef FNM_PERIOD
260#endif
28f540f4
RM
261#include <fnmatch.h>
262
263/* Some system header files erroneously define these.
264 We want our own definitions from <glob.h> to take precedence. */
a53bad16
UD
265#ifndef __GNU_LIBRARY__
266# undef GLOB_ERR
267# undef GLOB_MARK
268# undef GLOB_NOSORT
269# undef GLOB_DOOFFS
270# undef GLOB_NOCHECK
271# undef GLOB_APPEND
272# undef GLOB_NOESCAPE
273# undef GLOB_PERIOD
274#endif
28f540f4
RM
275#include <glob.h>
276\f
f41c8091
UD
277static
278#if __GNUC__ - 0 >= 2
279inline
280#endif
281const char *next_brace_sub __P ((const char *begin));
28f540f4
RM
282static int glob_in_dir __P ((const char *pattern, const char *directory,
283 int flags,
284 int (*errfunc) __P ((const char *, int)),
285 glob_t *pglob));
286static int prefix_array __P ((const char *prefix, char **array, size_t n));
287static int collated_compare __P ((const __ptr_t, const __ptr_t));
288
5ae9d168
UD
289
290/* Find the end of the sub-pattern in a brace expression. We define
291 this as an inline function if the compiler permits. */
292static
293#if __GNUC__ - 0 >= 2
294inline
295#endif
296const char *
ca34d7a7
UD
297next_brace_sub (begin)
298 const char *begin;
5ae9d168
UD
299{
300 unsigned int depth = 0;
301 const char *cp = begin;
302
303 while (1)
304 {
305 if (depth == 0)
306 {
307 if (*cp != ',' && *cp != '}' && *cp != '\0')
308 {
309 if (*cp == '{')
310 ++depth;
311 ++cp;
312 continue;
313 }
314 }
315 else
316 {
317 while (*cp != '\0' && (*cp != '}' || depth > 0))
318 {
319 if (*cp == '}')
e7fd8a39 320 --depth;
5ae9d168
UD
321 ++cp;
322 }
323 if (*cp == '\0')
324 /* An incorrectly terminated brace expression. */
325 return NULL;
326
327 continue;
328 }
329 break;
330 }
331
332 return cp;
333}
334
28f540f4
RM
335/* Do glob searching for PATTERN, placing results in PGLOB.
336 The bits defined above may be set in FLAGS.
337 If a directory cannot be opened or read and ERRFUNC is not nil,
338 it is called with the pathname that caused the error, and the
339 `errno' value from the failing call; if it returns non-zero
714a562f 340 `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
28f540f4
RM
341 If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
342 Otherwise, `glob' returns zero. */
343int
344glob (pattern, flags, errfunc, pglob)
345 const char *pattern;
346 int flags;
347 int (*errfunc) __P ((const char *, int));
348 glob_t *pglob;
349{
350 const char *filename;
351 char *dirname;
352 size_t dirlen;
353 int status;
354 int oldcount;
355
356 if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
357 {
c4029823 358 __set_errno (EINVAL);
28f540f4
RM
359 return -1;
360 }
361
787e4db9
RM
362 if (flags & GLOB_BRACE)
363 {
364 const char *begin = strchr (pattern, '{');
365 if (begin != NULL)
366 {
5ae9d168
UD
367 /* Allocate working buffer large enough for our work. Note that
368 we have at least an opening and closing brace. */
6025c399 369 int firstc;
5ae9d168
UD
370 char *alt_start;
371 const char *p;
372 const char *next;
373 const char *rest;
374 size_t rest_len;
375#ifdef __GNUC__
376 char onealt[strlen (pattern) - 1];
377#else
378 char *onealt = (char *) malloc (strlen (pattern) - 1);
379 if (onealt == NULL)
380 {
381 if (!(flags & GLOB_APPEND))
382 globfree (pglob);
383 return GLOB_NOSPACE;
384 }
385#endif
386
387 /* We know the prefix for all sub-patterns. */
86187531
UD
388#ifdef HAVE_MEMPCPY
389 alt_start = mempcpy (onealt, pattern, begin - pattern);
390#else
5ae9d168
UD
391 memcpy (onealt, pattern, begin - pattern);
392 alt_start = &onealt[begin - pattern];
86187531 393#endif
5ae9d168
UD
394
395 /* Find the first sub-pattern and at the same time find the
396 rest after the closing brace. */
397 next = next_brace_sub (begin + 1);
398 if (next == NULL)
787e4db9 399 {
5ae9d168
UD
400 /* It is an illegal expression. */
401#ifndef __GNUC__
402 free (onealt);
403#endif
404 return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
405 }
406
407 /* Now find the end of the whole brace expression. */
408 rest = next;
409 while (*rest != '}')
410 {
411 rest = next_brace_sub (rest + 1);
412 if (rest == NULL)
787e4db9 413 {
5ae9d168
UD
414 /* It is an illegal expression. */
415#ifndef __GNUC__
416 free (onealt);
417#endif
418 return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
6025c399 419 }
6025c399 420 }
5ae9d168
UD
421 /* Please note that we now can be sure the brace expression
422 is well-formed. */
423 rest_len = strlen (++rest) + 1;
6025c399
RM
424
425 /* We have a brace expression. BEGIN points to the opening {,
426 NEXT points past the terminator of the first element, and END
427 points past the final }. We will accumulate result names from
428 recursive runs for each brace alternative in the buffer using
429 GLOB_APPEND. */
430
431 if (!(flags & GLOB_APPEND))
432 {
433 /* This call is to set a new vector, so clear out the
434 vector so we can append to it. */
435 pglob->gl_pathc = 0;
436 pglob->gl_pathv = NULL;
437 }
438 firstc = pglob->gl_pathc;
439
6025c399
RM
440 p = begin + 1;
441 while (1)
442 {
6025c399 443 int result;
5ae9d168
UD
444
445 /* Construct the new glob expression. */
dd7d45e8
UD
446#ifdef HAVE_MEMPCPY
447 mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
448#else
5ae9d168
UD
449 memcpy (alt_start, p, next - p);
450 memcpy (&alt_start[next - p], rest, rest_len);
dd7d45e8 451#endif
5ae9d168 452
6025c399 453 result = glob (onealt,
5ae9d168
UD
454 ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC))
455 | GLOB_APPEND), errfunc, pglob);
6025c399
RM
456
457 /* If we got an error, return it. */
458 if (result && result != GLOB_NOMATCH)
787e4db9 459 {
5ae9d168
UD
460#ifndef __GNUC__
461 free (onealt);
462#endif
6025c399
RM
463 if (!(flags & GLOB_APPEND))
464 globfree (pglob);
465 return result;
466 }
467
5ae9d168
UD
468 if (*next == '}')
469 /* We saw the last entry. */
470 break;
471
472 p = next + 1;
473 next = next_brace_sub (p);
474 assert (next != NULL);
787e4db9 475 }
6025c399 476
5ae9d168
UD
477#ifndef __GNUC__
478 free (onealt);
479#endif
480
481 if (pglob->gl_pathc != firstc)
482 /* We found some entries. */
483 return 0;
484 else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
6025c399 485 return GLOB_NOMATCH;
787e4db9
RM
486 }
487 }
488
28f540f4
RM
489 /* Find the filename. */
490 filename = strrchr (pattern, '/');
491 if (filename == NULL)
492 {
493 filename = pattern;
9fb16eea
RM
494#ifdef _AMIGA
495 dirname = (char *) "";
496#else
28f540f4 497 dirname = (char *) ".";
9fb16eea 498#endif
28f540f4
RM
499 dirlen = 0;
500 }
501 else if (filename == pattern)
502 {
503 /* "/pattern". */
504 dirname = (char *) "/";
505 dirlen = 1;
506 ++filename;
507 }
508 else
509 {
510 dirlen = filename - pattern;
511 dirname = (char *) __alloca (dirlen + 1);
dd7d45e8
UD
512#ifdef HAVE_MEMPCPY
513 *((char *) mempcpy (dirname, pattern, dirlen)) = '\0';
514#else
28f540f4
RM
515 memcpy (dirname, pattern, dirlen);
516 dirname[dirlen] = '\0';
dd7d45e8 517#endif
28f540f4
RM
518 ++filename;
519 }
520
521 if (filename[0] == '\0' && dirlen > 1)
522 /* "pattern/". Expand "pattern", appending slashes. */
523 {
524 int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
525 if (val == 0)
526 pglob->gl_flags = (pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK);
527 return val;
528 }
529
530 if (!(flags & GLOB_APPEND))
531 {
532 pglob->gl_pathc = 0;
533 pglob->gl_pathv = NULL;
534 }
535
536 oldcount = pglob->gl_pathc;
537
0efef8fc 538#ifndef VMS
787e4db9
RM
539 if ((flags & GLOB_TILDE) && dirname[0] == '~')
540 {
5ae9d168 541 if (dirname[1] == '\0' || dirname[1] == '/')
787e4db9
RM
542 {
543 /* Look up home directory. */
5ae9d168 544 char *home_dir = getenv ("HOME");
61eb22d3 545# ifdef _AMIGA
5ae9d168
UD
546 if (home_dir == NULL || home_dir[0] == '\0')
547 home_dir = "SYS:";
61eb22d3
UD
548# else
549# ifdef WINDOWS32
5ae9d168
UD
550 if (home_dir == NULL || home_dir[0] == '\0')
551 home_dir = "c:/users/default"; /* poor default */
61eb22d3 552# else
5ae9d168 553 if (home_dir == NULL || home_dir[0] == '\0')
787e4db9 554 {
e4cf5070 555 int success;
61eb22d3 556# if defined HAVE_GETLOGIN_R || defined _LIBC
ca34d7a7 557 extern int getlogin_r __P ((char *, size_t));
e4cf5070
UD
558 size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;
559 char *name;
560
561 if (buflen == 0)
562 /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try
563 a moderate value. */
564 buflen = 16;
ca34d7a7 565 name = (char *) __alloca (buflen);
e4cf5070
UD
566
567 success = getlogin_r (name, buflen) >= 0;
61eb22d3 568# else
ca34d7a7 569 extern char *getlogin __P ((void));
e4cf5070 570 char *name;
ca34d7a7 571
e4cf5070 572 success = (name = getlogin ()) != NULL;
61eb22d3 573# endif
e4cf5070 574 if (success)
787e4db9 575 {
61eb22d3 576# if defined HAVE_GETPWNAM_R || defined _LIBC
e4cf5070
UD
577 size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
578 char *pwtmpbuf;
579 struct passwd pwbuf, *p;
580
ca34d7a7 581 pwtmpbuf = (char *) __alloca (pwbuflen);
e4cf5070
UD
582
583 success = (__getpwnam_r (name, &pwbuf, pwtmpbuf,
584 pwbuflen, &p) >= 0);
61eb22d3 585# else
787e4db9 586 struct passwd *p = getpwnam (name);
e4cf5070 587 success = p != NULL;
61eb22d3 588# endif
e4cf5070 589 if (success)
5ae9d168 590 home_dir = p->pw_dir;
787e4db9
RM
591 }
592 }
5ae9d168
UD
593 if (home_dir == NULL || home_dir[0] == '\0')
594 home_dir = (char *) "~"; /* No luck. */
61eb22d3
UD
595# endif /* WINDOWS32 */
596# endif
5ae9d168
UD
597 /* Now construct the full directory. */
598 if (dirname[1] == '\0')
599 dirname = home_dir;
600 else
601 {
602 char *newp;
603 size_t home_len = strlen (home_dir);
ca34d7a7 604 newp = (char *) __alloca (home_len + dirlen);
dd7d45e8
UD
605# ifdef HAVE_MEMPCPY
606 mempcpy (mempcpy (newp, home_dir, home_len),
607 &dirname[1], dirlen);
608# else
5ae9d168
UD
609 memcpy (newp, home_dir, home_len);
610 memcpy (&newp[home_len], &dirname[1], dirlen);
dd7d45e8 611# endif
5ae9d168
UD
612 dirname = newp;
613 }
787e4db9 614 }
61eb22d3 615# if !defined _AMIGA && !defined WINDOWS32
787e4db9
RM
616 else
617 {
5ae9d168
UD
618 char *end_name = strchr (dirname, '/');
619 char *user_name;
620 char *home_dir;
621
622 if (end_name == NULL)
623 user_name = dirname + 1;
624 else
625 {
ca34d7a7 626 user_name = (char *) __alloca (end_name - dirname);
dd7d45e8
UD
627# ifdef HAVE_MEMPCPY
628 *((char *) mempcpy (user_name, dirname + 1, end_name - dirname))
629 = '\0';
630# else
5ae9d168
UD
631 memcpy (user_name, dirname + 1, end_name - dirname);
632 user_name[end_name - dirname - 1] = '\0';
dd7d45e8 633# endif
5ae9d168
UD
634 }
635
787e4db9 636 /* Look up specific user's home directory. */
5ae9d168 637 {
61eb22d3 638# if defined HAVE_GETPWNAM_R || defined _LIBC
5ae9d168 639 size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
ca34d7a7 640 char *pwtmpbuf = (char *) __alloca (buflen);
5ae9d168
UD
641 struct passwd pwbuf, *p;
642 if (__getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) >= 0)
643 home_dir = p->pw_dir;
644 else
645 home_dir = NULL;
61eb22d3 646# else
5ae9d168
UD
647 struct passwd *p = getpwnam (user_name);
648 if (p != NULL)
649 home_dir = p->pw_dir;
650 else
651 home_dir = NULL;
61eb22d3 652# endif
5ae9d168
UD
653 }
654 /* If we found a home directory use this. */
655 if (home_dir != NULL)
656 {
657 char *newp;
658 size_t home_len = strlen (home_dir);
659 size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
ca34d7a7 660 newp = (char *) __alloca (home_len + rest_len + 1);
dd7d45e8
UD
661# ifdef HAVE_MEMPCPY
662 *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
663 end_name, rest_len)) = '\0';
664# else
5ae9d168
UD
665 memcpy (newp, home_dir, home_len);
666 memcpy (&newp[home_len], end_name, rest_len);
667 newp[home_len + rest_len] = '\0';
dd7d45e8 668# endif
5ae9d168
UD
669 dirname = newp;
670 }
787e4db9 671 }
61eb22d3 672# endif /* Not Amiga && not WINDOWS32. */
787e4db9 673 }
0efef8fc 674#endif /* Not VMS. */
787e4db9 675
e7fd8a39 676 if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
28f540f4
RM
677 {
678 /* The directory name contains metacharacters, so we
679 have to glob for the directory, and then glob for
680 the pattern in each directory found. */
681 glob_t dirs;
682 register int i;
683
684 status = glob (dirname,
1cab5444
UD
685 ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE))
686 | GLOB_NOSORT | GLOB_ONLYDIR),
28f540f4
RM
687 errfunc, &dirs);
688 if (status != 0)
689 return status;
690
691 /* We have successfully globbed the preceding directory name.
692 For each name we found, call glob_in_dir on it and FILENAME,
693 appending the results to PGLOB. */
694 for (i = 0; i < dirs.gl_pathc; ++i)
695 {
cc60175e 696 int old_pathc;
28f540f4
RM
697
698#ifdef SHELL
699 {
700 /* Make globbing interruptible in the bash shell. */
701 extern int interrupt_state;
702
703 if (interrupt_state)
704 {
705 globfree (&dirs);
706 globfree (&files);
714a562f 707 return GLOB_ABORTED;
28f540f4
RM
708 }
709 }
710#endif /* SHELL. */
711
cc60175e 712 old_pathc = pglob->gl_pathc;
28f540f4 713 status = glob_in_dir (filename, dirs.gl_pathv[i],
1cab5444
UD
714 ((flags | GLOB_APPEND)
715 & ~(GLOB_NOCHECK | GLOB_ERR)),
28f540f4
RM
716 errfunc, pglob);
717 if (status == GLOB_NOMATCH)
718 /* No matches in this directory. Try the next. */
719 continue;
720
721 if (status != 0)
722 {
723 globfree (&dirs);
724 globfree (pglob);
725 return status;
726 }
727
728 /* Stick the directory on the front of each name. */
729 if (prefix_array (dirs.gl_pathv[i],
cc60175e
UD
730 &pglob->gl_pathv[old_pathc],
731 pglob->gl_pathc - old_pathc))
28f540f4
RM
732 {
733 globfree (&dirs);
734 globfree (pglob);
735 return GLOB_NOSPACE;
736 }
737 }
738
739 flags |= GLOB_MAGCHAR;
740
741 if (pglob->gl_pathc == oldcount)
742 /* No matches. */
743 if (flags & GLOB_NOCHECK)
744 {
745 size_t len = strlen (pattern) + 1;
746 char *patcopy = (char *) malloc (len);
747 if (patcopy == NULL)
748 return GLOB_NOSPACE;
749 memcpy (patcopy, pattern, len);
750
751 pglob->gl_pathv
752 = (char **) realloc (pglob->gl_pathv,
753 (pglob->gl_pathc +
754 ((flags & GLOB_DOOFFS) ?
755 pglob->gl_offs : 0) +
756 1 + 1) *
757 sizeof (char *));
758 if (pglob->gl_pathv == NULL)
759 {
760 free (patcopy);
761 return GLOB_NOSPACE;
762 }
763
764 if (flags & GLOB_DOOFFS)
765 while (pglob->gl_pathc < pglob->gl_offs)
766 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
767
768 pglob->gl_pathv[pglob->gl_pathc++] = patcopy;
769 pglob->gl_pathv[pglob->gl_pathc] = NULL;
770 pglob->gl_flags = flags;
771 }
772 else
773 return GLOB_NOMATCH;
774 }
775 else
776 {
777 status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
778 if (status != 0)
779 return status;
780
781 if (dirlen > 0)
782 {
783 /* Stick the directory on the front of each name. */
cc60175e
UD
784 int ignore = oldcount;
785
786 if ((flags & GLOB_DOOFFS) && ignore < pglob->gl_offs)
787 ignore = pglob->gl_offs;
788
28f540f4 789 if (prefix_array (dirname,
cc60175e
UD
790 &pglob->gl_pathv[ignore],
791 pglob->gl_pathc - ignore))
28f540f4
RM
792 {
793 globfree (pglob);
794 return GLOB_NOSPACE;
795 }
796 }
797 }
798
bf3ccd1a
RM
799 if (flags & GLOB_MARK)
800 {
c043db7a 801 /* Append slashes to directory names. */
bf3ccd1a
RM
802 int i;
803 struct stat st;
804 for (i = oldcount; i < pglob->gl_pathc; ++i)
a9ddb793
UD
805 if (((flags & GLOB_ALTDIRFUNC)
806 ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st)
807 : __stat (pglob->gl_pathv[i], &st)) == 0
808 && S_ISDIR (st.st_mode))
a993273c
RM
809 {
810 size_t len = strlen (pglob->gl_pathv[i]) + 2;
811 char *new = realloc (pglob->gl_pathv[i], len);
812 if (new == NULL)
813 {
814 globfree (pglob);
815 return GLOB_NOSPACE;
816 }
817 strcpy (&new[len - 2], "/");
818 pglob->gl_pathv[i] = new;
819 }
bf3ccd1a
RM
820 }
821
28f540f4 822 if (!(flags & GLOB_NOSORT))
cc60175e
UD
823 {
824 /* Sort the vector. */
825 int non_sort = oldcount;
826
827 if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount)
828 non_sort = pglob->gl_offs;
829
830 qsort ((__ptr_t) &pglob->gl_pathv[non_sort],
831 pglob->gl_pathc - non_sort,
832 sizeof (char *), collated_compare);
833 }
28f540f4
RM
834
835 return 0;
836}
837
838
839/* Free storage allocated in PGLOB by a previous `glob' call. */
840void
841globfree (pglob)
842 register glob_t *pglob;
843{
844 if (pglob->gl_pathv != NULL)
845 {
846 register int i;
847 for (i = 0; i < pglob->gl_pathc; ++i)
848 if (pglob->gl_pathv[i] != NULL)
849 free ((__ptr_t) pglob->gl_pathv[i]);
850 free ((__ptr_t) pglob->gl_pathv);
851 }
852}
853
854
855/* Do a collated comparison of A and B. */
856static int
857collated_compare (a, b)
858 const __ptr_t a;
859 const __ptr_t b;
860{
861 const char *const s1 = *(const char *const * const) a;
862 const char *const s2 = *(const char *const * const) b;
863
864 if (s1 == s2)
865 return 0;
866 if (s1 == NULL)
867 return 1;
868 if (s2 == NULL)
869 return -1;
870 return strcoll (s1, s2);
871}
872
873
874/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
875 elements in place. Return nonzero if out of memory, zero if successful.
876 A slash is inserted between DIRNAME and each elt of ARRAY,
877 unless DIRNAME is just "/". Each old element of ARRAY is freed. */
878static int
879prefix_array (dirname, array, n)
880 const char *dirname;
881 char **array;
882 size_t n;
883{
884 register size_t i;
885 size_t dirlen = strlen (dirname);
886
887 if (dirlen == 1 && dirname[0] == '/')
888 /* DIRNAME is just "/", so normal prepending would get us "//foo".
889 We want "/foo" instead, so don't prepend any chars from DIRNAME. */
890 dirlen = 0;
891
892 for (i = 0; i < n; ++i)
893 {
894 size_t eltlen = strlen (array[i]) + 1;
895 char *new = (char *) malloc (dirlen + 1 + eltlen);
896 if (new == NULL)
897 {
898 while (i > 0)
899 free ((__ptr_t) array[--i]);
900 return 1;
901 }
902
dd7d45e8
UD
903#ifdef HAVE_MEMPCPY
904 {
905 char *endp = (char *) mempcpy (new, dirname, dirlen);
906 *endp++ = '/';
907 mempcpy (endp, array[i], eltlen);
908 }
909#else
28f540f4
RM
910 memcpy (new, dirname, dirlen);
911 new[dirlen] = '/';
912 memcpy (&new[dirlen + 1], array[i], eltlen);
dd7d45e8 913#endif
28f540f4
RM
914 free ((__ptr_t) array[i]);
915 array[i] = new;
916 }
917
918 return 0;
919}
920
921
922/* Return nonzero if PATTERN contains any metacharacters.
923 Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
e7fd8a39
UD
924int
925__glob_pattern_p (pattern, quote)
28f540f4
RM
926 const char *pattern;
927 int quote;
928{
929 register const char *p;
930 int open = 0;
931
932 for (p = pattern; *p != '\0'; ++p)
933 switch (*p)
934 {
935 case '?':
936 case '*':
937 return 1;
938
939 case '\\':
299a95b9 940 if (quote && p[1] != '\0')
28f540f4
RM
941 ++p;
942 break;
943
944 case '[':
945 open = 1;
946 break;
947
948 case ']':
949 if (open)
950 return 1;
951 break;
952 }
953
954 return 0;
955}
e7fd8a39
UD
956#ifdef _LIBC
957weak_alias (__glob_pattern_p, glob_pattern_p)
958#endif
28f540f4
RM
959
960
961/* Like `glob', but PATTERN is a final pathname component,
962 and matches are searched for in DIRECTORY.
963 The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
964 The GLOB_APPEND flag is assumed to be set (always appends). */
965static int
966glob_in_dir (pattern, directory, flags, errfunc, pglob)
967 const char *pattern;
968 const char *directory;
969 int flags;
970 int (*errfunc) __P ((const char *, int));
971 glob_t *pglob;
972{
a9ddb793 973 __ptr_t stream = NULL;
28f540f4
RM
974
975 struct globlink
976 {
977 struct globlink *next;
978 char *name;
979 };
980 struct globlink *names = NULL;
86187531
UD
981 size_t nfound;
982 int meta;
983 int save;
984
a9ddb793
UD
985 meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
986 if (meta == 0)
28f540f4 987 {
a9ddb793
UD
988 if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))
989 /* We need not do any tests. The PATTERN contains no meta
990 characters and we must not return an error therefore the
991 result will always contain exactly the one name. */
992 flags |= GLOB_NOCHECK;
993 else
994 {
995 /* Since we use the normal file functions we can also use stat()
996 to verify the file is there. */
997 struct stat st;
998 size_t patlen = strlen (pattern);
999 size_t dirlen = strlen (directory);
1000 char *fullname = __alloca (dirlen + 1 + patlen + 1);
1001
1002# ifdef HAVE_MEMPCPY
1003 mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
1004 "/", 1),
1005 pattern, patlen + 1);
1006# else
1007 memcpy (fullname, directory, dirlen);
1008 fullname[dirlen] = '/';
1009 memcpy (&fullname[dirlen + 1], pattern, patlen + 1);
1010# endif
1011 if (((flags & GLOB_ALTDIRFUNC)
1012 ? (*pglob->gl_stat) (fullname, &st)
1013 : __stat (fullname, &st)) == 0)
1014 /* We found this file to be existing. No tell the rest
1015 of the function to copy this name into the result. */
1016 flags |= GLOB_NOCHECK;
1017 }
1018
86187531 1019 nfound = 0;
28f540f4
RM
1020 }
1021 else
1022 {
a9ddb793 1023 if (pattern[0] == '\0')
28f540f4 1024 {
a9ddb793
UD
1025 /* This is a special case for matching directories like in
1026 "*a/". */
1027 names = (struct globlink *) __alloca (sizeof (struct globlink));
1028 names->name = (char *) malloc (1);
1029 if (names->name == NULL)
1030 goto memory_error;
1031 names->name[0] = '\0';
1032 names->next = NULL;
1033 nfound = 1;
1034 meta = 0;
1035 }
1036 else
1037 {
1038 stream = ((flags & GLOB_ALTDIRFUNC)
1039 ? (*pglob->gl_opendir) (directory)
1040 : (__ptr_t) opendir (directory));
1041 if (stream == NULL)
1042 {
1043 if ((errfunc != NULL && (*errfunc) (directory, errno))
1044 || (flags & GLOB_ERR))
1045 return GLOB_ABORTED;
1046 nfound = 0;
1047 meta = 0;
1048 }
1049 else
1050 {
1051 int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
1052 | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
1053#if defined _AMIGA || defined VMS
1054 | FNM_CASEFOLD
1055#endif
1056 );
1057 nfound = 0;
1058 flags |= GLOB_MAGCHAR;
1059
1060 while (1)
1061 {
1062 const char *name;
1063 size_t len;
1064 struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
1065 ? (*pglob->gl_readdir) (stream)
1066 : readdir ((DIR *) stream));
1067 if (d == NULL)
1068 break;
1069 if (! REAL_DIR_ENTRY (d))
1070 continue;
787e4db9 1071
1cab5444 1072#ifdef HAVE_D_TYPE
a9ddb793
UD
1073 /* If we shall match only directories use the information
1074 provided by the dirent call if possible. */
1075 if ((flags & GLOB_ONLYDIR)
1076 && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
1077 continue;
1cab5444
UD
1078#endif
1079
a9ddb793 1080 name = d->d_name;
86187531 1081
a9ddb793
UD
1082 if (fnmatch (pattern, name, fnm_flags) == 0)
1083 {
1084 struct globlink *new = (struct globlink *)
1085 __alloca (sizeof (struct globlink));
1086 len = NAMLEN (d);
1087 new->name = (char *) malloc (len + 1);
1088 if (new->name == NULL)
1089 goto memory_error;
dd7d45e8 1090#ifdef HAVE_MEMPCPY
a9ddb793
UD
1091 *((char *) mempcpy ((__ptr_t) new->name, name, len))
1092 = '\0';
dd7d45e8 1093#else
a9ddb793
UD
1094 memcpy ((__ptr_t) new->name, name, len);
1095 new->name[len] = '\0';
dd7d45e8 1096#endif
a9ddb793
UD
1097 new->next = names;
1098 names = new;
1099 ++nfound;
1100 }
1101 }
86187531
UD
1102 }
1103 }
28f540f4
RM
1104 }
1105
1106 if (nfound == 0 && (flags & GLOB_NOCHECK))
1107 {
1108 size_t len = strlen (pattern);
1109 nfound = 1;
1110 names = (struct globlink *) __alloca (sizeof (struct globlink));
1111 names->next = NULL;
a993273c 1112 names->name = (char *) malloc (len + 1);
28f540f4
RM
1113 if (names->name == NULL)
1114 goto memory_error;
dd7d45e8
UD
1115#ifdef HAVE_MEMPCPY
1116 *((char *) mempcpy (names->name, pattern, len)) = '\0';
1117#else
28f540f4 1118 memcpy (names->name, pattern, len);
28f540f4 1119 names->name[len] = '\0';
dd7d45e8 1120#endif
28f540f4
RM
1121 }
1122
61eb22d3
UD
1123 if (nfound != 0)
1124 {
1125 pglob->gl_pathv
1126 = (char **) realloc (pglob->gl_pathv,
1127 (pglob->gl_pathc +
1128 ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
1129 nfound + 1) *
1130 sizeof (char *));
1131 if (pglob->gl_pathv == NULL)
1132 goto memory_error;
28f540f4 1133
61eb22d3
UD
1134 if (flags & GLOB_DOOFFS)
1135 while (pglob->gl_pathc < pglob->gl_offs)
1136 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
28f540f4 1137
61eb22d3
UD
1138 for (; names != NULL; names = names->next)
1139 pglob->gl_pathv[pglob->gl_pathc++] = names->name;
1140 pglob->gl_pathv[pglob->gl_pathc] = NULL;
28f540f4 1141
61eb22d3
UD
1142 pglob->gl_flags = flags;
1143 }
28f540f4 1144
86187531 1145 save = errno;
a9ddb793
UD
1146 if (stream != NULL)
1147 if (flags & GLOB_ALTDIRFUNC)
1148 (*pglob->gl_closedir) (stream);
1149 else
1150 closedir ((DIR *) stream);
86187531
UD
1151 __set_errno (save);
1152
28f540f4
RM
1153 return nfound == 0 ? GLOB_NOMATCH : 0;
1154
1155 memory_error:
1156 {
1157 int save = errno;
787e4db9
RM
1158 if (flags & GLOB_ALTDIRFUNC)
1159 (*pglob->gl_closedir) (stream);
28f540f4 1160 else
faf92f2a 1161 closedir ((DIR *) stream);
c4029823 1162 __set_errno (save);
28f540f4
RM
1163 }
1164 while (names != NULL)
1165 {
1166 if (names->name != NULL)
1167 free ((__ptr_t) names->name);
1168 names = names->next;
1169 }
1170 return GLOB_NOSPACE;
1171}
1172
787e4db9 1173#endif /* Not ELIDE_CODE. */