summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvincentdarley <vincentdarley>2005-03-15 18:08:20 (GMT)
committervincentdarley <vincentdarley>2005-03-15 18:08:20 (GMT)
commit40320c2d537b4946866878bf43005672dc34dade (patch)
tree3a60d461d0cd76315e91eb297726993947421dcd
parent69c52177619d88251e8c6ec69f72db33e2c80434 (diff)
downloadtcl-40320c2d537b4946866878bf43005672dc34dade.zip
tcl-40320c2d537b4946866878bf43005672dc34dade.tar.gz
tcl-40320c2d537b4946866878bf43005672dc34dade.tar.bz2
fix to file norm, file pathtype on windows reserved filenames
-rw-r--r--ChangeLog7
-rw-r--r--generic/tclFileName.c37
-rw-r--r--tests/winFCmd.test50
-rw-r--r--win/tclWinFile.c83
4 files changed, 155 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog
index 012078b..46d5b0b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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;
}