Hi!

----

Attached (as "astksh_chroot_cd_devfd_cd_f_20120911_001.diff.txt") is a
patch which fixes two issues with "cd":
1. $ cd /dev/fd/$fd # doesn't work in chroot'ed environments when
/dev/fd is not mounted (thanks to CERN staff for reporting this).
2. POSIX does not mandate _any_ paths. Since doing a "cd" relative to
a directory fd has become very popular the request was made to add an
alternative to using /dev/fd which is more or less acceptable for the
POSIX people. Based on that and a few discussions I added the option
-f to cd that a directory descriptor can be passed and the path given
is relative to that file descriptor.

Notes:
- The code introduces a new function called |pathdevfd2relpathfd()| in
libast which can extract the fd number from a /dev/fd/$fd path (even
nested)
- If files or directories are opened relative to /dev/fd/$fd/$path
|sfopen()|/|sfopenat()| will now bypass the /dev/fd filesystem
completely (which gives a nice performance boost). The only exception
is that this can *NOT* be done for a plain /dev/fd/$fd, e.g.
/dev/fd/15. The problem is that there is AFAIK no way to open a file
from a file descriptor without using the /dev/fd filesystem or using
|dup()| ... but |dup()| rules itself out because the resulting
"cloned" fd still shares attributes like the current seek position
with the original fd...

Glenn: Is it acceptable for |sfopen()| to |dup()| the incoming file fd
(see "Notes" above) ?

----

Bye,
Roland

-- 
  __ .  . __
 (o.\ \/ /.o) roland.ma...@nrubsig.org
  \__\/\/__/  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
  /O /==\ O\  TEL +49 641 3992797
 (;O/ \/ \O;)
diff -r -u -N original/src/cmd/ksh93/bltins/cd_pwd.c 
build_fd/src/cmd/ksh93/bltins/cd_pwd.c
--- src/cmd/ksh93/bltins/cd_pwd.c       2012-08-09 15:24:15.000000000 +0200
+++ src/cmd/ksh93/bltins/cd_pwd.c       2012-09-14 04:28:45.561627242 +0200
@@ -19,8 +19,8 @@
 ***********************************************************************/
 #pragma prototyped
 /*
- * cd [-LP@]  [dirname]
- * cd [-LP@]  [old] [new]
+ * cd [-LP@f]  [dirname]
+ * cd [-LP@f]  [old] [new]
  * pwd [-LP]
  *
  *   David Korn
@@ -68,6 +68,10 @@
        NOT_USED(xattr);
 #endif
 
+       path = pathdevfd2relpathfd(path, &dir);
+       if (!path)
+               path = e_dot;
+
 #ifdef O_XATTR
        if(xattr)
        {
@@ -157,12 +161,21 @@
        int saverrno=0;
        int rval,flag=0,xattr=0;
        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 = 0;
                        break;
@@ -244,14 +257,18 @@
                        dir = sfstruse(shp->strbuf);
                }
        }
-#ifdef O_XATTR
-       if (xattr)
-#   ifdef PATH_BFPATH
+       if (
+#if defined(O_XATTR) || defined(AT_FDCWD)
+#      ifdef O_XATTR
+               xattr ||
+#      endif
+               (shp->pwdfd != dirfd))
+#      ifdef PATH_BFPATH
                cdpath = NULL;
-#   else
+#      else
                cdpath = "";
-#   endif
-#endif
+#      endif
+#endif /* defined(O_XATTR) || defined(AT_FDCWD) */
 
        rval = -1;
        do
