+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
@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}:
-# serial 1
+# serial 2
# See if we need to provide symlink replacement.
dnl Copyright (C) 2009 Free Software Foundation, Inc.
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])
[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])
/* 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;
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);