1 /* Test of link() function.
2 Copyright (C) 2009-2024 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* This file is designed to test both link(a,b) and
18 linkat(AT_FDCWD,a,AT_FDCWD,b,0). FUNC is the function to test.
19 Assumes that BASE and ASSERT are already defined, and that
20 appropriate headers are already included. If PRINT, warn before
21 skipping tests with status 77. This test does not try to create
22 hard links to symlinks, but does test other aspects of symlink. */
25 test_link (int (*func
) (char const *, char const *), bool print
)
30 /* Create first file. */
31 fd
= open (BASE
"a", O_CREAT
| O_EXCL
| O_WRONLY
, 0600);
33 ASSERT (write (fd
, "hello", 5) == 5);
34 ASSERT (close (fd
) == 0);
36 /* Not all file systems support link. Mingw doesn't have reliable
37 st_nlink on hard links, but our implementation does fail with
38 EPERM on poor file systems, and we can detect the inferior stat()
39 via st_ino. Cygwin 1.5.x copies rather than links files on those
40 file systems, but there, st_nlink and st_ino are reliable. */
41 ret
= func (BASE
"a", BASE
"b");
45 ASSERT (stat (BASE
"b", &st
) == 0);
46 if (st
.st_ino
&& st
.st_nlink
!= 2)
48 ASSERT (unlink (BASE
"b") == 0);
55 /* If the device does not support hard links, errno is
57 EOPNOTSUPP on FreeBSD,
58 EACCES on Android within Termux. */
63 #if defined __ANDROID__
67 fputs ("skipping test: "
68 "hard links not supported on this file system\n",
70 ASSERT (unlink (BASE
"a") == 0);
79 /* Now, for some behavior tests. Modify the contents of 'b', and
80 ensure that 'a' can see it, both while 'b' exists and after. */
81 fd
= open (BASE
"b", O_APPEND
| O_WRONLY
);
83 ASSERT (write (fd
, "world", 5) == 5);
84 ASSERT (close (fd
) == 0);
87 fd
= open (BASE
"a", O_RDONLY
);
89 ASSERT (read (fd
, buf
, 10) == 10);
90 ASSERT (strcmp (buf
, "helloworld") == 0);
91 ASSERT (close (fd
) == 0);
92 ASSERT (unlink (BASE
"b") == 0);
93 fd
= open (BASE
"a", O_RDONLY
);
95 ASSERT (read (fd
, buf
, 10) == 10);
96 ASSERT (strcmp (buf
, "helloworld") == 0);
97 ASSERT (close (fd
) == 0);
100 /* Test for various error conditions. */
101 ASSERT (mkdir (BASE
"d", 0700) == 0);
103 ASSERT (func (BASE
"a", ".") == -1);
104 ASSERT (errno
== EEXIST
|| errno
== EINVAL
);
106 ASSERT (func (BASE
"a", BASE
"a") == -1);
107 ASSERT (errno
== EEXIST
);
108 ASSERT (func (BASE
"a", BASE
"b") == 0);
110 ASSERT (func (BASE
"a", BASE
"b") == -1);
111 ASSERT (errno
== EEXIST
);
113 ASSERT (func (BASE
"a", BASE
"d") == -1);
114 ASSERT (errno
== EEXIST
);
116 ASSERT (func (BASE
"c", BASE
"e") == -1);
117 ASSERT (errno
== ENOENT
);
119 ASSERT (func (BASE
"a", BASE
"c/.") == -1);
120 ASSERT (errno
== ENOENT
);
122 ASSERT (func (BASE
"a/", BASE
"c") == -1);
123 ASSERT (errno
== ENOTDIR
|| errno
== EINVAL
);
125 ASSERT (func (BASE
"a", BASE
"c/") == -1);
126 ASSERT (errno
== ENOTDIR
|| errno
== ENOENT
|| errno
== EINVAL
);
128 /* Most platforms reject hard links to directories, and even on
129 those that do permit it, most users can't create them. We assume
130 that if this test is run as root and we managed to create a hard
131 link, then unlink better be able to clean it up. */
135 result
= func (BASE
"d", BASE
"c");
138 /* Probably root on Solaris. */
139 ASSERT (unlink (BASE
"c") == 0);
143 /* Most everyone else. */
144 ASSERT (errno
== EPERM
|| errno
== EACCES
|| errno
== EISDIR
);
146 ASSERT (func (BASE
"d/.", BASE
"c") == -1);
147 ASSERT (errno
== EPERM
|| errno
== EACCES
|| errno
== EISDIR
150 ASSERT (func (BASE
"d/.//", BASE
"c") == -1);
151 ASSERT (errno
== EPERM
|| errno
== EACCES
|| errno
== EISDIR
155 ASSERT (unlink (BASE
"a") == 0);
157 ASSERT (unlink (BASE
"c") == -1);
158 ASSERT (errno
== ENOENT
);
159 ASSERT (rmdir (BASE
"d") == 0);
161 /* Test invalid use of symlink. */
162 if (symlink (BASE
"a", BASE
"link") != 0)
164 ASSERT (unlink (BASE
"b") == 0);
166 fputs ("skipping test: symlinks not supported on this file system\n",
171 ASSERT (func (BASE
"b", BASE
"link/") == -1);
172 ASSERT (errno
== ENOTDIR
|| errno
== ENOENT
|| errno
== EEXIST
175 ASSERT (func (BASE
"b", BASE
"link") == -1);
176 ASSERT (errno
== EEXIST
);
177 ASSERT (rename (BASE
"b", BASE
"a") == 0);
179 ASSERT (func (BASE
"link/", BASE
"b") == -1);
180 ASSERT (errno
== ENOTDIR
|| errno
== EEXIST
|| errno
== EINVAL
);
183 ASSERT (unlink (BASE
"a") == 0);
184 ASSERT (unlink (BASE
"link") == 0);