Coverage Report

Created: 2026-05-23 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/proftpd/lib/glibc-glob.c
Line
Count
Source
1
/* Copyright (C) 1991-1999, 2000, 2001 Free Software Foundation, Inc.
2
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.
7
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.
12
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
   see <https://www.gnu.org/licenses/>.  */
16
17
/* AIX requires this to be the first thing in the file.  */
18
19
#if defined _AIX && !defined __GNUC__
20
 #pragma alloca
21
#endif
22
23
#include <config.h>
24
#include "options.h"
25
26
/* Make alloca work the best possible way.  */
27
#ifdef __GNUC__
28
#define alloca __builtin_alloca
29
#else /* not __GNUC__ */
30
#if HAVE_ALLOCA_H
31
#include <alloca.h>
32
#else /* not __GNUC__ or HAVE_ALLOCA_H */
33
#ifndef _AIX /* Already did AIX, up at the top.  */
34
char *alloca ();
35
#endif /* not _AIX */
36
#endif /* not HAVE_ALLOCA_H */
37
#endif /* not __GNUC__ */
38
39
0
#define MAX_RECURSION   PR_TUNABLE_GLOBBING_MAX_RECURSION
40
0
#define MAX_RESULTS PR_TUNABLE_GLOBBING_MAX_MATCHES
41
42
/* Enable GNU extensions in glob.h.  */
43
#ifndef _GNU_SOURCE
44
# define _GNU_SOURCE  1
45
#endif
46
47
#include <errno.h>
48
#include <sys/types.h>
49
#include <sys/stat.h>
50
51
/* Outcomment the following line for production quality code.  */
52
/* #define NDEBUG 1 */
53
#include <assert.h>
54
55
#include <stdio.h>    /* Needed on stupid SunOS for assert.  */
56
57
/* Comment out all this code if we are using the GNU C Library, and are not
58
   actually compiling the library itself.  This code is part of the GNU C
59
   Library, but also included in many other GNU distributions.  Compiling
60
   and linking in this code is a waste when using the GNU C library
61
   (especially if it is a shared library).  Rather than having every GNU
62
   program understand `configure --with-gnu-libc' and omit the object files,
63
   it is simpler to just do this in the source for each such file.  */
64
65
/* Proftpd modification: always undefine __GNU_LIBRARY__ because we are not
66
 * compiling as part of glibc.
67
 */
68
69
#undef __GNU_LIBRARY__
70
71
#define GLOB_INTERFACE_VERSION 1
72
#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
73
# include <gnu-versions.h>
74
# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
75
#  define ELIDE_CODE
76
# endif
77
#endif
78
79
#undef ELIDE_CODE
80
0
#define __alloca alloca
81
0
#define __readdir readdir
82
83
#ifndef ELIDE_CODE
84
#if !defined _LIBC || !defined GLOB_ONLY_P
85
86
#if defined STDC_HEADERS || defined __GNU_LIBRARY__
87
# include <stddef.h>
88
#endif
89
90
#if defined HAVE_UNISTD_H || defined _LIBC
91
# include <unistd.h>
92
# ifndef POSIX
93
#  ifdef _POSIX_VERSION
94
#   define POSIX
95
#  endif
96
# endif
97
#endif
98
99
#if !defined _AMIGA && !defined VMS && !defined WINDOWS32
100
# include <pwd.h>
101
#endif
102
103
#if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS
104
extern int errno;
105
#endif
106
#ifndef __set_errno
107
0
# define __set_errno(val) errno = (val)
108
#endif
109
110
#ifndef NULL
111
# define NULL 0
112
#endif
113
114
#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
115
# include <dirent.h>
116
0
# define NAMLEN(dirent) strlen((dirent)->d_name)
117
#else
118
# define dirent direct
119
# define NAMLEN(dirent) (dirent)->d_namlen
120
# ifdef HAVE_SYS_NDIR_H
121
#  include <sys/ndir.h>
122
# endif
123
# ifdef HAVE_SYS_DIR_H
124
#  include <sys/dir.h>
125
# endif
126
# ifdef HAVE_NDIR_H
127
#  include <ndir.h>
128
# endif
129
# ifdef HAVE_VMSDIR_H
130
#  include "vmsdir.h"
131
# endif /* HAVE_VMSDIR_H */
132
#endif
133
134
135
/* In GNU systems, <dirent.h> defines this macro for us.  */
136
#ifdef _D_NAMLEN
137
# undef NAMLEN
138
# define NAMLEN(d) _D_NAMLEN(d)
139
#endif
140
141
/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
142
   if the `d_type' member for `struct dirent' is available.  */
143
#ifdef _DIRENT_HAVE_D_TYPE
144
# define HAVE_D_TYPE  1
145
#endif
146
147
#ifdef _LIBC
148
# define HAVE_DIRENT64  1
149
#endif
150
151
/* If the system has the `struct dirent64' type we use it internally.  */
152
#if defined HAVE_DIRENT64 && !defined COMPILE_GLOB64
153
# if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
154
#  define CONVERT_D_NAMLEN(d64, d32)
155
# else
156
#  define CONVERT_D_NAMLEN(d64, d32) \
157
  (d64)->d_namlen = (d32)->d_namlen;
158
# endif
159
160
# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
161
#  define CONVERT_D_INO(d64, d32)
162
# else
163
#  define CONVERT_D_INO(d64, d32) \
164
  (d64)->d_ino = (d32)->d_ino;
165
# endif
166
167
# ifdef HAVE_D_TYPE
168
#  define CONVERT_D_TYPE(d64, d32) \
169
  (d64)->d_type = (d32)->d_type;
170
# else
171
#  define CONVERT_D_TYPE(d64, d32)
172
# endif
173
174
# define CONVERT_DIRENT_DIRENT64(d64, d32) \
175
  memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1);          \
176
  CONVERT_D_NAMLEN (d64, d32)                 \
177
  CONVERT_D_INO (d64, d32)                  \
178
  CONVERT_D_TYPE (d64, d32)
179
#endif
180
181
#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
182
/* Posix does not require that the d_ino field be present, and some
183
   systems do not provide it. */
184
0
# define REAL_DIR_ENTRY(dp) 1
185
#else
186
# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
187
#endif /* POSIX */
188
189
#if defined STDC_HEADERS || defined __GNU_LIBRARY__
190
# include <stdlib.h>
191
# include <string.h>
192
# define  ANSI_STRING
193
#else /* No standard headers.  */
194
195
extern char *getenv ();
196
197
# ifdef HAVE_STRING_H
198
#  include <string.h>
199
#  define ANSI_STRING
200
# else
201
#  include <strings.h>
202
# endif
203
# ifdef HAVE_MEMORY_H
204
#  include <memory.h>
205
# endif
206
207
extern char *malloc (), *realloc ();
208
extern void free ();
209
210
extern void qsort ();
211
extern void abort (), exit ();
212
213
#endif  /* Standard headers.  */
214
215
#ifndef ANSI_STRING
216
217
# ifndef bzero
218
extern void bzero ();
219
# endif
220
# ifndef bcopy
221
extern void bcopy ();
222
# endif
223
224
# define memcpy(d, s, n)  bcopy ((s), (d), (n))
225
# define strrchr  rindex
226
/* memset is only used for zero here, but let's be paranoid.  */
227
# define memset(s, better_be_zero, n) \
228
  ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0)))