@@ -294,7 +311,7 @@
 #endif /* SHOPT_FS_3D */
                }
                rval = newdirfd = sh_diropenat(shp,
-                       ((shp->pwdfd >= 0)?shp->pwdfd:AT_FDCWD),
+                       ((dirfd >= 0)?dirfd:AT_FDCWD),
                        path_relative(shp,stakptr(PATH_OFFSET)), xattr);
                if(newdirfd >=0)
                {
diff -r -u -N original/src/cmd/ksh93/data/builtins.c 
build_fd/src/cmd/ksh93/data/builtins.c
--- src/cmd/ksh93/data/builtins.c       2012-09-05 23:59:37.000000000 +0200
+++ src/cmd/ksh93/data/builtins.c       2012-09-14 02:24:42.136895254 +0200
@@ -442,7 +442,7 @@
 ;
 
 const char sh_optcd[] =
-"[-1c?\n@(#)$Id: cd (AT&T Research) 2012-07-10 $\n]"
+"[-1c?\n@(#)$Id: cd (AT&T Research) 2012-09-11 $\n]"
 USAGE_LICENSE
 "[+NAME?cd - change working directory ]"
 "[+DESCRIPTION?\bcd\b changes the current working directory of the "
@@ -478,6 +478,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 "
diff -r -u -N original/src/cmd/ksh93/sh/io.c build_fd/src/cmd/ksh93/sh/io.c
--- src/cmd/ksh93/sh/io.c       2012-09-05 23:53:53.000000000 +0200
+++ src/cmd/ksh93/sh/io.c       2012-09-14 04:40:26.639221455 +0200
@@ -755,6 +755,10 @@
        register int            fd = -1;
        mode_t                  mode;
        char                    *e;
+#ifdef AT_FDCWD
+       const char              *apath;
+       int                     dirfd = shp->pwdfd;
+#endif
        va_list                 ap;
        va_start(ap, flags);
        mode = (flags & O_CREAT) ? va_arg(ap, int) : 0;
@@ -770,10 +774,37 @@
                errno = ENOENT;
                return(-1);
        }
+#ifdef AT_FDCWD
+       if (path[0]=='/')
+       {
+               apath = pathdevfd2relpathfd(path, &dirfd);
+               /*
+                * |pathdevfd2relpathfd()| will return |NULL| if
+                * /dev/fd/${num} is not followed by a path.
+                * Question is whether we can use |dup()| in
+                * such a case (warning: |dup()| will cause both
+                * old and new fd to share attributes like the
+                * seek position)
+                */
+               if (apath)
+                       path = apath;
+               else if (path[strlen(path)-1]=='/')
+               {
+                       /*
+                        * If |pathdevfd2relpathfd()| returned |NULL|
+                        * and the input path ends with a '/' (e.g.
+                        * "/dev/fd/89/") we can happily assume it's
+                        * a directory...
+                        */
+                       path = e_dot;
+               }
+       }
+#endif /* AT_FDCWD */
        if (path[0]=='/' && path[1]=='d' && path[2]=='e' && path[3]=='v' && 
path[4]=='/')
        {
                switch (path[5])
                {
+#ifndef AT_FDCWD
                case 'f':
                        if (path[6]=='d' && path[7]=='/')
                        {
@@ -784,6 +815,7 @@
                                        fd = -1;
                        }
                        break;
+#endif
                case 's':
                        if (path[6]=='t' && path[7]=='d')
                                switch (path[8])
@@ -824,13 +856,21 @@
                        struct stat st;
                        if (stat(path,&st) >=0)
                        {
+#ifdef AT_FDCWD
+                               while((nfd = 
openat(dirfd,path,flags,st.st_mode))<0 && errno==EINTR)
+#else
                                while((nfd = open(path,flags,st.st_mode))<0 && 
errno==EINTR)
+#endif
                                        errno = err;
                        }
                }
                else
                {
+#ifdef AT_FDCWD
+                       while((nfd = openat(dirfd,path,flags))<0 && 
errno==EINTR)
+#else
                        while((nfd = open(path,flags))<0 && errno==EINTR)
+#endif
                                errno = err;
                }
                if(nfd>=0)
@@ -858,7 +898,11 @@
                        path = buf;
                }
 #endif
+#ifdef AT_FDCWD
+               while((fd = openat(dirfd, path, flags, mode)) < 0)
+#else
                while((fd = open(path, flags, mode)) < 0)
+#endif
                        if(errno!=EINTR || shp->trapnote)
                                return(-1);
        }
diff -r -u -N original/src/lib/libast/include/ast.h 
build_fd/src/lib/libast/include/ast.h
--- src/lib/libast/include/ast.h        2012-08-09 09:24:49.000000000 +0200
+++ src/lib/libast/include/ast.h        2012-09-14 03:37:52.182403240 +0200
@@ -300,6 +300,7 @@
 extern char*           pathcat_20100601(const char*, int, const char*, const 
char*, char*, size_t);
 extern int             pathcd(const char*, const char*);
 extern int             pathcheck(const char*, const char*, Pathcheck_t*);
