From: Eric Blake Date: Tue, 10 Nov 2009 14:59:39 +0000 (-0700) Subject: symlink: detect FreeBSD bug X-Git-Tag: stable/20091120~41 X-Git-Url: http://erislabs.org.uk/gitweb/?a=commitdiff_plain;h=ec1472041c35a30a4bdc7abeac5bd283a0ff5ff5;p=gnulib.git symlink: detect FreeBSD bug symlink(name,"dangling/") mistakenly created a symlink at the target of "dangling". * m4/symlink.m4 (gl_FUNC_SYMLINK): Also detect FreeBSD bug with slash on symlink. * doc/posix-functions/symlink.texi (symlink): Document the bug. * tests/test-symlink.h (test_symlink): Enhance test. Signed-off-by: Eric Blake (cherry picked from commit 24a6037afaa234252b05719df819e6645ec92697) --- diff --git a/ChangeLog b/ChangeLog index 8863561b3..227d9bd95 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-11-11 Eric Blake + + symlink: detect FreeBSD bug + * m4/symlink.m4 (gl_FUNC_SYMLINK): Also detect FreeBSD bug with + slash on symlink. + * doc/posix-functions/symlink.texi (symlink): Document the bug. + * tests/test-symlink.h (test_symlink): Enhance test. + 2009-11-10 Eric Blake link: detect FreeBSD bug diff --git a/doc/posix-functions/symlink.texi b/doc/posix-functions/symlink.texi index de7c0aa44..b3d740f76 100644 --- a/doc/posix-functions/symlink.texi +++ b/doc/posix-functions/symlink.texi @@ -11,7 +11,7 @@ Portability problems fixed by Gnulib: @item On some systems, @code{symlink(value,"name/")} mistakenly creates a symlink: -Solaris 9 +FreeBSD 7.2, Solaris 9 @item This function is missing on some platforms; however, the replacement always fails with @code{EPERM}: diff --git a/m4/symlink.m4 b/m4/symlink.m4 index abea0459a..010d4b875 100644 --- a/m4/symlink.m4 +++ b/m4/symlink.m4 @@ -1,4 +1,4 @@ -# serial 1 +# serial 2 # See if we need to provide symlink replacement. dnl Copyright (C) 2009 Free Software Foundation, Inc. @@ -13,8 +13,8 @@ AC_DEFUN([gl_FUNC_SYMLINK], AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) AC_CHECK_FUNCS_ONCE([symlink]) dnl The best we can do on mingw is provide a dummy that always fails, so - dnl that compilation can proceed with fewer ifdefs. On Solaris 9, we - dnl want to fix a bug with trailing slash handling. + dnl that compilation can proceed with fewer ifdefs. On Solaris 9 and + dnl FreeBSD 7.2, we want to fix a bug with trailing slash handling. if test $ac_cv_func_symlink = no; then HAVE_SYMLINK=0 AC_LIBOBJ([symlink]) @@ -24,9 +24,12 @@ AC_DEFUN([gl_FUNC_SYMLINK], [AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[#include -]], [[return !symlink ("a", "conftest.link/");]])], +]], [[if (!symlink ("a", "conftest.link/")) return 1; + if (symlink ("conftest.f", "conftest.lnk2")) return 2; + if (!symlink ("a", "conftest.lnk2/")) return 3;]])], [gl_cv_func_symlink_works=yes], [gl_cv_func_symlink_works=no], - [gl_cv_func_symlink_works="guessing no"])]) + [gl_cv_func_symlink_works="guessing no"]) + rm -f conftest.f conftest.link conftest.lnk2]) if test "$gl_cv_func_symlink_works" != yes; then REPLACE_SYMLINK=1 AC_LIBOBJ([symlink]) diff --git a/tests/test-symlink.h b/tests/test-symlink.h index d009a8098..c083c6c1e 100644 --- a/tests/test-symlink.h +++ b/tests/test-symlink.h @@ -35,11 +35,18 @@ test_symlink (int (*func) (char const *, char const *), bool print) /* Some systems allow the creation of 0-length symlinks as a synonym for "."; but most reject it. */ - errno = 0; - if (func ("", BASE "link2") == -1) - ASSERT (errno == ENOENT || errno == EINVAL); - else - ASSERT (unlink (BASE "link2") == 0); + { + int status; + errno = 0; + status = func ("", BASE "link2"); + if (status == -1) + ASSERT (errno == ENOENT || errno == EINVAL); + else + { + ASSERT (status == 0); + ASSERT (unlink (BASE "link2") == 0); + } + } /* Sanity checks of failures. */ errno = 0; @@ -69,6 +76,17 @@ test_symlink (int (*func) (char const *, char const *), bool print) ASSERT (func ("nowhere", BASE "file/") == -1); ASSERT (errno == EEXIST || errno == ENOTDIR || errno == ENOENT); + /* Trailing slash must always be rejected. */ + ASSERT (unlink (BASE "link1") == 0); + ASSERT (func (BASE "link2", BASE "link1") == 0); + errno = 0; + ASSERT (func (BASE "nowhere", BASE "link1/") == -1); + ASSERT (errno == EEXIST || errno == ENOTDIR || errno == ENOENT); + errno = 0; + ASSERT (unlink (BASE "link2") == -1); + ASSERT (errno == ENOENT); + + /* Cleanup. */ ASSERT (rmdir (BASE "dir") == 0); ASSERT (unlink (BASE "file") == 0); ASSERT (unlink (BASE "link1") == 0);