From: Eric Blake Date: Mon, 9 Nov 2009 17:44:08 +0000 (-0700) Subject: unlink, remove: detect FreeBSD bug X-Git-Tag: stable/20091120~43 X-Git-Url: https://erislabs.net/gitweb/?a=commitdiff_plain;h=12a64eb033ac96ccc78f96d66067c70be7d2be90;p=gnulib.git unlink, remove: detect FreeBSD bug 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 (cherry picked from commit 24208770c8721323060207c9be83dd24400678d3) --- diff --git a/ChangeLog b/ChangeLog index 599a2ab6a..8d3dcea35 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2009-11-10 Eric Blake + + 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 rename: detect FreeBSD bug diff --git a/doc/posix-functions/remove.texi b/doc/posix-functions/remove.texi index b3e3d1b1f..83a8955c9 100644 --- a/doc/posix-functions/remove.texi +++ b/doc/posix-functions/remove.texi @@ -11,7 +11,7 @@ Portability problems fixed by Gnulib: @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: diff --git a/doc/posix-functions/unlink.texi b/doc/posix-functions/unlink.texi index 1df1e30b3..42b9e817e 100644 --- a/doc/posix-functions/unlink.texi +++ b/doc/posix-functions/unlink.texi @@ -9,8 +9,8 @@ Gnulib module: unlink 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: diff --git a/m4/unlink.m4 b/m4/unlink.m4 index 626c3adf3..bed24665d 100644 --- a/m4/unlink.m4 +++ b/m4/unlink.m4 @@ -1,4 +1,4 @@ -# 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, @@ -8,18 +8,26 @@ AC_DEFUN([gl_FUNC_UNLINK], [ 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 #include -]], [[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]) diff --git a/tests/test-remove.c b/tests/test-remove.c index af5d01bc2..16bfe2f9b 100644 --- a/tests/test-remove.c +++ b/tests/test-remove.c @@ -113,6 +113,19 @@ main (void) 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; } diff --git a/tests/test-unlink.h b/tests/test-unlink.h index 6b6384e50..e65057de4 100644 --- a/tests/test-unlink.h +++ b/tests/test-unlink.h @@ -68,14 +68,17 @@ test_unlink_func (int (*func) (char const *name), bool print) 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);