From: Ulrich Drepper Date: Wed, 12 Aug 1998 12:30:23 +0000 (+0000) Subject: Carry over changes from 2.1 which increase the speed and fix some bugs. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=37c67432506b313c0719bdca9c65cb41c5967792;p=thirdparty%2Fglibc.git Carry over changes from 2.1 which increase the speed and fix some bugs. --- diff --git a/posix/glob.c b/posix/glob.c index 36282805efb..5fc094ebe70 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -155,6 +155,12 @@ extern void abort (), exit (); #endif /* Standard headers. */ +#ifdef HAVE_GETLOGIN_R +extern int getlogin_r __P ((char *, size_t)); +#else +extern char *getlogin __P ((void)); +#endif + #ifndef ANSI_STRING # ifndef bzero @@ -180,7 +186,6 @@ extern void bcopy (); # define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len) #endif - #ifndef __GNU_LIBRARY__ # ifdef __GNUC__ __inline @@ -239,6 +244,17 @@ extern char *alloca (); # endif #endif +#ifdef _LIBC +# undef strdup +# define strdup(str) __strdup (str) +# define sysconf(id) __sysconf (id) +# define closedir(dir) __closedir (dir) +# define opendir(name) __opendir (name) +# define readdir(str) __readdir (str) +# define getpwnam_r(name, bufp, buf, len, res) \ + __getpwnam_r (name, bufp, buf, len, res) +#endif + #if !(defined STDC_HEADERS || defined __GNU_LIBRARY__) # undef size_t # define size_t unsigned int @@ -246,21 +262,25 @@ extern char *alloca (); /* Some system header files erroneously define these. We want our own definitions from to take precedence. */ -#undef FNM_PATHNAME -#undef FNM_NOESCAPE -#undef FNM_PERIOD +#ifndef __GNU_LIBRARY__ +# undef FNM_PATHNAME +# undef FNM_NOESCAPE +# undef FNM_PERIOD +#endif #include /* Some system header files erroneously define these. We want our own definitions from to take precedence. */ -#undef GLOB_ERR -#undef GLOB_MARK -#undef GLOB_NOSORT -#undef GLOB_DOOFFS -#undef GLOB_NOCHECK -#undef GLOB_APPEND -#undef GLOB_NOESCAPE -#undef GLOB_PERIOD +#ifndef __GNU_LIBRARY__ +# undef GLOB_ERR +# undef GLOB_MARK +# undef GLOB_NOSORT +# undef GLOB_DOOFFS +# undef GLOB_NOCHECK +# undef GLOB_APPEND +# undef GLOB_NOESCAPE +# undef GLOB_PERIOD +#endif #include static @@ -337,7 +357,7 @@ glob (pattern, flags, errfunc, pglob) glob_t *pglob; { const char *filename; - char *dirname; + const char *dirname; size_t dirlen; int status; int oldcount; @@ -477,43 +497,98 @@ glob (pattern, flags, errfunc, pglob) /* Find the filename. */ filename = strrchr (pattern, '/'); +#if defined __MSDOS__ || defined WINDOWS32 + /* The case of "d:pattern". Since `:' is not allowed in + file names, we can safely assume that wherever it + happens in pattern, it signals the filename part. This + is so we could some day support patterns like "[a-z]:foo". */ + if (filename == NULL) + filename = strchr (pattern, ':'); +#endif /* __MSDOS__ || WINDOWS32 */ if (filename == NULL) { - filename = pattern; + /* This can mean two things: a simple name or "~name". The later + case is nothing but a notation for a directory. */ + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') + { + dirname = pattern; + dirlen = strlen (pattern); + + /* Set FILENAME to NULL as a special flag. This is ugly but + other solutions would require much more code. We test for + this special case below. */ + filename = NULL; + } + else + { + filename = pattern; #ifdef _AMIGA - dirname = (char *) ""; + dirname = ""; #else - dirname = (char *) "."; + dirname = "."; #endif - dirlen = 0; + dirlen = 0; + } } else if (filename == pattern) { /* "/pattern". */ - dirname = (char *) "/"; + dirname = "/"; dirlen = 1; ++filename; } else { + char *newp; dirlen = filename - pattern; - dirname = (char *) __alloca (dirlen + 1); +#if defined __MSDOS__ || defined WINDOWS32 + if (*filename == ':' + || (filename > pattern + 1 && filename[-1] == ':')) + { + char *drive_spec; + + ++dirlen; + drive_spec = (char *) __alloca (dirlen + 1); #ifdef HAVE_MEMPCPY - *((char *) mempcpy (dirname, pattern, dirlen)) = '\0'; + *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0'; #else - memcpy (dirname, pattern, dirlen); - dirname[dirlen] = '\0'; + memcpy (drive_spec, pattern, dirlen); + drive_spec[dirlen] = '\0'; +#endif + /* For now, disallow wildcards in the drive spec, to + prevent infinite recursion in glob. */ + if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE))) + return GLOB_NOMATCH; + /* If this is "d:pattern", we need to copy `:' to DIRNAME + as well. If it's "d:/pattern", don't remove the slash + from "d:/", since "d:" and "d:/" are not the same.*/ + } #endif + newp = (char *) __alloca (dirlen + 1); +#ifdef HAVE_MEMPCPY + *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; +#else + memcpy (newp, pattern, dirlen); + newp[dirlen] = '\0'; +#endif + dirname = newp; ++filename; - } - if (filename[0] == '\0' && dirlen > 1) - /* "pattern/". Expand "pattern", appending slashes. */ - { - int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); - if (val == 0) - pglob->gl_flags = (pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK); - return val; + if (filename[0] == '\0' +#if defined __MSDOS__ || defined WINDOWS32 + && dirname[dirlen - 1] != ':' + && (dirlen < 3 || dirname[dirlen - 2] != ':' + || dirname[dirlen - 1] != '/') +#endif + && dirlen > 1) + /* "pattern/". Expand "pattern", appending slashes. */ + { + int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); + if (val == 0) + pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) + | (flags & GLOB_MARK)); + return val; + } } if (!(flags & GLOB_APPEND)) @@ -525,12 +600,12 @@ glob (pattern, flags, errfunc, pglob) oldcount = pglob->gl_pathc; #ifndef VMS - if ((flags & GLOB_TILDE) && dirname[0] == '~') + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') { if (dirname[1] == '\0' || dirname[1] == '/') { /* Look up home directory. */ - char *home_dir = getenv ("HOME"); + const char *home_dir = getenv ("HOME"); # ifdef _AMIGA if (home_dir == NULL || home_dir[0] == '\0') home_dir = "SYS:"; @@ -542,37 +617,38 @@ glob (pattern, flags, errfunc, pglob) if (home_dir == NULL || home_dir[0] == '\0') { int success; + char *name; # if defined HAVE_GETLOGIN_R || defined _LIBC - extern int getlogin_r __P ((char *, size_t)); size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1; - char *name; if (buflen == 0) /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try a moderate value. */ - buflen = 16; + buflen = 20; name = (char *) __alloca (buflen); success = getlogin_r (name, buflen) >= 0; # else - extern char *getlogin __P ((void)); - char *name; - success = (name = getlogin ()) != NULL; # endif if (success) { + struct passwd *p; # if defined HAVE_GETPWNAM_R || defined _LIBC size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX); char *pwtmpbuf; - struct passwd pwbuf, *p; + struct passwd pwbuf; + if (pwbuflen == -1) + /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. + Try a moderate value. */ + pwbuflen = 1024; pwtmpbuf = (char *) __alloca (pwbuflen); - success = (__getpwnam_r (name, &pwbuf, pwtmpbuf, - pwbuflen, &p) >= 0); + success = (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) + >= 0); # else - struct passwd *p = getpwnam (name); + p = getpwnam (name); success = p != NULL; # endif if (success) @@ -580,7 +656,10 @@ glob (pattern, flags, errfunc, pglob) } } if (home_dir == NULL || home_dir[0] == '\0') - home_dir = (char *) "~"; /* No luck. */ + if (flags & GLOB_TILDE_CHECK) + return GLOB_NOMATCH; + else + home_dir = "~"; /* No luck. */ # endif /* WINDOWS32 */ # endif /* Now construct the full directory. */ @@ -605,35 +684,45 @@ glob (pattern, flags, errfunc, pglob) else { char *end_name = strchr (dirname, '/'); - char *user_name; - char *home_dir; + const char *user_name; + const char *home_dir; if (end_name == NULL) user_name = dirname + 1; else { - user_name = (char *) __alloca (end_name - dirname); + char *newp; + newp = (char *) __alloca (end_name - dirname); # ifdef HAVE_MEMPCPY - *((char *) mempcpy (user_name, dirname + 1, end_name - dirname)) + *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) = '\0'; # else - memcpy (user_name, dirname + 1, end_name - dirname); - user_name[end_name - dirname - 1] = '\0'; + memcpy (newp, dirname + 1, end_name - dirname); + newp[end_name - dirname - 1] = '\0'; # endif + user_name = newp; } /* Look up specific user's home directory. */ { + struct passwd *p; # if defined HAVE_GETPWNAM_R || defined _LIBC size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); - char *pwtmpbuf = (char *) __alloca (buflen); - struct passwd pwbuf, *p; - if (__getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) >= 0) + char *pwtmpbuf; + struct passwd pwbuf; + + if (buflen == -1) + /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a + moderate value. */ + buflen = 1024; + pwtmpbuf = (char *) __alloca (buflen); + + if (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) >= 0) home_dir = p->pw_dir; else home_dir = NULL; # else - struct passwd *p = getpwnam (user_name); + p = getpwnam (user_name); if (p != NULL) home_dir = p->pw_dir; else @@ -657,11 +746,69 @@ glob (pattern, flags, errfunc, pglob) # endif dirname = newp; } + else + if (flags & GLOB_TILDE_CHECK) + /* We have to regard it as an error if we cannot find the + home directory. */ + return GLOB_NOMATCH; } # endif /* Not Amiga && not WINDOWS32. */ } #endif /* Not VMS. */ + /* Now test whether we looked for "~" or "~NAME". In this case we + can give the answer now. */ + if (filename == NULL) + { + struct stat st; + + /* 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_pathv + = (char **) realloc (pglob->gl_pathv, + (pglob->gl_pathc + + ((flags & GLOB_DOOFFS) ? + pglob->gl_offs : 0) + + 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); +#else + { + size_t len = strlen (dirname) + 1; + char *dircopy = malloc (len); + if (dircopy != NULL) + pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname, + len); + } +#endif + if (pglob->gl_pathv[pglob->gl_pathc] == NULL) + { + free (pglob->gl_pathv); + return GLOB_NOSPACE; + } + pglob->gl_pathv[++pglob->gl_pathc] = NULL; + pglob->gl_flags = flags; + + return 0; + } + + /* Not found. */ + return GLOB_NOMATCH; + } + if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE))) { /* The directory name contains metacharacters, so we @@ -727,26 +874,29 @@ 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 + flag was set we must return the list consisting of the disrectory + names followed by the filename. */ if (pglob->gl_pathc == oldcount) /* No matches. */ if (flags & GLOB_NOCHECK) { - size_t len = strlen (pattern) + 1; - char *patcopy = (char *) malloc (len); - if (patcopy == NULL) - return GLOB_NOSPACE; - memcpy (patcopy, pattern, len); + size_t filename_len = strlen (filename) + 1; + char **new_pathv; + struct stat st; + /* 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) + - 1 + 1) * + dirs.gl_pathc + 1) * sizeof (char *)); if (pglob->gl_pathv == NULL) { - free (patcopy); + globfree (&dirs); return GLOB_NOSPACE; } @@ -754,12 +904,55 @@ glob (pattern, flags, errfunc, pglob) while (pglob->gl_pathc < pglob->gl_offs) pglob->gl_pathv[pglob->gl_pathc++] = NULL; - pglob->gl_pathv[pglob->gl_pathc++] = patcopy; + for (i = 0; i < dirs.gl_pathc; ++i) + { + const char *dir = dirs.gl_pathv[i]; + size_t dir_len = strlen (dir); + + /* 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)) + /* 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) + { + globfree (&dirs); + globfree (pglob); + return GLOB_NOSPACE; + } + +#ifdef HAVE_MEMPCPY + mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc], + 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], + filename, filename_len); +#endif + ++pglob->gl_pathc; + } + pglob->gl_pathv[pglob->gl_pathc] = 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) + * sizeof (char *))); + if (new_pathv != NULL) + pglob->gl_pathv = new_pathv; } else return GLOB_NOMATCH; + + globfree (&dirs); } else { @@ -791,10 +984,10 @@ glob (pattern, flags, errfunc, pglob) int i; struct stat st; for (i = oldcount; i < pglob->gl_pathc; ++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)) + if (((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st) + : __stat (pglob->gl_pathv[i], &st)) == 0 + && S_ISDIR (st.st_mode)) { size_t len = strlen (pglob->gl_pathv[i]) + 2; char *new = realloc (pglob->gl_pathv[i], len); @@ -872,11 +1065,31 @@ prefix_array (dirname, array, n) { register size_t i; size_t dirlen = strlen (dirname); +#if defined __MSDOS__ || defined WINDOWS32 + int sep_char = '/'; +# define DIRSEP_CHAR sep_char +#else +# define DIRSEP_CHAR '/' +#endif if (dirlen == 1 && dirname[0] == '/') /* DIRNAME is just "/", so normal prepending would get us "//foo". We want "/foo" instead, so don't prepend any chars from DIRNAME. */ dirlen = 0; +#if defined __MSDOS__ || defined WINDOWS32 + else if (dirlen > 1) + { + if (dirname[dirlen - 1] == '/') + /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */ + --dirlen; + else if (dirname[dirlen - 1] == ':') + { + /* DIRNAME is "d:". Use `:' instead of `/'. */ + --dirlen; + sep_char = ':'; + } + } +#endif for (i = 0; i < n; ++i) { @@ -892,12 +1105,12 @@ prefix_array (dirname, array, n) #ifdef HAVE_MEMPCPY { char *endp = (char *) mempcpy (new, dirname, dirlen); - *endp++ = '/'; + *endp++ = DIRSEP_CHAR; mempcpy (endp, array[i], eltlen); } #else memcpy (new, dirname, dirlen); - new[dirlen] = '/'; + new[dirlen] = DIRSEP_CHAR; memcpy (&new[dirlen + 1], array[i], eltlen); #endif free ((__ptr_t) array[i]); @@ -959,7 +1172,7 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) int (*errfunc) __P ((const char *, int)); glob_t *pglob; { - __ptr_t stream; + __ptr_t stream = NULL; struct globlink { @@ -971,92 +1184,127 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) int meta; int save; - stream = ((flags & GLOB_ALTDIRFUNC) ? - (*pglob->gl_opendir) (directory) : - (__ptr_t) opendir (directory)); - if (stream == NULL) + meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)); + if (meta == 0) { - if ((errfunc != NULL && (*errfunc) (directory, errno)) || - (flags & GLOB_ERR)) - return GLOB_ABORTED; + 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); + +# ifdef HAVE_MEMPCPY + mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), + "/", 1), + pattern, patlen + 1); +# else + 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; + } + nfound = 0; - meta = 0; - } - else if (pattern[0] == '\0') - { - /* This is a special case for matching directories like in - "*a/". */ - names = (struct globlink *) __alloca (sizeof (struct globlink)); - names->name = (char *) malloc (1); - if (names->name == NULL) - goto memory_error; - names->name[0] = '\0'; - names->next = NULL; - nfound = 1; - meta = 0; } else { - nfound = 0; - meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)); - if(meta) - flags |= GLOB_MAGCHAR; - - while (1) + if (pattern[0] == '\0') { - const char *name; - size_t len; - struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ? - (*pglob->gl_readdir) (stream) : - readdir ((DIR *) stream)); - if (d == NULL) - break; - if (! REAL_DIR_ENTRY (d)) - continue; + /* This is a special case for matching directories like in + "*a/". */ + names = (struct globlink *) __alloca (sizeof (struct globlink)); + names->name = (char *) malloc (1); + if (names->name == NULL) + goto memory_error; + names->name[0] = '\0'; + names->next = NULL; + nfound = 1; + meta = 0; + } + else + { + stream = ((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_opendir) (directory) + : (__ptr_t) opendir (directory)); + if (stream == NULL) + { + if ((errfunc != NULL && (*errfunc) (directory, errno)) + || (flags & GLOB_ERR)) + return GLOB_ABORTED; + nfound = 0; + meta = 0; + } + else + { + int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) + | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) +#if defined _AMIGA || defined VMS + | FNM_CASEFOLD +#endif + ); + nfound = 0; + flags |= GLOB_MAGCHAR; + + while (1) + { + const char *name; + size_t len; + struct dirent *d = ((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_readdir) (stream) + : readdir ((DIR *) stream)); + if (d == NULL) + break; + if (! REAL_DIR_ENTRY (d)) + continue; #ifdef HAVE_D_TYPE - /* If we shall match only directories use the information - provided by the dirent call if possible. */ - if ((flags & GLOB_ONLYDIR) - && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR) - continue; + /* If we shall match only directories use the information + provided by the dirent call if possible. */ + if ((flags & GLOB_ONLYDIR) + && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR) + continue; #endif - name = d->d_name; + name = d->d_name; - if ((!meta && strcmp (pattern, name) == 0) - || fnmatch (pattern, name, - (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) | - ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) -#ifdef _AMIGA - | FNM_CASEFOLD -#endif - ) == 0) - { - struct globlink *new - = (struct globlink *) __alloca (sizeof (struct globlink)); - len = NAMLEN (d); - new->name = (char *) malloc (len + 1); - if (new->name == NULL) - goto memory_error; + if (fnmatch (pattern, name, fnm_flags) == 0) + { + struct globlink *new = (struct globlink *) + __alloca (sizeof (struct globlink)); + len = NAMLEN (d); + new->name = (char *) malloc (len + 1); + if (new->name == NULL) + goto memory_error; #ifdef HAVE_MEMPCPY - *((char *) mempcpy ((__ptr_t) new->name, name, len)) = '\0'; + *((char *) mempcpy ((__ptr_t) new->name, name, len)) + = '\0'; #else - memcpy ((__ptr_t) new->name, name, len); - new->name[len] = '\0'; + memcpy ((__ptr_t) new->name, name, len); + new->name[len] = '\0'; #endif - new->next = names; - names = new; - ++nfound; - if (!meta) - break; + new->next = names; + names = new; + ++nfound; + } + } } } } - if (nfound == 0 && (flags & GLOB_NOMAGIC) && !meta) - flags |= GLOB_NOCHECK; - if (nfound == 0 && (flags & GLOB_NOCHECK)) { size_t len = strlen (pattern); @@ -1097,10 +1345,11 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) } save = errno; - if (flags & GLOB_ALTDIRFUNC) - (*pglob->gl_closedir) (stream); - else - closedir ((DIR *) stream); + if (stream != NULL) + if (flags & GLOB_ALTDIRFUNC) + (*pglob->gl_closedir) (stream); + else + closedir ((DIR *) stream); __set_errno (save); return nfound == 0 ? GLOB_NOMATCH : 0;