spawn: Use special invocation for <spawn.h> on OS/2 kLIBC.
[gnulib.git] / tests / test-link.h
blob6806546c069a9b92f236fefcfe6092cbf82749fa
1 /* Test of link() function.
2 Copyright (C) 2009-2021 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. */
24 static int
25 test_link (int (*func) (char const *, char const *), bool print)
27 int fd;
28 int ret;
30 /* Create first file. */
31 fd = open (BASE "a", O_CREAT | O_EXCL | O_WRONLY, 0600);
32 ASSERT (0 <= fd);
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");
42 if (!ret)
44 struct stat st;
45 ASSERT (stat (BASE "b", &st) == 0);
46 if (st.st_ino && st.st_nlink != 2)
48 ASSERT (unlink (BASE "b") == 0);
49 errno = EPERM;
50 ret = -1;
53 if (ret == -1)
55 /* If the device does not support hard links, errno is
56 EPERM on Linux, EOPNOTSUPP on FreeBSD. */
57 switch (errno)
59 case EPERM:
60 case EOPNOTSUPP:
61 if (print)
62 fputs ("skipping test: "
63 "hard links not supported on this file system\n",
64 stderr);
65 ASSERT (unlink (BASE "a") == 0);
66 return 77;
67 default:
68 perror ("link");
69 return 1;
72 ASSERT (ret == 0);
74 /* Now, for some behavior tests. Modify the contents of 'b', and
75 ensure that 'a' can see it, both while 'b' exists and after. */
76 fd = open (BASE "b", O_APPEND | O_WRONLY);
77 ASSERT (0 <= fd);
78 ASSERT (write (fd, "world", 5) == 5);
79 ASSERT (close (fd) == 0);
81 char buf[11] = { 0 };
82 fd = open (BASE "a", O_RDONLY);
83 ASSERT (0 <= fd);
84 ASSERT (read (fd, buf, 10) == 10);
85 ASSERT (strcmp (buf, "helloworld") == 0);
86 ASSERT (close (fd) == 0);
87 ASSERT (unlink (BASE "b") == 0);
88 fd = open (BASE "a", O_RDONLY);
89 ASSERT (0 <= fd);
90 ASSERT (read (fd, buf, 10) == 10);
91 ASSERT (strcmp (buf, "helloworld") == 0);
92 ASSERT (close (fd) == 0);
95 /* Test for various error conditions. */
96 ASSERT (mkdir (BASE "d", 0700) == 0);
97 errno = 0;
98 ASSERT (func (BASE "a", ".") == -1);
99 ASSERT (errno == EEXIST || errno == EINVAL);
100 errno = 0;
101 ASSERT (func (BASE "a", BASE "a") == -1);
102 ASSERT (errno == EEXIST);
103 ASSERT (func (BASE "a", BASE "b") == 0);
104 errno = 0;
105 ASSERT (func (BASE "a", BASE "b") == -1);
106 ASSERT (errno == EEXIST);
107 errno = 0;
108 ASSERT (func (BASE "a", BASE "d") == -1);
109 ASSERT (errno == EEXIST);
110 errno = 0;
111 ASSERT (func (BASE "c", BASE "e") == -1);
112 ASSERT (errno == ENOENT);
113 errno = 0;
114 ASSERT (func (BASE "a", BASE "c/.") == -1);
115 ASSERT (errno == ENOENT);
116 errno = 0;
117 ASSERT (func (BASE "a/", BASE "c") == -1);
118 ASSERT (errno == ENOTDIR || errno == EINVAL);
119 errno = 0;
120 ASSERT (func (BASE "a", BASE "c/") == -1);
121 ASSERT (errno == ENOTDIR || errno == ENOENT || errno == EINVAL);
123 /* Most platforms reject hard links to directories, and even on
124 those that do permit it, most users can't create them. We assume
125 that if this test is run as root and we managed to create a hard
126 link, then unlink better be able to clean it up. */
128 int result;
129 errno = 0;
130 result = func (BASE "d", BASE "c");
131 if (result == 0)
133 /* Probably root on Solaris. */
134 ASSERT (unlink (BASE "c") == 0);
136 else
138 /* Most everyone else. */
139 ASSERT (errno == EPERM || errno == EACCES || errno == EISDIR);
140 errno = 0;
141 ASSERT (func (BASE "d/.", BASE "c") == -1);
142 ASSERT (errno == EPERM || errno == EACCES || errno == EISDIR
143 || errno == EINVAL);
144 errno = 0;
145 ASSERT (func (BASE "d/.//", BASE "c") == -1);
146 ASSERT (errno == EPERM || errno == EACCES || errno == EISDIR
147 || errno == EINVAL);
150 ASSERT (unlink (BASE "a") == 0);
151 errno = 0;
152 ASSERT (unlink (BASE "c") == -1);
153 ASSERT (errno == ENOENT);
154 ASSERT (rmdir (BASE "d") == 0);
156 /* Test invalid use of symlink. */
157 if (symlink (BASE "a", BASE "link") != 0)
159 ASSERT (unlink (BASE "b") == 0);
160 if (print)
161 fputs ("skipping test: symlinks not supported on this file system\n",
162 stderr);
163 return 77;
165 errno = 0;
166 ASSERT (func (BASE "b", BASE "link/") == -1);
167 ASSERT (errno == ENOTDIR || errno == ENOENT || errno == EEXIST
168 || errno == EINVAL);
169 errno = 0;
170 ASSERT (func (BASE "b", BASE "link") == -1);
171 ASSERT (errno == EEXIST);
172 ASSERT (rename (BASE "b", BASE "a") == 0);
173 errno = 0;
174 ASSERT (func (BASE "link/", BASE "b") == -1);
175 ASSERT (errno == ENOTDIR || errno == EEXIST || errno == EINVAL);
177 /* Clean up. */
178 ASSERT (unlink (BASE "a") == 0);
179 ASSERT (unlink (BASE "link") == 0);
181 return 0;