blob: 488f22970dc6c3e07717dec234040283f41d9908 [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/* Copyright (C) 1991-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
18
19#undef ENABLE_GLOB_BRACE_EXPANSION
20#undef ENABLE_GLOB_TILDE_EXPANSION
21
22#include <features.h>
23#include <stdlib.h>
24#include <string.h>
25#include <errno.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <unistd.h>
29#include <dirent.h>
30#include <malloc.h>
31#include <fnmatch.h>
32#include <glob.h>
33
34
35
36#ifdef ENABLE_GLOB_TILDE_EXPANSION
37#include <pwd.h>
38#endif
39
40#ifdef COMPILE_GLOB64
41#undef stat
42#define stat stat64
43#define struct_stat64 struct stat64
44#define __stat64(fname, buf) stat64 (fname, buf)
45#define dirent dirent64
46#define __readdir readdir64
47#define __readdir64 readdir64
48#define glob_t glob64_t
49#define glob(pattern, flags, errfunc, pglob) glob64 (pattern, flags, errfunc, pglob)
50#define globfree(pglob) globfree64 (pglob)
51#else
52#define __readdir readdir
53#ifdef __UCLIBC_HAS_LFS__
54#define __readdir64 readdir64
55#else
56#define __readdir64 readdir
57#endif
58#define struct_stat64 struct stat
59#define __stat64(fname, buf) stat (fname, buf)
60#endif
61
62
63/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
64 if the `d_type' member for `struct dirent' is available.
65 HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */
66#if defined _DIRENT_HAVE_D_TYPE
67/* True if the directory entry D must be of type T. */
68# define DIRENT_MUST_BE(d, t) ((d)->d_type == (t))
69
70/* True if the directory entry D might be a symbolic link. */
71# define DIRENT_MIGHT_BE_SYMLINK(d) \
72 ((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK)
73
74/* True if the directory entry D might be a directory. */
75# define DIRENT_MIGHT_BE_DIR(d) \
76 ((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d))
77
78#else /* !HAVE_D_TYPE */
79# define DIRENT_MUST_BE(d, t) false
80# define DIRENT_MIGHT_BE_SYMLINK(d) true
81# define DIRENT_MIGHT_BE_DIR(d) true
82#endif /* HAVE_D_TYPE */
83
84
85# define NAMLEN(dirent) strlen((dirent)->d_name)
86#ifdef _D_NAMLEN
87# undef NAMLEN
88# define NAMLEN(d) _D_NAMLEN(d)
89#endif
90
91# if defined _DIRENT_HAVE_D_NAMLEN
92# define CONVERT_D_NAMLEN(d64, d32) (d64)->d_namlen = (d32)->d_namlen;
93# else
94# define CONVERT_D_NAMLEN(d64, d32)
95# endif
96
97# define CONVERT_D_INO(d64, d32) (d64)->d_ino = (d32)->d_ino;
98
99# ifdef _DIRENT_HAVE_D_TYPE
100# define CONVERT_D_TYPE(d64, d32) (d64)->d_type = (d32)->d_type;
101# else
102# define CONVERT_D_TYPE(d64, d32)
103# endif
104
105# define CONVERT_DIRENT_DIRENT64(d64, d32) \
106 memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \
107 CONVERT_D_NAMLEN (d64, d32) \
108 CONVERT_D_INO (d64, d32) \
109 CONVERT_D_TYPE (d64, d32)
110
111extern int __collated_compare (const void *a, const void *b) attribute_hidden;
112extern int __prefix_array (const char *dirname, char **array, size_t n) attribute_hidden;
113#if defined ENABLE_GLOB_BRACE_EXPANSION
114extern const char *__next_brace_sub (const char *cp, int flags) attribute_hidden;
115#endif
116
117#ifndef COMPILE_GLOB64
118/* Return nonzero if PATTERN contains any metacharacters.
119 Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
120int glob_pattern_p(const char *pattern, int quote)
121{
122 register const char *p;
123 int open = 0;
124
125 for (p = pattern; *p != '\0'; ++p)
126 switch (*p)
127 {
128 case '?':
129 case '*':
130 return 1;
131
132 case '\\':
133 if (quote && p[1] != '\0')
134 ++p;
135 break;
136
137 case '[':
138 open = 1;
139 break;
140
141 case ']':
142 if (open)
143 return 1;
144 break;
145 }
146
147 return 0;
148}
149libc_hidden_def(glob_pattern_p)
150
151
152/* Do a collated comparison of A and B. */
153int __collated_compare (const void *a, const void *b)
154{
155 const char *const s1 = *(const char *const * const) a;
156 const char *const s2 = *(const char *const * const) b;
157
158 if (s1 == s2)
159 return 0;
160 if (s1 == NULL)
161 return 1;
162 if (s2 == NULL)
163 return -1;
164 return strcoll (s1, s2);
165}
166
167
168/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
169 elements in place. Return nonzero if out of memory, zero if successful.
170 A slash is inserted between DIRNAME and each elt of ARRAY,
171 unless DIRNAME is just "/". Each old element of ARRAY is freed.
172 If ADD_SLASH is non-zero, allocate one character more than
173 necessary, so that a slash can be appended later. */
174int __prefix_array (const char *dirname, char **array, size_t n)
175{
176 register size_t i;
177 size_t dirlen = strlen (dirname);
178# define DIRSEP_CHAR '/'
179
180 if (dirlen == 1 && dirname[0] == '/')
181 /* DIRNAME is just "/", so normal prepending would get us "//foo".
182 We want "/foo" instead, so don't prepend any chars from DIRNAME. */
183 dirlen = 0;
184
185 for (i = 0; i < n; ++i)
186 {
187 size_t eltlen = strlen (array[i]) + 1;
188 char *new = (char *) malloc (dirlen + 1 + eltlen);
189 if (new == NULL)
190 {
191 while (i > 0)
192 free (array[--i]);
193 return 1;
194 }
195
196 {
197 char *endp = mempcpy (new, dirname, dirlen);
198 *endp++ = DIRSEP_CHAR;
199 mempcpy (endp, array[i], eltlen);
200 }
201 free (array[i]);
202 array[i] = new;
203 }
204
205 return 0;
206}
207
208#if defined ENABLE_GLOB_BRACE_EXPANSION
209/* Find the end of the sub-pattern in a brace expression. */
210const char *
211__next_brace_sub (const char *cp, int flags)
212{
213 unsigned int depth = 0;
214 while (*cp != '\0')
215 if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\')
216 {
217 if (*++cp == '\0')
218 break;
219 ++cp;
220 }
221 else
222 {
223 if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
224 break;
225
226 if (*cp++ == '{')
227 depth++;
228 }
229
230 return *cp != '\0' ? cp : NULL;
231}
232#endif
233#endif
234
235
236static int
237link_exists_p (const char *dir, size_t dirlen, const char *fname,
238 glob_t *pglob, int flags)
239{
240 size_t fnamelen = strlen (fname);
241 char *fullname = (char *) alloca (dirlen + 1 + fnamelen + 1);
242 struct stat st;
243 struct_stat64 st64;
244
245 mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1),
246 fname, fnamelen + 1);
247
248 return (((flags & GLOB_ALTDIRFUNC)
249 ? (*pglob->gl_stat) (fullname, &st)
250 : __stat64 (fullname, &st64)) == 0);
251}
252
253/* Like `glob', but PATTERN is a final pathname component,
254 and matches are searched for in DIRECTORY.
255 The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
256 The GLOB_APPEND flag is assumed to be set (always appends). */
257static int glob_in_dir (const char *pattern, const char *directory, int flags,
258 int (*errfunc) (const char *, int),
259 glob_t *pglob)
260{
261 size_t dirlen = strlen (directory);
262 void *stream = NULL;
263 struct globlink
264 {
265 struct globlink *next;
266 char *name;
267 };
268 struct globlink *names = NULL;
269 size_t nfound;
270 int meta;
271 int save;
272
273 meta = glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
274 if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
275 {
276 /* We need not do any tests. The PATTERN contains no meta
277 characters and we must not return an error therefore the
278 result will always contain exactly one name. */
279 flags |= GLOB_NOCHECK;
280 nfound = 0;
281 }
282 else if (meta == 0 &&
283 ((flags & GLOB_NOESCAPE) || strchr (pattern, '\\') == NULL))
284 {
285 /* Since we use the normal file functions we can also use stat()
286 to verify the file is there. */
287 struct stat st;
288 struct_stat64 st64;
289 size_t patlen = strlen (pattern);
290 char *fullname = (char *) alloca (dirlen + 1 + patlen + 1);
291
292 mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
293 "/", 1),
294 pattern, patlen + 1);
295 if (((flags & GLOB_ALTDIRFUNC)
296 ? (*pglob->gl_stat) (fullname, &st)
297 : __stat64 (fullname, &st64)) == 0)
298 /* We found this file to be existing. Now tell the rest
299 of the function to copy this name into the result. */
300 flags |= GLOB_NOCHECK;
301
302 nfound = 0;
303 }
304 else
305 {
306 if (pattern[0] == '\0')
307 {
308 /* This is a special case for matching directories like in
309 "*a/". */
310 names = (struct globlink *) alloca (sizeof (struct globlink));
311 names->name = (char *) malloc (1);
312 if (names->name == NULL)
313 goto memory_error;
314 names->name[0] = '\0';
315 names->next = NULL;
316 nfound = 1;
317 meta = 0;
318 }
319 else
320 {
321 stream = ((flags & GLOB_ALTDIRFUNC)
322 ? (*pglob->gl_opendir) (directory)
323 : opendir (directory));
324 if (stream == NULL)
325 {
326 if (errno != ENOTDIR
327 && ((errfunc != NULL && (*errfunc) (directory, errno))
328 || (flags & GLOB_ERR)))
329 return GLOB_ABORTED;
330 nfound = 0;
331 meta = 0;
332 }
333 else
334 {
335 int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
336 | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
337 );
338 nfound = 0;
339 flags |= GLOB_MAGCHAR;
340
341 while (1)
342 {
343 const char *name;
344 size_t len;
345#if defined __UCLIBC_HAS_LFS__ && !defined COMPILE_GLOB64
346 struct dirent64 *d;
347 union
348 {
349 struct dirent64 d64;
350 char room [offsetof (struct dirent64, d_name[0])
351 + NAME_MAX + 1];
352 }
353 d64buf;
354
355 if (flags & GLOB_ALTDIRFUNC)
356 {
357 struct dirent *d32 = (*pglob->gl_readdir) (stream);
358 if (d32 != NULL)
359 {
360 CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32);
361 d = &d64buf.d64;
362 }
363 else
364 d = NULL;
365 }
366 else
367 d = __readdir64 (stream);
368#else
369 struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
370 ? ((struct dirent *)
371 (*pglob->gl_readdir) (stream))
372 : __readdir (stream));
373#endif
374 if (d == NULL)
375 break;
376# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
377 if (! REAL_DIR_ENTRY (d))
378 continue;
379
380 /* If we shall match only directories use the information
381 provided by the dirent call if possible. */
382 if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d))
383 continue;
384
385 name = d->d_name;
386
387 if (fnmatch (pattern, name, fnm_flags) == 0)
388 {
389 /* If the file we found is a symlink we have to
390 make sure the target file exists. */
391 if (!DIRENT_MIGHT_BE_SYMLINK (d)
392 || link_exists_p (directory, dirlen, name, pglob,
393 flags))
394 {
395 struct globlink *new = (struct globlink *)
396 alloca (sizeof (struct globlink));
397 len = NAMLEN (d);
398 new->name = (char *) malloc (len + 1);
399 if (new->name == NULL)
400 goto memory_error;
401 *((char *) mempcpy (new->name, name, len)) = '\0';
402 new->next = names;
403 names = new;
404 ++nfound;
405 }
406 }
407 }
408 }
409 }
410 }
411
412 if (nfound == 0 && (flags & GLOB_NOCHECK))
413 {
414 size_t len = strlen (pattern);
415 nfound = 1;
416 names = (struct globlink *) alloca (sizeof (struct globlink));
417 names->next = NULL;
418 names->name = (char *) malloc (len + 1);
419 if (names->name == NULL)
420 goto memory_error;
421 *((char *) mempcpy (names->name, pattern, len)) = '\0';
422 }
423
424 if (nfound != 0)
425 {
426 char **new_gl_pathv;
427
428 new_gl_pathv
429 = (char **) realloc (pglob->gl_pathv,
430 (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
431 * sizeof (char *));
432 if (new_gl_pathv == NULL)
433 goto memory_error;
434 pglob->gl_pathv = new_gl_pathv;
435
436 for (; names != NULL; names = names->next)
437 pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc++] = names->name;
438 pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
439
440 pglob->gl_flags = flags;
441 }
442
443 save = errno;
444 if (stream != NULL)
445 {
446 if (flags & GLOB_ALTDIRFUNC)
447 (*pglob->gl_closedir) (stream);
448 else
449 closedir (stream);
450 }
451 __set_errno (save);
452
453 return nfound == 0 ? GLOB_NOMATCH : 0;
454
455 memory_error:
456 {
457 int save2 = errno;
458 if (flags & GLOB_ALTDIRFUNC)
459 (*pglob->gl_closedir) (stream);
460 else
461 closedir (stream);
462 __set_errno (save2);
463 }
464 while (names != NULL)
465 {
466 free (names->name);
467 names = names->next;
468 }
469 return GLOB_NOSPACE;
470}
471
472/* Do glob searching for PATTERN, placing results in PGLOB.
473 The bits defined above may be set in FLAGS.
474 If a directory cannot be opened or read and ERRFUNC is not nil,
475 it is called with the pathname that caused the error, and the
476 `errno' value from the failing call; if it returns non-zero
477 `glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
478 If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
479 Otherwise, `glob' returns zero. */
480int
481glob (
482 const char *pattern,
483 int flags,
484 int (*errfunc) (const char *, int),
485 glob_t *pglob)
486{
487 const char *filename;
488 const char *dirname;
489 size_t dirlen;
490 int status;
491 size_t oldcount;
492
493 if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
494 {
495 __set_errno (EINVAL);
496 return -1;
497 }
498
499
500 if (!(flags & GLOB_DOOFFS))
501 /* Have to do this so `globfree' knows where to start freeing. It
502 also makes all the code that uses gl_offs simpler. */
503 pglob->gl_offs = 0;
504
505#if defined ENABLE_GLOB_BRACE_EXPANSION
506 if (flags & GLOB_BRACE)
507 {
508 const char *begin;
509
510 if (flags & GLOB_NOESCAPE)
511 begin = strchr (pattern, '{');
512 else
513 {
514 begin = pattern;
515 while (1)
516 {
517 if (*begin == '\0')
518 {
519 begin = NULL;
520 break;
521 }
522
523 if (*begin == '\\' && begin[1] != '\0')
524 ++begin;
525 else if (*begin == '{')
526 break;
527
528 ++begin;
529 }
530 }
531
532 if (begin != NULL)
533 {
534 /* Allocate working buffer large enough for our work. Note that
535 we have at least an opening and closing brace. */
536 size_t firstc;
537 char *alt_start;
538 const char *p;
539 const char *next;
540 const char *rest;
541 size_t rest_len;
542 char onealt[strlen (pattern) - 1];
543
544 /* We know the prefix for all sub-patterns. */
545 alt_start = mempcpy (onealt, pattern, begin - pattern);
546
547 /* Find the first sub-pattern and at the same time find the
548 rest after the closing brace. */
549 next = __next_brace_sub (begin + 1, flags);
550 if (next == NULL)
551 {
552 /* It is an illegal expression. */
553 return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
554 }
555
556 /* Now find the end of the whole brace expression. */
557 rest = next;
558 while (*rest != '}')
559 {
560 rest = __next_brace_sub (rest + 1, flags);
561 if (rest == NULL)
562 {
563 /* It is an illegal expression. */
564 return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
565 }
566 }
567 /* Please note that we now can be sure the brace expression
568 is well-formed. */
569 rest_len = strlen (++rest) + 1;
570
571 /* We have a brace expression. BEGIN points to the opening {,
572 NEXT points past the terminator of the first element, and END
573 points past the final }. We will accumulate result names from
574 recursive runs for each brace alternative in the buffer using
575 GLOB_APPEND. */
576
577 if (!(flags & GLOB_APPEND))
578 {
579 /* This call is to set a new vector, so clear out the
580 vector so we can append to it. */
581 pglob->gl_pathc = 0;
582 pglob->gl_pathv = NULL;
583 }
584 firstc = pglob->gl_pathc;
585
586 p = begin + 1;
587 while (1)
588 {
589 int result;
590
591 /* Construct the new glob expression. */
592 mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
593
594 result = glob (onealt,
595 ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
596 | GLOB_APPEND), errfunc, pglob);
597
598 /* If we got an error, return it. */
599 if (result && result != GLOB_NOMATCH)
600 {
601 if (!(flags & GLOB_APPEND))
602 {
603 globfree (pglob);
604 pglob->gl_pathc = 0;
605 }
606 return result;
607 }
608
609 if (*next == '}')
610 /* We saw the last entry. */
611 break;
612
613 p = next + 1;
614 next = __next_brace_sub (p, flags);
615 /* assert (next != NULL); */
616 }
617
618
619 if (pglob->gl_pathc != firstc)
620 /* We found some entries. */
621 return 0;
622 else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
623 return GLOB_NOMATCH;
624 }
625 }
626#endif
627
628 /* Find the filename. */
629 filename = strrchr (pattern, '/');
630 if (filename == NULL)
631 {
632 /* This can mean two things: a simple name or "~name". The latter
633 case is nothing but a notation for a directory. */
634 if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
635 {
636 dirname = pattern;
637 dirlen = strlen (pattern);
638
639 /* Set FILENAME to NULL as a special flag. This is ugly but
640 other solutions would require much more code. We test for
641 this special case below. */
642 filename = NULL;
643 }
644 else
645 {
646 filename = pattern;
647 dirname = ".";
648 dirlen = 0;
649 }
650 }
651 else if (filename == pattern)
652 {
653 /* "/pattern". */
654 dirname = "/";
655 dirlen = 1;
656 ++filename;
657 }
658 else
659 {
660 char *newp;
661 dirlen = filename - pattern;
662 newp = (char *) alloca (dirlen + 1);
663 *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
664 dirname = newp;
665 ++filename;
666
667 if (filename[0] == '\0'
668 && dirlen > 1)
669 /* "pattern/". Expand "pattern", appending slashes. */
670 {
671 int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
672 if (val == 0)
673 pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
674 | (flags & GLOB_MARK));
675 return val;
676 }
677 }
678
679 if (!(flags & GLOB_APPEND))
680 {
681 pglob->gl_pathc = 0;
682 if (!(flags & GLOB_DOOFFS))
683 pglob->gl_pathv = NULL;
684 else
685 {
686 size_t i;
687 pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
688 * sizeof (char *));
689 if (pglob->gl_pathv == NULL)
690 return GLOB_NOSPACE;
691
692 for (i = 0; i <= pglob->gl_offs; ++i)
693 pglob->gl_pathv[i] = NULL;
694 }
695 }
696
697 oldcount = pglob->gl_pathc + pglob->gl_offs;
698
699#if defined ENABLE_GLOB_TILDE_EXPANSION
700 if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
701 {
702 if (dirname[1] == '\0' || dirname[1] == '/')
703 {
704 /* Look up home directory. */
705 const char *home_dir = getenv ("HOME");
706 if (home_dir == NULL || home_dir[0] == '\0')
707 {
708 int success;
709 char *name;
710# define GET_LOGIN_NAME_MAX() sysconf (_SC_LOGIN_NAME_MAX)
711 size_t buflen = GET_LOGIN_NAME_MAX () + 1;
712
713 if (buflen == 0)
714 /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try
715 a moderate value. */
716 buflen = 20;
717 name = (char *) alloca (buflen);
718
719 success = getlogin_r (name, buflen) == 0;
720 if (success)
721 {
722 struct passwd *p;
723# define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX)
724 long int pwbuflen = GETPW_R_SIZE_MAX ();
725 char *pwtmpbuf;
726 struct passwd pwbuf;
727 int save = errno;
728
729 pwtmpbuf = (char *) alloca (pwbuflen);
730
731 while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
732 != 0)
733 {
734 if (errno != ERANGE)
735 {
736 p = NULL;
737 break;
738 }
739 pwtmpbuf = extend_alloca (pwtmpbuf, pwbuflen,
740 2 * pwbuflen);
741 __set_errno (save);
742 }
743 if (p != NULL)
744 home_dir = p->pw_dir;
745 }
746 }
747 if (home_dir == NULL || home_dir[0] == '\0')
748 {
749 if (flags & GLOB_TILDE_CHECK)
750 return GLOB_NOMATCH;
751 else
752 home_dir = "~"; /* No luck. */
753 }
754 /* Now construct the full directory. */
755 if (dirname[1] == '\0')
756 dirname = home_dir;
757 else
758 {
759 char *newp;
760 size_t home_len = strlen (home_dir);
761 newp = (char *) alloca (home_len + dirlen);
762 mempcpy (mempcpy (newp, home_dir, home_len),
763 &dirname[1], dirlen);
764 dirname = newp;
765 }
766 }
767 else
768 {
769 char *end_name = strchr (dirname, '/');
770 const char *user_name;
771 const char *home_dir;
772
773 if (end_name == NULL)
774 user_name = dirname + 1;
775 else
776 {
777 char *newp;
778 newp = (char *) alloca (end_name - dirname);
779 *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
780 = '\0';
781 user_name = newp;
782 }
783
784 /* Look up specific user's home directory. */
785 {
786 struct passwd *p;
787 long int buflen = GETPW_R_SIZE_MAX ();
788 char *pwtmpbuf;
789 struct passwd pwbuf;
790 int save = errno;
791
792 pwtmpbuf = (char *) alloca (buflen);
793
794 while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
795 {
796 if (errno != ERANGE)
797 {
798 p = NULL;
799 break;
800 }
801 pwtmpbuf = extend_alloca (pwtmpbuf, buflen, 2 * buflen);
802 __set_errno (save);
803 }
804 if (p != NULL)
805 home_dir = p->pw_dir;
806 else
807 home_dir = NULL;
808 }
809 /* If we found a home directory use this. */
810 if (home_dir != NULL)
811 {
812 char *newp;
813 size_t home_len = strlen (home_dir);
814 size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
815 newp = (char *) alloca (home_len + rest_len + 1);
816 *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
817 end_name, rest_len)) = '\0';
818 dirname = newp;
819 }
820 else
821 if (flags & GLOB_TILDE_CHECK)
822 /* We have to regard it as an error if we cannot find the
823 home directory. */
824 return GLOB_NOMATCH;
825 }
826 }
827
828 /* Now test whether we looked for "~" or "~NAME". In this case we
829 can give the answer now. */
830 if (filename == NULL)
831 {
832 struct stat st;
833 struct_stat64 st64;
834
835 /* Return the directory if we don't check for error or if it exists. */
836 if ((flags & GLOB_NOCHECK)
837 || (((flags & GLOB_ALTDIRFUNC)
838 ? ((*pglob->gl_stat) (dirname, &st) == 0
839 && S_ISDIR (st.st_mode))
840 : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode)))))
841 {
842 int newcount = pglob->gl_pathc + pglob->gl_offs;
843 char **new_gl_pathv;
844
845 new_gl_pathv
846 = (char **) realloc (pglob->gl_pathv,
847 (newcount + 1 + 1) * sizeof (char *));
848 if (new_gl_pathv == NULL)
849 {
850 nospace:
851 free (pglob->gl_pathv);
852 pglob->gl_pathv = NULL;
853 pglob->gl_pathc = 0;
854 return GLOB_NOSPACE;
855 }
856 pglob->gl_pathv = new_gl_pathv;
857
858 pglob->gl_pathv[newcount] = strdup (dirname);
859 if (pglob->gl_pathv[newcount] == NULL)
860 goto nospace;
861 pglob->gl_pathv[++newcount] = NULL;
862 ++pglob->gl_pathc;
863 pglob->gl_flags = flags;
864
865 return 0;
866 }
867
868 /* Not found. */
869 return GLOB_NOMATCH;
870 }
871#endif
872
873 if (glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
874 {
875 /* The directory name contains metacharacters, so we
876 have to glob for the directory, and then glob for
877 the pattern in each directory found. */
878 glob_t dirs;
879 size_t i;
880
881 if ((flags & GLOB_ALTDIRFUNC) != 0)
882 {
883 /* Use the alternative access functions also in the recursive
884 call. */
885 dirs.gl_opendir = pglob->gl_opendir;
886 dirs.gl_readdir = pglob->gl_readdir;
887 dirs.gl_closedir = pglob->gl_closedir;
888 dirs.gl_stat = pglob->gl_stat;
889 dirs.gl_lstat = pglob->gl_lstat;
890 }
891
892 status = glob (dirname,
893 ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE
894 | GLOB_ALTDIRFUNC))
895 | GLOB_NOSORT | GLOB_ONLYDIR),
896 errfunc, &dirs);
897 if (status != 0)
898 return status;
899
900 /* We have successfully globbed the preceding directory name.
901 For each name we found, call glob_in_dir on it and FILENAME,
902 appending the results to PGLOB. */
903 for (i = 0; i < dirs.gl_pathc; ++i)
904 {
905 int old_pathc;
906
907 old_pathc = pglob->gl_pathc;
908 status = glob_in_dir (filename, dirs.gl_pathv[i],
909 ((flags | GLOB_APPEND)
910 & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
911 errfunc, pglob);
912 if (status == GLOB_NOMATCH)
913 /* No matches in this directory. Try the next. */
914 continue;
915
916 if (status != 0)
917 {
918 globfree (&dirs);
919 globfree (pglob);
920 pglob->gl_pathc = 0;
921 return status;
922 }
923
924 /* Stick the directory on the front of each name. */
925 if (__prefix_array (dirs.gl_pathv[i],
926 &pglob->gl_pathv[old_pathc + pglob->gl_offs],
927 pglob->gl_pathc - old_pathc))
928 {
929 globfree (&dirs);
930 globfree (pglob);
931 pglob->gl_pathc = 0;
932 return GLOB_NOSPACE;
933 }
934 }
935
936 flags |= GLOB_MAGCHAR;
937
938 /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
939 But if we have not found any matching entry and the GLOB_NOCHECK
940 flag was set we must return the input pattern itself. */
941 if (pglob->gl_pathc + pglob->gl_offs == oldcount)
942 {
943 /* No matches. */
944 if (flags & GLOB_NOCHECK)
945 {
946 int newcount = pglob->gl_pathc + pglob->gl_offs;
947 char **new_gl_pathv;
948
949 new_gl_pathv = (char **) realloc (pglob->gl_pathv,
950 (newcount + 2)
951 * sizeof (char *));
952 if (new_gl_pathv == NULL)
953 {
954 globfree (&dirs);
955 return GLOB_NOSPACE;
956 }
957 pglob->gl_pathv = new_gl_pathv;
958
959 pglob->gl_pathv[newcount] = strdup (pattern);
960 if (pglob->gl_pathv[newcount] == NULL)
961 {
962 globfree (&dirs);
963 globfree (pglob);
964 pglob->gl_pathc = 0;
965 return GLOB_NOSPACE;
966 }
967
968 ++pglob->gl_pathc;
969 ++newcount;
970
971 pglob->gl_pathv[newcount] = NULL;
972 pglob->gl_flags = flags;
973 }
974 else
975 {
976 globfree (&dirs);
977 return GLOB_NOMATCH;
978 }
979 }
980
981 globfree (&dirs);
982 }
983 else
984 {
985 int old_pathc = pglob->gl_pathc;
986
987 status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
988 if (status != 0)
989 return status;
990
991 if (dirlen > 0)
992 {
993 /* Stick the directory on the front of each name. */
994 if (__prefix_array (dirname,
995 &pglob->gl_pathv[old_pathc + pglob->gl_offs],
996 pglob->gl_pathc - old_pathc))
997 {
998 globfree (pglob);
999 pglob->gl_pathc = 0;
1000 return GLOB_NOSPACE;
1001 }
1002 }
1003 }
1004
1005 if (flags & GLOB_MARK)
1006 {
1007 /* Append slashes to directory names. */
1008 size_t i;
1009 struct stat st;
1010 struct_stat64 st64;
1011
1012 for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i)
1013 if (((flags & GLOB_ALTDIRFUNC)
1014 ? ((*pglob->gl_stat) (pglob->gl_pathv[i], &st) == 0
1015 && S_ISDIR (st.st_mode))
1016 : (__stat64 (pglob->gl_pathv[i], &st64) == 0
1017 && S_ISDIR (st64.st_mode))))
1018 {
1019 size_t len = strlen (pglob->gl_pathv[i]) + 2;
1020 char *new = realloc (pglob->gl_pathv[i], len);
1021 if (new == NULL)
1022 {
1023 globfree (pglob);
1024 pglob->gl_pathc = 0;
1025 return GLOB_NOSPACE;
1026 }
1027 strcpy (&new[len - 2], "/");
1028 pglob->gl_pathv[i] = new;
1029 }
1030 }
1031
1032 if (!(flags & GLOB_NOSORT))
1033 {
1034 /* Sort the vector. */
1035 qsort (&pglob->gl_pathv[oldcount],
1036 pglob->gl_pathc + pglob->gl_offs - oldcount,
1037 sizeof (char *), __collated_compare);
1038 }
1039
1040 return 0;
1041}
1042#ifdef COMPILE_GLOB64
1043libc_hidden_def(glob64)
1044#else
1045libc_hidden_def(glob)
1046#endif
1047
1048
1049/* Free storage allocated in PGLOB by a previous `glob' call. */
1050void
1051globfree (register glob_t *pglob)
1052{
1053 if (pglob->gl_pathv != NULL)
1054 {
1055 size_t i;
1056 for (i = 0; i < pglob->gl_pathc; ++i)
1057 if (pglob->gl_pathv[pglob->gl_offs + i] != NULL)
1058 free (pglob->gl_pathv[pglob->gl_offs + i]);
1059 free (pglob->gl_pathv);
1060 pglob->gl_pathv = NULL;
1061 }
1062}
1063#ifdef COMPILE_GLOB64
1064libc_hidden_def(globfree64)
1065#else
1066libc_hidden_def(globfree)
1067#endif