diff options
Diffstat (limited to 'sysdeps/generic/glob.c')
-rw-r--r-- | sysdeps/generic/glob.c | 224 |
1 files changed, 119 insertions, 105 deletions
diff --git a/sysdeps/generic/glob.c b/sysdeps/generic/glob.c index 0fe48b03d6..6098766ca0 100644 --- a/sysdeps/generic/glob.c +++ b/sysdeps/generic/glob.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc. +/* Copyright (C) 1991-1999, 2000 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -248,9 +248,16 @@ extern char *alloca (); # define readdir(str) __readdir (str) # define getpwnam_r(name, bufp, buf, len, res) \ __getpwnam_r (name, bufp, buf, len, res) -# ifndef __stat -# define __stat(fname, buf) __xstat (_STAT_VER, fname, buf) +# ifndef __stat64 +# define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf) # endif +# define HAVE_STAT64 1 +#endif + +#ifndef HAVE_STAT64 +# define __stat64(fname, buf) __stat (fname, buf) +/* This is the variable name we are using. */ +# define st64 st #endif #if !(defined STDC_HEADERS || defined __GNU_LIBRARY__) @@ -372,6 +379,11 @@ glob (pattern, flags, errfunc, pglob) return -1; } + if (!(flags & GLOB_DOOFFS)) + /* Have to do this so `globfree' knows where to start freeing. It + also makes all the code that uses gl_offs simpler. */ + pglob->gl_offs = 0; + if (flags & GLOB_BRACE) { const char *begin = strchr (pattern, '{'); @@ -598,10 +610,22 @@ glob (pattern, flags, errfunc, pglob) if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; - pglob->gl_pathv = NULL; + if (!(flags & GLOB_DOOFFS)) + pglob->gl_pathv = NULL; + else + { + int i; + pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1) + * sizeof (char *)); + if (pglob->gl_pathv == NULL) + return GLOB_NOSPACE; + + for (i = 0; i <= pglob->gl_offs; ++i) + pglob->gl_pathv[i] = NULL; + } } - oldcount = pglob->gl_pathc; + oldcount = pglob->gl_pathc + pglob->gl_offs; #ifndef VMS if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') @@ -785,45 +809,42 @@ glob (pattern, flags, errfunc, pglob) if (filename == NULL) { struct stat st; +#ifdef HAVE_STAT64 + struct stat64 st64; +#endif /* Return the directory if we don't check for error or if it exists. */ if ((flags & GLOB_NOCHECK) || (((flags & GLOB_ALTDIRFUNC) - ? (*pglob->gl_stat) (dirname, &st) - : __stat (dirname, &st)) == 0 - && S_ISDIR (st.st_mode))) + ? ((*pglob->gl_stat) (dirname, &st) == 0 + && S_ISDIR (st.st_mode)) + : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode))))) { + int newcount = pglob->gl_pathc + pglob->gl_offs; + pglob->gl_pathv = (char **) realloc (pglob->gl_pathv, - (pglob->gl_pathc + - ((flags & GLOB_DOOFFS) ? - pglob->gl_offs : 0) + - 1 + 1) * - sizeof (char *)); + (newcount + 1 + 1) * sizeof (char *)); if (pglob->gl_pathv == NULL) return GLOB_NOSPACE; - if (flags & GLOB_DOOFFS) - while (pglob->gl_pathc < pglob->gl_offs) - pglob->gl_pathv[pglob->gl_pathc++] = NULL; - #if defined HAVE_STRDUP || defined _LIBC - pglob->gl_pathv[pglob->gl_pathc] = strdup (dirname); + pglob->gl_pathv[newcount] = strdup (dirname); #else { size_t len = strlen (dirname) + 1; char *dircopy = malloc (len); if (dircopy != NULL) - pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname, - len); + pglob->gl_pathv[newcount] = memcpy (dircopy, dirname, len); } #endif - if (pglob->gl_pathv[pglob->gl_pathc] == NULL) + if (pglob->gl_pathv[newcount] == NULL) { free (pglob->gl_pathv); return GLOB_NOSPACE; } - pglob->gl_pathv[++pglob->gl_pathc] = NULL; + pglob->gl_pathv[++newcount] = NULL; + ++pglob->gl_pathc; pglob->gl_flags = flags; return 0; @@ -883,8 +904,7 @@ glob (pattern, flags, errfunc, pglob) old_pathc = pglob->gl_pathc; status = glob_in_dir (filename, dirs.gl_pathv[i], - ((flags | GLOB_APPEND) - & ~(GLOB_NOCHECK | GLOB_ERR)), + ((flags | GLOB_APPEND) & ~GLOB_NOCHECK), errfunc, pglob); if (status == GLOB_NOMATCH) /* No matches in this directory. Try the next. */ @@ -899,7 +919,7 @@ glob (pattern, flags, errfunc, pglob) /* Stick the directory on the front of each name. */ if (prefix_array (dirs.gl_pathv[i], - &pglob->gl_pathv[old_pathc], + &pglob->gl_pathv[old_pathc + pglob->gl_offs], pglob->gl_pathc - old_pathc)) { globfree (&dirs); @@ -911,36 +931,33 @@ glob (pattern, flags, errfunc, pglob) flags |= GLOB_MAGCHAR; /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls. - But if we have not found any matching entry and thie GLOB_NOCHECK + But if we have not found any matching entry and the GLOB_NOCHECK flag was set we must return the list consisting of the disrectory names followed by the filename. */ - if (pglob->gl_pathc == oldcount) + if (pglob->gl_pathc + pglob->gl_offs == oldcount) { /* No matches. */ if (flags & GLOB_NOCHECK) { size_t filename_len = strlen (filename) + 1; char **new_pathv; + int newcount = pglob->gl_pathc + pglob->gl_offs; struct stat st; +#ifdef HAVE_STAT64 + struct stat64 st64; +#endif /* This is an pessimistic guess about the size. */ pglob->gl_pathv = (char **) realloc (pglob->gl_pathv, - (pglob->gl_pathc + - ((flags & GLOB_DOOFFS) ? - pglob->gl_offs : 0) + - dirs.gl_pathc + 1) * - sizeof (char *)); + (newcount + dirs.gl_pathc + 1) + * sizeof (char *)); if (pglob->gl_pathv == NULL) { globfree (&dirs); return GLOB_NOSPACE; } - if (flags & GLOB_DOOFFS) - while (pglob->gl_pathc < pglob->gl_offs) - pglob->gl_pathv[pglob->gl_pathc++] = NULL; - for (i = 0; i < dirs.gl_pathc; ++i) { const char *dir = dirs.gl_pathv[i]; @@ -948,14 +965,16 @@ glob (pattern, flags, errfunc, pglob) /* First check whether this really is a directory. */ if (((flags & GLOB_ALTDIRFUNC) - ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0 - || !S_ISDIR (st.st_mode)) + ? ((*pglob->gl_stat) (dir, &st) != 0 + || !S_ISDIR (st.st_mode)) + : (__stat64 (dir, &st64) != 0 + || !S_ISDIR (st64.st_mode)))) /* No directory, ignore this entry. */ continue; - pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1 - + filename_len); - if (pglob->gl_pathv[pglob->gl_pathc] == NULL) + pglob->gl_pathv[newcount] = malloc (dir_len + 1 + + filename_len); + if (pglob->gl_pathv[newcount] == NULL) { globfree (&dirs); globfree (pglob); @@ -963,25 +982,26 @@ glob (pattern, flags, errfunc, pglob) } #ifdef HAVE_MEMPCPY - mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc], + mempcpy (mempcpy (mempcpy (pglob->gl_pathv[newcount], dir, dir_len), "/", 1), filename, filename_len); #else - memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len); - pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/'; - memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1], + memcpy (pglob->gl_pathv[newcount], dir, dir_len); + pglob->gl_pathv[newcount][dir_len] = '/'; + memcpy (&pglob->gl_pathv[newcount][dir_len + 1], filename, filename_len); #endif ++pglob->gl_pathc; + ++newcount; } - pglob->gl_pathv[pglob->gl_pathc] = NULL; + pglob->gl_pathv[newcount] = NULL; pglob->gl_flags = flags; /* Now we know how large the gl_pathv vector must be. */ new_pathv = (char **) realloc (pglob->gl_pathv, - ((pglob->gl_pathc + 1) + ((newcount + 1) * sizeof (char *))); if (new_pathv != NULL) pglob->gl_pathv = new_pathv; @@ -994,6 +1014,8 @@ glob (pattern, flags, errfunc, pglob) } else { + int old_pathc = pglob->gl_pathc; + status = glob_in_dir (filename, dirname, flags, errfunc, pglob); if (status != 0) return status; @@ -1001,14 +1023,9 @@ glob (pattern, flags, errfunc, pglob) if (dirlen > 0) { /* Stick the directory on the front of each name. */ - int ignore = oldcount; - - if ((flags & GLOB_DOOFFS) && ignore < pglob->gl_offs) - ignore = pglob->gl_offs; - if (prefix_array (dirname, - &pglob->gl_pathv[ignore], - pglob->gl_pathc - ignore)) + &pglob->gl_pathv[old_pathc + pglob->gl_offs], + pglob->gl_pathc - old_pathc)) { globfree (pglob); return GLOB_NOSPACE; @@ -1021,11 +1038,16 @@ glob (pattern, flags, errfunc, pglob) /* Append slashes to directory names. */ int i; struct stat st; - for (i = oldcount; i < pglob->gl_pathc; ++i) +#ifdef HAVE_STAT64 + struct stat64 st64; +#endif + + for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i) if (((flags & GLOB_ALTDIRFUNC) - ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st) - : __stat (pglob->gl_pathv[i], &st)) == 0 - && S_ISDIR (st.st_mode)) + ? ((*pglob->gl_stat) (pglob->gl_pathv[i], &st) == 0 + && S_ISDIR (st.st_mode)) + : (__stat64 (pglob->gl_pathv[i], &st64) == 0 + && S_ISDIR (st64.st_mode)))) { size_t len = strlen (pglob->gl_pathv[i]) + 2; char *new = realloc (pglob->gl_pathv[i], len); @@ -1042,13 +1064,8 @@ glob (pattern, flags, errfunc, pglob) if (!(flags & GLOB_NOSORT)) { /* Sort the vector. */ - int non_sort = oldcount; - - if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount) - non_sort = pglob->gl_offs; - - qsort ((__ptr_t) &pglob->gl_pathv[non_sort], - pglob->gl_pathc - non_sort, + qsort ((__ptr_t) &pglob->gl_pathv[oldcount], + pglob->gl_pathc + pglob->gl_offs - oldcount, sizeof (char *), collated_compare); } @@ -1065,8 +1082,8 @@ globfree (pglob) { register int i; for (i = 0; i < pglob->gl_pathc; ++i) - if (pglob->gl_pathv[i] != NULL) - free ((__ptr_t) pglob->gl_pathv[i]); + if (pglob->gl_pathv[pglob->gl_offs + i] != NULL) + free ((__ptr_t) pglob->gl_pathv[pglob->gl_offs + i]); free ((__ptr_t) pglob->gl_pathv); } } @@ -1214,7 +1231,6 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) glob_t *pglob; { __ptr_t stream = NULL; - struct globlink { struct globlink *next; @@ -1226,38 +1242,42 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) int save; meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)); - if (meta == 0) + if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) { - if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)) - /* We need not do any tests. The PATTERN contains no meta - characters and we must not return an error therefore the - result will always contain exactly one name. */ - flags |= GLOB_NOCHECK; - else - { - /* Since we use the normal file functions we can also use stat() - to verify the file is there. */ - struct stat st; - size_t patlen = strlen (pattern); - size_t dirlen = strlen (directory); - char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1); + /* We need not do any tests. The PATTERN contains no meta + characters and we must not return an error therefore the + result will always contain exactly one name. */ + flags |= GLOB_NOCHECK; + nfound = 0; + } + else if (meta == 0 && + ((flags & GLOB_NOESCAPE) || strchr(pattern, '\\') == NULL)) + { + /* Since we use the normal file functions we can also use stat() + to verify the file is there. */ + struct stat st; +# ifdef HAVE_STAT64 + struct stat64 st64; +# endif + size_t patlen = strlen (pattern); + size_t dirlen = strlen (directory); + char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1); # ifdef HAVE_MEMPCPY - mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), - "/", 1), - pattern, patlen + 1); + mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), + "/", 1), + pattern, patlen + 1); # else - memcpy (fullname, directory, dirlen); - fullname[dirlen] = '/'; - memcpy (&fullname[dirlen + 1], pattern, patlen + 1); + memcpy (fullname, directory, dirlen); + fullname[dirlen] = '/'; + memcpy (&fullname[dirlen + 1], pattern, patlen + 1); # endif - if (((flags & GLOB_ALTDIRFUNC) - ? (*pglob->gl_stat) (fullname, &st) - : __stat (fullname, &st)) == 0) - /* We found this file to be existing. Now tell the rest - of the function to copy this name into the result. */ - flags |= GLOB_NOCHECK; - } + if (((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_stat) (fullname, &st) + : __stat64 (fullname, &st64)) == 0) + /* We found this file to be existing. Now tell the rest + of the function to copy this name into the result. */ + flags |= GLOB_NOCHECK; nfound = 0; } @@ -1368,20 +1388,14 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) { pglob->gl_pathv = (char **) realloc (pglob->gl_pathv, - (pglob->gl_pathc + - ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + - nfound + 1) * - sizeof (char *)); + (pglob->gl_pathc + pglob->gl_offs + nfound + 1) + * sizeof (char *)); if (pglob->gl_pathv == NULL) goto memory_error; - if (flags & GLOB_DOOFFS) - while (pglob->gl_pathc < pglob->gl_offs) - pglob->gl_pathv[pglob->gl_pathc++] = NULL; - for (; names != NULL; names = names->next) - pglob->gl_pathv[pglob->gl_pathc++] = names->name; - pglob->gl_pathv[pglob->gl_pathc] = NULL; + pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc++] = names->name; + pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; pglob->gl_flags = flags; } |