+extern const char *    pathdevfd2relpathfd(const char *, int *);
 extern int             pathexists(char*, int);
 extern char*           pathfind(const char*, const char*, const char*, char*, 
size_t);
 extern int             pathgetlink(const char*, char*, int);
diff -r -u -N original/src/lib/libast/Makefile build_fd/src/lib/libast/Makefile
--- src/lib/libast/Makefile     2012-07-31 20:29:26.000000000 +0200
+++ src/lib/libast/Makefile     2012-09-14 03:40:38.780372849 +0200
@@ -79,7 +79,7 @@
        pathexists.c pathfind.c pathkey.c pathprobe.c pathrepl.c \
        pathnative.c pathposix.c pathtemp.c pathtmp.c pathstat.c \
        pathgetlink.c pathsetlink.c pathbin.c pathshell.c pathcd.c \
-       pathprog.c \
+       pathdevfd2relpathfd.c pathprog.c \
        fs3d.c ftwalk.c ftwflags.c fts.c \
        astintercept.c conformance.c getenv.c setenviron.c \
        optget.c optjoin.c optesc.c optctx.c strsort.c struniq.c \
diff -r -u -N original/src/lib/libast/Mamfile build_fd/src/lib/libast/Mamfile
--- src/lib/libast/Mamfile      2012-09-12 06:32:14.000000000 +0200
+++ src/lib/libast/Mamfile      2012-09-14 03:40:18.456277422 +0200
@@ -1197,6 +1197,18 @@
 prev path/pathcd.c
 exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd 
-D_PACKAGE_ast -c path/pathcd.c
 done pathcd.o generated
+make pathdevfd2relpathfd.o
+make path/pathdevfd2relpathfd.c
+make include/stk.h implicit
+prev include/sfio.h implicit
+done include/stk.h
+prev include/error.h implicit
+prev include/ast.h implicit
+done path/pathdevfd2relpathfd.c
+meta pathdevfd2relpathfd.o %.c>%.o path/pathdevfd2relpathfd.c 
pathdevfd2relpathfd
+prev path/pathdevfd2relpathfd.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd 
-D_PACKAGE_ast -c path/pathdevfd2relpathfd.c
+done pathdevfd2relpathfd.o generated
 make pathprog.o
 make path/pathprog.c
 make FEATURE/prog implicit
@@ -6115,7 +6127,7 @@
 exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd 
-D_PACKAGE_ast -c obsolete/spawn.c
 done spawn.o generated
 exec - ${AR} rc libast.a state.o transition.o opendir.o readdir.o rewinddir.o 
