1 /* Test of rename() function.
2 Copyright (C) 2009 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 2 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 <http://www.gnu.org/licenses/>. */
17 /* This file is designed to test both rename(a,b) and
18 renameat(AT_FDCWD,a,AT_FDCWD,b). 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 symlink tests with status 77. */
24 test_rename (int (*func) (char const *, char const *), bool print)
28 int fd = creat (BASE "file", 0600);
30 ASSERT (write (fd, "hi", 2) == 2);
31 ASSERT (close (fd) == 0);
32 ASSERT (mkdir (BASE "dir", 0700) == 0);
36 errno = 0; /* Missing source. */
37 ASSERT (func (BASE "missing", BASE "missing") == -1);
38 ASSERT (errno == ENOENT);
40 ASSERT (func (BASE "missing/", BASE "missing") == -1);
41 ASSERT (errno == ENOENT);
43 ASSERT (func (BASE "missing", BASE "missing/") == -1);
44 ASSERT (errno == ENOENT);
45 errno = 0; /* Empty operand. */
46 ASSERT (func ("", BASE "missing") == -1);
47 ASSERT (errno == ENOENT);
49 ASSERT (func (BASE "file", "") == -1);
50 ASSERT (errno == ENOENT);
52 ASSERT (func (BASE "", "") == -1);
53 ASSERT (errno == ENOENT);
56 errno = 0; /* Trailing slash. */
57 ASSERT (func (BASE "file", BASE "file2/") == -1);
58 ASSERT (errno == ENOENT || errno == ENOTDIR);
60 ASSERT (func (BASE "file/", BASE "file2") == -1);
61 ASSERT (errno == ENOTDIR);
63 ASSERT (stat (BASE "file2", &st) == -1);
64 ASSERT (errno == ENOENT);
65 ASSERT (func (BASE "file", BASE "file2") == 0); /* Simple rename. */
67 ASSERT (stat (BASE "file", &st) == -1);
68 ASSERT (errno == ENOENT);
69 memset (&st, 0, sizeof st);
70 ASSERT (stat (BASE "file2", &st) == 0);
71 ASSERT (st.st_size == 2);
72 ASSERT (close (creat (BASE "file", 0600)) == 0); /* Overwrite. */
74 ASSERT (func (BASE "file2", BASE "file/") == -1);
75 ASSERT (errno == ENOTDIR);
76 ASSERT (func (BASE "file2", BASE "file") == 0);
77 memset (&st, 0, sizeof st);
78 ASSERT (stat (BASE "file", &st) == 0);
79 ASSERT (st.st_size == 2);
81 ASSERT (stat (BASE "file2", &st) == -1);
82 ASSERT (errno == ENOENT);
85 ASSERT (func (BASE "dir", BASE "dir2/") == 0); /* Simple rename. */
87 ASSERT (stat (BASE "dir", &st) == -1);
88 ASSERT (errno == ENOENT);
89 ASSERT (stat (BASE "dir2", &st) == 0);
90 ASSERT (func (BASE "dir2/", BASE "dir") == 0);
91 ASSERT (stat (BASE "dir", &st) == 0);
93 ASSERT (stat (BASE "dir2", &st) == -1);
94 ASSERT (errno == ENOENT);
95 ASSERT (func (BASE "dir", BASE "dir2") == 0);
97 ASSERT (stat (BASE "dir", &st) == -1);
98 ASSERT (errno == ENOENT);
99 ASSERT (stat (BASE "dir2", &st) == 0);
100 ASSERT (mkdir (BASE "dir", 0700) == 0); /* Empty onto empty. */
101 ASSERT (func (BASE "dir2", BASE "dir") == 0);
102 ASSERT (mkdir (BASE "dir2", 0700) == 0);
103 ASSERT (func (BASE "dir2", BASE "dir/") == 0);
104 ASSERT (mkdir (BASE "dir2", 0700) == 0);
105 ASSERT (func (BASE "dir2/", BASE "dir") == 0);
106 ASSERT (mkdir (BASE "dir2", 0700) == 0);
107 ASSERT (close (creat (BASE "dir/file", 0600)) == 0); /* Empty onto full. */
109 ASSERT (func (BASE "dir2", BASE "dir") == -1);
110 ASSERT (errno == EEXIST || errno == ENOTEMPTY);
112 ASSERT (func (BASE "dir2/", BASE "dir") == -1);
113 ASSERT (errno == EEXIST || errno == ENOTEMPTY);
115 ASSERT (func (BASE "dir2", BASE "dir/") == -1);
116 ASSERT (errno == EEXIST || errno == ENOTEMPTY);
117 ASSERT (func (BASE "dir", BASE "dir2") == 0); /* Full onto empty. */
119 ASSERT (stat (BASE "dir", &st) == -1);
120 ASSERT (errno == ENOENT);
121 ASSERT (stat (BASE "dir2/file", &st) == 0);
122 ASSERT (mkdir (BASE "dir", 0700) == 0);
123 ASSERT (func (BASE "dir2/", BASE "dir") == 0);
124 ASSERT (stat (BASE "dir/file", &st) == 0);
126 ASSERT (stat (BASE "dir2", &st) == -1);
127 ASSERT (errno == ENOENT);
128 ASSERT (mkdir (BASE "dir2", 0700) == 0);
129 ASSERT (func (BASE "dir", BASE "dir2/") == 0);
131 ASSERT (stat (BASE "dir", &st) == -1);
132 ASSERT (errno == ENOENT);
133 ASSERT (stat (BASE "dir2/file", &st) == 0);
134 ASSERT (unlink (BASE "dir2/file") == 0);
135 errno = 0; /* Reject trailing dot. */
136 ASSERT (func (BASE "dir2", BASE "dir/.") == -1);
137 ASSERT (errno == EINVAL || errno == ENOENT);
138 ASSERT (mkdir (BASE "dir", 0700) == 0);
140 ASSERT (func (BASE "dir2", BASE "dir/.") == -1);
141 ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR);
143 ASSERT (func (BASE "dir2/.", BASE "dir") == -1);
144 ASSERT (errno == EINVAL || errno == EBUSY);
145 ASSERT (rmdir (BASE "dir") == 0);
147 ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
148 ASSERT (errno == EINVAL || errno == ENOENT);
149 ASSERT (mkdir (BASE "dir", 0700) == 0);
151 ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
152 ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR);
154 ASSERT (func (BASE "dir2/.//", BASE "dir") == -1);
155 ASSERT (errno == EINVAL || errno == EBUSY);
156 ASSERT (rmdir (BASE "dir2") == 0);
157 errno = 0; /* Move into subdir. */
158 ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
159 ASSERT (errno == EINVAL || errno == EACCES);
161 ASSERT (stat (BASE "dir/sub", &st) == -1);
162 ASSERT (errno == ENOENT);
163 ASSERT (mkdir (BASE "dir/sub", 0700) == 0);
165 ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
166 ASSERT (errno == EINVAL);
167 ASSERT (stat (BASE "dir/sub", &st) == 0);
168 ASSERT (rmdir (BASE "dir/sub") == 0);
170 /* Mixing file and directory. */
171 errno = 0; /* File onto dir. */
172 ASSERT (func (BASE "file", BASE "dir") == -1);
173 ASSERT (errno == EISDIR || errno == ENOTDIR);
175 ASSERT (func (BASE "file", BASE "dir/") == -1);
176 ASSERT (errno == EISDIR || errno == ENOTDIR);
177 errno = 0; /* Dir onto file. */
178 ASSERT (func (BASE "dir", BASE "file") == -1);
179 ASSERT (errno == ENOTDIR);
181 ASSERT (func (BASE "dir/", BASE "file") == -1);
182 ASSERT (errno == ENOTDIR);
185 ASSERT (func (BASE "file", BASE "file") == 0); /* File onto self. */
186 memset (&st, 0, sizeof st);
187 ASSERT (stat (BASE "file", &st) == 0);
188 ASSERT (st.st_size == 2);
189 ASSERT (func (BASE "dir", BASE "dir") == 0); /* Empty dir onto self. */
190 ASSERT (stat (BASE "dir", &st) == 0);
191 ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
192 ASSERT (func (BASE "dir", BASE "dir") == 0); /* Full dir onto self. */
193 ASSERT (unlink (BASE "dir/file") == 0);
195 /* Not all file systems support link. Mingw doesn't have
196 reliable st_nlink on hard links, but our implementation does
197 fail with EPERM on poor file systems, and we can detect the
198 inferior stat() via st_ino. Cygwin 1.5.x copies rather than
199 links files on those file systems, but there, st_nlink and
200 st_ino are reliable. */
201 int ret = link (BASE "file", BASE "file2");
204 memset (&st, 0, sizeof st);
205 ASSERT (stat (BASE "file2", &st) == 0);
206 if (st.st_ino && st.st_nlink != 2)
208 ASSERT (unlink (BASE "file2") == 0);
215 /* If the device does not support hard links, errno is
216 EPERM on Linux, EOPNOTSUPP on FreeBSD. */
222 fputs ("skipping test: "
223 "hard links not supported on this file system\n",
225 ASSERT (unlink (BASE "file") == 0);
226 ASSERT (rmdir (BASE "dir") == 0);
235 ASSERT (func (BASE "file", BASE "file2") == 0); /* File onto hard link. */
236 memset (&st, 0, sizeof st);
237 ASSERT (stat (BASE "file", &st) == 0);
238 ASSERT (st.st_size == 2);
239 memset (&st, 0, sizeof st);
240 ASSERT (stat (BASE "file2", &st) == 0);
241 ASSERT (st.st_size == 2);
242 ASSERT (unlink (BASE "file2") == 0);
245 if (symlink (BASE "file", BASE "link1"))
248 fputs ("skipping test: symlinks not supported on this filesystem\n",
250 ASSERT (unlink (BASE "file") == 0);
251 ASSERT (rmdir (BASE "dir") == 0);
254 ASSERT (func (BASE "link1", BASE "link2") == 0); /* Simple rename. */
255 ASSERT (stat (BASE "file", &st) == 0);
257 ASSERT (lstat (BASE "link1", &st) == -1);
258 ASSERT (errno == ENOENT);
259 memset (&st, 0, sizeof st);
260 ASSERT (lstat (BASE "link2", &st) == 0);
261 ASSERT (S_ISLNK (st.st_mode));
262 ASSERT (symlink (BASE "nowhere", BASE "link1") == 0); /* Overwrite. */
263 ASSERT (func (BASE "link2", BASE "link1") == 0);
264 memset (&st, 0, sizeof st);
265 ASSERT (stat (BASE "link1", &st) == 0);
266 ASSERT (st.st_size == 2);
268 ASSERT (lstat (BASE "link2", &st) == -1);
269 ASSERT (errno == ENOENT);
270 ASSERT (symlink (BASE "link2", BASE "link2") == 0); /* Symlink loop. */
271 ASSERT (func (BASE "link2", BASE "link2") == 0);
273 ASSERT (func (BASE "link2/", BASE "link2") == -1);
274 ASSERT (errno == ELOOP || errno == ENOTDIR);
275 ASSERT (func (BASE "link2", BASE "link3") == 0);
276 ASSERT (unlink (BASE "link3") == 0);
277 ASSERT (symlink (BASE "nowhere", BASE "link2") == 0); /* Dangling link. */
278 ASSERT (func (BASE "link2", BASE "link3") == 0);
280 ASSERT (lstat (BASE "link2", &st) == -1);
281 ASSERT (errno == ENOENT);
282 memset (&st, 0, sizeof st);
283 ASSERT (lstat (BASE "link3", &st) == 0);
284 errno = 0; /* Trailing slash on dangling. */
285 ASSERT (func (BASE "link3/", BASE "link2") == -1);
286 ASSERT (errno == ENOENT || errno == ENOTDIR);
288 ASSERT (func (BASE "link3", BASE "link2/") == -1);
289 ASSERT (errno == ENOENT || errno == ENOTDIR);
291 ASSERT (lstat (BASE "link2", &st) == -1);
292 ASSERT (errno == ENOENT);
293 memset (&st, 0, sizeof st);
294 ASSERT (lstat (BASE "link3", &st) == 0);
295 errno = 0; /* Trailing slash on link to file. */
296 ASSERT (func (BASE "link1/", BASE "link2") == -1);
297 ASSERT (errno == ENOTDIR);
299 ASSERT (func (BASE "link1", BASE "link3/") == -1);
300 ASSERT (errno == ENOENT || errno == ENOTDIR);
302 /* Mixing symlink and file. */
303 ASSERT (close (creat (BASE "file2", 0600)) == 0); /* File onto link. */
304 ASSERT (func (BASE "file2", BASE "link3") == 0);
306 ASSERT (stat (BASE "file2", &st) == -1);
307 ASSERT (errno == ENOENT);
308 memset (&st, 0, sizeof st);
309 ASSERT (lstat (BASE "link3", &st) == 0);
310 ASSERT (S_ISREG (st.st_mode));
311 ASSERT (unlink (BASE "link3") == 0);
312 ASSERT (symlink (BASE "nowhere", BASE "link2") == 0); /* Link onto file. */
313 ASSERT (close (creat (BASE "file2", 0600)) == 0);
314 ASSERT (func (BASE "link2", BASE "file2") == 0);
316 ASSERT (lstat (BASE "link2", &st) == -1);
317 ASSERT (errno == ENOENT);
318 memset (&st, 0, sizeof st);
319 ASSERT (lstat (BASE "file2", &st) == 0);
320 ASSERT (S_ISLNK (st.st_mode));
321 ASSERT (unlink (BASE "file2") == 0);
322 errno = 0; /* Trailing slash. */
323 ASSERT (func (BASE "file/", BASE "link1") == -1);
324 ASSERT (errno == ENOTDIR);
326 ASSERT (func (BASE "file", BASE "link1/") == -1);
327 ASSERT (errno == ENOTDIR || errno == ENOENT);
329 ASSERT (func (BASE "link1/", BASE "file") == -1);
330 ASSERT (errno == ENOTDIR);
332 ASSERT (func (BASE "link1", BASE "file/") == -1);
333 ASSERT (errno == ENOTDIR || errno == ENOENT);
334 memset (&st, 0, sizeof st);
335 ASSERT (lstat (BASE "file", &st) == 0);
336 ASSERT (S_ISREG (st.st_mode));
337 memset (&st, 0, sizeof st);
338 ASSERT (lstat (BASE "link1", &st) == 0);
339 ASSERT (S_ISLNK (st.st_mode));
341 /* Mixing symlink and directory. */
342 errno = 0; /* Directory onto link. */
343 ASSERT (func (BASE "dir", BASE "link1") == -1);
344 ASSERT (errno == ENOTDIR);
346 ASSERT (func (BASE "dir/", BASE "link1") == -1);
347 ASSERT (errno == ENOTDIR);
349 ASSERT (func (BASE "dir", BASE "link1/") == -1);
350 ASSERT (errno == ENOTDIR);
351 errno = 0; /* Link onto directory. */
352 ASSERT (func (BASE "link1", BASE "dir") == -1);
353 ASSERT (errno == EISDIR || errno == ENOTDIR);
355 ASSERT (func (BASE "link1", BASE "dir/") == -1);
356 ASSERT (errno == EISDIR || errno == ENOTDIR);
358 ASSERT (func (BASE "link1/", BASE "dir") == -1);
359 ASSERT (errno == ENOTDIR);
360 memset (&st, 0, sizeof st);
361 ASSERT (lstat (BASE "link1", &st) == 0);
362 ASSERT (S_ISLNK (st.st_mode));
363 memset (&st, 0, sizeof st);
364 ASSERT (lstat (BASE "dir", &st) == 0);
365 ASSERT (S_ISDIR (st.st_mode));
367 /* POSIX requires rename("link-to-dir/","other") to rename "dir" and
368 leave "link-to-dir" dangling, but GNU rejects this. POSIX
369 requires rename("dir","dangling/") to create the directory so
370 that "dangling/" now resolves, but GNU rejects this. While we
371 prefer GNU behavior, we don't enforce it. However, we do test
372 that the system either follows POSIX in both cases, or follows
376 ASSERT (symlink (BASE "dir2", BASE "link2") == 0);
378 result = func (BASE "dir", BASE "link2/");
383 ASSERT (lstat (BASE "dir", &st) == -1);
384 ASSERT (errno == ENOENT);
385 memset (&st, 0, sizeof st);
386 ASSERT (lstat (BASE "dir2", &st) == 0);
387 ASSERT (S_ISDIR (st.st_mode));
388 memset (&st, 0, sizeof st);
389 ASSERT (lstat (BASE "link2", &st) == 0);
390 ASSERT (S_ISLNK (st.st_mode));
391 ASSERT (func (BASE "link2/", BASE "dir") == 0);
392 memset (&st, 0, sizeof st);
393 ASSERT (lstat (BASE "dir", &st) == 0);
394 ASSERT (S_ISDIR (st.st_mode));
396 ASSERT (lstat (BASE "dir2", &st) == -1);
397 ASSERT (errno == ENOENT);
398 memset (&st, 0, sizeof st);
399 ASSERT (lstat (BASE "link2", &st) == 0);
400 ASSERT (S_ISLNK (st.st_mode));
405 ASSERT (result == -1);
406 ASSERT (errno == ENOTDIR);
407 memset (&st, 0, sizeof st);
408 ASSERT (lstat (BASE "dir", &st) == 0);
409 ASSERT (S_ISDIR (st.st_mode));
411 ASSERT (lstat (BASE "dir2", &st) == -1);
412 ASSERT (errno == ENOENT);
413 memset (&st, 0, sizeof st);
414 ASSERT (lstat (BASE "link2", &st) == 0);
415 ASSERT (S_ISLNK (st.st_mode));
416 ASSERT (unlink (BASE "link2") == 0);
417 ASSERT (symlink (BASE "dir", BASE "link2") == 0);
418 errno = 0; /* OpenBSD notices that link2/ and dir are the same. */
419 result = func (BASE "link2/", BASE "dir");
420 if (result) /* GNU/Linux rejects attempts to use link2/. */
422 ASSERT (result == -1);
423 ASSERT (errno == ENOTDIR);
425 memset (&st, 0, sizeof st);
426 ASSERT (lstat (BASE "dir", &st) == 0);
427 ASSERT (S_ISDIR (st.st_mode));
429 ASSERT (lstat (BASE "dir2", &st) == -1);
430 ASSERT (errno == ENOENT);
431 memset (&st, 0, sizeof st);
432 ASSERT (lstat (BASE "link2", &st) == 0);
433 ASSERT (S_ISLNK (st.st_mode));
438 ASSERT (unlink (BASE "file") == 0);
439 ASSERT (rmdir (BASE "dir") == 0);
440 ASSERT (unlink (BASE "link1") == 0);
441 ASSERT (unlink (BASE "link2") == 0);