229
#endif  /* Not ANSI_STRING.  */
230
231
#if !defined HAVE_STRCOLL && !defined _LIBC
232
# define strcoll  strcmp
233
#endif
234
235
#if !defined HAVE_MEMPCPY && defined __GLIBC__ && __GLIBC__ - 0 == 2 && __GLIBC_MINOR__ >= 1
236
# define HAVE_MEMPCPY 1
237
# undef  mempcpy
238
# define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len)
239
#endif
240
241
static unsigned long nbresults;
242
243
#ifndef __GNU_LIBRARY__
244
# ifdef __GNUC__
245
__inline
246
# endif
247
# ifndef __SASC
248
#  ifdef WINDOWS32
249
static void *
250
#  else
251
static char *
252
# endif
253
my_realloc (void *p, size_t n)
254
0
{
255
  /* These casts are the for sake of the broken Ultrix compiler,
256
     which warns of illegal pointer combinations otherwise.  */
257
0
  if (p == NULL)
258
0
    return (char *) malloc (n);
259
0
  return (char *) realloc (p, n);
260
0
}
261
0
# define  realloc my_realloc
262
# endif /* __SASC */
263
#endif /* __GNU_LIBRARY__ */
264
265
#if !defined __alloca && !defined __GNU_LIBRARY__
266
267
# ifdef __GNUC__
268
#  undef alloca
269
#  define alloca(n) __builtin_alloca (n)
270
# else  /* Not GCC.  */
271
#  ifdef HAVE_ALLOCA_H
272
#   include <alloca.h>
273
#  else /* Not HAVE_ALLOCA_H.  */
274
#   ifndef _AIX
275
#    ifdef WINDOWS32
276
#     include <malloc.h>
277
#    else
278
extern char *alloca ();
279
#    endif /* WINDOWS32 */
280
#   endif /* Not _AIX.  */
281
#  endif /* sparc or HAVE_ALLOCA_H.  */
282
# endif /* GCC.  */
283
284
# define __alloca alloca
285
286
#endif
287
288
#ifdef IRIX6
289
#include <alloca.h>
290
#endif
291
292
#ifndef __GNU_LIBRARY__
293
0
# define __stat stat
294
# ifdef STAT_MACROS_BROKEN
295
#  undef S_ISDIR
296
# endif
297
# ifndef S_ISDIR
298
#  define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
299
# endif
300
#endif
301
302
#ifdef _LIBC
303
# undef strdup
304
# define strdup(str) __strdup (str)
305
# define sysconf(id) __sysconf (id)
306
# define closedir(dir) __closedir (dir)
307
# define opendir(name) __opendir (name)
308
# define readdir(str) __readdir64 (str)
309
# define getpwnam_r(name, bufp, buf, len, res) \
310
   __getpwnam_r (name, bufp, buf, len, res)
311
# ifndef __stat64
312
#  define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
313
# endif
314
# define HAVE_STAT64  1
315
#endif
316
317
#ifndef HAVE_STAT64
318
0
# define __stat64(fname, buf) __stat (fname, buf)
319
/* This is the variable name we are using.  */
320
# define st64 st
321
#endif
322
323
#if !(defined STDC_HEADERS || defined __GNU_LIBRARY__)
324
# undef size_t
325
# define size_t unsigned int
326
#endif
327
328
/* Some system header files erroneously define these.
329
   We want our own definitions from <fnmatch.h> to take precedence.  */
330
#ifndef __GNU_LIBRARY__
331
# undef FNM_PATHNAME
332
# undef FNM_NOESCAPE
333
# undef FNM_PERIOD
334
#endif
335
#include <fnmatch.h>
336
337
/* Some system header files erroneously define these.
338
   We want our own definitions from <glob.h> to take precedence.  */
339
#ifndef __GNU_LIBRARY__
340
# undef GLOB_ERR
341
# undef GLOB_MARK
342
# undef GLOB_NOSORT
343
# undef GLOB_DOOFFS
344
# undef GLOB_NOCHECK
345
# undef GLOB_APPEND
346
# undef GLOB_NOESCAPE
347
# undef GLOB_PERIOD
348
#endif
349
#include <glibc-glob.h>
350
351
#ifdef HAVE_GETLOGIN_R
352
extern int getlogin_r __P ((char *, size_t));
353
#else
354
extern char *getlogin __P ((void));
355
#endif
356

357
static
358
#if __GNUC__ - 0 >= 2
359
inline
360
#endif
361
const char *next_brace_sub __P ((const char *begin));
362
363
#endif /* GLOB_ONLY_P */
364
365
static int glob_in_dir __P ((const char *pattern, const char *directory,
366
           int flags,
367
           int (*errfunc) (const char *, int),
368
           glob_t *pglob));
369
370
/* Prototype __glob_pattern_p to avoid compiler warning.
371
 */
372
#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
373
/* Return nonzero if PATTERN contains any metacharacters.
374
   Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
375
static int __glob_pattern_p (const char *pattern, int quote);
376
#endif /* NO_GLOB_PATTERN_P */
377
378
#if !defined _LIBC || !defined GLOB_ONLY_P
379
static int prefix_array __P ((const char *prefix, char **array, size_t n));
380
static int collated_compare __P ((const __ptr_t, const __ptr_t));
381
382
/* Find the end of the sub-pattern in a brace expression.  We define
383
   this as an inline function if the compiler permits.  */
384
static
385
#if __GNUC__ - 0 >= 2
386
inline
387
#endif
388
const char *
389
next_brace_sub (const char *begin)
390
0
{
391
0
  unsigned int depth = 0;
392
0
  const char *cp = begin;
393
394
0
  while (1)
395
0
    {
396
0
      if (depth == 0)
397
0
  {
398
0
    if (*cp != ',' && *cp != '}' && *cp != '\0')
399
0
      {
400
0
        if (*cp == '{')
401
0
    ++depth;
402
0
        ++cp;
403
0
        continue;
404
0
      }
405
0
  }
406
0
      else
407
0
  {
408
0
    while (*cp != '\0' && (*cp != '}' || depth > 0))
409
0
      {
410
0
        if (*cp == '}')
411
0
    --depth;
412
0
        ++cp;
413
0
      }
414
0
    if (*cp == '\0')
415
      /* An incorrectly terminated brace expression.  */
416
0
      return NULL;
417
418
0
    continue;
419
0
  }
420
0
      break;
421
0
    }
422
423
0
  return cp;
424
0
}
425
426
#endif /* !GLOB_ONLY_P */
427
428
/* Do glob searching for PATTERN, placing results in PGLOB.
429
   The bits defined above may be set in FLAGS.
430
   If a directory cannot be opened or read and ERRFUNC is not nil,
431
   it is called with the pathname that caused the error, and the
432
   `errno' value from the failing call; if it returns non-zero
433
   `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
434
   If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
435
   Otherwise, `glob' returns zero.  */
