00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #if defined _AIX && !defined __GNUC__
00043 #pragma alloca
00044 #endif
00045
00046
00047
00048 # include "system.h"
00049
00050
00051 # include <stddef.h>
00052
00053 # include <assert.h>
00054
00055 #undef __alloca
00056 #define __alloca alloca
00057 #define __stat stat
00058 #define NAMLEN(_d) NLENGTH(_d)
00059
00060
00061 # if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
00062 # define CONVERT_D_NAMLEN(d64, d32)
00063 # else
00064 # define CONVERT_D_NAMLEN(d64, d32) \
00065 (d64)->d_namlen = (d32)->d_namlen;
00066 # endif
00067
00068 # if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
00069 # define CONVERT_D_INO(d64, d32)
00070 # else
00071 # define CONVERT_D_INO(d64, d32) \
00072 (d64)->d_ino = (d32)->d_ino;
00073 # endif
00074
00075 # ifdef _DIRENT_HAVE_D_TYPE
00076 # define CONVERT_D_TYPE(d64, d32) \
00077 (d64)->d_type = (d32)->d_type;
00078 # else
00079 # define CONVERT_D_TYPE(d64, d32)
00080 # endif
00081
00082 # define CONVERT_DIRENT_DIRENT64(d64, d32) \
00083 memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \
00084 CONVERT_D_NAMLEN (d64, d32) \
00085 CONVERT_D_INO (d64, d32) \
00086 CONVERT_D_TYPE (d64, d32)
00087
00088 #if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
00089
00090
00091 # define REAL_DIR_ENTRY(dp) 1
00092 #else
00093 # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
00094 #endif
00095
00096 #include <errno.h>
00097 #ifndef __set_errno
00098 # define __set_errno(val) errno = (val)
00099 #endif
00100
00101
00102
00103
00104 #define GLOB_INTERFACE_VERSION 1
00105
00106
00107 static inline const char *next_brace_sub __P ((const char *begin))
00108 ;
00109 static int glob_in_dir __P ((const char *pattern, const char *directory,
00110 int flags,
00111 int (*errfunc) (const char *, int),
00112 glob_t *pglob))
00113
00114 ;
00115 static int prefix_array __P ((const char *prefix, char **array, size_t n))
00116 ;
00117 static int collated_compare __P ((const __ptr_t, const __ptr_t))
00118 ;
00119
00120
00121
00122
00123 static inline const char *
00124 next_brace_sub (const char *begin)
00125 {
00126 unsigned int depth = 0;
00127 const char *cp = begin;
00128
00129 while (1)
00130 {
00131 if (depth == 0)
00132 {
00133 if (*cp != ',' && *cp != '}' && *cp != '\0')
00134 {
00135 if (*cp == '{')
00136 ++depth;
00137 ++cp;
00138 continue;
00139 }
00140 }
00141 else
00142 {
00143 while (*cp != '\0' && (*cp != '}' || depth > 0))
00144 {
00145 if (*cp == '}')
00146 --depth;
00147 ++cp;
00148 }
00149 if (*cp == '\0')
00150
00151 return NULL;
00152
00153 continue;
00154 }
00155 break;
00156 }
00157
00158 return cp;
00159 }
00160
00161 static int __glob_pattern_p (const char *pattern, int quote);
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 int
00172 glob (const char *pattern, int flags,
00173 int (*errfunc) __P ((const char *, int)), glob_t *pglob)
00174 {
00175 const char *filename;
00176 const char *dirname;
00177 size_t dirlen;
00178 int status;
00179 int oldcount;
00180
00181 if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
00182 {
00183 __set_errno (EINVAL);
00184 return -1;
00185 }
00186
00187 if (flags & GLOB_BRACE)
00188 {
00189 const char *begin = strchr (pattern, '{');
00190 if (begin != NULL)
00191 {
00192
00193
00194 int firstc;
00195 char *alt_start;
00196 const char *p;
00197 const char *next;
00198 const char *rest;
00199 size_t rest_len;
00200 #ifdef __GNUC__
00201 char onealt[strlen (pattern) - 1];
00202 #else
00203 char *onealt = (char *) xmalloc (strlen (pattern) - 1);
00204 if (onealt == NULL)
00205 {
00206 if (!(flags & GLOB_APPEND))
00207 globfree (pglob);
00208 return GLOB_NOSPACE;
00209 }
00210 #endif
00211
00212
00213 #ifdef HAVE_MEMPCPY
00214 alt_start = mempcpy (onealt, pattern, begin - pattern);
00215 #else
00216 memcpy (onealt, pattern, begin - pattern);
00217 alt_start = &onealt[begin - pattern];
00218 #endif
00219
00220
00221
00222 next = next_brace_sub (begin + 1);
00223 if (next == NULL)
00224 {
00225
00226 #ifndef __GNUC__
00227 free (onealt);
00228 #endif
00229 return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
00230 }
00231
00232
00233 rest = next;
00234 while (*rest != '}')
00235 {
00236 rest = next_brace_sub (rest + 1);
00237 if (rest == NULL)
00238 {
00239
00240 #ifndef __GNUC__
00241 free (onealt);
00242 #endif
00243 return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
00244 }
00245 }
00246
00247
00248 rest_len = strlen (++rest) + 1;
00249
00250
00251
00252
00253
00254
00255
00256 if (!(flags & GLOB_APPEND))
00257 {
00258
00259
00260 pglob->gl_pathc = 0;
00261 pglob->gl_pathv = NULL;
00262 }
00263 firstc = pglob->gl_pathc;
00264
00265 p = begin + 1;
00266 while (1)
00267 {
00268 int result;
00269
00270
00271 #ifdef HAVE_MEMPCPY
00272 mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
00273 #else
00274 memcpy (alt_start, p, next - p);
00275 memcpy (&alt_start[next - p], rest, rest_len);
00276 #endif
00277
00278 result = glob (onealt,
00279 ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC))
00280 | GLOB_APPEND), errfunc, pglob);
00281
00282
00283 if (result && result != GLOB_NOMATCH)
00284 {
00285 #ifndef __GNUC__
00286 free (onealt);
00287 #endif
00288 if (!(flags & GLOB_APPEND))
00289 globfree (pglob);
00290 return result;
00291 }
00292
00293 if (*next == '}')
00294
00295 break;
00296
00297 p = next + 1;
00298 next = next_brace_sub (p);
00299 assert (next != NULL);
00300 }
00301
00302 #ifndef __GNUC__
00303 free (onealt);
00304 #endif
00305
00306 if ((int)pglob->gl_pathc != firstc)
00307
00308 return 0;
00309 else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
00310 return GLOB_NOMATCH;
00311 }
00312 }
00313
00314
00315 filename = strrchr (pattern, '/');
00316 #if defined __MSDOS__ || defined WINDOWS32
00317
00318
00319
00320
00321 if (filename == NULL)
00322 filename = strchr (pattern, ':');
00323 #endif
00324 if (filename == NULL)
00325 {
00326
00327
00328 if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
00329 {
00330 dirname = pattern;
00331 dirlen = strlen (pattern);
00332
00333
00334
00335
00336 filename = NULL;
00337 }
00338 else
00339 {
00340 filename = pattern;
00341 #ifdef _AMIGA
00342 dirname = "";
00343 #else
00344 dirname = ".";
00345 #endif
00346 dirlen = 0;
00347 }
00348 }
00349 else if (filename == pattern)
00350 {
00351
00352 dirname = "/";
00353 dirlen = 1;
00354 ++filename;
00355 }
00356 else
00357 {
00358 char *newp;
00359 dirlen = filename - pattern;
00360 #if defined __MSDOS__ || defined WINDOWS32
00361 if (*filename == ':'
00362 || (filename > pattern + 1 && filename[-1] == ':'))
00363 {
00364 char *drive_spec;
00365
00366 ++dirlen;
00367 drive_spec = (char *) __alloca (dirlen + 1);
00368 #ifdef HAVE_MEMPCPY
00369 *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
00370 #else
00371 memcpy (drive_spec, pattern, dirlen);
00372 drive_spec[dirlen] = '\0';
00373 #endif
00374
00375
00376 if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
00377 return GLOB_NOMATCH;
00378
00379
00380
00381 }
00382 #endif
00383 newp = (char *) __alloca (dirlen + 1);
00384 #ifdef HAVE_MEMPCPY
00385 *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
00386 #else
00387 memcpy (newp, pattern, dirlen);
00388 newp[dirlen] = '\0';
00389 #endif
00390 dirname = newp;
00391 ++filename;
00392
00393 if (filename[0] == '\0'
00394 #if defined __MSDOS__ || defined WINDOWS32
00395 && dirname[dirlen - 1] != ':'
00396 && (dirlen < 3 || dirname[dirlen - 2] != ':'
00397 || dirname[dirlen - 1] != '/')
00398 #endif
00399 && dirlen > 1)
00400
00401 {
00402 int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
00403 if (val == 0)
00404 pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
00405 | (flags & GLOB_MARK));
00406 return val;
00407 }
00408 }
00409
00410 if (!(flags & GLOB_APPEND))
00411 {
00412 pglob->gl_pathc = 0;
00413 pglob->gl_pathv = NULL;
00414 }
00415
00416 oldcount = pglob->gl_pathc;
00417
00418 #ifndef VMS
00419 if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
00420 {
00421 if (dirname[1] == '\0' || dirname[1] == '/')
00422 {
00423
00424 const char *home_dir = getenv ("HOME");
00425 # ifdef _AMIGA
00426 if (home_dir == NULL || home_dir[0] == '\0')
00427 home_dir = "SYS:";
00428 # else
00429 # ifdef WINDOWS32
00430 if (home_dir == NULL || home_dir[0] == '\0')
00431 home_dir = "c:/users/default";
00432 # else
00433 if (home_dir == NULL || home_dir[0] == '\0')
00434 {
00435 int success;
00436 char *name;
00437 # if defined HAVE_GETLOGIN_R || defined _LIBC
00438 size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;
00439
00440 if (buflen == 0)
00441
00442
00443 buflen = 20;
00444 name = (char *) __alloca (buflen);
00445
00446 success = getlogin_r (name, buflen) >= 0;
00447 # else
00448 success = (name = getlogin ()) != NULL;
00449 # endif
00450 if (success)
00451 {
00452 struct passwd *p;
00453 # if defined HAVE_GETPWNAM_R || defined _LIBC
00454 size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
00455 char *pwtmpbuf;
00456 struct passwd pwbuf;
00457 int save = errno;
00458
00459 if (pwbuflen == -1)
00460
00461
00462 pwbuflen = 1024;
00463 pwtmpbuf = (char *) __alloca (pwbuflen);
00464
00465 while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
00466 != 0)
00467 {
00468 if (errno != ERANGE)
00469 {
00470 p = NULL;
00471 break;
00472 }
00473 pwbuflen *= 2;
00474 pwtmpbuf = (char *) __alloca (pwbuflen);
00475 __set_errno (save);
00476 }
00477 # else
00478 p = getpwnam (name);
00479 # endif
00480 if (p != NULL)
00481 home_dir = p->pw_dir;
00482 }
00483 }
00484 if (home_dir == NULL || home_dir[0] == '\0')
00485 {
00486 if (flags & GLOB_TILDE_CHECK)
00487 return GLOB_NOMATCH;
00488 else
00489 home_dir = "~";
00490 }
00491 # endif
00492 # endif
00493
00494 if (dirname[1] == '\0')
00495 dirname = home_dir;
00496 else
00497 {
00498 char *newp;
00499 size_t home_len = strlen (home_dir);
00500 newp = (char *) __alloca (home_len + dirlen);
00501 # ifdef HAVE_MEMPCPY
00502 mempcpy (mempcpy (newp, home_dir, home_len),
00503 &dirname[1], dirlen);
00504 # else
00505 memcpy (newp, home_dir, home_len);
00506 memcpy (&newp[home_len], &dirname[1], dirlen);
00507 # endif
00508 dirname = newp;
00509 }
00510 }
00511 # if !defined _AMIGA && !defined WINDOWS32
00512 else
00513 {
00514 char *end_name = strchr (dirname, '/');
00515 const char *user_name;
00516 const char *home_dir;
00517
00518 if (end_name == NULL)
00519 user_name = dirname + 1;
00520 else
00521 {
00522 char *newp;
00523 newp = (char *) __alloca (end_name - dirname);
00524 # ifdef HAVE_MEMPCPY
00525 *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
00526 = '\0';
00527 # else
00528 memcpy (newp, dirname + 1, end_name - dirname);
00529 newp[end_name - dirname - 1] = '\0';
00530 # endif
00531 user_name = newp;
00532 }
00533
00534
00535 {
00536 struct passwd *p;
00537 # if defined HAVE_GETPWNAM_R || defined _LIBC
00538 size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
00539 char *pwtmpbuf;
00540 struct passwd pwbuf;
00541 int save = errno;
00542
00543 if (buflen == -1)
00544
00545
00546 buflen = 1024;
00547 pwtmpbuf = (char *) __alloca (buflen);
00548
00549 while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
00550 {
00551 if (errno != ERANGE)
00552 {
00553 p = NULL;
00554 break;
00555 }
00556 buflen *= 2;
00557 pwtmpbuf = __alloca (buflen);
00558 __set_errno (save);
00559 }
00560 # else
00561 p = getpwnam (user_name);
00562 # endif
00563 if (p != NULL)
00564 home_dir = p->pw_dir;
00565 else
00566 home_dir = NULL;
00567 }
00568
00569 if (home_dir != NULL)
00570 {
00571 char *newp;
00572 size_t home_len = strlen (home_dir);
00573 size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
00574 newp = (char *) __alloca (home_len + rest_len + 1);
00575 # ifdef HAVE_MEMPCPY
00576 *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
00577 end_name, rest_len)) = '\0';
00578 # else
00579 memcpy (newp, home_dir, home_len);
00580 memcpy (&newp[home_len], end_name, rest_len);
00581 newp[home_len + rest_len] = '\0';
00582 # endif
00583 dirname = newp;
00584 }
00585 else
00586 if (flags & GLOB_TILDE_CHECK)
00587
00588
00589 return GLOB_NOMATCH;
00590 }
00591 # endif
00592 }
00593 #endif
00594
00595
00596
00597 if (filename == NULL)
00598 {
00599 struct stat st;
00600
00601
00602 if ((flags & GLOB_NOCHECK)
00603 || (((flags & GLOB_ALTDIRFUNC)
00604 ? (*pglob->gl_stat) (dirname, &st)
00605 : __stat (dirname, &st)) == 0
00606 && S_ISDIR (st.st_mode)))
00607 {
00608 pglob->gl_pathv
00609 = (char **) xrealloc (pglob->gl_pathv,
00610 (pglob->gl_pathc +
00611 ((flags & GLOB_DOOFFS) ?
00612 pglob->gl_offs : 0) +
00613 1 + 1) *
00614 sizeof (char *));
00615 if (pglob->gl_pathv == NULL)
00616 return GLOB_NOSPACE;
00617
00618 if (flags & GLOB_DOOFFS)
00619 while (pglob->gl_pathc < pglob->gl_offs)
00620 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
00621
00622 #if defined HAVE_STRDUP || defined _LIBC
00623 pglob->gl_pathv[pglob->gl_pathc] = xstrdup (dirname);
00624 #else
00625 {
00626 size_t len = strlen (dirname) + 1;
00627 char *dircopy = xmalloc (len);
00628 if (dircopy != NULL)
00629 pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname,
00630 len);
00631 }
00632 #endif
00633 if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
00634 {
00635 free (pglob->gl_pathv);
00636 return GLOB_NOSPACE;
00637 }
00638 pglob->gl_pathv[++pglob->gl_pathc] = NULL;
00639 pglob->gl_flags = flags;
00640
00641 return 0;
00642 }
00643
00644
00645 return GLOB_NOMATCH;
00646 }
00647
00648 if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
00649 {
00650
00651
00652
00653 glob_t dirs;
00654 register int i;
00655
00656 if ((flags & GLOB_ALTDIRFUNC) != 0)
00657 {
00658
00659
00660 dirs.gl_opendir = pglob->gl_opendir;
00661 dirs.gl_readdir = pglob->gl_readdir;
00662 dirs.gl_closedir = pglob->gl_closedir;
00663 dirs.gl_stat = pglob->gl_stat;
00664 dirs.gl_lstat = pglob->gl_lstat;
00665 }
00666
00667 status = glob (dirname,
00668 ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE
00669 | GLOB_ALTDIRFUNC))
00670 | GLOB_NOSORT | GLOB_ONLYDIR),
00671 errfunc, &dirs);
00672 if (status != 0)
00673 return status;
00674
00675
00676
00677
00678 for (i = 0; i < (int)dirs.gl_pathc; ++i)
00679 {
00680 int old_pathc;
00681
00682 #ifdef SHELL
00683 {
00684
00685 extern int interrupt_state;
00686
00687 if (interrupt_state)
00688 {
00689 globfree (&dirs);
00690 globfree (&files);
00691 return GLOB_ABORTED;
00692 }
00693 }
00694 #endif
00695
00696 old_pathc = pglob->gl_pathc;
00697 status = glob_in_dir (filename, dirs.gl_pathv[i],
00698 ((flags | GLOB_APPEND)
00699 & ~(GLOB_NOCHECK | GLOB_ERR)),
00700 errfunc, pglob);
00701 if (status == GLOB_NOMATCH)
00702
00703 continue;
00704
00705 if (status != 0)
00706 {
00707 globfree (&dirs);
00708 globfree (pglob);
00709 return status;
00710 }
00711
00712
00713 if (prefix_array (dirs.gl_pathv[i],
00714 &pglob->gl_pathv[old_pathc],
00715 pglob->gl_pathc - old_pathc))
00716 {
00717 globfree (&dirs);
00718 globfree (pglob);
00719 return GLOB_NOSPACE;
00720 }
00721 }
00722
00723 flags |= GLOB_MAGCHAR;
00724
00725
00726
00727
00728
00729 if ((int)pglob->gl_pathc == oldcount)
00730 {
00731
00732 if (flags & GLOB_NOCHECK)
00733 {
00734 size_t filename_len = strlen (filename) + 1;
00735 char **new_pathv;
00736 struct stat st;
00737
00738
00739 pglob->gl_pathv
00740 = (char **) xrealloc (pglob->gl_pathv,
00741 (pglob->gl_pathc +
00742 ((flags & GLOB_DOOFFS) ?
00743 pglob->gl_offs : 0) +
00744 dirs.gl_pathc + 1) *
00745 sizeof (char *));
00746 if (pglob->gl_pathv == NULL)
00747 {
00748 globfree (&dirs);
00749 return GLOB_NOSPACE;
00750 }
00751
00752 if (flags & GLOB_DOOFFS)
00753 while (pglob->gl_pathc < pglob->gl_offs)
00754 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
00755
00756 for (i = 0; i < (int)dirs.gl_pathc; ++i)
00757 {
00758 const char *dir = dirs.gl_pathv[i];
00759 size_t dir_len = strlen (dir);
00760
00761
00762 if (((flags & GLOB_ALTDIRFUNC)
00763 ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0
00764 || !S_ISDIR (st.st_mode))
00765
00766 continue;
00767
00768 pglob->gl_pathv[pglob->gl_pathc] = xmalloc (dir_len + 1
00769 + filename_len);
00770 if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
00771 {
00772 globfree (&dirs);
00773 globfree (pglob);
00774 return GLOB_NOSPACE;
00775 }
00776
00777 #ifdef HAVE_MEMPCPY
00778 mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc],
00779 dir, dir_len),
00780 "/", 1),
00781 filename, filename_len);
00782 #else
00783 memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len);
00784 pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/';
00785 memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1],
00786 filename, filename_len);
00787 #endif
00788 ++pglob->gl_pathc;
00789 }
00790
00791 pglob->gl_pathv[pglob->gl_pathc] = NULL;
00792 pglob->gl_flags = flags;
00793
00794
00795 new_pathv = (char **) xrealloc (pglob->gl_pathv,
00796 ((pglob->gl_pathc + 1)
00797 * sizeof (char *)));
00798 if (new_pathv != NULL)
00799 pglob->gl_pathv = new_pathv;
00800 }
00801 else
00802 return GLOB_NOMATCH;
00803 }
00804
00805 globfree (&dirs);
00806 }
00807 else
00808 {
00809 status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
00810 if (status != 0)
00811 return status;
00812
00813 if (dirlen > 0)
00814 {
00815
00816 int ignore = oldcount;
00817
00818 if ((flags & GLOB_DOOFFS) && ignore < (int)pglob->gl_offs)
00819 ignore = pglob->gl_offs;
00820
00821 if (prefix_array (dirname,
00822 &pglob->gl_pathv[ignore],
00823 pglob->gl_pathc - ignore))
00824 {
00825 globfree (pglob);
00826 return GLOB_NOSPACE;
00827 }
00828 }
00829 }
00830
00831 if (flags & GLOB_MARK)
00832 {
00833
00834 int i;
00835 struct stat st;
00836 for (i = oldcount; i < (int)pglob->gl_pathc; ++i)
00837 if (((flags & GLOB_ALTDIRFUNC)
00838 ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st)
00839 : __stat (pglob->gl_pathv[i], &st)) == 0
00840 && S_ISDIR (st.st_mode))
00841 {
00842 size_t len = strlen (pglob->gl_pathv[i]) + 2;
00843 char *new = xrealloc (pglob->gl_pathv[i], len);
00844 if (new == NULL)
00845 {
00846 globfree (pglob);
00847 return GLOB_NOSPACE;
00848 }
00849 strcpy (&new[len - 2], "/");
00850 pglob->gl_pathv[i] = new;
00851 }
00852 }
00853
00854 if (!(flags & GLOB_NOSORT))
00855 {
00856
00857 int non_sort = oldcount;
00858
00859 if ((flags & GLOB_DOOFFS) && (int)pglob->gl_offs > oldcount)
00860 non_sort = pglob->gl_offs;
00861
00862 qsort ((__ptr_t) &pglob->gl_pathv[non_sort],
00863 pglob->gl_pathc - non_sort,
00864 sizeof (char *), collated_compare);
00865 }
00866
00867 return 0;
00868 }
00869
00870
00871
00872 void
00873 globfree (glob_t *pglob)
00874 {
00875 if (pglob->gl_pathv != NULL)
00876 {
00877 register int i;
00878 for (i = 0; i < (int)pglob->gl_pathc; ++i)
00879 if (pglob->gl_pathv[i] != NULL)
00880 free ((__ptr_t) pglob->gl_pathv[i]);
00881 free ((__ptr_t) pglob->gl_pathv);
00882 }
00883 }
00884
00885
00886
00887 static int
00888 collated_compare (const __ptr_t a, const __ptr_t b)
00889 {
00890 const char *const s1 = *(const char *const * const) a;
00891 const char *const s2 = *(const char *const * const) b;
00892
00893 if (s1 == s2)
00894 return 0;
00895 if (s1 == NULL)
00896 return 1;
00897 if (s2 == NULL)
00898 return -1;
00899 return strcoll (s1, s2);
00900 }
00901
00902
00903
00904
00905
00906
00907 static int
00908 prefix_array (const char *dirname, char **array, size_t n)
00909 {
00910 register size_t i;
00911 size_t dirlen = strlen (dirname);
00912 #if defined __MSDOS__ || defined WINDOWS32
00913 int sep_char = '/';
00914 # define DIRSEP_CHAR sep_char
00915 #else
00916 # define DIRSEP_CHAR '/'
00917 #endif
00918
00919 if (dirlen == 1 && dirname[0] == '/')
00920
00921
00922 dirlen = 0;
00923 #if defined __MSDOS__ || defined WINDOWS32
00924 else if (dirlen > 1)
00925 {
00926 if (dirname[dirlen - 1] == '/')
00927
00928 --dirlen;
00929 else if (dirname[dirlen - 1] == ':')
00930 {
00931
00932 --dirlen;
00933 sep_char = ':';
00934 }
00935 }
00936 #endif
00937
00938 for (i = 0; i < n; ++i)
00939 {
00940 size_t eltlen = strlen (array[i]) + 1;
00941 char *new = (char *) xmalloc (dirlen + 1 + eltlen);
00942 if (new == NULL)
00943 {
00944 while (i > 0)
00945 free ((__ptr_t) array[--i]);
00946 return 1;
00947 }
00948
00949 #ifdef HAVE_MEMPCPY
00950 {
00951 char *endp = (char *) mempcpy (new, dirname, dirlen);
00952 *endp++ = DIRSEP_CHAR;
00953 mempcpy (endp, array[i], eltlen);
00954 }
00955 #else
00956 memcpy (new, dirname, dirlen);
00957 new[dirlen] = DIRSEP_CHAR;
00958 memcpy (&new[dirlen + 1], array[i], eltlen);
00959 #endif
00960 free ((__ptr_t) array[i]);
00961 array[i] = new;
00962 }
00963
00964 return 0;
00965 }
00966
00967
00968
00969 #if !defined _LIBC || !defined NO_GLOB_PATTERN_P
00970
00971
00972 static int
00973 __glob_pattern_p (const char *pattern, int quote)
00974 {
00975 register const char *p;
00976 int open = 0;
00977
00978 for (p = pattern; *p != '\0'; ++p)
00979 switch (*p)
00980 {
00981 case '?':
00982 case '*':
00983 return 1;
00984
00985 case '\\':
00986 if (quote && p[1] != '\0')
00987 ++p;
00988 break;
00989
00990 case '[':
00991 open = 1;
00992 break;
00993
00994 case ']':
00995 if (open)
00996 return 1;
00997 break;
00998 }
00999
01000 return 0;
01001 }
01002 # ifdef _LIBC
01003 weak_alias (__glob_pattern_p, glob_pattern_p)
01004 # endif
01005 #endif
01006
01007
01008
01009
01010
01011
01012 static int
01013 glob_in_dir (const char *pattern, const char *directory, int flags,
01014 int (*errfunc) __P ((const char *, int)), glob_t *pglob)
01015 {
01016 __ptr_t stream = NULL;
01017
01018 struct globlink
01019 {
01020 struct globlink *next;
01021 char *name;
01022 };
01023 struct globlink *names = NULL;
01024 size_t nfound;
01025 int meta;
01026 int save;
01027
01028 meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
01029 if (meta == 0)
01030 {
01031 if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))
01032
01033
01034
01035 flags |= GLOB_NOCHECK;
01036 else
01037 {
01038
01039
01040 struct stat st;
01041 size_t patlen = strlen (pattern);
01042 size_t dirlen = strlen (directory);
01043 char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
01044
01045 # ifdef HAVE_MEMPCPY
01046 mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
01047 "/", 1),
01048 pattern, patlen + 1);
01049 # else
01050 memcpy (fullname, directory, dirlen);
01051 fullname[dirlen] = '/';
01052 memcpy (&fullname[dirlen + 1], pattern, patlen + 1);
01053 # endif
01054 if (((flags & GLOB_ALTDIRFUNC)
01055 ? (*pglob->gl_stat) (fullname, &st)
01056 : __stat (fullname, &st)) == 0)
01057
01058
01059 flags |= GLOB_NOCHECK;
01060 }
01061
01062 nfound = 0;
01063 }
01064 else
01065 {
01066 if (pattern[0] == '\0')
01067 {
01068
01069
01070 names = (struct globlink *) __alloca (sizeof (struct globlink));
01071 names->name = (char *) xmalloc (1);
01072 if (names->name == NULL)
01073 goto memory_error;
01074 names->name[0] = '\0';
01075 names->next = NULL;
01076 nfound = 1;
01077 meta = 0;
01078 }
01079 else
01080 {
01081 stream = ((flags & GLOB_ALTDIRFUNC)
01082 ? (*pglob->gl_opendir) (directory)
01083 : (__ptr_t) opendir (directory));
01084 if (stream == NULL)
01085 {
01086 if (errno != ENOTDIR
01087 && ((errfunc != NULL && (*errfunc) (directory, errno))
01088 || (flags & GLOB_ERR)))
01089 return GLOB_ABORTED;
01090 nfound = 0;
01091 meta = 0;
01092 }
01093 else
01094 {
01095 int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
01096 | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
01097 #if defined _AMIGA || defined VMS
01098 | FNM_CASEFOLD
01099 #endif
01100 );
01101 nfound = 0;
01102 flags |= GLOB_MAGCHAR;
01103
01104 while (1)
01105 {
01106 const char *name;
01107 size_t len;
01108 #ifdef _LARGEFILE64_SOURCE
01109 struct dirent64 *d;
01110 union
01111 {
01112 struct dirent64 d64;
01113 char room [offsetof (struct dirent64, d_name[0])
01114 + NAME_MAX + 1];
01115 }
01116 d64buf;
01117
01118 if ((flags & GLOB_ALTDIRFUNC))
01119 {
01120 struct dirent *d32 = (*pglob->gl_readdir) (stream);
01121 if (d32 != NULL)
01122 {
01123 CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32);
01124 d = &d64buf.d64;
01125 }
01126 else
01127 d = NULL;
01128 }
01129 else
01130 d = readdir64 (stream);
01131 #else
01132 struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
01133 ? (*pglob->gl_readdir) (stream)
01134 : readdir ((DIR *) stream));
01135 #endif
01136 if (d == NULL)
01137 break;
01138 if (! REAL_DIR_ENTRY (d))
01139 continue;
01140
01141 #ifdef HAVE_D_TYPE
01142
01143
01144 if ((flags & GLOB_ONLYDIR)
01145 && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
01146 continue;
01147 #endif
01148
01149 name = d->d_name;
01150
01151 if (fnmatch (pattern, name, fnm_flags) == 0)
01152 {
01153 struct globlink *new = (struct globlink *)
01154 __alloca (sizeof (struct globlink));
01155 len = NAMLEN (d);
01156 new->name = (char *) xmalloc (len + 1);
01157 if (new->name == NULL)
01158 goto memory_error;
01159 #ifdef HAVE_MEMPCPY
01160 *((char *) mempcpy ((__ptr_t) new->name, name, len))
01161 = '\0';
01162 #else
01163 memcpy ((__ptr_t) new->name, name, len);
01164 new->name[len] = '\0';
01165 #endif
01166 new->next = names;
01167 names = new;
01168 ++nfound;
01169 }
01170 }
01171 }
01172 }
01173 }
01174
01175 if (nfound == 0 && (flags & GLOB_NOCHECK))
01176 {
01177 size_t len = strlen (pattern);
01178 nfound = 1;
01179 names = (struct globlink *) __alloca (sizeof (struct globlink));
01180 names->next = NULL;
01181 names->name = (char *) xmalloc (len + 1);
01182 if (names->name == NULL)
01183 goto memory_error;
01184 #ifdef HAVE_MEMPCPY
01185 *((char *) mempcpy (names->name, pattern, len)) = '\0';
01186 #else
01187 memcpy (names->name, pattern, len);
01188 names->name[len] = '\0';
01189 #endif
01190 }
01191
01192 if (nfound != 0)
01193 {
01194 pglob->gl_pathv
01195 = (char **) xrealloc (pglob->gl_pathv,
01196 (pglob->gl_pathc +
01197 ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
01198 nfound + 1) *
01199 sizeof (char *));
01200 if (pglob->gl_pathv == NULL)
01201 goto memory_error;
01202
01203 if (flags & GLOB_DOOFFS)
01204 while (pglob->gl_pathc < pglob->gl_offs)
01205 pglob->gl_pathv[pglob->gl_pathc++] = NULL;
01206
01207 for (; names != NULL; names = names->next)
01208 pglob->gl_pathv[pglob->gl_pathc++] = names->name;
01209 pglob->gl_pathv[pglob->gl_pathc] = NULL;
01210
01211 pglob->gl_flags = flags;
01212 }
01213
01214 save = errno;
01215 if (stream != NULL)
01216 {
01217 if (flags & GLOB_ALTDIRFUNC)
01218 (*pglob->gl_closedir) (stream);
01219 else
01220 closedir ((DIR *) stream);
01221 }
01222 __set_errno (save);
01223
01224 return nfound == 0 ? GLOB_NOMATCH : 0;
01225
01226 memory_error:
01227 {
01228 save = errno;
01229 if (flags & GLOB_ALTDIRFUNC)
01230 (*pglob->gl_closedir) (stream);
01231 else
01232 closedir ((DIR *) stream);
01233 __set_errno (save);
01234 }
01235 while (names != NULL)
01236 {
01237 if (names->name != NULL)
01238 free ((__ptr_t) names->name);
01239 names = names->next;
01240 }
01241 return GLOB_NOSPACE;
01242 }
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264