/* Test of link() function.
- Copyright (C) 2009 Free Software Foundation, Inc.
+ Copyright (C) 2009-2013 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include <config.h>
-
/* This file is designed to test both link(a,b) and
- linkat(AT_FDCWD,a,AT_FDCWD,b). FUNC is the function to test.
+ 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 symlink tests with status 77. */
+ 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)
if (ret == -1)
{
/* If the device does not support hard links, errno is
- EPERM on Linux, EOPNOTSUPP on FreeBSD. */
+ EPERM on Linux, EOPNOTSUPP on FreeBSD. */
switch (errno)
- {
- case EPERM:
- case EOPNOTSUPP:
+ {
+ case EPERM:
+ case EOPNOTSUPP:
if (print)
fputs ("skipping test: "
"hard links not supported on this file system\n",
stderr);
ASSERT (unlink (BASE "a") == 0);
- return 77;
- default:
- perror ("link");
- return 1;
- }
+ return 77;
+ default:
+ perror ("link");
+ return 1;
+ }
}
ASSERT (ret == 0);
ASSERT (close (fd) == 0);
}
- /* Test for various error conditions. Assumes hard links to
- directories are not permitted. */
+ /* Test for various error conditions. */
ASSERT (mkdir (BASE "d", 0700) == 0);
errno = 0;
ASSERT (func (BASE "a", ".") == -1);
ASSERT (errno == ENOENT);
errno = 0;
ASSERT (func (BASE "a/", BASE "c") == -1);
- ASSERT (errno == ENOTDIR);
+ ASSERT (errno == ENOTDIR || errno == EINVAL);
errno = 0;
ASSERT (func (BASE "a", BASE "c/") == -1);
- ASSERT (errno == ENOTDIR || errno == ENOENT);
- errno = 0;
- ASSERT (func (BASE "d", BASE "c") == -1);
- ASSERT (errno == EPERM || errno == EACCES);
+ ASSERT (errno == ENOTDIR || errno == ENOENT || errno == EINVAL);
- /* Clean up. */
+ /* Most platforms reject hard links to directories, and even on
+ those that do permit it, most users can't create them. We assume
+ that if this test is run as root and we managed to create a hard
+ link, then unlink better be able to clean it up. */
+ {
+ int result;
+ errno = 0;
+ result = func (BASE "d", BASE "c");
+ if (result == 0)
+ {
+ /* Probably root on Solaris. */
+ ASSERT (unlink (BASE "c") == 0);
+ }
+ else
+ {
+ /* Most everyone else. */
+ ASSERT (errno == EPERM || errno == EACCES || errno == EISDIR);
+ errno = 0;
+ ASSERT (func (BASE "d/.", BASE "c") == -1);
+ ASSERT (errno == EPERM || errno == EACCES || errno == EISDIR
+ || errno == EINVAL);
+ errno = 0;
+ ASSERT (func (BASE "d/.//", BASE "c") == -1);
+ ASSERT (errno == EPERM || errno == EACCES || errno == EISDIR
+ || errno == EINVAL);
+ }
+ }
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
+ || errno == EINVAL);
+ errno = 0;
+ ASSERT (func (BASE "b", BASE "link") == -1);
+ ASSERT (errno == EEXIST);
+ ASSERT (rename (BASE "b", BASE "a") == 0);
+ errno = 0;
+ ASSERT (func (BASE "link/", BASE "b") == -1);
+ ASSERT (errno == ENOTDIR || errno == EEXIST || errno == EINVAL);
+
+ /* Clean up. */
+ ASSERT (unlink (BASE "a") == 0);
+ ASSERT (unlink (BASE "link") == 0);
+
return 0;
}