-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 According to Eric Blake on 11/11/2009 6:21 AM: > I also discovered that readlink is broken on FreeBSD: > > $ touch a > $ ln -s a b > $ ln -s b c > $ readlink c/ > a => Oops - read the contents of b.
I'm pushing this for readlink. - -- Don't work too hard, make some time for fun as well! Eric Blake e...@byu.net -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkr6wHgACgkQ84KuGfSFAYCiqQCdE0WWlP824SL1e/5GaJPfZShP NzQAn2bVPDeMic22rgEI8jjF/ahq0qJP =qoks -----END PGP SIGNATURE-----
>From dfd4d11c50dd4729bf46c26a3bbdda0c6031409d Mon Sep 17 00:00:00 2001 From: Eric Blake <e...@byu.net> Date: Wed, 11 Nov 2009 06:34:02 -0700 Subject: [PATCH] readlink: detect FreeBSD bug readlink("link-to-symlink/",buf,len) mistakenly read the contents of "symlink", rather than failing. * m4/readlink.m4 (gl_FUNC_READLINK): Also detect FreeBSD bug with slash on symlink. * doc/posix-functions/readlink.texi (readlink): Document the bug. * tests/test-readlink.h (test_readlink): Enhance test. Signed-off-by: Eric Blake <e...@byu.net> --- ChangeLog | 6 ++++++ doc/posix-functions/readlink.texi | 2 +- m4/readlink.m4 | 7 +++++-- tests/test-readlink.h | 13 ++++++++++++- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 227d9bd..fbfa1e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2009-11-11 Eric Blake <e...@byu.net> + readlink: detect FreeBSD bug + * m4/readlink.m4 (gl_FUNC_READLINK): Also detect FreeBSD bug with + slash on symlink. + * doc/posix-functions/readlink.texi (readlink): Document the bug. + * tests/test-readlink.h (test_readlink): Enhance test. + symlink: detect FreeBSD bug * m4/symlink.m4 (gl_FUNC_SYMLINK): Also detect FreeBSD bug with slash on symlink. diff --git a/doc/posix-functions/readlink.texi b/doc/posix-functions/readlink.texi index b1218f6..de898fb 100644 --- a/doc/posix-functions/readlink.texi +++ b/doc/posix-functions/readlink.texi @@ -10,7 +10,7 @@ readlink @itemize @item Some platforms mistakenly succeed on @code{readlink("link/",buf,len)}: -Solaris 9. +FreeBSD 7.2, Solaris 9. @item On some platforms, @code{readlink} returns @code{int} instead of @code{ssize_t}: diff --git a/m4/readlink.m4 b/m4/readlink.m4 index fa7c2dd..e61c1a1 100644 --- a/m4/readlink.m4 +++ b/m4/readlink.m4 @@ -1,4 +1,4 @@ -# readlink.m4 serial 7 +# readlink.m4 serial 8 dnl Copyright (C) 2003, 2007, 2009 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -21,15 +21,18 @@ AC_DEFUN([gl_FUNC_READLINK], /* Cause compilation failure if original declaration has wrong type. */ ssize_t readlink (const char *, char *, size_t);]])], [gl_cv_decl_readlink_works=yes], [gl_cv_decl_readlink_works=no])]) + dnl Solaris 9 ignores trailing slash. + dnl FreeBSD 7.2 dereferences only one level of links with trailing slash. AC_CACHE_CHECK([whether readlink handles trailing slash correctly], [gl_cv_func_readlink_works], [# We have readlink, so assume ln -s works. ln -s conftest.no-such conftest.link + ln -s conftest.link conftest.lnk2 AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[#include <unistd.h> ]], [[char buf[20]; - return readlink ("conftest.link/", buf, sizeof buf) != -1;]])], + return readlink ("conftest.lnk2/", buf, sizeof buf) != -1;]])], [gl_cv_func_readlink_works=yes], [gl_cv_func_readlink_works=no], [gl_cv_func_readlink_works="guessing no"]) rm -f conftest.link]) diff --git a/tests/test-readlink.h b/tests/test-readlink.h index 4ce67f7..5f5e910 100644 --- a/tests/test-readlink.h +++ b/tests/test-readlink.h @@ -52,11 +52,11 @@ test_readlink (ssize_t (*func) (char const *, char *, size_t), bool print) errno = 0; ASSERT (func (BASE "file/", buf, sizeof buf) == -1); ASSERT (errno == ENOTDIR); - ASSERT (unlink (BASE "file") == 0); /* Now test actual symlinks. */ if (symlink (BASE "dir", BASE "link")) { + ASSERT (unlink (BASE "file") == 0); if (print) fputs ("skipping test: symlinks not supported on this file system\n", stderr); @@ -66,6 +66,17 @@ test_readlink (ssize_t (*func) (char const *, char *, size_t), bool print) errno = 0; ASSERT (func (BASE "link/", buf, sizeof buf) == -1); ASSERT (errno == EINVAL); + ASSERT (symlink (BASE "link", BASE "link2") == 0); + errno = 0; + ASSERT (func (BASE "link2/", buf, sizeof buf) == -1); + ASSERT (errno == EINVAL); + ASSERT (unlink (BASE "link2") == 0); + ASSERT (symlink (BASE "file", BASE "link2") == 0); + errno = 0; + ASSERT (func (BASE "link2/", buf, sizeof buf) == -1); + ASSERT (errno == ENOTDIR); + ASSERT (unlink (BASE "file") == 0); + ASSERT (unlink (BASE "link2") == 0); { /* Up till now, no readlink has been successful, so buf should be unchanged. */ -- 1.6.5.rc1