From 5b3cf09d56c6bccfa2d2d4ffcedab7afa9738188 Mon Sep 17 00:00:00 2001 From: vincentdarley Date: Tue, 30 Mar 2004 15:35:45 +0000 Subject: fix to glob with volume relative paths, bug 898238 --- ChangeLog | 12 ++++++++++++ generic/tclFileName.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++-- generic/tclIOUtil.c | 13 ++++++++++--- tests/fileName.test | 9 ++++++--- tests/fileSystem.test | 22 ++++++++++++++++++++++ 5 files changed, 100 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index d6dc060..fc42294 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,17 @@ 2004-03-30 Vince Darley + * generic/tclFileName.c: Fix to Windows glob where the pattern is + * generic/tclIOUtil.c: a volume relative path or a network + * tests/fileName.test: share [Bug 898238]. On windows 'glob' + * tests/fileSystem.test: will now return the results of + 'glob /foo/bar' and 'glob \\foo\\bar' as 'C:/foo/bar', i.e. a + correct absolute path (rather than a volume relative path). + + Note that the test suite does not test commands like + 'glob //Machine/Shared/*' (on a network share). + +2004-03-30 Vince Darley + * generic/tclPathObj.c: Fix to filename bugs recently * tests/fileName.test: introduced [Bug 918320]. diff --git a/generic/tclFileName.c b/generic/tclFileName.c index 563357a..b056ca3 100644 --- a/generic/tclFileName.c +++ b/generic/tclFileName.c @@ -10,12 +10,13 @@ * 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.50 2004/03/17 18:14:13 das Exp $ + * RCS: @(#) $Id: tclFileName.c,v 1.51 2004/03/30 15:35:46 vincentdarley Exp $ */ #include "tclInt.h" #include "tclPort.h" #include "tclRegexp.h" +#include "tclFilesystem.h" /* For TclGetPathType() */ /* * The following variable is set in the TclPlatformInit call to one @@ -253,7 +254,7 @@ Tcl_GetPathType(path) Tcl_PathType TclpGetNativePathType(pathPtr, driveNameLengthPtr, driveNameRef) - Tcl_Obj *pathPtr; /* Native path of interest */ + Tcl_Obj *pathPtr; /* Native path of interest */ int *driveNameLengthPtr; /* Returns length of drive, if non-NULL * and path was absolute */ Tcl_Obj **driveNameRef; @@ -1634,6 +1635,53 @@ TclGlob(interp, pattern, pathPrefix, globFlags, types) } tail = p; Tcl_IncrRefCount(pathPrefix); + } else if (pathPrefix == NULL && (tail[0] == '/' + || (tail[0] == '\\' && tail[1] == '\\'))) { + int driveNameLen; + Tcl_Obj *driveName; + Tcl_Obj *temp = Tcl_NewStringObj(tail, -1); + Tcl_IncrRefCount(temp); + + switch (TclGetPathType(temp, NULL, &driveNameLen, &driveName)) { + case TCL_PATH_VOLUME_RELATIVE: { + /* + * Volume relative path which is equivalent to a path in + * the root of the cwd's volume. We will actually return + * non-volume-relative paths here. i.e. 'glob /foo*' will + * return 'C:/foobar'. This is much the same as globbing + * for a path with '\\' will return one with '/' on Windows. + */ + Tcl_Obj *cwd = Tcl_FSGetCwd(interp); + if (cwd == NULL) { + Tcl_DecrRefCount(temp); + if (globFlags & TCL_GLOBMODE_NO_COMPLAIN) { + return TCL_OK; + } else { + return TCL_ERROR; + } + } + pathPrefix = Tcl_NewStringObj(Tcl_GetString(cwd), 3); + Tcl_DecrRefCount(cwd); + if (tail[0] == '/') { + tail++; + } else { + tail+=2; + } + Tcl_IncrRefCount(pathPrefix); + break; + } + case TCL_PATH_ABSOLUTE: { + /* + * Absolute, possibly network path //Machine/Share. + * Use that as the path prefix (it already has a + * refCount). + */ + pathPrefix = driveName; + tail += driveNameLen; + break; + } + } + Tcl_DecrRefCount(temp); } /* * ':' no longer needed as a separator. It is only relevant diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c index a65971f..52bec32 100644 --- a/generic/tclIOUtil.c +++ b/generic/tclIOUtil.c @@ -17,7 +17,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclIOUtil.c,v 1.96 2004/03/17 18:14:13 das Exp $ + * RCS: @(#) $Id: tclIOUtil.c,v 1.97 2004/03/30 15:35:46 vincentdarley Exp $ */ #include "tclInt.h" @@ -3442,8 +3442,15 @@ TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr, driveNameRef) * non-NULL, then set to the * filesystem which claims this * path */ - int *driveNameLengthPtr; - Tcl_Obj **driveNameRef; + int *driveNameLengthPtr; /* If the path is absolute, and + * this is non-NULL, then set to + * the length of the driveName */ + Tcl_Obj **driveNameRef; /* If the path is absolute, and + * this is non-NULL, then set to + * the name of the drive, + * network-volume which contains + * the path, already with a + * refCount for the caller. */ { FilesystemRecord *fsRecPtr; int pathLen; diff --git a/tests/fileName.test b/tests/fileName.test index 6168f6f..791b69d 100644 --- a/tests/fileName.test +++ b/tests/fileName.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: fileName.test,v 1.39 2004/03/30 09:56:33 vincentdarley Exp $ +# RCS: @(#) $Id: fileName.test,v 1.40 2004/03/30 15:35:47 vincentdarley Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest @@ -1312,12 +1312,15 @@ test filename-14.21 {asterisks, question marks, and brackets} { test filename-14.22 {asterisks, question marks, and brackets} { list [catch {glob goo/* x*z foo?q} msg] $msg } {1 {no files matched glob patterns "goo/* x*z foo?q"}} -test filename-14.23 {slash globbing} {unixOrPc} { +test filename-14.23 {slash globbing} {unixOnly} { glob / } / +test filename-14.23.2 {slash globbing} {pcOnly} { + glob / +} [file norm /] test filename-14.24 {slash globbing} {pcOnly} { glob {\\} -} / +} [file norm /] test filename-14.25 {type specific globbing} {unixOnly} { list [catch {lsort [glob -dir globTest -types f *]} msg] $msg } [list 0 [lsort [list \ diff --git a/tests/fileSystem.test b/tests/fileSystem.test index 5f8105d..a619929 100644 --- a/tests/fileSystem.test +++ b/tests/fileSystem.test @@ -400,6 +400,28 @@ test filesystem-1.39 {file normalisation with volume relative} {winOnly} { } } {ok} +test filesystem-1.40 {file normalisation with repeated separators} { + set a [file norm foo////bar] + set b [file norm foo/bar] + + if {![string equal $a $b]} { + set res "Paths should be equal: $a , $b" + } else { + set res "ok" + } +} {ok} + +test filesystem-1.41 {file normalisation with repeated separators} {winOnly} { + set a [file norm foo\\\\\\bar] + set b [file norm foo/bar] + + if {![string equal $a $b]} { + set res "Paths should be equal: $a , $b" + } else { + set res "ok" + } +} {ok} + test filesystem-2.0 {new native path} {unixOnly} { foreach f [lsort [glob -nocomplain /usr/bin/c*]] { catch {file readlink $f} -- cgit v0.12