Skip to content

Commit

Permalink
Fix incorrect behavior of 'cd ../.foo' (#46)
Browse files Browse the repository at this point in the history
The cd builtin was removing '.' from directory names when combined
with a preceding '../', which caused commands like 'cd ../.local'
to become 'cd ../local'. This patch fixes the problem by limiting
the extra handling to leading '..'. The bugfix comes from ksh93v-
2013-10-10-alpha, although this version is a shortened patch from
Solaris (as ksh93v- refactored a decent amount of the code for the
cd builtin).

src/cmd/ksh93/bltins/cd_pwd.c:
- cd should only check for leading '..', as trying to handle a lone
  '.' only causes problems.

src/cmd/ksh93/tests/builtins.sh:
- Add a regression test for this problem based on the test present in
  ksh93v- 2013-10-10-alpha.

Patch from Solaris:
https://github.com/oracle/solaris-userland/blob/860d27f/components/ksh93/patches/270-23319761.patch
  • Loading branch information
JohnoKing committed Jun 26, 2020
1 parent eaaa0de commit bb4745e
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 27 deletions.
5 changes: 5 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ For full details, see the git log at: https://github.com/ksh93/ksh

Any uppercase BUG_* names are modernish shell bug IDs.

2020-06-26:

- Changing to a directory that has a name starting with a '.' will no
longer fail if preceded by '../' (i.e. 'cd ../.local' will now work).

2020-06-24:

- Fixed buggy tab completion of tilde-expanded paths such as
Expand Down
38 changes: 12 additions & 26 deletions src/cmd/ksh93/bltins/cd_pwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,34 +109,20 @@ int b_cd(int argc, char *argv[],Shbltin_t *context)
if(!oldpwd)
oldpwd = path_pwd(shp,1);
}
if(*dir=='.')
if(*dir!='/')
{
/* test for pathname . ./ .. or ../ */
int n=0;
char *sp;
for(dp=dir; *dp=='.'; dp++)
/* check for leading .. */
char *cp;
sfprintf(shp->strbuf,"%s",dir);
cp = sfstruse(shp->strbuf);
pathcanon(cp, 0);
if(cp[0]=='.' && cp[1]=='.' && (cp[2]=='/' || cp[2]==0))
{
if(*++dp=='.' && (*++dp=='/' || *dp==0))
n++;
else if(*dp && *dp!='/')
break;
if(*dp==0)
break;
}
if(n)
{
cdpath = 0;
sp = oldpwd + strlen(oldpwd);
while(n--)
{
while(--sp > oldpwd && *sp!='/');
if(sp==oldpwd)
break;

}
sfwrite(shp->strbuf,oldpwd,sp+1-oldpwd);
sfputr(shp->strbuf,dp,0);
dir = sfstruse(shp->strbuf);
if(!shp->strbuf2)
shp->strbuf2 = sfstropen();
sfprintf(shp->strbuf2,"%s/%s",oldpwd,cp);
dir = sfstruse(shp->strbuf2);
pathcanon(dir, 0);
}
}
rval = -1;
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/ksh93/include/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
* David Korn <dgk@research.att.com> *
* *
***********************************************************************/
#define SH_RELEASE "93u+m 2020-06-24"
#define SH_RELEASE "93u+m 2020-06-26"
9 changes: 9 additions & 0 deletions src/cmd/ksh93/tests/builtins.sh
Original file line number Diff line number Diff line change
Expand Up @@ -717,5 +717,14 @@ chmod is $(whence -p chmod)
chmod is a tracked alias for $(whence -p chmod)"
[[ $actual == $expected ]] || err_exit '`whence -a` does not work correctly with tracked aliases'
# ======
# 'cd ../.foo' should not exclude the '.' in '.foo'
(
cd "$tmp"
mkdir foo .bar
cd foo
cd ../.bar
) || err_exit 'cd ../.bar when ../.bar exists should not fail'
# ======
exit $((Errors<125?Errors:125))

0 comments on commit bb4745e

Please sign in to comment.