Index: tclUnixFile.c =================================================================== RCS file: /cvsroot/tcl/tcl/unix/tclUnixFile.c,v retrieving revision 1.10 diff -U3 -r1.10 tclUnixFile.c --- tclUnixFile.c 2001/07/31 19:12:07 1.10 +++ tclUnixFile.c 2001/08/22 10:46:25 @@ -315,10 +315,8 @@ } /* - * Now check to see if the file matches. If there are more - * characters to be processed, then ensure matching files are - * directories before calling TclDoGlob. Otherwise, just add - * the file to the result. + * Now check to see if the file matches, according to both type + * and pattern. If so, add the file to the result. */ utf = Tcl_ExternalToUtfDString(NULL, entryPtr->d_name, -1, &ds); @@ -329,17 +327,29 @@ Tcl_DStringAppend(&dsOrig, utf, -1); fname = Tcl_DStringValue(&dsOrig); if (types != NULL) { - if (types->perm != 0) { - struct stat buf; + struct stat buf; + if (types->perm != 0) { if (TclpStat(fname, &buf) != 0) { - panic("stat failed on known file"); + /* + * Either the file has disappeared between the + * 'readdir' call and the 'TclpStat' call, or + * the file is a link to a file which doesn't + * exist (which we could ascertain with + * TclpLstat), or there is some other strange + * problem. In all these cases, we define this + * to mean the file does not match any defined + * permission, and therefore it is not + * added to the list of files to return. + */ + typeOk = 0; } + /* * readonly means that there are NO write permissions * (even for user), but execute is OK for anybody */ - if ( + if (typeOk && ( ((types->perm & TCL_GLOB_PERM_RONLY) && (buf.st_mode & (S_IWOTH|S_IWGRP|S_IWUSR))) || ((types->perm & TCL_GLOB_PERM_R) && @@ -348,17 +358,19 @@ (TclpAccess(fname, W_OK) != 0)) || ((types->perm & TCL_GLOB_PERM_X) && (TclpAccess(fname, X_OK) != 0)) - ) { + )) { typeOk = 0; } } if (typeOk && (types->type != 0)) { - struct stat buf; - /* - * We must match at least one flag to be listed - */ - typeOk = 0; - if (TclpLstat(fname, &buf) >= 0) { + if (types->perm == 0) { + /* We haven't yet done a stat on the file */ + if (TclpStat(fname, &buf) != 0) { + /* Posix error occurred */ + typeOk = 0; + } + } + if (typeOk) { /* * In order bcdpfls as in 'find -t' */ @@ -373,19 +385,24 @@ S_ISFIFO(buf.st_mode)) || ((types->type & TCL_GLOB_TYPE_FILE) && S_ISREG(buf.st_mode)) -#ifdef S_ISLNK - || ((types->type & TCL_GLOB_TYPE_LINK) && - S_ISLNK(buf.st_mode)) -#endif #ifdef S_ISSOCK || ((types->type & TCL_GLOB_TYPE_SOCK) && S_ISSOCK(buf.st_mode)) #endif ) { - typeOk = 1; + /* Do nothing -- this file is ok */ + } else { + typeOk = 0; +#ifdef S_ISLNK + if (types->type & TCL_GLOB_TYPE_LINK) { + if (TclpLstat(fname, &buf) == 0) { + if (S_ISLNK(buf.st_mode)) { + typeOk = 1; + } + } + } +#endif } - } else { - /* Posix error occurred */ } } }