diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | generic/tclFileName.c | 37 | ||||
-rw-r--r-- | tests/winFCmd.test | 50 | ||||
-rw-r--r-- | win/tclWinFile.c | 83 |
4 files changed, 155 insertions, 22 deletions
@@ -1,3 +1,10 @@ +2005-03-15 Vince Darley <vincentdarley@users.sourceforge.net> + + * generic/tclFileName.c: + * win/tclWinFile.c: + * tests/winFCMd.test: fix to 'file pathtype' and 'file norm' + failures on reserved filenames like 'COM1:', etc. + 2005-03-15 Kevin B. Kenny <kennykb@acm.org> * generic/tclClock.c: diff --git a/generic/tclFileName.c b/generic/tclFileName.c index 7fbfb7f..cc1f91a 100644 --- a/generic/tclFileName.c +++ b/generic/tclFileName.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: tclFileName.c,v 1.40.2.7 2004/03/09 12:56:59 vincentdarley Exp $ + * RCS: @(#) $Id: tclFileName.c,v 1.40.2.8 2005/03/15 18:08:21 vincentdarley Exp $ */ #include "tclInt.h" @@ -244,37 +244,38 @@ ExtractWinRoot(path, resultPtr, offset, typePtr) } } else { int abs = 0; - if (path[0] == 'c' && path[1] == 'o') { - if (path[2] == 'm' && path[3] >= '1' && path[3] <= '9') { - /* May have match for 'com[1-9]:?', which is a serial port */ - if (path[4] == '\0') { - abs = 4; - } else if (path [4] == ':' && path[5] == '\0') { + if ((path[0] == 'c' || path[0] == 'C') + && (path[1] == 'o' || path[1] == 'O')) { + if ((path[2] == 'm' || path[2] == 'M') + && path[3] >= '1' && path[3] <= '4') { + /* May have match for 'com[1-4]:?', which is a serial port */ + if (path[4] == '\0') { + abs = 4; + } else if (path [4] == ':' && path[5] == '\0') { abs = 5; - } - } else if (path[2] == 'n' && path[3] == '\0') { + } + } else if ((path[2] == 'n' || path[2] == 'N') && path[3] == '\0') { /* Have match for 'con' */ abs = 3; } - } else if (path[0] == 'l' && path[1] == 'p' && path[2] == 't') { - if (path[3] >= '1' && path[3] <= '9') { - /* May have match for 'lpt[1-9]:?' */ + } else if ((path[0] == 'l' || path[0] == 'L') + && (path[1] == 'p' || path[1] == 'P') + && (path[2] == 't' || path[2] == 'T')) { + if (path[3] >= '1' && path[3] <= '3') { + /* May have match for 'lpt[1-3]:?' */ if (path[4] == '\0') { abs = 4; } else if (path [4] == ':' && path[5] == '\0') { abs = 5; } } - } else if (path[0] == 'p' && path[1] == 'r' - && path[2] == 'n' && path[3] == '\0') { + } else if (stricmp(path, "prn") == 0) { /* Have match for 'prn' */ abs = 3; - } else if (path[0] == 'n' && path[1] == 'u' - && path[2] == 'l' && path[3] == '\0') { + } else if (stricmp(path, "nul") == 0) { /* Have match for 'nul' */ abs = 3; - } else if (path[0] == 'a' && path[1] == 'u' - && path[2] == 'x' && path[3] == '\0') { + } else if (stricmp(path, "aux") == 0) { /* Have match for 'aux' */ abs = 3; } diff --git a/tests/winFCmd.test b/tests/winFCmd.test index 49bae98..937aef3 100644 --- a/tests/winFCmd.test +++ b/tests/winFCmd.test @@ -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: winFCmd.test,v 1.20.2.6 2005/01/17 13:04:44 vincentdarley Exp $ +# RCS: @(#) $Id: winFCmd.test,v 1.20.2.7 2005/03/15 18:08:24 vincentdarley Exp $ # if {[lsearch [namespace children] ::tcltest] == -1} { @@ -1020,6 +1020,54 @@ test winFCmd-16.12 {Windows file normalization} {pcOnly} { cd $pwd unset d dd pwd +test winFCmd-18.1 {Windows reserved path names} -constraints win -body { + file pathtype com1 +} -result "absolute" + +test winFCmd-18.1.2 {Windows reserved path names} -constraints win -body { + file pathtype com4 +} -result "absolute" + +test winFCmd-18.1.3 {Windows reserved path names} -constraints win -body { + file pathtype com5 +} -result "relative" + +test winFCmd-18.1.4 {Windows reserved path names} -constraints win -body { + file pathtype lpt3 +} -result "absolute" + +test winFCmd-18.1.5 {Windows reserved path names} -constraints win -body { + file pathtype lpt4 +} -result "relative" + +test winFCmd-18.2 {Windows reserved path names} -constraints win -body { + file pathtype com1: +} -result "absolute" + +test winFCmd-18.3 {Windows reserved path names} -constraints win -body { + file pathtype COM1 +} -result "absolute" + +test winFCmd-18.4 {Windows reserved path names} -constraints win -body { + file pathtype CoM1: +} -result "absolute" + +test winFCmd-18.5 {Windows reserved path names} -constraints win -body { + file normalize com1: +} -result COM1 + +test winFCmd-18.6 {Windows reserved path names} -constraints win -body { + file normalize COM1: +} -result COM1 + +test winFCmd-18.7 {Windows reserved path names} -constraints win -body { + file normalize cOm1 +} -result COM1 + +test winFCmd-18.8 {Windows reserved path names} -constraints win -body { + file normalize cOm1: +} -result COM1 + # This block of code used to occur after the "return" call, so I'm # commenting it out and assuming that this code is still under construction. #foreach source {tef ted tnf tnd "" nul com1} { diff --git a/win/tclWinFile.c b/win/tclWinFile.c index 1ad7da8..18c4787 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.44.2.10 2004/10/08 20:16:42 hobbs Exp $ + * RCS: @(#) $Id: tclWinFile.c,v 1.44.2.11 2005/03/15 18:08:24 vincentdarley Exp $ */ //#define _WIN32_WINNT 0x0500 @@ -178,6 +178,7 @@ static int NativeWriteReparse(CONST TCHAR* LinkDirectory, static int NativeMatchType(int isDrive, DWORD attr, CONST TCHAR* nativeName, Tcl_GlobTypeData *types); static int WinIsDrive(CONST char *name, int nameLen); +static int WinIsReserved(CONST char *path); static Tcl_Obj* WinReadLink(CONST TCHAR* LinkSource); static Tcl_Obj* WinReadLinkDirectory(CONST TCHAR* LinkDirectory); static int WinLink(CONST TCHAR* LinkSource, CONST TCHAR* LinkTarget, @@ -1010,6 +1011,52 @@ WinIsDrive( return 0; } +/* + * Does the given path represent a reserved window path name? If not + * return 0, if true, return the number of characters of the path that + * we actually want (not any trailing :). + */ +static int WinIsReserved( + CONST char *path) /* Path in UTF-8 */ +{ + if ((path[0] == 'c' || path[0] == 'C') + && (path[1] == 'o' || path[1] == 'O')) { + if ((path[2] == 'm' || path[2] == 'M') + && path[3] >= '1' && path[3] <= '4') { + /* May have match for 'com[1-4]:?', which is a serial port */ + if (path[4] == '\0') { + return 4; + } else if (path [4] == ':' && path[5] == '\0') { + return 4; + } + } else if ((path[2] == 'n' || path[2] == 'N') && path[3] == '\0') { + /* Have match for 'con' */ + return 3; + } + } else if ((path[0] == 'l' || path[0] == 'L') + && (path[1] == 'p' || path[1] == 'P') + && (path[2] == 't' || path[2] == 'T')) { + if (path[3] >= '1' && path[3] <= '3') { + /* May have match for 'lpt[1-3]:?' */ + if (path[4] == '\0') { + return 4; + } else if (path [4] == ':' && path[5] == '\0') { + return 4; + } + } + } else if (stricmp(path, "prn") == 0) { + /* Have match for 'prn' */ + return 3; + } else if (stricmp(path, "nul") == 0) { + /* Have match for 'nul' */ + return 3; + } else if (stricmp(path, "aux") == 0) { + /* Have match for 'aux' */ + return 3; + } + return 0; +} + /* *---------------------------------------------------------------------- * @@ -2140,9 +2187,22 @@ TclpObjNormalizePath(interp, pathPtr, nextCheckpoint) * the current normalized path, if the file exists. */ if (isDrive) { - if (GetFileAttributesA(nativePath) - == 0xffffffff) { + if (GetFileAttributesA(nativePath) == 0xffffffff) { /* File doesn't exist */ + if (isDrive) { + int len = WinIsReserved(path); + if (len > 0) { + /* Actually it does exist - COM1, etc */ + int i; + for (i=0;i<len;i++) { + if (nativePath[i] >= 'a') { + ((char*)nativePath)[i] -= ('a' - 'A'); + } + } + Tcl_DStringAppend(&dsNorm, nativePath, len); + lastValidPathEnd = currentPathEndPosition; + } + } Tcl_DStringFree(&ds); break; } @@ -2209,6 +2269,23 @@ TclpObjNormalizePath(interp, pathPtr, nextCheckpoint) if ((*tclWinProcs->getFileAttributesExProc)(nativePath, GetFileExInfoStandard, &data) != TRUE) { /* File doesn't exist */ + if (isDrive) { + int len = WinIsReserved(path); + if (len > 0) { + /* Actually it does exist - COM1, etc */ + int i; + for (i=0;i<len;i++) { + WCHAR wc = ((WCHAR*)nativePath)[i]; + if (wc >= L'a') { + wc -= (L'a' - L'A'); + ((WCHAR*)nativePath)[i] = wc; + } + } + Tcl_DStringAppend(&dsNorm, nativePath, + sizeof(WCHAR)*len); + lastValidPathEnd = currentPathEndPosition; + } + } Tcl_DStringFree(&ds); break; } |