1 /*
2 * Copyright (c) 2015 Cedric Hnyda <chnyda@suse.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it would 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.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 /* Description:
20 * Calls renameat2(2) with the flag RENAME_EXCHANGE and check that
21 * the content was swapped
22 */
23
24 #define _GNU_SOURCE
25
26 #include "test.h"
27 #include "safe_macros.h"
28 #include "lapi/fcntl.h"
29 #include "renameat2.h"
30
31 #define TEST_DIR "test_dir/"
32 #define TEST_DIR2 "test_dir2/"
33
34 #define TEST_FILE "test_file"
35 #define TEST_FILE2 "test_file2"
36
37 char *TCID = "renameat202";
38
39 static int olddirfd;
40 static int newdirfd;
41 static int fd = -1;
42 static int cnt;
43
44 static const char content[] = "content";
45 static long fs_type;
46
47
48 int TST_TOTAL = 1;
49
50 static void setup(void);
51 static void cleanup(void);
52 static void renameat2_verify(void);
53
54
main(int ac,char ** av)55 int main(int ac, char **av)
56 {
57 int lc;
58
59 tst_parse_opts(ac, av, NULL, NULL);
60
61 setup();
62
63 for (lc = 0; TEST_LOOPING(lc); lc++) {
64
65 tst_count = 0;
66
67 TEST(renameat2(olddirfd, TEST_FILE,
68 newdirfd, TEST_FILE2, RENAME_EXCHANGE));
69
70 cnt++;
71
72 renameat2_verify();
73 }
74
75 cleanup();
76 tst_exit();
77 }
78
setup(void)79 static void setup(void)
80 {
81 if ((tst_kvercmp(3, 15, 0)) < 0) {
82 tst_brkm(TCONF, NULL,
83 "This test can only run on kernels that are 3.15. and higher");
84 }
85
86 tst_tmpdir();
87
88 fs_type = tst_fs_type(cleanup, ".");
89
90 SAFE_MKDIR(cleanup, TEST_DIR, 0700);
91 SAFE_MKDIR(cleanup, TEST_DIR2, 0700);
92
93 SAFE_TOUCH(cleanup, TEST_DIR TEST_FILE, 0600, NULL);
94 SAFE_TOUCH(cleanup, TEST_DIR2 TEST_FILE2, 0600, NULL);
95
96 olddirfd = SAFE_OPEN(cleanup, TEST_DIR, O_DIRECTORY);
97 newdirfd = SAFE_OPEN(cleanup, TEST_DIR2, O_DIRECTORY);
98
99 SAFE_FILE_PRINTF(cleanup, TEST_DIR TEST_FILE, "%s", content);
100
101 }
102
cleanup(void)103 static void cleanup(void)
104 {
105 if (olddirfd > 0 && close(olddirfd) < 0)
106 tst_resm(TWARN | TERRNO, "close olddirfd failed");
107
108 if (newdirfd > 0 && close(newdirfd) < 0)
109 tst_resm(TWARN | TERRNO, "close newdirfd failed");
110
111 if (fd > 0 && close(fd) < 0)
112 tst_resm(TWARN | TERRNO, "close fd failed");
113
114 tst_rmdir();
115
116 }
117
renameat2_verify(void)118 static void renameat2_verify(void)
119 {
120 char str[BUFSIZ] = { 0 };
121 struct stat st;
122 char *emptyfile;
123 char *contentfile;
124 int readn, data_len;
125
126 if (TEST_ERRNO == EINVAL && TST_BTRFS_MAGIC == fs_type) {
127 tst_brkm(TCONF, cleanup,
128 "RENAME_EXCHANGE flag is not implemeted on %s",
129 tst_fs_type_name(fs_type));
130 }
131
132 if (TEST_RETURN != 0) {
133 tst_resm(TFAIL | TTERRNO, "renameat2() failed unexpectedly");
134 return;
135 }
136
137 if (cnt % 2 == 1) {
138 emptyfile = TEST_DIR TEST_FILE;
139 contentfile = TEST_DIR2 TEST_FILE2;
140 } else {
141 emptyfile = TEST_DIR2 TEST_FILE2;
142 contentfile = TEST_DIR TEST_FILE;
143 }
144
145 fd = SAFE_OPEN(cleanup, contentfile, O_RDONLY);
146
147 SAFE_STAT(cleanup, emptyfile, &st);
148
149 readn = SAFE_READ(cleanup, 0, fd, str, BUFSIZ);
150
151 if (close(fd) < 0)
152 tst_brkm(TERRNO | TFAIL, cleanup, "close fd failed");
153 fd = 0;
154
155 data_len = sizeof(content) - 1;
156 if (readn != data_len) {
157 tst_resm(TFAIL, "Wrong number of bytes read after renameat2(). "
158 "Expect %d, got %d", data_len, readn);
159 return;
160 }
161 if (strncmp(content, str, data_len)) {
162 tst_resm(TFAIL, "File content changed after renameat2(). "
163 "Expect '%s', got '%s'", content, str);
164 return;
165 }
166 if (st.st_size) {
167 tst_resm(TFAIL, "emptyfile has non-zero file size");
168 return;
169 }
170 tst_resm(TPASS, "renameat2() test passed");
171 }
172