436
static int
437
glob_limited (unsigned int depth, const char *pattern, int flags,
438
    int (*errfunc) __P((const char *, int)), glob_t *pglob)
439
0
{
440
0
  const char *filename;
441
0
  const char *dirname;
442
0
  size_t dirlen;
443
0
  int status;
444
0
  size_t oldcount;
445
446
0
  if (depth > MAX_RECURSION) {
447
0
    return GLOB_NOSPACE;
448
0
  }
449
0
  if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
450
0
    {
451
0
      __set_errno (EINVAL);
452
0
      return -1;
453
0
    }
454
455
0
  if (!(flags & GLOB_DOOFFS))
456
    /* Have to do this so `globfree' knows where to start freeing.  It
457
       also makes all the code that uses gl_offs simpler. */
458
0
    pglob->gl_offs = 0;
459
460
0
  if (flags & GLOB_BRACE)
461
0
    {
462
0
      const char *begin = strchr (pattern, '{');
463
0
      if (begin != NULL)
464
0
  {
465
    /* Allocate working buffer large enough for our work.  Note that
466
      we have at least an opening and closing brace.  */
467
0
    size_t firstc;
468
0
    char *alt_start;
469
0
    const char *p;
470
0
    const char *next;
471
0
    const char *rest;
472
0
    size_t rest_len;
473
0
#ifdef __GNUC__
474
0
    char onealt[strlen (pattern) - 1];
475
#else
476
    char *onealt = (char *) malloc (strlen (pattern) - 1);
477
    if (onealt == NULL)
478
      {
479
        if (!(flags & GLOB_APPEND))
480
    globfree (pglob);
481
        return GLOB_NOSPACE;
482
      }
483
#endif
484
485
    /* We know the prefix for all sub-patterns.  */
486
0
#ifdef HAVE_MEMPCPY
487
0
    alt_start = mempcpy (onealt, pattern, begin - pattern);
488
#else
489
    memcpy (onealt, pattern, begin - pattern);
490
    alt_start = &onealt[begin - pattern];
491
#endif
492
493
    /* Find the first sub-pattern and at the same time find the
494
       rest after the closing brace.  */
495
0
    next = next_brace_sub (begin + 1);
496
0
    if (next == NULL)
497
0
      {
498
        /* It is an illegal expression.  */
499
#ifndef __GNUC__
500
        free (onealt);
501
#endif
502
0
        return glob_limited (depth + 1U, pattern, flags & ~GLOB_BRACE, errfunc, pglob);
503
0
      }
504
505
    /* Now find the end of the whole brace expression.  */
506
0
    rest = next;
507
0
    while (*rest != '}')
508
0
      {
509
0
        rest = next_brace_sub (rest + 1);
510
0
        if (rest == NULL)
511
0
    {
512
      /* It is an illegal expression.  */
513
#ifndef __GNUC__
514
      free (onealt);
515
#endif
516
0
      return glob_limited (depth + 1U, pattern, flags & ~GLOB_BRACE, errfunc, pglob);
517
0
    }
518
0
      }
519
    /* Please note that we now can be sure the brace expression
520
       is well-formed.  */
521
0
    rest_len = strlen (++rest) + 1;
522
523
    /* We have a brace expression.  BEGIN points to the opening {,
524
       NEXT points past the terminator of the first element, and END
525
       points past the final }.  We will accumulate result names from
526
       recursive runs for each brace alternative in the buffer using
527
       GLOB_APPEND.  */
528
529
0
    if (!(flags & GLOB_APPEND))
530
0
      {
531
        /* This call is to set a new vector, so clear out the
532
     vector so we can append to it.  */
533
0
        pglob->gl_pathc = 0;
534
0
        pglob->gl_pathv = NULL;
535
0
      }
536
0
    firstc = pglob->gl_pathc;
537
538
0
    p = begin + 1;
539
0
    while (1)
540
0
      {
541
0
        int result;
542
      
543
        /* Construct the new glob expression.  */
544
0
#ifdef HAVE_MEMPCPY
545
0
        mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
546
#else
547
        memcpy (alt_start, p, next - p);
548
        memcpy (&alt_start[next - p], rest, rest_len);
549
#endif
550
551
0
        result = glob_limited (depth + 1U, onealt,
552
0
           ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC))
553
0
            | GLOB_APPEND), errfunc, pglob);
554
555
        /* If we got an error, return it.  */
556
0
        if (result && result != GLOB_NOMATCH)
557
0
    {
558
#ifndef __GNUC__
559
      free (onealt);
560
#endif
561
0
      if (!(flags & GLOB_APPEND))
562
0
        globfree (pglob);
563
0
      return result;
564
0
    }
565
566
0
        if (*next == '}')
567
    /* We saw the last entry.  */
568
0
    break;
569
570
0
        p = next + 1;
571
0
        next = next_brace_sub (p);
572
0
        assert (next != NULL);
573
0
      }
574
575
#ifndef __GNUC__
576
    free (onealt);
577
#endif
578
579
0
    if (pglob->gl_pathc != firstc)
580
      /* We found some entries.  */
581
0
      return 0;
582
0
    else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
583
0
      return GLOB_NOMATCH;
584
0
  }
585
0
    }
586
587
  /* Find the filename.  */
588
0
  filename = strrchr (pattern, '/');
589
#if defined __MSDOS__ || defined WINDOWS32
590
  /* The case of "d:pattern".  Since `:' is not allowed in
591
     file names, we can safely assume that wherever it
592
     happens in pattern, it signals the filename part.  This
593
     is so we could some day support patterns like "[a-z]:foo".  */
594
  if (filename == NULL)
595
    filename = strchr (pattern, ':');
596
#endif /* __MSDOS__ || WINDOWS32 */
597
0
  if (filename == NULL)
598
0
    {
599
      /* This can mean two things: a simple name or "~name".  The latter
600
   case is nothing but a notation for a directory.  */
601
0
      if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
602
0
  {
603
0
    dirname = pattern;
604
0
    dirlen = strlen (pattern);
605
606
    /* Set FILENAME to NULL as a special flag.  This is ugly but
607
       other solutions would require much more code.  We test for
608
       this special case below.  */
609
0
    filename = NULL;
610
0
  }
611
0
      else
612
0
  {
613
0
    filename = pattern;
614
#ifdef _AMIGA
615
    dirname = "";
616
#else
617
0
    dirname = ".";
618
0
#endif
619
0
    dirlen = 0;
620
0
  }
621
0
    }
