]>
Commit | Line | Data |
---|---|---|
28f540f4 RM |
1 | /* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. |
2 | ||
3 | This library is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU Library General Public License as | |
5 | published by the Free Software Foundation; either version 2 of the | |
6 | License, or (at your option) any later version. | |
7 | ||
8 | This library is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
11 | Library General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU Library General Public | |
14 | License along with this library; see the file COPYING.LIB. If | |
15 | not, write to the Free Software Foundation, Inc., 675 Mass Ave, | |
16 | Cambridge, MA 02139, USA. */ | |
17 | ||
18 | /* AIX requires this to be the first thing in the file. */ | |
19 | #if defined (_AIX) && !defined (__GNUC__) | |
20 | #pragma alloca | |
21 | #endif | |
22 | ||
23 | #ifdef HAVE_CONFIG_H | |
24 | #include <config.h> | |
25 | #endif | |
26 | ||
27 | #include <errno.h> | |
28 | #include <sys/types.h> | |
29 | ||
30 | ||
31 | /* Comment out all this code if we are using the GNU C Library, and are not | |
32 | actually compiling the library itself. This code is part of the GNU C | |
33 | Library, but also included in many other GNU distributions. Compiling | |
34 | and linking in this code is a waste when using the GNU C library | |
35 | (especially if it is a shared library). Rather than having every GNU | |
36 | program understand `configure --with-gnu-libc' and omit the object files, | |
37 | it is simpler to just do this in the source for each such file. */ | |
38 | ||
39 | #if defined (_LIBC) || !defined (__GNU_LIBRARY__) | |
40 | ||
41 | ||
42 | #ifdef STDC_HEADERS | |
43 | #include <stddef.h> | |
44 | #endif | |
45 | ||
46 | #ifdef HAVE_UNISTD_H | |
47 | #include <unistd.h> | |
48 | #ifndef POSIX | |
49 | #ifdef _POSIX_VERSION | |
50 | #define POSIX | |
51 | #endif | |
52 | #endif | |
53 | #endif | |
54 | ||
55 | #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS) | |
56 | extern int errno; | |
57 | #endif | |
58 | ||
59 | #ifndef NULL | |
60 | #define NULL 0 | |
61 | #endif | |
62 | ||
63 | ||
64 | #if defined (POSIX) || defined (HAVE_DIRENT_H) || defined (__GNU_LIBRARY__) | |
65 | #include <dirent.h> | |
66 | #ifndef __GNU_LIBRARY__ | |
67 | #define D_NAMLEN(d) strlen((d)->d_name) | |
68 | #else /* GNU C library. */ | |
69 | #define D_NAMLEN(d) ((d)->d_namlen) | |
70 | #endif /* Not GNU C library. */ | |
71 | #else /* Not POSIX or HAVE_DIRENT_H. */ | |
72 | #define direct dirent | |
73 | #define D_NAMLEN(d) ((d)->d_namlen) | |
74 | #ifdef HAVE_SYS_NDIR_H | |
75 | #include <sys/ndir.h> | |
76 | #endif /* HAVE_SYS_NDIR_H */ | |
77 | #ifdef HAVE_SYS_DIR_H | |
78 | #include <sys/dir.h> | |
79 | #endif /* HAVE_SYS_DIR_H */ | |
80 | #ifdef HAVE_NDIR_H | |
81 | #include <ndir.h> | |
82 | #endif /* HAVE_NDIR_H */ | |
83 | #endif /* POSIX or HAVE_DIRENT_H or __GNU_LIBRARY__. */ | |
84 | ||
85 | #if defined (POSIX) && !defined (__GNU_LIBRARY__) | |
86 | /* Posix does not require that the d_ino field be present, and some | |
87 | systems do not provide it. */ | |
88 | #define REAL_DIR_ENTRY(dp) 1 | |
89 | #else | |
90 | #define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) | |
91 | #endif /* POSIX */ | |
92 | ||
93 | #if (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__)) | |
94 | #include <stdlib.h> | |
95 | #include <string.h> | |
96 | #define ANSI_STRING | |
97 | #else /* No standard headers. */ | |
98 | ||
99 | #ifdef HAVE_STRING_H | |
100 | #include <string.h> | |
101 | #define ANSI_STRING | |
102 | #else | |
103 | #include <strings.h> | |
104 | #endif | |
105 | #ifdef HAVE_MEMORY_H | |
106 | #include <memory.h> | |
107 | #endif | |
108 | ||
109 | extern char *malloc (), *realloc (); | |
110 | extern void free (); | |
111 | ||
112 | extern void qsort (); | |
113 | extern void abort (), exit (); | |
114 | ||
115 | #endif /* Standard headers. */ | |
116 | ||
117 | #ifndef ANSI_STRING | |
118 | ||
119 | #ifndef bzero | |
120 | extern void bzero (); | |
121 | #endif | |
122 | #ifndef bcopy | |
123 | extern void bcopy (); | |
124 | #endif | |
125 | ||
126 | #define memcpy(d, s, n) bcopy ((s), (d), (n)) | |
127 | #define strrchr rindex | |
128 | /* memset is only used for zero here, but let's be paranoid. */ | |
129 | #define memset(s, better_be_zero, n) \ | |
130 | ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0))) | |
131 | #endif /* Not ANSI_STRING. */ | |
132 | ||
133 | #ifndef HAVE_STRCOLL | |
134 | #define strcoll strcmp | |
135 | #endif | |
136 | ||
137 | ||
138 | #ifndef __GNU_LIBRARY__ | |
139 | #ifdef __GNUC__ | |
140 | __inline | |
141 | #endif | |
142 | static char * | |
143 | my_realloc (p, n) | |
144 | char *p; | |
145 | unsigned int n; | |
146 | { | |
147 | /* These casts are the for sake of the broken Ultrix compiler, | |
148 | which warns of illegal pointer combinations otherwise. */ | |
149 | if (p == NULL) | |
150 | return (char *) malloc (n); | |
151 | return (char *) realloc (p, n); | |
152 | } | |
153 | #define realloc my_realloc | |
154 | #endif | |
155 | ||
156 | ||
157 | #if !defined(__alloca) && !defined(__GNU_LIBRARY__) | |
158 | ||
159 | #ifdef __GNUC__ | |
160 | #undef alloca | |
161 | #define alloca(n) __builtin_alloca (n) | |
162 | #else /* Not GCC. */ | |
163 | #if defined (sparc) || defined (HAVE_ALLOCA_H) | |
164 | #include <alloca.h> | |
165 | #else /* Not sparc or HAVE_ALLOCA_H. */ | |
166 | #ifndef _AIX | |
167 | extern char *alloca (); | |
168 | #endif /* Not _AIX. */ | |
169 | #endif /* sparc or HAVE_ALLOCA_H. */ | |
170 | #endif /* GCC. */ | |
171 | ||
172 | #define __alloca alloca | |
173 | ||
174 | #endif | |
175 | ||
176 | #ifndef STDC_HEADERS | |
177 | #undef size_t | |
178 | #define size_t unsigned int | |
179 | #endif | |
180 | ||
181 | /* Some system header files erroneously define these. | |
182 | We want our own definitions from <fnmatch.h> to take precedence. */ | |
183 | #undef FNM_PATHNAME | |
184 | #undef FNM_NOESCAPE | |
185 | #undef FNM_PERIOD | |
186 | #include <fnmatch.h> | |
187 | ||
188 | /* Some system header files erroneously define these. | |
189 | We want our own definitions from <glob.h> to take precedence. */ | |
190 | #undef GLOB_ERR | |
191 | #undef GLOB_MARK | |
192 | #undef GLOB_NOSORT | |
193 | #undef GLOB_DOOFFS | |
194 | #undef GLOB_NOCHECK | |
195 | #undef GLOB_APPEND | |
196 | #undef GLOB_NOESCAPE | |
197 | #undef GLOB_PERIOD | |
198 | #include <glob.h> | |
199 | \f | |
200 | __ptr_t (*__glob_opendir_hook) __P ((const char *directory)); | |
201 | const char *(*__glob_readdir_hook) __P ((__ptr_t stream)); | |
202 | void (*__glob_closedir_hook) __P ((__ptr_t stream)); | |
203 | ||
204 | static int glob_pattern_p __P ((const char *pattern, int quote)); | |
205 | static int glob_in_dir __P ((const char *pattern, const char *directory, | |
206 | int flags, | |
207 | int (*errfunc) __P ((const char *, int)), | |
208 | glob_t *pglob)); | |
209 | static int prefix_array __P ((const char *prefix, char **array, size_t n)); | |
210 | static int collated_compare __P ((const __ptr_t, const __ptr_t)); | |
211 | ||
212 | /* Do glob searching for PATTERN, placing results in PGLOB. | |
213 | The bits defined above may be set in FLAGS. | |
214 | If a directory cannot be opened or read and ERRFUNC is not nil, | |
215 | it is called with the pathname that caused the error, and the | |
216 | `errno' value from the failing call; if it returns non-zero | |
217 | `glob' returns GLOB_ABEND; if it returns zero, the error is ignored. | |
218 | If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. | |
219 | Otherwise, `glob' returns zero. */ | |
220 | int | |
221 | glob (pattern, flags, errfunc, pglob) | |
222 | const char *pattern; | |
223 | int flags; | |
224 | int (*errfunc) __P ((const char *, int)); | |
225 | glob_t *pglob; | |
226 | { | |
227 | const char *filename; | |
228 | char *dirname; | |
229 | size_t dirlen; | |
230 | int status; | |
231 | int oldcount; | |
232 | ||
233 | if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) | |
234 | { | |
235 | errno = EINVAL; | |
236 | return -1; | |
237 | } | |
238 | ||
239 | /* Find the filename. */ | |
240 | filename = strrchr (pattern, '/'); | |
241 | if (filename == NULL) | |
242 | { | |
243 | filename = pattern; | |
244 | dirname = (char *) "."; | |
245 | dirlen = 0; | |
246 | } | |
247 | else if (filename == pattern) | |
248 | { | |
249 | /* "/pattern". */ | |
250 | dirname = (char *) "/"; | |
251 | dirlen = 1; | |
252 | ++filename; | |
253 | } | |
254 | else | |
255 | { | |
256 | dirlen = filename - pattern; | |
257 | dirname = (char *) __alloca (dirlen + 1); | |
258 | memcpy (dirname, pattern, dirlen); | |
259 | dirname[dirlen] = '\0'; | |
260 | ++filename; | |
261 | } | |
262 | ||
263 | if (filename[0] == '\0' && dirlen > 1) | |
264 | /* "pattern/". Expand "pattern", appending slashes. */ | |
265 | { | |
266 | int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); | |
267 | if (val == 0) | |
268 | pglob->gl_flags = (pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK); | |
269 | return val; | |
270 | } | |
271 | ||
272 | if (!(flags & GLOB_APPEND)) | |
273 | { | |
274 | pglob->gl_pathc = 0; | |
275 | pglob->gl_pathv = NULL; | |
276 | } | |
277 | ||
278 | oldcount = pglob->gl_pathc; | |
279 | ||
280 | if (glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE))) | |
281 | { | |
282 | /* The directory name contains metacharacters, so we | |
283 | have to glob for the directory, and then glob for | |
284 | the pattern in each directory found. */ | |
285 | glob_t dirs; | |
286 | register int i; | |
287 | ||
288 | status = glob (dirname, | |
289 | ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE)) | | |
290 | GLOB_NOSORT), | |
291 | errfunc, &dirs); | |
292 | if (status != 0) | |
293 | return status; | |
294 | ||
295 | /* We have successfully globbed the preceding directory name. | |
296 | For each name we found, call glob_in_dir on it and FILENAME, | |
297 | appending the results to PGLOB. */ | |
298 | for (i = 0; i < dirs.gl_pathc; ++i) | |
299 | { | |
300 | int oldcount; | |
301 | ||
302 | #ifdef SHELL | |
303 | { | |
304 | /* Make globbing interruptible in the bash shell. */ | |
305 | extern int interrupt_state; | |
306 | ||
307 | if (interrupt_state) | |
308 | { | |
309 | globfree (&dirs); | |
310 | globfree (&files); | |
311 | return GLOB_ABEND; | |
312 | } | |
313 | } | |
314 | #endif /* SHELL. */ | |
315 | ||
316 | oldcount = pglob->gl_pathc; | |
317 | status = glob_in_dir (filename, dirs.gl_pathv[i], | |
318 | (flags | GLOB_APPEND) & ~GLOB_NOCHECK, | |
319 | errfunc, pglob); | |
320 | if (status == GLOB_NOMATCH) | |
321 | /* No matches in this directory. Try the next. */ | |
322 | continue; | |
323 | ||
324 | if (status != 0) | |
325 | { | |
326 | globfree (&dirs); | |
327 | globfree (pglob); | |
328 | return status; | |
329 | } | |
330 | ||
331 | /* Stick the directory on the front of each name. */ | |
332 | if (prefix_array (dirs.gl_pathv[i], | |
333 | &pglob->gl_pathv[oldcount], | |
334 | pglob->gl_pathc - oldcount)) | |
335 | { | |
336 | globfree (&dirs); | |
337 | globfree (pglob); | |
338 | return GLOB_NOSPACE; | |
339 | } | |
340 | } | |
341 | ||
342 | flags |= GLOB_MAGCHAR; | |
343 | ||
344 | if (pglob->gl_pathc == oldcount) | |
345 | /* No matches. */ | |
346 | if (flags & GLOB_NOCHECK) | |
347 | { | |
348 | size_t len = strlen (pattern) + 1; | |
349 | char *patcopy = (char *) malloc (len); | |
350 | if (patcopy == NULL) | |
351 | return GLOB_NOSPACE; | |
352 | memcpy (patcopy, pattern, len); | |
353 | ||
354 | pglob->gl_pathv | |
355 | = (char **) realloc (pglob->gl_pathv, | |
356 | (pglob->gl_pathc + | |
357 | ((flags & GLOB_DOOFFS) ? | |
358 | pglob->gl_offs : 0) + | |
359 | 1 + 1) * | |
360 | sizeof (char *)); | |
361 | if (pglob->gl_pathv == NULL) | |
362 | { | |
363 | free (patcopy); | |
364 | return GLOB_NOSPACE; | |
365 | } | |
366 | ||
367 | if (flags & GLOB_DOOFFS) | |
368 | while (pglob->gl_pathc < pglob->gl_offs) | |
369 | pglob->gl_pathv[pglob->gl_pathc++] = NULL; | |
370 | ||
371 | pglob->gl_pathv[pglob->gl_pathc++] = patcopy; | |
372 | pglob->gl_pathv[pglob->gl_pathc] = NULL; | |
373 | pglob->gl_flags = flags; | |
374 | } | |
375 | else | |
376 | return GLOB_NOMATCH; | |
377 | } | |
378 | else | |
379 | { | |
380 | status = glob_in_dir (filename, dirname, flags, errfunc, pglob); | |
381 | if (status != 0) | |
382 | return status; | |
383 | ||
384 | if (dirlen > 0) | |
385 | { | |
386 | /* Stick the directory on the front of each name. */ | |
387 | if (prefix_array (dirname, | |
388 | &pglob->gl_pathv[oldcount], | |
389 | pglob->gl_pathc - oldcount)) | |
390 | { | |
391 | globfree (pglob); | |
392 | return GLOB_NOSPACE; | |
393 | } | |
394 | } | |
395 | } | |
396 | ||
397 | if (!(flags & GLOB_NOSORT)) | |
398 | /* Sort the vector. */ | |
399 | qsort ((__ptr_t) & pglob->gl_pathv[oldcount], | |
400 | pglob->gl_pathc - oldcount, | |
401 | sizeof (char *), collated_compare); | |
402 | ||
403 | return 0; | |
404 | } | |
405 | ||
406 | ||
407 | /* Free storage allocated in PGLOB by a previous `glob' call. */ | |
408 | void | |
409 | globfree (pglob) | |
410 | register glob_t *pglob; | |
411 | { | |
412 | if (pglob->gl_pathv != NULL) | |
413 | { | |
414 | register int i; | |
415 | for (i = 0; i < pglob->gl_pathc; ++i) | |
416 | if (pglob->gl_pathv[i] != NULL) | |
417 | free ((__ptr_t) pglob->gl_pathv[i]); | |
418 | free ((__ptr_t) pglob->gl_pathv); | |
419 | } | |
420 | } | |
421 | ||
422 | ||
423 | /* Do a collated comparison of A and B. */ | |
424 | static int | |
425 | collated_compare (a, b) | |
426 | const __ptr_t a; | |
427 | const __ptr_t b; | |
428 | { | |
429 | const char *const s1 = *(const char *const * const) a; | |
430 | const char *const s2 = *(const char *const * const) b; | |
431 | ||
432 | if (s1 == s2) | |
433 | return 0; | |
434 | if (s1 == NULL) | |
435 | return 1; | |
436 | if (s2 == NULL) | |
437 | return -1; | |
438 | return strcoll (s1, s2); | |
439 | } | |
440 | ||
441 | ||
442 | /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's | |
443 | elements in place. Return nonzero if out of memory, zero if successful. | |
444 | A slash is inserted between DIRNAME and each elt of ARRAY, | |
445 | unless DIRNAME is just "/". Each old element of ARRAY is freed. */ | |
446 | static int | |
447 | prefix_array (dirname, array, n) | |
448 | const char *dirname; | |
449 | char **array; | |
450 | size_t n; | |
451 | { | |
452 | register size_t i; | |
453 | size_t dirlen = strlen (dirname); | |
454 | ||
455 | if (dirlen == 1 && dirname[0] == '/') | |
456 | /* DIRNAME is just "/", so normal prepending would get us "//foo". | |
457 | We want "/foo" instead, so don't prepend any chars from DIRNAME. */ | |
458 | dirlen = 0; | |
459 | ||
460 | for (i = 0; i < n; ++i) | |
461 | { | |
462 | size_t eltlen = strlen (array[i]) + 1; | |
463 | char *new = (char *) malloc (dirlen + 1 + eltlen); | |
464 | if (new == NULL) | |
465 | { | |
466 | while (i > 0) | |
467 | free ((__ptr_t) array[--i]); | |
468 | return 1; | |
469 | } | |
470 | ||
471 | memcpy (new, dirname, dirlen); | |
472 | new[dirlen] = '/'; | |
473 | memcpy (&new[dirlen + 1], array[i], eltlen); | |
474 | free ((__ptr_t) array[i]); | |
475 | array[i] = new; | |
476 | } | |
477 | ||
478 | return 0; | |
479 | } | |
480 | ||
481 | ||
482 | /* Return nonzero if PATTERN contains any metacharacters. | |
483 | Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ | |
484 | static int | |
485 | glob_pattern_p (pattern, quote) | |
486 | const char *pattern; | |
487 | int quote; | |
488 | { | |
489 | register const char *p; | |
490 | int open = 0; | |
491 | ||
492 | for (p = pattern; *p != '\0'; ++p) | |
493 | switch (*p) | |
494 | { | |
495 | case '?': | |
496 | case '*': | |
497 | return 1; | |
498 | ||
499 | case '\\': | |
500 | if (quote) | |
501 | ++p; | |
502 | break; | |
503 | ||
504 | case '[': | |
505 | open = 1; | |
506 | break; | |
507 | ||
508 | case ']': | |
509 | if (open) | |
510 | return 1; | |
511 | break; | |
512 | } | |
513 | ||
514 | return 0; | |
515 | } | |
516 | ||
517 | ||
518 | /* Like `glob', but PATTERN is a final pathname component, | |
519 | and matches are searched for in DIRECTORY. | |
520 | The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done. | |
521 | The GLOB_APPEND flag is assumed to be set (always appends). */ | |
522 | static int | |
523 | glob_in_dir (pattern, directory, flags, errfunc, pglob) | |
524 | const char *pattern; | |
525 | const char *directory; | |
526 | int flags; | |
527 | int (*errfunc) __P ((const char *, int)); | |
528 | glob_t *pglob; | |
529 | { | |
530 | __ptr_t stream; | |
531 | ||
532 | struct globlink | |
533 | { | |
534 | struct globlink *next; | |
535 | char *name; | |
536 | }; | |
537 | struct globlink *names = NULL; | |
538 | size_t nfound = 0; | |
539 | ||
540 | if (!glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE))) | |
541 | { | |
542 | stream = NULL; | |
543 | flags |= GLOB_NOCHECK; | |
544 | } | |
545 | else | |
546 | { | |
547 | flags |= GLOB_MAGCHAR; | |
548 | ||
549 | stream = (__glob_opendir_hook ? (*__glob_opendir_hook) (directory) | |
550 | : (__ptr_t) opendir (directory)); | |
551 | if (stream == NULL) | |
552 | { | |
553 | if ((errfunc != NULL && (*errfunc) (directory, errno)) || | |
554 | (flags & GLOB_ERR)) | |
555 | return GLOB_ABEND; | |
556 | } | |
557 | else | |
558 | while (1) | |
559 | { | |
560 | const char *name; | |
561 | size_t len; | |
562 | ||
563 | if (__glob_readdir_hook) | |
564 | { | |
565 | name = (*__glob_readdir_hook) (stream); | |
566 | if (name == NULL) | |
567 | break; | |
568 | len = 0; | |
569 | } | |
570 | else | |
571 | { | |
572 | struct dirent *d = readdir ((DIR *) stream); | |
573 | if (d == NULL) | |
574 | break; | |
575 | if (! REAL_DIR_ENTRY (d)) | |
576 | continue; | |
577 | name = d->d_name; | |
578 | #ifdef HAVE_D_NAMLEN | |
579 | len = d->d_namlen; | |
580 | #else | |
581 | len = 0; | |
582 | #endif | |
583 | } | |
584 | ||
585 | if (fnmatch (pattern, name, | |
586 | (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) | | |
587 | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)) == 0) | |
588 | { | |
589 | struct globlink *new | |
590 | = (struct globlink *) __alloca (sizeof (struct globlink)); | |
591 | if (len == 0) | |
592 | len = strlen (name); | |
593 | new->name | |
594 | = (char *) malloc (len + ((flags & GLOB_MARK) ? 1 : 0) + 1); | |
595 | if (new->name == NULL) | |
596 | goto memory_error; | |
597 | memcpy ((__ptr_t) new->name, name, len); | |
598 | if (flags & GLOB_MARK) | |
599 | new->name[len++] = '/'; | |
600 | new->name[len] = '\0'; | |
601 | new->next = names; | |
602 | names = new; | |
603 | ++nfound; | |
604 | } | |
605 | } | |
606 | } | |
607 | ||
608 | if (nfound == 0 && (flags & GLOB_NOCHECK)) | |
609 | { | |
610 | size_t len = strlen (pattern); | |
611 | nfound = 1; | |
612 | names = (struct globlink *) __alloca (sizeof (struct globlink)); | |
613 | names->next = NULL; | |
614 | names->name = (char *) malloc (len + ((flags & GLOB_MARK) ? 1 : 0) + 1); | |
615 | if (names->name == NULL) | |
616 | goto memory_error; | |
617 | memcpy (names->name, pattern, len); | |
618 | if (flags & GLOB_MARK) | |
619 | names->name[len++] = '/'; | |
620 | names->name[len] = '\0'; | |
621 | } | |
622 | ||
623 | pglob->gl_pathv | |
624 | = (char **) realloc (pglob->gl_pathv, | |
625 | (pglob->gl_pathc + | |
626 | ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + | |
627 | nfound + 1) * | |
628 | sizeof (char *)); | |
629 | if (pglob->gl_pathv == NULL) | |
630 | goto memory_error; | |
631 | ||
632 | if (flags & GLOB_DOOFFS) | |
633 | while (pglob->gl_pathc < pglob->gl_offs) | |
634 | pglob->gl_pathv[pglob->gl_pathc++] = NULL; | |
635 | ||
636 | for (; names != NULL; names = names->next) | |
637 | pglob->gl_pathv[pglob->gl_pathc++] = names->name; | |
638 | pglob->gl_pathv[pglob->gl_pathc] = NULL; | |
639 | ||
640 | pglob->gl_flags = flags; | |
641 | ||
642 | if (stream != NULL) | |
643 | { | |
644 | int save = errno; | |
645 | if (__glob_closedir_hook) | |
646 | (*__glob_closedir_hook) (stream); | |
647 | else | |
648 | (void) closedir ((DIR *) stream); | |
649 | errno = save; | |
650 | } | |
651 | return nfound == 0 ? GLOB_NOMATCH : 0; | |
652 | ||
653 | memory_error: | |
654 | { | |
655 | int save = errno; | |
656 | if (__glob_closedir_hook) | |
657 | (*__glob_closedir_hook) (stream); | |
658 | else | |
659 | (void) closedir ((DIR *) stream); | |
660 | errno = save; | |
661 | } | |
662 | while (names != NULL) | |
663 | { | |
664 | if (names->name != NULL) | |
665 | free ((__ptr_t) names->name); | |
666 | names = names->next; | |
667 | } | |
668 | return GLOB_NOSPACE; | |
669 | } | |
670 | ||
671 | #endif /* _LIBC or not __GNU_LIBRARY__. */ |