seekdir.o telldir.o getcwd.o fastfind.o hashalloc.o hashdump.o hashfree.o 
hashlast.o hashlook.o hashscan.o hashsize.o hashview.o hashwalk.o memhash.o 
memsum.o strhash.o strkey.o strsum.o stracmp.o strnacmp.o ccmap.o ccmapid.o 
ccnative.o chresc.o chrtoi.o
-exec - ${AR} rc libast.a streval.o strexpr.o strmatch.o strcopy.o modei.o 
modex.o strmode.o strlcat.o strlcpy.o strlook.o strncopy.o strsearch.o 
strpsearch.o stresc.o stropt.o strtape.o strpcmp.o strnpcmp.o strvcmp.o 
strnvcmp.o tok.o tokline.o tokscan.o pathaccess.o pathcat.o pathcanon.o 
pathcheck.o pathpath.o pathexists.o pathfind.o pathkey.o pathprobe.o pathrepl.o 
pathnative.o pathposix.o pathtemp.o pathtmp.o pathstat.o pathgetlink.o 
pathsetlink.o pathbin.o pathshell.o pathcd.o pathprog.o fs3d.o ftwalk.o 
ftwflags.o fts.o astintercept.o conformance.o getenv.o setenviron.o optget.o 
optjoin.o optesc.o optctx.o strsort.o struniq.o magic.o mime.o mimetype.o 
signal.o sigflag.o systrace.o error.o errorf.o errormsg.o errorx.o localeconv.o 
setlocale.o translate.o catopen.o iconv.o lc.o lctab.o mc.o base64.o recfmt.o 
recstr.o reclen.o fmtrec.o fmtbase.o fmtbuf.o fmtclock.o fmtdev.o fmtelapsed.o 
fmterror.o fmtesc.o fmtfmt.o fmtfs.o fmtident.o fmtint.o fmtip4.o fmtip6.o 
fmtls.o fmtmatch.o fmtmode.o fmtnum.o fmtperm.o fmtre.o fmttime.o
+exec - ${AR} rc libast.a streval.o strexpr.o strmatch.o strcopy.o modei.o 
modex.o strmode.o strlcat.o strlcpy.o strlook.o strncopy.o strsearch.o 
strpsearch.o stresc.o stropt.o strtape.o strpcmp.o strnpcmp.o strvcmp.o 
strnvcmp.o tok.o tokline.o tokscan.o pathaccess.o pathcat.o pathcanon.o 
pathcheck.o pathpath.o pathexists.o pathfind.o pathkey.o pathprobe.o pathrepl.o 
pathnative.o pathposix.o pathtemp.o pathtmp.o pathstat.o pathgetlink.o 
pathsetlink.o pathbin.o pathshell.o pathcd.o pathdevfd2relpathfd.o pathprog.o 
fs3d.o ftwalk.o ftwflags.o fts.o astintercept.o conformance.o getenv.o 
setenviron.o optget.o optjoin.o optesc.o optctx.o strsort.o struniq.o magic.o 
mime.o mimetype.o signal.o sigflag.o systrace.o error.o errorf.o errormsg.o 
errorx.o localeconv.o setlocale.o translate.o catopen.o iconv.o lc.o lctab.o 
mc.o base64.o recfmt.o recstr.o reclen.o fmtrec.o fmtbase.o fmtbuf.o fmtclock.o 
fmtdev.o fmtelapsed.o fmterror.o fmtesc.o fmtfmt.o fmtfs.o fmtident.o fmtint.o 
fmtip4.o fmtip6.o fmtls.o fmtmatch.o fmtmode.o fmtnum.o fmtperm.o fmtre.o 
fmttime.o
 exec - ${AR} rc libast.a fmtuid.o fmtgid.o fmtsignal.o fmtscale.o fmttmx.o 
fmttv.o fmtversion.o strelapsed.o strperm.o struid.o strgid.o strtoip4.o 
strtoip6.o stack.o stk.o swapget.o swapmem.o swapop.o swapput.o sigdata.o 
sigcrit.o sigunblock.o procopen.o procclose.o procrun.o procfree.o tmdate.o 
tmequiv.o tmfix.o tmfmt.o tmform.o tmgoff.o tminit.o tmleap.o tmlex.o 
tmlocale.o tmmake.o tmpoff.o tmscan.o tmsleep.o tmtime.o tmtype.o tmweek.o 
tmword.o tmzone.o tmxdate.o tmxduration.o tmxfmt.o tmxgettime.o tmxleap.o 
tmxmake.o tmxscan.o tmxsettime.o tmxsleep.o tmxtime.o tmxtouch.o tvcmp.o 
tvgettime.o tvsettime.o tvsleep.o tvtouch.o cmdarg.o vecargs.o vecfile.o 
vecfree.o vecload.o vecstring.o univdata.o touch.o mnt.o debug.o memccpy.o 
memchr.o memcmp.o memcpy.o memdup.o memmove.o memset.o mkdir.o mkfifo.o mknod.o 
rmdir.o remove.o rename.o link.o unlink.o strdup.o strchr.o strrchr.o strstr.o 
strtod.o strtold.o strtol.o strtoll.o strtoul.o strtoull.o strton.o strtonll.o 
strntod.o strntold.o strnton.o
 exec - ${AR} rc libast.a strntonll.o strntol.o strntoll.o strntoul.o 
