gettext: Sync with gettext 0.23.
[gnulib.git] / tests / test-rename.h
blobc0678492e8dedc43194e117cb80f30672bb991bd
1 /* Test of rename() function.
2 Copyright (C) 2009-2024 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,
503 EOPNOTSUPP on FreeBSD,
504 EACCES on Android within Termux. */
505 switch (errno)
507 case EPERM:
508 case EOPNOTSUPP:
509 #if defined __ANDROID__
510 case EACCES:
511 #endif
512 if (print)
513 fputs ("skipping test: "
514 "hard links not supported on this file system\n",
515 stderr);
516 ASSERT (unlink (BASE "file") == 0);
517 ASSERT (rmdir (BASE "dir") == 0);
518 return 77;
519 default:
520 perror ("link");
521 return 1;
524 ASSERT (ret == 0);
526 /* Files present here:
527 {BASE}file
528 {BASE}file2 (hard link to file)
529 {BASE}dir/
531 { /* File onto hard link. */
532 ASSERT (func (BASE "file", BASE "file2") == 0);
533 memset (&st, 0, sizeof st);
534 if (stat (BASE "file", &st) != 0)
536 /* This can happen on NetBSD. */
537 ASSERT (errno == ENOENT);
538 ASSERT (link (BASE "file2", BASE "file") == 0);
539 ASSERT (stat (BASE "file", &st) == 0);
541 ASSERT (st.st_size == 2);
542 memset (&st, 0, sizeof st);
543 ASSERT (stat (BASE "file2", &st) == 0);
544 ASSERT (st.st_size == 2);
546 /* Files present here:
547 {BASE}file
548 {BASE}file2
549 {BASE}dir/
551 ASSERT (unlink (BASE "file2") == 0);
552 /* Files present here:
553 {BASE}file
554 {BASE}dir/
557 /* Symlinks. */
559 if (symlink (BASE "file", BASE "link1"))
561 if (print)
562 fputs ("skipping test: symlinks not supported on this file system\n",
563 stderr);
564 ASSERT (unlink (BASE "file") == 0);
565 ASSERT (rmdir (BASE "dir") == 0);
566 return 77;
568 /* Files present here:
569 {BASE}file
570 {BASE}link1 -> {BASE}file
571 {BASE}dir/
573 { /* Simple rename. */
574 ASSERT (func (BASE "link1", BASE "link2") == 0);
575 ASSERT (stat (BASE "file", &st) == 0);
576 errno = 0;
577 ASSERT (lstat (BASE "link1", &st) == -1);
578 ASSERT (errno == ENOENT);
579 memset (&st, 0, sizeof st);
580 ASSERT (lstat (BASE "link2", &st) == 0);
581 ASSERT (S_ISLNK (st.st_mode));
583 /* Files present here:
584 {BASE}file
585 {BASE}link2 -> {BASE}file
586 {BASE}dir/
588 { /* Overwrite. */
589 ASSERT (symlink (BASE "nowhere", BASE "link1") == 0);
590 /* Files present here:
591 {BASE}file
592 {BASE}link1 -> {BASE}nowhere
593 {BASE}link2 -> {BASE}file
594 {BASE}dir/
597 ASSERT (func (BASE "link2", BASE "link1") == 0);
598 memset (&st, 0, sizeof st);
599 ASSERT (stat (BASE "link1", &st) == 0);
600 ASSERT (st.st_size == 2);
601 errno = 0;
602 ASSERT (lstat (BASE "link2", &st) == -1);
603 ASSERT (errno == ENOENT);
606 /* Files present here:
607 {BASE}file
608 {BASE}link1 -> {BASE}file
609 {BASE}dir/
611 { /* Symlink loop. */
612 ASSERT (symlink (BASE "link2", BASE "link2") == 0);
613 /* Files present here:
614 {BASE}file
615 {BASE}link1 -> {BASE}file
616 {BASE}link2 -> {BASE}link2
617 {BASE}dir/
620 ASSERT (func (BASE "link2", BASE "link2") == 0);
623 errno = 0;
624 ASSERT (func (BASE "link2/", BASE "link2") == -1);
625 ASSERT (errno == ELOOP || errno == ENOTDIR);
627 ASSERT (func (BASE "link2", BASE "link3") == 0);
628 /* Files present here:
629 {BASE}file
630 {BASE}link1 -> {BASE}file
631 {BASE}link3 -> {BASE}link2
632 {BASE}dir/
634 ASSERT (unlink (BASE "link3") == 0);
636 /* Files present here:
637 {BASE}file
638 {BASE}link1 -> {BASE}file
639 {BASE}dir/
641 { /* Dangling link. */
642 ASSERT (symlink (BASE "nowhere", BASE "link2") == 0);
643 /* Files present here:
644 {BASE}file
645 {BASE}link1 -> {BASE}file
646 {BASE}link2 -> {BASE}nowhere
647 {BASE}dir/
650 ASSERT (func (BASE "link2", BASE "link3") == 0);
651 errno = 0;
652 ASSERT (lstat (BASE "link2", &st) == -1);
653 ASSERT (errno == ENOENT);
654 memset (&st, 0, sizeof st);
655 ASSERT (lstat (BASE "link3", &st) == 0);
658 /* Files present here:
659 {BASE}file
660 {BASE}link1 -> {BASE}file
661 {BASE}link3 -> {BASE}nowhere
662 {BASE}dir/
664 { /* Trailing slash on dangling. */
666 errno = 0;
667 ASSERT (func (BASE "link3/", BASE "link2") == -1);
668 ASSERT (errno == ENOENT || errno == ENOTDIR);
671 errno = 0;
672 ASSERT (func (BASE "link3", BASE "link2/") == -1);
673 ASSERT (errno == ENOENT || errno == ENOTDIR);
676 errno = 0;
677 ASSERT (lstat (BASE "link2", &st) == -1);
678 ASSERT (errno == ENOENT);
680 memset (&st, 0, sizeof st);
681 ASSERT (lstat (BASE "link3", &st) == 0);
683 /* Files present here:
684 {BASE}file
685 {BASE}link1 -> {BASE}file
686 {BASE}link3 -> {BASE}nowhere
687 {BASE}dir/
689 { /* Trailing slash on link to file. */
691 errno = 0;
692 ASSERT (func (BASE "link1/", BASE "link2") == -1);
693 ASSERT (errno == ENOTDIR);
696 errno = 0;
697 ASSERT (func (BASE "link1", BASE "link3/") == -1);
698 ASSERT (errno == ENOENT || errno == ENOTDIR);
701 /* Files present here:
702 {BASE}file
703 {BASE}link1 -> {BASE}file
704 {BASE}link3 -> {BASE}nowhere
705 {BASE}dir/
708 /* Mixing symlink and file. */
710 { /* File onto link. */
711 ASSERT (close (creat (BASE "file2", 0600)) == 0);
712 /* Files present here:
713 {BASE}file
714 {BASE}file2
715 {BASE}link1 -> {BASE}file
716 {BASE}link3 -> {BASE}nowhere
717 {BASE}dir/
720 ASSERT (func (BASE "file2", BASE "link3") == 0);
721 errno = 0;
722 ASSERT (stat (BASE "file2", &st) == -1);
723 ASSERT (errno == ENOENT);
724 memset (&st, 0, sizeof st);
725 ASSERT (lstat (BASE "link3", &st) == 0);
726 ASSERT (S_ISREG (st.st_mode));
728 /* Files present here:
729 {BASE}file
730 {BASE}link1 -> {BASE}file
731 {BASE}link3
732 {BASE}dir/
734 ASSERT (unlink (BASE "link3") == 0);
736 /* Files present here:
737 {BASE}file
738 {BASE}link1 -> {BASE}file
739 {BASE}dir/
741 { /* Link onto file. */
742 ASSERT (symlink (BASE "nowhere", BASE "link2") == 0);
743 /* Files present here:
744 {BASE}file
745 {BASE}link1 -> {BASE}file
746 {BASE}link2 -> {BASE}nowhere
747 {BASE}dir/
749 ASSERT (close (creat (BASE "file2", 0600)) == 0);
750 /* Files present here:
751 {BASE}file
752 {BASE}file2
753 {BASE}link1 -> {BASE}file
754 {BASE}link2 -> {BASE}nowhere
755 {BASE}dir/
758 ASSERT (func (BASE "link2", BASE "file2") == 0);
759 errno = 0;
760 ASSERT (lstat (BASE "link2", &st) == -1);
761 ASSERT (errno == ENOENT);
762 memset (&st, 0, sizeof st);
763 ASSERT (lstat (BASE "file2", &st) == 0);
764 ASSERT (S_ISLNK (st.st_mode));
766 /* Files present here:
767 {BASE}file
768 {BASE}file2 -> {BASE}nowhere
769 {BASE}link1 -> {BASE}file
770 {BASE}dir/
772 ASSERT (unlink (BASE "file2") == 0);
774 /* Files present here:
775 {BASE}file
776 {BASE}link1 -> {BASE}file
777 {BASE}dir/
779 { /* Trailing slash. */
781 errno = 0;
782 ASSERT (func (BASE "file/", BASE "link1") == -1);
783 ASSERT (errno == ENOTDIR);
786 errno = 0;
787 ASSERT (func (BASE "file", BASE "link1/") == -1);
788 ASSERT (errno == ENOTDIR || errno == ENOENT);
791 errno = 0;
792 ASSERT (func (BASE "link1/", BASE "file") == -1);
793 ASSERT (errno == ENOTDIR);
796 errno = 0;
797 ASSERT (func (BASE "link1", BASE "file/") == -1);
798 ASSERT (errno == ENOTDIR || errno == ENOENT);
799 memset (&st, 0, sizeof st);
800 ASSERT (lstat (BASE "file", &st) == 0);
801 ASSERT (S_ISREG (st.st_mode));
802 memset (&st, 0, sizeof st);
803 ASSERT (lstat (BASE "link1", &st) == 0);
804 ASSERT (S_ISLNK (st.st_mode));
807 /* Files present here:
808 {BASE}file
809 {BASE}link1 -> {BASE}file
810 {BASE}dir/
813 /* Mixing symlink and directory. */
815 { /* Directory onto link. */
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 errno = 0;
828 ASSERT (func (BASE "dir", BASE "link1/") == -1);
829 ASSERT (errno == ENOTDIR);
832 { /* Link onto directory. */
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 == EISDIR || errno == ENOTDIR);
844 errno = 0;
845 ASSERT (func (BASE "link1/", BASE "dir") == -1);
846 ASSERT (errno == ENOTDIR);
847 memset (&st, 0, sizeof st);
848 ASSERT (lstat (BASE "link1", &st) == 0);
849 ASSERT (S_ISLNK (st.st_mode));
850 memset (&st, 0, sizeof st);
851 ASSERT (lstat (BASE "dir", &st) == 0);
852 ASSERT (S_ISDIR (st.st_mode));
855 /* Files present here:
856 {BASE}file
857 {BASE}link1 -> {BASE}file
858 {BASE}dir/
861 /* POSIX requires rename("link-to-dir/","other") to rename "dir" and
862 leave "link-to-dir" dangling, but GNU rejects this. POSIX
863 requires rename("dir","dangling/") to create the directory so
864 that "dangling/" now resolves, but GNU rejects this. While we
865 prefer GNU behavior, we don't enforce it. However, we do test
866 that the system either follows POSIX in both cases, or follows
867 GNU. */
869 int result;
870 ASSERT (symlink (BASE "dir2", BASE "link2") == 0);
871 /* Files present here:
872 {BASE}file
873 {BASE}link1 -> {BASE}file
874 {BASE}link2 -> {BASE}dir2
875 {BASE}dir/
877 errno = 0;
878 result = func (BASE "dir", BASE "link2/");
879 if (result == 0)
881 /* POSIX. */
882 errno = 0;
883 ASSERT (lstat (BASE "dir", &st) == -1);
884 ASSERT (errno == ENOENT);
885 memset (&st, 0, sizeof st);
886 ASSERT (lstat (BASE "dir2", &st) == 0);
887 ASSERT (S_ISDIR (st.st_mode));
888 memset (&st, 0, sizeof st);
889 ASSERT (lstat (BASE "link2", &st) == 0);
890 ASSERT (S_ISLNK (st.st_mode));
891 /* Files present here:
892 {BASE}file
893 {BASE}link1 -> {BASE}file
894 {BASE}link2 -> {BASE}dir2
895 {BASE}dir2/
898 ASSERT (func (BASE "link2/", BASE "dir") == 0);
899 memset (&st, 0, sizeof st);
900 ASSERT (lstat (BASE "dir", &st) == 0);
901 ASSERT (S_ISDIR (st.st_mode));
902 errno = 0;
903 ASSERT (lstat (BASE "dir2", &st) == -1);
904 ASSERT (errno == ENOENT);
905 memset (&st, 0, sizeof st);
906 ASSERT (lstat (BASE "link2", &st) == 0);
907 ASSERT (S_ISLNK (st.st_mode));
910 else
912 /* GNU. */
913 ASSERT (result == -1);
914 ASSERT (errno == ENOTDIR);
915 memset (&st, 0, sizeof st);
916 ASSERT (lstat (BASE "dir", &st) == 0);
917 ASSERT (S_ISDIR (st.st_mode));
918 errno = 0;
919 ASSERT (lstat (BASE "dir2", &st) == -1);
920 ASSERT (errno == ENOENT);
921 memset (&st, 0, sizeof st);
922 ASSERT (lstat (BASE "link2", &st) == 0);
923 ASSERT (S_ISLNK (st.st_mode));
924 ASSERT (unlink (BASE "link2") == 0);
925 ASSERT (symlink (BASE "dir", BASE "link2") == 0);
926 /* Files present here:
927 {BASE}file
928 {BASE}link1 -> {BASE}file
929 {BASE}link2 -> {BASE}dir
930 {BASE}dir/
932 errno = 0; /* OpenBSD notices that link2/ and dir are the same. */
933 result = func (BASE "link2/", BASE "dir");
934 if (result) /* GNU/Linux rejects attempts to use link2/. */
936 ASSERT (result == -1);
937 ASSERT (errno == ENOTDIR || errno == EISDIR);
939 memset (&st, 0, sizeof st);
940 ASSERT (lstat (BASE "dir", &st) == 0);
941 ASSERT (S_ISDIR (st.st_mode));
942 errno = 0;
943 ASSERT (lstat (BASE "dir2", &st) == -1);
944 ASSERT (errno == ENOENT);
945 memset (&st, 0, sizeof st);
946 ASSERT (lstat (BASE "link2", &st) == 0);
947 ASSERT (S_ISLNK (st.st_mode));
950 /* Files present here:
951 {BASE}file
952 {BASE}link1 -> {BASE}file
953 {BASE}link2 -> {BASE}dir or {BASE}dir2
954 {BASE}dir/
957 /* Clean up. */
958 ASSERT (unlink (BASE "file") == 0);
959 ASSERT (rmdir (BASE "dir") == 0);
960 ASSERT (unlink (BASE "link1") == 0);
961 ASSERT (unlink (BASE "link2") == 0);
963 return 0;