bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] readlinkat: avoid OS X 10.10 trailing slash bug


From: Pádraig Brady
Subject: [PATCH] readlinkat: avoid OS X 10.10 trailing slash bug
Date: Sun, 31 May 2015 03:32:52 +0100

* doc/posix-functions/readlink.texi: Mention that OS X 10.10
has this bug.
* doc/posix-functions/readlinkat.texi: Likewise.  Also mention
that OS X 10.10 has this function.
* lib/readlinkat.c (rpl_readlinkat): Handle the trailing slash bug,
as done for readlink().
* m4/readlinkat.m4 (gl_FUNC_READLINKAT): Check for the readlink()
trailing slash bug, and assume readlinkat() has the same issue.
Also fix a typo where $gl_cv_decl_readlink_works was tested,
rather than the correct $gl_cv_decl_readlinkat_works.
---
 doc/posix-functions/readlink.texi   |  2 +-
 doc/posix-functions/readlinkat.texi |  5 ++++-
 lib/readlinkat.c                    | 18 ++++++++++++++++++
 m4/readlinkat.m4                    | 18 ++++++++++++++----
 4 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/doc/posix-functions/readlink.texi 
b/doc/posix-functions/readlink.texi
index 60654b1..1460d02 100644
--- a/doc/posix-functions/readlink.texi
+++ b/doc/posix-functions/readlink.texi
@@ -10,7 +10,7 @@ Portability problems fixed by Gnulib:
 @itemize
 @item
 Some platforms mistakenly succeed on @code{readlink("link/",buf,len)}:
-FreeBSD 7.2, Solaris 9.
+FreeBSD 7.2, Solaris 9, Mac OS X 10.10.
 @item
 On some platforms, @code{readlink} returns @code{int} instead of
 @code{ssize_t}:
diff --git a/doc/posix-functions/readlinkat.texi 
b/doc/posix-functions/readlinkat.texi
index 51fbeba..8564068 100644
--- a/doc/posix-functions/readlinkat.texi
+++ b/doc/posix-functions/readlinkat.texi
@@ -10,10 +10,13 @@ Portability problems fixed by Gnulib:
 @itemize
 @item
 This function is missing on some platforms:
-glibc 2.3.6, Mac OS X 10.5, FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8,
+glibc 2.3.6, Mac OS X < 10.10, FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 
3.1.8,
 AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 1.5.x, mingw, MSVC 
9, Interix 3.5, BeOS.
 But the replacement function is not safe to be used in libraries and is not 
multithread-safe.
 @item
+Some platforms mistakenly succeed on @code{readlink("link/",buf,len)}:
+Mac OS X 10.10.
address@hidden
 On some platforms, @code{readlinkat} returns @code{int} instead of
 @code{ssize_t}:
 AIX 7.1.
diff --git a/lib/readlinkat.c b/lib/readlinkat.c
index f4826f9..c91cf0e 100644
--- a/lib/readlinkat.c
+++ b/lib/readlinkat.c
@@ -18,7 +18,10 @@
 
 #include <config.h>
 
+#include <errno.h>
 #include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
 
 #if HAVE_READLINKAT
 
@@ -27,6 +30,21 @@
 ssize_t
 rpl_readlinkat (int fd, char const *file, char *buf, size_t len)
 {
+# if READLINK_TRAILING_SLASH_BUG
+  size_t file_len = strlen (file);
+  if (file_len && file[file_len - 1] == '/')
+    {
+      /* Even if FILE without the slash is a symlink to a directory,
+         both lstat() and stat() must resolve the trailing slash to
+         the directory rather than the symlink.  We can therefore
+         safely use stat() to distinguish between EINVAL and
+         ENOTDIR/ENOENT, avoiding extra overhead of rpl_lstat().  */
+      struct stat st;
+      if (stat (file, &st) == 0)
+        errno = EINVAL;
+      return -1;
+    }
+# endif /* READLINK_TRAILING_SLASH_BUG */
   return readlinkat (fd, file, buf, len);
 }
 
diff --git a/m4/readlinkat.m4 b/m4/readlinkat.m4
index d0f5e69..3477602 100644
--- a/m4/readlinkat.m4
+++ b/m4/readlinkat.m4
@@ -1,4 +1,4 @@
-# serial 4
+# serial 5
 # See if we need to provide readlinkat replacement.
 
 dnl Copyright (C) 2009-2015 Free Software Foundation, Inc.
@@ -13,6 +13,7 @@ AC_DEFUN([gl_FUNC_READLINKAT],
   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
   AC_CHECK_FUNCS_ONCE([readlinkat])
+  AC_REQUIRE([gl_FUNC_READLINK])
   if test $ac_cv_func_readlinkat = no; then
     HAVE_READLINKAT=0
   else
@@ -25,8 +26,17 @@ AC_DEFUN([gl_FUNC_READLINKAT],
              ssize_t readlinkat (int, char const *, char *, size_t);]])],
          [gl_cv_decl_readlinkat_works=yes],
          [gl_cv_decl_readlinkat_works=no])])
-    if test "$gl_cv_decl_readlink_works" != yes; then
-      REPLACE_READLINKAT=1
-    fi
+    # Assume readinkat has the same trailing slash bug as readlink,
+    # as is the case on Mac Os X 10.10
+    case "$gl_cv_func_readlink_works" in
+      *yes)
+        if test "$gl_cv_decl_readlinkat_works" != yes; then
+          REPLACE_READLINKAT=1
+        fi
+        ;;
+      *)
+        REPLACE_READLINKAT=1
+        ;;
+    esac
   fi
 ])
-- 
2.4.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]