zsh-workers
 help / color / mirror / code / Atom feed
From: Stephane Chazelas <stephane@chazelas.org>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: can we have an option for cd to do a plain chdir()
Date: Sun, 6 Feb 2022 17:44:06 +0000	[thread overview]
Message-ID: <20220206174406.rirklyrkzlx6winw@chazelas.org> (raw)

I was surprised to see that after:

ln -s /proc/self/cwd/.. link; cd link

I ended up two directories up instead of one.

strace revealed:

$ strace -fe getcwd,readlink,chdir,fchdir zsh -c 'cd link'
readlink("/proc/self/fd/0", "/dev/pts/4", 4095) = 10
chdir("/home/chazelas/link")            = 0
chdir("/home/chazelas/link")            = 0
+++ exited with 0 +++

Not sure why the two chdir()s there.

That it prepends $PWD to the path is also a problem if the
current working directory has been renamed, but most shells do
that without -P.

It's better in that case with cd -P or with chaselinks:

$ strace -fe getcwd,readlink,chdir,fchdir zsh -c 'cd -P link'
readlink("/proc/self/fd/0", "/dev/pts/4", 4095) = 10
chdir("/home/chazelas/link")            = 0
readlink("/home", 0x7ffe6ba34f00, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/chazelas", 0x7ffe6ba34f00, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/chazelas/link", "/proc/self/cwd/..", 4096) = 17
readlink("/proc", 0x7ffe6ba2fe70, 4096) = -1 EINVAL (Invalid argument)
readlink("/proc/self", "1000438", 4096) = 7
readlink("/proc/1000438", 0x7ffe6ba2ade0, 4096) = -1 EINVAL (Invalid argument)
readlink("/proc/1000438/cwd", "/home", 4096) = 5
readlink("/home", 0x7ffe6ba2ade0, 4096) = -1 EINVAL (Invalid argument)
chdir("..")                             = 0
chdir("/home")                          = 0
+++ exited with 0 +++
~$ strace -fe getcwd,readlink,chdir,fchdir zsh -o chaselinks -c 'cd link'
readlink("/proc/self/fd/0", "/dev/pts/4", 4095) = 10
readlink("/home", 0x7ffdfc3e0f40, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/chazelas", 0x7ffdfc3e0f40, 4096) = -1 EINVAL (Invalid argument)
chdir("/home/chazelas/link")            = 0
readlink("/home", 0x7ffdfc3df960, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/chazelas", 0x7ffdfc3df960, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/chazelas/link", "/proc/self/cwd/..", 4096) = 17
readlink("/proc", 0x7ffdfc3da8d0, 4096) = -1 EINVAL (Invalid argument)
readlink("/proc/self", "1002598", 4096) = 7
readlink("/proc/1002598", 0x7ffdfc3d5840, 4096) = -1 EINVAL (Invalid argument)
readlink("/proc/1002598/cwd", "/home", 4096) = 5
readlink("/home", 0x7ffdfc3d5840, 4096) = -1 EINVAL (Invalid argument)
chdir("..")                             = 0
chdir("/home")                          = 0
+++ exited with 0 +++

But that sounds a bit overkill and racy.

In scripts, you usually want your cd's to do plain chdir()s but
there are many things that get in the way:

- the need for -P to avoid the logical traversal
- the need to -- as usual for avoid problems with dirnames
  starting with -
- CDPATH (it is inherited from the environment but at least when
  not in POSIX mode, that doesn't take precedence over actual
  relative path).
- The "-" string that is taken as $OLDPWD
- Also in zsh, the -n +n ones.
- and then there's that special fancy chasing of symlinks

So, to do an actual chdir, we need something like:

chdir() {
  case $1 in
    (/*) cd -P "$1";;
    ('') print -u2 "not sure out to chdir to an empty string";;
    (*) cd -P "./$1";;
  esac
}

Which addresses the first 5 points, but not the 6th.

It would be nice if we could just do for instance cd -r -- $dir
which would just a do chdir($dir) and set $PWD to getcwd() if
successful.

(or have chdir (which atm exits as a builtin for tcsh junkies I
suppose) do that and not take any option).

What do you think?

-- 
Stephane


             reply	other threads:[~2022-02-06 17:44 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-06 17:44 Stephane Chazelas [this message]
2022-02-09 17:16 ` Bart Schaefer
2022-02-10 20:27   ` Stephane Chazelas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220206174406.rirklyrkzlx6winw@chazelas.org \
    --to=stephane@chazelas.org \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).