xref: /xnu-10002.1.13/tests/rename_excl.c (revision 1031c584a5e37aff177559b9f69dbd3c8c3fd30a)
1 #include <darwintest.h>
2 #include <darwintest_utils.h>
3 #include <dirent.h>
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <sys/stat.h>
10 
11 
12 T_GLOBAL_META(
13 	T_META_NAMESPACE("xnu.vfs"),
14 	T_META_CHECK_LEAKS(false)
15 	);
16 
17 #define TEST_DIR         "rename_dir"
18 #define TEST_FILE1       TEST_DIR "/file1"
19 #define TEST_FILE1_UC    TEST_DIR "/FILE1"
20 #define TEST_FILE2       TEST_DIR "/file2"
21 #define TEST_FILE3_HL    TEST_DIR "/file3"
22 
23 static void
cleanup(void)24 cleanup(void)
25 {
26 	(void) remove(TEST_FILE1);
27 	(void) remove(TEST_FILE1_UC);
28 	(void) remove(TEST_FILE2);
29 	(void) remove(TEST_FILE3_HL);
30 	(void) rmdir(TEST_DIR);
31 }
32 
33 /*
34  * This unit-test validates the behavior of renamex_np() with RENAME_EXCL flag.
35  * On either a case-insensitve/case-sensitive volume:
36  * 1. rename from source to existing target should succeed when the change is
37  *    only case-variant (for e.g rename_dir/file1 -> rename_dir/FILE1)
38  * 2. rename from source to existing target should fail with EEXIST
39  * 3. rename from source to existing target which is a hardlink of the source
40  *    should fail with EEXIST
41  *
42  * On case-insensitive volume:
43  * 1. rename from source to itself should succeed
44  *    (rename_dir/file1 -> rename_dir/file1)
45  *
46  * On case-sensitive volume:
47  * 1. rename from source to itself should fail with EEXIST
48  *    (rename_dir/file1 -> rename_dir/file1)
49  */
50 
51 T_DECL(rename_excl_with_case_variant,
52     "test renamex_np() with RENAME_EXCL flag for files with case variants")
53 {
54 	const char *tmpdir = dt_tmpdir();
55 	long case_sensitive_vol;
56 	int err, saved_errno;
57 	int fd;
58 
59 	T_SETUPBEGIN;
60 
61 	atexit(cleanup);
62 
63 	T_ASSERT_POSIX_ZERO(chdir(tmpdir),
64 	    "Setup: changing to tmpdir: %s", tmpdir);
65 
66 	T_ASSERT_POSIX_SUCCESS(mkdir(TEST_DIR, 0777),
67 	    "Setup: creating test dir: %s", TEST_DIR);
68 
69 	T_WITH_ERRNO;
70 	fd = open(TEST_FILE1, O_CREAT | O_RDWR, 0666);
71 	T_ASSERT_TRUE(fd != -1, "Creating test file1: %s", TEST_FILE1);
72 
73 	T_ASSERT_POSIX_SUCCESS(close(fd), "Closing test file1: %s",
74 	    TEST_FILE1);
75 
76 	T_WITH_ERRNO;
77 	fd = open(TEST_FILE2, O_CREAT | O_RDWR, 0666);
78 	T_ASSERT_TRUE(fd != -1, "Creating test file2: %s", TEST_FILE2);
79 
80 	T_ASSERT_POSIX_SUCCESS(close(fd), "Closing test file2: %s",
81 	    TEST_FILE2);
82 
83 	T_ASSERT_POSIX_SUCCESS(link(TEST_FILE1, TEST_FILE3_HL),
84 	    "Creating hardlink for %s from source: %s",
85 	    TEST_FILE3_HL, TEST_FILE1);
86 
87 	case_sensitive_vol = pathconf(TEST_DIR, _PC_CASE_SENSITIVE);
88 	T_ASSERT_TRUE(case_sensitive_vol != -1,
89 	    "Checking if target volume is case-sensitive, is_case_sensitive: %ld",
90 	    case_sensitive_vol);
91 
92 	T_SETUPEND;
93 
94 	err = renamex_np(TEST_FILE1, TEST_FILE2, RENAME_EXCL);
95 	saved_errno = errno;
96 	T_ASSERT_TRUE((err == -1 && saved_errno == EEXIST),
97 	    "Renaming with RENAME_EXCL from source: %s to target: %s",
98 	    TEST_FILE1, TEST_FILE2);
99 
100 	err = renamex_np(TEST_FILE1, TEST_FILE3_HL, RENAME_EXCL);
101 	saved_errno = errno;
102 	T_ASSERT_TRUE((err == -1 && saved_errno == EEXIST),
103 	    "Renaming with RENAME_EXCL from source: %s to hardlink target: %s",
104 	    TEST_FILE1, TEST_FILE3_HL);
105 
106 	if (case_sensitive_vol) {
107 		err = renamex_np(TEST_FILE1, TEST_FILE1, RENAME_EXCL);
108 		saved_errno = errno;
109 		T_ASSERT_TRUE((err == -1 && saved_errno == EEXIST),
110 		    "Renaming with RENAME_EXCL from source: %s to target: %s",
111 		    TEST_FILE1, TEST_FILE1);
112 	} else {
113 		T_ASSERT_POSIX_SUCCESS(renamex_np(TEST_FILE1, TEST_FILE1, RENAME_EXCL),
114 		    "Renaming with RENAME_EXCL from source: %s to target: %s",
115 		    TEST_FILE1, TEST_FILE1);
116 	}
117 
118 	T_ASSERT_POSIX_SUCCESS(renamex_np(TEST_FILE1, TEST_FILE1_UC, RENAME_EXCL),
119 	    "Renaming with RENAME_EXCL from source: %s to target: %s",
120 	    TEST_FILE1, TEST_FILE1_UC);
121 }
122