diff options
author | apnadkarni <apnmbx-wits@yahoo.com> | 2023-09-20 06:32:32 (GMT) |
---|---|---|
committer | apnadkarni <apnmbx-wits@yahoo.com> | 2023-09-20 06:32:32 (GMT) |
commit | c1d507af302a1330ff03c3507d5bd1c965224064 (patch) | |
tree | 1ac896f6837e2749b2e37997aa3bdf7e94c91a89 /generic/tclPathObj.c | |
parent | ef9ea15d10ceacfb89e94c3f73a3fab9c3601df1 (diff) | |
download | tcl-c1d507af302a1330ff03c3507d5bd1c965224064.zip tcl-c1d507af302a1330ff03c3507d5bd1c965224064.tar.gz tcl-c1d507af302a1330ff03c3507d5bd1c965224064.tar.bz2 |
Bug [a288e2003b] - file normalize broken for zipfs.
Diffstat (limited to 'generic/tclPathObj.c')
-rw-r--r-- | generic/tclPathObj.c | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/generic/tclPathObj.c b/generic/tclPathObj.c index 1e8f994..0095469 100644 --- a/generic/tclPathObj.c +++ b/generic/tclPathObj.c @@ -143,9 +143,17 @@ TclFSNormalizeAbsolutePath( * directory separator - we can't use '..' to * remove the volume in a path. */ Tcl_Obj *retVal = NULL; + int zipVolumeLen; dirSep = TclGetString(pathPtr); - if (tclPlatform == TCL_PLATFORM_WINDOWS) { + zipVolumeLen = TclIsZipfsPath(dirSep); + if (zipVolumeLen) { + /* + * NOTE: file normalization for zipfs is very specific to + * format of zipfs volume being of the form //xxx:/ + */ + dirSep += zipVolumeLen-1; /* Start parse after : */ + } else if (tclPlatform == TCL_PLATFORM_WINDOWS) { if ( (dirSep[0] == '/' || dirSep[0] == '\\') && (dirSep[1] == '/' || dirSep[1] == '\\') && (dirSep[2] == '?') @@ -246,13 +254,17 @@ TclFSNormalizeAbsolutePath( Tcl_AppendToObj(retVal, dirSep, 1); } if (!first || (tclPlatform == TCL_PLATFORM_UNIX)) { - linkObj = Tcl_FSLink(retVal, NULL, 0); + if (zipVolumeLen) { + linkObj = NULL; + } else { + linkObj = Tcl_FSLink(retVal, NULL, 0); - /* Safety check in case driver caused sharing */ - if (Tcl_IsShared(retVal)) { - TclDecrRefCount(retVal); - retVal = Tcl_DuplicateObj(retVal); - Tcl_IncrRefCount(retVal); + /* Safety check in case driver caused sharing */ + if (Tcl_IsShared(retVal)) { + TclDecrRefCount(retVal); + retVal = Tcl_DuplicateObj(retVal); + Tcl_IncrRefCount(retVal); + } } if (linkObj != NULL) { @@ -322,10 +334,12 @@ TclFSNormalizeAbsolutePath( /* * Either way, we now remove the last path element (but - * not the first character of the path). + * not the first character of the path). In the case of + * zipfs, make sure not to go beyond the zipfs volume. */ - while (--curLen >= 0) { + int minLen = zipVolumeLen ? zipVolumeLen - 1 : 0; + while (--curLen >= minLen) { if (IsSeparatorOrNull(linkStr[curLen])) { if (curLen) { Tcl_SetObjLength(retVal, curLen); @@ -384,13 +398,21 @@ TclFSNormalizeAbsolutePath( /* * Ensure a windows drive like C:/ has a trailing separator. + * Likewise for zipfs volumes. */ - - if (tclPlatform == TCL_PLATFORM_WINDOWS) { + if (zipVolumeLen || (tclPlatform == TCL_PLATFORM_WINDOWS)) { + int needTrailingSlash = 0; int len; const char *path = TclGetStringFromObj(retVal, &len); - - if (len == 2 && path[0] != 0 && path[1] == ':') { + if (zipVolumeLen) { + if (len == (zipVolumeLen - 1)) + needTrailingSlash = 1; + } else { + if (len == 2 && path[0] != 0 && path[1] == ':') { + needTrailingSlash = 1; + } + } + if (needTrailingSlash) { if (Tcl_IsShared(retVal)) { TclDecrRefCount(retVal); retVal = Tcl_DuplicateObj(retVal); |