strntoull.o strcasecmp.o strncasecmp.o strerror.o mktemp.o tmpnam.o fsync.o 
execlp.o execve.o execvp.o execvpe.o spawnveg.o vfork.o killpg.o hsearch.o 
tsearch.o getlogin.o putenv.o setenv.o unsetenv.o lstat.o statvfs.o eaccess.o 
gross.o omitted.o readlink.o symlink.o getpgrp.o setpgid.o setsid.o waitpid.o 
creat64.o fcntl.o open.o atexit.o getdents.o getwd.o dup2.o errno.o 
getpreroot.o ispreroot.o realopen.o setpreroot.o getgroups.o mount.o system.o 
iblocks.o modedata.o tmdata.o memfatal.o sfkeyprintf.o sfdcdio.o sfdcdos.o 
sfdcfilter.o sfdcseekable.o sfdcslow.o sfdcsubstr.o sfdctee.o sfdcunion.o 
sfdcmore.o sfdcprefix.o wc.o wc2utf8.o basename.o closelog.o dirname.o 
fmtmsglib.o fnmatch.o ftw.o getdate.o getsubopt.o glob.o nftw.o openlog.o 
re_comp.o resolvepath.o realpath.o regcmp.o regexp.o setlogmask.o strftime.o 
strptime.o swab.o syslog.o tempnam.o wordexp.o mktime.o regalloc.o regclass.o 
regcoll.o regcomp.o regcache.o regdecomp.o regerror.o regexec.o regfatal.o 
reginit.o
 exec - ${AR} rc libast.a regnexec.o regsubcomp.o regsubexec.o regsub.o 
