symlink: detect FreeBSD bug
authorEric Blake <ebb9@byu.net>
Tue, 10 Nov 2009 14:59:39 +0000 (07:59 -0700)
committerIan Beckwith <ianb@erislabs.net>
Sun, 15 Nov 2009 02:50:47 +0000 (02:50 +0000)
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 <ebb9@byu.net>
(cherry picked from commit 24a6037afaa234252b05719df819e6645ec92697)

ChangeLog
doc/posix-functions/symlink.texi
m4/symlink.m4
tests/test-symlink.h

index 8863561..227d9bd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2009-11-11  Eric Blake  <ebb9@byu.net>
+
+       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  <ebb9@byu.net>
 
        link: detect FreeBSD bug
index de7c0aa..b3d740f 100644 (file)
@@ -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}:
index abea045..010d4b8 100644 (file)
@@ -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 <unistd.h>
-]], [[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])
index d009a80..c083c6c 100644 (file)
@@ -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);