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