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. */
23 /* Tests whether a file, given by a file name without slashes, exists in
24 the current directory, by scanning the directory entries. */
26 dentry_exists (const char *filename)
29 DIR *dir = opendir (".");
34 struct dirent *d = readdir (dir);
37 if (strcmp (d->d_name, filename) == 0)
43 ASSERT (closedir (dir) == 0);
47 /* Asserts that a specific file, given by a file name without slashes, does
48 not exist in the current directory. */
50 assert_nonexistent (const char *filename)
54 /* The usual way to test the presence of a file is via stat() or lstat(). */
56 if (stat (filename, &st) == -1)
57 ASSERT (errno == ENOENT);
59 /* But after renaming a directory over an empty directory on an NFS-mounted
60 file system, on Linux 2.6.18, for a period of 30 seconds the old
61 directory name is "present" according to stat() but "nonexistent"
62 according to dentry_exists(). */
63 ASSERT (!dentry_exists (filename));
67 test_rename (int (*func) (char const *, char const *), bool print)
71 int fd = creat (BASE "file", 0600);
73 ASSERT (write (fd, "hi", 2) == 2);
74 ASSERT (close (fd) == 0);
75 ASSERT (mkdir (BASE "dir", 0700) == 0);
77 /* Files present here:
84 { /* Missing source. */
87 ASSERT (func (BASE "missing", BASE "missing") == -1);
88 ASSERT (errno == ENOENT);
92 ASSERT (func (BASE "missing/", BASE "missing") == -1);
93 ASSERT (errno == ENOENT);
97 ASSERT (func (BASE "missing", BASE "missing/") == -1);
98 ASSERT (errno == ENOENT);
101 { /* Empty operand. */
104 ASSERT (func ("", BASE "missing") == -1);
105 ASSERT (errno == ENOENT);
109 ASSERT (func (BASE "file", "") == -1);
110 ASSERT (errno == ENOENT);
114 ASSERT (func (BASE "", "") == -1);
115 ASSERT (errno == ENOENT);
121 { /* Trailing slash. */
124 ASSERT (func (BASE "file", BASE "file2/") == -1);
125 ASSERT (errno == ENOENT || errno == ENOTDIR);
129 ASSERT (func (BASE "file/", BASE "file2") == -1);
130 ASSERT (errno == ENOTDIR);
134 ASSERT (stat (BASE "file2", &st) == -1);
135 ASSERT (errno == ENOENT);
138 { /* Simple rename. */
139 ASSERT (func (BASE "file", BASE "file2") == 0);
141 ASSERT (stat (BASE "file", &st) == -1);
142 ASSERT (errno == ENOENT);
143 memset (&st, 0, sizeof st);
144 ASSERT (stat (BASE "file2", &st) == 0);
145 ASSERT (st.st_size == 2);
147 /* Files present here:
152 ASSERT (close (creat (BASE "file", 0600)) == 0);
154 ASSERT (func (BASE "file2", BASE "file/") == -1);
155 ASSERT (errno == ENOTDIR);
156 ASSERT (func (BASE "file2", BASE "file") == 0);
157 memset (&st, 0, sizeof st);
158 ASSERT (stat (BASE "file", &st) == 0);
159 ASSERT (st.st_size == 2);
161 ASSERT (stat (BASE "file2", &st) == -1);
162 ASSERT (errno == ENOENT);
164 /* Files present here:
171 { /* Simple rename. */
173 ASSERT (func (BASE "dir", BASE "dir2/") == 0);
175 ASSERT (stat (BASE "dir", &st) == -1);
176 ASSERT (errno == ENOENT);
177 ASSERT (stat (BASE "dir2", &st) == 0);
179 /* Files present here:
184 ASSERT (func (BASE "dir2/", BASE "dir") == 0);
185 ASSERT (stat (BASE "dir", &st) == 0);
187 ASSERT (stat (BASE "dir2", &st) == -1);
188 ASSERT (errno == ENOENT);
190 /* Files present here:
195 ASSERT (func (BASE "dir", BASE "dir2") == 0);
197 ASSERT (stat (BASE "dir", &st) == -1);
198 ASSERT (errno == ENOENT);
199 ASSERT (stat (BASE "dir2", &st) == 0);
201 /* Files present here:
205 { /* Empty onto empty. */
206 ASSERT (mkdir (BASE "dir", 0700) == 0);
207 /* Files present here:
212 ASSERT (func (BASE "dir2", BASE "dir") == 0);
213 /* Files present here:
217 ASSERT (mkdir (BASE "dir2", 0700) == 0);
218 /* Files present here:
223 ASSERT (func (BASE "dir2", BASE "dir/") == 0);
224 /* Files present here:
228 ASSERT (mkdir (BASE "dir2", 0700) == 0);
229 /* Files present here:
234 ASSERT (func (BASE "dir2/", BASE "dir") == 0);
235 /* Files present here:
239 ASSERT (mkdir (BASE "dir2", 0700) == 0);
241 /* Files present here:
246 { /* Empty onto full. */
247 ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
248 /* Files present here:
256 ASSERT (func (BASE "dir2", BASE "dir") == -1);
257 ASSERT (errno == EEXIST || errno == ENOTEMPTY);
261 ASSERT (func (BASE "dir2/", BASE "dir") == -1);
262 ASSERT (errno == EEXIST || errno == ENOTEMPTY);
266 ASSERT (func (BASE "dir2", BASE "dir/") == -1);
267 ASSERT (errno == EEXIST || errno == ENOTEMPTY);
270 { /* Full onto empty. */
271 ASSERT (func (BASE "dir", BASE "dir2") == 0);
272 assert_nonexistent (BASE "dir");
273 ASSERT (stat (BASE "dir2/file", &st) == 0);
274 /* Files present here:
279 ASSERT (mkdir (BASE "dir", 0700) == 0);
280 /* Files present here:
287 ASSERT (func (BASE "dir2/", BASE "dir") == 0);
288 ASSERT (stat (BASE "dir/file", &st) == 0);
290 ASSERT (stat (BASE "dir2", &st) == -1);
291 ASSERT (errno == ENOENT);
293 /* Files present here:
298 ASSERT (mkdir (BASE "dir2", 0700) == 0);
299 /* Files present here:
306 ASSERT (func (BASE "dir", BASE "dir2/") == 0);
307 assert_nonexistent (BASE "dir");
308 ASSERT (stat (BASE "dir2/file", &st) == 0);
310 /* Files present here:
315 ASSERT (unlink (BASE "dir2/file") == 0);
317 /* Files present here:
321 { /* Reject trailing dot. */
324 ASSERT (func (BASE "dir2", BASE "dir/.") == -1);
325 ASSERT (errno == EINVAL || errno == ENOENT);
327 ASSERT (mkdir (BASE "dir", 0700) == 0);
328 /* Files present here:
335 ASSERT (func (BASE "dir2", BASE "dir/.") == -1);
336 ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR
337 || errno == ENOTEMPTY);
341 ASSERT (func (BASE "dir2/.", BASE "dir") == -1);
342 ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST);
344 ASSERT (rmdir (BASE "dir") == 0);
345 /* Files present here:
351 ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
352 ASSERT (errno == EINVAL || errno == ENOENT);
354 ASSERT (mkdir (BASE "dir", 0700) == 0);
355 /* Files present here:
362 ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
363 ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR
364 || errno == ENOTEMPTY);
368 ASSERT (func (BASE "dir2/.//", BASE "dir") == -1);
369 ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST);
371 ASSERT (rmdir (BASE "dir2") == 0);
372 /* Files present here:
377 { /* Move into subdir. */
380 ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
381 ASSERT (errno == EINVAL || errno == EACCES);
385 ASSERT (stat (BASE "dir/sub", &st) == -1);
386 ASSERT (errno == ENOENT);
388 ASSERT (mkdir (BASE "dir/sub", 0700) == 0);
389 /* Files present here:
396 ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
397 ASSERT (errno == EINVAL);
398 ASSERT (stat (BASE "dir/sub", &st) == 0);
400 ASSERT (rmdir (BASE "dir/sub") == 0);
403 /* Files present here:
408 /* Mixing file and directory. */
411 { /* File onto dir. */
414 ASSERT (func (BASE "file", BASE "dir") == -1);
415 ASSERT (errno == EISDIR || errno == ENOTDIR);
419 ASSERT (func (BASE "file", BASE "dir/") == -1);
420 ASSERT (errno == EISDIR || errno == ENOTDIR);
423 { /* Dir onto file. */
426 ASSERT (func (BASE "dir", BASE "file") == -1);
427 ASSERT (errno == ENOTDIR);
431 ASSERT (func (BASE "dir/", BASE "file") == -1);
432 ASSERT (errno == ENOTDIR);
439 { /* File onto self. */
440 ASSERT (func (BASE "file", BASE "file") == 0);
441 memset (&st, 0, sizeof st);
442 ASSERT (stat (BASE "file", &st) == 0);
443 ASSERT (st.st_size == 2);
445 /* Files present here:
449 { /* Empty dir onto self. */
450 ASSERT (func (BASE "dir", BASE "dir") == 0);
451 ASSERT (stat (BASE "dir", &st) == 0);
453 /* Files present here:
457 ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
458 /* Files present here:
463 { /* Full dir onto self. */
464 ASSERT (func (BASE "dir", BASE "dir") == 0);
466 ASSERT (unlink (BASE "dir/file") == 0);
467 /* Files present here:
472 /* Not all file systems support link. Mingw doesn't have
473 reliable st_nlink on hard links, but our implementation does
474 fail with EPERM on poor file systems, and we can detect the
475 inferior stat() via st_ino. Cygwin 1.5.x copies rather than
476 links files on those file systems, but there, st_nlink and
477 st_ino are reliable. */
478 int ret = link (BASE "file", BASE "file2");
481 memset (&st, 0, sizeof st);
482 ASSERT (stat (BASE "file2", &st) == 0);
483 if (st.st_ino && st.st_nlink != 2)
485 ASSERT (unlink (BASE "file2") == 0);
492 /* If the device does not support hard links, errno is
493 EPERM on Linux, EOPNOTSUPP on FreeBSD. */
499 fputs ("skipping test: "
500 "hard links not supported on this file system\n",
502 ASSERT (unlink (BASE "file") == 0);
503 ASSERT (rmdir (BASE "dir") == 0);
512 /* Files present here:
514 {BASE}file2 (hard link to file)
517 { /* File onto hard link. */
518 ASSERT (func (BASE "file", BASE "file2") == 0);
519 memset (&st, 0, sizeof st);
520 ASSERT (stat (BASE "file", &st) == 0);
521 ASSERT (st.st_size == 2);
522 memset (&st, 0, sizeof st);
523 ASSERT (stat (BASE "file2", &st) == 0);
524 ASSERT (st.st_size == 2);
526 /* Files present here:
531 ASSERT (unlink (BASE "file2") == 0);
532 /* Files present here:
539 if (symlink (BASE "file", BASE "link1"))
542 fputs ("skipping test: symlinks not supported on this file system\n",
544 ASSERT (unlink (BASE "file") == 0);
545 ASSERT (rmdir (BASE "dir") == 0);
548 /* Files present here:
550 {BASE}link1 -> {BASE}file
553 { /* Simple rename. */
554 ASSERT (func (BASE "link1", BASE "link2") == 0);
555 ASSERT (stat (BASE "file", &st) == 0);
557 ASSERT (lstat (BASE "link1", &st) == -1);
558 ASSERT (errno == ENOENT);
559 memset (&st, 0, sizeof st);
560 ASSERT (lstat (BASE "link2", &st) == 0);
561 ASSERT (S_ISLNK (st.st_mode));
563 /* Files present here:
565 {BASE}link2 -> {BASE}file
569 ASSERT (symlink (BASE "nowhere", BASE "link1") == 0);
570 /* Files present here:
572 {BASE}link1 -> {BASE}nowhere
573 {BASE}link2 -> {BASE}file
577 ASSERT (func (BASE "link2", BASE "link1") == 0);
578 memset (&st, 0, sizeof st);
579 ASSERT (stat (BASE "link1", &st) == 0);
580 ASSERT (st.st_size == 2);
582 ASSERT (lstat (BASE "link2", &st) == -1);
583 ASSERT (errno == ENOENT);
586 /* Files present here:
588 {BASE}link1 -> {BASE}file
591 { /* Symlink loop. */
592 ASSERT (symlink (BASE "link2", BASE "link2") == 0);
593 /* Files present here:
595 {BASE}link1 -> {BASE}file
596 {BASE}link2 -> {BASE}link2
600 ASSERT (func (BASE "link2", BASE "link2") == 0);
604 ASSERT (func (BASE "link2/", BASE "link2") == -1);
605 ASSERT (errno == ELOOP || errno == ENOTDIR);
607 ASSERT (func (BASE "link2", BASE "link3") == 0);
608 /* Files present here:
610 {BASE}link1 -> {BASE}file
611 {BASE}link3 -> {BASE}link2
614 ASSERT (unlink (BASE "link3") == 0);
616 /* Files present here:
618 {BASE}link1 -> {BASE}file
621 { /* Dangling link. */
622 ASSERT (symlink (BASE "nowhere", BASE "link2") == 0);
623 /* Files present here:
625 {BASE}link1 -> {BASE}file
626 {BASE}link2 -> {BASE}nowhere
630 ASSERT (func (BASE "link2", BASE "link3") == 0);
632 ASSERT (lstat (BASE "link2", &st) == -1);
633 ASSERT (errno == ENOENT);
634 memset (&st, 0, sizeof st);
635 ASSERT (lstat (BASE "link3", &st) == 0);
638 /* Files present here:
640 {BASE}link1 -> {BASE}file
641 {BASE}link3 -> {BASE}nowhere
644 { /* Trailing slash on dangling. */
647 ASSERT (func (BASE "link3/", BASE "link2") == -1);
648 ASSERT (errno == ENOENT || errno == ENOTDIR);
652 ASSERT (func (BASE "link3", BASE "link2/") == -1);
653 ASSERT (errno == ENOENT || errno == ENOTDIR);
657 ASSERT (lstat (BASE "link2", &st) == -1);
658 ASSERT (errno == ENOENT);
660 memset (&st, 0, sizeof st);
661 ASSERT (lstat (BASE "link3", &st) == 0);
663 /* Files present here:
665 {BASE}link1 -> {BASE}file
666 {BASE}link3 -> {BASE}nowhere
669 { /* Trailing slash on link to file. */
672 ASSERT (func (BASE "link1/", BASE "link2") == -1);
673 ASSERT (errno == ENOTDIR);
677 ASSERT (func (BASE "link1", BASE "link3/") == -1);
678 ASSERT (errno == ENOENT || errno == ENOTDIR);
681 /* Files present here:
683 {BASE}link1 -> {BASE}file
684 {BASE}link3 -> {BASE}nowhere
688 /* Mixing symlink and file. */
690 { /* File onto link. */
691 ASSERT (close (creat (BASE "file2", 0600)) == 0);
692 /* Files present here:
695 {BASE}link1 -> {BASE}file
696 {BASE}link3 -> {BASE}nowhere
700 ASSERT (func (BASE "file2", BASE "link3") == 0);
702 ASSERT (stat (BASE "file2", &st) == -1);
703 ASSERT (errno == ENOENT);
704 memset (&st, 0, sizeof st);
705 ASSERT (lstat (BASE "link3", &st) == 0);
706 ASSERT (S_ISREG (st.st_mode));
708 /* Files present here:
710 {BASE}link1 -> {BASE}file
714 ASSERT (unlink (BASE "link3") == 0);
716 /* Files present here:
718 {BASE}link1 -> {BASE}file
721 { /* Link onto file. */
722 ASSERT (symlink (BASE "nowhere", BASE "link2") == 0);
723 /* Files present here:
725 {BASE}link1 -> {BASE}file
726 {BASE}link2 -> {BASE}nowhere
729 ASSERT (close (creat (BASE "file2", 0600)) == 0);
730 /* Files present here:
733 {BASE}link1 -> {BASE}file
734 {BASE}link2 -> {BASE}nowhere
738 ASSERT (func (BASE "link2", BASE "file2") == 0);
740 ASSERT (lstat (BASE "link2", &st) == -1);
741 ASSERT (errno == ENOENT);
742 memset (&st, 0, sizeof st);
743 ASSERT (lstat (BASE "file2", &st) == 0);
744 ASSERT (S_ISLNK (st.st_mode));
746 /* Files present here:
748 {BASE}file2 -> {BASE}nowhere
749 {BASE}link1 -> {BASE}file
752 ASSERT (unlink (BASE "file2") == 0);
754 /* Files present here:
756 {BASE}link1 -> {BASE}file
759 { /* Trailing slash. */
762 ASSERT (func (BASE "file/", BASE "link1") == -1);
763 ASSERT (errno == ENOTDIR);
767 ASSERT (func (BASE "file", BASE "link1/") == -1);
768 ASSERT (errno == ENOTDIR || errno == ENOENT);
772 ASSERT (func (BASE "link1/", BASE "file") == -1);
773 ASSERT (errno == ENOTDIR);
777 ASSERT (func (BASE "link1", BASE "file/") == -1);
778 ASSERT (errno == ENOTDIR || errno == ENOENT);
779 memset (&st, 0, sizeof st);
780 ASSERT (lstat (BASE "file", &st) == 0);
781 ASSERT (S_ISREG (st.st_mode));
782 memset (&st, 0, sizeof st);
783 ASSERT (lstat (BASE "link1", &st) == 0);
784 ASSERT (S_ISLNK (st.st_mode));
787 /* Files present here:
789 {BASE}link1 -> {BASE}file
793 /* Mixing symlink and directory. */
795 { /* Directory onto link. */
798 ASSERT (func (BASE "dir", BASE "link1") == -1);
799 ASSERT (errno == ENOTDIR);
803 ASSERT (func (BASE "dir/", BASE "link1") == -1);
804 ASSERT (errno == ENOTDIR);
808 ASSERT (func (BASE "dir", BASE "link1/") == -1);
809 ASSERT (errno == ENOTDIR);
812 { /* Link onto directory. */
815 ASSERT (func (BASE "link1", BASE "dir") == -1);
816 ASSERT (errno == EISDIR || errno == ENOTDIR);
820 ASSERT (func (BASE "link1", BASE "dir/") == -1);
821 ASSERT (errno == EISDIR || errno == ENOTDIR);
825 ASSERT (func (BASE "link1/", BASE "dir") == -1);
826 ASSERT (errno == ENOTDIR);
827 memset (&st, 0, sizeof st);
828 ASSERT (lstat (BASE "link1", &st) == 0);
829 ASSERT (S_ISLNK (st.st_mode));
830 memset (&st, 0, sizeof st);
831 ASSERT (lstat (BASE "dir", &st) == 0);
832 ASSERT (S_ISDIR (st.st_mode));
835 /* Files present here:
837 {BASE}link1 -> {BASE}file
841 /* POSIX requires rename("link-to-dir/","other") to rename "dir" and
842 leave "link-to-dir" dangling, but GNU rejects this. POSIX
843 requires rename("dir","dangling/") to create the directory so
844 that "dangling/" now resolves, but GNU rejects this. While we
845 prefer GNU behavior, we don't enforce it. However, we do test
846 that the system either follows POSIX in both cases, or follows
850 ASSERT (symlink (BASE "dir2", BASE "link2") == 0);
851 /* Files present here:
853 {BASE}link1 -> {BASE}file
854 {BASE}link2 -> {BASE}dir2
858 result = func (BASE "dir", BASE "link2/");
863 ASSERT (lstat (BASE "dir", &st) == -1);
864 ASSERT (errno == ENOENT);
865 memset (&st, 0, sizeof st);
866 ASSERT (lstat (BASE "dir2", &st) == 0);
867 ASSERT (S_ISDIR (st.st_mode));
868 memset (&st, 0, sizeof st);
869 ASSERT (lstat (BASE "link2", &st) == 0);
870 ASSERT (S_ISLNK (st.st_mode));
871 /* Files present here:
873 {BASE}link1 -> {BASE}file
874 {BASE}link2 -> {BASE}dir2
878 ASSERT (func (BASE "link2/", BASE "dir") == 0);
879 memset (&st, 0, sizeof st);
880 ASSERT (lstat (BASE "dir", &st) == 0);
881 ASSERT (S_ISDIR (st.st_mode));
883 ASSERT (lstat (BASE "dir2", &st) == -1);
884 ASSERT (errno == ENOENT);
885 memset (&st, 0, sizeof st);
886 ASSERT (lstat (BASE "link2", &st) == 0);
887 ASSERT (S_ISLNK (st.st_mode));
893 ASSERT (result == -1);
894 ASSERT (errno == ENOTDIR);
895 memset (&st, 0, sizeof st);
896 ASSERT (lstat (BASE "dir", &st) == 0);
897 ASSERT (S_ISDIR (st.st_mode));
899 ASSERT (lstat (BASE "dir2", &st) == -1);
900 ASSERT (errno == ENOENT);
901 memset (&st, 0, sizeof st);
902 ASSERT (lstat (BASE "link2", &st) == 0);
903 ASSERT (S_ISLNK (st.st_mode));
904 ASSERT (unlink (BASE "link2") == 0);
905 ASSERT (symlink (BASE "dir", BASE "link2") == 0);
906 /* Files present here:
908 {BASE}link1 -> {BASE}file
909 {BASE}link2 -> {BASE}dir
912 errno = 0; /* OpenBSD notices that link2/ and dir are the same. */
913 result = func (BASE "link2/", BASE "dir");
914 if (result) /* GNU/Linux rejects attempts to use link2/. */
916 ASSERT (result == -1);
917 ASSERT (errno == ENOTDIR || errno == EISDIR);
919 memset (&st, 0, sizeof st);
920 ASSERT (lstat (BASE "dir", &st) == 0);
921 ASSERT (S_ISDIR (st.st_mode));
923 ASSERT (lstat (BASE "dir2", &st) == -1);
924 ASSERT (errno == ENOENT);
925 memset (&st, 0, sizeof st);
926 ASSERT (lstat (BASE "link2", &st) == 0);
927 ASSERT (S_ISLNK (st.st_mode));
930 /* Files present here:
932 {BASE}link1 -> {BASE}file
933 {BASE}link2 -> {BASE}dir or {BASE}dir2
938 ASSERT (unlink (BASE "file") == 0);
939 ASSERT (rmdir (BASE "dir") == 0);
940 ASSERT (unlink (BASE "link1") == 0);
941 ASSERT (unlink (BASE "link2") == 0);