summaryrefslogtreecommitdiffstats
path: root/generic/tclPathObj.c
diff options
context:
space:
mode:
authorapnadkarni <apnmbx-wits@yahoo.com>2023-09-20 06:32:32 (GMT)
committerapnadkarni <apnmbx-wits@yahoo.com>2023-09-20 06:32:32 (GMT)
commitc1d507af302a1330ff03c3507d5bd1c965224064 (patch)
tree1ac896f6837e2749b2e37997aa3bdf7e94c91a89 /generic/tclPathObj.c
parentef9ea15d10ceacfb89e94c3f73a3fab9c3601df1 (diff)
downloadtcl-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.c48
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);