622
0
  else if (filename == pattern)
623
0
    {
624
      /* "/pattern".  */
625
0
      dirname = "/";
626
0
      dirlen = 1;
627
0
      ++filename;
628
0
    }
629
0
  else
630
0
    {
631
0
      char *newp;
632
0
      dirlen = filename - pattern;
633
#if defined __MSDOS__ || defined WINDOWS32
634
      if (*filename == ':'
635
    || (filename > pattern + 1 && filename[-1] == ':'))
636
  {
637
    char *drive_spec;
638
639
    ++dirlen;
640
    drive_spec = (char *) __alloca (dirlen + 1);
641
#ifdef HAVE_MEMPCPY
642
    *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
643
#else
644
    memcpy (drive_spec, pattern, dirlen);
645
    drive_spec[dirlen] = '\0';
646
#endif
647
    /* For now, disallow wildcards in the drive spec, to
648
       prevent infinite recursion in glob.  */
649
    if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
650
      return GLOB_NOMATCH;
651
    /* If this is "d:pattern", we need to copy `:' to DIRNAME
652
       as well.  If it's "d:/pattern", don't remove the slash
653
       from "d:/", since "d:" and "d:/" are not the same.*/
654
  }
655
#endif
656
0
      newp = (char *) __alloca (dirlen + 1);
657
0
#ifdef HAVE_MEMPCPY
658
0
      *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
659
#else
660
      memcpy (newp, pattern, dirlen);
661
      newp[dirlen] = '\0';
662
#endif
663
0
      dirname = newp;
664
0
      ++filename;
665
666
0
      if (filename[0] == '\0'
667
#if defined __MSDOS__ || defined WINDOWS32
668
          && dirname[dirlen - 1] != ':'
669
    && (dirlen < 3 || dirname[dirlen - 2] != ':'
670
        || dirname[dirlen - 1] != '/')
671
#endif
672
0
    && dirlen > 1)
673
  /* "pattern/".  Expand "pattern", appending slashes.  */
674
0
  {
675
0
    int val = glob_limited (depth + 1U, dirname, flags | GLOB_MARK, errfunc, pglob);
676
0
    if (val == 0)
677
0
      pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
678
0
             | (flags & GLOB_MARK));
679
0
    return val;
680
0
  }
681
0
    }
682
683
0
  if (!(flags & GLOB_APPEND))
684
0
    {
685
0
      pglob->gl_pathc = 0;
686
0
      if (!(flags & GLOB_DOOFFS))
687
0
        pglob->gl_pathv = NULL;
688
0
      else
689
0
  {
690
0
    size_t i;
691
0
    pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
692
0
                * sizeof (char *));
693
0
    if (pglob->gl_pathv == NULL)
694
0
      return GLOB_NOSPACE;
695
696
0
    for (i = 0; i <= pglob->gl_offs; ++i)
697
0
      pglob->gl_pathv[i] = NULL;
698
0
  }
699
0
    }
700
701
0
  oldcount = pglob->gl_pathc + pglob->gl_offs;
702
703
0
#ifndef VMS
704
0
  if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
705
0
    {
706
0
      if (dirname[1] == '\0' || dirname[1] == '/')
707
0
  {
708
    /* Look up home directory.  */
709
0
    const char *home_dir = getenv ("HOME");
710
# ifdef _AMIGA
711
    if (home_dir == NULL || home_dir[0] == '\0')
712
      home_dir = "SYS:";
713
# else
714
#  ifdef WINDOWS32
715
    if (home_dir == NULL || home_dir[0] == '\0')
716
            home_dir = "c:/users/default"; /* poor default */
717
#  else
718
0
    if (home_dir == NULL || home_dir[0] == '\0')
719
0
      {
720
0
        int success;
721
0
        char *name;
722
#   if defined HAVE_GETLOGIN_R || defined _LIBC
723
        size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;
724
725
        if (buflen == 0)
726
    /* `sysconf' does not support _SC_LOGIN_NAME_MAX.  Try
727
       a moderate value.  */
728
    buflen = PR_TUNABLE_LOGIN_MAX+1;
729
        name = (char *) __alloca (buflen);
730
731
        success = getlogin_r (name, buflen) >= 0;
732
#   else
733
0
        success = (name = getlogin ()) != NULL;
734
0
#   endif
735
0
        if (success)
736
0
    {
737
0
      struct passwd *p;
738
#   if defined HAVE_GETPWNAM_R || defined _LIBC
739
      long int pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
740
      char *pwtmpbuf;
741
      struct passwd pwbuf;
742
      int save = errno;
743
744
      if (pwbuflen == -1)
745
        /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
746
           Try a moderate value.  */
747
        pwbuflen = 1024;
748
      pwtmpbuf = (char *) __alloca (pwbuflen);
749
750
      while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
751
       != 0)
752
        {
753
          if (errno != ERANGE)
754
      {
755
        p = NULL;
756
        break;
757
      }
758
          pwbuflen *= 2;
759
          pwtmpbuf = (char *) __alloca (pwbuflen);
760
          __set_errno (save);
761
        }
762
#   else
763
0
      p = getpwnam (name);
764
0
#   endif
765
0
      if (p != NULL)
766
0
        home_dir = p->pw_dir;
767
0
    }
768
0
      }
769
0
    if (home_dir == NULL || home_dir[0] == '\0')
770
0
      {
771
0
        if (flags & GLOB_TILDE_CHECK)
772
0
    return GLOB_NOMATCH;
773
0
        else
774
0
    home_dir = "~"; /* No luck.  */
775
0
      }
776
0
#  endif /* WINDOWS32 */
777
0
# endif
778
    /* Now construct the full directory.  */
779
0
    if (dirname[1] == '\0')
780
0
      dirname = home_dir;
781
0
    else
782
0
      {
783
0
        char *newp;
784
0
        size_t home_len = strlen (home_dir);
785
0
        newp = (char *) __alloca (home_len + dirlen);
786
0
# ifdef HAVE_MEMPCPY
787
0
        mempcpy (mempcpy (newp, home_dir, home_len),
788
0
           &dirname[1], dirlen);
789
# else
790
        memcpy (newp, home_dir, home_len);
791
        memcpy (&newp[home_len], &dirname[1], dirlen);
792
# endif
793
0
        dirname = newp;
794
0
      }
795
0
  }
796
0
# if !defined _AMIGA && !defined WINDOWS32
797
0
      else
