]> git.ipfire.org Git - thirdparty/glibc.git/blame - posix/glob.c
Remove internal usage of extensible stat functions
[thirdparty/glibc.git] / posix / glob.c
CommitLineData
d614a753 1/* Copyright (C) 1991-2020 Free Software Foundation, Inc.
41bdb6e2 2 This file is part of the GNU C Library.
28f540f4 3
41bdb6e2
AJ
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.
28f540f4 8
41bdb6e2 9 The GNU C Library is distributed in the hope that it will be useful,
47707456
UD
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 12 Lesser General Public License for more details.
28f540f4 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6 15 License along with the GNU C Library; if not, see
5a82c748 16 <https://www.gnu.org/licenses/>. */
28f540f4 17
49a0ba27 18#include <glob.h>
97aa195c 19
28f540f4
RM
20#include <errno.h>
21#include <sys/types.h>
bf3ccd1a 22#include <sys/stat.h>
5171f307 23#include <stdbool.h>
49a0ba27 24#include <stddef.h>
5171f307 25#include <stdint.h>
5ae9d168 26#include <assert.h>
c66c9082 27#include <unistd.h>
5ae9d168 28
c66c9082
AZ
29#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
30# define WINDOWS32
28f540f4
RM
31#endif
32
c66c9082
AZ
33#ifndef WINDOWS32
34# include <pwd.h>
90bb2039
UD
35#endif
36
49a0ba27 37#include <errno.h>
c66c9082 38#include <dirent.h>
49a0ba27
RM
39#include <stdlib.h>
40#include <string.h>
49a0ba27 41#include <alloca.h>
bf3ccd1a 42
50304ef0 43#ifdef _LIBC
c3966b88 44# undef strdup
c9243dac 45# define strdup(str) __strdup (str)
50304ef0
UD
46# define sysconf(id) __sysconf (id)
47# define closedir(dir) __closedir (dir)
48# define opendir(name) __opendir (name)
2958e6cc 49# define readdir(str) __readdir64 (str)
ec986e23 50# define getpwnam_r(name, bufp, buf, len, res) \
c66c9082 51 __getpwnam_r (name, bufp, buf, len, res)
49a0ba27 52# define struct_stat64 struct stat64
c66c9082 53# define FLEXIBLE_ARRAY_MEMBER
ccf970c7 54# include <shlib-compat.h>
49a0ba27 55#else /* !_LIBC */
ccf970c7 56# define __glob glob
c66c9082 57# define __getlogin_r(buf, len) getlogin_r (buf, len)
5554304f 58# define __lstat64(fname, buf) lstat (fname, buf)
c66c9082 59# define __stat64(fname, buf) stat (fname, buf)
c66c9082
AZ
60# define struct_stat64 struct stat
61# ifndef __MVS__
62# define __alloca alloca
63# endif
64# define __readdir readdir
65# define COMPILE_GLOB64
49a0ba27 66#endif /* _LIBC */
50304ef0 67
28f540f4
RM
68#include <fnmatch.h>
69
c66c9082
AZ
70#include <flexmember.h>
71#include <glob_internal.h>
5a79f975 72#include <scratch_buffer.h>
28f540f4 73\f
e833b53f 74static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
60f0e64b 75
c66c9082
AZ
76typedef uint_fast8_t dirent_type;
77
78#if !defined _LIBC && !defined HAVE_STRUCT_DIRENT_D_TYPE
79/* Any distinct values will do here.
80 Undef any existing macros out of the way. */
81# undef DT_UNKNOWN
82# undef DT_DIR
83# undef DT_LNK
84# define DT_UNKNOWN 0
85# define DT_DIR 1
86# define DT_LNK 2
87#endif
88
5171f307
FW
89/* A representation of a directory entry which does not depend on the
90 layout of struct dirent, or the size of ino_t. */
91struct readdir_result
92{
93 const char *name;
c66c9082
AZ
94#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
95 dirent_type type;
96#endif
5171f307
FW
97};
98
c66c9082
AZ
99/* Initialize and return type member of struct readdir_result. */
100static dirent_type
101readdir_result_type (struct readdir_result d)
5171f307 102{
c66c9082
AZ
103#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
104# define D_TYPE_TO_RESULT(source) (source)->d_type,
105 return d.type;
106#else
107# define D_TYPE_TO_RESULT(source)
108 return DT_UNKNOWN;
109#endif
5171f307
FW
110}
111
5171f307
FW
112/* Construct an initializer for a struct readdir_result object from a
113 struct dirent *. No copy of the name is made. */
114#define READDIR_RESULT_INITIALIZER(source) \
115 { \
116 source->d_name, \
117 D_TYPE_TO_RESULT (source) \
5171f307
FW
118 }
119
5171f307
FW
120/* Call gl_readdir on STREAM. This macro can be overridden to reduce
121 type safety if an old interface version needs to be supported. */
122#ifndef GL_READDIR
123# define GL_READDIR(pglob, stream) ((pglob)->gl_readdir (stream))
124#endif
125
126/* Extract name and type from directory entry. No copy of the name is
127 made. If SOURCE is NULL, result name is NULL. Keep in sync with
128 convert_dirent64 below. */
129static struct readdir_result
130convert_dirent (const struct dirent *source)
131{
132 if (source == NULL)
133 {
134 struct readdir_result result = { NULL, };
135 return result;
136 }
137 struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
138 return result;
139}
140
141#ifndef COMPILE_GLOB64
142/* Like convert_dirent, but works on struct dirent64 instead. Keep in
143 sync with convert_dirent above. */
144static struct readdir_result
145convert_dirent64 (const struct dirent64 *source)
146{
147 if (source == NULL)
148 {
149 struct readdir_result result = { NULL, };
150 return result;
151 }
152 struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
153 return result;
154}
155#endif
156
c66c9082
AZ
157#ifndef _LIBC
158/* The results of opendir() in this file are not used with dirfd and fchdir,
159 and we do not leak fds to any single-threaded code that could use stdio,
160 therefore save some unnecessary recursion in fchdir.c and opendir_safer.c.
161 FIXME - if the kernel ever adds support for multi-thread safety for
162 avoiding standard fds, then we should use opendir_safer. */
163# ifdef GNULIB_defined_opendir
164# undef opendir
165# endif
166# ifdef GNULIB_defined_closedir
167# undef closedir
168# endif
5171f307 169
c66c9082
AZ
170/* Just use malloc. */
171# define __libc_use_alloca(n) false
172# define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0)
173# define extend_alloca_account(buf, len, newlen, avar) \
174 ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0)
05f135ba
UD
175#endif
176
ccf970c7
AZ
177static int
178glob_lstat (glob_t *pglob, int flags, const char *fullname)
179{
180/* Use on glob-lstat-compat.c to provide a compat symbol which does not
181 use lstat / gl_lstat. */
182#ifdef GLOB_NO_LSTAT
183# define GL_LSTAT gl_stat
184# define LSTAT64 __stat64
185#else
186# define GL_LSTAT gl_lstat
187# define LSTAT64 __lstat64
188#endif
189
190 union
191 {
192 struct stat st;
193 struct_stat64 st64;
194 } ust;
195 return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
196 ? pglob->GL_LSTAT (fullname, &ust.st)
197 : LSTAT64 (fullname, &ust.st64));
198}
199
c66c9082
AZ
200/* Set *R = A + B. Return true if the answer is mathematically
201 incorrect due to overflow; in this case, *R is the low order
202 bits of the correct answer. */
203
204static bool
205size_add_wrapv (size_t a, size_t b, size_t *r)
206{
207#if 5 <= __GNUC__ && !defined __ICC
208 return __builtin_add_overflow (a, b, r);
209#else
210 *r = a + b;
211 return *r < a;
212#endif
213}
214
215static bool
216glob_use_alloca (size_t alloca_used, size_t len)
217{
218 size_t size;
219 return (!size_add_wrapv (alloca_used, len, &size)
220 && __libc_use_alloca (size));
221}
222
79937577
UD
223static int glob_in_dir (const char *pattern, const char *directory,
224 int flags, int (*errfunc) (const char *, int),
f2962a71 225 glob_t *pglob, size_t alloca_used);
e833b53f
EB
226static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL;
227static int collated_compare (const void *, const void *) __THROWNL;
28f540f4 228
5ae9d168 229
5554304f
AZ
230/* Return true if FILENAME is a directory or a symbolic link to a directory.
231 Use FLAGS and PGLOB to resolve the filename. */
232static bool
233is_dir (char const *filename, int flags, glob_t const *pglob)
234{
235 struct stat st;
236 struct_stat64 st64;
237 return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
238 ? pglob->gl_stat (filename, &st) == 0 && S_ISDIR (st.st_mode)
239 : __stat64 (filename, &st64) == 0 && S_ISDIR (st64.st_mode));
240}
241
98d2ca3d
UD
242/* Find the end of the sub-pattern in a brace expression. */
243static const char *
49a0ba27 244next_brace_sub (const char *cp, int flags)
5ae9d168 245{
b87c4b24 246 size_t depth = 0;
98d2ca3d
UD
247 while (*cp != '\0')
248 if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\')
249 {
250 if (*++cp == '\0')
251 break;
252 ++cp;
253 }
254 else
255 {
256 if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
257 break;
258
259 if (*cp++ == '{')
260 depth++;
261 }
262
638670cd 263 return *cp != '\0' ? cp : NULL;
5ae9d168
UD
264}
265
ccf970c7
AZ
266#ifndef GLOB_ATTRIBUTE
267# define GLOB_ATTRIBUTE
268#endif
60f0e64b 269
28f540f4
RM
270/* Do glob searching for PATTERN, placing results in PGLOB.
271 The bits defined above may be set in FLAGS.
272 If a directory cannot be opened or read and ERRFUNC is not nil,
273 it is called with the pathname that caused the error, and the
c66c9082
AZ
274 'errno' value from the failing call; if it returns non-zero
275 'glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
28f540f4 276 If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
c66c9082 277 Otherwise, 'glob' returns zero. */
28f540f4 278int
4a381a81 279GLOB_ATTRIBUTE
ccf970c7
AZ
280__glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
281 glob_t *pglob)
28f540f4
RM
282{
283 const char *filename;
f2962a71 284 char *dirname = NULL;
28f540f4
RM
285 size_t dirlen;
286 int status;
ec6f8477 287 size_t oldcount;
05f135ba
UD
288 int meta;
289 int dirname_modified;
f2962a71 290 int malloc_dirname = 0;
05f135ba 291 glob_t dirs;
f2962a71 292 int retval = 0;
f2962a71 293 size_t alloca_used = 0;
28f540f4
RM
294
295 if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
296 {
c4029823 297 __set_errno (EINVAL);
28f540f4
RM
298 return -1;
299 }
300
a471e96a
OB
301 /* POSIX requires all slashes to be matched. This means that with
302 a trailing slash we must match only directories. */
303 if (pattern[0] && pattern[strlen (pattern) - 1] == '/')
304 flags |= GLOB_ONLYDIR;
305
460adbb8 306 if (!(flags & GLOB_DOOFFS))
c66c9082 307 /* Have to do this so 'globfree' knows where to start freeing. It
460adbb8
UD
308 also makes all the code that uses gl_offs simpler. */
309 pglob->gl_offs = 0;
310
44c637ce
AS
311 if (!(flags & GLOB_APPEND))
312 {
313 pglob->gl_pathc = 0;
314 if (!(flags & GLOB_DOOFFS))
315 pglob->gl_pathv = NULL;
316 else
317 {
318 size_t i;
319
320 if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
321 return GLOB_NOSPACE;
322
323 pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
324 * sizeof (char *));
325 if (pglob->gl_pathv == NULL)
326 return GLOB_NOSPACE;
327
328 for (i = 0; i <= pglob->gl_offs; ++i)
329 pglob->gl_pathv[i] = NULL;
330 }
331 }
332
787e4db9
RM
333 if (flags & GLOB_BRACE)
334 {
98d2ca3d
UD
335 const char *begin;
336
337 if (flags & GLOB_NOESCAPE)
338 begin = strchr (pattern, '{');
339 else
340 {
341 begin = pattern;
342 while (1)
343 {
344 if (*begin == '\0')
345 {
346 begin = NULL;
347 break;
348 }
349
350 if (*begin == '\\' && begin[1] != '\0')
351 ++begin;
352 else if (*begin == '{')
353 break;
354
355 ++begin;
356 }
357 }
358
787e4db9
RM
359 if (begin != NULL)
360 {
5ae9d168
UD
361 /* Allocate working buffer large enough for our work. Note that
362 we have at least an opening and closing brace. */
ec6f8477 363 size_t firstc;
5ae9d168
UD
364 char *alt_start;
365 const char *p;
366 const char *next;
367 const char *rest;
368 size_t rest_len;
f2962a71
UD
369 char *onealt;
370 size_t pattern_len = strlen (pattern) - 1;
c66c9082 371 int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
f2962a71
UD
372 if (alloca_onealt)
373 onealt = alloca_account (pattern_len, alloca_used);
374 else
5ae9d168 375 {
c66c9082 376 onealt = malloc (pattern_len);
f2962a71 377 if (onealt == NULL)
44c637ce 378 return GLOB_NOSPACE;
5ae9d168 379 }
5ae9d168
UD
380
381 /* We know the prefix for all sub-patterns. */
86187531 382 alt_start = mempcpy (onealt, pattern, begin - pattern);
5ae9d168
UD
383
384 /* Find the first sub-pattern and at the same time find the
385 rest after the closing brace. */
98d2ca3d 386 next = next_brace_sub (begin + 1, flags);
5ae9d168 387 if (next == NULL)
787e4db9 388 {
c66c9082 389 /* It is an invalid expression. */
f2962a71 390 illegal_brace:
a1ffb40e 391 if (__glibc_unlikely (!alloca_onealt))
f2962a71 392 free (onealt);
44c637ce
AS
393 flags &= ~GLOB_BRACE;
394 goto no_brace;
5ae9d168
UD
395 }
396
397 /* Now find the end of the whole brace expression. */
398 rest = next;
399 while (*rest != '}')
400 {
98d2ca3d 401 rest = next_brace_sub (rest + 1, flags);
5ae9d168 402 if (rest == NULL)
f2962a71
UD
403 /* It is an illegal expression. */
404 goto illegal_brace;
6025c399 405 }
5ae9d168
UD
406 /* Please note that we now can be sure the brace expression
407 is well-formed. */
408 rest_len = strlen (++rest) + 1;
6025c399
RM
409
410 /* We have a brace expression. BEGIN points to the opening {,
411 NEXT points past the terminator of the first element, and END
412 points past the final }. We will accumulate result names from
413 recursive runs for each brace alternative in the buffer using
414 GLOB_APPEND. */
6025c399
RM
415 firstc = pglob->gl_pathc;
416
6025c399
RM
417 p = begin + 1;
418 while (1)
419 {
6025c399 420 int result;
5ae9d168
UD
421
422 /* Construct the new glob expression. */
dd7d45e8 423 mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
5ae9d168 424
ccf970c7
AZ
425 result = __glob (onealt,
426 ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
427 | GLOB_APPEND),
428 errfunc, pglob);
6025c399
RM
429
430 /* If we got an error, return it. */
431 if (result && result != GLOB_NOMATCH)
787e4db9 432 {
a1ffb40e 433 if (__glibc_unlikely (!alloca_onealt))
f2962a71 434 free (onealt);
6025c399 435 if (!(flags & GLOB_APPEND))
03af5793
UD
436 {
437 globfree (pglob);
438 pglob->gl_pathc = 0;
439 }
6025c399
RM
440 return result;
441 }
442
5ae9d168
UD
443 if (*next == '}')
444 /* We saw the last entry. */
445 break;
446
447 p = next + 1;
98d2ca3d 448 next = next_brace_sub (p, flags);
5ae9d168 449 assert (next != NULL);
787e4db9 450 }
6025c399 451
a1ffb40e 452 if (__glibc_unlikely (!alloca_onealt))
f2962a71 453 free (onealt);
5ae9d168
UD
454
455 if (pglob->gl_pathc != firstc)
456 /* We found some entries. */
457 return 0;
458 else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
6025c399 459 return GLOB_NOMATCH;
787e4db9
RM
460 }
461 }
462
44c637ce 463 no_brace:
a5f3b0f8
UD
464 oldcount = pglob->gl_pathc + pglob->gl_offs;
465
28f540f4
RM
466 /* Find the filename. */
467 filename = strrchr (pattern, '/');
c66c9082 468
786a5421 469#if defined __MSDOS__ || defined WINDOWS32
c66c9082 470 /* The case of "d:pattern". Since ':' is not allowed in
786a5421
UD
471 file names, we can safely assume that wherever it
472 happens in pattern, it signals the filename part. This
473 is so we could some day support patterns like "[a-z]:foo". */
474 if (filename == NULL)
475 filename = strchr (pattern, ':');
476#endif /* __MSDOS__ || WINDOWS32 */
c66c9082 477
05f135ba 478 dirname_modified = 0;
28f540f4
RM
479 if (filename == NULL)
480 {
49c091e5 481 /* This can mean two things: a simple name or "~name". The latter
6c202c68 482 case is nothing but a notation for a directory. */
1bc21e7a 483 if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
6c202c68 484 {
f2962a71 485 dirname = (char *) pattern;
6c202c68
UD
486 dirlen = strlen (pattern);
487
c9243dac 488 /* Set FILENAME to NULL as a special flag. This is ugly but
786a5421 489 other solutions would require much more code. We test for
c9243dac
UD
490 this special case below. */
491 filename = NULL;
6c202c68
UD
492 }
493 else
494 {
a1ffb40e 495 if (__glibc_unlikely (pattern[0] == '\0'))
8f2e3994
UD
496 {
497 dirs.gl_pathv = NULL;
498 goto no_matches;
499 }
500
6c202c68 501 filename = pattern;
f2962a71 502 dirname = (char *) ".";
6c202c68
UD
503 dirlen = 0;
504 }
28f540f4 505 }
c8d48fae 506 else if (filename == pattern
64ba41bc
UD
507 || (filename == pattern + 1 && pattern[0] == '\\'
508 && (flags & GLOB_NOESCAPE) == 0))
28f540f4 509 {
c8d48fae 510 /* "/pattern" or "\\/pattern". */
f2962a71 511 dirname = (char *) "/";
28f540f4
RM
512 dirlen = 1;
513 ++filename;
514 }
515 else
516 {
ec986e23 517 char *newp;
28f540f4 518 dirlen = filename - pattern;
786a5421
UD
519#if defined __MSDOS__ || defined WINDOWS32
520 if (*filename == ':'
521 || (filename > pattern + 1 && filename[-1] == ':'))
522 {
523 char *drive_spec;
524
525 ++dirlen;
c66c9082 526 drive_spec = __alloca (dirlen + 1);
786a5421 527 *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
786a5421
UD
528 /* For now, disallow wildcards in the drive spec, to
529 prevent infinite recursion in glob. */
530 if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
531 return GLOB_NOMATCH;
c66c9082 532 /* If this is "d:pattern", we need to copy ':' to DIRNAME
786a5421
UD
533 as well. If it's "d:/pattern", don't remove the slash
534 from "d:/", since "d:" and "d:/" are not the same.*/
535 }
536#endif
c66c9082
AZ
537
538 if (glob_use_alloca (alloca_used, dirlen + 1))
f2962a71
UD
539 newp = alloca_account (dirlen + 1, alloca_used);
540 else
f2962a71
UD
541 {
542 newp = malloc (dirlen + 1);
543 if (newp == NULL)
544 return GLOB_NOSPACE;
545 malloc_dirname = 1;
546 }
ec986e23 547 *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
ec986e23 548 dirname = newp;
28f540f4 549 ++filename;
28f540f4 550
786a5421 551#if defined __MSDOS__ || defined WINDOWS32
c66c9082
AZ
552 bool drive_root = (dirlen > 1
553 && (dirname[dirlen - 1] == ':'
554 || (dirlen > 2 && dirname[dirlen - 2] == ':'
555 && dirname[dirlen - 1] == '/')));
556#else
557 bool drive_root = false;
786a5421 558#endif
c66c9082
AZ
559
560 if (filename[0] == '\0' && dirlen > 1 && !drive_root)
561 /* "pattern/". Expand "pattern", appending slashes. */
6c202c68 562 {
05f135ba
UD
563 int orig_flags = flags;
564 if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
565 {
566 /* "pattern\\/". Remove the final backslash if it hasn't
567 been quoted. */
568 char *p = (char *) &dirname[dirlen - 1];
569
570 while (p > dirname && p[-1] == '\\') --p;
571 if ((&dirname[dirlen] - p) & 1)
572 {
573 *(char *) &dirname[--dirlen] = '\0';
574 flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
575 }
576 }
ccf970c7 577 int val = __glob (dirname, flags | GLOB_MARK, errfunc, pglob);
6c202c68
UD
578 if (val == 0)
579 pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
580 | (flags & GLOB_MARK));
05f135ba
UD
581 else if (val == GLOB_NOMATCH && flags != orig_flags)
582 {
583 /* Make sure globfree (&dirs); is a nop. */
584 dirs.gl_pathv = NULL;
585 flags = orig_flags;
586 oldcount = pglob->gl_pathc + pglob->gl_offs;
587 goto no_matches;
588 }
f2962a71
UD
589 retval = val;
590 goto out;
6c202c68 591 }
28f540f4
RM
592 }
593
1bc21e7a 594 if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
787e4db9 595 {
05f135ba
UD
596 if (dirname[1] == '\0' || dirname[1] == '/'
597 || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\'
598 && (dirname[2] == '\0' || dirname[2] == '/')))
787e4db9
RM
599 {
600 /* Look up home directory. */
f2962a71
UD
601 char *home_dir = getenv ("HOME");
602 int malloc_home_dir = 0;
5ae9d168 603 if (home_dir == NULL || home_dir[0] == '\0')
787e4db9 604 {
c66c9082
AZ
605#ifdef WINDOWS32
606 /* Windows NT defines HOMEDRIVE and HOMEPATH. But give
607 preference to HOME, because the user can change HOME. */
608 const char *home_drive = getenv ("HOMEDRIVE");
609 const char *home_path = getenv ("HOMEPATH");
610
611 if (home_drive != NULL && home_path != NULL)
612 {
613 size_t home_drive_len = strlen (home_drive);
614 size_t home_path_len = strlen (home_path);
615 char *mem = alloca (home_drive_len + home_path_len + 1);
616
617 memcpy (mem, home_drive, home_drive_len);
618 memcpy (mem + home_drive_len, home_path, home_path_len + 1);
619 home_dir = mem;
620 }
621 else
622 home_dir = "c:/users/default"; /* poor default */
623#else
ffca8901
AZ
624 int err;
625 struct passwd *p;
626 struct passwd pwbuf;
627 struct scratch_buffer s;
628 scratch_buffer_init (&s);
629 while (true)
c66c9082 630 {
ffca8901
AZ
631 p = NULL;
632 err = __getlogin_r (s.data, s.length);
633 if (err == 0)
c66c9082 634 {
c66c9082 635# if defined HAVE_GETPWNAM_R || defined _LIBC
ffca8901 636 size_t ssize = strlen (s.data) + 1;
e184ac3a
AZ
637 char *sdata = s.data;
638 err = getpwnam_r (sdata, &pwbuf, sdata + ssize,
ffca8901 639 s.length - ssize, &p);
c66c9082 640# else
ffca8901
AZ
641 p = getpwnam (s.data);
642 if (p == NULL)
643 err = errno;
c66c9082 644# endif
ffca8901
AZ
645 }
646 if (err != ERANGE)
647 break;
648 if (!scratch_buffer_grow (&s))
f2962a71 649 {
ffca8901
AZ
650 retval = GLOB_NOSPACE;
651 goto out;
f2962a71 652 }
787e4db9 653 }
ffca8901 654 if (err == 0)
c66c9082 655 {
ffca8901
AZ
656 home_dir = strdup (p->pw_dir);
657 malloc_home_dir = 1;
658 }
659 scratch_buffer_free (&s);
660 if (err == 0 && home_dir == NULL)
661 {
662 retval = GLOB_NOSPACE;
663 goto out;
c66c9082
AZ
664 }
665#endif /* WINDOWS32 */
787e4db9 666 }
5ae9d168 667 if (home_dir == NULL || home_dir[0] == '\0')
6e4c40ba 668 {
c66c9082
AZ
669 if (__glibc_unlikely (malloc_home_dir))
670 free (home_dir);
6e4c40ba 671 if (flags & GLOB_TILDE_CHECK)
f2962a71 672 {
f2962a71
UD
673 retval = GLOB_NOMATCH;
674 goto out;
675 }
6e4c40ba 676 else
c66c9082
AZ
677 {
678 home_dir = (char *) "~"; /* No luck. */
679 malloc_home_dir = 0;
680 }
6e4c40ba 681 }
5ae9d168
UD
682 /* Now construct the full directory. */
683 if (dirname[1] == '\0')
05f135ba 684 {
a1ffb40e 685 if (__glibc_unlikely (malloc_dirname))
f2962a71
UD
686 free (dirname);
687
05f135ba
UD
688 dirname = home_dir;
689 dirlen = strlen (dirname);
f2962a71 690 malloc_dirname = malloc_home_dir;
05f135ba 691 }
5ae9d168
UD
692 else
693 {
694 char *newp;
695 size_t home_len = strlen (home_dir);
c66c9082 696 int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
f2962a71
UD
697 if (use_alloca)
698 newp = alloca_account (home_len + dirlen, alloca_used);
699 else
700 {
701 newp = malloc (home_len + dirlen);
702 if (newp == NULL)
703 {
a1ffb40e 704 if (__glibc_unlikely (malloc_home_dir))
f2962a71
UD
705 free (home_dir);
706 retval = GLOB_NOSPACE;
707 goto out;
708 }
709 }
710
dd7d45e8
UD
711 mempcpy (mempcpy (newp, home_dir, home_len),
712 &dirname[1], dirlen);
f2962a71 713
a1ffb40e 714 if (__glibc_unlikely (malloc_dirname))
f2962a71
UD
715 free (dirname);
716
5ae9d168 717 dirname = newp;
05f135ba 718 dirlen += home_len - 1;
f2962a71 719 malloc_dirname = !use_alloca;
c66c9082
AZ
720
721 if (__glibc_unlikely (malloc_home_dir))
722 free (home_dir);
5ae9d168 723 }
05f135ba 724 dirname_modified = 1;
787e4db9
RM
725 }
726 else
727 {
c66c9082 728#ifndef WINDOWS32
5ae9d168 729 char *end_name = strchr (dirname, '/');
f2962a71
UD
730 char *user_name;
731 int malloc_user_name = 0;
05f135ba 732 char *unescape = NULL;
5ae9d168 733
05f135ba
UD
734 if (!(flags & GLOB_NOESCAPE))
735 {
736 if (end_name == NULL)
737 {
738 unescape = strchr (dirname, '\\');
739 if (unescape)
740 end_name = strchr (unescape, '\0');
741 }
742 else
743 unescape = memchr (dirname, '\\', end_name - dirname);
744 }
5ae9d168
UD
745 if (end_name == NULL)
746 user_name = dirname + 1;
747 else
748 {
ec986e23 749 char *newp;
c66c9082 750 if (glob_use_alloca (alloca_used, end_name - dirname))
f2962a71
UD
751 newp = alloca_account (end_name - dirname, alloca_used);
752 else
753 {
754 newp = malloc (end_name - dirname);
755 if (newp == NULL)
756 {
757 retval = GLOB_NOSPACE;
758 goto out;
759 }
760 malloc_user_name = 1;
761 }
05f135ba
UD
762 if (unescape != NULL)
763 {
764 char *p = mempcpy (newp, dirname + 1,
765 unescape - dirname - 1);
766 char *q = unescape;
a159b53f 767 while (q != end_name)
05f135ba
UD
768 {
769 if (*q == '\\')
770 {
a159b53f 771 if (q + 1 == end_name)
05f135ba
UD
772 {
773 /* "~fo\\o\\" unescape to user_name "foo\\",
774 but "~fo\\o\\/" unescape to user_name
775 "foo". */
776 if (filename == NULL)
777 *p++ = '\\';
778 break;
779 }
780 ++q;
781 }
782 *p++ = *q++;
783 }
784 *p = '\0';
785 }
786 else
c369d66e 787 *((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1))
05f135ba 788 = '\0';
ec986e23 789 user_name = newp;
5ae9d168
UD
790 }
791
787e4db9 792 /* Look up specific user's home directory. */
5ae9d168 793 {
ec986e23 794 struct passwd *p;
5a79f975
AZ
795 struct scratch_buffer pwtmpbuf;
796 scratch_buffer_init (&pwtmpbuf);
797
61eb22d3 798# if defined HAVE_GETPWNAM_R || defined _LIBC
ec986e23 799 struct passwd pwbuf;
5a79f975
AZ
800
801 while (getpwnam_r (user_name, &pwbuf,
802 pwtmpbuf.data, pwtmpbuf.length, &p)
803 == ERANGE)
f2962a71 804 {
5a79f975 805 if (!scratch_buffer_grow (&pwtmpbuf))
f2962a71 806 {
f2962a71
UD
807 retval = GLOB_NOSPACE;
808 goto out;
809 }
f6b56b55 810 }
61eb22d3 811# else
ec986e23 812 p = getpwnam (user_name);
f6b56b55 813# endif
f2962a71 814
a1ffb40e 815 if (__glibc_unlikely (malloc_user_name))
f2962a71
UD
816 free (user_name);
817
818 /* If we found a home directory use this. */
5ae9d168 819 if (p != NULL)
f2962a71
UD
820 {
821 size_t home_len = strlen (p->pw_dir);
822 size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
ddc650e9
AS
823 char *d, *newp;
824 bool use_alloca = glob_use_alloca (alloca_used,
825 home_len + rest_len + 1);
f2962a71 826
ddc650e9
AS
827 if (use_alloca)
828 newp = alloca_account (home_len + rest_len + 1, alloca_used);
f2962a71
UD
829 else
830 {
ddc650e9
AS
831 newp = malloc (home_len + rest_len + 1);
832 if (newp == NULL)
f2962a71 833 {
5a79f975 834 scratch_buffer_free (&pwtmpbuf);
f2962a71
UD
835 retval = GLOB_NOSPACE;
836 goto out;
837 }
f2962a71 838 }
ddc650e9 839 d = mempcpy (newp, p->pw_dir, home_len);
d711a00f
AZ
840 if (end_name != NULL)
841 d = mempcpy (d, end_name, rest_len);
842 *d = '\0';
f2962a71 843
ddc650e9
AS
844 if (__glibc_unlikely (malloc_dirname))
845 free (dirname);
846 dirname = newp;
847 malloc_dirname = !use_alloca;
848
f2962a71
UD
849 dirlen = home_len + rest_len;
850 dirname_modified = 1;
f2962a71 851 }
5ae9d168 852 else
f2962a71 853 {
f2962a71 854 if (flags & GLOB_TILDE_CHECK)
c66c9082
AZ
855 {
856 /* We have to regard it as an error if we cannot find the
857 home directory. */
858 retval = GLOB_NOMATCH;
859 goto out;
860 }
f2962a71 861 }
5a79f975 862 scratch_buffer_free (&pwtmpbuf);
5ae9d168 863 }
c66c9082 864#endif /* !WINDOWS32 */
787e4db9
RM
865 }
866 }
867
c9243dac
UD
868 /* Now test whether we looked for "~" or "~NAME". In this case we
869 can give the answer now. */
870 if (filename == NULL)
871 {
5554304f
AZ
872 size_t newcount = pglob->gl_pathc + pglob->gl_offs;
873 char **new_gl_pathv;
460adbb8 874
5554304f
AZ
875 if (newcount > SIZE_MAX / sizeof (char *) - 2)
876 {
877 nospace:
878 free (pglob->gl_pathv);
879 pglob->gl_pathv = NULL;
880 pglob->gl_pathc = 0;
881 retval = GLOB_NOSPACE;
882 goto out;
883 }
90bb2039 884
5554304f
AZ
885 new_gl_pathv = realloc (pglob->gl_pathv,
886 (newcount + 2) * sizeof (char *));
887 if (new_gl_pathv == NULL)
888 goto nospace;
889 pglob->gl_pathv = new_gl_pathv;
c9243dac 890
5554304f
AZ
891 if (flags & GLOB_MARK && is_dir (dirname, flags, pglob))
892 {
893 char *p;
894 pglob->gl_pathv[newcount] = malloc (dirlen + 2);
895 if (pglob->gl_pathv[newcount] == NULL)
896 goto nospace;
897 p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
898 p[0] = '/';
899 p[1] = '\0';
900 if (__glibc_unlikely (malloc_dirname))
901 free (dirname);
902 }
903 else
904 {
905 if (__glibc_unlikely (malloc_dirname))
906 pglob->gl_pathv[newcount] = dirname;
907 else
908 {
909 pglob->gl_pathv[newcount] = strdup (dirname);
910 if (pglob->gl_pathv[newcount] == NULL)
911 goto nospace;
912 }
913 }
914 pglob->gl_pathv[++newcount] = NULL;
915 ++pglob->gl_pathc;
916 pglob->gl_flags = flags;
c9243dac 917
5554304f 918 return 0;
c9243dac
UD
919 }
920
05f135ba
UD
921 meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE));
922 /* meta is 1 if correct glob pattern containing metacharacters.
923 If meta has bit (1 << 2) set, it means there was an unterminated
924 [ which we handle the same, using fnmatch. Broken unterminated
925 pattern bracket expressions ought to be rare enough that it is
926 not worth special casing them, fnmatch will do the right thing. */
07b4f49d 927 if (meta & (GLOBPAT_SPECIAL | GLOBPAT_BRACKET))
28f540f4
RM
928 {
929 /* The directory name contains metacharacters, so we
930 have to glob for the directory, and then glob for
931 the pattern in each directory found. */
ec6f8477 932 size_t i;
28f540f4 933
05f135ba
UD
934 if (!(flags & GLOB_NOESCAPE) && dirlen > 0 && dirname[dirlen - 1] == '\\')
935 {
936 /* "foo\\/bar". Remove the final backslash from dirname
937 if it has not been quoted. */
938 char *p = (char *) &dirname[dirlen - 1];
939
940 while (p > dirname && p[-1] == '\\') --p;
941 if ((&dirname[dirlen] - p) & 1)
942 *(char *) &dirname[--dirlen] = '\0';
943 }
944
a1ffb40e 945 if (__glibc_unlikely ((flags & GLOB_ALTDIRFUNC) != 0))
29332175
UD
946 {
947 /* Use the alternative access functions also in the recursive
948 call. */
949 dirs.gl_opendir = pglob->gl_opendir;
950 dirs.gl_readdir = pglob->gl_readdir;
951 dirs.gl_closedir = pglob->gl_closedir;
952 dirs.gl_stat = pglob->gl_stat;
953 dirs.gl_lstat = pglob->gl_lstat;
954 }
955
ccf970c7
AZ
956 status = __glob (dirname,
957 ((flags & (GLOB_ERR | GLOB_NOESCAPE | GLOB_ALTDIRFUNC))
958 | GLOB_NOSORT | GLOB_ONLYDIR),
959 errfunc, &dirs);
28f540f4 960 if (status != 0)
05f135ba
UD
961 {
962 if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
c66c9082
AZ
963 {
964 retval = status;
965 goto out;
966 }
05f135ba
UD
967 goto no_matches;
968 }
28f540f4
RM
969
970 /* We have successfully globbed the preceding directory name.
971 For each name we found, call glob_in_dir on it and FILENAME,
972 appending the results to PGLOB. */
973 for (i = 0; i < dirs.gl_pathc; ++i)
974 {
b87c4b24 975 size_t old_pathc;
28f540f4 976
cc60175e 977 old_pathc = pglob->gl_pathc;
28f540f4 978 status = glob_in_dir (filename, dirs.gl_pathv[i],
add09583
UD
979 ((flags | GLOB_APPEND)
980 & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
f2962a71 981 errfunc, pglob, alloca_used);
28f540f4
RM
982 if (status == GLOB_NOMATCH)
983 /* No matches in this directory. Try the next. */
984 continue;
985
986 if (status != 0)
987 {
988 globfree (&dirs);
989 globfree (pglob);
03af5793 990 pglob->gl_pathc = 0;
c66c9082
AZ
991 retval = status;
992 goto out;
28f540f4
RM
993 }
994
995 /* Stick the directory on the front of each name. */
996 if (prefix_array (dirs.gl_pathv[i],
460adbb8 997 &pglob->gl_pathv[old_pathc + pglob->gl_offs],
cc60175e 998 pglob->gl_pathc - old_pathc))
28f540f4
RM
999 {
1000 globfree (&dirs);
1001 globfree (pglob);
03af5793 1002 pglob->gl_pathc = 0;
c66c9082
AZ
1003 retval = GLOB_NOSPACE;
1004 goto out;
28f540f4
RM
1005 }
1006 }
1007
1008 flags |= GLOB_MAGCHAR;
1009
c66c9082 1010 /* We have ignored the GLOB_NOCHECK flag in the 'glob_in_dir' calls.
460adbb8 1011 But if we have not found any matching entry and the GLOB_NOCHECK
d1dddedf 1012 flag was set we must return the input pattern itself. */
460adbb8 1013 if (pglob->gl_pathc + pglob->gl_offs == oldcount)
6e4c40ba 1014 {
05f135ba 1015 no_matches:
6e4c40ba
UD
1016 /* No matches. */
1017 if (flags & GLOB_NOCHECK)
1018 {
b87c4b24 1019 size_t newcount = pglob->gl_pathc + pglob->gl_offs;
d1dddedf 1020 char **new_gl_pathv;
6e4c40ba 1021
c66c9082 1022 if (newcount > SIZE_MAX / sizeof (char *) - 2)
6e4c40ba 1023 {
90bb2039 1024 nospace2:
6e4c40ba 1025 globfree (&dirs);
c66c9082
AZ
1026 retval = GLOB_NOSPACE;
1027 goto out;
6e4c40ba 1028 }
90bb2039 1029
c66c9082
AZ
1030 new_gl_pathv = realloc (pglob->gl_pathv,
1031 (newcount + 2) * sizeof (char *));
90bb2039
UD
1032 if (new_gl_pathv == NULL)
1033 goto nospace2;
d1dddedf 1034 pglob->gl_pathv = new_gl_pathv;
28f540f4 1035
c66c9082 1036 pglob->gl_pathv[newcount] = strdup (pattern);
870a4e12 1037 if (pglob->gl_pathv[newcount] == NULL)
6e4c40ba 1038 {
870a4e12
UD
1039 globfree (&dirs);
1040 globfree (pglob);
03af5793 1041 pglob->gl_pathc = 0;
c66c9082
AZ
1042 retval = GLOB_NOSPACE;
1043 goto out;
6e4c40ba 1044 }
e852e889 1045
870a4e12
UD
1046 ++pglob->gl_pathc;
1047 ++newcount;
1048
460adbb8 1049 pglob->gl_pathv[newcount] = NULL;
6e4c40ba 1050 pglob->gl_flags = flags;
6e4c40ba
UD
1051 }
1052 else
1338451b
AJ
1053 {
1054 globfree (&dirs);
c66c9082
AZ
1055 retval = GLOB_NOMATCH;
1056 goto out;
1338451b 1057 }
6e4c40ba 1058 }
e852e889
UD
1059
1060 globfree (&dirs);
28f540f4
RM
1061 }
1062 else
1063 {
b87c4b24 1064 size_t old_pathc = pglob->gl_pathc;
05f135ba 1065 int orig_flags = flags;
460adbb8 1066
07b4f49d 1067 if (meta & GLOBPAT_BACKSLASH)
05f135ba
UD
1068 {
1069 char *p = strchr (dirname, '\\'), *q;
1070 /* We need to unescape the dirname string. It is certainly
1071 allocated by alloca, as otherwise filename would be NULL
1072 or dirname wouldn't contain backslashes. */
1073 q = p;
1074 do
1075 {
1076 if (*p == '\\')
1077 {
1078 *q = *++p;
1079 --dirlen;
1080 }
1081 else
1082 *q = *p;
1083 ++q;
1084 }
1085 while (*p++ != '\0');
1086 dirname_modified = 1;
1087 }
1088 if (dirname_modified)
1089 flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
f2962a71
UD
1090 status = glob_in_dir (filename, dirname, flags, errfunc, pglob,
1091 alloca_used);
28f540f4 1092 if (status != 0)
05f135ba
UD
1093 {
1094 if (status == GLOB_NOMATCH && flags != orig_flags
1095 && pglob->gl_pathc + pglob->gl_offs == oldcount)
1096 {
1097 /* Make sure globfree (&dirs); is a nop. */
1098 dirs.gl_pathv = NULL;
1099 flags = orig_flags;
1100 goto no_matches;
1101 }
c66c9082
AZ
1102 retval = status;
1103 goto out;
05f135ba 1104 }
28f540f4
RM
1105
1106 if (dirlen > 0)
1107 {
1108 /* Stick the directory on the front of each name. */
1109 if (prefix_array (dirname,
460adbb8
UD
1110 &pglob->gl_pathv[old_pathc + pglob->gl_offs],
1111 pglob->gl_pathc - old_pathc))
28f540f4
RM
1112 {
1113 globfree (pglob);
03af5793 1114 pglob->gl_pathc = 0;
c66c9082
AZ
1115 retval = GLOB_NOSPACE;
1116 goto out;
28f540f4
RM
1117 }
1118 }
1119 }
1120
bf3ccd1a
RM
1121 if (flags & GLOB_MARK)
1122 {
c043db7a 1123 /* Append slashes to directory names. */
ec6f8477 1124 size_t i;
460adbb8
UD
1125
1126 for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i)
5554304f 1127 if (is_dir (pglob->gl_pathv[i], flags, pglob))
a993273c 1128 {
0a164fe0 1129 size_t len = strlen (pglob->gl_pathv[i]) + 2;
a993273c 1130 char *new = realloc (pglob->gl_pathv[i], len);
0a164fe0 1131 if (new == NULL)
a993273c
RM
1132 {
1133 globfree (pglob);
03af5793 1134 pglob->gl_pathc = 0;
c66c9082
AZ
1135 retval = GLOB_NOSPACE;
1136 goto out;
a993273c
RM
1137 }
1138 strcpy (&new[len - 2], "/");
1139 pglob->gl_pathv[i] = new;
1140 }
bf3ccd1a
RM
1141 }
1142
28f540f4 1143 if (!(flags & GLOB_NOSORT))
cc60175e
UD
1144 {
1145 /* Sort the vector. */
49a0ba27 1146 qsort (&pglob->gl_pathv[oldcount],
460adbb8 1147 pglob->gl_pathc + pglob->gl_offs - oldcount,
cc60175e
UD
1148 sizeof (char *), collated_compare);
1149 }
28f540f4 1150
f2962a71 1151 out:
a1ffb40e 1152 if (__glibc_unlikely (malloc_dirname))
f2962a71
UD
1153 free (dirname);
1154
1155 return retval;
28f540f4 1156}
ccf970c7
AZ
1157#if defined _LIBC && !defined __glob
1158versioned_symbol (libc, __glob, glob, GLIBC_2_27);
1159libc_hidden_ver (__glob, glob)
c41f555e 1160#endif
28f540f4
RM
1161
1162
28f540f4
RM
1163/* Do a collated comparison of A and B. */
1164static int
49a0ba27 1165collated_compare (const void *a, const void *b)
28f540f4 1166{
c66c9082
AZ
1167 char *const *ps1 = a; char *s1 = *ps1;
1168 char *const *ps2 = b; char *s2 = *ps2;
28f540f4
RM
1169
1170 if (s1 == s2)
1171 return 0;
1172 if (s1 == NULL)
1173 return 1;
1174 if (s2 == NULL)
1175 return -1;
1176 return strcoll (s1, s2);
1177}
1178
1179
1180/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
1181 elements in place. Return nonzero if out of memory, zero if successful.
1182 A slash is inserted between DIRNAME and each elt of ARRAY,
1183 unless DIRNAME is just "/". Each old element of ARRAY is freed. */
1184static int
49a0ba27 1185prefix_array (const char *dirname, char **array, size_t n)
28f540f4 1186{
2e09a79a 1187 size_t i;
28f540f4 1188 size_t dirlen = strlen (dirname);
c66c9082 1189 char dirsep_char = '/';
28f540f4
RM
1190
1191 if (dirlen == 1 && dirname[0] == '/')
1192 /* DIRNAME is just "/", so normal prepending would get us "//foo".
1193 We want "/foo" instead, so don't prepend any chars from DIRNAME. */
1194 dirlen = 0;
c66c9082 1195
786a5421 1196#if defined __MSDOS__ || defined WINDOWS32
c66c9082 1197 if (dirlen > 1)
786a5421 1198 {
ea1bfb07 1199 if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
786a5421
UD
1200 /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */
1201 --dirlen;
1202 else if (dirname[dirlen - 1] == ':')
1203 {
c66c9082 1204 /* DIRNAME is "d:". Use ':' instead of '/'. */
786a5421 1205 --dirlen;
c66c9082 1206 dirsep_char = ':';
786a5421
UD
1207 }
1208 }
1209#endif
28f540f4
RM
1210
1211 for (i = 0; i < n; ++i)
1212 {
1213 size_t eltlen = strlen (array[i]) + 1;
c66c9082 1214 char *new = malloc (dirlen + 1 + eltlen);
28f540f4
RM
1215 if (new == NULL)
1216 {
1217 while (i > 0)
49a0ba27 1218 free (array[--i]);
28f540f4
RM
1219 return 1;
1220 }
1221
dd7d45e8 1222 {
49a0ba27 1223 char *endp = mempcpy (new, dirname, dirlen);
c66c9082 1224 *endp++ = dirsep_char;
dd7d45e8
UD
1225 mempcpy (endp, array[i], eltlen);
1226 }
49a0ba27 1227 free (array[i]);
28f540f4
RM
1228 array[i] = new;
1229 }
1230
1231 return 0;
1232}
1233
c66c9082 1234/* Like 'glob', but PATTERN is a final pathname component,
28f540f4
RM
1235 and matches are searched for in DIRECTORY.
1236 The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
1237 The GLOB_APPEND flag is assumed to be set (always appends). */
1238static int
49a0ba27
RM
1239glob_in_dir (const char *pattern, const char *directory, int flags,
1240 int (*errfunc) (const char *, int),
f2962a71 1241 glob_t *pglob, size_t alloca_used)
28f540f4 1242{
66b38fc9 1243 size_t dirlen = strlen (directory);
49a0ba27 1244 void *stream = NULL;
c66c9082
AZ
1245# define GLOBNAMES_MEMBERS(nnames) \
1246 struct globnames *next; size_t count; char *name[nnames];
1247 struct globnames { GLOBNAMES_MEMBERS (FLEXIBLE_ARRAY_MEMBER) };
1248 struct { GLOBNAMES_MEMBERS (64) } init_names_buf;
1249 struct globnames *init_names = (struct globnames *) &init_names_buf;
1250 struct globnames *names = init_names;
1251 struct globnames *names_alloca = init_names;
f1122ec3 1252 size_t nfound = 0;
f1122ec3 1253 size_t cur = 0;
86187531
UD
1254 int meta;
1255 int save;
c66c9082 1256 int result;
86187531 1257
c66c9082 1258 alloca_used += sizeof init_names_buf;
f2962a71 1259
c66c9082
AZ
1260 init_names->next = NULL;
1261 init_names->count = ((sizeof init_names_buf
1262 - offsetof (struct globnames, name))
1263 / sizeof init_names->name[0]);
f1122ec3 1264
05f135ba 1265 meta = __glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE));
07b4f49d 1266 if (meta == GLOBPAT_NONE && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
28f540f4 1267 {
460adbb8
UD
1268 /* We need not do any tests. The PATTERN contains no meta
1269 characters and we must not return an error therefore the
1270 result will always contain exactly one name. */
1271 flags |= GLOB_NOCHECK;
460adbb8 1272 }
07b4f49d 1273 else if (meta == GLOBPAT_NONE)
460adbb8 1274 {
460adbb8 1275 size_t patlen = strlen (pattern);
c66c9082
AZ
1276 size_t fullsize;
1277 bool alloca_fullname
1278 = (! size_add_wrapv (dirlen + 1, patlen + 1, &fullsize)
1279 && glob_use_alloca (alloca_used, fullsize));
f2962a71
UD
1280 char *fullname;
1281 if (alloca_fullname)
c66c9082 1282 fullname = alloca_account (fullsize, alloca_used);
f2962a71
UD
1283 else
1284 {
c66c9082 1285 fullname = malloc (fullsize);
f2962a71
UD
1286 if (fullname == NULL)
1287 return GLOB_NOSPACE;
1288 }
a9ddb793 1289
460adbb8
UD
1290 mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
1291 "/", 1),
1292 pattern, patlen + 1);
ccf970c7 1293 if (glob_lstat (pglob, flags, fullname) == 0
c66c9082 1294 || errno == EOVERFLOW)
460adbb8
UD
1295 /* We found this file to be existing. Now tell the rest
1296 of the function to copy this name into the result. */
1297 flags |= GLOB_NOCHECK;
f2962a71 1298
a1ffb40e 1299 if (__glibc_unlikely (!alloca_fullname))
f2962a71 1300 free (fullname);
28f540f4
RM
1301 }
1302 else
1303 {
1b6aa63f 1304 stream = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
05f135ba
UD
1305 ? (*pglob->gl_opendir) (directory)
1306 : opendir (directory));
1307 if (stream == NULL)
28f540f4 1308 {
05f135ba
UD
1309 if (errno != ENOTDIR
1310 && ((errfunc != NULL && (*errfunc) (directory, errno))
1311 || (flags & GLOB_ERR)))
1312 return GLOB_ABORTED;
a9ddb793
UD
1313 }
1314 else
1315 {
05f135ba 1316 int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
c66c9082 1317 | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
05f135ba 1318 flags |= GLOB_MAGCHAR;
a9ddb793 1319
05f135ba
UD
1320 while (1)
1321 {
5171f307
FW
1322 struct readdir_result d;
1323 {
1324 if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
1325 d = convert_dirent (GL_READDIR (pglob, stream));
1326 else
1327 {
1328#ifdef COMPILE_GLOB64
1329 d = convert_dirent (__readdir (stream));
2958e6cc 1330#else
5171f307 1331 d = convert_dirent64 (__readdir64 (stream));
2958e6cc 1332#endif
5171f307
FW
1333 }
1334 }
1335 if (d.name == NULL)
05f135ba 1336 break;
787e4db9 1337
05f135ba
UD
1338 /* If we shall match only directories use the information
1339 provided by the dirent call if possible. */
c66c9082
AZ
1340 if (flags & GLOB_ONLYDIR)
1341 switch (readdir_result_type (d))
1342 {
1343 case DT_DIR: case DT_LNK: case DT_UNKNOWN: break;
1344 default: continue;
1345 }
1cab5444 1346
5171f307 1347 if (fnmatch (pattern, d.name, fnm_flags) == 0)
05f135ba 1348 {
5554304f 1349 if (cur == names->count)
a9ddb793 1350 {
5554304f
AZ
1351 struct globnames *newnames;
1352 size_t count = names->count * 2;
1353 size_t nameoff = offsetof (struct globnames, name);
1354 size_t size = FLEXSIZEOF (struct globnames, name,
1355 count * sizeof (char *));
1356 if ((SIZE_MAX - nameoff) / 2 / sizeof (char *)
1357 < names->count)
05f135ba 1358 goto memory_error;
5554304f
AZ
1359 if (glob_use_alloca (alloca_used, size))
1360 newnames = names_alloca
1361 = alloca_account (size, alloca_used);
1362 else if ((newnames = malloc (size))
1363 == NULL)
c66c9082 1364 goto memory_error;
5554304f
AZ
1365 newnames->count = count;
1366 newnames->next = names;
1367 names = newnames;
1368 cur = 0;
a9ddb793 1369 }
5554304f
AZ
1370 names->name[cur] = strdup (d.name);
1371 if (names->name[cur] == NULL)
1372 goto memory_error;
1373 ++cur;
1374 ++nfound;
1375 if (SIZE_MAX - pglob->gl_offs <= nfound)
1376 goto memory_error;
a9ddb793 1377 }
86187531
UD
1378 }
1379 }
28f540f4
RM
1380 }
1381
1382 if (nfound == 0 && (flags & GLOB_NOCHECK))
1383 {
1384 size_t len = strlen (pattern);
1385 nfound = 1;
c66c9082 1386 names->name[cur] = malloc (len + 1);
f1122ec3 1387 if (names->name[cur] == NULL)
28f540f4 1388 goto memory_error;
f1122ec3 1389 *((char *) mempcpy (names->name[cur++], pattern, len)) = '\0';
28f540f4
RM
1390 }
1391
c66c9082 1392 result = GLOB_NOMATCH;
61eb22d3
UD
1393 if (nfound != 0)
1394 {
c66c9082 1395 char **new_gl_pathv;
f1122ec3 1396 result = 0;
a334319f 1397
c66c9082
AZ
1398 if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc
1399 < pglob->gl_offs + nfound + 1)
90bb2039
UD
1400 goto memory_error;
1401
d1dddedf 1402 new_gl_pathv
c66c9082
AZ
1403 = realloc (pglob->gl_pathv,
1404 (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
1405 * sizeof (char *));
1406
d1dddedf 1407 if (new_gl_pathv == NULL)
f1122ec3
UD
1408 {
1409 memory_error:
1410 while (1)
1411 {
1412 struct globnames *old = names;
1413 for (size_t i = 0; i < cur; ++i)
1414 free (names->name[i]);
1415 names = names->next;
f01e4069
UD
1416 /* NB: we will not leak memory here if we exit without
1417 freeing the current block assigned to OLD. At least
1418 the very first block is always allocated on the stack
1419 and this is the block assigned to OLD here. */
f1122ec3 1420 if (names == NULL)
f01e4069 1421 {
c66c9082 1422 assert (old == init_names);
f01e4069
UD
1423 break;
1424 }
f1122ec3
UD
1425 cur = names->count;
1426 if (old == names_alloca)
1427 names_alloca = names;
1428 else
1429 free (old);
1430 }
1431 result = GLOB_NOSPACE;
1432 }
1433 else
1434 {
1435 while (1)
1436 {
1437 struct globnames *old = names;
1438 for (size_t i = 0; i < cur; ++i)
1439 new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++]
1440 = names->name[i];
1441 names = names->next;
f01e4069
UD
1442 /* NB: we will not leak memory here if we exit without
1443 freeing the current block assigned to OLD. At least
1444 the very first block is always allocated on the stack
1445 and this is the block assigned to OLD here. */
f1122ec3 1446 if (names == NULL)
f01e4069 1447 {
c66c9082 1448 assert (old == init_names);
f01e4069
UD
1449 break;
1450 }
f1122ec3
UD
1451 cur = names->count;
1452 if (old == names_alloca)
1453 names_alloca = names;
1454 else
1455 free (old);
1456 }
1457
1458 pglob->gl_pathv = new_gl_pathv;
28f540f4 1459
f1122ec3 1460 pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
28f540f4 1461
f1122ec3
UD
1462 pglob->gl_flags = flags;
1463 }
61eb22d3 1464 }
28f540f4 1465
a9ddb793 1466 if (stream != NULL)
6e4c40ba 1467 {
f1122ec3 1468 save = errno;
a1ffb40e 1469 if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
6e4c40ba
UD
1470 (*pglob->gl_closedir) (stream);
1471 else
49a0ba27 1472 closedir (stream);
f1122ec3 1473 __set_errno (save);
6e4c40ba 1474 }
28f540f4 1475
f1122ec3 1476 return result;
28f540f4 1477}