On Thu, Jun 20, 2013 at 1:13 PM, Roland Mainz <[email protected]> wrote:
> On Wed, Jun 19, 2013 at 5:49 PM, Cedric Blancher
> <[email protected]> wrote:
>> On 19 June 2013 16:16, David Korn <[email protected]> wrote:
>>> cc: [email protected]
>>> 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 [email protected] 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) [email protected]
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
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 "
_______________________________________________
ast-developers mailing list
[email protected]
http://lists.research.att.com/mailman/listinfo/ast-developers