Discussion:
[ast-developers] [patch] Add $ cd -f $dirfd relative_path # to "cd" builtin... / was: Re: When will the tree reopen for normal patches?
Roland Mainz
2013-06-20 11:13:07 UTC
Permalink
On Wed, Jun 19, 2013 at 5:49 PM, Cedric Blancher
cc: ast-developers at research.att.com
Subject: Re: [ast-developers] When will the tree reopen for normal patches?
--------
cd /dev/fd/$d no longer works
What do you mean that it no longer works, I just did
exec 9< /tmp
and was able to do
cd /dev/fd/9/foo
to change to /tmp/foo.
/bin/ksh -c 'exec {n}</etc ; cd /dev/fd/$n/ ; true'
/bin/ksh: cd: /dev/fd/11/: [Bad address]
This has been reported to ast-developers at research.att.com several
times. Search for '[Bad address]'.
There were also requests for cd -f $n relative_path to allow relative
paths which go above the starting point of fd, e.g. cd -f $n ../../a/b
The other reason for cd -f $fd relative_path was that POSIX does not
standardise absolute paths and that bash and dash developers see it as
a cleaner API to openat() than using /dev/fd
Attached (as "astksh_20130613_cd_f_dirfd_002.diff.txt") is the patch
to add $ cd -f $fd # ... it's more or less the same solution which was
proposed for bash4&&dash, too.

