windows-stat-override: New module.
[gnulib/ericb.git] / tests / test-rename.h
blob93a1041db1023d1e4a23c16583141c1397204cfe
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 ASSERT (stat (BASE "file", &st) == 0);
526 ASSERT (st.st_size == 2);
527 memset (&st, 0, sizeof st);
528 ASSERT (stat (BASE "file2", &st) == 0);
529 ASSERT (st.st_size == 2);
531 /* Files present here:
532 {BASE}file
533 {BASE}file2
534 {BASE}dir/
536 ASSERT (unlink (BASE "file2") == 0);
537 /* Files present here:
538 {BASE}file
539 {BASE}dir/
542 /* Symlinks. */
544 if (symlink (BASE "file", BASE "link1"))
546 if (print)
547 fputs ("skipping test: symlinks not supported on this file system\n",
548 stderr);
549 ASSERT (unlink (BASE "file") == 0);
550 ASSERT (rmdir (BASE "dir") == 0);
551 return 77;
553 /* Files present here:
554 {BASE}file
555 {BASE}link1 -> {BASE}file
556 {BASE}dir/
558 { /* Simple rename. */
559 ASSERT (func (BASE "link1", BASE "link2") == 0);
560 ASSERT (stat (BASE "file", &st) == 0);
561 errno = 0;
562 ASSERT (lstat (BASE "link1", &st) == -1);
563 ASSERT (errno == ENOENT);
564 memset (&st, 0, sizeof st);
565 ASSERT (lstat (BASE "link2", &st) == 0);
566 ASSERT (S_ISLNK (st.st_mode));
568 /* Files present here:
569 {BASE}file
570 {BASE}link2 -> {BASE}file
571 {BASE}dir/
573 { /* Overwrite. */
574 ASSERT (symlink (BASE "nowhere", BASE "link1") == 0);
575 /* Files present here:
576 {BASE}file
577 {BASE}link1 -> {BASE}nowhere
578 {BASE}link2 -> {BASE}file
579 {BASE}dir/
582 ASSERT (func (BASE "link2", BASE "link1") == 0);
583 memset (&st, 0, sizeof st);
584 ASSERT (stat (BASE "link1", &st) == 0);
585 ASSERT (st.st_size == 2);
586 errno = 0;
587 ASSERT (lstat (BASE "link2", &st) == -1);
588 ASSERT (errno == ENOENT);
591 /* Files present here:
592 {BASE}file
593 {BASE}link1 -> {BASE}file
594 {BASE}dir/
596 { /* Symlink loop. */
597 ASSERT (symlink (BASE "link2", BASE "link2") == 0);
598 /* Files present here:
599 {BASE}file
600 {BASE}link1 -> {BASE}file
601 {BASE}link2 -> {BASE}link2
602 {BASE}dir/
605 ASSERT (func (BASE "link2", BASE "link2") == 0);
608 errno = 0;
609 ASSERT (func (BASE "link2/", BASE "link2") == -1);
610 ASSERT (errno == ELOOP || errno == ENOTDIR);
612 ASSERT (func (BASE "link2", BASE "link3") == 0);
613 /* Files present here:
614 {BASE}file
615 {BASE}link1 -> {BASE}file
616 {BASE}link3 -> {BASE}link2
617 {BASE}dir/
619 ASSERT (unlink (BASE "link3") == 0);
621 /* Files present here:
622 {BASE}file
623 {BASE}link1 -> {BASE}file
624 {BASE}dir/
626 { /* Dangling link. */
627 ASSERT (symlink (BASE "nowhere", BASE "link2") == 0);
628 /* Files present here:
629 {BASE}file
630 {BASE}link1 -> {BASE}file
631 {BASE}link2 -> {BASE}nowhere
632 {BASE}dir/
635 ASSERT (func (BASE "link2", BASE "link3") == 0);
636 errno = 0;
637 ASSERT (lstat (BASE "link2", &st) == -1);
638 ASSERT (errno == ENOENT);
639 memset (&st, 0, sizeof st);
640 ASSERT (lstat (BASE "link3", &st) == 0);
643 /* Files present here:
644 {BASE}file
645 {BASE}link1 -> {BASE}file
646 {BASE}link3 -> {BASE}nowhere
647 {BASE}dir/
649 { /* Trailing slash on dangling. */
651 errno = 0;
652 ASSERT (func (BASE "link3/", BASE "link2") == -1);
653 ASSERT (errno == ENOENT || errno == ENOTDIR);
656 errno = 0;
657 ASSERT (func (BASE "link3", BASE "link2/") == -1);
658 ASSERT (errno == ENOENT || errno == ENOTDIR);
661 errno = 0;
662 ASSERT (lstat (BASE "link2", &st) == -1);
663 ASSERT (errno == ENOENT);
665 memset (&st, 0, sizeof st);
666 ASSERT (lstat (BASE "link3", &st) == 0);
668 /* Files present here:
669 {BASE}file
670 {BASE}link1 -> {BASE}file
671 {BASE}link3 -> {BASE}nowhere
672 {BASE}dir/
674 { /* Trailing slash on link to file. */
676 errno = 0;
677 ASSERT (func (BASE "link1/", BASE "link2") == -1);
678 ASSERT (errno == ENOTDIR);
681 errno = 0;
682 ASSERT (func (BASE "link1", BASE "link3/") == -1);
683 ASSERT (errno == ENOENT || errno == ENOTDIR);
686 /* Files present here:
687 {BASE}file
688 {BASE}link1 -> {BASE}file
689 {BASE}link3 -> {BASE}nowhere
690 {BASE}dir/
693 /* Mixing symlink and file. */
695 { /* File onto link. */
696 ASSERT (close (creat (BASE "file2", 0600)) == 0);
697 /* Files present here:
698 {BASE}file
699 {BASE}file2
700 {BASE}link1 -> {BASE}file
701 {BASE}link3 -> {BASE}nowhere
702 {BASE}dir/
705 ASSERT (func (BASE "file2", BASE "link3") == 0);
706 errno = 0;
707 ASSERT (stat (BASE "file2", &st) == -1);
708 ASSERT (errno == ENOENT);
709 memset (&st, 0, sizeof st);
710 ASSERT (lstat (BASE "link3", &st) == 0);
711 ASSERT (S_ISREG (st.st_mode));
713 /* Files present here:
714 {BASE}file
715 {BASE}link1 -> {BASE}file
716 {BASE}link3
717 {BASE}dir/
719 ASSERT (unlink (BASE "link3") == 0);
721 /* Files present here:
722 {BASE}file
723 {BASE}link1 -> {BASE}file
724 {BASE}dir/
726 { /* Link onto file. */
727 ASSERT (symlink (BASE "nowhere", BASE "link2") == 0);
728 /* Files present here:
729 {BASE}file
730 {BASE}link1 -> {BASE}file
731 {BASE}link2 -> {BASE}nowhere
732 {BASE}dir/
734 ASSERT (close (creat (BASE "file2", 0600)) == 0);
735 /* Files present here:
736 {BASE}file
737 {BASE}file2
738 {BASE}link1 -> {BASE}file
739 {BASE}link2 -> {BASE}nowhere
740 {BASE}dir/
743 ASSERT (func (BASE "link2", BASE "file2") == 0);
744 errno = 0;
745 ASSERT (lstat (BASE "link2", &st) == -1);
746 ASSERT (errno == ENOENT);
747 memset (&st, 0, sizeof st);
748 ASSERT (lstat (BASE "file2", &st) == 0);
749 ASSERT (S_ISLNK (st.st_mode));
751 /* Files present here:
752 {BASE}file
753 {BASE}file2 -> {BASE}nowhere
754 {BASE}link1 -> {BASE}file
755 {BASE}dir/
757 ASSERT (unlink (BASE "file2") == 0);
759 /* Files present here:
760 {BASE}file
761 {BASE}link1 -> {BASE}file
762 {BASE}dir/
764 { /* Trailing slash. */
766 errno = 0;
767 ASSERT (func (BASE "file/", BASE "link1") == -1);
768 ASSERT (errno == ENOTDIR);
771 errno = 0;
772 ASSERT (func (BASE "file", BASE "link1/") == -1);
773 ASSERT (errno == ENOTDIR || errno == ENOENT);
776 errno = 0;
777 ASSERT (func (BASE "link1/", BASE "file") == -1);
778 ASSERT (errno == ENOTDIR);
781 errno = 0;
782 ASSERT (func (BASE "link1", BASE "file/") == -1);
783 ASSERT (errno == ENOTDIR || errno == ENOENT);
784 memset (&st, 0, sizeof st);
785 ASSERT (lstat (BASE "file", &st) == 0);
786 ASSERT (S_ISREG (st.st_mode));
787 memset (&st, 0, sizeof st);
788 ASSERT (lstat (BASE "link1", &st) == 0);
789 ASSERT (S_ISLNK (st.st_mode));
792 /* Files present here:
793 {BASE}file
794 {BASE}link1 -> {BASE}file
795 {BASE}dir/
798 /* Mixing symlink and directory. */
800 { /* Directory onto link. */
802 errno = 0;
803 ASSERT (func (BASE "dir", BASE "link1") == -1);
804 ASSERT (errno == ENOTDIR);
807 errno = 0;
808 ASSERT (func (BASE "dir/", BASE "link1") == -1);
809 ASSERT (errno == ENOTDIR);
812 errno = 0;
813 ASSERT (func (BASE "dir", BASE "link1/") == -1);
814 ASSERT (errno == ENOTDIR);
817 { /* Link onto directory. */
819 errno = 0;
820 ASSERT (func (BASE "link1", BASE "dir") == -1);
821 ASSERT (errno == EISDIR || errno == ENOTDIR);
824 errno = 0;
825 ASSERT (func (BASE "link1", BASE "dir/") == -1);
826 ASSERT (errno == EISDIR || errno == ENOTDIR);
829 errno = 0;
830 ASSERT (func (BASE "link1/", BASE "dir") == -1);
831 ASSERT (errno == ENOTDIR);
832 memset (&st, 0, sizeof st);
833 ASSERT (lstat (BASE "link1", &st) == 0);
834 ASSERT (S_ISLNK (st.st_mode));
835 memset (&st, 0, sizeof st);
836 ASSERT (lstat (BASE "dir", &st) == 0);
837 ASSERT (S_ISDIR (st.st_mode));
840 /* Files present here:
841 {BASE}file
842 {BASE}link1 -> {BASE}file
843 {BASE}dir/
846 /* POSIX requires rename("link-to-dir/","other") to rename "dir" and
847 leave "link-to-dir" dangling, but GNU rejects this. POSIX
848 requires rename("dir","dangling/") to create the directory so
849 that "dangling/" now resolves, but GNU rejects this. While we
850 prefer GNU behavior, we don't enforce it. However, we do test
851 that the system either follows POSIX in both cases, or follows
852 GNU. */
854 int result;
855 ASSERT (symlink (BASE "dir2", BASE "link2") == 0);
856 /* Files present here:
857 {BASE}file
858 {BASE}link1 -> {BASE}file
859 {BASE}link2 -> {BASE}dir2
860 {BASE}dir/
862 errno = 0;
863 result = func (BASE "dir", BASE "link2/");
864 if (result == 0)
866 /* POSIX. */
867 errno = 0;
868 ASSERT (lstat (BASE "dir", &st) == -1);
869 ASSERT (errno == ENOENT);
870 memset (&st, 0, sizeof st);
871 ASSERT (lstat (BASE "dir2", &st) == 0);
872 ASSERT (S_ISDIR (st.st_mode));
873 memset (&st, 0, sizeof st);
874 ASSERT (lstat (BASE "link2", &st) == 0);
875 ASSERT (S_ISLNK (st.st_mode));
876 /* Files present here:
877 {BASE}file
878 {BASE}link1 -> {BASE}file
879 {BASE}link2 -> {BASE}dir2
880 {BASE}dir2/
883 ASSERT (func (BASE "link2/", BASE "dir") == 0);
884 memset (&st, 0, sizeof st);
885 ASSERT (lstat (BASE "dir", &st) == 0);
886 ASSERT (S_ISDIR (st.st_mode));
887 errno = 0;
888 ASSERT (lstat (BASE "dir2", &st) == -1);
889 ASSERT (errno == ENOENT);
890 memset (&st, 0, sizeof st);
891 ASSERT (lstat (BASE "link2", &st) == 0);
892 ASSERT (S_ISLNK (st.st_mode));
895 else
897 /* GNU. */
898 ASSERT (result == -1);
899 ASSERT (errno == ENOTDIR);
900 memset (&st, 0, sizeof st);
901 ASSERT (lstat (BASE "dir", &st) == 0);
902 ASSERT (S_ISDIR (st.st_mode));
903 errno = 0;
904 ASSERT (lstat (BASE "dir2", &st) == -1);
905 ASSERT (errno == ENOENT);
906 memset (&st, 0, sizeof st);
907 ASSERT (lstat (BASE "link2", &st) == 0);
908 ASSERT (S_ISLNK (st.st_mode));
909 ASSERT (unlink (BASE "link2") == 0);
910 ASSERT (symlink (BASE "dir", BASE "link2") == 0);
911 /* Files present here:
912 {BASE}file
913 {BASE}link1 -> {BASE}file
914 {BASE}link2 -> {BASE}dir
915 {BASE}dir/
917 errno = 0; /* OpenBSD notices that link2/ and dir are the same. */
918 result = func (BASE "link2/", BASE "dir");
919 if (result) /* GNU/Linux rejects attempts to use link2/. */
921 ASSERT (result == -1);
922 ASSERT (errno == ENOTDIR || errno == EISDIR);
924 memset (&st, 0, sizeof st);
925 ASSERT (lstat (BASE "dir", &st) == 0);
926 ASSERT (S_ISDIR (st.st_mode));
927 errno = 0;
928 ASSERT (lstat (BASE "dir2", &st) == -1);
929 ASSERT (errno == ENOENT);
930 memset (&st, 0, sizeof st);
931 ASSERT (lstat (BASE "link2", &st) == 0);
932 ASSERT (S_ISLNK (st.st_mode));
935 /* Files present here:
936 {BASE}file
937 {BASE}link1 -> {BASE}file
938 {BASE}link2 -> {BASE}dir or {BASE}dir2
939 {BASE}dir/
942 /* Clean up. */
943 ASSERT (unlink (BASE "file") == 0);
944 ASSERT (rmdir (BASE "dir") == 0);
945 ASSERT (unlink (BASE "link1") == 0);
946 ASSERT (unlink (BASE "link2") == 0);
948 return 0;