link("link-to-file/","a") mistakenly created "a" as a link to "file".
* m4/link.m4 (gl_FUNC_LINK): Also detect FreeBSD bug with slash on
symlink.
* doc/posix-functions/link.texi (link): Document the bug.
* tests/test-link.h (test_link): Enhance test.
* tests/test-linkat.c (main): Update caller.
Signed-off-by: Eric Blake <ebb9@byu.net>
2009-11-10 Eric Blake <ebb9@byu.net>
+ link: detect FreeBSD bug
+ * m4/link.m4 (gl_FUNC_LINK): Also detect FreeBSD bug with slash on
+ symlink.
+ * doc/posix-functions/link.texi (link): Document the bug.
+ * tests/test-link.h (test_link): Enhance test.
+ * tests/test-linkat.c (main): Update caller.
+
unlink, remove: detect FreeBSD bug
* m4/unlink.m4 (gl_FUNC_UNLINK): Also detect FreeBSD bug with
slash on symlink.
@item
This function fails to reject trailing slashes on non-directories on
some platforms:
-Solaris, Cygwin 1.5.x.
+FreeBSD 7.2, Solaris, Cygwin 1.5.x.
@end itemize
Portability problems not fixed by Gnulib:
-# link.m4 serial 3
+# link.m4 serial 4
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_CACHE_CHECK([whether link handles trailing slash correctly],
[gl_cv_func_link_works],
[touch conftest.a
+ # Assume that if we have lstat, we can also check symlinks.
+ if test $ac_cv_func_lstat = yes; then
+ ln -s conftest.a conftest.lnk
+ fi
AC_RUN_IFELSE(
[AC_LANG_PROGRAM(
[[#include <unistd.h>
-]], [[return !link ("conftest.a", "conftest.b/");]])],
+]], [[if (!link ("conftest.a", "conftest.b/")) return 1;
+#if HAVE_LSTAT
+ if (!link ("conftest.lnk/", "conftest.b")) return 2;
+#endif
+ ]])],
[gl_cv_func_link_works=yes], [gl_cv_func_link_works=no],
[gl_cv_func_link_works="guessing no"])
- rm -f conftest.a conftest.b])
+ rm -f conftest.a conftest.b conftest.lnk])
if test "$gl_cv_func_link_works" != yes; then
REPLACE_LINK=1
AC_LIBOBJ([link])
linkat(AT_FDCWD,a,AT_FDCWD,b,0). FUNC is the function to test.
Assumes that BASE and ASSERT are already defined, and that
appropriate headers are already included. If PRINT, warn before
- skipping tests with status 77. This test does not exercise link on
- symlinks. */
+ skipping tests with status 77. This test does not try to create
+ hard links to symlinks, but does test other aspects of symlink. */
static int
test_link (int (*func) (char const *, char const *), bool print)
ASSERT (errno == EPERM || errno == EACCES || errno == EINVAL);
}
}
-
- /* Clean up. */
ASSERT (unlink (BASE "a") == 0);
- ASSERT (unlink (BASE "b") == 0);
errno = 0;
ASSERT (unlink (BASE "c") == -1);
ASSERT (errno == ENOENT);
ASSERT (rmdir (BASE "d") == 0);
+ /* Test invalid use of symlink. */
+ if (symlink (BASE "a", BASE "link") != 0)
+ {
+ ASSERT (unlink (BASE "b") == 0);
+ if (print)
+ fputs ("skipping test: symlinks not supported on this file system\n",
+ stderr);
+ return 77;
+ }
+ errno = 0;
+ ASSERT (func (BASE "b", BASE "link/") == -1);
+ ASSERT (errno == ENOTDIR || errno == ENOENT || errno == EEXIST);
+ ASSERT (rename (BASE "b", BASE "a") == 0);
+ errno = 0;
+ ASSERT (func (BASE "link/", BASE "b") == -1);
+ ASSERT (errno == ENOTDIR || errno == EEXIST);
+
+ /* Clean up. */
+ ASSERT (unlink (BASE "a") == 0);
+ ASSERT (unlink (BASE "link") == 0);
+
return 0;
}
do \
{ \
if (!(expr)) \
- { \
- fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
- fflush (stderr); \
- abort (); \
- } \
+ { \
+ fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+ fflush (stderr); \
+ abort (); \
+ } \
} \
while (0)
ASSERT (system ("rm -rf " BASE "*") == 0);
/* Test basic link functionality, without mentioning symlinks. */
- result = test_link (do_link, false);
+ result = test_link (do_link, true);
dfd1 = open (".", O_RDONLY);
ASSERT (0 <= dfd1);
ASSERT (test_link (do_link, false) == result);
ASSERT (rmdir (BASE "sub1") == 0);
ASSERT (rmdir (BASE "sub2") == 0);
free (cwd);
- fputs ("skipping test: symlinks not supported on this file system\n",
- stderr);
+ if (!result)
+ fputs ("skipping test: symlinks not supported on this file system\n",
+ stderr);
return result;
}
dfd = open (".", O_RDONLY);