Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [BUG] cdpath=(.) breaks cd from / on Cygwin

Looks good to me. When I build with this patch, cd from / on Cygwin works as expected, even with an explicit '.' in $cdpath.



On 2/15/15 5:57 PM, Bart Schaefer wrote:
On Feb 15,  3:18pm, Andrew Janke wrote:
} In Src/builtin.c, function cd_try_chdir(), lines 1080-1093, there's some
} special case handling for Cygwin and the prefix '/'. But when the prefix
} is '.', it goes down a different code path. It constructs the path
} starting from pwd (which is '/' in this case), and then goes through the
} path normalization which elides '.' segments. But it doesn't have a
} special case check for Cygwin to check for leading '/' again. And I
} think the elision of the first '.' segment will result in a computed
} path starting with '//' but not further escaped.

That's a pretty close analysis.  The real problem is that when pwd is
"/", cd_try_chdir() unnecessarily inserts yet another "/" into the
path before appending a cdpath segment (the "pfix").  So the path has
already become "//./" before normalization even begins.  This is a
waste of effort when pwd is "/" on any platform.

I'm not sure why we bother compiling different branches for cygwin and
otherwise in cd_try_chdir().  Doesn't appear the cygwin variation would
be wrong anywhere else.  But I won't mess with that here.

Try this patch:

diff --git a/Src/builtin.c b/Src/builtin.c
index c4e4b94..614b17d 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -1093,9 +1093,11 @@ cd_try_chdir(char *pfix, char *dest, int hard)
  	} else {
  	    int pfl = strlen(pfix);
  	    dlen = strlen(pwd);
+	    if (dlen == 1 && *pwd == '/')
+		dlen = 0;
  	    buf = zalloc(dlen + pfl + strlen(dest) + 3);
-	    strcpy(buf, pwd);
+	    if (dlen)
+		strcpy(buf, pwd);
  	    buf[dlen] = '/';
  	    strcpy(buf + dlen + 1, pfix);
  	    buf[dlen + 1 + pfl] = '/';

Messages sorted by: Reverse Date, Date, Thread, Author