unlink("link-to-file/") mistakenly removed "file".
* m4/unlink.m4 (gl_FUNC_UNLINK): Also detect FreeBSD bug with
slash on symlink.
* doc/posix-functions/unlink.texi (unlink): Document the bug.
* doc/posix-functions/remove.texi (remove): Likewise.
* tests/test-unlink.h (test_unlink): Enhance test.
* tests/test-remove.c (main): Likewise.
Signed-off-by: Eric Blake <ebb9@byu.net>
+2009-11-10 Eric Blake <ebb9@byu.net>
+
+ unlink, remove: detect FreeBSD bug
+ * m4/unlink.m4 (gl_FUNC_UNLINK): Also detect FreeBSD bug with
+ slash on symlink.
+ * doc/posix-functions/unlink.texi (unlink): Document the bug.
+ * doc/posix-functions/remove.texi (remove): Likewise.
+ * tests/test-unlink.h (test_unlink): Enhance test.
+ * tests/test-remove.c (main): Likewise.
+
2009-11-09 Eric Blake <ebb9@byu.net>
rename: detect FreeBSD bug
@item
This function fails to reject trailing slashes on non-directories on
some platforms:
-Solaris 9.
+FreeBSD 7.2, Solaris 9.
@item
This function mistakenly removes a directory with
@code{remove("dir/./")} on some platforms:
Portability problems fixed by Gnulib:
@itemize
@item
-Some systems mistakenly succeed on @code{unlink("file/")}:
-GNU/Hurd, Solaris 9.
+Some systems mistakenly succeed on @code{unlink("link-to-file/")}:
+GNU/Hurd, FreeBSD 7.2, Solaris 9.
@end itemize
Portability problems not fixed by Gnulib:
-# unlink.m4 serial 1
+# unlink.m4 serial 2
dnl Copyright (C) 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,
[
AC_REQUIRE([gl_AC_DOS])
AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
- dnl Detect Solaris 9 bug.
+ dnl Detect Solaris 9 and FreeBSD 7.2 bug.
AC_CACHE_CHECK([whether unlink honors trailing slashes],
[gl_cv_func_unlink_works],
[touch conftest.file
+ # Assume that if we have lstat, we can also check symlinks.
+ if test $ac_cv_func_lstat = yes; then
+ ln -s conftest.file conftest.lnk
+ fi
AC_RUN_IFELSE(
[AC_LANG_PROGRAM(
[[#include <stdio.h>
#include <errno.h>
-]], [[return !unlink ("conftest.file/") || errno != ENOTDIR;]])],
+]], [[if (!unlink ("conftest.file/") || errno != ENOTDIR) return 1;
+#if HAVE_LSTAT
+ if (!unlink ("conftest.lnk/") || errno != ENOTDIR) return 2;
+#endif
+ ]])],
[gl_cv_func_unlink_works=yes], [gl_cv_func_unlink_works=no],
[gl_cv_func_unlink_works="guessing no"])
- rm -f conftest.file])
+ rm -f conftest.file conftest.lnk])
if test x"$gl_cv_func_unlink_works" != xyes; then
REPLACE_UNLINK=1
AC_LIBOBJ([unlink])
ASSERT (S_ISLNK (st.st_mode));
}
ASSERT (remove (BASE "link") == 0);
+ /* Trailing slash on symlink to non-directory is an error. */
+ ASSERT (symlink (BASE "loop", BASE "loop") == 0);
+ errno = 0;
+ ASSERT (remove (BASE "loop/") == -1);
+ ASSERT (errno == ELOOP || errno == ENOTDIR);
+ ASSERT (remove (BASE "loop") == 0);
+ ASSERT (close (creat (BASE "file", 0600)) == 0);
+ ASSERT (symlink (BASE "file", BASE "link") == 0);
+ errno = 0;
+ ASSERT (remove (BASE "link/") == -1);
+ ASSERT (errno == ENOTDIR);
+ ASSERT (remove (BASE "link") == 0);
+ ASSERT (remove (BASE "file") == 0);
return 0;
}
ASSERT (func (BASE "dir/file") == 0);
ASSERT (rmdir (BASE "dir") == 0);
if (print)
- fputs ("skipping test: symlinks not supported on this file system\n",
- stderr);
+ fputs ("skipping test: symlinks not supported on this file system\n",
+ stderr);
return 77;
}
if (cannot_unlink_dir ())
ASSERT (func (BASE "link/") == -1);
ASSERT (func (BASE "link") == 0);
ASSERT (symlink (BASE "dir/file", BASE "link") == 0);
+ errno = 0;
+ ASSERT (func (BASE "link/") == -1);
+ ASSERT (errno == ENOTDIR);
/* Order here proves unlink of a symlink does not follow through to
the file. */
ASSERT (func (BASE "link") == 0);