1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <dirent.h>
16 #include <fcntl.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <errno.h>
22 #include "test.h"
23 #define BUFFER_SIZE 1024
24 #define RENAME_ZERO 0
25 
26 static int g_error = 0;
27 static char g_dirPath[] = "/data/local/tmp";
28 static char g_oldPath[] = "/data/local/tmp/renameat2_test.txt";
29 static char g_oldName[] = "renameat2_test.txt";
30 static char g_oldMsg[] = "renameat2";
31 static char g_newPath[] = "/data/local/tmp/newrenameat2_test.txt";
32 static char g_newName[] = "newrenameat2_test.txt";
33 static char g_newMsg[] = "newrenameat2";
34 
WriteFile(char *path, char *msg)35 static void WriteFile(char *path, char *msg)
36 {
37     FILE *file = fopen(path, "w+");
38     if (file == NULL) {
39         g_error++;
40         return;
41     }
42     size_t len = strlen(msg);
43     size_t n = fwrite(msg, sizeof(char), len, file);
44     if (fclose(file)) {
45         g_error++;
46         return;
47     }
48     if (n != len) {
49         g_error++;
50         return;
51     }
52 }
53 
ReadFile(char *path, size_t len, char *buf)54 static void ReadFile(char *path, size_t len, char *buf)
55 {
56     FILE *file = fopen(path, "r");
57     if (file == NULL) {
58         g_error++;
59         return;
60     }
61     size_t n = fread(buf, sizeof(char), len, file);
62     if (fclose(file)) {
63         g_error++;
64         return;
65     }
66     if (n != len) {
67         g_error++;
68         return;
69     }
70 }
71 
CompareFileString(char *path, size_t readCount, char *compareString)72 static void CompareFileString(char *path, size_t readCount, char *compareString)
73 {
74     char buf[BUFFER_SIZE] = {0};
75     ReadFile(path, readCount, buf);
76     if (strcmp(compareString, buf)) {
77         g_error++;
78     }
79 }
80 
RemoveFilenull81 static void RemoveFile()
82 {
83     if (access(g_oldPath, F_OK) == 0) {
84         if (remove(g_oldPath)) {
85             printf("information: file removed fail\n");
86         }
87     }
88     if (access(g_newPath, F_OK) == 0) {
89         if (remove(g_newPath)) {
90             printf("information: file removed fail\n");
91         }
92     }
93 }
94 
RenameNoReplaceTest(int oldFolder, int newFolder)95 static void RenameNoReplaceTest(int oldFolder, int newFolder)
96 {
97     WriteFile(g_oldPath, g_oldMsg);
98     if (renameat2(oldFolder, g_oldName, newFolder, g_newName, RENAME_NOREPLACE) == -1) {
99         g_error++;
100         return;
101     }
102     if (access(g_oldPath, F_OK) == 0) {
103         g_error++;
104         return;
105     }
106     CompareFileString(g_newPath, strlen(g_oldMsg), g_oldMsg);
107     RemoveFile();
108 
109     WriteFile(g_oldPath, g_oldMsg);
110     WriteFile(g_newPath, g_newMsg);
111     if (renameat2(oldFolder, g_oldName, newFolder, g_newName, RENAME_NOREPLACE) == 0) {
112         g_error++;
113         return;
114     }
115     CompareFileString(g_oldPath, strlen(g_oldMsg), g_oldMsg);
116     CompareFileString(g_newPath, strlen(g_newMsg), g_newMsg);
117     RemoveFile();
118 
119     WriteFile(g_oldPath, g_oldMsg);
120     if (renameat2(AT_FDCWD, g_oldPath, AT_FDCWD, g_newPath, RENAME_NOREPLACE) == -1) {
121         g_error++;
122         return;
123     }
124     if (access(g_oldPath, F_OK) == 0) {
125         g_error++;
126         return;
127     }
128     CompareFileString(g_newPath, strlen(g_oldMsg), g_oldMsg);
129     RemoveFile();
130 
131     WriteFile(g_oldPath, g_oldMsg);
132     WriteFile(g_newPath, g_newMsg);
133     if (renameat2(AT_FDCWD, g_oldPath, AT_FDCWD, g_newPath, RENAME_NOREPLACE) == 0) {
134         g_error++;
135         return;
136     }
137     CompareFileString(g_oldPath, strlen(g_oldMsg), g_oldMsg);
138     CompareFileString(g_newPath, strlen(g_newMsg), g_newMsg);
139     RemoveFile();
140 }
141 
ZeroTest(int oldFolder, int newFolder)142 static void ZeroTest(int oldFolder, int newFolder)
143 {
144     WriteFile(g_oldPath, g_oldMsg);
145     if (renameat2(oldFolder, g_oldName, newFolder, g_newName, RENAME_ZERO) == -1) {
146         g_error++;
147         return;
148     }
149     if (access(g_oldPath, F_OK) == 0) {
150         g_error++;
151         return;
152     }
153     CompareFileString(g_newPath, strlen(g_oldMsg), g_oldMsg);
154     RemoveFile();
155 
156     WriteFile(g_oldPath, g_oldMsg);
157     WriteFile(g_newPath, g_newMsg);
158     if (renameat2(oldFolder, g_oldName, newFolder, g_newName, RENAME_ZERO) == -1) {
159         g_error++;
160         return;
161     }
162     if (access(g_oldPath, F_OK) == 0) {
163         g_error++;
164         return;
165     }
166     CompareFileString(g_newPath, strlen(g_oldMsg), g_oldMsg);
167     RemoveFile();
168 
169     WriteFile(g_oldPath, g_oldMsg);
170     if (renameat2(AT_FDCWD, g_oldPath, AT_FDCWD, g_newPath, RENAME_ZERO) == -1) {
171         g_error++;
172         return;
173     }
174     if (access(g_oldPath, F_OK) == 0) {
175         g_error++;
176         return;
177     }
178     CompareFileString(g_newPath, strlen(g_oldMsg), g_oldMsg);
179     RemoveFile();
180 
181     WriteFile(g_oldPath, g_oldMsg);
182     WriteFile(g_newPath, g_newMsg);
183     if (renameat2(AT_FDCWD, g_oldPath, AT_FDCWD, g_newPath, RENAME_ZERO) == -1) {
184         g_error++;
185         return;
186     }
187     if (access(g_oldPath, F_OK) == 0) {
188         g_error++;
189         return;
190     }
191     CompareFileString(g_newPath, strlen(g_oldMsg), g_oldMsg);
192     RemoveFile();
193 }
194 
RenameExchangeTest(int oldFolder, int newFolder)195 static void RenameExchangeTest(int oldFolder, int newFolder)
196 {
197     WriteFile(g_oldPath, g_oldMsg);
198     WriteFile(g_newPath, g_newMsg);
199     if (renameat2(oldFolder, g_oldName, newFolder, g_newName, RENAME_EXCHANGE) == -1) {
200         g_error++;
201         return;
202     }
203     CompareFileString(g_newPath, strlen(g_oldMsg), g_oldMsg);
204     CompareFileString(g_oldPath, strlen(g_newMsg), g_newMsg);
205     RemoveFile();
206 
207     WriteFile(g_oldPath, g_oldMsg);
208     WriteFile(g_newPath, g_newMsg);
209     if (renameat2(AT_FDCWD, g_oldPath, AT_FDCWD, g_newPath, RENAME_EXCHANGE) == -1) {
210         g_error++;
211         return;
212     }
213     CompareFileString(g_newPath, strlen(g_oldMsg), g_oldMsg);
214     CompareFileString(g_oldPath, strlen(g_newMsg), g_newMsg);
215     RemoveFile();
216 }
217 
CloseFolder(DIR *dir)218 static void CloseFolder(DIR *dir)
219 {
220     if (closedir(dir)) {
221         printf("information: close folder fail\n");
222     }
223 }
224 
main(void)225 int main(void)
226 {
227     DIR *dir = opendir(g_dirPath);
228     if (dir == NULL) {
229         t_error("%s open dir failed, errno: %d\n", __func__, errno);
230         return 1;
231     }
232     int dirFD = dirfd(dir);
233     if (dirFD == -1) {
234         t_error("%s open dirfd failed, errno: %d\n", __func__, errno);
235         return 1;
236     }
237 
238     g_error = 0;
239     RenameNoReplaceTest(dirFD, dirFD);
240     if (g_error) {
241         t_error("%s renameat2 failed,flags: RENAME_NOREPLACE\n", __func__);
242         RemoveFile();
243         CloseFolder(dir);
244         return 1;
245     }
246 
247     g_error = 0;
248     ZeroTest(dirFD, dirFD);
249     if (g_error) {
250         t_error("%s renameat2 failed,flags: zero\n", __func__);
251         RemoveFile();
252         CloseFolder(dir);
253         return 1;
254     }
255 
256     g_error = 0;
257     RenameExchangeTest(dirFD, dirFD);
258     if (g_error) {
259         t_error("%s renameat2 failed,flags: RENAME_EXCHANGE\n", __func__);
260         RemoveFile();
261         CloseFolder(dir);
262         return 1;
263     }
264     CloseFolder(dir);
265     return 0;
266 }