rpm  5.2.1
glob.c
Go to the documentation of this file.
1 /*@-bounds@*/
2 /*@-branchstate@*/
3 /*@-compdef@*/
4 /*@-immediatetrans@*/
5 /*@-internalglobs@*/
6 /*@-loopswitchbreak@*/
7 /*@-modnomods@*/
8 /*@-mods@*/
9 /*@-moduncon@*/
10 /*@-modunconnomods@*/
11 /*@-noeffectuncon@*/
12 /*@-nullpass@*/
13 /*@-onlytrans@*/
14 /*@-protoparammatch@*/
15 /*@-retalias@*/
16 /*@-retvalint@*/
17 /*@-shadow@*/
18 /*@-sizeoftype@*/
19 /*@-temptrans@*/
20 /*@-type@*/
21 /*@-unqualifiedtrans@*/
22 /*@-unrecog@*/
23 
24 /* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
25 
26  This library is free software; you can redistribute it and/or
27  modify it under the terms of the GNU Library General Public License as
28  published by the Free Software Foundation; either version 2 of the
29  License, or (at your option) any later version.
30 
31  This library is distributed in the hope that it will be useful,
32  but WITHOUT ANY WARRANTY; without even the implied warranty of
33  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34  Library General Public License for more details.
35 
36  You should have received a copy of the GNU Library General Public
37  License along with this library; see the file COPYING.LIB. If not,
38  write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
39  Boston, MA 02111-1307, USA. */
40 
41 /* AIX requires this to be the first thing in the file. */
42 #if defined _AIX && !defined __GNUC__
43  #pragma alloca
44 #endif
45 
46 /*@access DIR@*/
47 
48 # include "system.h"
49 
50 /* Needed for offsetof() */
51 # include <stddef.h>
52 
53 # include <assert.h>
54 
55 #undef __alloca
56 #define __alloca alloca
57 #define __stat stat
58 #define NAMLEN(_d) NLENGTH(_d)
59 
60 /* If the system has the `struct dirent64' type we use it internally. */
61 # if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
62 # define CONVERT_D_NAMLEN(d64, d32)
63 # else
64 # define CONVERT_D_NAMLEN(d64, d32) \
65  (d64)->d_namlen = (d32)->d_namlen;
66 # endif
67 
68 # if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
69 # define CONVERT_D_INO(d64, d32)
70 # else
71 # define CONVERT_D_INO(d64, d32) \
72  (d64)->d_ino = (d32)->d_ino;
73 # endif
74 
75 # ifdef _DIRENT_HAVE_D_TYPE
76 # define CONVERT_D_TYPE(d64, d32) \
77  (d64)->d_type = (d32)->d_type;
78 # else
79 # define CONVERT_D_TYPE(d64, d32)
80 # endif
81 
82 # define CONVERT_DIRENT_DIRENT64(d64, d32) \
83  memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \
84  CONVERT_D_NAMLEN (d64, d32) \
85  CONVERT_D_INO (d64, d32) \
86  CONVERT_D_TYPE (d64, d32)
87 
88 #if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
89 /* Posix does not require that the d_ino field be present, and some
90  systems do not provide it. */
91 # define REAL_DIR_ENTRY(dp) 1
92 #else
93 # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
94 #endif /* POSIX */
95 
96 #include <errno.h>
97 #ifndef __set_errno
98 # define __set_errno(val) errno = (val)
99 #endif
100 
101 /* Outcomment the following line for production quality code. */
102 /* #define NDEBUG 1 */
103 
104 #define GLOB_INTERFACE_VERSION 1
105 
106 /*@null@*/
107 static inline const char *next_brace_sub __P ((const char *begin))
108  /*@*/;
109 static int glob_in_dir __P ((const char *pattern, const char *directory,
110  int flags,
111  int (*errfunc) (const char *, int),
112  glob_t *pglob))
113  /*@globals fileSystem @*/
114  /*@modifies fileSystem @*/;
115 static int prefix_array __P ((const char *prefix, char **array, size_t n))
116  /*@*/;
117 static int collated_compare __P ((const __ptr_t, const __ptr_t))
118  /*@*/;
119 
120 
121 /* Find the end of the sub-pattern in a brace expression. We define
122  this as an inline function if the compiler permits. */
123 static inline const char *
124 next_brace_sub (const char *begin)
125 {
126  unsigned int depth = 0;
127  const char *cp = begin;
128 
129  while (1)
130  {
131  if (depth == 0)
132  {
133  if (*cp != ',' && *cp != '}' && *cp != '\0')
134  {
135  if (*cp == '{')
136  ++depth;
137  ++cp;
138  continue;
139  }
140  }
141  else
142  {
143  while (*cp != '\0' && (*cp != '}' || depth > 0))
144  {
145  if (*cp == '}')
146  --depth;
147  ++cp;
148  }
149  if (*cp == '\0')
150  /* An incorrectly terminated brace expression. */
151  return NULL;
152 
153  continue;
154  }
155  break;
156  }
157 
158  return cp;
159 }
160 
161 static int __glob_pattern_p (const char *pattern, int quote);
162 
163 /* Do glob searching for PATTERN, placing results in PGLOB.
164  The bits defined above may be set in FLAGS.
165  If a directory cannot be opened or read and ERRFUNC is not nil,
166  it is called with the pathname that caused the error, and the
167  `errno' value from the failing call; if it returns non-zero
168  `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
169  If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
170  Otherwise, `glob' returns zero. */
171 int
172 glob (const char *pattern, int flags,
173  int (*errfunc) __P ((const char *, int)), glob_t *pglob)
174 {
175  const char *filename;
176  const char *dirname;
177  size_t dirlen;
178  int status;
179  int oldcount;
180 
181  if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
182  {
183  __set_errno (EINVAL);
184  return -1;
185  }
186 
187  if (flags & GLOB_BRACE)
188  {
189  const char *begin = strchr (pattern, '{');
190  if (begin != NULL)
191  {
192  /* Allocate working buffer large enough for our work. Note that
193  we have at least an opening and closing brace. */
194  int firstc;
195  char *alt_start;
196  const char *p;
197  const char *next;
198  const char *rest;
199  size_t rest_len;
200 #ifdef __GNUC__
201  char onealt[strlen (pattern) - 1];
202 #else
203  char *onealt = (char *) xmalloc (strlen (pattern) - 1);
204  if (onealt == NULL)
205  {
206  if (!(flags & GLOB_APPEND))
207  globfree (pglob);
208  return GLOB_NOSPACE;
209  }
210 #endif
211 
212  /* We know the prefix for all sub-patterns. */
213 #ifdef HAVE_MEMPCPY
214  alt_start = mempcpy (onealt, pattern, begin - pattern);
215 #else
216  memcpy (onealt, pattern, begin - pattern);
217  alt_start = &onealt[begin - pattern];
218 #endif
219 
220  /* Find the first sub-pattern and at the same time find the
221  rest after the closing brace. */
222  next = next_brace_sub (begin + 1);
223  if (next == NULL)
224  {
225  /* It is an illegal expression. */
226 #ifndef __GNUC__
227  free (onealt);
228 #endif
229  return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
230  }
231 
232  /* Now find the end of the whole brace expression. */
233  rest = next;
234  while (*rest != '}')
235  {
236  rest = next_brace_sub (rest + 1);
237  if (rest == NULL)
238  {
239  /* It is an illegal expression. */
240 #ifndef __GNUC__
241  free (onealt);
242 #endif
243  return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
244  }
245  }
246  /* Please note that we now can be sure the brace expression
247  is well-formed. */
248  rest_len = strlen (++rest) + 1;
249 
250  /* We have a brace expression. BEGIN points to the opening {,
251  NEXT points past the terminator of the first element, and END
252  points past the final }. We will accumulate result names from
253  recursive runs for each brace alternative in the buffer using
254  GLOB_APPEND. */
255 
256  if (!(flags & GLOB_APPEND))
257  {
258  /* This call is to set a new vector, so clear out the
259  vector so we can append to it. */
260  pglob->gl_pathc = 0;
261  pglob->gl_pathv = NULL;
262  }
263  firstc = pglob->gl_pathc;
264 
265  p = begin + 1;
266  while (1)
267  {
268  int result;
269 
270  /* Construct the new glob expression. */
271 #ifdef HAVE_MEMPCPY
272  mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
273 #else
274  memcpy (alt_start, p, next - p);
275  memcpy (&alt_start[next - p], rest, rest_len);
276 #endif
277 
278  result = glob (onealt,
279  ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC))
280  | GLOB_APPEND), errfunc, pglob);
281 
282  /* If we got an error, return it. */
283  if (result && result != GLOB_NOMATCH)
284  {
285 #ifndef __GNUC__
286  free (onealt);
287 #endif
288  if (!(flags & GLOB_APPEND))
289  globfree (pglob);
290  return result;
291  }
292 
293  if (*next == '}')
294  /* We saw the last entry. */
295  break;
296 
297  p = next + 1;
298  next = next_brace_sub (p);
299  assert (next != NULL);
300  }
301 
302 #ifndef __GNUC__
303  free (onealt);
304 #endif
305 
306  if ((int)pglob->gl_pathc != firstc)
307  /* We found some entries. */
308  return 0;
309  else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
310  return GLOB_NOMATCH;
311  }
312  }
313 
314  /* Find the filename. */
315  filename = strrchr (pattern, '/');
316 #if defined __MSDOS__ || defined WINDOWS32
317  /* The case of "d:pattern". Since `:' is not allowed in
318  file names, we can safely assume that wherever it
319  happens in pattern, it signals the filename part. This
320  is so we could some day support patterns like "[a-z]:foo". */
321  if (filename == NULL)
322  filename = strchr (pattern, ':');
323 #endif /* __MSDOS__ || WINDOWS32 */
324  if (filename == NULL)
325  {
326  /* This can mean two things: a simple name or "~name". The latter
327  case is nothing but a notation for a directory. */
328  if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
329  {
330  dirname = pattern;
331  dirlen = strlen (pattern);
332 
333  /* Set FILENAME to NULL as a special flag. This is ugly but
334  other solutions would require much more code. We test for
335  this special case below. */
336  filename = NULL;
337  }
338  else
339  {
340  filename = pattern;
341 #ifdef _AMIGA
342  dirname = "";
343 #else
344  dirname = ".";
345 #endif
346  dirlen = 0;
347  }
348  }
349  else if (filename == pattern)
350  {
351  /* "/pattern". */
352  dirname = "/";
353  dirlen = 1;
354  ++filename;
355  }
356  else
357  {
358  char *newp;
359  dirlen = filename - pattern;
360 #if defined __MSDOS__ || defined WINDOWS32
361  if (*filename == ':'
362  || (filename > pattern + 1 && filename[-1] == ':'))
363  {
364  char *drive_spec;
365 
366  ++dirlen;
367  drive_spec = (char *) __alloca (dirlen + 1);
368 #ifdef HAVE_MEMPCPY
369  *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
370 #else
371  memcpy (drive_spec, pattern, dirlen);
372  drive_spec[dirlen] = '\0';
373 #endif
374  /* For now, disallow wildcards in the drive spec, to
375  prevent infinite recursion in glob. */
376  if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
377  return GLOB_NOMATCH;
378  /* If this is "d:pattern", we need to copy `:' to DIRNAME
379  as well. If it's "d:/pattern", don't remove the slash
380  from "d:/", since "d:" and "d:/" are not the same.*/
381  }
382 #endif
383  newp = (char *) __alloca (dirlen + 1);
384 #ifdef HAVE_MEMPCPY
385  *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
386 #else
387  memcpy (newp, pattern, dirlen);
388  newp[dirlen] = '\0';
389 #endif
390  dirname = newp;
391  ++filename;
392 
393  if (filename[0] == '\0'
394 #if defined __MSDOS__ || defined WINDOWS32
395  && dirname[dirlen - 1] != ':'
396  && (dirlen < 3 || dirname[dirlen - 2] != ':'
397  || dirname[dirlen - 1] != '/')
398 #endif
399  && dirlen > 1)
400  /* "pattern/". Expand "pattern", appending slashes. */
401  {
402  int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
403  if (val == 0)
404  pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
405  | (flags & GLOB_MARK));
406  return val;
407  }
408  }
409 
410  if (!(flags & GLOB_APPEND))
411  {
412  pglob->gl_pathc = 0;
413  pglob->gl_pathv = NULL;
414  }
415 
416  oldcount = pglob->gl_pathc;
417 
418 #ifndef VMS
419  if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
420  {
421  if (dirname[1] == '\0' || dirname[1] == '/')
422  {
423  /* Look up home directory. */
424  const char *home_dir = getenv ("HOME");
425 # ifdef _AMIGA
426  if (home_dir == NULL || home_dir[0] == '\0')
427  home_dir = "SYS:";
428 # else
429 # ifdef WINDOWS32
430  if (home_dir == NULL || home_dir[0] == '\0')
431  home_dir = "c:/users/default"; /* poor default */
432 # else
433  if (home_dir == NULL || home_dir[0] == '\0')
434  {
435  int success;
436  char *name;
437 # if defined HAVE_GETLOGIN_R || defined _LIBC
438  size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;
439 
440  if (buflen == 0)
441  /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try
442  a moderate value. */
443  buflen = 20;
444  name = (char *) __alloca (buflen);
445 
446  success = getlogin_r (name, buflen) >= 0;
447 # else
448  success = (name = getlogin ()) != NULL;
449 # endif
450  if (success)
451  {
452  struct passwd *p;
453 # if defined HAVE_GETPWNAM_R || defined _LIBC
454  size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
455  char *pwtmpbuf;
456  struct passwd pwbuf;
457  int save = errno;
458 
459  if (pwbuflen == -1)
460  /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
461  Try a moderate value. */
462  pwbuflen = 1024;
463  pwtmpbuf = (char *) __alloca (pwbuflen);
464 
465  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
466  != 0)
467  {
468  if (errno != ERANGE)
469  {
470  p = NULL;
471  break;
472  }
473  pwbuflen *= 2;
474  pwtmpbuf = (char *) __alloca (pwbuflen);
475  __set_errno (save);
476  }
477 # else
478  p = getpwnam (name);
479 # endif
480  if (p != NULL)
481  home_dir = p->pw_dir;
482  }
483  }
484  if (home_dir == NULL || home_dir[0] == '\0')
485  {
486  if (flags & GLOB_TILDE_CHECK)
487  return GLOB_NOMATCH;
488  else
489  home_dir = "~"; /* No luck. */
490  }
491 # endif /* WINDOWS32 */
492 # endif
493  /* Now construct the full directory. */
494  if (dirname[1] == '\0')
495  dirname = home_dir;
496  else
497  {
498  char *newp;
499  size_t home_len = strlen (home_dir);
500  newp = (char *) __alloca (home_len + dirlen);
501 # ifdef HAVE_MEMPCPY
502  mempcpy (mempcpy (newp, home_dir, home_len),
503  &dirname[1], dirlen);
504 # else
505  memcpy (newp, home_dir, home_len);
506  memcpy (&newp[home_len], &dirname[1], dirlen);
507 # endif
508  dirname = newp;
509  }
510  }
511 # if !defined _AMIGA && !defined WINDOWS32
512  else
513  {
514  char *end_name = strchr (dirname, '/');
515  const char *user_name;
516  const char *home_dir;
517 
518  if (end_name == NULL)
519  user_name = dirname + 1;
520  else
521  {
522  char *newp;
523  newp = (char *) __alloca (end_name - dirname);
524 # ifdef HAVE_MEMPCPY
525  *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
526  = '\0';
527 # else
528  memcpy (newp, dirname + 1, end_name - dirname);
529  newp[end_name - dirname - 1] = '\0';
530 # endif
531  user_name = newp;
532  }
533 
534  /* Look up specific user's home directory. */
535  {
536  struct passwd *p;
537 # if defined HAVE_GETPWNAM_R || defined _LIBC
538  size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
539  char *pwtmpbuf;
540  struct passwd pwbuf;
541  int save = errno;
542 
543  if (buflen == -1)
544  /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a
545  moderate value. */
546  buflen = 1024;
547  pwtmpbuf = (char *) __alloca (buflen);
548 
549  while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
550  {
551  if (errno != ERANGE)
552  {
553  p = NULL;
554  break;
555  }
556  buflen *= 2;
557  pwtmpbuf = __alloca (buflen);
558  __set_errno (save);
559  }
560 # else
561  p = getpwnam (user_name);
562 # endif
563  if (p != NULL)
564  home_dir = p->pw_dir;
565  else
566  home_dir = NULL;
567  }
568  /* If we found a home directory use this. */
569  if (home_dir != NULL)
570  {
571  char *newp;
572  size_t home_len = strlen (home_dir);
573  size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
574  newp = (char *) __alloca (home_len + rest_len + 1);
575 # ifdef HAVE_MEMPCPY
576  *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
577  end_name, rest_len)) = '\0';
578 # else
579  memcpy (newp, home_dir, home_len);
580  memcpy (&newp[home_len], end_name, rest_len);
581  newp[home_len + rest_len] = '\0';
582 # endif
583  dirname = newp;
584  }
585  else
586  if (flags & GLOB_TILDE_CHECK)
587  /* We have to regard it as an error if we cannot find the
588  home directory. */
589  return GLOB_NOMATCH;
590  }
591 # endif /* Not Amiga && not WINDOWS32. */
592  }
593 #endif /* Not VMS. */
594 
595  /* Now test whether we looked for "~" or "~NAME". In this case we
596  can give the answer now. */
597  if (filename == NULL)
598  {
599  struct stat st;
600 
601  /* Return the directory if we don't check for error or if it exists. */
602  if ((flags & GLOB_NOCHECK)
603  || (((flags & GLOB_ALTDIRFUNC)
604  ? (*pglob->gl_stat) (dirname, &st)
605  : __stat (dirname, &st)) == 0
606  && S_ISDIR (st.st_mode)))
607  {
608  pglob->gl_pathv
609  = (char **) xrealloc (pglob->gl_pathv,
610  (pglob->gl_pathc +
611  ((flags & GLOB_DOOFFS) ?
612  pglob->gl_offs : 0) +
613  1 + 1) *
614  sizeof (char *));
615  if (pglob->gl_pathv == NULL)
616  return GLOB_NOSPACE;
617 
618  if (flags & GLOB_DOOFFS)
619  while (pglob->gl_pathc < pglob->gl_offs)
620  pglob->gl_pathv[pglob->gl_pathc++] = NULL;
621 
622 #if defined HAVE_STRDUP || defined _LIBC
623  pglob->gl_pathv[pglob->gl_pathc] = xstrdup (dirname);
624 #else
625  {
626  size_t len = strlen (dirname) + 1;
627  char *dircopy = xmalloc (len);
628  if (dircopy != NULL)
629  pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname,
630  len);
631  }
632 #endif
633  if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
634  {
635  free (pglob->gl_pathv);
636  return GLOB_NOSPACE;
637  }
638  pglob->gl_pathv[++pglob->gl_pathc] = NULL;
639  pglob->gl_flags = flags;
640 
641  return 0;
642  }
643 
644  /* Not found. */
645  return GLOB_NOMATCH;
646  }
647 
648  if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
649  {
650  /* The directory name contains metacharacters, so we
651  have to glob for the directory, and then glob for
652  the pattern in each directory found. */
653  glob_t dirs;
654  register int i;
655 
656  if ((flags & GLOB_ALTDIRFUNC) != 0)
657  {
658  /* Use the alternative access functions also in the recursive
659  call. */
660  dirs.gl_opendir = pglob->gl_opendir;
661  dirs.gl_readdir = pglob->gl_readdir;
662  dirs.gl_closedir = pglob->gl_closedir;
663  dirs.gl_stat = pglob->gl_stat;
664  dirs.gl_lstat = pglob->gl_lstat;
665  }
666 
667  status = glob (dirname,
668  ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE
669  | GLOB_ALTDIRFUNC))
671  errfunc, &dirs);
672  if (status != 0)
673  return status;
674 
675  /* We have successfully globbed the preceding directory name.
676  For each name we found, call glob_in_dir on it and FILENAME,
677  appending the results to PGLOB. */
678  for (i = 0; i < (int)dirs.gl_pathc; ++i)
679  {
680  int old_pathc;
681 
682 #ifdef SHELL
683  {
684  /* Make globbing interruptible in the bash shell. */
685  extern int interrupt_state;
686 
687  if (interrupt_state)
688  {
689  globfree (&dirs);
690  globfree (&files);
691  return GLOB_ABORTED;
692  }
693  }
694 #endif /* SHELL. */
695 
696  old_pathc = pglob->gl_pathc;
697  status = glob_in_dir (filename, dirs.gl_pathv[i],
698  ((flags | GLOB_APPEND)
699  & ~(GLOB_NOCHECK | GLOB_ERR)),
700  errfunc, pglob);
701  if (status == GLOB_NOMATCH)
702  /* No matches in this directory. Try the next. */
703  continue;
704 
705  if (status != 0)
706  {
707  globfree (&dirs);
708  globfree (pglob);
709  return status;
710  }
711 
712  /* Stick the directory on the front of each name. */
713  if (prefix_array (dirs.gl_pathv[i],
714  &pglob->gl_pathv[old_pathc],
715  pglob->gl_pathc - old_pathc))
716  {
717  globfree (&dirs);
718  globfree (pglob);
719  return GLOB_NOSPACE;
720  }
721  }
722 
723  flags |= GLOB_MAGCHAR;
724 
725  /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
726  But if we have not found any matching entry and thie GLOB_NOCHECK
727  flag was set we must return the list consisting of the disrectory
728  names followed by the filename. */
729  if ((int)pglob->gl_pathc == oldcount)
730  {
731  /* No matches. */
732  if (flags & GLOB_NOCHECK)
733  {
734  size_t filename_len = strlen (filename) + 1;
735  char **new_pathv;
736  struct stat st;
737 
738  /* This is an pessimistic guess about the size. */
739  pglob->gl_pathv
740  = (char **) xrealloc (pglob->gl_pathv,
741  (pglob->gl_pathc +
742  ((flags & GLOB_DOOFFS) ?
743  pglob->gl_offs : 0) +
744  dirs.gl_pathc + 1) *
745  sizeof (char *));
746  if (pglob->gl_pathv == NULL)
747  {
748  globfree (&dirs);
749  return GLOB_NOSPACE;
750  }
751 
752  if (flags & GLOB_DOOFFS)
753  while (pglob->gl_pathc < pglob->gl_offs)
754  pglob->gl_pathv[pglob->gl_pathc++] = NULL;
755 
756  for (i = 0; i < (int)dirs.gl_pathc; ++i)
757  {
758  const char *dir = dirs.gl_pathv[i];
759  size_t dir_len = strlen (dir);
760 
761  /* First check whether this really is a directory. */
762  if (((flags & GLOB_ALTDIRFUNC)
763  ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0
764  || !S_ISDIR (st.st_mode))
765  /* No directory, ignore this entry. */
766  continue;
767 
768  pglob->gl_pathv[pglob->gl_pathc] = xmalloc (dir_len + 1
769  + filename_len);
770  if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
771  {
772  globfree (&dirs);
773  globfree (pglob);
774  return GLOB_NOSPACE;
775  }
776 
777 #ifdef HAVE_MEMPCPY
778  mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc],
779  dir, dir_len),
780  "/", 1),
781  filename, filename_len);
782 #else
783  memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len);
784  pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/';
785  memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1],
786  filename, filename_len);
787 #endif
788  ++pglob->gl_pathc;
789  }
790 
791  pglob->gl_pathv[pglob->gl_pathc] = NULL;
792  pglob->gl_flags = flags;
793 
794  /* Now we know how large the gl_pathv vector must be. */
795  new_pathv = (char **) xrealloc (pglob->gl_pathv,
796  ((pglob->gl_pathc + 1)
797  * sizeof (char *)));
798  if (new_pathv != NULL)
799  pglob->gl_pathv = new_pathv;
800  }
801  else
802  return GLOB_NOMATCH;
803  }
804 
805  globfree (&dirs);
806  }
807  else
808  {
809  status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
810  if (status != 0)
811  return status;
812 
813  if (dirlen > 0)
814  {
815  /* Stick the directory on the front of each name. */
816  int ignore = oldcount;
817 
818  if ((flags & GLOB_DOOFFS) && ignore < (int)pglob->gl_offs)
819  ignore = pglob->gl_offs;
820 
821  if (prefix_array (dirname,
822  &pglob->gl_pathv[ignore],
823  pglob->gl_pathc - ignore))
824  {
825  globfree (pglob);
826  return GLOB_NOSPACE;
827  }
828  }
829  }
830 
831  if (flags & GLOB_MARK)
832  {
833  /* Append slashes to directory names. */
834  int i;
835  struct stat st;
836  for (i = oldcount; i < (int)pglob->gl_pathc; ++i)
837  if (((flags & GLOB_ALTDIRFUNC)
838  ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st)
839  : __stat (pglob->gl_pathv[i], &st)) == 0
840  && S_ISDIR (st.st_mode))
841  {
842  size_t len = strlen (pglob->gl_pathv[i]) + 2;
843  char *new = xrealloc (pglob->gl_pathv[i], len);
844  if (new == NULL)
845  {
846  globfree (pglob);
847  return GLOB_NOSPACE;
848  }
849  strcpy (&new[len - 2], "/");
850  pglob->gl_pathv[i] = new;
851  }
852  }
853 
854  if (!(flags & GLOB_NOSORT))
855  {
856  /* Sort the vector. */
857  int non_sort = oldcount;
858 
859  if ((flags & GLOB_DOOFFS) && (int)pglob->gl_offs > oldcount)
860  non_sort = pglob->gl_offs;
861 
862  qsort ((__ptr_t) &pglob->gl_pathv[non_sort],
863  pglob->gl_pathc - non_sort,
864  sizeof (char *), collated_compare);
865  }
866 
867  return 0;
868 }
869 
870 
871 /* Free storage allocated in PGLOB by a previous `glob' call. */
872 void
873 globfree (glob_t *pglob)
874 {
875  if (pglob->gl_pathv != NULL)
876  {
877  register int i;
878  for (i = 0; i < (int)pglob->gl_pathc; ++i)
879  if (pglob->gl_pathv[i] != NULL)
880  free ((__ptr_t) pglob->gl_pathv[i]);
881  free ((__ptr_t) pglob->gl_pathv);
882  }
883 }
884 
885 
886 /* Do a collated comparison of A and B. */
887 static int
888 collated_compare (const __ptr_t a, const __ptr_t b)
889 {
890  const char *const s1 = *(const char *const * const) a;
891  const char *const s2 = *(const char *const * const) b;
892 
893  if (s1 == s2)
894  return 0;
895  if (s1 == NULL)
896  return 1;
897  if (s2 == NULL)
898  return -1;
899  return strcoll (s1, s2);
900 }
901 
902 
903 /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
904  elements in place. Return nonzero if out of memory, zero if successful.
905  A slash is inserted between DIRNAME and each elt of ARRAY,
906  unless DIRNAME is just "/". Each old element of ARRAY is freed. */
907 static int
908 prefix_array (const char *dirname, char **array, size_t n)
909 {
910  register size_t i;
911  size_t dirlen = strlen (dirname);
912 #if defined __MSDOS__ || defined WINDOWS32
913  int sep_char = '/';
914 # define DIRSEP_CHAR sep_char
915 #else
916 # define DIRSEP_CHAR '/'
917 #endif
918 
919  if (dirlen == 1 && dirname[0] == '/')
920  /* DIRNAME is just "/", so normal prepending would get us "//foo".
921  We want "/foo" instead, so don't prepend any chars from DIRNAME. */
922  dirlen = 0;
923 #if defined __MSDOS__ || defined WINDOWS32
924  else if (dirlen > 1)
925  {
926  if (dirname[dirlen - 1] == '/')
927  /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */
928  --dirlen;
929  else if (dirname[dirlen - 1] == ':')
930  {
931  /* DIRNAME is "d:". Use `:' instead of `/'. */
932  --dirlen;
933  sep_char = ':';
934  }
935  }
936 #endif
937 
938  for (i = 0; i < n; ++i)
939  {
940  size_t eltlen = strlen (array[i]) + 1;
941  char *new = (char *) xmalloc (dirlen + 1 + eltlen);
942  if (new == NULL)
943  {
944  while (i > 0)
945  free ((__ptr_t) array[--i]);
946  return 1;
947  }
948 
949 #ifdef HAVE_MEMPCPY
950  {
951  char *endp = (char *) mempcpy (new, dirname, dirlen);
952  *endp++ = DIRSEP_CHAR;
953  mempcpy (endp, array[i], eltlen);
954  }
955 #else
956  memcpy (new, dirname, dirlen);
957  new[dirlen] = DIRSEP_CHAR;
958  memcpy (&new[dirlen + 1], array[i], eltlen);
959 #endif
960  free ((__ptr_t) array[i]);
961  array[i] = new;
962  }
963 
964  return 0;
965 }
966 
967 
968 /* We must not compile this function twice. */
969 #if !defined _LIBC || !defined NO_GLOB_PATTERN_P
970 /* Return nonzero if PATTERN contains any metacharacters.
971  Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
972 static int
973 __glob_pattern_p (const char *pattern, int quote)
974 {
975  register const char *p;
976  int open = 0;
977 
978  for (p = pattern; *p != '\0'; ++p)
979  switch (*p)
980  {
981  case '?':
982  case '*':
983  return 1;
984 
985  case '\\':
986  if (quote && p[1] != '\0')
987  ++p;
988  break;
989 
990  case '[':
991  open = 1;
992  break;
993 
994  case ']':
995  if (open)
996  return 1;
997  break;
998  }
999 
1000  return 0;
1001 }
1002 # ifdef _LIBC
1003 weak_alias (__glob_pattern_p, glob_pattern_p)
1004 # endif
1005 #endif
1006 
1007 
1008 /* Like `glob', but PATTERN is a final pathname component,
1009  and matches are searched for in DIRECTORY.
1010  The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
1011  The GLOB_APPEND flag is assumed to be set (always appends). */
1012 static int
1013 glob_in_dir (const char *pattern, const char *directory, int flags,
1014  int (*errfunc) __P ((const char *, int)), glob_t *pglob)
1015 {
1016  __ptr_t stream = NULL;
1017 
1018  struct globlink
1019  {
1020  struct globlink *next;
1021  char *name;
1022  };
1023  struct globlink *names = NULL;
1024  size_t nfound;
1025  int meta;
1026  int save;
1027 
1028  meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
1029  if (meta == 0)
1030  {
1031  if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))
1032  /* We need not do any tests. The PATTERN contains no meta
1033  characters and we must not return an error therefore the
1034  result will always contain exactly one name. */
1035  flags |= GLOB_NOCHECK;
1036  else
1037  {
1038  /* Since we use the normal file functions we can also use stat()
1039  to verify the file is there. */
1040  struct stat st;
1041  size_t patlen = strlen (pattern);
1042  size_t dirlen = strlen (directory);
1043  char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
1044 
1045 # ifdef HAVE_MEMPCPY
1046  mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
1047  "/", 1),
1048  pattern, patlen + 1);
1049 # else
1050  memcpy (fullname, directory, dirlen);
1051  fullname[dirlen] = '/';
1052  memcpy (&fullname[dirlen + 1], pattern, patlen + 1);
1053 # endif
1054  if (((flags & GLOB_ALTDIRFUNC)
1055  ? (*pglob->gl_stat) (fullname, &st)
1056  : __stat (fullname, &st)) == 0)
1057  /* We found this file to be existing. Now tell the rest
1058  of the function to copy this name into the result. */
1059  flags |= GLOB_NOCHECK;
1060  }
1061 
1062  nfound = 0;
1063  }
1064  else
1065  {
1066  if (pattern[0] == '\0')
1067  {
1068  /* This is a special case for matching directories like in
1069  "*a/". */
1070  names = (struct globlink *) __alloca (sizeof (struct globlink));
1071  names->name = (char *) xmalloc (1);
1072  if (names->name == NULL)
1073  goto memory_error;
1074  names->name[0] = '\0';
1075  names->next = NULL;
1076  nfound = 1;
1077  meta = 0;
1078  }
1079  else
1080  {
1081  stream = ((flags & GLOB_ALTDIRFUNC)
1082  ? (*pglob->gl_opendir) (directory)
1083  : (__ptr_t) opendir (directory));
1084  if (stream == NULL)
1085  {
1086  if (errno != ENOTDIR
1087  && ((errfunc != NULL && (*errfunc) (directory, errno))
1088  || (flags & GLOB_ERR)))
1089  return GLOB_ABORTED;
1090  nfound = 0;
1091  meta = 0;
1092  }
1093  else
1094  {
1095  int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
1096  | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
1097 #if defined _AMIGA || defined VMS
1098  | FNM_CASEFOLD
1099 #endif
1100  );
1101  nfound = 0;
1102  flags |= GLOB_MAGCHAR;
1103 
1104  while (1)
1105  {
1106  const char *name;
1107  size_t len;
1108 #ifdef _LARGEFILE64_SOURCE
1109  struct dirent64 *d;
1110  union
1111  {
1112  struct dirent64 d64;
1113  char room [offsetof (struct dirent64, d_name[0])
1114  + NAME_MAX + 1];
1115  }
1116  d64buf;
1117 
1118  if ((flags & GLOB_ALTDIRFUNC))
1119  {
1120  struct dirent *d32 = (*pglob->gl_readdir) (stream);
1121  if (d32 != NULL)
1122  {
1123  CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32);
1124  d = &d64buf.d64;
1125  }
1126  else
1127  d = NULL;
1128  }
1129  else
1130  d = readdir64 (stream);
1131 #else
1132  struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
1133  ? (*pglob->gl_readdir) (stream)
1134  : readdir ((DIR *) stream));
1135 #endif
1136  if (d == NULL)
1137  break;
1138  if (! REAL_DIR_ENTRY (d))
1139  continue;
1140 
1141 #ifdef HAVE_D_TYPE
1142  /* If we shall match only directories use the information
1143  provided by the dirent call if possible. */
1144  if ((flags & GLOB_ONLYDIR)
1145  && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
1146  continue;
1147 #endif
1148 
1149  name = d->d_name;
1150 
1151  if (fnmatch (pattern, name, fnm_flags) == 0)
1152  {
1153  struct globlink *new = (struct globlink *)
1154  __alloca (sizeof (struct globlink));
1155  len = NAMLEN (d);
1156  new->name = (char *) xmalloc (len + 1);
1157  if (new->name == NULL)
1158  goto memory_error;
1159 #ifdef HAVE_MEMPCPY
1160  *((char *) mempcpy ((__ptr_t) new->name, name, len))
1161  = '\0';
1162 #else
1163  memcpy ((__ptr_t) new->name, name, len);
1164  new->name[len] = '\0';
1165 #endif
1166  new->next = names;
1167  names = new;
1168  ++nfound;
1169  }
1170  }
1171  }
1172  }
1173  }
1174 
1175  if (nfound == 0 && (flags & GLOB_NOCHECK))
1176  {
1177  size_t len = strlen (pattern);
1178  nfound = 1;
1179  names = (struct globlink *) __alloca (sizeof (struct globlink));
1180  names->next = NULL;
1181  names->name = (char *) xmalloc (len + 1);
1182  if (names->name == NULL)
1183  goto memory_error;
1184 #ifdef HAVE_MEMPCPY
1185  *((char *) mempcpy (names->name, pattern, len)) = '\0';
1186 #else
1187  memcpy (names->name, pattern, len);
1188  names->name[len] = '\0';
1189 #endif
1190  }
1191 
1192  if (nfound != 0)
1193  {
1194  pglob->gl_pathv
1195  = (char **) xrealloc (pglob->gl_pathv,
1196  (pglob->gl_pathc +
1197  ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
1198  nfound + 1) *
1199  sizeof (char *));
1200  if (pglob->gl_pathv == NULL)
1201  goto memory_error;
1202 
1203  if (flags & GLOB_DOOFFS)
1204  while (pglob->gl_pathc < pglob->gl_offs)
1205  pglob->gl_pathv[pglob->gl_pathc++] = NULL;
1206 
1207  for (; names != NULL; names = names->next)
1208  pglob->gl_pathv[pglob->gl_pathc++] = names->name;
1209  pglob->gl_pathv[pglob->gl_pathc] = NULL;
1210 
1211  pglob->gl_flags = flags;
1212  }
1213 
1214  save = errno;
1215  if (stream != NULL)
1216  {
1217  if (flags & GLOB_ALTDIRFUNC)
1218  (*pglob->gl_closedir) (stream);
1219  else
1220  closedir ((DIR *) stream);
1221  }
1222  __set_errno (save);
1223 
1224  return nfound == 0 ? GLOB_NOMATCH : 0;
1225 
1226  memory_error:
1227  {
1228  save = errno;
1229  if (flags & GLOB_ALTDIRFUNC)
1230  (*pglob->gl_closedir) (stream);
1231  else
1232  closedir ((DIR *) stream);
1233  __set_errno (save);
1234  }
1235  while (names != NULL)
1236  {
1237  if (names->name != NULL)
1238  free ((__ptr_t) names->name);
1239  names = names->next;
1240  }
1241  return GLOB_NOSPACE;
1242 }
1243 /*@=unrecog@*/
1244 /*@=unqualifiedtrans@*/
1245 /*@=type@*/
1246 /*@=temptrans@*/
1247 /*@=sizeoftype@*/
1248 /*@=shadow@*/
1249 /*@=retvalint@*/
1250 /*@=retalias@*/
1251 /*@=protoparammatch@*/
1252 /*@=onlytrans@*/
1253 /*@=nullpass@*/
1254 /*@=noeffectuncon@*/
1255 /*@=modunconnomods@*/
1256 /*@=moduncon@*/
1257 /*@=mods@*/
1258 /*@=modnomods@*/
1259 /*@=loopswitchbreak@*/
1260 /*@=internalglobs@*/
1261 /*@=immediatetrans@*/
1262 /*@=compdef@*/
1263 /*@=branchstate@*/
1264 /*@=bounds@*/