rpm 5.3.7
|
00001 /*@-bounds@*/ 00002 /*@-branchstate@*/ 00003 /*@-compdef@*/ 00004 /*@-immediatetrans@*/ 00005 /*@-internalglobs@*/ 00006 /*@-loopswitchbreak@*/ 00007 /*@-modnomods@*/ 00008 /*@-mods@*/ 00009 /*@-moduncon@*/ 00010 /*@-modunconnomods@*/ 00011 /*@-noeffectuncon@*/ 00012 /*@-nullpass@*/ 00013 /*@-onlytrans@*/ 00014 /*@-protoparammatch@*/ 00015 /*@-retalias@*/ 00016 /*@-retvalint@*/ 00017 /*@-shadow@*/ 00018 /*@-sizeoftype@*/ 00019 /*@-temptrans@*/ 00020 /*@-type@*/ 00021 /*@-unqualifiedtrans@*/ 00022 /*@-unrecog@*/ 00023 00024 /* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc. 00025 00026 This library is free software; you can redistribute it and/or 00027 modify it under the terms of the GNU Library General Public License as 00028 published by the Free Software Foundation; either version 2 of the 00029 License, or (at your option) any later version. 00030 00031 This library is distributed in the hope that it will be useful, 00032 but WITHOUT ANY WARRANTY; without even the implied warranty of 00033 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00034 Library General Public License for more details. 00035 00036 You should have received a copy of the GNU Library General Public 00037 License along with this library; see the file COPYING.LIB. If not, 00038 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00039 Boston, MA 02111-1307, USA. */ 00040 00041 /* AIX requires this to be the first thing in the file. */ 00042 #if defined _AIX && !defined __GNUC__ 00043 #pragma alloca 00044 #endif 00045 00046 /*@access DIR@*/ 00047 00048 # include "system.h" 00049 00050 /* Needed for offsetof() */ 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 /* If the system has the `struct dirent64' type we use it internally. */ 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 /* Posix does not require that the d_ino field be present, and some 00090 systems do not provide it. */ 00091 # define REAL_DIR_ENTRY(dp) 1 00092 #else 00093 # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) 00094 #endif /* POSIX */ 00095 00096 #include <errno.h> 00097 #ifndef __set_errno 00098 # define __set_errno(val) errno = (val) 00099 #endif 00100 00101 #if !defined(NAME_MAX) /* XXX OpenIndiana needs this. */ 00102 #define NAME_MAX 255 00103 #endif 00104 00105 /* Outcomment the following line for production quality code. */ 00106 /* #define NDEBUG 1 */ 00107 00108 #define GLOB_INTERFACE_VERSION 1 00109 00110 /*@null@*/ 00111 static inline const char *next_brace_sub __P ((const char *begin)) 00112 /*@*/; 00113 static int glob_in_dir __P ((const char *pattern, const char *directory, 00114 int flags, 00115 int (*errfunc) (const char *, int), 00116 glob_t *pglob)) 00117 /*@globals fileSystem @*/ 00118 /*@modifies fileSystem @*/; 00119 static int prefix_array __P ((const char *prefix, char **array, size_t n)) 00120 /*@*/; 00121 static int collated_compare __P ((const __ptr_t, const __ptr_t)) 00122 /*@*/; 00123 00124 00125 /* Find the end of the sub-pattern in a brace expression. We define 00126 this as an inline function if the compiler permits. */ 00127 static inline const char * 00128 next_brace_sub (const char *begin) 00129 { 00130 unsigned int depth = 0; 00131 const char *cp = begin; 00132 00133 while (1) 00134 { 00135 if (depth == 0) 00136 { 00137 if (*cp != ',' && *cp != '}' && *cp != '\0') 00138 { 00139 if (*cp == '{') 00140 ++depth; 00141 ++cp; 00142 continue; 00143 } 00144 } 00145 else 00146 { 00147 while (*cp != '\0' && (*cp != '}' || depth > 0)) 00148 { 00149 if (*cp == '}') 00150 --depth; 00151 ++cp; 00152 } 00153 if (*cp == '\0') 00154 /* An incorrectly terminated brace expression. */ 00155 return NULL; 00156 00157 continue; 00158 } 00159 break; 00160 } 00161 00162 return cp; 00163 } 00164 00165 static int __glob_pattern_p (const char *pattern, int quote); 00166 00167 /* Do glob searching for PATTERN, placing results in PGLOB. 00168 The bits defined above may be set in FLAGS. 00169 If a directory cannot be opened or read and ERRFUNC is not nil, 00170 it is called with the pathname that caused the error, and the 00171 `errno' value from the failing call; if it returns non-zero 00172 `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored. 00173 If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. 00174 Otherwise, `glob' returns zero. */ 00175 int 00176 glob (const char *pattern, int flags, 00177 int (*errfunc) __P ((const char *, int)), glob_t *pglob) 00178 { 00179 const char *filename; 00180 const char *dirname; 00181 size_t dirlen; 00182 int status; 00183 int oldcount; 00184 00185 if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) 00186 { 00187 __set_errno (EINVAL); 00188 return -1; 00189 } 00190 00191 if (flags & GLOB_BRACE) 00192 { 00193 const char *begin = strchr (pattern, '{'); 00194 if (begin != NULL) 00195 { 00196 /* Allocate working buffer large enough for our work. Note that 00197 we have at least an opening and closing brace. */ 00198 int firstc; 00199 char *alt_start; 00200 const char *p; 00201 const char *next; 00202 const char *rest; 00203 size_t rest_len; 00204 #ifdef __GNUC__ 00205 char onealt[strlen (pattern) - 1]; 00206 #else 00207 char *onealt = (char *) xmalloc (strlen (pattern) - 1); 00208 if (onealt == NULL) 00209 { 00210 if (!(flags & GLOB_APPEND)) 00211 globfree (pglob); 00212 return GLOB_NOSPACE; 00213 } 00214 #endif 00215 00216 /* We know the prefix for all sub-patterns. */ 00217 #ifdef HAVE_MEMPCPY 00218 alt_start = mempcpy (onealt, pattern, begin - pattern); 00219 #else 00220 memcpy (onealt, pattern, begin - pattern); 00221 alt_start = &onealt[begin - pattern]; 00222 #endif 00223 00224 /* Find the first sub-pattern and at the same time find the 00225 rest after the closing brace. */ 00226 next = next_brace_sub (begin + 1); 00227 if (next == NULL) 00228 { 00229 /* It is an illegal expression. */ 00230 #ifndef __GNUC__ 00231 free (onealt); 00232 #endif 00233 return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); 00234 } 00235 00236 /* Now find the end of the whole brace expression. */ 00237 rest = next; 00238 while (*rest != '}') 00239 { 00240 rest = next_brace_sub (rest + 1); 00241 if (rest == NULL) 00242 { 00243 /* It is an illegal expression. */ 00244 #ifndef __GNUC__ 00245 free (onealt); 00246 #endif 00247 return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); 00248 } 00249 } 00250 /* Please note that we now can be sure the brace expression 00251 is well-formed. */ 00252 rest_len = strlen (++rest) + 1; 00253 00254 /* We have a brace expression. BEGIN points to the opening {, 00255 NEXT points past the terminator of the first element, and END 00256 points past the final }. We will accumulate result names from 00257 recursive runs for each brace alternative in the buffer using 00258 GLOB_APPEND. */ 00259 00260 if (!(flags & GLOB_APPEND)) 00261 { 00262 /* This call is to set a new vector, so clear out the 00263 vector so we can append to it. */ 00264 pglob->gl_pathc = 0; 00265 pglob->gl_pathv = NULL; 00266 } 00267 firstc = pglob->gl_pathc; 00268 00269 p = begin + 1; 00270 while (1) 00271 { 00272 int result; 00273 00274 /* Construct the new glob expression. */ 00275 #ifdef HAVE_MEMPCPY 00276 mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len); 00277 #else 00278 memcpy (alt_start, p, next - p); 00279 memcpy (&alt_start[next - p], rest, rest_len); 00280 #endif 00281 00282 result = glob (onealt, 00283 ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC)) 00284 | GLOB_APPEND), errfunc, pglob); 00285 00286 /* If we got an error, return it. */ 00287 if (result && result != GLOB_NOMATCH) 00288 { 00289 #ifndef __GNUC__ 00290 free (onealt); 00291 #endif 00292 if (!(flags & GLOB_APPEND)) 00293 globfree (pglob); 00294 return result; 00295 } 00296 00297 if (*next == '}') 00298 /* We saw the last entry. */ 00299 break; 00300 00301 p = next + 1; 00302 next = next_brace_sub (p); 00303 assert (next != NULL); 00304 } 00305 00306 #ifndef __GNUC__ 00307 free (onealt); 00308 #endif 00309 00310 if ((int)pglob->gl_pathc != firstc) 00311 /* We found some entries. */ 00312 return 0; 00313 else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) 00314 return GLOB_NOMATCH; 00315 } 00316 } 00317 00318 /* Find the filename. */ 00319 filename = strrchr (pattern, '/'); 00320 #if defined __MSDOS__ || defined WINDOWS32 00321 /* The case of "d:pattern". Since `:' is not allowed in 00322 file names, we can safely assume that wherever it 00323 happens in pattern, it signals the filename part. This 00324 is so we could some day support patterns like "[a-z]:foo". */ 00325 if (filename == NULL) 00326 filename = strchr (pattern, ':'); 00327 #endif /* __MSDOS__ || WINDOWS32 */ 00328 if (filename == NULL) 00329 { 00330 /* This can mean two things: a simple name or "~name". The latter 00331 case is nothing but a notation for a directory. */ 00332 if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') 00333 { 00334 dirname = pattern; 00335 dirlen = strlen (pattern); 00336 00337 /* Set FILENAME to NULL as a special flag. This is ugly but 00338 other solutions would require much more code. We test for 00339 this special case below. */ 00340 filename = NULL; 00341 } 00342 else 00343 { 00344 filename = pattern; 00345 #ifdef _AMIGA 00346 dirname = ""; 00347 #else 00348 dirname = "."; 00349 #endif 00350 dirlen = 0; 00351 } 00352 } 00353 else if (filename == pattern) 00354 { 00355 /* "/pattern". */ 00356 dirname = "/"; 00357 dirlen = 1; 00358 ++filename; 00359 } 00360 else 00361 { 00362 char *newp; 00363 dirlen = filename - pattern; 00364 #if defined __MSDOS__ || defined WINDOWS32 00365 if (*filename == ':' 00366 || (filename > pattern + 1 && filename[-1] == ':')) 00367 { 00368 char *drive_spec; 00369 00370 ++dirlen; 00371 drive_spec = (char *) __alloca (dirlen + 1); 00372 #ifdef HAVE_MEMPCPY 00373 *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0'; 00374 #else 00375 memcpy (drive_spec, pattern, dirlen); 00376 drive_spec[dirlen] = '\0'; 00377 #endif 00378 /* For now, disallow wildcards in the drive spec, to 00379 prevent infinite recursion in glob. */ 00380 if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE))) 00381 return GLOB_NOMATCH; 00382 /* If this is "d:pattern", we need to copy `:' to DIRNAME 00383 as well. If it's "d:/pattern", don't remove the slash 00384 from "d:/", since "d:" and "d:/" are not the same.*/ 00385 } 00386 #endif 00387 newp = (char *) __alloca (dirlen + 1); 00388 #ifdef HAVE_MEMPCPY 00389 *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; 00390 #else 00391 memcpy (newp, pattern, dirlen); 00392 newp[dirlen] = '\0'; 00393 #endif 00394 dirname = newp; 00395 ++filename; 00396 00397 if (filename[0] == '\0' 00398 #if defined __MSDOS__ || defined WINDOWS32 00399 && dirname[dirlen - 1] != ':' 00400 && (dirlen < 3 || dirname[dirlen - 2] != ':' 00401 || dirname[dirlen - 1] != '/') 00402 #endif 00403 && dirlen > 1) 00404 /* "pattern/". Expand "pattern", appending slashes. */ 00405 { 00406 int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); 00407 if (val == 0) 00408 pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) 00409 | (flags & GLOB_MARK)); 00410 return val; 00411 } 00412 } 00413 00414 if (!(flags & GLOB_APPEND)) 00415 { 00416 pglob->gl_pathc = 0; 00417 pglob->gl_pathv = NULL; 00418 } 00419 00420 oldcount = pglob->gl_pathc; 00421 00422 #ifndef VMS 00423 if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') 00424 { 00425 if (dirname[1] == '\0' || dirname[1] == '/') 00426 { 00427 /* Look up home directory. */ 00428 const char *home_dir = getenv ("HOME"); 00429 # ifdef _AMIGA 00430 if (home_dir == NULL || home_dir[0] == '\0') 00431 home_dir = "SYS:"; 00432 # else 00433 # ifdef WINDOWS32 00434 if (home_dir == NULL || home_dir[0] == '\0') 00435 home_dir = "c:/users/default"; /* poor default */ 00436 # else 00437 if (home_dir == NULL || home_dir[0] == '\0') 00438 { 00439 int success; 00440 char *name; 00441 # if defined HAVE_GETLOGIN_R || defined _LIBC 00442 size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1; 00443 00444 if (buflen == 0) 00445 /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try 00446 a moderate value. */ 00447 buflen = 20; 00448 name = (char *) __alloca (buflen); 00449 00450 success = getlogin_r (name, buflen) >= 0; 00451 # else 00452 success = (name = getlogin ()) != NULL; 00453 # endif 00454 if (success) 00455 { 00456 struct passwd *p; 00457 # if defined HAVE_GETPWNAM_R || defined _LIBC 00458 size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX); 00459 char *pwtmpbuf; 00460 struct passwd pwbuf; 00461 int save = errno; 00462 00463 if (pwbuflen == -1) 00464 /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. 00465 Try a moderate value. */ 00466 pwbuflen = 1024; 00467 pwtmpbuf = (char *) __alloca (pwbuflen); 00468 00469 while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) 00470 != 0) 00471 { 00472 if (errno != ERANGE) 00473 { 00474 p = NULL; 00475 break; 00476 } 00477 pwbuflen *= 2; 00478 pwtmpbuf = (char *) __alloca (pwbuflen); 00479 __set_errno (save); 00480 } 00481 # else 00482 p = getpwnam (name); 00483 # endif 00484 if (p != NULL) 00485 home_dir = p->pw_dir; 00486 } 00487 } 00488 if (home_dir == NULL || home_dir[0] == '\0') 00489 { 00490 if (flags & GLOB_TILDE_CHECK) 00491 return GLOB_NOMATCH; 00492 else 00493 home_dir = "~"; /* No luck. */ 00494 } 00495 # endif /* WINDOWS32 */ 00496 # endif 00497 /* Now construct the full directory. */ 00498 if (dirname[1] == '\0') 00499 dirname = home_dir; 00500 else 00501 { 00502 char *newp; 00503 size_t home_len = strlen (home_dir); 00504 newp = (char *) __alloca (home_len + dirlen); 00505 # ifdef HAVE_MEMPCPY 00506 mempcpy (mempcpy (newp, home_dir, home_len), 00507 &dirname[1], dirlen); 00508 # else 00509 memcpy (newp, home_dir, home_len); 00510 memcpy (&newp[home_len], &dirname[1], dirlen); 00511 # endif 00512 dirname = newp; 00513 } 00514 } 00515 # if !defined _AMIGA && !defined WINDOWS32 00516 else 00517 { 00518 char *end_name = strchr (dirname, '/'); 00519 const char *user_name; 00520 const char *home_dir; 00521 00522 if (end_name == NULL) 00523 user_name = dirname + 1; 00524 else 00525 { 00526 char *newp; 00527 newp = (char *) __alloca (end_name - dirname); 00528 # ifdef HAVE_MEMPCPY 00529 *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) 00530 = '\0'; 00531 # else 00532 memcpy (newp, dirname + 1, end_name - dirname); 00533 newp[end_name - dirname - 1] = '\0'; 00534 # endif 00535 user_name = newp; 00536 } 00537 00538 /* Look up specific user's home directory. */ 00539 { 00540 struct passwd *p; 00541 # if defined HAVE_GETPWNAM_R || defined _LIBC 00542 size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); 00543 char *pwtmpbuf; 00544 struct passwd pwbuf; 00545 int save = errno; 00546 00547 if (buflen == -1) 00548 /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a 00549 moderate value. */ 00550 buflen = 1024; 00551 pwtmpbuf = (char *) __alloca (buflen); 00552 00553 while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0) 00554 { 00555 if (errno != ERANGE) 00556 { 00557 p = NULL; 00558 break; 00559 } 00560 buflen *= 2; 00561 pwtmpbuf = __alloca (buflen); 00562 __set_errno (save); 00563 } 00564 # else 00565 p = getpwnam (user_name); 00566 # endif 00567 if (p != NULL) 00568 home_dir = p->pw_dir; 00569 else 00570 home_dir = NULL; 00571 } 00572 /* If we found a home directory use this. */ 00573 if (home_dir != NULL) 00574 { 00575 char *newp; 00576 size_t home_len = strlen (home_dir); 00577 size_t rest_len = end_name == NULL ? 0 : strlen (end_name); 00578 newp = (char *) __alloca (home_len + rest_len + 1); 00579 # ifdef HAVE_MEMPCPY 00580 *((char *) mempcpy (mempcpy (newp, home_dir, home_len), 00581 end_name, rest_len)) = '\0'; 00582 # else 00583 memcpy (newp, home_dir, home_len); 00584 memcpy (&newp[home_len], end_name, rest_len); 00585 newp[home_len + rest_len] = '\0'; 00586 # endif 00587 dirname = newp; 00588 } 00589 else 00590 if (flags & GLOB_TILDE_CHECK) 00591 /* We have to regard it as an error if we cannot find the 00592 home directory. */ 00593 return GLOB_NOMATCH; 00594 } 00595 # endif /* Not Amiga && not WINDOWS32. */ 00596 } 00597 #endif /* Not VMS. */ 00598 00599 /* Now test whether we looked for "~" or "~NAME". In this case we 00600 can give the answer now. */ 00601 if (filename == NULL) 00602 { 00603 struct stat st; 00604 00605 /* Return the directory if we don't check for error or if it exists. */ 00606 if ((flags & GLOB_NOCHECK) 00607 || (((flags & GLOB_ALTDIRFUNC) 00608 ? (*pglob->gl_stat) (dirname, &st) 00609 : __stat (dirname, &st)) == 0 00610 && S_ISDIR (st.st_mode))) 00611 { 00612 pglob->gl_pathv 00613 = (char **) xrealloc (pglob->gl_pathv, 00614 (pglob->gl_pathc + 00615 ((flags & GLOB_DOOFFS) ? 00616 pglob->gl_offs : 0) + 00617 1 + 1) * 00618 sizeof (char *)); 00619 if (pglob->gl_pathv == NULL) 00620 return GLOB_NOSPACE; 00621 00622 if (flags & GLOB_DOOFFS) 00623 while (pglob->gl_pathc < pglob->gl_offs) 00624 pglob->gl_pathv[pglob->gl_pathc++] = NULL; 00625 00626 #if defined HAVE_STRDUP || defined _LIBC 00627 pglob->gl_pathv[pglob->gl_pathc] = xstrdup (dirname); 00628 #else 00629 { 00630 size_t len = strlen (dirname) + 1; 00631 char *dircopy = xmalloc (len); 00632 if (dircopy != NULL) 00633 pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname, 00634 len); 00635 } 00636 #endif 00637 if (pglob->gl_pathv[pglob->gl_pathc] == NULL) 00638 { 00639 free (pglob->gl_pathv); 00640 return GLOB_NOSPACE; 00641 } 00642 pglob->gl_pathv[++pglob->gl_pathc] = NULL; 00643 pglob->gl_flags = flags; 00644 00645 return 0; 00646 } 00647 00648 /* Not found. */ 00649 return GLOB_NOMATCH; 00650 } 00651 00652 if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE))) 00653 { 00654 /* The directory name contains metacharacters, so we 00655 have to glob for the directory, and then glob for 00656 the pattern in each directory found. */ 00657 glob_t dirs; 00658 register int i; 00659 00660 if ((flags & GLOB_ALTDIRFUNC) != 0) 00661 { 00662 /* Use the alternative access functions also in the recursive 00663 call. */ 00664 dirs.gl_opendir = pglob->gl_opendir; 00665 dirs.gl_readdir = pglob->gl_readdir; 00666 dirs.gl_closedir = pglob->gl_closedir; 00667 dirs.gl_stat = pglob->gl_stat; 00668 dirs.gl_lstat = pglob->gl_lstat; 00669 } 00670 00671 status = glob (dirname, 00672 ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE 00673 | GLOB_ALTDIRFUNC)) 00674 | GLOB_NOSORT | GLOB_ONLYDIR), 00675 errfunc, &dirs); 00676 if (status != 0) 00677 return status; 00678 00679 /* We have successfully globbed the preceding directory name. 00680 For each name we found, call glob_in_dir on it and FILENAME, 00681 appending the results to PGLOB. */ 00682 for (i = 0; i < (int)dirs.gl_pathc; ++i) 00683 { 00684 int old_pathc; 00685 00686 #ifdef SHELL 00687 { 00688 /* Make globbing interruptible in the bash shell. */ 00689 extern int interrupt_state; 00690 00691 if (interrupt_state) 00692 { 00693 globfree (&dirs); 00694 globfree (&files); 00695 return GLOB_ABORTED; 00696 } 00697 } 00698 #endif /* SHELL. */ 00699 00700 old_pathc = pglob->gl_pathc; 00701 status = glob_in_dir (filename, dirs.gl_pathv[i], 00702 ((flags | GLOB_APPEND) 00703 & ~(GLOB_NOCHECK | GLOB_ERR)), 00704 errfunc, pglob); 00705 if (status == GLOB_NOMATCH) 00706 /* No matches in this directory. Try the next. */ 00707 continue; 00708 00709 if (status != 0) 00710 { 00711 globfree (&dirs); 00712 globfree (pglob); 00713 return status; 00714 } 00715 00716 /* Stick the directory on the front of each name. */ 00717 if (prefix_array (dirs.gl_pathv[i], 00718 &pglob->gl_pathv[old_pathc], 00719 pglob->gl_pathc - old_pathc)) 00720 { 00721 globfree (&dirs); 00722 globfree (pglob); 00723 return GLOB_NOSPACE; 00724 } 00725 } 00726 00727 flags |= GLOB_MAGCHAR; 00728 00729 /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls. 00730 But if we have not found any matching entry and thie GLOB_NOCHECK 00731 flag was set we must return the list consisting of the disrectory 00732 names followed by the filename. */ 00733 if ((int)pglob->gl_pathc == oldcount) 00734 { 00735 /* No matches. */ 00736 if (flags & GLOB_NOCHECK) 00737 { 00738 size_t filename_len = strlen (filename) + 1; 00739 char **new_pathv; 00740 struct stat st; 00741 00742 /* This is an pessimistic guess about the size. */ 00743 pglob->gl_pathv 00744 = (char **) xrealloc (pglob->gl_pathv, 00745 (pglob->gl_pathc + 00746 ((flags & GLOB_DOOFFS) ? 00747 pglob->gl_offs : 0) + 00748 dirs.gl_pathc + 1) * 00749 sizeof (char *)); 00750 if (pglob->gl_pathv == NULL) 00751 { 00752 globfree (&dirs); 00753 return GLOB_NOSPACE; 00754 } 00755 00756 if (flags & GLOB_DOOFFS) 00757 while (pglob->gl_pathc < pglob->gl_offs) 00758 pglob->gl_pathv[pglob->gl_pathc++] = NULL; 00759 00760 for (i = 0; i < (int)dirs.gl_pathc; ++i) 00761 { 00762 const char *dir = dirs.gl_pathv[i]; 00763 size_t dir_len = strlen (dir); 00764 00765 /* First check whether this really is a directory. */ 00766 if (((flags & GLOB_ALTDIRFUNC) 00767 ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0 00768 || !S_ISDIR (st.st_mode)) 00769 /* No directory, ignore this entry. */ 00770 continue; 00771 00772 pglob->gl_pathv[pglob->gl_pathc] = xmalloc (dir_len + 1 00773 + filename_len); 00774 if (pglob->gl_pathv[pglob->gl_pathc] == NULL) 00775 { 00776 globfree (&dirs); 00777 globfree (pglob); 00778 return GLOB_NOSPACE; 00779 } 00780 00781 #ifdef HAVE_MEMPCPY 00782 mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc], 00783 dir, dir_len), 00784 "/", 1), 00785 filename, filename_len); 00786 #else 00787 memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len); 00788 pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/'; 00789 memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1], 00790 filename, filename_len); 00791 #endif 00792 ++pglob->gl_pathc; 00793 } 00794 00795 pglob->gl_pathv[pglob->gl_pathc] = NULL; 00796 pglob->gl_flags = flags; 00797 00798 /* Now we know how large the gl_pathv vector must be. */ 00799 new_pathv = (char **) xrealloc (pglob->gl_pathv, 00800 ((pglob->gl_pathc + 1) 00801 * sizeof (char *))); 00802 if (new_pathv != NULL) 00803 pglob->gl_pathv = new_pathv; 00804 } 00805 else 00806 return GLOB_NOMATCH; 00807 } 00808 00809 globfree (&dirs); 00810 } 00811 else 00812 { 00813 status = glob_in_dir (filename, dirname, flags, errfunc, pglob); 00814 if (status != 0) 00815 return status; 00816 00817 if (dirlen > 0) 00818 { 00819 /* Stick the directory on the front of each name. */ 00820 int ignore = oldcount; 00821 00822 if ((flags & GLOB_DOOFFS) && ignore < (int)pglob->gl_offs) 00823 ignore = pglob->gl_offs; 00824 00825 if (prefix_array (dirname, 00826 &pglob->gl_pathv[ignore], 00827 pglob->gl_pathc - ignore)) 00828 { 00829 globfree (pglob); 00830 return GLOB_NOSPACE; 00831 } 00832 } 00833 } 00834 00835 if (flags & GLOB_MARK) 00836 { 00837 /* Append slashes to directory names. */ 00838 int i; 00839 struct stat st; 00840 for (i = oldcount; i < (int)pglob->gl_pathc; ++i) 00841 if (((flags & GLOB_ALTDIRFUNC) 00842 ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st) 00843 : __stat (pglob->gl_pathv[i], &st)) == 0 00844 && S_ISDIR (st.st_mode)) 00845 { 00846 size_t len = strlen (pglob->gl_pathv[i]) + 2; 00847 char *new = xrealloc (pglob->gl_pathv[i], len); 00848 if (new == NULL) 00849 { 00850 globfree (pglob); 00851 return GLOB_NOSPACE; 00852 } 00853 strcpy (&new[len - 2], "/"); 00854 pglob->gl_pathv[i] = new; 00855 } 00856 } 00857 00858 if (!(flags & GLOB_NOSORT)) 00859 { 00860 /* Sort the vector. */ 00861 int non_sort = oldcount; 00862 00863 if ((flags & GLOB_DOOFFS) && (int)pglob->gl_offs > oldcount) 00864 non_sort = pglob->gl_offs; 00865 00866 qsort ((__ptr_t) &pglob->gl_pathv[non_sort], 00867 pglob->gl_pathc - non_sort, 00868 sizeof (char *), collated_compare); 00869 } 00870 00871 return 0; 00872 } 00873 00874 00875 /* Free storage allocated in PGLOB by a previous `glob' call. */ 00876 void 00877 globfree (glob_t *pglob) 00878 { 00879 if (pglob->gl_pathv != NULL) 00880 { 00881 register int i; 00882 for (i = 0; i < (int)pglob->gl_pathc; ++i) 00883 if (pglob->gl_pathv[i] != NULL) 00884 free ((__ptr_t) pglob->gl_pathv[i]); 00885 free ((__ptr_t) pglob->gl_pathv); 00886 } 00887 } 00888 00889 00890 /* Do a collated comparison of A and B. */ 00891 static int 00892 collated_compare (const __ptr_t a, const __ptr_t b) 00893 { 00894 const char *const s1 = *(const char *const * const) a; 00895 const char *const s2 = *(const char *const * const) b; 00896 00897 if (s1 == s2) 00898 return 0; 00899 if (s1 == NULL) 00900 return 1; 00901 if (s2 == NULL) 00902 return -1; 00903 return strcoll (s1, s2); 00904 } 00905 00906 00907 /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's 00908 elements in place. Return nonzero if out of memory, zero if successful. 00909 A slash is inserted between DIRNAME and each elt of ARRAY, 00910 unless DIRNAME is just "/". Each old element of ARRAY is freed. */ 00911 static int 00912 prefix_array (const char *dirname, char **array, size_t n) 00913 { 00914 register size_t i; 00915 size_t dirlen = strlen (dirname); 00916 #if defined __MSDOS__ || defined WINDOWS32 00917 int sep_char = '/'; 00918 # define DIRSEP_CHAR sep_char 00919 #else 00920 # define DIRSEP_CHAR '/' 00921 #endif 00922 00923 if (dirlen == 1 && dirname[0] == '/') 00924 /* DIRNAME is just "/", so normal prepending would get us "//foo". 00925 We want "/foo" instead, so don't prepend any chars from DIRNAME. */ 00926 dirlen = 0; 00927 #if defined __MSDOS__ || defined WINDOWS32 00928 else if (dirlen > 1) 00929 { 00930 if (dirname[dirlen - 1] == '/') 00931 /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */ 00932 --dirlen; 00933 else if (dirname[dirlen - 1] == ':') 00934 { 00935 /* DIRNAME is "d:". Use `:' instead of `/'. */ 00936 --dirlen; 00937 sep_char = ':'; 00938 } 00939 } 00940 #endif 00941 00942 for (i = 0; i < n; ++i) 00943 { 00944 size_t eltlen = strlen (array[i]) + 1; 00945 char *new = (char *) xmalloc (dirlen + 1 + eltlen); 00946 if (new == NULL) 00947 { 00948 while (i > 0) 00949 free ((__ptr_t) array[--i]); 00950 return 1; 00951 } 00952 00953 #ifdef HAVE_MEMPCPY 00954 { 00955 char *endp = (char *) mempcpy (new, dirname, dirlen); 00956 *endp++ = DIRSEP_CHAR; 00957 mempcpy (endp, array[i], eltlen); 00958 } 00959 #else 00960 memcpy (new, dirname, dirlen); 00961 new[dirlen] = DIRSEP_CHAR; 00962 memcpy (&new[dirlen + 1], array[i], eltlen); 00963 #endif 00964 free ((__ptr_t) array[i]); 00965 array[i] = new; 00966 } 00967 00968 return 0; 00969 } 00970 00971 00972 /* We must not compile this function twice. */ 00973 #if !defined _LIBC || !defined NO_GLOB_PATTERN_P 00974 /* Return nonzero if PATTERN contains any metacharacters. 00975 Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ 00976 static int 00977 __glob_pattern_p (const char *pattern, int quote) 00978 { 00979 register const char *p; 00980 int open = 0; 00981 00982 for (p = pattern; *p != '\0'; ++p) 00983 switch (*p) 00984 { 00985 case '?': 00986 case '*': 00987 return 1; 00988 00989 case '\\': 00990 if (quote && p[1] != '\0') 00991 ++p; 00992 break; 00993 00994 case '[': 00995 open = 1; 00996 break; 00997 00998 case ']': 00999 if (open) 01000 return 1; 01001 break; 01002 } 01003 01004 return 0; 01005 } 01006 # ifdef _LIBC 01007 weak_alias (__glob_pattern_p, glob_pattern_p) 01008 # endif 01009 #endif 01010 01011 01012 /* Like `glob', but PATTERN is a final pathname component, 01013 and matches are searched for in DIRECTORY. 01014 The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done. 01015 The GLOB_APPEND flag is assumed to be set (always appends). */ 01016 static int 01017 glob_in_dir (const char *pattern, const char *directory, int flags, 01018 int (*errfunc) __P ((const char *, int)), glob_t *pglob) 01019 { 01020 __ptr_t stream = NULL; 01021 01022 struct globlink 01023 { 01024 struct globlink *next; 01025 char *name; 01026 }; 01027 struct globlink *names = NULL; 01028 size_t nfound; 01029 int meta; 01030 int save; 01031 01032 meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)); 01033 if (meta == 0) 01034 { 01035 if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)) 01036 /* We need not do any tests. The PATTERN contains no meta 01037 characters and we must not return an error therefore the 01038 result will always contain exactly one name. */ 01039 flags |= GLOB_NOCHECK; 01040 else 01041 { 01042 /* Since we use the normal file functions we can also use stat() 01043 to verify the file is there. */ 01044 struct stat st; 01045 size_t patlen = strlen (pattern); 01046 size_t dirlen = strlen (directory); 01047 char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1); 01048 01049 # ifdef HAVE_MEMPCPY 01050 mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), 01051 "/", 1), 01052 pattern, patlen + 1); 01053 # else 01054 memcpy (fullname, directory, dirlen); 01055 fullname[dirlen] = '/'; 01056 memcpy (&fullname[dirlen + 1], pattern, patlen + 1); 01057 # endif 01058 if (((flags & GLOB_ALTDIRFUNC) 01059 ? (*pglob->gl_stat) (fullname, &st) 01060 : __stat (fullname, &st)) == 0) 01061 /* We found this file to be existing. Now tell the rest 01062 of the function to copy this name into the result. */ 01063 flags |= GLOB_NOCHECK; 01064 } 01065 01066 nfound = 0; 01067 } 01068 else 01069 { 01070 if (pattern[0] == '\0') 01071 { 01072 /* This is a special case for matching directories like in 01073 "*a/". */ 01074 names = (struct globlink *) __alloca (sizeof (struct globlink)); 01075 names->name = (char *) xmalloc (1); 01076 if (names->name == NULL) 01077 goto memory_error; 01078 names->name[0] = '\0'; 01079 names->next = NULL; 01080 nfound = 1; 01081 meta = 0; 01082 } 01083 else 01084 { 01085 stream = ((flags & GLOB_ALTDIRFUNC) 01086 ? (*pglob->gl_opendir) (directory) 01087 : (__ptr_t) opendir (directory)); 01088 if (stream == NULL) 01089 { 01090 if (errno != ENOTDIR 01091 && ((errfunc != NULL && (*errfunc) (directory, errno)) 01092 || (flags & GLOB_ERR))) 01093 return GLOB_ABORTED; 01094 nfound = 0; 01095 meta = 0; 01096 } 01097 else 01098 { 01099 int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) 01100 | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) 01101 #if defined _AMIGA || defined VMS 01102 | FNM_CASEFOLD 01103 #endif 01104 ); 01105 nfound = 0; 01106 flags |= GLOB_MAGCHAR; 01107 01108 while (1) 01109 { 01110 const char *name; 01111 size_t len; 01112 #ifdef _LARGEFILE64_SOURCE 01113 struct dirent64 *d; 01114 union 01115 { 01116 struct dirent64 d64; 01117 char room [offsetof (struct dirent64, d_name[0]) 01118 + NAME_MAX + 1]; 01119 } 01120 d64buf; 01121 01122 if ((flags & GLOB_ALTDIRFUNC)) 01123 { 01124 struct dirent *d32 = (*pglob->gl_readdir) (stream); 01125 if (d32 != NULL) 01126 { 01127 CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32); 01128 d = &d64buf.d64; 01129 } 01130 else 01131 d = NULL; 01132 } 01133 else 01134 d = readdir64 (stream); 01135 #else 01136 struct dirent *d = ((flags & GLOB_ALTDIRFUNC) 01137 ? (*pglob->gl_readdir) (stream) 01138 : readdir ((DIR *) stream)); 01139 #endif 01140 if (d == NULL) 01141 break; 01142 if (! REAL_DIR_ENTRY (d)) 01143 continue; 01144 01145 #ifdef HAVE_D_TYPE 01146 /* If we shall match only directories use the information 01147 provided by the dirent call if possible. */ 01148 if ((flags & GLOB_ONLYDIR) 01149 && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR) 01150 continue; 01151 #endif 01152 01153 name = d->d_name; 01154 01155 if (fnmatch (pattern, name, fnm_flags) == 0) 01156 { 01157 struct globlink *new = (struct globlink *) 01158 __alloca (sizeof (struct globlink)); 01159 len = NAMLEN (d); 01160 new->name = (char *) xmalloc (len + 1); 01161 if (new->name == NULL) 01162 goto memory_error; 01163 #ifdef HAVE_MEMPCPY 01164 *((char *) mempcpy ((__ptr_t) new->name, name, len)) 01165 = '\0'; 01166 #else 01167 memcpy ((__ptr_t) new->name, name, len); 01168 new->name[len] = '\0'; 01169 #endif 01170 new->next = names; 01171 names = new; 01172 ++nfound; 01173 } 01174 } 01175 } 01176 } 01177 } 01178 01179 if (nfound == 0 && (flags & GLOB_NOCHECK)) 01180 { 01181 size_t len = strlen (pattern); 01182 nfound = 1; 01183 names = (struct globlink *) __alloca (sizeof (struct globlink)); 01184 names->next = NULL; 01185 names->name = (char *) xmalloc (len + 1); 01186 if (names->name == NULL) 01187 goto memory_error; 01188 #ifdef HAVE_MEMPCPY 01189 *((char *) mempcpy (names->name, pattern, len)) = '\0'; 01190 #else 01191 memcpy (names->name, pattern, len); 01192 names->name[len] = '\0'; 01193 #endif 01194 } 01195 01196 if (nfound != 0) 01197 { 01198 pglob->gl_pathv 01199 = (char **) xrealloc (pglob->gl_pathv, 01200 (pglob->gl_pathc + 01201 ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + 01202 nfound + 1) * 01203 sizeof (char *)); 01204 if (pglob->gl_pathv == NULL) 01205 goto memory_error; 01206 01207 if (flags & GLOB_DOOFFS) 01208 while (pglob->gl_pathc < pglob->gl_offs) 01209 pglob->gl_pathv[pglob->gl_pathc++] = NULL; 01210 01211 for (; names != NULL; names = names->next) 01212 pglob->gl_pathv[pglob->gl_pathc++] = names->name; 01213 pglob->gl_pathv[pglob->gl_pathc] = NULL; 01214 01215 pglob->gl_flags = flags; 01216 } 01217 01218 save = errno; 01219 if (stream != NULL) 01220 { 01221 if (flags & GLOB_ALTDIRFUNC) 01222 (*pglob->gl_closedir) (stream); 01223 else 01224 closedir ((DIR *) stream); 01225 } 01226 __set_errno (save); 01227 01228 return nfound == 0 ? GLOB_NOMATCH : 0; 01229 01230 memory_error: 01231 { 01232 save = errno; 01233 if (flags & GLOB_ALTDIRFUNC) 01234 (*pglob->gl_closedir) (stream); 01235 else 01236 closedir ((DIR *) stream); 01237 __set_errno (save); 01238 } 01239 while (names != NULL) 01240 { 01241 if (names->name != NULL) 01242 free ((__ptr_t) names->name); 01243 names = names->next; 01244 } 01245 return GLOB_NOSPACE; 01246 } 01247 /*@=unrecog@*/ 01248 /*@=unqualifiedtrans@*/ 01249 /*@=type@*/ 01250 /*@=temptrans@*/ 01251 /*@=sizeoftype@*/ 01252 /*@=shadow@*/ 01253 /*@=retvalint@*/ 01254 /*@=retalias@*/ 01255 /*@=protoparammatch@*/ 01256 /*@=onlytrans@*/ 01257 /*@=nullpass@*/ 01258 /*@=noeffectuncon@*/ 01259 /*@=modunconnomods@*/ 01260 /*@=moduncon@*/ 01261 /*@=mods@*/ 01262 /*@=modnomods@*/ 01263 /*@=loopswitchbreak@*/ 01264 /*@=internalglobs@*/ 01265 /*@=immediatetrans@*/ 01266 /*@=compdef@*/ 01267 /*@=branchstate@*/ 01268 /*@=bounds@*/