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