798
0
  {
799
0
    char *end_name = strchr (dirname, '/');
800
0
    const char *user_name;
801
0
    const char *home_dir;
802
803
0
    if (end_name == NULL)
804
0
      user_name = dirname + 1;
805
0
    else
806
0
      {
807
0
        char *newp;
808
0
        newp = (char *) __alloca (end_name - dirname);
809
0
# ifdef HAVE_MEMPCPY
810
0
        *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
811
0
    = '\0';
812
# else
813
        memcpy (newp, dirname + 1, end_name - dirname);
814
        newp[end_name - dirname - 1] = '\0';
815
# endif
816
0
        user_name = newp;
817
0
      }
818
819
    /* Look up specific user's home directory.  */
820
0
    {
821
0
      struct passwd *p;
822
#  if defined HAVE_GETPWNAM_R || defined _LIBC
823
      long int buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
824
      char *pwtmpbuf;
825
      struct passwd pwbuf;
826
      int save = errno;
827
828
      if (buflen == -1)
829
        /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.  Try a
830
     moderate value.  */
831
        buflen = 1024;
832
      pwtmpbuf = (char *) __alloca (buflen);
833
834
      while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
835
        {
836
    if (errno != ERANGE)
837
      {
838
        p = NULL;
839
        break;
840
      }
841
    buflen *= 2;
842
    pwtmpbuf = __alloca (buflen);
843
    __set_errno (save);
844
        }
845
#  else
846
0
      p = getpwnam (user_name);
847
0
#  endif
848
0
      if (p != NULL)
849
0
        home_dir = p->pw_dir;
850
0
      else
851
0
        home_dir = NULL;
852
0
    }
853
    /* If we found a home directory use this.  */
854
0
    if (home_dir != NULL)
855
0
      {
856
0
        char *newp;
857
0
        size_t home_len = strlen (home_dir);
858
0
        size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
859
0
        newp = (char *) __alloca (home_len + rest_len + 1);
860
0
#  ifdef HAVE_MEMPCPY
861
0
        *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
862
0
          end_name, rest_len)) = '\0';
863
#  else
864
        memcpy (newp, home_dir, home_len);
865
        memcpy (&newp[home_len], end_name, rest_len);
866
        newp[home_len + rest_len] = '\0';
867
#  endif
868
0
        dirname = newp;
869
0
      }
870
0
    else
871
0
      if (flags & GLOB_TILDE_CHECK)
872
        /* We have to regard it as an error if we cannot find the
873
     home directory.  */
874
0
        return GLOB_NOMATCH;
875
0
  }
876
0
# endif /* Not Amiga && not WINDOWS32.  */
877
0
    }
878
0
#endif  /* Not VMS.  */
879
880
  /* Now test whether we looked for "~" or "~NAME".  In this case we
881
     can give the answer now.  */
882
0
  if (filename == NULL)
883
0
    {
884
0
      struct stat st;
885
#ifdef HAVE_STAT64
886
      struct stat64 st64;
887
#endif
888
889
      /* Return the directory if we don't check for error or if it exists.  */
890
0
      if ((flags & GLOB_NOCHECK)
891
0
    || (((flags & GLOB_ALTDIRFUNC)
892
0
         ? ((*pglob->gl_stat) (dirname, &st) == 0
893
0
      && S_ISDIR (st.st_mode))
894
0
         : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode)))))
895
0
  {
896
0
    int newcount = pglob->gl_pathc + pglob->gl_offs;
897
0
          char **new_buf;
898
899
0
    new_buf
900
0
      = (char **) realloc (pglob->gl_pathv,
901
0
         (newcount + 1 + 1) * sizeof (char *));
902
0
    if (new_buf == NULL)
903
0
      return GLOB_NOSPACE;
904
905
0
    pglob->gl_pathv = new_buf;
906
907
#if defined HAVE_STRDUP || defined _LIBC
908
     pglob->gl_pathv[newcount] = strdup (dirname);
909
#else
910
0
    {
911
0
      size_t len = strlen (dirname) + 1;
912
0
      char *dircopy = malloc (len);
913
0
      if (dircopy != NULL)
914
0
        pglob->gl_pathv[newcount] = memcpy (dircopy, dirname, len);
915
0
    }
916
0
#endif
917
0
    if (pglob->gl_pathv[newcount] == NULL)
918
0
      {
919
0
        free (pglob->gl_pathv);
920
0
        return GLOB_NOSPACE;
921
0
      }
922
0
    pglob->gl_pathv[++newcount] = NULL;
923
0
    ++pglob->gl_pathc;
924
0
    pglob->gl_flags = flags;
925
926
0
    return 0;
927
0
  }
928
929
      /* Not found.  */
930
0
      return GLOB_NOMATCH;
931
0
    }
932
933
0
  if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
934
0
    {
935
      /* The directory name contains metacharacters, so we
936
   have to glob for the directory, and then glob for
937
   the pattern in each directory found.  */
938
0
      glob_t dirs;
939
0
      size_t i;
940
941
0
      if ((flags & GLOB_ALTDIRFUNC) != 0)
942
0
  {
943
    /* Use the alternative access functions also in the recursive
944
       call.  */
945
0
    dirs.gl_opendir = pglob->gl_opendir;
946
0
    dirs.gl_readdir = pglob->gl_readdir;
947
0
    dirs.gl_closedir = pglob->gl_closedir;
948
0
    dirs.gl_stat = pglob->gl_stat;
949
0
    dirs.gl_lstat = pglob->gl_lstat;
950
0
  }
951
952
0
      status = glob_limited (depth + 1U, dirname,
953
0
         ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE
954
0
        | GLOB_ALTDIRFUNC))
955
0
          | GLOB_NOSORT | GLOB_ONLYDIR),
956
0
         errfunc, &dirs);
957
0
      if (status != 0)
958
0
  return status;
959
960
      /* We have successfully globbed the preceding directory name.
961
   For each name we found, call glob_in_dir on it and FILENAME,
962
   appending the results to PGLOB.  */
963
0
      for (i = 0; i < dirs.gl_pathc; ++i)
964
0
  {
965
0
    int old_pathc;
966
967
#ifdef  SHELL
968
    {
969
      /* Make globbing interruptible in the bash shell. */
970
      extern int interrupt_state;
971
972
      if (interrupt_state)
973
        {
974
    globfree (&dirs);
975
    return GLOB_ABORTED;
976
        }
977
    }
978
#endif /* SHELL.  */
979
980
0
    old_pathc = pglob->gl_pathc;
981
0
    status = glob_in_dir (filename, dirs.gl_pathv[i],
982
0
        ((flags | GLOB_APPEND) & ~GLOB_NOCHECK),
983
0
        errfunc, pglob);
984
0
    if (status == GLOB_NOMATCH)
985
      /* No matches in this directory.  Try the next.  */
986
0
      continue;
987
988
0
    if (status != 0)
989
0
      {
990
0
        globfree (&dirs);
991
0
        globfree (pglob);
992
0
        return status;
993
0
      }
994
995
    /* Stick the directory on the front of each name.  */
996
0
    if (prefix_array (dirs.gl_pathv[i],
997
0
          &pglob->gl_pathv[old_pathc + pglob->gl_offs],
998
0
          pglob->gl_pathc - old_pathc))
999
0
      {
1000
0
        globfree (&dirs);
1001
0
        globfree (pglob);
1002
0
        return GLOB_NOSPACE;
1003
0
      }
1004
0
  }