----

Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
-------------- next part --------------
diff -r -u build_i386_64bit_debug/src/cmd/ksh93/bltins/cd_pwd.c build_i386_64bit_debug_cd_f/src/cmd/ksh93/bltins/cd_pwd.c
--- src/cmd/ksh93/bltins/cd_pwd.c 2013-05-16 16:36:14.000000000 +0200
+++ src/cmd/ksh93/bltins/cd_pwd.c 2013-06-20 12:49:48.032595845 +0200
@@ -19,8 +19,8 @@
***********************************************************************/
#pragma prototyped
/*
- * cd [-LP@] [dirname]
- * cd [-LP@] [old] [new]
+ * cd [-LP@] [-f dirfd] [dirname]
+ * cd [-LP@] [-fdirfd] [old] [new]
* pwd [-LP]
*
* David Korn
@@ -171,12 +171,21 @@
int rval;
bool flag=false,xattr=false;
char *oldpwd;
+ int dirfd = shp->pwdfd;
int newdirfd;
Namval_t *opwdnod, *pwdnod;
if(sh_isoption(shp,SH_RESTRICTED))
errormsg(SH_DICT,ERROR_exit(1),e_restricted+4);
while((rval = optget(argv,sh_optcd))) switch(rval)
{
+#ifdef AT_FDCWD
+ case 'f':
+ errno = 0;
+ dirfd = strtol(opt_info.arg, (char **)NULL, 10);
+ if ((errno != 0) || (dirfd < 0))
+ errormsg(SH_DICT, ERROR_system(1), "%s: invalid dir fd", opt_info.arg);
+ break;
+#endif
case 'L':
flag = false;
break;
@@ -307,7 +316,7 @@
continue;
#endif /* SHOPT_FS_3D */
}
- rval = newdirfd = sh_diropenat(shp, shp->pwdfd,
+ rval = newdirfd = sh_diropenat(shp, dirfd,
path_relative(shp,stakptr(PATH_OFFSET)), xattr);
if(newdirfd >=0)
{
@@ -346,7 +355,7 @@
if(rval<0 && *dir=='/' && *(path_relative(shp,stakptr(PATH_OFFSET)))!='/')
{
rval = newdirfd = sh_diropenat(shp,
- shp->pwdfd,
+ dirfd,
dir, xattr);
if(newdirfd >=0)
{
diff -r -u build_i386_64bit_debug/src/cmd/ksh93/data/builtins.c build_i386_64bit_debug_cd_f/src/cmd/ksh93/data/builtins.c
--- src/cmd/ksh93/data/builtins.c 2013-05-30 05:34:48.000000000 +0200
+++ src/cmd/ksh93/data/builtins.c 2013-06-20 12:52:28.993198173 +0200
@@ -446,7 +446,7 @@
;

const char sh_optcd[] =
-"[-1c?\n@(#)$Id: cd (AT&T Research) 2012-07-10 $\n]"
+"[-1c?\n@(#)$Id: cd (AT&T Research) 2013-06-20 $\n]"
USAGE_LICENSE
"[+NAME?cd - change working directory ]"
"[+DESCRIPTION?\bcd\b changes the current working directory of the "
@@ -482,6 +482,9 @@
"\bPATH_RESOLVE\b. If \bPATH_RESOLVE\b is \bphysical\b, "
"then the behavior will be as if \b-P\b were specified. Otherwise, "
"the behavior will be as if \b-L\b were specified.]"
+#ifdef AT_FDCWD
+"[f]#[dirfd?Path is relative to this directory fd.]"
+#endif
"[L?Handle each pathname component \b..\b in a logical fashion by moving "
"up one level by name in the present working directory.]"
"[P?The present working directory is first converted to an absolute pathname "
Roland Mainz
2013-06-20 18:30:23 UTC
Permalink
Post by Roland Mainz
On Wed, Jun 19, 2013 at 5:49 PM, Cedric Blancher
cc: ast-developers at research.att.com
Subject: Re: [ast-developers] When will the tree reopen for normal patches?
--------
cd /dev/fd/$d no longer works
What do you mean that it no longer works, I just did
exec 9< /tmp
and was able to do
cd /dev/fd/9/foo
to change to /tmp/foo.
/bin/ksh -c 'exec {n}</etc ; cd /dev/fd/$n/ ; true'
/bin/ksh: cd: /dev/fd/11/: [Bad address]
This has been reported to ast-developers at research.att.com several
times. Search for '[Bad address]'.
There were also requests for cd -f $n relative_path to allow relative
paths which go above the starting point of fd, e.g. cd -f $n ../../a/b
The other reason for cd -f $fd relative_path was that POSIX does not
standardise absolute paths and that bash and dash developers see it as
a cleaner API to openat() than using /dev/fd
Attached (as "astksh_20130613_cd_f_dirfd_002.diff.txt") is the patch
to add $ cd -f $fd # ... it's more or less the same solution which was
proposed for bash4&&dash, too.
Attached (as "astksh_20130613_cd_f_dirfd_003.diff.txt") is an updated
patch which fixes the issue that the "pwd" builtin was unable to
determinate the current cwd location.

The fix works the same way how Sun's Solaris and other OSes with NFSv4
XATTR support handled the issue in their Bourne shell+csh versions.

Example:
-- snip --
$ ksh -c 'redirect {n}<"/etc" ; cd -f $n X11 ; pwd -P; pwd -L ; true'
-- snip --
... will print...
-- snip --
/etc/X11
.
-- snip --
... "/etc/X11" is the physical location... but we use "." as the
logical location since the logical cwd can not successfully be
determinated... for example because the directory the descriptor $n is
pointing to may have moved or the location wasn't know from the
beginning (David: No... a tracking cache doesn't help if an external
process or filesystem deamon renames the directory). We can't let
"pwd" return an error... Sun once determinated that it breaks too many
scripts (while using "." as logical name seems to work) ... ;-(

More complex example:
-- snip --
$ bash -c 'rm -Rf transaction_done ;mkdir transaction1 ; exec
{n}<"transaction1" ; n=$n ~/bin/ksh -c "mv transaction1
transaction_done ; cd -f \$n . ; pwd -L ; pwd -P ; true"'
.
/home/test001/tmp/l1/transaction_done
-- snip --
"." is used as logical name since there is no name associated with the
file descriptor at the time the shell obtains the fd.

----

Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
-------------- next part --------------
diff -r -u build_i386_64bit_debug/src/cmd/ksh93/bltins/cd_pwd.c build_i386_64bit_debug_cd_f/src/cmd/ksh93/bltins/cd_pwd.c
--- build_i386_64bit_debug/src/cmd/ksh93/bltins/cd_pwd.c 2013-05-16 16:36:14.000000000 +0200
+++ build_i386_64bit_debug_cd_f/src/cmd/ksh93/bltins/cd_pwd.c 2013-06-20 20:03:23.354628290 +0200
@@ -19,8 +19,8 @@
***********************************************************************/
#pragma prototyped
/*
- * cd [-LP@] [dirname]
- * cd [-LP@] [old] [new]
+ * cd [-LP@] [-f dirfd] [dirname]
+ * cd [-LP@] [-fdirfd] [old] [new]
* pwd [-LP]
*
* David Korn
@@ -114,7 +114,7 @@
{
while(*p=='/')
p++;
- path = *p?(const char*)p:0;
+ path = *p?(const char*)p:e_dot;
dir = fd;
}
}
@@ -169,14 +169,24 @@
register Shell_t *shp = context->shp;
int saverrno=0;
int rval;
- bool flag=false,xattr=false;
+ bool flag=false,xattr=false,unset_pwdnod=false;
char *oldpwd;
+ int dirfd = shp->pwdfd;
int newdirfd;
Namval_t *opwdnod, *pwdnod;
if(sh_isoption(shp,SH_RESTRICTED))
errormsg(SH_DICT,ERROR_exit(1),e_restricted+4);
while((rval = optget(argv,sh_optcd))) switch(rval)
{
+#ifdef AT_FDCWD
+ case 'f':
+ errno = 0;
+ dirfd = strtol(opt_info.arg, (char **)NULL, 10);
+ if ((errno != 0) || (dirfd < 0))
+ errormsg(SH_DICT, ERROR_system(1), "%s: invalid dir fd", opt_info.arg);
+ unset_pwdnod=true;
+ break;
+#endif
case 'L':
flag = false;
break;
@@ -186,6 +196,7 @@
#ifdef O_XATTR
case '@':
xattr = true;
+ unset_pwdnod=true;
break;
#endif
case ':':
@@ -307,7 +318,7 @@
continue;
#endif /* SHOPT_FS_3D */
}
- rval = newdirfd = sh_diropenat(shp, shp->pwdfd,
+ rval = newdirfd = sh_diropenat(shp, dirfd,
path_relative(shp,stakptr(PATH_OFFSET)), xattr);
if(newdirfd >=0)
{
@@ -346,7 +357,7 @@
if(rval<0 && *dir=='/' && *(path_relative(shp,stakptr(PATH_OFFSET)))!='/')
{
rval = newdirfd = sh_diropenat(shp,
- shp->pwdfd,
+ dirfd,
dir, xattr);
if(newdirfd >=0)
{
@@ -403,9 +414,17 @@
/* delete trailing '/' */
while(--flag>0 && dir[flag]=='/')
dir[flag] = 0;
- nv_putval(pwdnod,dir,NV_RDONLY);
- nv_onattr(pwdnod,NV_NOFREE|NV_EXPORT);
- shp->pwd = pwdnod->nvalue.cp;
+ if (unset_pwdnod)
+ {
+ nv_unset(pwdnod);
+ shp->pwd = strdup(e_dot);
+ }
+ else
+ {
+ nv_putval(pwdnod,dir,NV_RDONLY);
+ nv_onattr(pwdnod,NV_NOFREE|NV_EXPORT);
+ shp->pwd = pwdnod->nvalue.cp;
+ }
nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED);
path_newdir(shp,shp->pathlist);
path_newdir(shp,shp->cdpathlist);
@@ -416,17 +435,18 @@

int b_pwd(int argc, char *argv[],Shbltin_t *context)
{
- register int n, flag = 0;
- register char *cp;
+ register int n;
+ bool pflag = false;
+ register char *cp, *freecp=NULL;
register Shell_t *shp = context->shp;
NOT_USED(argc);
while((n = optget(argv,sh_optpwd))) switch(n)
{
case 'L':
- flag = 0;
+ pflag = false;
break;
case 'P':
- flag = 1;
+ pflag = true;
break;
case ':':
errormsg(SH_DICT,2, "%s", opt_info.arg);
@@ -437,22 +457,44 @@
}
if(error_info.errors)
errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
- if(*(cp = path_pwd(shp,0)) != '/')
+ cp = path_pwd(shp,0);
+ if(!((*cp == '/') || (cp[0] == '.' && cp[1] == '\0')))
errormsg(SH_DICT,ERROR_system(1), e_pwd);
- if(flag)
+ if(pflag)
{
+ int mc;
+
+ /*
+ * Try the hard way to find the physical location.
+ * This may happen for NFSv4 xattr directories,
+ * Solaris samfs and some other special cases
+ * which may not have a proper logical name when
+ * "cd" was used.
+ */
+ if(cp[0] == '.' && cp[1] == '\0')
+ {
+ freecp = cp = getcwd(NULL, 0);
+ if (!cp)
+ errormsg(SH_DICT,ERROR_system(1), e_pwd);
+ }
+
#if SHOPT_FS_3D
- if(shp->gd->lim.fs3d && (flag = mount(e_dot,NIL(char*),FS3D_GET|FS3D_VIEW,0))>=0)
+ if(shp->gd->lim.fs3d && (mc = mount(e_dot,NIL(char*),FS3D_GET|FS3D_VIEW,0))>=0)
{
- cp = (char*)stakseek(++flag+PATH_MAX);
- mount(e_dot,cp,FS3D_GET|FS3D_VIEW|FS3D_SIZE(flag),0);
+ cp = (char*)stakseek(++mc+PATH_MAX);
+ mount(e_dot,cp,FS3D_GET|FS3D_VIEW|FS3D_SIZE(mc),0);
}
else
#endif /* SHOPT_FS_3D */
cp = strcpy(stakseek(strlen(cp)+PATH_MAX),cp);
pathcanon(cp,PATH_MAX,PATH_PHYSICAL);
}
+
sfputr(sfstdout,cp,'\n');
+
+ if (freecp)
+ free(freecp);
+
return(0);
}

diff -r -u build_i386_64bit_debug/src/cmd/ksh93/data/builtins.c build_i386_64bit_debug_cd_f/src/cmd/ksh93/data/builtins.c
--- build_i386_64bit_debug/src/cmd/ksh93/data/builtins.c 2013-05-30 05:34:48.000000000 +0200
+++ build_i386_64bit_debug_cd_f/src/cmd/ksh93/data/builtins.c 2013-06-20 12:52:28.993198173 +0200
@@ -446,7 +446,7 @@
;

const char sh_optcd[] =
-"[-1c?\n@(#)$Id: cd (AT&T Research) 2012-07-10 $\n]"
+"[-1c?\n@(#)$Id: cd (AT&T Research) 2013-06-20 $\n]"
USAGE_LICENSE
"[+NAME?cd - change working directory ]"
"[+DESCRIPTION?\bcd\b changes the current working directory of the "
@@ -482,6 +482,9 @@
"\bPATH_RESOLVE\b. If \bPATH_RESOLVE\b is \bphysical\b, "
"then the behavior will be as if \b-P\b were specified. Otherwise, "
"the behavior will be as if \b-L\b were specified.]"
+#ifdef AT_FDCWD
+"[f]#[dirfd?Path is relative to this directory fd.]"
+#endif
"[L?Handle each pathname component \b..\b in a logical fashion by moving "
"up one level by name in the present working directory.]"
"[P?The present working directory is first converted to an absolute pathname "
Roland Mainz
2013-06-20 18:55:09 UTC
Permalink
Post by Roland Mainz
Post by Roland Mainz
On Wed, Jun 19, 2013 at 5:49 PM, Cedric Blancher
cc: ast-developers at research.att.com
Subject: Re: [ast-developers] When will the tree reopen for normal patches?
--------
cd /dev/fd/$d no longer works
What do you mean that it no longer works, I just did
exec 9< /tmp
and was able to do
cd /dev/fd/9/foo
to change to /tmp/foo.
/bin/ksh -c 'exec {n}</etc ; cd /dev/fd/$n/ ; true'
/bin/ksh: cd: /dev/fd/11/: [Bad address]
This has been reported to ast-developers at research.att.com several
times. Search for '[Bad address]'.
There were also requests for cd -f $n relative_path to allow relative
paths which go above the starting point of fd, e.g. cd -f $n ../../a/b
The other reason for cd -f $fd relative_path was that POSIX does not
standardise absolute paths and that bash and dash developers see it as
a cleaner API to openat() than using /dev/fd
Attached (as "astksh_20130613_cd_f_dirfd_002.diff.txt") is the patch
to add $ cd -f $fd # ... it's more or less the same solution which was
proposed for bash4&&dash, too.
Attached (as "astksh_20130613_cd_f_dirfd_003.diff.txt") is an updated
patch which fixes the issue that the "pwd" builtin was unable to
determinate the current cwd location.
The fix works the same way how Sun's Solaris and other OSes with NFSv4
XATTR support handled the issue in their Bourne shell+csh versions.
-- snip --
$ ksh -c 'redirect {n}<"/etc" ; cd -f $n X11 ; pwd -P; pwd -L ; true'
-- snip --
... will print...
-- snip --
/etc/X11
.
-- snip --
... "/etc/X11" is the physical location... but we use "." as the
logical location since the logical cwd can not successfully be
determinated... for example because the directory the descriptor $n is
pointing to may have moved or the location wasn't know from the
beginning (David: No... a tracking cache doesn't help if an external
process or filesystem deamon renames the directory). We can't let
"pwd" return an error... Sun once determinated that it breaks too many
scripts (while using "." as logical name seems to work) ... ;-(
-- snip --
$ bash -c 'rm -Rf transaction_done ;mkdir transaction1 ; exec
{n}<"transaction1" ; n=$n ~/bin/ksh -c "mv transaction1
transaction_done ; cd -f \$n . ; pwd -L ; pwd -P ; true"'
.
/home/test001/tmp/l1/transaction_done
-- snip --
"." is used as logical name since there is no name associated with the
file descriptor at the time the shell obtains the fd.
... and finally... in the case David&&Glenn do not like the idea of
"." being returned as logical directory by the "pwd" builtin is a
patch (as "astksh_20130613_cd_f_dirfd_003_alternative1_no_logicalpwd_dot.diff.txt")
which throws an error if someone wants to access the logical
directory.

----

Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
-------------- next part --------------
diff -r -u build_i386_64bit_debug/src/cmd/ksh93/bltins/cd_pwd.c build_i386_64bit_debug_cd_f/src/cmd/ksh93/bltins/cd_pwd.c
--- build_i386_64bit_debug/src/cmd/ksh93/bltins/cd_pwd.c 2013-05-16 16:36:14.000000000 +0200
+++ build_i386_64bit_debug_cd_f/src/cmd/ksh93/bltins/cd_pwd.c 2013-06-20 20:46:33.378961553 +0200
@@ -19,8 +19,8 @@
***********************************************************************/
#pragma prototyped
/*
- * cd [-LP@] [dirname]
- * cd [-LP@] [old] [new]
+ * cd [-LP@] [-f dirfd] [dirname]
+ * cd [-LP@] [-fdirfd] [old] [new]
* pwd [-LP]
*
* David Korn
@@ -114,7 +114,7 @@
{
while(*p=='/')
p++;
- path = *p?(const char*)p:0;
+ path = *p?(const char*)p:e_dot;
dir = fd;
}
}
@@ -169,14 +169,24 @@
register Shell_t *shp = context->shp;
int saverrno=0;
int rval;
- bool flag=false,xattr=false;
+ bool flag=false,xattr=false,unset_pwdnod=false;
char *oldpwd;
+ int dirfd = shp->pwdfd;
int newdirfd;
Namval_t *opwdnod, *pwdnod;
if(sh_isoption(shp,SH_RESTRICTED))
errormsg(SH_DICT,ERROR_exit(1),e_restricted+4);
while((rval = optget(argv,sh_optcd))) switch(rval)
{
+#ifdef AT_FDCWD
+ case 'f':
+ errno = 0;
+ dirfd = strtol(opt_info.arg, (char **)NULL, 10);
+ if ((errno != 0) || (dirfd < 0))
+ errormsg(SH_DICT, ERROR_system(1), "%s: invalid dir fd", opt_info.arg);
+ unset_pwdnod=true;
+ break;
+#endif
case 'L':
flag = false;
break;
@@ -186,6 +196,7 @@
#ifdef O_XATTR
case '@':
xattr = true;
+ unset_pwdnod=true;
break;
#endif
case ':':
@@ -307,7 +318,7 @@
continue;
#endif /* SHOPT_FS_3D */
}
- rval = newdirfd = sh_diropenat(shp, shp->pwdfd,
+ rval = newdirfd = sh_diropenat(shp, dirfd,
path_relative(shp,stakptr(PATH_OFFSET)), xattr);
if(newdirfd >=0)
{
@@ -346,7 +357,7 @@
if(rval<0 && *dir=='/' && *(path_relative(shp,stakptr(PATH_OFFSET)))!='/')
{
rval = newdirfd = sh_diropenat(shp,
- shp->pwdfd,
+ dirfd,
dir, xattr);
if(newdirfd >=0)
{
@@ -403,9 +414,17 @@
/* delete trailing '/' */
while(--flag>0 && dir[flag]=='/')
dir[flag] = 0;
- nv_putval(pwdnod,dir,NV_RDONLY);
- nv_onattr(pwdnod,NV_NOFREE|NV_EXPORT);
- shp->pwd = pwdnod->nvalue.cp;
+ if (unset_pwdnod)
+ {
+ nv_unset(pwdnod);
+ shp->pwd = strdup(e_dot);
+ }
+ else
+ {
+ nv_putval(pwdnod,dir,NV_RDONLY);
+ nv_onattr(pwdnod,NV_NOFREE|NV_EXPORT);
+ shp->pwd = pwdnod->nvalue.cp;
+ }
nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED);
path_newdir(shp,shp->pathlist);
path_newdir(shp,shp->cdpathlist);
@@ -416,17 +435,18 @@

int b_pwd(int argc, char *argv[],Shbltin_t *context)
{
- register int n, flag = 0;
- register char *cp;
+ register int n;
+ bool pflag = false;
+ register char *cp, *freecp=NULL;
register Shell_t *shp = context->shp;
NOT_USED(argc);
while((n = optget(argv,sh_optpwd))) switch(n)
{
case 'L':
- flag = 0;
+ pflag = false;
break;
case 'P':
- flag = 1;
+ pflag = true;
break;
case ':':
errormsg(SH_DICT,2, "%s", opt_info.arg);
@@ -437,22 +457,47 @@
}
if(error_info.errors)
errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
- if(*(cp = path_pwd(shp,0)) != '/')
- errormsg(SH_DICT,ERROR_system(1), e_pwd);
- if(flag)
+ cp = path_pwd(shp,0);
+ if(pflag)
{
+ int mc;
+
+ /*
+ * Try the hard way to find the physical location.
+ * This may happen for NFSv4 xattr directories,
+ * Solaris samfs and some other special cases
+ * which may not have a proper logical name when
+ * "cd" was used.
+ */
+ if(*cp != '/')
+ {
+ freecp = cp = getcwd(NULL, 0);
+ if (!cp)
+ errormsg(SH_DICT,ERROR_system(1), e_pwd);
+ }
+
#if SHOPT_FS_3D
- if(shp->gd->lim.fs3d && (flag = mount(e_dot,NIL(char*),FS3D_GET|FS3D_VIEW,0))>=0)
+ if(shp->gd->lim.fs3d && (mc = mount(e_dot,NIL(char*),FS3D_GET|FS3D_VIEW,0))>=0)
{
- cp = (char*)stakseek(++flag+PATH_MAX);
- mount(e_dot,cp,FS3D_GET|FS3D_VIEW|FS3D_SIZE(flag),0);
+ cp = (char*)stakseek(++mc+PATH_MAX);
+ mount(e_dot,cp,FS3D_GET|FS3D_VIEW|FS3D_SIZE(mc),0);
}
else
#endif /* SHOPT_FS_3D */
cp = strcpy(stakseek(strlen(cp)+PATH_MAX),cp);
pathcanon(cp,PATH_MAX,PATH_PHYSICAL);
}
+ else
+ {
+ if(*cp != '/')
+ errormsg(SH_DICT,ERROR_system(1), e_pwd);
+ }
+
sfputr(sfstdout,cp,'\n');
+
+ if (freecp)
+ free(freecp);
+
return(0);
}

diff -r -u build_i386_64bit_debug/src/cmd/ksh93/data/builtins.c build_i386_64bit_debug_cd_f/src/cmd/ksh93/data/builtins.c
--- build_i386_64bit_debug/src/cmd/ksh93/data/builtins.c 2013-05-30 05:34:48.000000000 +0200
+++ build_i386_64bit_debug_cd_f/src/cmd/ksh93/data/builtins.c 2013-06-20 12:52:28.993198173 +0200
@@ -446,7 +446,7 @@
;

const char sh_optcd[] =
-"[-1c?\n@(#)$Id: cd (AT&T Research) 2012-07-10 $\n]"
+"[-1c?\n@(#)$Id: cd (AT&T Research) 2013-06-20 $\n]"
USAGE_LICENSE
"[+NAME?cd - change working directory ]"
"[+DESCRIPTION?\bcd\b changes the current working directory of the "
@@ -482,6 +482,9 @@
"\bPATH_RESOLVE\b. If \bPATH_RESOLVE\b is \bphysical\b, "
"then the behavior will be as if \b-P\b were specified. Otherwise, "
"the behavior will be as if \b-L\b were specified.]"
+#ifdef AT_FDCWD
+"[f]#[dirfd?Path is relative to this directory fd.]"
+#endif
"[L?Handle each pathname component \b..\b in a logical fashion by moving "
"up one level by name in the present working directory.]"
"[P?The present working directory is first converted to an absolute pathname "
Only in build_i386_64bit_debug_cd_f/src/cmd/ksh93/tests: arrays.sh
Roland Mainz
2013-06-20 18:56:51 UTC
Permalink
Post by Roland Mainz
Post by Roland Mainz
Post by Roland Mainz
On Wed, Jun 19, 2013 at 5:49 PM, Cedric Blancher
cc: ast-developers at research.att.com
Subject: Re: [ast-developers] When will the tree reopen for normal patches?
--------
cd /dev/fd/$d no longer works
What do you mean that it no longer works, I just did
exec 9< /tmp
and was able to do
cd /dev/fd/9/foo
to change to /tmp/foo.
/bin/ksh -c 'exec {n}</etc ; cd /dev/fd/$n/ ; true'
/bin/ksh: cd: /dev/fd/11/: [Bad address]
This has been reported to ast-developers at research.att.com several
times. Search for '[Bad address]'.
There were also requests for cd -f $n relative_path to allow relative
paths which go above the starting point of fd, e.g. cd -f $n ../../a/b
The other reason for cd -f $fd relative_path was that POSIX does not
standardise absolute paths and that bash and dash developers see it as
a cleaner API to openat() than using /dev/fd
Attached (as "astksh_20130613_cd_f_dirfd_002.diff.txt") is the patch
to add $ cd -f $fd # ... it's more or less the same solution which was
proposed for bash4&&dash, too.
Attached (as "astksh_20130613_cd_f_dirfd_003.diff.txt") is an updated
patch which fixes the issue that the "pwd" builtin was unable to
determinate the current cwd location.
The fix works the same way how Sun's Solaris and other OSes with NFSv4
XATTR support handled the issue in their Bourne shell+csh versions.
-- snip --
$ ksh -c 'redirect {n}<"/etc" ; cd -f $n X11 ; pwd -P; pwd -L ; true'
-- snip --
... will print...
-- snip --
/etc/X11
.
-- snip --
... "/etc/X11" is the physical location... but we use "." as the
logical location since the logical cwd can not successfully be
determinated... for example because the directory the descriptor $n is
pointing to may have moved or the location wasn't know from the
beginning (David: No... a tracking cache doesn't help if an external
process or filesystem deamon renames the directory). We can't let
"pwd" return an error... Sun once determinated that it breaks too many
scripts (while using "." as logical name seems to work) ... ;-(
-- snip --
$ bash -c 'rm -Rf transaction_done ;mkdir transaction1 ; exec
{n}<"transaction1" ; n=$n ~/bin/ksh -c "mv transaction1
transaction_done ; cd -f \$n . ; pwd -L ; pwd -P ; true"'
.
/home/test001/tmp/l1/transaction_done
-- snip --
"." is used as logical name since there is no name associated with the
file descriptor at the time the shell obtains the fd.
... and finally... in the case David&&Glenn do not like the idea of
"." being returned as logical directory by the "pwd" builtin is a
patch (as "astksh_20130613_cd_f_dirfd_003_alternative1_no_logicalpwd_dot.diff.txt")
which throws an error if someone wants to access the logical
directory.
[sorry... I send the email too fast without proofreading]

s/wants to access the logical directory/wants to obtain the logical
cwd name/ when the shell is not able to determinate it.

----

Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
Irek Szczesniak
2013-06-20 20:47:34 UTC
Permalink
Post by Roland Mainz
Post by Roland Mainz
Post by Roland Mainz
On Wed, Jun 19, 2013 at 5:49 PM, Cedric Blancher
cc: ast-developers at research.att.com
Subject: Re: [ast-developers] When will the tree reopen for normal patches?
--------
cd /dev/fd/$d no longer works
What do you mean that it no longer works, I just did
exec 9< /tmp
and was able to do
cd /dev/fd/9/foo
to change to /tmp/foo.
/bin/ksh -c 'exec {n}</etc ; cd /dev/fd/$n/ ; true'
/bin/ksh: cd: /dev/fd/11/: [Bad address]
This has been reported to ast-developers at research.att.com several
times. Search for '[Bad address]'.
There were also requests for cd -f $n relative_path to allow relative
paths which go above the starting point of fd, e.g. cd -f $n ../../a/b
The other reason for cd -f $fd relative_path was that POSIX does not
standardise absolute paths and that bash and dash developers see it as
a cleaner API to openat() than using /dev/fd
Attached (as "astksh_20130613_cd_f_dirfd_002.diff.txt") is the patch
to add $ cd -f $fd # ... it's more or less the same solution which was
proposed for bash4&&dash, too.
Attached (as "astksh_20130613_cd_f_dirfd_003.diff.txt") is an updated
patch which fixes the issue that the "pwd" builtin was unable to
determinate the current cwd location.
The fix works the same way how Sun's Solaris and other OSes with NFSv4
XATTR support handled the issue in their Bourne shell+csh versions.
-- snip --
$ ksh -c 'redirect {n}<"/etc" ; cd -f $n X11 ; pwd -P; pwd -L ; true'
-- snip --
... will print...
-- snip --
/etc/X11
.
-- snip --
... "/etc/X11" is the physical location... but we use "." as the
logical location since the logical cwd can not successfully be
determinated... for example because the directory the descriptor $n is
pointing to may have moved or the location wasn't know from the
beginning (David: No... a tracking cache doesn't help if an external
process or filesystem deamon renames the directory). We can't let
"pwd" return an error... Sun once determinated that it breaks too many
scripts (while using "." as logical name seems to work) ... ;-(
-- snip --
$ bash -c 'rm -Rf transaction_done ;mkdir transaction1 ; exec
{n}<"transaction1" ; n=$n ~/bin/ksh -c "mv transaction1
transaction_done ; cd -f \$n . ; pwd -L ; pwd -P ; true"'
.
/home/test001/tmp/l1/transaction_done
-- snip --
"." is used as logical name since there is no name associated with the
file descriptor at the time the shell obtains the fd.
... and finally... in the case David&&Glenn do not like the idea of
"." being returned as logical directory by the "pwd" builtin is a
patch (as "astksh_20130613_cd_f_dirfd_003_alternative1_no_logicalpwd_dot.diff.txt")
which throws an error if someone wants to access the logical
directory.
I think this is the better solution because POSIX (in
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pwd.html)
says "...The pwd utility shall write to standard output an absolute
pathname of the current working directory, which does not contain the
filenames dot or dot-dot...". If the pwd utility can't determinate the
name of the cwd it should return an error.

The hard case aren't the directories relative to a directory file
descriptor, the hard cases are the NFSv4 and CIFS/SMBFS O_XATTR
directories which neither have logical or physical names. Obtaining
the logical path can fail - but what should we return as physical name
in such a case? Let pwd fail with an error message too?

I'll test the patch against CIFS today.

Irek
David Korn
2013-06-24 21:56:36 UTC
Permalink
cc: ast-developers at research.att.com
Subject: Re: Re: [patch] Add $ cd -f $dirfd relative_path # to "cd" builtin... / was: Re: [ast-developers] When will the tree reopen for normal patches?
--------
Post by Roland Mainz
-- snip --
$ bash -c 'rm -Rf transaction_done ;mkdir transaction1 ; exec
{n}<"transaction1" ; n=$n ~/bin/ksh -c "mv transaction1
transaction_done ; cd -f \$n . ; pwd -L ; pwd -P ; true"'
.
/home/test001/tmp/l1/transaction_done
-- snip --
This example seems to violate POSIX.

redirect {n}<"/etc" opens file descritor $n with close-on exec
so it will be close for ksh.

Maybe you meant:

rm -Rf transaction_done ;mkdir transaction1
n=$n ~/bin/ksh -c "mv transaction1 > transaction_done ; cd -f \$n . ; pwd -L ; pwd -P ; true" {n}<"transaction1"


This works in ksh bug gives a pathname for the logical directory
and the output is
/proc/19478/fd/11
/home/dgk/src/cmd/ksh93/gsf9/transaction_done



David Korn
dgk at research.att.com

Loading...