regrecord.o regrexec.o regstat.o dtclose.o dtdisc.o dthash.o dtlist.o 
dtmethod.o dtopen.o dtstat.o dtstrhash.o dttree.o dtuser.o dtview.o dtwalk.o 
dtnew.o dtcomp.o sfclose.o sfclrlock.o sfdisc.o sfdlen.o sfexcept.o sfgetl.o 
sfgetu.o sfcvt.o sfecvt.o sffcvt.o sfextern.o sffilbuf.o sfflsbuf.o sfprints.o 
sfgetd.o sfgetr.o sfllen.o sfmode.o sfmove.o sfnew.o sfpkrd.o sfnotify.o 
sfnputc.o sfopen.o sfpeek.o sfpoll.o sfpool.o sfpopen.o sfprintf.o sfputd.o 
sfputl.o sfputr.o sfputu.o sfrd.o sfread.o sfreserve.o sfscanf.o sfseek.o 
sfset.o sfsetbuf.o sfsetfd.o sfsize.o sfsk.o sfstack.o sfstrtod.o sfsync.o 
sfswap.o sftable.o sftell.o sftmp.o sfungetc.o sfvprintf.o sfvscanf.o sfwr.o 
sfwrite.o sfpurge.o sfraise.o sfwalk.o sfgetm.o sfmutex.o sfputm.o sfresize.o 
_sfclrerr.o _sfeof.o _sferror.o _sffileno.o _sfopen.o _sfstacked.o _sfvalue.o 
_sfgetc.o _sfgetl.o _sfgetl2.o _sfgetu.o _sfgetu2.o _sfdlen.o _sfllen.o 
_sfslen.o _sfulen.o _sfputc.o _sfputd.o
diff -r -u -N original/src/lib/libast/path/pathdevfd2relpathfd.c 
build_fd/src/lib/libast/path/pathdevfd2relpathfd.c
--- src/lib/libast/path/pathdevfd2relpathfd.c   1970-01-01 01:00:00.000000000 
+0100
+++ src/lib/libast/path/pathdevfd2relpathfd.c   2012-09-14 05:40:36.211985009 
+0200
@@ -0,0 +1,110 @@
+/***********************************************************************
+*                                                                      *
+*               This software is part of the ast package               *
+*          Copyright (c) 1985-2011 AT&T Intellectual Property          *
+*                      and is licensed under the                       *
+*                 Eclipse Public License, Version 1.0                  *
+*                    by AT&T Intellectual Property                     *
+*                                                                      *
+*                A copy of the License is available at                 *
+*          http://www.eclipse.org/org/documents/epl-v10.html           *
+*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
+*                                                                      *
+*              Information and Software Systems Research               *
+*                            AT&T Research                             *
+*                           Florham Park NJ                            *
+*                                                                      *
+*               Roland Mainz <roland.ma...@nrubsig.org>                *
+*                                                                      *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Strip leading /dev/fd/<num>... from paths and return relative path
+ * to that file descriptor
+ */
+
+#include <ast.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+
+/*
+ * Loop to collect all /dev/fd entries and either
+ * return the original path if it does not begin with
+ * /dev/fd/<number> or extract the <number> from
+ * /dev/fd/<number>... and return the remaining path
+ * relative to fd <number>. If nothing is left in the
+ * remaining relative path return |NULL|.
+ *
+ * Examples: 
+ * path=|/dev/fd/| should return |/dev/fd/| and not touch fd_p
+ * path=|/dev/fd/45| should return NULL and *fd_p=45
+ * path=|/dev/fd/45/| should return NULL and *fd_p=45
+ * path=|/dev/fd/45/dev|| should return |dev|, *fd_p=45
+ * path=|/dev/fd/45/dev/fd/14/valeria| should return |valeria|
+ *      and *fd_p=14
+ * path=|/dev/fd/45///////////////////dev/fd/14/hello|
+ *      should return |hello| and *fd_p=14
+ * path=|//dev/fd/45/dev| should return |//dev/fd/45/dev| and
+ *      not touch fd_p
+ */
+const char *pathdevfd2relpathfd(const char *p, int *fd_p)
+{
+       char            buff[32];
+       char            *b;
+       const char      *s;
+       int             fd;
+       bool            relative_path=false;
+
+       /* Return immediately if this is a relative path... */
+       if (*p!='/')
+               return (p);
+       p++;
+
+       while(p[0]=='d' && p[1]=='e' && p[2]=='v' && p[3]=='/' &&
+             p[4]=='f' && p[5]=='d' && p[6]=='/' &&
+             isdigit(p[7]))
+               
+       {
+               s=p+7;
+               b=buff;
+               while (isdigit(*s) && *s!='\0' && (b < (buff+sizeof(buff)-1)))
+                       *b++ = *s++;
+               *b='\0';
+               
+               errno=0;
+               fd=strtol(buff, NULL, 10);
+               if ((errno == 0) && (fd >= 0))
+               {
+                       /*
+                        * Eat all '/' to make sure the path we return
+                        * is really a relative one (relative to the
+                        * fd)
+                        */
+                       while (*s=='/')
+                               s++;
+                       p=s;
+                       *fd_p=fd;
+                       relative_path=true;
+               }
+       }
+
+       /*
+        * Make sure we return a relative path to the fd we returned,
+        * an absolute one would screw things up...
+        */
+       if (relative_path)
+       {
+               /* Nothing left ? */
+               if (*p=='\0')
+                       p=NULL;
+       }
+       else
+       {
+               p--;
+       }
+
+       return (p);
+}
+
diff -r -u -N original/src/lib/libast/sfio/_sfopen.c 
build_fd/src/lib/libast/sfio/_sfopen.c
--- src/lib/libast/sfio/_sfopen.c       2012-08-31 23:25:24.000000000 +0200
+++ src/lib/libast/sfio/_sfopen.c       2012-09-14 04:35:36.016886271 +0200
@@ -57,9 +57,30 @@
 {
        int     fd, oldfd, oflags, fflags, sflags;
        SFMTXDECL(f);
+#ifdef AT_FDCWD
+       if (file)
+       {
+               const char *afile;
 
-       if (file && *file == '/')
-               cwd = AT_FDCWD;
+               if (*file == '/')
+               {
+                       cwd = AT_FDCWD;
+                       afile = pathdevfd2relpathfd(file, &cwd);
+                       /*
+                        * |pathdevfd2relpathfd| will return |NULL| if
+                        *  /dev/fd/${num} is not followed by a path.
+                        * Question is whether we can use |dup()| in
+                        * such a case (warning: |dup()| will cause
+                        * both old and new fd to share attributes
+                        * like the seek position)
+                        */
+                       if (afile)
+                               file = afile;
+                       else if (file[strlen(file)-1]=='/')
+                               file = ".";
+               }
+       }
+#endif
 #if !defined(sysopenatf)
        if (cwd != AT_FDCWD)
        {
_______________________________________________
ast-developers mailing list
ast-developers@research.att.com
https://mailman.research.att.com/mailman/listinfo/ast-developers

Reply via email to