1005
1006
0
      flags |= GLOB_MAGCHAR;
1007
1008
      /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
1009
   But if we have not found any matching entry and the GLOB_NOCHECK
1010
   flag was set we must return the list consisting of the disrectory
1011
   names followed by the filename.  */
1012
0
      if (pglob->gl_pathc + pglob->gl_offs == oldcount)
1013
0
  {
1014
    /* No matches.  */
1015
0
    if (flags & GLOB_NOCHECK)
1016
0
      {
1017
0
        size_t filename_len = strlen (filename) + 1;
1018
0
        char **new_pathv, **new_buf;
1019
0
        int newcount = pglob->gl_pathc + pglob->gl_offs;
1020
0
        struct stat st;
1021
#ifdef HAVE_STAT64
1022
        struct stat64 st64;
1023
#endif
1024
1025
        /* This is an pessimistic guess about the size.  */
1026
0
        new_buf
1027
0
    = (char **) realloc (pglob->gl_pathv,
1028
0
             (newcount + dirs.gl_pathc + 1)
1029
0
             * sizeof (char *));
1030
0
        if (new_buf == NULL)
1031
0
    {
1032
0
      globfree (&dirs);
1033
0
      return GLOB_NOSPACE;
1034
0
    }
1035
1036
0
        pglob->gl_pathv = new_buf;
1037
1038
0
        for (i = 0; i < dirs.gl_pathc; ++i)
1039
0
    {
1040
0
      const char *dir = dirs.gl_pathv[i];
1041
0
      size_t dir_len = strlen (dir);
1042
1043
      /* First check whether this really is a directory.  */
1044
0
      if (((flags & GLOB_ALTDIRFUNC)
1045
0
           ? ((*pglob->gl_stat) (dir, &st) != 0
1046
0
        || !S_ISDIR (st.st_mode))
1047
0
           : (__stat64 (dir, &st64) != 0
1048
0
        || !S_ISDIR (st64.st_mode))))
1049
        /* No directory, ignore this entry.  */
1050
0
        continue;
1051
1052
0
      pglob->gl_pathv[newcount] = malloc (dir_len + 1
1053
0
                  + filename_len);
1054
0
      if (pglob->gl_pathv[newcount] == NULL)
1055
0
        {
1056
0
          globfree (&dirs);
1057
0
          globfree (pglob);
1058
0
          return GLOB_NOSPACE;
1059
0
        }
1060
1061
0
#ifdef HAVE_MEMPCPY
1062
0
      mempcpy (mempcpy (mempcpy (pglob->gl_pathv[newcount],
1063
0
               dir, dir_len),
1064
0
            "/", 1),
1065
0
         filename, filename_len);
1066
#else
1067
      memcpy (pglob->gl_pathv[newcount], dir, dir_len);
1068
      pglob->gl_pathv[newcount][dir_len] = '/';
1069
      memcpy (&pglob->gl_pathv[newcount][dir_len + 1],
1070
        filename, filename_len);
1071
#endif
1072
0
      ++pglob->gl_pathc;
1073
0
      ++newcount;
1074
0
    }
1075
1076
0
        pglob->gl_pathv[newcount] = NULL;
1077
0
        pglob->gl_flags = flags;
1078
1079
        /* Now we know how large the gl_pathv vector must be.  */
1080
0
        new_pathv = (char **) realloc (pglob->gl_pathv,
1081
0
               ((newcount + 1)
1082
0
                * sizeof (char *)));
1083
0
        if (new_pathv != NULL)
1084
0
    pglob->gl_pathv = new_pathv;
1085
0
      }
1086
0
    else
1087
0
      {
1088
0
        globfree (&dirs);
1089
0
        return GLOB_NOMATCH;
1090
0
      }
1091
0
  }
1092
1093
0
      globfree (&dirs);
1094
0
    }
1095
0
  else
1096
0
    {
1097
0
      int old_pathc = pglob->gl_pathc;
1098
1099
0
      status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
1100
0
      if (status != 0)
1101
0
  return status;
1102
1103
0
      if (dirlen > 0)
1104
0
  {
1105
    /* Stick the directory on the front of each name.  */
1106
0
    if (prefix_array (dirname,
1107
0
          &pglob->gl_pathv[old_pathc + pglob->gl_offs],
1108
0
          pglob->gl_pathc - old_pathc))
1109
0
      {
1110
0
        globfree (pglob);
1111
0
        return GLOB_NOSPACE;
1112
0
      }
1113
0
  }
1114
0
    }
1115
1116
0
  if (flags & GLOB_MARK)
1117
0
    {
1118
      /* Append slashes to directory names.  */
1119
0
      size_t i;
1120
0
      struct stat st;
1121
#ifdef HAVE_STAT64
1122
      struct stat64 st64;
1123
#endif
1124
1125
0
      for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i)
1126
0
  if ((((flags & GLOB_ALTDIRFUNC) && (pglob->gl_pathv != NULL))
1127
0
       ? ((*pglob->gl_stat) (pglob->gl_pathv[i], &st) == 0
1128
0
    && S_ISDIR (st.st_mode))
1129
0
       : (__stat64 (pglob->gl_pathv[i], &st64) == 0
1130
0
    && S_ISDIR (st64.st_mode))))
1131
0
    {
1132
0
      size_t len = strlen (pglob->gl_pathv[i]) + 2;
1133
0
      char *new = realloc (pglob->gl_pathv[i], len);
1134
0
      if (new == NULL)
1135
0
        {
1136
0
    globfree (pglob);
1137
0
    return GLOB_NOSPACE;
1138
0
        }
1139
0
      strcpy (&new[len - 2], "/");
1140
0
      pglob->gl_pathv[i] = new;
1141
0
    }
1142
0
    }
1143
1144
0
  if (!(flags & GLOB_NOSORT))
1145
0
    {
1146
      /* Sort the vector.  */
1147
0
      qsort ((__ptr_t) &pglob->gl_pathv[oldcount],
1148
0
       pglob->gl_pathc + pglob->gl_offs - oldcount,
1149
0
       sizeof (char *), collated_compare);
1150
0
    }
1151
1152
0
  return 0;
1153
0
}
1154
1155
int
1156
glob (const char *pattern, int flags, int (*errfunc) __P((const char *, int)),
1157
    glob_t *pglob)
