zsh-workers
 help / color / mirror / code / Atom feed
* cdpath and empty string
@ 2013-08-07  8:49 Phil Pennock
  2013-08-08  1:23 ` Bart Schaefer
  0 siblings, 1 reply; 2+ messages in thread
From: Phil Pennock @ 2013-08-07  8:49 UTC (permalink / raw)
  To: zsh-workers

Finally got irritated enough to track down what's required to trigger
what looks like a zsh bug.

    % mkdir /tmp/T1 /tmp/T2 /tmp/T2/T1
    % zsh -f
    redoubt% typeset -a cdpath
    redoubt% cdpath=(/tmp/T1 '')
    redoubt% cd /tmp/T2
    redoubt% cd T1
    /tmp/T1/T1
    redoubt% pwd
    /tmp/T2/T1
    redoubt% echo $PWD
    /tmp/T1/T1
    redoubt% cd .
    redoubt% echo $PWD
    /tmp/T2/T1


If $cdpath has an empty string at the end (in my case, using
"${cdpath[@]}" instead of ${cdpath[@]} when prepending elements), then
"cd foo" for unqualified 'foo' which is only found relative to cwd will
always print $cdpath[1]/foo while cd'ing into ./foo.

$PWD is left corrupted, fixed by "cd ."; pwd is fine.

I haven't figured out where this is happening; I know it's in the C, but
reading the code I can't tell where and I need to get back to work
instead of continuing to investigate.  :(

Any thoughts?

-Phil


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: cdpath and empty string
  2013-08-07  8:49 cdpath and empty string Phil Pennock
@ 2013-08-08  1:23 ` Bart Schaefer
  0 siblings, 0 replies; 2+ messages in thread
From: Bart Schaefer @ 2013-08-08  1:23 UTC (permalink / raw)
  To: Phil Pennock, zsh-workers

On Aug 7,  4:49am, Phil Pennock wrote:
}
} If $cdpath has an empty string at the end (in my case, using
} "${cdpath[@]}" instead of ${cdpath[@]} when prepending elements), then
} "cd foo" for unqualified 'foo' which is only found relative to cwd will
} always print $cdpath[1]/foo while cd'ing into ./foo.

This gets rather confusing ... I've been wanting to rewrite the guts of
builtin.c:cd_do_chdir for years, but every time I try to start on it I
find some rathole that it would take me down to untangle its interaction
with something else.

In this case an empty-string element in $cdpath is supposed to get
treated as if it were '.' -- and indeed the same symptoms occur if there
is an explicit '.' instead of empty.  Several things are going on:

(1) If there is not a dot, then
    (1a) POSIXCD says to search cdpath first, then try the current dir.
    (1b) Otherwise, zsh tries the current dir first all is well.
(2) If there IS a dot, then the local directory is supposed to be tried
    when the position of dot in the cdpath is reached (POSXCD irrelevant).

So cd_do_chdir scans cdpath and discovers the empty string / dot, and
takes branch (2) which means it immediately calls cd_try_chdir with a
prefix of /tmp/T1 [first element of cdpath].  This assembles the path
"/tmp/T1/T1" and calls utils.c:lchdir on it.  This is where things go
wrong; that call to lchdir fails (as it should), so cd_do_chdir then
calls lchdir on the original path "T1", which succeeds.

Code snippet with comment:

    /* We try the full path first.  If that fails, try the
     * argument to cd relatively.  This is useful if the cwd
     * or a parent directory is renamed in the interim.
     */
    if (lchdir(buf, NULL, hard) && lchdir(dest, NULL, hard)) {
	free(buf);
	return NULL;
    }

A potential fix is

    if (lchdir(buf, NULL, hard) && (pfix || lchdir(dest, NULL, hard))) {

because I can't think of a case where the "useful" comment applies when
we're pasting together a path.  However, this makes a redundant call if
dest is already a full path, so perhaps

    if (lchdir(buf, NULL, hard) &&
        (pfix || *dest == '/' || lchdir(dest, NULL, hard))) {

would be better.  Are there any other potential callers of cd_try_chdir
that would be messed up by this?  Ramifications of calling cd_try_chdir
with BOTH pfix AND *dest == '/' that would need the second call to
lchdir to discover that the prefix should not have been pasted onto
the front of dest in the first place?  (Which might be better fixed by
testing for *dest == '/' before gluing on the prefix.)


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2013-08-08  1:23 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-07  8:49 cdpath and empty string Phil Pennock
2013-08-08  1:23 ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).