Good morning,

The following piece of shell code does not work on sunos.
mkfifo /tmp/pipe
cat < /tmp/pipe &
exec 6>/tmp/pipe
test -p /dev/fd/6 && echo pipe

The reason is on sunos /dev/fd/6 is a special character file, not a pipe
(unlike bsd), not a symlink (unlike linux, cygwin).
sh_stat ends up calling stat("/dev/fd/6", finfo) and obtains stat of /dev/fd/6
file rather than stat of the file pointed to by fd 6.

The patch in the attachment makes sh_stat always use fstat regardless of
HAVE_DEV_FD.
I've tested this patch on linux, sunos and aix.

regards, Dmitry
diff --git a/lib/sh/eaccess.c b/lib/sh/eaccess.c
index 8132a9a..1575dd2 100644
--- a/lib/sh/eaccess.c
+++ b/lib/sh/eaccess.c
@@ -82,8 +82,6 @@ sh_stat (path, finfo)
      const char *path;
      struct stat *finfo;
 {
-  static char *pbuf = 0;
-
   if (*path == '\0')
     {
       errno = ENOENT;
@@ -91,7 +89,6 @@ sh_stat (path, finfo)
     }
   if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0)
     {
-#if !defined (HAVE_DEV_FD)
       intmax_t fd;
       int r;
 
@@ -103,16 +100,6 @@ sh_stat (path, finfo)
         }
       errno = ENOENT;
       return (-1);
-#else
-  /* If HAVE_DEV_FD is defined, DEV_FD_PREFIX is defined also, and has a
-     trailing slash.  Make sure /dev/fd/xx really uses DEV_FD_PREFIX/xx.
-     On most systems, with the notable exception of linux, this is
-     effectively a no-op. */
-      pbuf = xrealloc (pbuf, sizeof (DEV_FD_PREFIX) + strlen (path + 8));
-      strcpy (pbuf, DEV_FD_PREFIX);
-      strcat (pbuf, path + 8);
-      return (stat (pbuf, finfo));
-#endif /* !HAVE_DEV_FD */
     }
 #if !defined (HAVE_DEV_STDIN)
   else if (STREQN (path, "/dev/std", 8))
diff --git a/tests/test.tests b/tests/test.tests
index 47eef35..5a790d8 100644
--- a/tests/test.tests
+++ b/tests/test.tests
@@ -436,3 +436,17 @@ t -t /dev/tty4444444...
 
 # fixed in bash-4.0-beta
 t -t ' '
+
+exec 6>&-
+echo "t -p /dev/fd/6"
+t -p /dev/fd/6
+
+rm /tmp/pipe 2>/dev/null
+mkfifo /tmp/pipe
+cat < /tmp/pipe &
+exec 6>&-
+exec 6>/tmp/pipe
+echo "t -p /dev/fd/6"
+t -p /dev/fd/6
+kill $! 2>/dev/null
+rm /tmp/pipe 2>/dev/null

Reply via email to