1 /* Test of rename() function.
2 Copyright (C) 2009, 2010 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 <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
142 || errno == ENOTEMPTY);
144 ASSERT (func (BASE "dir2/.", BASE "dir") == -1);
145 ASSERT (errno == EINVAL || errno == EBUSY);
146 ASSERT (rmdir (BASE "dir") == 0);
148 ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
149 ASSERT (errno == EINVAL || errno == ENOENT);
150 ASSERT (mkdir (BASE "dir", 0700) == 0);
152 ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
153 ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR
154 || errno == ENOTEMPTY);
156 ASSERT (func (BASE "dir2/.//", BASE "dir") == -1);
157 ASSERT (errno == EINVAL || errno == EBUSY);
158 ASSERT (rmdir (BASE "dir2") == 0);
159 errno = 0; /* Move into subdir. */
160 ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
161 ASSERT (errno == EINVAL || errno == EACCES);
163 ASSERT (stat (BASE "dir/sub", &st) == -1);
164 ASSERT (errno == ENOENT);
165 ASSERT (mkdir (BASE "dir/sub", 0700) == 0);
167 ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
168 ASSERT (errno == EINVAL);
169 ASSERT (stat (BASE "dir/sub", &st) == 0);
170 ASSERT (rmdir (BASE "dir/sub") == 0);
172 /* Mixing file and directory. */
173 errno = 0; /* File onto dir. */
174 ASSERT (func (BASE "file", BASE "dir") == -1);
175 ASSERT (errno == EISDIR || errno == ENOTDIR);
177 ASSERT (func (BASE "file", BASE "dir/") == -1);
178 ASSERT (errno == EISDIR || errno == ENOTDIR);
179 errno = 0; /* Dir onto file. */
180 ASSERT (func (BASE "dir", BASE "file") == -1);
181 ASSERT (errno == ENOTDIR);
183 ASSERT (func (BASE "dir/", BASE "file") == -1);
184 ASSERT (errno == ENOTDIR);
187 ASSERT (func (BASE "file", BASE "file") == 0); /* File onto self. */
188 memset (&st, 0, sizeof st);
189 ASSERT (stat (BASE "file", &st) == 0);
190 ASSERT (st.st_size == 2);
191 ASSERT (func (BASE "dir", BASE "dir") == 0); /* Empty dir onto self. */
192 ASSERT (stat (BASE "dir", &st) == 0);
193 ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
194 ASSERT (func (BASE "dir", BASE "dir") == 0); /* Full dir onto self. */
195 ASSERT (unlink (BASE "dir/file") == 0);
197 /* Not all file systems support link. Mingw doesn't have
198 reliable st_nlink on hard links, but our implementation does
199 fail with EPERM on poor file systems, and we can detect the
200 inferior stat() via st_ino. Cygwin 1.5.x copies rather than
201 links files on those file systems, but there, st_nlink and
202 st_ino are reliable. */
203 int ret = link (BASE "file", BASE "file2");
206 memset (&st, 0, sizeof st);
207 ASSERT (stat (BASE "file2", &st) == 0);
208 if (st.st_ino && st.st_nlink != 2)
210 ASSERT (unlink (BASE "file2") == 0);
217 /* If the device does not support hard links, errno is
218 EPERM on Linux, EOPNOTSUPP on FreeBSD. */
224 fputs ("skipping test: "
225 "hard links not supported on this file system\n",
227 ASSERT (unlink (BASE "file") == 0);
228 ASSERT (rmdir (BASE "dir") == 0);
237 ASSERT (func (BASE "file", BASE "file2") == 0); /* File onto hard link. */
238 memset (&st, 0, sizeof st);
239 ASSERT (stat (BASE "file", &st) == 0);
240 ASSERT (st.st_size == 2);
241 memset (&st, 0, sizeof st);
242 ASSERT (stat (BASE "file2", &st) == 0);
243 ASSERT (st.st_size == 2);
244 ASSERT (unlink (BASE "file2") == 0);
247 if (symlink (BASE "file", BASE "link1"))
250 fputs ("skipping test: symlinks not supported on this file system\n",
252 ASSERT (unlink (BASE "file") == 0);
253 ASSERT (rmdir (BASE "dir") == 0);
256 ASSERT (func (BASE "link1", BASE "link2") == 0); /* Simple rename. */
257 ASSERT (stat (BASE "file", &st) == 0);
259 ASSERT (lstat (BASE "link1", &st) == -1);
260 ASSERT (errno == ENOENT);
261 memset (&st, 0, sizeof st);
262 ASSERT (lstat (BASE "link2", &st) == 0);
263 ASSERT (S_ISLNK (st.st_mode));
264 ASSERT (symlink (BASE "nowhere", BASE "link1") == 0); /* Overwrite. */
265 ASSERT (func (BASE "link2", BASE "link1") == 0);
266 memset (&st, 0, sizeof st);
267 ASSERT (stat (BASE "link1", &st) == 0);
268 ASSERT (st.st_size == 2);
270 ASSERT (lstat (BASE "link2", &st) == -1);
271 ASSERT (errno == ENOENT);
272 ASSERT (symlink (BASE "link2", BASE "link2") == 0); /* Symlink loop. */
273 ASSERT (func (BASE "link2", BASE "link2") == 0);
275 ASSERT (func (BASE "link2/", BASE "link2") == -1);
276 ASSERT (errno == ELOOP || errno == ENOTDIR);
277 ASSERT (func (BASE "link2", BASE "link3") == 0);
278 ASSERT (unlink (BASE "link3") == 0);
279 ASSERT (symlink (BASE "nowhere", BASE "link2") == 0); /* Dangling link. */
280 ASSERT (func (BASE "link2", BASE "link3") == 0);
282 ASSERT (lstat (BASE "link2", &st) == -1);
283 ASSERT (errno == ENOENT);
284 memset (&st, 0, sizeof st);
285 ASSERT (lstat (BASE "link3", &st) == 0);
286 errno = 0; /* Trailing slash on dangling. */
287 ASSERT (func (BASE "link3/", BASE "link2") == -1);
288 ASSERT (errno == ENOENT || errno == ENOTDIR);
290 ASSERT (func (BASE "link3", BASE "link2/") == -1);
291 ASSERT (errno == ENOENT || errno == ENOTDIR);
293 ASSERT (lstat (BASE "link2", &st) == -1);
294 ASSERT (errno == ENOENT);
295 memset (&st, 0, sizeof st);
296 ASSERT (lstat (BASE "link3", &st) == 0);
297 errno = 0; /* Trailing slash on link to file. */
298 ASSERT (func (BASE "link1/", BASE "link2") == -1);
299 ASSERT (errno == ENOTDIR);
301 ASSERT (func (BASE "link1", BASE "link3/") == -1);
302 ASSERT (errno == ENOENT || errno == ENOTDIR);
304 /* Mixing symlink and file. */
305 ASSERT (close (creat (BASE "file2", 0600)) == 0); /* File onto link. */
306 ASSERT (func (BASE "file2", BASE "link3") == 0);
308 ASSERT (stat (BASE "file2", &st) == -1);
309 ASSERT (errno == ENOENT);
310 memset (&st, 0, sizeof st);
311 ASSERT (lstat (BASE "link3", &st) == 0);
312 ASSERT (S_ISREG (st.st_mode));
313 ASSERT (unlink (BASE "link3") == 0);
314 ASSERT (symlink (BASE "nowhere", BASE "link2") == 0); /* Link onto file. */
315 ASSERT (close (creat (BASE "file2", 0600)) == 0);
316 ASSERT (func (BASE "link2", BASE "file2") == 0);
318 ASSERT (lstat (BASE "link2", &st) == -1);
319 ASSERT (errno == ENOENT);
320 memset (&st, 0, sizeof st);
321 ASSERT (lstat (BASE "file2", &st) == 0);
322 ASSERT (S_ISLNK (st.st_mode));
323 ASSERT (unlink (BASE "file2") == 0);
324 errno = 0; /* Trailing slash. */
325 ASSERT (func (BASE "file/", BASE "link1") == -1);
326 ASSERT (errno == ENOTDIR);
328 ASSERT (func (BASE "file", BASE "link1/") == -1);
329 ASSERT (errno == ENOTDIR || errno == ENOENT);
331 ASSERT (func (BASE "link1/", BASE "file") == -1);
332 ASSERT (errno == ENOTDIR);
334 ASSERT (func (BASE "link1", BASE "file/") == -1);
335 ASSERT (errno == ENOTDIR || errno == ENOENT);
336 memset (&st, 0, sizeof st);
337 ASSERT (lstat (BASE "file", &st) == 0);
338 ASSERT (S_ISREG (st.st_mode));
339 memset (&st, 0, sizeof st);
340 ASSERT (lstat (BASE "link1", &st) == 0);
341 ASSERT (S_ISLNK (st.st_mode));
343 /* Mixing symlink and directory. */
344 errno = 0; /* Directory onto link. */
345 ASSERT (func (BASE "dir", BASE "link1") == -1);
346 ASSERT (errno == ENOTDIR);
348 ASSERT (func (BASE "dir/", BASE "link1") == -1);
349 ASSERT (errno == ENOTDIR);
351 ASSERT (func (BASE "dir", BASE "link1/") == -1);
352 ASSERT (errno == ENOTDIR);
353 errno = 0; /* Link onto directory. */
354 ASSERT (func (BASE "link1", BASE "dir") == -1);
355 ASSERT (errno == EISDIR || errno == ENOTDIR);
357 ASSERT (func (BASE "link1", BASE "dir/") == -1);
358 ASSERT (errno == EISDIR || errno == ENOTDIR);
360 ASSERT (func (BASE "link1/", BASE "dir") == -1);
361 ASSERT (errno == ENOTDIR);
362 memset (&st, 0, sizeof st);
363 ASSERT (lstat (BASE "link1", &st) == 0);
364 ASSERT (S_ISLNK (st.st_mode));
365 memset (&st, 0, sizeof st);
366 ASSERT (lstat (BASE "dir", &st) == 0);
367 ASSERT (S_ISDIR (st.st_mode));
369 /* POSIX requires rename("link-to-dir/","other") to rename "dir" and
370 leave "link-to-dir" dangling, but GNU rejects this. POSIX
371 requires rename("dir","dangling/") to create the directory so
372 that "dangling/" now resolves, but GNU rejects this. While we
373 prefer GNU behavior, we don't enforce it. However, we do test
374 that the system either follows POSIX in both cases, or follows
378 ASSERT (symlink (BASE "dir2", BASE "link2") == 0);
380 result = func (BASE "dir", BASE "link2/");
385 ASSERT (lstat (BASE "dir", &st) == -1);
386 ASSERT (errno == ENOENT);
387 memset (&st, 0, sizeof st);
388 ASSERT (lstat (BASE "dir2", &st) == 0);
389 ASSERT (S_ISDIR (st.st_mode));
390 memset (&st, 0, sizeof st);
391 ASSERT (lstat (BASE "link2", &st) == 0);
392 ASSERT (S_ISLNK (st.st_mode));
393 ASSERT (func (BASE "link2/", BASE "dir") == 0);
394 memset (&st, 0, sizeof st);
395 ASSERT (lstat (BASE "dir", &st) == 0);
396 ASSERT (S_ISDIR (st.st_mode));
398 ASSERT (lstat (BASE "dir2", &st) == -1);
399 ASSERT (errno == ENOENT);
400 memset (&st, 0, sizeof st);
401 ASSERT (lstat (BASE "link2", &st) == 0);
402 ASSERT (S_ISLNK (st.st_mode));
407 ASSERT (result == -1);
408 ASSERT (errno == ENOTDIR);
409 memset (&st, 0, sizeof st);
410 ASSERT (lstat (BASE "dir", &st) == 0);
411 ASSERT (S_ISDIR (st.st_mode));
413 ASSERT (lstat (BASE "dir2", &st) == -1);
414 ASSERT (errno == ENOENT);
415 memset (&st, 0, sizeof st);
416 ASSERT (lstat (BASE "link2", &st) == 0);
417 ASSERT (S_ISLNK (st.st_mode));
418 ASSERT (unlink (BASE "link2") == 0);
419 ASSERT (symlink (BASE "dir", BASE "link2") == 0);
420 errno = 0; /* OpenBSD notices that link2/ and dir are the same. */
421 result = func (BASE "link2/", BASE "dir");
422 if (result) /* GNU/Linux rejects attempts to use link2/. */
424 ASSERT (result == -1);
425 ASSERT (errno == ENOTDIR);
427 memset (&st, 0, sizeof st);
428 ASSERT (lstat (BASE "dir", &st) == 0);
429 ASSERT (S_ISDIR (st.st_mode));
431 ASSERT (lstat (BASE "dir2", &st) == -1);
432 ASSERT (errno == ENOENT);
433 memset (&st, 0, sizeof st);
434 ASSERT (lstat (BASE "link2", &st) == 0);
435 ASSERT (S_ISLNK (st.st_mode));
440 ASSERT (unlink (BASE "file") == 0);
441 ASSERT (rmdir (BASE "dir") == 0);
442 ASSERT (unlink (BASE "link1") == 0);
443 ASSERT (unlink (BASE "link2") == 0);