diff options
Diffstat (limited to 'win/tclWinFile.c')
-rw-r--r-- | win/tclWinFile.c | 117 |
1 files changed, 46 insertions, 71 deletions
diff --git a/win/tclWinFile.c b/win/tclWinFile.c index 8e52d6d..e09fb79 100644 --- a/win/tclWinFile.c +++ b/win/tclWinFile.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWinFile.c,v 1.49 2003/04/22 23:20:43 andreas_kupries Exp $ + * RCS: @(#) $Id: tclWinFile.c,v 1.50 2003/05/16 01:48:43 hobbs Exp $ */ //#define _WIN32_WINNT 0x0500 @@ -777,97 +777,77 @@ TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types) DWORD attr; HANDLE handle; WIN32_FIND_DATAT data; - CONST char *dirName; /* utf-8 dir name, later - * with pattern appended */ + CONST char *dirName; int dirLength; int matchSpecialDots; - Tcl_DString ds; /* native encoding of dir, also used - * temporarily for other things. */ + Tcl_DString ds; /* native encoding of dir */ Tcl_DString dsOrig; /* utf-8 encoding of dir */ + Tcl_DString dirString; /* utf-8 encoding of dir with \'s */ Tcl_Obj *fileNamePtr; - char lastChar; /* - * Get the normalized path representation - * (the main thing is we dont want any '~' sequences). + * Convert the path to normalized form since some interfaces only + * accept backslashes. Also, ensure that the directory ends with a + * separator character. */ - fileNamePtr = Tcl_FSGetNormalizedPath(interp, pathPtr); + fileNamePtr = Tcl_FSGetTranslatedPath(interp, pathPtr); if (fileNamePtr == NULL) { return TCL_ERROR; } + Tcl_DStringInit(&dsOrig); + dirName = Tcl_GetStringFromObj(fileNamePtr, &dirLength); + Tcl_DStringAppend(&dsOrig, dirName, dirLength); + + Tcl_DStringInit(&dirString); + if (dirLength == 0) { + Tcl_DStringAppend(&dirString, ".\\", 2); + } else { + char *p; + + Tcl_DStringAppend(&dirString, dirName, dirLength); + for (p = Tcl_DStringValue(&dirString); *p != '\0'; p++) { + if (*p == '/') { + *p = '\\'; + } + } + p--; + /* Make sure we have a trailing directory delimiter */ + if ((*p != '\\') && (*p != ':')) { + Tcl_DStringAppend(&dirString, "\\", 1); + Tcl_DStringAppend(&dsOrig, "/", 1); + dirLength++; + } + } + dirName = Tcl_DStringValue(&dirString); /* - * Verify that the specified path exists and - * is actually a directory. + * First verify that the specified path is actually a directory. */ - native = Tcl_FSGetNativePath(pathPtr); - if (native == NULL) { - return TCL_OK; - } + + native = Tcl_WinUtfToTChar(dirName, Tcl_DStringLength(&dirString), + &ds); attr = (*tclWinProcs->getFileAttributesProc)(native); + Tcl_DStringFree(&ds); if ((attr == 0xffffffff) || ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0)) { + Tcl_DStringFree(&dirString); return TCL_OK; } - /* - * Build up the directory name for searching, including - * a trailing directory separator. - */ - - Tcl_DStringInit(&dsOrig); - dirName = Tcl_GetStringFromObj(fileNamePtr, &dirLength); - Tcl_DStringAppend(&dsOrig, dirName, dirLength); - - lastChar = dirName[dirLength -1]; - if ((lastChar != '\\') && (lastChar != '/') && (lastChar != ':')) { - Tcl_DStringAppend(&dsOrig, "/", 1); - dirLength++; - } - dirName = Tcl_DStringValue(&dsOrig); - /* - * We need to check all files in the directory, so we append - * '*.*' to the path, unless the pattern we've been given is - * rather simple, when we can use that instead. + * We need to check all files in the directory, so append a *.* + * to the path. */ - if (strpbrk(pattern, "[]\\") == NULL) { - /* - * The pattern is a simple one containing just '*' and/or '?'. - * This means we can get the OS to help us, by passing - * it the pattern. - */ - dirName = Tcl_DStringAppend(&dsOrig, pattern, -1); - } else { - dirName = Tcl_DStringAppend(&dsOrig, "*.*", 3); - } + dirName = Tcl_DStringAppend(&dirString, "*.*", 3); native = Tcl_WinUtfToTChar(dirName, -1, &ds); - if (tclWinProcs->findFirstFileExProc == NULL - || (types == NULL) - || (types->type != TCL_GLOB_TYPE_DIR)) { - handle = (*tclWinProcs->findFirstFileProc)(native, &data); - } else { - /* We can be more efficient, for pure directory requests */ - handle = (*tclWinProcs->findFirstFileExProc)(native, - FindExInfoStandard, &data, - FindExSearchLimitToDirectories, NULL, 0); - } + handle = (*tclWinProcs->findFirstFileProc)(native, &data); Tcl_DStringFree(&ds); if (handle == INVALID_HANDLE_VALUE) { - DWORD err = GetLastError(); - if (err == ERROR_FILE_NOT_FOUND) { - /* - * We used our 'pattern' above, and matched nothing - * This means we just return TCL_OK, indicating - * no results found. - */ - Tcl_DStringFree(&dsOrig); - return TCL_OK; - } - TclWinConvertError(err); + Tcl_DStringFree(&dirString); + TclWinConvertError(GetLastError()); Tcl_ResetResult(interp); Tcl_AppendResult(interp, "couldn't read directory \"", Tcl_DStringValue(&dsOrig), "\": ", @@ -876,12 +856,6 @@ TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types) return TCL_ERROR; } - /* - * We may use this later, so we must restore it to its - * length including the directory delimiter - */ - Tcl_DStringSetLength(&dsOrig, dirLength); - /* * Check to see if the pattern should match the special * . and .. names, referring to the current directory, @@ -975,6 +949,7 @@ TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types) } while ((*tclWinProcs->findNextFileProc)(handle, &data) == TRUE); FindClose(handle); + Tcl_DStringFree(&dirString); Tcl_DStringFree(&dsOrig); return TCL_OK; } |