1158
0
{
1159
0
  nbresults = 0UL;
1160
0
  return glob_limited(0U, pattern, flags, errfunc, pglob);
1161
0
}
1162
1163
#if !defined _LIBC || !defined GLOB_ONLY_P
1164
1165
/* Free storage allocated in PGLOB by a previous `glob' call.  */
1166
void
1167
globfree (register glob_t *pglob)
1168
0
{
1169
0
  if (pglob->gl_pathv != NULL)
1170
0
    {
1171
0
      size_t i;
1172
0
      for (i = 0; i < pglob->gl_pathc; ++i)
1173
0
  if (pglob->gl_pathv[pglob->gl_offs + i] != NULL)
1174
0
    free ((__ptr_t) pglob->gl_pathv[pglob->gl_offs + i]);
1175
0
      free ((__ptr_t) pglob->gl_pathv);
1176
0
    }
1177
0
}
1178
1179
1180
/* Do a collated comparison of A and B.  */
1181
static int
1182
collated_compare (const __ptr_t a, const __ptr_t b)
1183
0
{
1184
0
  const char *const s1 = *(const char *const * const) a;
1185
0
  const char *const s2 = *(const char *const * const) b;
1186
1187
0
  if (s1 == s2)
1188
0
    return 0;
1189
0
  if (s1 == NULL)
1190
0
    return 1;
1191
0
  if (s2 == NULL)
1192
0
    return -1;
1193
0
  return strcoll (s1, s2);
1194
0
}
1195
1196
1197
/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
1198
   elements in place.  Return nonzero if out of memory, zero if successful.
1199
   A slash is inserted between DIRNAME and each elt of ARRAY,
1200
   unless DIRNAME is just "/".  Each old element of ARRAY is freed.  */
1201
static int
1202
prefix_array (const char *dirname, char **array, size_t n)
1203
0
{
1204
0
  register size_t i;
1205
0
  size_t dirlen = strlen (dirname);
1206
#if defined __MSDOS__ || defined WINDOWS32
1207
  int sep_char = '/';
1208
# define DIRSEP_CHAR sep_char
1209
#else
1210
0
# define DIRSEP_CHAR '/'
1211
0
#endif
1212
1213
0
  if (dirlen == 1 && dirname[0] == '/')
1214
    /* DIRNAME is just "/", so normal prepending would get us "//foo".
1215
       We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
1216
0
    dirlen = 0;
1217
#if defined __MSDOS__ || defined WINDOWS32
1218
  else if (dirlen > 1)
1219
    {
1220
      if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
1221
  /* DIRNAME is "d:/".  Don't prepend the slash from DIRNAME.  */
1222
  --dirlen;
1223
      else if (dirname[dirlen - 1] == ':')
1224
  {
1225
    /* DIRNAME is "d:".  Use `:' instead of `/'.  */
1226
    --dirlen;
1227
    sep_char = ':';
1228
  }
1229
    }
1230
#endif
1231
1232
0
  for (i = 0; i < n; ++i)
1233
0
    {
1234
0
      size_t eltlen = strlen (array[i]) + 1;
1235
0
      char *new = (char *) malloc (dirlen + 1 + eltlen);
1236
0
      if (new == NULL)
1237
0
  {
1238
0
    while (i > 0)
1239
0
      free ((__ptr_t) array[--i]);
1240
0
    return 1;
1241
0
  }
1242
1243
0
#ifdef HAVE_MEMPCPY
1244
0
      {
1245
0
  char *endp = (char *) mempcpy (new, dirname, dirlen);
1246
0
  *endp++ = DIRSEP_CHAR;
1247
0
  mempcpy (endp, array[i], eltlen);
1248
0
      }
1249
#else
1250
      memcpy (new, dirname, dirlen);
1251
      new[dirlen] = DIRSEP_CHAR;
1252
      memcpy (&new[dirlen + 1], array[i], eltlen);
1253
#endif
1254
0
      free ((__ptr_t) array[i]);
1255
0
      array[i] = new;
1256
0
    }
1257
1258
0
  return 0;
1259
0
}
1260
1261
/* We must not compile this function twice.  */
1262
#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
1263
/* Return nonzero if PATTERN contains any metacharacters.
1264
   Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
1265
static int
1266
__glob_pattern_p (const char *pattern, int quote)
1267
0
{
1268
0
  register const char *p;
1269
0
  int open = 0;
1270
1271
0
  for (p = pattern; *p != '\0'; ++p)
1272
0
    switch (*p)
1273
0
      {
1274
0
      case '?':
1275
0
      case '*':
1276
0
  return 1;
1277
1278
0
      case '\\':
1279
0
  if (quote && p[1] != '\0')
1280
0
    ++p;
1281
0
  break;
1282
1283
0
      case '[':
1284
0
  open = 1;
1285
0
  break;
1286
1287
0
      case ']':
1288
0
  if (open)
1289
0
    return 1;
1290
0
  break;
1291
0
      }
1292
1293
0
  return 0;
1294
0
}
1295
# ifdef _LIBC
1296
weak_alias (__glob_pattern_p, glob_pattern_p)
1297
# endif
1298
#endif
1299
1300
#endif /* !GLOB_ONLY_P */
1301
1302
/* Like `glob', but PATTERN is a final pathname component,
1303
   and matches are searched for in DIRECTORY.
1304
   The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
1305
   The GLOB_APPEND flag is assumed to be set (always appends).  */
1306
static int
1307
glob_in_dir (const char *pattern, const char *directory, int flags,
1308
    int (*errfunc) __P((const char *, int)), glob_t *pglob)
1309
0
{
1310
0
  __ptr_t stream = NULL;
1311
0
  struct globlink
1312
0
    {
1313
0
      struct globlink *next;
1314
0
      char *name;
1315
0
    };
1316
0
  struct globlink *names = NULL;
1317
0
  size_t nfound;
1318
0
  int meta;
1319
0
  int save;
1320
1321
0
  meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
1322
0
  if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
1323
0
    {
1324
      /* We need not do any tests.  The PATTERN contains no meta
1325
   characters and we must not return an error therefore the
1326
   result will always contain exactly one name.  */
1327
0
      flags |= GLOB_NOCHECK;
1328
0
      nfound = 0;
1329
0
    }
1330
0
  else if (meta == 0 &&
1331
0
     ((flags & GLOB_NOESCAPE) || strchr(pattern, '\\') == NULL))
1332
0
    {
1333
      /* Since we use the normal file functions we can also use stat()
1334
   to verify the file is there.  */
1335
0
      struct stat st;
1336
# ifdef HAVE_STAT64
1337
      struct stat64 st64;
1338
# endif
1339
0
      size_t patlen = strlen (pattern);
1340
0
      size_t dirlen = strlen (directory);
1341
0
      char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
1342
1343
0
# ifdef HAVE_MEMPCPY
1344
0
      mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
1345
0
      "/", 1),
1346
0
         pattern, patlen + 1);
1347
# else
1348
      memcpy (fullname, directory, dirlen);
1349
      fullname[dirlen] = '/';
1350
      memcpy (&fullname[dirlen + 1], pattern, patlen + 1);
