1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #ifdef HAVE_CONFIG_H
21: # include <config.h>
22: #endif
23:
24: #include <glob.h>
25:
26: #include <errno.h>
27: #include <sys/types.h>
28: #include <sys/stat.h>
29: #include <stddef.h>
30:
31:
32:
33: #include <assert.h>
34:
35: #include <stdio.h>
36:
37: #if !defined _LIBC || !defined GLOB_ONLY_P
38: #if defined HAVE_UNISTD_H || defined _LIBC
39: # include <unistd.h>
40: # ifndef POSIX
41: # ifdef _POSIX_VERSION
42: # define POSIX
43: # endif
44: # endif
45: #endif
46:
47: #include <pwd.h>
48:
49: #include <errno.h>
50: #ifndef __set_errno
51: # define __set_errno(val) errno = (val)
52: #endif
53:
54: #if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
55: # include <dirent.h>
56: # define NAMLEN(dirent) strlen((dirent)->d_name)
57: #else
58: # define dirent direct
59: # define NAMLEN(dirent) (dirent)->d_namlen
60: # ifdef HAVE_SYS_NDIR_H
61: # include <sys/ndir.h>
62: # endif
63: # ifdef HAVE_SYS_DIR_H
64: # include <sys/dir.h>
65: # endif
66: # ifdef HAVE_NDIR_H
67: # include <ndir.h>
68: # endif
69: # ifdef HAVE_VMSDIR_H
70: # include "vmsdir.h"
71: # endif
72: #endif
73:
74:
75:
76: #ifdef _D_NAMLEN
77: # undef NAMLEN
78: # define NAMLEN(d) _D_NAMLEN(d)
79: #endif
80:
81:
82:
83:
84: #if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
85:
86: # define DIRENT_MUST_BE(d, t) ((d)->d_type == (t))
87:
88:
89: # define DIRENT_MIGHT_BE_SYMLINK(d) \
90: ((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK)
91:
92:
93: # define DIRENT_MIGHT_BE_DIR(d) \
94: ((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d))
95:
96: #else
97: # define DIRENT_MUST_BE(d, t) false
98: # define DIRENT_MIGHT_BE_SYMLINK(d) true
99: # define DIRENT_MIGHT_BE_DIR(d) true
100: #endif
101:
102:
103: #if defined _LIBC && !defined COMPILE_GLOB64
104: # if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
105: # define CONVERT_D_NAMLEN(d64, d32)
106: # else
107: # define CONVERT_D_NAMLEN(d64, d32) \
108: (d64)->d_namlen = (d32)->d_namlen;
109: # endif
110:
111: # if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
112: # define CONVERT_D_INO(d64, d32)
113: # else
114: # define CONVERT_D_INO(d64, d32) \
115: (d64)->d_ino = (d32)->d_ino;
116: # endif
117:
118: # ifdef _DIRENT_HAVE_D_TYPE
119: # define CONVERT_D_TYPE(d64, d32) \
120: (d64)->d_type = (d32)->d_type;
121: # else
122: # define CONVERT_D_TYPE(d64, d32)
123: # endif
124:
125: # define CONVERT_DIRENT_DIRENT64(d64, d32) \
126: memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \
127: CONVERT_D_NAMLEN (d64, d32) \
128: CONVERT_D_INO (d64, d32) \
129: CONVERT_D_TYPE (d64, d32)
130: #endif
131:
132:
133: #if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
134:
135:
136: # define REAL_DIR_ENTRY(dp) 1
137: #else
138: # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
139: #endif
140:
141: #include <stdlib.h>
142: #include <string.h>
143:
144:
145: #include <limits.h>
146: #ifndef NAME_MAX
147: # define NAME_MAX (sizeof (((struct dirent *) 0)->d_name))
148: #endif
149:
150: #include <alloca.h>
151:
152: #ifdef _LIBC
153: # undef strdup
154: # define strdup(str) __strdup (str)
155: # define sysconf(id) __sysconf (id)
156: # define closedir(dir) __closedir (dir)
157: # define opendir(name) __opendir (name)
158: # define readdir(str) __readdir64 (str)
159: # define getpwnam_r(name, bufp, buf, len, res) \
160: __getpwnam_r (name, bufp, buf, len, res)
161: # ifndef __stat64
162: # define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
163: # endif
164: # define struct_stat64 struct stat64
165: #else
166: # include "getlogin_r.h"
167: # include "mempcpy.h"
168: # include "stat-macros.h"
169: # include "strdup.h"
170: # define __stat64(fname, buf) stat (fname, buf)
171: # define struct_stat64 struct stat
172: # define __stat(fname, buf) stat (fname, buf)
173: # define __alloca alloca
174: # define __readdir readdir
175: # define __readdir64 readdir64
176: # define __glob_pattern_p glob_pattern_p
177: #endif
178:
179: #include <fnmatch.h>
180:
181: #ifdef _SC_GETPW_R_SIZE_MAX
182: # define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX)
183: #else
184: # define GETPW_R_SIZE_MAX() (-1)
185: #endif
186: #ifdef _SC_LOGIN_NAME_MAX
187: # define GET_LOGIN_NAME_MAX() sysconf (_SC_LOGIN_NAME_MAX)
188: #else
189: # define GET_LOGIN_NAME_MAX() (-1)
190: #endif
191: ^L
192: static const char *next_brace_sub (const char *begin, int flags) __THROW;
193:
194: #endif
195:
196: #ifndef attribute_hidden
197: # define attribute_hidden
198: #endif
199:
200: static int glob_in_dir (const char *pattern, const char *directory,
201: int flags, int (*errfunc) (const char *, int),
202: glob_t *pglob);
203: extern int __glob_pattern_type (const char *pattern, int quote)
204: attribute_hidden;
205:
206: #if !defined _LIBC || !defined GLOB_ONLY_P
207: static int prefix_array (const char *prefix, char **array, size_t n) __THROW;
208: static int collated_compare (const void *, const void *) __THROW;
209:
210:
211:
212: static const char *
213: next_brace_sub (const char *cp, int flags)
214: {
215: unsigned int depth = 0;
216: while (*cp != '\0')
217: if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\')
218: {
219: if (*++cp == '\0')
220: break;
221: ++cp;
222: }
223: else
224: {
225: if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
226: break;
227:
228: if (*cp++ == '{')
229: depth++;
230: }
231:
232: return *cp != '\0' ? cp : NULL;
233: }
234:
235: #endif
236:
237:
238:
239:
240:
241:
242:
243:
244:
245: int
246: #ifdef GLOB_ATTRIBUTE
247: GLOB_ATTRIBUTE
248: #endif
249: glob (pattern, flags, errfunc, pglob)
250: const char *pattern;
251: int flags;
252: int (*errfunc) (const char *, int);
253: glob_t *pglob;
254: {
255: const char *filename;
256: const char *dirname;
257: size_t dirlen;
258: int status;
259: size_t oldcount;
260: int meta;
261: int dirname_modified;
262: glob_t dirs;
263:
264: if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
265: {
266: __set_errno (EINVAL);
267: return -1;
268: }
269:
270: if (!(flags & GLOB_DOOFFS))
271:
272:
273: pglob->gl_offs = 0;
274:
275: if (flags & GLOB_BRACE)
276: {
277: const char *begin;
278:
279: if (flags & GLOB_NOESCAPE)
280: begin = strchr (pattern, '{');
281: else
282: {
283: begin = pattern;
284: while (1)
285: {
286: if (*begin == '\0')
287: {
288: begin = NULL;
289: break;
290: }
291:
292: if (*begin == '\\' && begin[1] != '\0')
293: ++begin;
294: else if (*begin == '{')
295: break;
296:
297: ++begin;
298: }
299: }
300:
301: if (begin != NULL)
302: {
303:
304:
305: size_t firstc;
306: char *alt_start;
307: const char *p;
308: const char *next;
309: const char *rest;
310: size_t rest_len;
311: #ifdef __GNUC__
312: char onealt[strlen (pattern) - 1];
313: #else
314: char *onealt = (char *) malloc (strlen (pattern) - 1);
315: if (onealt == NULL)
316: {
317: if (!(flags & GLOB_APPEND))
318: {
319: pglob->gl_pathc = 0;
320: pglob->gl_pathv = NULL;
321: }
322: return GLOB_NOSPACE;
323: }
324: #endif
325:
326:
327: alt_start = mempcpy (onealt, pattern, begin - pattern);
328:
329:
330:
331: next = next_brace_sub (begin + 1, flags);
332: if (next == NULL)
333: {
334:
335: #ifndef __GNUC__
336: free (onealt);
337: #endif
338: return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
339: }
340:
341:
342: rest = next;
343: while (*rest != '}')
344: {
345: rest = next_brace_sub (rest + 1, flags);
346: if (rest == NULL)
347: {
348:
349: #ifndef __GNUC__
350: free (onealt);
351: #endif
352: return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
353: }
354: }
355:
356:
357: rest_len = strlen (++rest) + 1;
358:
359:
360:
361:
362:
363:
364:
365: if (!(flags & GLOB_APPEND))
366: {
367:
368:
369: pglob->gl_pathc = 0;
370: pglob->gl_pathv = NULL;
371: }
372: firstc = pglob->gl_pathc;
373:
374: p = begin + 1;
375: while (1)
376: {
377: int result;
378:
379:
380: mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
381:
382: result = glob (onealt,
383: ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
384: | GLOB_APPEND), errfunc, pglob);
385:
386:
387: if (result && result != GLOB_NOMATCH)
388: {
389: #ifndef __GNUC__
390: free (onealt);
391: #endif
392: if (!(flags & GLOB_APPEND))
393: {
394: globfree (pglob);
395: pglob->gl_pathc = 0;
396: }
397: return result;
398: }
399:
400: if (*next == '}')
401:
402: break;
403:
404: p = next + 1;
405: next = next_brace_sub (p, flags);
406: assert (next != NULL);
407: }
408:
409: #ifndef __GNUC__
410: free (onealt);
411: #endif
412:
413: if (pglob->gl_pathc != firstc)
414:
415: return 0;
416: else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
417: return GLOB_NOMATCH;
418: }
419: }
420:
421:
422: filename = strrchr (pattern, '/');
423: #if defined __MSDOS__ || defined WINDOWS32
424:
425:
426:
427:
428: if (filename == NULL)
429: filename = strchr (pattern, ':');
430: #endif
431: dirname_modified = 0;
432: if (filename == NULL)
433: {
434:
435:
436: if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
437: {
438: dirname = pattern;
439: dirlen = strlen (pattern);
440:
441:
442:
443:
444: filename = NULL;
445: }
446: else
447: {
448: filename = pattern;
449: #ifdef _AMIGA
450: dirname = "";
451: #else
452: dirname = ".";
453: #endif
454: dirlen = 0;
455: }
456: }
457: else if (filename == pattern
458: || (filename == pattern + 1 && pattern[0] == '\\'
459: && (flags & GLOB_NOESCAPE) == 0))
460: {
461:
462: dirname = "/";
463: dirlen = 1;
464: ++filename;
465: }
466: else
467: {
468: char *newp;
469: dirlen = filename - pattern;
470: #if defined __MSDOS__ || defined WINDOWS32
471: if (*filename == ':'
472: || (filename > pattern + 1 && filename[-1] == ':'))
473: {
474: char *drive_spec;
475:
476: ++dirlen;
477: drive_spec = (char *) __alloca (dirlen + 1);
478: *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
479:
480:
481: if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
482: return GLOB_NOMATCH;
483:
484:
485:
486: }
487: #endif
488: newp = (char *) __alloca (dirlen + 1);
489: *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
490: dirname = newp;
491: ++filename;
492:
493: if (filename[0] == '\0'
494: #if defined __MSDOS__ || defined WINDOWS32
495: && dirname[dirlen - 1] != ':'
496: && (dirlen < 3 || dirname[dirlen - 2] != ':'
497: || dirname[dirlen - 1] != '/')
498: #endif
499: && dirlen > 1)
500:
501: {
502: int orig_flags = flags;
503: if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
504: {
505:
506:
507: char *p = (char *) &dirname[dirlen - 1];
508:
509: while (p > dirname && p[-1] == '\\') --p;
510: if ((&dirname[dirlen] - p) & 1)
511: {
512: *(char *) &dirname[--dirlen] = '\0';
513: flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
514: }
515: }
516: int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
517: if (val == 0)
518: pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
519: | (flags & GLOB_MARK));
520: else if (val == GLOB_NOMATCH && flags != orig_flags)
521: {
522:
523: dirs.gl_pathv = NULL;
524: flags = orig_flags;
525: oldcount = pglob->gl_pathc + pglob->gl_offs;
526: goto no_matches;
527: }
528: return val;
529: }
530: }
531:
532: if (!(flags & GLOB_APPEND))
533: {
534: pglob->gl_pathc = 0;
535: if (!(flags & GLOB_DOOFFS))
536: pglob->gl_pathv = NULL;
537: else
538: {
539: size_t i;
540: pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
541: * sizeof (char *));
542: if (pglob->gl_pathv == NULL)
543: return GLOB_NOSPACE;
544:
545: for (i = 0; i <= pglob->gl_offs; ++i)
546: pglob->gl_pathv[i] = NULL;
547: }
548: }
549:
550: oldcount = pglob->gl_pathc + pglob->gl_offs;