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