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