010d58d76c3ac8ab8a6b24b559b79556934c0d19
[gnulib/ericb.git] / tests / test-rename.h
blob010d58d76c3ac8ab8a6b24b559b79556934c0d19
1 /* Test of rename() function.
2 Copyright (C) 2009-2017 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. */
25 static bool
26 dentry_exists (const char *filename)
28 bool exists = false;
29 DIR *dir = opendir (".");
31 ASSERT (dir != NULL);
32 for (;;)
34 struct dirent *d = readdir (dir);
35 if (d == NULL)
36 break;
37 if (strcmp (d->d_name, filename) == 0)
39 exists = true;
40 break;
43 ASSERT (closedir (dir) == 0);
44 return exists;
47 /* Asserts that a specific file, given by a file name without slashes, does
48 not exist in the current directory. */
49 static void
50 assert_nonexistent (const char *filename)
52 struct stat st;
54 /* The usual way to test the presence of a file is via stat() or lstat(). */
55 errno = 0;
56 if (stat (filename, &st) == -1)
57 ASSERT (errno == ENOENT);
58 else
60 /* But after renaming a directory over an empty directory on an NFS-
61 mounted file system, on Linux 2.6.18, for a period of 30 seconds the
62 old directory name is "present" according to stat() but "nonexistent"
63 according to dentry_exists(). */
64 ASSERT (!dentry_exists (filename));
65 /* Remove the old directory name, so that subsequent mkdir calls
66 succeed. */
67 (void) rmdir (filename);
71 static int
72 test_rename (int (*func) (char const *, char const *), bool print)
74 /* Setup. */
75 struct stat st;
76 int fd = creat (BASE "file", 0600);
77 ASSERT (0 <= fd);
78 ASSERT (write (fd, "hi", 2) == 2);
79 ASSERT (close (fd) == 0);
80 ASSERT (mkdir (BASE "dir", 0700) == 0);
82 /* Files present here:
83 {BASE}file
84 {BASE}dir/
87 /* Obvious errors. */
89 { /* Missing source. */
91 errno = 0;
92 ASSERT (func (BASE "missing", BASE "missing") == -1);
93 ASSERT (errno == ENOENT);
96 errno = 0;
97 ASSERT (func (BASE "missing/", BASE "missing") == -1);
98 ASSERT (errno == ENOENT);
101 errno = 0;
102 ASSERT (func (BASE "missing", BASE "missing/") == -1);
103 ASSERT (errno == ENOENT);
106 { /* Empty operand. */
108 errno = 0;
109 ASSERT (func ("", BASE "missing") == -1);
110 ASSERT (errno == ENOENT);
113 errno = 0;
114 ASSERT (func (BASE "file", "") == -1);
115 ASSERT (errno == ENOENT);
118 errno = 0;
119 ASSERT (func (BASE "", "") == -1);
120 ASSERT (errno == ENOENT);
124 /* Files. */
126 { /* Trailing slash. */
128 errno = 0;
129 ASSERT (func (BASE "file", BASE "file2/") == -1);
130 ASSERT (errno == ENOENT || errno == ENOTDIR);
133 errno = 0;
134 ASSERT (func (BASE "file/", BASE "file2") == -1);
135 ASSERT (errno == ENOTDIR);
138 errno = 0;
139 ASSERT (stat (BASE "file2", &st) == -1);
140 ASSERT (errno == ENOENT);
143 { /* Simple rename. */
144 ASSERT (func (BASE "file", BASE "file2") == 0);
145 errno = 0;
146 ASSERT (stat (BASE "file", &st) == -1);
147 ASSERT (errno == ENOENT);
148 memset (&st, 0, sizeof st);
149 ASSERT (stat (BASE "file2", &st) == 0);
150 ASSERT (st.st_size == 2);
152 /* Files present here:
153 {BASE}file2
154 {BASE}dir/
156 { /* Overwrite. */
157 ASSERT (close (creat (BASE "file", 0600)) == 0);
158 errno = 0;
159 ASSERT (func (BASE "file2", BASE "file/") == -1);
160 ASSERT (errno == ENOTDIR);
161 ASSERT (func (BASE "file2", BASE "file") == 0);
162 memset (&st, 0, sizeof st);
163 ASSERT (stat (BASE "file", &st) == 0);
164 ASSERT (st.st_size == 2);
165 errno = 0;
166 ASSERT (stat (BASE "file2", &st) == -1);
167 ASSERT (errno == ENOENT);
169 /* Files present here:
170 {BASE}file
171 {BASE}dir/
174 /* Directories. */
176 { /* Simple rename. */
178 ASSERT (func (BASE "dir", BASE "dir2/") == 0);
179 errno = 0;
180 ASSERT (stat (BASE "dir", &st) == -1);
181 ASSERT (errno == ENOENT);
182 ASSERT (stat (BASE "dir2", &st) == 0);
184 /* Files present here:
185 {BASE}file
186 {BASE}dir2/
189 ASSERT (func (BASE "dir2/", BASE "dir") == 0);
190 ASSERT (stat (BASE "dir", &st) == 0);
191 errno = 0;
192 ASSERT (stat (BASE "dir2", &st) == -1);
193 ASSERT (errno == ENOENT);
195 /* Files present here:
196 {BASE}file
197 {BASE}dir/
200 ASSERT (func (BASE "dir", BASE "dir2") == 0);
201 errno = 0;
202 ASSERT (stat (BASE "dir", &st) == -1);
203 ASSERT (errno == ENOENT);
204 ASSERT (stat (BASE "dir2", &st) == 0);
206 /* Files present here:
207 {BASE}file
208 {BASE}dir2/
210 { /* Empty onto empty. */
211 ASSERT (mkdir (BASE "dir", 0700) == 0);
212 /* Files present here:
213 {BASE}file
214 {BASE}dir/
215 {BASE}dir2/
217 ASSERT (func (BASE "dir2", BASE "dir") == 0);
218 /* Files present here:
219 {BASE}file
220 {BASE}dir/
222 ASSERT (mkdir (BASE "dir2", 0700) == 0);
223 /* Files present here:
224 {BASE}file
225 {BASE}dir/
226 {BASE}dir2/
228 ASSERT (func (BASE "dir2", BASE "dir/") == 0);
229 /* Files present here:
230 {BASE}file
231 {BASE}dir/
233 ASSERT (mkdir (BASE "dir2", 0700) == 0);
234 /* Files present here:
235 {BASE}file
236 {BASE}dir/
237 {BASE}dir2/
239 ASSERT (func (BASE "dir2/", BASE "dir") == 0);
240 /* Files present here:
241 {BASE}file
242 {BASE}dir/
244 ASSERT (mkdir (BASE "dir2", 0700) == 0);
246 /* Files present here:
247 {BASE}file
248 {BASE}dir/
249 {BASE}dir2/
251 { /* Empty onto full. */
252 ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
253 /* Files present here:
254 {BASE}file
255 {BASE}dir/
256 {BASE}dir/file
257 {BASE}dir2/
260 errno = 0;
261 ASSERT (func (BASE "dir2", BASE "dir") == -1);
262 ASSERT (errno == EEXIST || errno == ENOTEMPTY);
265 errno = 0;
266 ASSERT (func (BASE "dir2/", BASE "dir") == -1);
267 ASSERT (errno == EEXIST || errno == ENOTEMPTY);
270 errno = 0;
271 ASSERT (func (BASE "dir2", BASE "dir/") == -1);
272 ASSERT (errno == EEXIST || errno == ENOTEMPTY);
275 { /* Full onto empty. */
276 ASSERT (func (BASE "dir", BASE "dir2") == 0);
277 assert_nonexistent (BASE "dir");
278 ASSERT (stat (BASE "dir2/file", &st) == 0);
279 /* Files present here:
280 {BASE}file
281 {BASE}dir2/
282 {BASE}dir2/file
284 ASSERT (mkdir (BASE "dir", 0700) == 0);
285 /* Files present here:
286 {BASE}file
287 {BASE}dir/
288 {BASE}dir2/
289 {BASE}dir2/file
292 ASSERT (func (BASE "dir2/", BASE "dir") == 0);
293 ASSERT (stat (BASE "dir/file", &st) == 0);
294 errno = 0;
295 ASSERT (stat (BASE "dir2", &st) == -1);
296 ASSERT (errno == ENOENT);
298 /* Files present here:
299 {BASE}file
300 {BASE}dir/
301 {BASE}dir/file
303 ASSERT (mkdir (BASE "dir2", 0700) == 0);
304 /* Files present here:
305 {BASE}file
306 {BASE}dir/
307 {BASE}dir/file
308 {BASE}dir2/
311 ASSERT (func (BASE "dir", BASE "dir2/") == 0);
312 assert_nonexistent (BASE "dir");
313 ASSERT (stat (BASE "dir2/file", &st) == 0);
315 /* Files present here:
316 {BASE}file
317 {BASE}dir2/
318 {BASE}dir2/file
320 ASSERT (unlink (BASE "dir2/file") == 0);
322 /* Files present here:
323 {BASE}file
324 {BASE}dir2/
326 { /* Reject trailing dot. */
328 errno = 0;
329 ASSERT (func (BASE "dir2", BASE "dir/.") == -1);
330 ASSERT (errno == EINVAL || errno == ENOENT);
332 ASSERT (mkdir (BASE "dir", 0700) == 0);
333 /* Files present here:
334 {BASE}file
335 {BASE}dir/
336 {BASE}dir2/
339 errno = 0;
340 ASSERT (func (BASE "dir2", BASE "dir/.") == -1);
341 ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR
342 || errno == ENOTEMPTY || errno == EEXIST);
345 errno = 0;
346 ASSERT (func (BASE "dir2/.", BASE "dir") == -1);
347 ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST);
349 ASSERT (rmdir (BASE "dir") == 0);
350 /* Files present here:
351 {BASE}file
352 {BASE}dir2/
355 errno = 0;
356 ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
357 ASSERT (errno == EINVAL || errno == ENOENT);
359 ASSERT (mkdir (BASE "dir", 0700) == 0);
360 /* Files present here:
361 {BASE}file
362 {BASE}dir/
363 {BASE}dir2/
366 errno = 0;
367 ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
368 ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR
369 || errno == ENOTEMPTY || errno == EEXIST);
372 errno = 0;
373 ASSERT (func (BASE "dir2/.//", BASE "dir") == -1);
374 ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST);
376 ASSERT (rmdir (BASE "dir2") == 0);
377 /* Files present here:
378 {BASE}file
379 {BASE}dir/
382 { /* Move into subdir. */
384 errno = 0;
385 ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
386 ASSERT (errno == EINVAL || errno == EACCES);
389 errno = 0;
390 ASSERT (stat (BASE "dir/sub", &st) == -1);
391 ASSERT (errno == ENOENT);
393 ASSERT (mkdir (BASE "dir/sub", 0700) == 0);
394 /* Files present here:
395 {BASE}file
396 {BASE}dir/
397 {BASE}dir/sub/
400 errno = 0;
401 ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
402 ASSERT (errno == EINVAL);
403 ASSERT (stat (BASE "dir/sub", &st) == 0);
405 ASSERT (rmdir (BASE "dir/sub") == 0);
408 /* Files present here:
409 {BASE}file
410 {BASE}dir/
413 /* Mixing file and directory. */
416 { /* File onto dir. */
418 errno = 0;
419 ASSERT (func (BASE "file", BASE "dir") == -1);
420 ASSERT (errno == EISDIR || errno == ENOTDIR);
423 errno = 0;
424 ASSERT (func (BASE "file", BASE "dir/") == -1);
425 ASSERT (errno == EISDIR || errno == ENOTDIR);
428 { /* Dir onto file. */
430 errno = 0;
431 ASSERT (func (BASE "dir", BASE "file") == -1);
432 ASSERT (errno == ENOTDIR);
435 errno = 0;
436 ASSERT (func (BASE "dir/", BASE "file") == -1);
437 ASSERT (errno == ENOTDIR);
442 /* Hard links. */
444 { /* File onto self. */
445 ASSERT (func (BASE "file", BASE "file") == 0);
446 memset (&st, 0, sizeof st);
447 ASSERT (stat (BASE "file", &st) == 0);
448 ASSERT (st.st_size == 2);
450 /* Files present here:
451 {BASE}file
452 {BASE}dir/
454 { /* Empty dir onto self. */
455 ASSERT (func (BASE "dir", BASE "dir") == 0);
456 ASSERT (stat (BASE "dir", &st) == 0);
458 /* Files present here:
459 {BASE}file
460 {BASE}dir/
462 ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
463 /* Files present here:
464 {BASE}file
465 {BASE}dir/
466 {BASE}dir/file
468 { /* Full dir onto self. */
469 ASSERT (func (BASE "dir", BASE "dir") == 0);
471 ASSERT (unlink (BASE "dir/file") == 0);
472 /* Files present here:
473 {BASE}file
474 {BASE}dir/
477 /* Not all file systems support link. Mingw doesn't have
478 reliable st_nlink on hard links, but our implementation does
479 fail with EPERM on poor file systems, and we can detect the
480 inferior stat() via st_ino. Cygwin 1.5.x copies rather than
481 links files on those file systems, but there, st_nlink and
482 st_ino are reliable. */
483 int ret = link (BASE "file", BASE "file2");
484 if (!ret)
486 memset (&st, 0, sizeof st);
487 ASSERT (stat (BASE "file2", &st) == 0);
488 if (st.st_ino && st.st_nlink != 2)
490 ASSERT (unlink (BASE "file2") == 0);
491 errno = EPERM;
492 ret = -1;
495 if (ret == -1)
497 /* If the device does not support hard links, errno is
498 EPERM on Linux, EOPNOTSUPP on FreeBSD. */
499 switch (errno)
501 case EPERM:
502 case EOPNOTSUPP:
503 if (print)
504 fputs ("skipping test: "
505 "hard links not supported on this file system\n",
506 stderr);
507 ASSERT (unlink (BASE "file") == 0);
508 ASSERT (rmdir (BASE "dir") == 0);
509 return 77;
510 default:
511 perror ("link");
512 return 1;
515 ASSERT (ret == 0);
517 /* Files present here:
518 {BASE}file
519 {BASE}file2 (hard link to file)
520 {BASE}dir/
522 { /* File onto hard link. */
523 ASSERT (func (BASE "file", BASE "file2") == 0);
524 memset (&st, 0, sizeof st);
525 if (stat (BASE "file", &st) != 0)
527 /* This can happen on NetBSD. */
528 ASSERT (errno == ENOENT);
529 ASSERT (link (BASE "file2", BASE "file") == 0);
530 ASSERT (stat (BASE "file", &st) == 0);
532 ASSERT (st.st_size == 2);
533 memset (&st, 0, sizeof st);
534 ASSERT (stat (BASE "file2", &st) == 0);
535 ASSERT (st.st_size == 2);
537 /* Files present here:
538 {BASE}file
539 {BASE}file2
540 {BASE}dir/
542 ASSERT (unlink (BASE "file2") == 0);
543 /* Files present here:
544 {BASE}file
545 {BASE}dir/
548 /* Symlinks. */
550 if (symlink (BASE "file", BASE "link1"))
552 if (print)
553 fputs ("skipping test: symlinks not supported on this file system\n",
554 stderr);
555 ASSERT (unlink (BASE "file") == 0);
556 ASSERT (rmdir (BASE "dir") == 0);
557 return 77;
559 /* Files present here:
560 {BASE}file
561 {BASE}link1 -> {BASE}file
562 {BASE}dir/
564 { /* Simple rename. */
565 ASSERT (func (BASE "link1", BASE "link2") == 0);
566 ASSERT (stat (BASE "file", &st) == 0);
567 errno = 0;
568 ASSERT (lstat (BASE "link1", &st) == -1);
569 ASSERT (errno == ENOENT);
570 memset (&st, 0, sizeof st);
571 ASSERT (lstat (BASE "link2", &st) == 0);
572 ASSERT (S_ISLNK (st.st_mode));
574 /* Files present here:
575 {BASE}file
576 {BASE}link2 -> {BASE}file
577 {BASE}dir/
579 { /* Overwrite. */
580 ASSERT (symlink (BASE "nowhere", BASE "link1") == 0);
581 /* Files present here:
582 {BASE}file
583 {BASE}link1 -> {BASE}nowhere
584 {BASE}link2 -> {BASE}file
585 {BASE}dir/
588 ASSERT (func (BASE "link2", BASE "link1") == 0);
589 memset (&st, 0, sizeof st);
590 ASSERT (stat (BASE "link1", &st) == 0);
591 ASSERT (st.st_size == 2);
592 errno = 0;
593 ASSERT (lstat (BASE "link2", &st) == -1);
594 ASSERT (errno == ENOENT);
597 /* Files present here:
598 {BASE}file
599 {BASE}link1 -> {BASE}file
600 {BASE}dir/
602 { /* Symlink loop. */
603 ASSERT (symlink (BASE "link2", BASE "link2") == 0);
604 /* Files present here:
605 {BASE}file
606 {BASE}link1 -> {BASE}file
607 {BASE}link2 -> {BASE}link2
608 {BASE}dir/
611 ASSERT (func (BASE "link2", BASE "link2") == 0);
614 errno = 0;
615 ASSERT (func (BASE "link2/", BASE "link2") == -1);
616 ASSERT (errno == ELOOP || errno == ENOTDIR);
618 ASSERT (func (BASE "link2", BASE "link3") == 0);
619 /* Files present here:
620 {BASE}file
621 {BASE}link1 -> {BASE}file
622 {BASE}link3 -> {BASE}link2
623 {BASE}dir/
625 ASSERT (unlink (BASE "link3") == 0);
627 /* Files present here:
628 {BASE}file
629 {BASE}link1 -> {BASE}file
630 {BASE}dir/
632 { /* Dangling link. */
633 ASSERT (symlink (BASE "nowhere", BASE "link2") == 0);
634 /* Files present here:
635 {BASE}file
636 {BASE}link1 -> {BASE}file
637 {BASE}link2 -> {BASE}nowhere
638 {BASE}dir/
641 ASSERT (func (BASE "link2", BASE "link3") == 0);
642 errno = 0;
643 ASSERT (lstat (BASE "link2", &st) == -1);
644 ASSERT (errno == ENOENT);
645 memset (&st, 0, sizeof st);
646 ASSERT (lstat (BASE "link3", &st) == 0);
649 /* Files present here:
650 {BASE}file
651 {BASE}link1 -> {BASE}file
652 {BASE}link3 -> {BASE}nowhere
653 {BASE}dir/
655 { /* Trailing slash on dangling. */
657 errno = 0;
658 ASSERT (func (BASE "link3/", BASE "link2") == -1);
659 ASSERT (errno == ENOENT || errno == ENOTDIR);
662 errno = 0;
663 ASSERT (func (BASE "link3", BASE "link2/") == -1);
664 ASSERT (errno == ENOENT || errno == ENOTDIR);
667 errno = 0;
668 ASSERT (lstat (BASE "link2", &st) == -1);
669 ASSERT (errno == ENOENT);
671 memset (&st, 0, sizeof st);
672 ASSERT (lstat (BASE "link3", &st) == 0);
674 /* Files present here:
675 {BASE}file
676 {BASE}link1 -> {BASE}file
677 {BASE}link3 -> {BASE}nowhere
678 {BASE}dir/
680 { /* Trailing slash on link to file. */
682 errno = 0;
683 ASSERT (func (BASE "link1/", BASE "link2") == -1);
684 ASSERT (errno == ENOTDIR);
687 errno = 0;
688 ASSERT (func (BASE "link1", BASE "link3/") == -1);
689 ASSERT (errno == ENOENT || errno == ENOTDIR);
692 /* Files present here:
693 {BASE}file
694 {BASE}link1 -> {BASE}file
695 {BASE}link3 -> {BASE}nowhere
696 {BASE}dir/
699 /* Mixing symlink and file. */
701 { /* File onto link. */
702 ASSERT (close (creat (BASE "file2", 0600)) == 0);
703 /* Files present here:
704 {BASE}file
705 {BASE}file2
706 {BASE}link1 -> {BASE}file
707 {BASE}link3 -> {BASE}nowhere
708 {BASE}dir/
711 ASSERT (func (BASE "file2", BASE "link3") == 0);
712 errno = 0;
713 ASSERT (stat (BASE "file2", &st) == -1);
714 ASSERT (errno == ENOENT);
715 memset (&st, 0, sizeof st);
716 ASSERT (lstat (BASE "link3", &st) == 0);
717 ASSERT (S_ISREG (st.st_mode));
719 /* Files present here:
720 {BASE}file
721 {BASE}link1 -> {BASE}file
722 {BASE}link3
723 {BASE}dir/
725 ASSERT (unlink (BASE "link3") == 0);
727 /* Files present here:
728 {BASE}file
729 {BASE}link1 -> {BASE}file
730 {BASE}dir/
732 { /* Link onto file. */
733 ASSERT (symlink (BASE "nowhere", BASE "link2") == 0);
734 /* Files present here:
735 {BASE}file
736 {BASE}link1 -> {BASE}file
737 {BASE}link2 -> {BASE}nowhere
738 {BASE}dir/
740 ASSERT (close (creat (BASE "file2", 0600)) == 0);
741 /* Files present here:
742 {BASE}file
743 {BASE}file2
744 {BASE}link1 -> {BASE}file
745 {BASE}link2 -> {BASE}nowhere
746 {BASE}dir/
749 ASSERT (func (BASE "link2", BASE "file2") == 0);
750 errno = 0;
751 ASSERT (lstat (BASE "link2", &st) == -1);
752 ASSERT (errno == ENOENT);
753 memset (&st, 0, sizeof st);
754 ASSERT (lstat (BASE "file2", &st) == 0);
755 ASSERT (S_ISLNK (st.st_mode));
757 /* Files present here:
758 {BASE}file
759 {BASE}file2 -> {BASE}nowhere
760 {BASE}link1 -> {BASE}file
761 {BASE}dir/
763 ASSERT (unlink (BASE "file2") == 0);
765 /* Files present here:
766 {BASE}file
767 {BASE}link1 -> {BASE}file
768 {BASE}dir/
770 { /* Trailing slash. */
772 errno = 0;
773 ASSERT (func (BASE "file/", BASE "link1") == -1);
774 ASSERT (errno == ENOTDIR);
777 errno = 0;
778 ASSERT (func (BASE "file", BASE "link1/") == -1);
779 ASSERT (errno == ENOTDIR || errno == ENOENT);
782 errno = 0;
783 ASSERT (func (BASE "link1/", BASE "file") == -1);
784 ASSERT (errno == ENOTDIR);
787 errno = 0;
788 ASSERT (func (BASE "link1", BASE "file/") == -1);
789 ASSERT (errno == ENOTDIR || errno == ENOENT);
790 memset (&st, 0, sizeof st);
791 ASSERT (lstat (BASE "file", &st) == 0);
792 ASSERT (S_ISREG (st.st_mode));
793 memset (&st, 0, sizeof st);
794 ASSERT (lstat (BASE "link1", &st) == 0);
795 ASSERT (S_ISLNK (st.st_mode));
798 /* Files present here:
799 {BASE}file
800 {BASE}link1 -> {BASE}file
801 {BASE}dir/
804 /* Mixing symlink and directory. */
806 { /* Directory onto link. */
808 errno = 0;
809 ASSERT (func (BASE "dir", BASE "link1") == -1);
810 ASSERT (errno == ENOTDIR);
813 errno = 0;
814 ASSERT (func (BASE "dir/", BASE "link1") == -1);
815 ASSERT (errno == ENOTDIR);
818 errno = 0;
819 ASSERT (func (BASE "dir", BASE "link1/") == -1);
820 ASSERT (errno == ENOTDIR);
823 { /* Link onto directory. */
825 errno = 0;
826 ASSERT (func (BASE "link1", BASE "dir") == -1);
827 ASSERT (errno == EISDIR || errno == ENOTDIR);
830 errno = 0;
831 ASSERT (func (BASE "link1", BASE "dir/") == -1);
832 ASSERT (errno == EISDIR || errno == ENOTDIR);
835 errno = 0;
836 ASSERT (func (BASE "link1/", BASE "dir") == -1);
837 ASSERT (errno == ENOTDIR);
838 memset (&st, 0, sizeof st);
839 ASSERT (lstat (BASE "link1", &st) == 0);
840 ASSERT (S_ISLNK (st.st_mode));
841 memset (&st, 0, sizeof st);
842 ASSERT (lstat (BASE "dir", &st) == 0);
843 ASSERT (S_ISDIR (st.st_mode));
846 /* Files present here:
847 {BASE}file
848 {BASE}link1 -> {BASE}file
849 {BASE}dir/
852 /* POSIX requires rename("link-to-dir/","other") to rename "dir" and
853 leave "link-to-dir" dangling, but GNU rejects this. POSIX
854 requires rename("dir","dangling/") to create the directory so
855 that "dangling/" now resolves, but GNU rejects this. While we
856 prefer GNU behavior, we don't enforce it. However, we do test
857 that the system either follows POSIX in both cases, or follows
858 GNU. */
860 int result;
861 ASSERT (symlink (BASE "dir2", BASE "link2") == 0);
862 /* Files present here:
863 {BASE}file
864 {BASE}link1 -> {BASE}file
865 {BASE}link2 -> {BASE}dir2
866 {BASE}dir/
868 errno = 0;
869 result = func (BASE "dir", BASE "link2/");
870 if (result == 0)
872 /* POSIX. */
873 errno = 0;
874 ASSERT (lstat (BASE "dir", &st) == -1);
875 ASSERT (errno == ENOENT);
876 memset (&st, 0, sizeof st);
877 ASSERT (lstat (BASE "dir2", &st) == 0);
878 ASSERT (S_ISDIR (st.st_mode));
879 memset (&st, 0, sizeof st);
880 ASSERT (lstat (BASE "link2", &st) == 0);
881 ASSERT (S_ISLNK (st.st_mode));
882 /* Files present here:
883 {BASE}file
884 {BASE}link1 -> {BASE}file
885 {BASE}link2 -> {BASE}dir2
886 {BASE}dir2/
889 ASSERT (func (BASE "link2/", BASE "dir") == 0);
890 memset (&st, 0, sizeof st);
891 ASSERT (lstat (BASE "dir", &st) == 0);
892 ASSERT (S_ISDIR (st.st_mode));
893 errno = 0;
894 ASSERT (lstat (BASE "dir2", &st) == -1);
895 ASSERT (errno == ENOENT);
896 memset (&st, 0, sizeof st);
897 ASSERT (lstat (BASE "link2", &st) == 0);
898 ASSERT (S_ISLNK (st.st_mode));
901 else
903 /* GNU. */
904 ASSERT (result == -1);
905 ASSERT (errno == ENOTDIR);
906 memset (&st, 0, sizeof st);
907 ASSERT (lstat (BASE "dir", &st) == 0);
908 ASSERT (S_ISDIR (st.st_mode));
909 errno = 0;
910 ASSERT (lstat (BASE "dir2", &st) == -1);
911 ASSERT (errno == ENOENT);
912 memset (&st, 0, sizeof st);
913 ASSERT (lstat (BASE "link2", &st) == 0);
914 ASSERT (S_ISLNK (st.st_mode));
915 ASSERT (unlink (BASE "link2") == 0);
916 ASSERT (symlink (BASE "dir", BASE "link2") == 0);
917 /* Files present here:
918 {BASE}file
919 {BASE}link1 -> {BASE}file
920 {BASE}link2 -> {BASE}dir
921 {BASE}dir/
923 errno = 0; /* OpenBSD notices that link2/ and dir are the same. */
924 result = func (BASE "link2/", BASE "dir");
925 if (result) /* GNU/Linux rejects attempts to use link2/. */
927 ASSERT (result == -1);
928 ASSERT (errno == ENOTDIR || errno == EISDIR);
930 memset (&st, 0, sizeof st);
931 ASSERT (lstat (BASE "dir", &st) == 0);
932 ASSERT (S_ISDIR (st.st_mode));
933 errno = 0;
934 ASSERT (lstat (BASE "dir2", &st) == -1);
935 ASSERT (errno == ENOENT);
936 memset (&st, 0, sizeof st);
937 ASSERT (lstat (BASE "link2", &st) == 0);
938 ASSERT (S_ISLNK (st.st_mode));
941 /* Files present here:
942 {BASE}file
943 {BASE}link1 -> {BASE}file
944 {BASE}link2 -> {BASE}dir or {BASE}dir2
945 {BASE}dir/
948 /* Clean up. */
949 ASSERT (unlink (BASE "file") == 0);
950 ASSERT (rmdir (BASE "dir") == 0);
951 ASSERT (unlink (BASE "link1") == 0);
952 ASSERT (unlink (BASE "link2") == 0);
954 return 0;