From 5ee290c7a89d9f3f0b0a908304d0ad34b55df709 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Wed, 20 Jan 2021 05:43:46 +0000 Subject: [PATCH] cd: Fork if $PWD exists but is not actually the PWD (re: d1483150) Commit d1483150 did not fully fix #153. Test case from Harald van Dijk that was still failing: $ mkdir test $ cd test $ rmdir $PWD $ mkdir $PWD $ ksh -c "(cd /); pwd" / Forking a virtual subshell in that case is needed to avoid ending up in a directory that replaced the PWD, because it will not be possible for a process to change back to the original directory. src/cmd/ksh93/bltins/cd_pwd.c: - When deciding whether to fork, instead of attempting to opendir the PWD, compare the inodes $PWD and "." to determine if $PWD still actually refers to the current directory. This uses the test_inode() function which is also used by 'test foo -ef bar'. src/cmd/ksh93/tests/subshell.sh: - Add test based on the above. Progresses: https://github.com/ksh93/ksh/issues/153 --- src/cmd/ksh93/bltins/cd_pwd.c | 6 +----- src/cmd/ksh93/tests/subshell.sh | 9 +++++++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/cmd/ksh93/bltins/cd_pwd.c b/src/cmd/ksh93/bltins/cd_pwd.c index 10b8f7174..801d7f6dd 100644 --- a/src/cmd/ksh93/bltins/cd_pwd.c +++ b/src/cmd/ksh93/bltins/cd_pwd.c @@ -37,7 +37,6 @@ #include "name.h" #include "builtins.h" #include -#include /* * Invalidate path name bindings to relative paths @@ -99,10 +98,7 @@ int b_cd(int argc, char *argv[],Shbltin_t *context) if(shp->subshell && !shp->subshare) { #if _lib_fchdir - DIR *testdir; - if(testdir = opendir(nv_getval(pwdnod))) - closedir(testdir); - else + if(!test_inode(nv_getval(pwdnod),e_dot)) #endif sh_subfork(); } diff --git a/src/cmd/ksh93/tests/subshell.sh b/src/cmd/ksh93/tests/subshell.sh index 03fdb2101..d287b8072 100755 --- a/src/cmd/ksh93/tests/subshell.sh +++ b/src/cmd/ksh93/tests/subshell.sh @@ -904,6 +904,15 @@ exp="PWD=$PWD" got=$( { "$SHELL" -c '(cd /; (cd /)); print -r -- "PWD=$PWD"'; } 2>&1 ) ((!(e = $?))) && [[ $got == "$exp" ]] || err_exit 'failed to restore nonexistent PWD on exiting a virtual subshell' \ "(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))" +cd "$tmp" +mkdir recreated +cd recreated +tmp=$tmp "$SHELL" -c 'cd /; rmdir "$tmp/recreated"; mkdir "$tmp/recreated"' +exp="PWD=$PWD" +got=$( { "$SHELL" -c '(cd /); print -r -- "PWD=$PWD"'; } 2>&1 ) +((!(e = $?))) && [[ $got == "$exp" ]] || err_exit 'failed to restore re-created PWD on exiting a virtual subshell' \ + "(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))" +cd "$tmp" # ====== exit $((Errors<125?Errors:125))