diff options
author | vincentdarley <vincentdarley@noemail.net> | 2003-02-10 10:26:19 (GMT) |
---|---|---|
committer | vincentdarley <vincentdarley@noemail.net> | 2003-02-10 10:26:19 (GMT) |
commit | fbdc918e2a9aa85153ac460ab5edf00e8c2c9605 (patch) | |
tree | 6b5cf965bfd562f73bbc5ea7df396db96fb238cd /unix | |
parent | a16348cd7741beb6e917e7b5b1a8c22162779965 (diff) | |
download | tcl-fbdc918e2a9aa85153ac460ab5edf00e8c2c9605.zip tcl-fbdc918e2a9aa85153ac460ab5edf00e8c2c9605.tar.gz tcl-fbdc918e2a9aa85153ac460ab5edf00e8c2c9605.tar.bz2 |
filesystem speed up round 2
FossilOrigin-Name: 1f9c0e4f03a1887a627fd66e6affceebf25f9519
Diffstat (limited to 'unix')
-rw-r--r-- | unix/tclUnixFCmd.c | 50 | ||||
-rw-r--r-- | unix/tclUnixFile.c | 94 |
2 files changed, 79 insertions, 65 deletions
diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index 5a9525f..a5b6792 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclUnixFCmd.c,v 1.26 2003/02/04 17:06:52 vincentdarley Exp $ + * RCS: @(#) $Id: tclUnixFCmd.c,v 1.27 2003/02/10 10:26:26 vincentdarley Exp $ * * Portions of this code were derived from NetBSD source code which has * the following copyright notice: @@ -839,8 +839,9 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr) } while ((dirEntPtr = TclOSreaddir(dirPtr)) != NULL) { /* INTL: Native. */ - if ((strcmp(dirEntPtr->d_name, ".") == 0) - || (strcmp(dirEntPtr->d_name, "..") == 0)) { + if ((dirEntPtr->d_name[0] == '.') + && ((dirEntPtr->d_name[1] == '\0') + || (strcmp(dirEntPtr->d_name, "..") == 0))) { continue; } @@ -1652,7 +1653,6 @@ GetModeFromPermString(interp, modeStringPtr, modePtr) * *--------------------------------------------------------------------------- */ - int TclpObjNormalizePath(interp, pathPtr, nextCheckpoint) Tcl_Interp *interp; @@ -1668,9 +1668,29 @@ TclpObjNormalizePath(interp, pathPtr, nextCheckpoint) Tcl_DString ds; CONST char *nativePath; #endif + /* + * We add '1' here because if nextCheckpoint is zero we know + * that '/' exists, and if it isn't zero, it must point at + * a directory separator which we also know exists. + */ + currentPathEndPosition = path + nextCheckpoint + 1; - currentPathEndPosition = path + nextCheckpoint; - +#ifndef NO_REALPATH + /* For speed, try to get the entire path in one go */ + if (nextCheckpoint == 0) { + char *lastDir = strrchr(currentPathEndPosition, '/'); + if (lastDir != NULL) { + nativePath = Tcl_UtfToExternalDString(NULL, path, + lastDir - path, &ds); + if (Realpath(nativePath, normPath) != NULL) { + nextCheckpoint = lastDir - path; + goto wholeStringOk; + } + } + } + /* Else do it the slow way */ +#endif + while (1) { cur = *currentPathEndPosition; if ((cur == '/') && (path != currentPathEndPosition)) { @@ -1713,12 +1733,25 @@ TclpObjNormalizePath(interp, pathPtr, nextCheckpoint) nativePath = Tcl_UtfToExternalDString(NULL, path, nextCheckpoint, &ds); if (Realpath(nativePath, normPath) != NULL) { + int newNormLen; + wholeStringOk: + newNormLen = strlen(normPath); + if ((newNormLen == Tcl_DStringLength(&ds)) + && (strcmp(normPath, nativePath) == 0)) { + /* String is unchanged */ + Tcl_DStringFree(&ds); + if (path[nextCheckpoint] != '\0') { + nextCheckpoint++; + } + return nextCheckpoint; + } + /* * Free up the native path and put in its place the * converted, normalized path. */ Tcl_DStringFree(&ds); - Tcl_ExternalToUtfDString(NULL, normPath, (int) strlen(normPath), &ds); + Tcl_ExternalToUtfDString(NULL, normPath, (int) newNormLen, &ds); if (path[nextCheckpoint] != '\0') { /* not at end, append remaining path */ @@ -1745,3 +1778,6 @@ TclpObjNormalizePath(interp, pathPtr, nextCheckpoint) return nextCheckpoint; } + + + diff --git a/unix/tclUnixFile.c b/unix/tclUnixFile.c index 2dacb64..62f9a3a 100644 --- a/unix/tclUnixFile.c +++ b/unix/tclUnixFile.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclUnixFile.c,v 1.29 2003/01/09 10:38:34 vincentdarley Exp $ + * RCS: @(#) $Id: tclUnixFile.c,v 1.30 2003/02/10 10:26:26 vincentdarley Exp $ */ #include "tclInt.h" @@ -217,25 +217,25 @@ TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types) if (pattern == NULL || (*pattern == '\0')) { /* Match a file directly */ - CONST char *native = (CONST char*) Tcl_FSGetNativePath(pathPtr); + native = (CONST char*) Tcl_FSGetNativePath(pathPtr); if (NativeMatchType(native, types)) { Tcl_ListObjAppendElement(interp, resultPtr, pathPtr); } return TCL_OK; } else { - CONST char *fname, *dirName; DIR *d; - Tcl_DString ds; - Tcl_StatBuf statBuf; + Tcl_DirEntry *entryPtr; + CONST char *dirName; + int dirLength; int matchHidden; int nativeDirLen; - int result = TCL_OK; - Tcl_DString dsOrig; - int baseLength; - + Tcl_StatBuf statBuf; + Tcl_DString ds; /* native encoding of dir */ + Tcl_DString dsOrig; /* utf-8 encoding of dir */ + Tcl_DStringInit(&dsOrig); - Tcl_DStringAppend(&dsOrig, Tcl_GetString(fileNamePtr), -1); - baseLength = Tcl_DStringLength(&dsOrig); + dirName = Tcl_GetStringFromObj(fileNamePtr, &dirLength); + Tcl_DStringAppend(&dsOrig, dirName, dirLength); /* * Make sure that the directory part of the name really is a @@ -245,27 +245,16 @@ TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types) * otherwise "glob foo.c" would return "./foo.c". */ - if (baseLength == 0) { + if (dirLength == 0) { dirName = "."; } else { dirName = Tcl_DStringValue(&dsOrig); /* Make sure we have a trailing directory delimiter */ - if (dirName[baseLength-1] != '/') { + if (dirName[dirLength-1] != '/') { dirName = Tcl_DStringAppend(&dsOrig, "/", 1); - baseLength++; + dirLength++; } } - - /* - * Check to see if the pattern needs to compare with hidden files. - */ - - if ((pattern[0] == '.') - || ((pattern[0] == '\\') && (pattern[1] == '.'))) { - matchHidden = 1; - } else { - matchHidden = 0; - } /* * Now open the directory for reading and iterate over the contents. @@ -282,41 +271,32 @@ TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types) d = opendir(native); /* INTL: Native. */ if (d == NULL) { - char savedChar = '\0'; - Tcl_ResetResult(interp); Tcl_DStringFree(&ds); - - /* - * Strip off a trailing '/' if necessary, before reporting the error. - */ - - if (baseLength > 0) { - savedChar = (Tcl_DStringValue(&dsOrig))[baseLength-1]; - if (savedChar == '/') { - (Tcl_DStringValue(&dsOrig))[baseLength-1] = '\0'; - } - } + Tcl_ResetResult(interp); Tcl_AppendResult(interp, "couldn't read directory \"", Tcl_DStringValue(&dsOrig), "\": ", Tcl_PosixError(interp), (char *) NULL); - if (baseLength > 0) { - (Tcl_DStringValue(&dsOrig))[baseLength-1] = savedChar; - } Tcl_DStringFree(&dsOrig); return TCL_ERROR; } nativeDirLen = Tcl_DStringLength(&ds); - while (1) { + /* + * Check to see if the pattern needs to compare with hidden files. + */ + + if ((pattern[0] == '.') + || ((pattern[0] == '\\') && (pattern[1] == '.'))) { + matchHidden = 1; + } else { + matchHidden = 0; + } + + while ((entryPtr = TclOSreaddir(d)) != NULL) { /* INTL: Native. */ Tcl_DString utfDs; - CONST char *utf; - Tcl_DirEntry *entryPtr; + CONST char *utfname; - entryPtr = TclOSreaddir(d); /* INTL: Native. */ - if (entryPtr == NULL) { - break; - } if (types != NULL && (types->perm & TCL_GLOB_PERM_HIDDEN)) { /* * We explicitly asked for hidden files, so turn around @@ -338,22 +318,20 @@ TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types) * and pattern. If so, add the file to the result. */ - utf = Tcl_ExternalToUtfDString(NULL, entryPtr->d_name, -1, &utfDs); - if (Tcl_StringMatch(utf, pattern) != 0) { + utfname = Tcl_ExternalToUtfDString(NULL, entryPtr->d_name, + -1, &utfDs); + if (Tcl_StringCaseMatch(utfname, pattern, 0)) { int typeOk = 1; - Tcl_DStringSetLength(&dsOrig, baseLength); - Tcl_DStringAppend(&dsOrig, utf, -1); - fname = Tcl_DStringValue(&dsOrig); if (types != NULL) { - char *nativeEntry; Tcl_DStringSetLength(&ds, nativeDirLen); - nativeEntry = Tcl_DStringAppend(&ds, entryPtr->d_name, -1); - typeOk = NativeMatchType(nativeEntry, types); + native = Tcl_DStringAppend(&ds, entryPtr->d_name, -1); + typeOk = NativeMatchType(native, types); } if (typeOk) { Tcl_ListObjAppendElement(interp, resultPtr, - Tcl_NewStringObj(fname, Tcl_DStringLength(&dsOrig))); + TclNewFSPathObj(pathPtr, utfname, + Tcl_DStringLength(&utfDs))); } } Tcl_DStringFree(&utfDs); @@ -362,7 +340,7 @@ TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types) closedir(d); Tcl_DStringFree(&ds); Tcl_DStringFree(&dsOrig); - return result; + return TCL_OK; } } static int |