Coverage Report

Created: 2025-07-18 06:04

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