rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

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))
670 | GLOB_NOSORT | GLOB_ONLYDIR),
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@*/