1351
# endif
1352
0
      if (((flags & GLOB_ALTDIRFUNC)
1353
0
     ? (*pglob->gl_stat) (fullname, &st)
1354
0
     : __stat64 (fullname, &st64)) == 0)
1355
  /* We found this file to be existing.  Now tell the rest
1356
     of the function to copy this name into the result.  */
1357
0
  flags |= GLOB_NOCHECK;
1358
1359
0
      nfound = 0;
1360
0
    }
1361
0
  else
1362
0
    {
1363
0
      if (pattern[0] == '\0')
1364
0
  {
1365
    /* This is a special case for matching directories like in
1366
       "*a/".  */
1367
0
    names = (struct globlink *) __alloca (sizeof (struct globlink));
1368
0
    names->name = (char *) malloc (1);
1369
0
    names->next = NULL;
1370
0
    if (names->name == NULL)
1371
0
      goto memory_error;
1372
0
    names->name[0] = '\0';
1373
0
    nfound = 1;
1374
0
    meta = 0;
1375
0
  }
1376
0
      else
1377
0
  {
1378
0
    stream = ((flags & GLOB_ALTDIRFUNC)
1379
0
        ? (*pglob->gl_opendir) (directory)
1380
0
        : (__ptr_t) opendir (directory));
1381
0
    if (stream == NULL)
1382
0
      {
1383
0
        if (errno != ENOTDIR
1384
0
      && ((errfunc != NULL && (*errfunc) (directory, errno))
1385
0
          || (flags & GLOB_ERR)))
1386
0
    return GLOB_ABORTED;
1387
0
        nfound = 0;
1388
0
        meta = 0;
1389
0
      }
1390
0
    else
1391
0
      {
1392
0
        int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
1393
0
             | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
1394
#if defined _AMIGA || defined VMS
1395
           | FNM_CASEFOLD
1396
#endif
1397
0
           );
1398
0
        nfound = 0;
1399
0
        flags |= GLOB_MAGCHAR;
1400
1401
0
        while (1)
1402
0
    {
1403
0
      const char *name;
1404
0
      size_t len;
1405
#if defined HAVE_DIRENT64 && !defined COMPILE_GLOB64
1406
      struct dirent64 *d;
1407
      struct dirent64 d64;
1408
1409
      if (flags & GLOB_ALTDIRFUNC)
1410
        {
1411
          struct dirent *d32 = (*pglob->gl_readdir) (stream);
1412
          if (d32 != NULL)
1413
      {
1414
        CONVERT_DIRENT_DIRENT64 (&d64, d32);
1415
        d = &d64;
1416
      }
1417
          else
1418
      d = NULL;
1419
        }
1420
      else
1421
        d = __readdir64 ((DIR *) stream);
1422
#else
1423
0
      struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
1424
0
              ? ((struct dirent *)
1425
0
           (*pglob->gl_readdir) (stream))
1426
0
              : __readdir ((DIR *) stream));
1427
0
#endif
1428
0
      if (d == NULL)
1429
0
        break;
1430
0
      if (nbresults > MAX_RESULTS) { 
1431
0
        break;
1432
0
      }
1433
0
      nbresults++;  
1434
0
      if (! REAL_DIR_ENTRY (d))
1435
0
        continue;
1436
1437
0
#ifdef HAVE_D_TYPE
1438
      /* If we shall match only directories use the information
1439
         provided by the dirent call if possible.  */
1440
0
      if ((flags & GLOB_ONLYDIR)
1441
0
          && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
1442
0
        continue;
1443
0
#endif
1444
1445
0
      name = d->d_name;
1446
      
1447
0
      if (fnmatch (pattern, name, fnm_flags) == 0)
1448
0
        {
1449
0
          struct globlink *new = (struct globlink *)
1450
0
      __alloca (sizeof (struct globlink));
1451
0
          len = NAMLEN (d);     
1452
0
          new->name = (char *) malloc (len + 1);
1453
0
          if (new->name == NULL)
1454
0
      goto memory_error;
1455
0
#ifdef HAVE_MEMPCPY
1456
0
          *((char *) mempcpy ((__ptr_t) new->name, name, len))
1457
0
      = '\0';
1458
#else
1459
          memcpy ((__ptr_t) new->name, name, len);
1460
          new->name[len] = '\0';
1461
#endif
1462
0
          new->next = names;
1463
0
          names = new;
1464
0
          ++nfound;
1465
0
        }
1466
0
    }
1467
0
      }
1468
0
  }
1469
0
    }
1470
1471
0
  if (nfound == 0 && (flags & GLOB_NOCHECK))
1472
0
    {
1473
0
      size_t len = strlen (pattern);
1474
0
      nfound = 1;
1475
0
      names = (struct globlink *) __alloca (sizeof (struct globlink));
1476
0
      names->next = NULL;
1477
0
      names->name = (char *) malloc (len + 1);
1478
0
      if (names->name == NULL)
1479
0
  goto memory_error;
1480
0
#ifdef HAVE_MEMPCPY
1481
0
      *((char *) mempcpy (names->name, pattern, len)) = '\0';
1482
#else
1483
      memcpy (names->name, pattern, len);
1484
      names->name[len] = '\0';
1485
#endif
1486
0
    }
1487
1488
0
  if (nfound != 0)
1489
0
    {
1490
0
      char **new_buf;
1491
1492
0
      new_buf
1493
0
  = (char **) realloc (pglob->gl_pathv,
1494
0
           (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
1495
0
           * sizeof (char *));
1496
0
      if (new_buf == NULL)
1497
0
  goto memory_error;
1498
1499
0
      pglob->gl_pathv = new_buf;
1500
1501
0
      for (; names != NULL; names = names->next)
1502
0
  pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc++] = names->name;
1503
0
      pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
1504
1505
0
      pglob->gl_flags = flags;
1506
0
    }
1507
1508
0
  save = errno;
1509
0
  if (stream != NULL)
1510
0
    {
1511
0
      if (flags & GLOB_ALTDIRFUNC)
1512
0
  (*pglob->gl_closedir) (stream);
1513
0
      else
1514
0
  closedir ((DIR *) stream);
1515
0
    }
1516
0
  __set_errno (save);
1517
1518
0
  return nfound == 0 ? GLOB_NOMATCH : 0;
1519
1520
0
 memory_error:
1521
0
  {
1522
0
    int my_save = errno;
1523
0
    if (flags & GLOB_ALTDIRFUNC)
1524
0
      (*pglob->gl_closedir) (stream);
1525
0
    else
1526
0
      closedir ((DIR *) stream);
1527
0
    __set_errno (my_save);
1528
0
  }
1529
0
  while (names != NULL)
1530
0
    {
1531
0
      if (names->name != NULL)
1532
0
  free ((__ptr_t) names->name);
1533
0
      names = names->next;
1534
0
    }
1535
0
  return GLOB_NOSPACE;
1536
0
}
1537
1538
#endif  /* Not ELIDE_CODE.  */