uchar C++ tests: Fix build error on FreeBSD 12.
[gnulib.git] / tests / test-rename.h
blob844e1077b946b77b046cf26e815640a92a3753ac
1 /* Test of rename() function.
2 Copyright (C) 2009-2020 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 <https://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
343 || errno == ENOENT /* WSL */);
346 errno = 0;
347 ASSERT (func (BASE "dir2/.", BASE "dir") == -1);
348 ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST
349 || errno == ENOENT /* WSL */);
351 ASSERT (rmdir (BASE "dir") == 0);
352 /* Files present here:
353 {BASE}file
354 {BASE}dir2/
357 errno = 0;
358 ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
359 ASSERT (errno == EINVAL || errno == ENOENT);
361 ASSERT (mkdir (BASE "dir", 0700) == 0);
362 /* Files present here:
363 {BASE}file
364 {BASE}dir/
365 {BASE}dir2/
368 errno = 0;
369 ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
370 ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR
371 || errno == ENOTEMPTY || errno == EEXIST
372 || errno == ENOENT /* WSL */);
375 errno = 0;
376 ASSERT (func (BASE "dir2/.//", BASE "dir") == -1);
377 ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST
378 || errno == ENOENT /* WSL */);
380 ASSERT (rmdir (BASE "dir2") == 0);
381 /* Files present here:
382 {BASE}file
383 {BASE}dir/
386 { /* Move into subdir. */
388 errno = 0;
389 ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
390 ASSERT (errno == EINVAL || errno == EACCES);
393 errno = 0;
394 ASSERT (stat (BASE "dir/sub", &st) == -1);
395 ASSERT (errno == ENOENT);
397 ASSERT (mkdir (BASE "dir/sub", 0700) == 0);
398 /* Files present here:
399 {BASE}file
400 {BASE}dir/
401 {BASE}dir/sub/
404 errno = 0;
405 ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
406 ASSERT (errno == EINVAL);
407 ASSERT (stat (BASE "dir/sub", &st) == 0);
409 ASSERT (rmdir (BASE "dir/sub") == 0);
412 /* Files present here:
413 {BASE}file
414 {BASE}dir/
417 /* Mixing file and directory. */
420 { /* File onto dir. */
422 errno = 0;
423 ASSERT (func (BASE "file", BASE "dir") == -1);
424 ASSERT (errno == EISDIR || errno == ENOTDIR);
427 errno = 0;
428 ASSERT (func (BASE "file", BASE "dir/") == -1);
429 ASSERT (errno == EISDIR || errno == ENOTDIR);
432 { /* Dir onto file. */
434 errno = 0;
435 ASSERT (func (BASE "dir", BASE "file") == -1);
436 ASSERT (errno == ENOTDIR);
439 errno = 0;
440 ASSERT (func (BASE "dir/", BASE "file") == -1);
441 ASSERT (errno == ENOTDIR);
446 /* Hard links. */
448 { /* File onto self. */
449 ASSERT (func (BASE "file", BASE "file") == 0);
450 memset (&st, 0, sizeof st);
451 ASSERT (stat (BASE "file", &st) == 0);
452 ASSERT (st.st_size == 2);
454 /* Files present here:
455 {BASE}file
456 {BASE}dir/
458 { /* Empty dir onto self. */
459 ASSERT (func (BASE "dir", BASE "dir") == 0);
460 ASSERT (stat (BASE "dir", &st) == 0);
462 /* Files present here:
463 {BASE}file
464 {BASE}dir/
466 ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
467 /* Files present here:
468 {BASE}file
469 {BASE}dir/
470 {BASE}dir/file
472 { /* Full dir onto self. */
473 ASSERT (func (BASE "dir", BASE "dir") == 0);
475 ASSERT (unlink (BASE "dir/file") == 0);
476 /* Files present here:
477 {BASE}file
478 {BASE}dir/
481 /* Not all file systems support link. Mingw doesn't have
482 reliable st_nlink on hard links, but our implementation does
483 fail with EPERM on poor file systems, and we can detect the
484 inferior stat() via st_ino. Cygwin 1.5.x copies rather than
485 links files on those file systems, but there, st_nlink and
486 st_ino are reliable. */
487 int ret = link (BASE "file", BASE "file2");
488 if (!ret)
490 memset (&st, 0, sizeof st);
491 ASSERT (stat (BASE "file2", &st) == 0);
492 if (st.st_ino && st.st_nlink != 2)
494 ASSERT (unlink (BASE "file2") == 0);
495 errno = EPERM;
496 ret = -1;
499 if (ret == -1)
501 /* If the device does not support hard links, errno is
502 EPERM on Linux, EOPNOTSUPP on FreeBSD. */
503 switch (errno)
505 case EPERM:
506 case EOPNOTSUPP:
507 if (print)
508 fputs ("skipping test: "
509 "hard links not supported on this file system\n",
510 stderr);
511 ASSERT (unlink (BASE "file") == 0);
512 ASSERT (rmdir (BASE "dir") == 0);
513 return 77;
514 default:
515 perror ("link");
516 return 1;
519 ASSERT (ret == 0);
521 /* Files present here:
522 {BASE}file
523 {BASE}file2 (hard link to file)
524 {BASE}dir/
526 { /* File onto hard link. */
527 ASSERT (func (BASE "file", BASE "file2") == 0);
528 memset (&st, 0, sizeof st);
529 if (stat (BASE "file", &st) != 0)
531 /* This can happen on NetBSD. */
532 ASSERT (errno == ENOENT);
533 ASSERT (link (BASE "file2", BASE "file") == 0);
534 ASSERT (stat (BASE "file", &st) == 0);
536 ASSERT (st.st_size == 2);
537 memset (&st, 0, sizeof st);
538 ASSERT (stat (BASE "file2", &st) == 0);
539 ASSERT (st.st_size == 2);
541 /* Files present here:
542 {BASE}file
543 {BASE}file2
544 {BASE}dir/
546 ASSERT (unlink (BASE "file2") == 0);
547 /* Files present here:
548 {BASE}file
549 {BASE}dir/
552 /* Symlinks. */
554 if (symlink (BASE "file", BASE "link1"))
556 if (print)
557 fputs ("skipping test: symlinks not supported on this file system\n",
558 stderr);
559 ASSERT (unlink (BASE "file") == 0);
560 ASSERT (rmdir (BASE "dir") == 0);
561 return 77;
563 /* Files present here:
564 {BASE}file
565 {BASE}link1 -> {BASE}file
566 {BASE}dir/
568 { /* Simple rename. */
569 ASSERT (func (BASE "link1", BASE "link2") == 0);
570 ASSERT (stat (BASE "file", &st) == 0);
571 errno = 0;
572 ASSERT (lstat (BASE "link1", &st) == -1);
573 ASSERT (errno == ENOENT);
574 memset (&st, 0, sizeof st);
575 ASSERT (lstat (BASE "link2", &st) == 0);
576 ASSERT (S_ISLNK (st.st_mode));
578 /* Files present here:
579 {BASE}file
580 {BASE}link2 -> {BASE}file
581 {BASE}dir/
583 { /* Overwrite. */
584 ASSERT (symlink (BASE "nowhere", BASE "link1") == 0);
585 /* Files present here:
586 {BASE}file
587 {BASE}link1 -> {BASE}nowhere
588 {BASE}link2 -> {BASE}file
589 {BASE}dir/
592 ASSERT (func (BASE "link2", BASE "link1") == 0);
593 memset (&st, 0, sizeof st);
594 ASSERT (stat (BASE "link1", &st) == 0);
595 ASSERT (st.st_size == 2);
596 errno = 0;
597 ASSERT (lstat (BASE "link2", &st) == -1);
598 ASSERT (errno == ENOENT);
601 /* Files present here:
602 {BASE}file
603 {BASE}link1 -> {BASE}file
604 {BASE}dir/
606 { /* Symlink loop. */
607 ASSERT (symlink (BASE "link2", BASE "link2") == 0);
608 /* Files present here:
609 {BASE}file
610 {BASE}link1 -> {BASE}file
611 {BASE}link2 -> {BASE}link2
612 {BASE}dir/
615 ASSERT (func (BASE "link2", BASE "link2") == 0);
618 errno = 0;
619 ASSERT (func (BASE "link2/", BASE "link2") == -1);
620 ASSERT (errno == ELOOP || errno == ENOTDIR);
622 ASSERT (func (BASE "link2", BASE "link3") == 0);
623 /* Files present here:
624 {BASE}file
625 {BASE}link1 -> {BASE}file
626 {BASE}link3 -> {BASE}link2
627 {BASE}dir/
629 ASSERT (unlink (BASE "link3") == 0);
631 /* Files present here:
632 {BASE}file
633 {BASE}link1 -> {BASE}file
634 {BASE}dir/
636 { /* Dangling link. */
637 ASSERT (symlink (BASE "nowhere", BASE "link2") == 0);
638 /* Files present here:
639 {BASE}file
640 {BASE}link1 -> {BASE}file
641 {BASE}link2 -> {BASE}nowhere
642 {BASE}dir/
645 ASSERT (func (BASE "link2", BASE "link3") == 0);
646 errno = 0;
647 ASSERT (lstat (BASE "link2", &st) == -1);
648 ASSERT (errno == ENOENT);
649 memset (&st, 0, sizeof st);
650 ASSERT (lstat (BASE "link3", &st) == 0);
653 /* Files present here:
654 {BASE}file
655 {BASE}link1 -> {BASE}file
656 {BASE}link3 -> {BASE}nowhere
657 {BASE}dir/
659 { /* Trailing slash on dangling. */
661 errno = 0;
662 ASSERT (func (BASE "link3/", BASE "link2") == -1);
663 ASSERT (errno == ENOENT || errno == ENOTDIR);
666 errno = 0;
667 ASSERT (func (BASE "link3", BASE "link2/") == -1);
668 ASSERT (errno == ENOENT || errno == ENOTDIR);
671 errno = 0;
672 ASSERT (lstat (BASE "link2", &st) == -1);
673 ASSERT (errno == ENOENT);
675 memset (&st, 0, sizeof st);
676 ASSERT (lstat (BASE "link3", &st) == 0);
678 /* Files present here:
679 {BASE}file
680 {BASE}link1 -> {BASE}file
681 {BASE}link3 -> {BASE}nowhere
682 {BASE}dir/
684 { /* Trailing slash on link to file. */
686 errno = 0;
687 ASSERT (func (BASE "link1/", BASE "link2") == -1);
688 ASSERT (errno == ENOTDIR);
691 errno = 0;
692 ASSERT (func (BASE "link1", BASE "link3/") == -1);
693 ASSERT (errno == ENOENT || errno == ENOTDIR);
696 /* Files present here:
697 {BASE}file
698 {BASE}link1 -> {BASE}file
699 {BASE}link3 -> {BASE}nowhere
700 {BASE}dir/
703 /* Mixing symlink and file. */
705 { /* File onto link. */
706 ASSERT (close (creat (BASE "file2", 0600)) == 0);
707 /* Files present here:
708 {BASE}file
709 {BASE}file2
710 {BASE}link1 -> {BASE}file
711 {BASE}link3 -> {BASE}nowhere
712 {BASE}dir/
715 ASSERT (func (BASE "file2", BASE "link3") == 0);
716 errno = 0;
717 ASSERT (stat (BASE "file2", &st) == -1);
718 ASSERT (errno == ENOENT);
719 memset (&st, 0, sizeof st);
720 ASSERT (lstat (BASE "link3", &st) == 0);
721 ASSERT (S_ISREG (st.st_mode));
723 /* Files present here:
724 {BASE}file
725 {BASE}link1 -> {BASE}file
726 {BASE}link3
727 {BASE}dir/
729 ASSERT (unlink (BASE "link3") == 0);
731 /* Files present here:
732 {BASE}file
733 {BASE}link1 -> {BASE}file
734 {BASE}dir/
736 { /* Link onto file. */
737 ASSERT (symlink (BASE "nowhere", BASE "link2") == 0);
738 /* Files present here:
739 {BASE}file
740 {BASE}link1 -> {BASE}file
741 {BASE}link2 -> {BASE}nowhere
742 {BASE}dir/
744 ASSERT (close (creat (BASE "file2", 0600)) == 0);
745 /* Files present here:
746 {BASE}file
747 {BASE}file2
748 {BASE}link1 -> {BASE}file
749 {BASE}link2 -> {BASE}nowhere
750 {BASE}dir/
753 ASSERT (func (BASE "link2", BASE "file2") == 0);
754 errno = 0;
755 ASSERT (lstat (BASE "link2", &st) == -1);
756 ASSERT (errno == ENOENT);
757 memset (&st, 0, sizeof st);
758 ASSERT (lstat (BASE "file2", &st) == 0);
759 ASSERT (S_ISLNK (st.st_mode));
761 /* Files present here:
762 {BASE}file
763 {BASE}file2 -> {BASE}nowhere
764 {BASE}link1 -> {BASE}file
765 {BASE}dir/
767 ASSERT (unlink (BASE "file2") == 0);
769 /* Files present here:
770 {BASE}file
771 {BASE}link1 -> {BASE}file
772 {BASE}dir/
774 { /* Trailing slash. */
776 errno = 0;
777 ASSERT (func (BASE "file/", BASE "link1") == -1);
778 ASSERT (errno == ENOTDIR);
781 errno = 0;
782 ASSERT (func (BASE "file", BASE "link1/") == -1);
783 ASSERT (errno == ENOTDIR || errno == ENOENT);
786 errno = 0;
787 ASSERT (func (BASE "link1/", BASE "file") == -1);
788 ASSERT (errno == ENOTDIR);
791 errno = 0;
792 ASSERT (func (BASE "link1", BASE "file/") == -1);
793 ASSERT (errno == ENOTDIR || errno == ENOENT);
794 memset (&st, 0, sizeof st);
795 ASSERT (lstat (BASE "file", &st) == 0);
796 ASSERT (S_ISREG (st.st_mode));
797 memset (&st, 0, sizeof st);
798 ASSERT (lstat (BASE "link1", &st) == 0);
799 ASSERT (S_ISLNK (st.st_mode));
802 /* Files present here:
803 {BASE}file
804 {BASE}link1 -> {BASE}file
805 {BASE}dir/
808 /* Mixing symlink and directory. */
810 { /* Directory onto link. */
812 errno = 0;
813 ASSERT (func (BASE "dir", BASE "link1") == -1);
814 ASSERT (errno == ENOTDIR);
817 errno = 0;
818 ASSERT (func (BASE "dir/", BASE "link1") == -1);
819 ASSERT (errno == ENOTDIR);
822 errno = 0;
823 ASSERT (func (BASE "dir", BASE "link1/") == -1);
824 ASSERT (errno == ENOTDIR);
827 { /* Link onto directory. */
829 errno = 0;
830 ASSERT (func (BASE "link1", BASE "dir") == -1);
831 ASSERT (errno == EISDIR || errno == ENOTDIR);
834 errno = 0;
835 ASSERT (func (BASE "link1", BASE "dir/") == -1);
836 ASSERT (errno == EISDIR || errno == ENOTDIR);
839 errno = 0;
840 ASSERT (func (BASE "link1/", BASE "dir") == -1);
841 ASSERT (errno == ENOTDIR);
842 memset (&st, 0, sizeof st);
843 ASSERT (lstat (BASE "link1", &st) == 0);
844 ASSERT (S_ISLNK (st.st_mode));
845 memset (&st, 0, sizeof st);
846 ASSERT (lstat (BASE "dir", &st) == 0);
847 ASSERT (S_ISDIR (st.st_mode));
850 /* Files present here:
851 {BASE}file
852 {BASE}link1 -> {BASE}file
853 {BASE}dir/
856 /* POSIX requires rename("link-to-dir/","other") to rename "dir" and
857 leave "link-to-dir" dangling, but GNU rejects this. POSIX
858 requires rename("dir","dangling/") to create the directory so
859 that "dangling/" now resolves, but GNU rejects this. While we
860 prefer GNU behavior, we don't enforce it. However, we do test
861 that the system either follows POSIX in both cases, or follows
862 GNU. */
864 int result;
865 ASSERT (symlink (BASE "dir2", BASE "link2") == 0);
866 /* Files present here:
867 {BASE}file
868 {BASE}link1 -> {BASE}file
869 {BASE}link2 -> {BASE}dir2
870 {BASE}dir/
872 errno = 0;
873 result = func (BASE "dir", BASE "link2/");
874 if (result == 0)
876 /* POSIX. */
877 errno = 0;
878 ASSERT (lstat (BASE "dir", &st) == -1);
879 ASSERT (errno == ENOENT);
880 memset (&st, 0, sizeof st);
881 ASSERT (lstat (BASE "dir2", &st) == 0);
882 ASSERT (S_ISDIR (st.st_mode));
883 memset (&st, 0, sizeof st);
884 ASSERT (lstat (BASE "link2", &st) == 0);
885 ASSERT (S_ISLNK (st.st_mode));
886 /* Files present here:
887 {BASE}file
888 {BASE}link1 -> {BASE}file
889 {BASE}link2 -> {BASE}dir2
890 {BASE}dir2/
893 ASSERT (func (BASE "link2/", BASE "dir") == 0);
894 memset (&st, 0, sizeof st);
895 ASSERT (lstat (BASE "dir", &st) == 0);
896 ASSERT (S_ISDIR (st.st_mode));
897 errno = 0;
898 ASSERT (lstat (BASE "dir2", &st) == -1);
899 ASSERT (errno == ENOENT);
900 memset (&st, 0, sizeof st);
901 ASSERT (lstat (BASE "link2", &st) == 0);
902 ASSERT (S_ISLNK (st.st_mode));
905 else
907 /* GNU. */
908 ASSERT (result == -1);
909 ASSERT (errno == ENOTDIR);
910 memset (&st, 0, sizeof st);
911 ASSERT (lstat (BASE "dir", &st) == 0);
912 ASSERT (S_ISDIR (st.st_mode));
913 errno = 0;
914 ASSERT (lstat (BASE "dir2", &st) == -1);
915 ASSERT (errno == ENOENT);
916 memset (&st, 0, sizeof st);
917 ASSERT (lstat (BASE "link2", &st) == 0);
918 ASSERT (S_ISLNK (st.st_mode));
919 ASSERT (unlink (BASE "link2") == 0);
920 ASSERT (symlink (BASE "dir", BASE "link2") == 0);
921 /* Files present here:
922 {BASE}file
923 {BASE}link1 -> {BASE}file
924 {BASE}link2 -> {BASE}dir
925 {BASE}dir/
927 errno = 0; /* OpenBSD notices that link2/ and dir are the same. */
928 result = func (BASE "link2/", BASE "dir");
929 if (result) /* GNU/Linux rejects attempts to use link2/. */
931 ASSERT (result == -1);
932 ASSERT (errno == ENOTDIR || errno == EISDIR);
934 memset (&st, 0, sizeof st);
935 ASSERT (lstat (BASE "dir", &st) == 0);
936 ASSERT (S_ISDIR (st.st_mode));
937 errno = 0;
938 ASSERT (lstat (BASE "dir2", &st) == -1);
939 ASSERT (errno == ENOENT);
940 memset (&st, 0, sizeof st);
941 ASSERT (lstat (BASE "link2", &st) == 0);
942 ASSERT (S_ISLNK (st.st_mode));
945 /* Files present here:
946 {BASE}file
947 {BASE}link1 -> {BASE}file
948 {BASE}link2 -> {BASE}dir or {BASE}dir2
949 {BASE}dir/
952 /* Clean up. */
953 ASSERT (unlink (BASE "file") == 0);
954 ASSERT (rmdir (BASE "dir") == 0);
955 ASSERT (unlink (BASE "link1") == 0);
956 ASSERT (unlink (BASE "link2") == 0);
958 return 0;