• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include <errno.h>
17 #include <ftw.h>
18 #include <limits.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <dirent.h>
23 #include <pthread.h>
24 #include <sys/stat.h>
25 #include "functionalext.h"
26 
27 #define TEST_FD_LIMIT 128
28 #define TEST_FLAG_SIZE 4
29 #define TEST_DIGIT_TWO 2
30 #define TEST_PATH_DEPTH 5
31 #define TEST_NFTW_PATH "/data/local/tmp/nftwPath"
32 
33 pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
34 
nftw_callback(const char * pathname,const struct stat * sb,int flag,struct FTW * ftw)35 static int nftw_callback(const char *pathname, const struct stat *sb, int flag, struct FTW *ftw)
36 {
37     EXPECT_TRUE("nftw_callback", pathname != NULL);
38     EXPECT_TRUE("nftw_callback", sb != NULL);
39     if (flag == FTW_NS) {
40         struct stat st;
41         EXPECT_EQ("nftw_callback", stat(pathname, &st), -1);
42         return 0;
43     }
44 
45     if (S_ISDIR(sb->st_mode)) {
46         if (access(pathname, R_OK) == 0) {
47             EXPECT_TRUE("nftw_callback", flag == FTW_D || flag == FTW_DP);
48         } else {
49             EXPECT_EQ("nftw_callback", flag, FTW_DNR);
50         }
51     } else if (S_ISLNK(sb->st_mode)) {
52         EXPECT_TRUE("nftw_callback", flag == FTW_SL || flag == FTW_SLN);
53     } else {
54         EXPECT_EQ("nftw_callback", flag, FTW_F);
55     }
56     return 0;
57 }
58 
remove_directory(const char * path)59 void remove_directory(const char *path)
60 {
61     DIR *dir;
62     struct dirent *entry;
63     char filepath[PATH_MAX];
64 
65     if (!(dir = opendir(path))) {
66         return;
67     }
68 
69     while ((entry = readdir(dir)) != NULL) {
70         if (entry->d_type == DT_DIR) {
71             if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
72                 continue;
73             }
74 
75             int result = snprintf(filepath, sizeof(filepath), "%s/%s", path, entry->d_name);
76             if (result >= sizeof(filepath)) {
77                 t_error("%s error in snprintf! \n", __func__);
78             }
79             remove_directory(filepath);
80         } else {
81             int result = snprintf(filepath, sizeof(filepath), "%s/%s", path, entry->d_name);
82             if (result >= sizeof(filepath)) {
83                 t_error("%s error in snprintf! \n", __func__);
84             }
85             if (remove(filepath) == -1) {
86                 t_error("%s error in remove test nftw filepath! \n", __func__);
87             }
88         }
89     }
90 
91     closedir(dir);
92 
93     // Now we can remove the empty directory
94     if (rmdir(path) == -1) {
95         t_error("%s error in rmdir test nftw path! \n", __func__);
96     }
97 }
98 
nftw_build_testfile(const char * path)99 void nftw_build_testfile(const char *path)
100 {
101     // Create directory
102     if (mkdir(path, 0755) == -1) {
103         t_error("%s error in mkdir test nftw path! %s \n", __func__, path);
104         return;
105     }
106 
107     char file[PATH_MAX];
108     int result = snprintf(file, sizeof(file), "%s/normal_file.txt", path);
109     if (result >= sizeof(file)) {
110         t_error("%s error in snprintf! \n", __func__);
111     }
112     // Create plain file
113     int fd = open(file, O_WRONLY | O_CREAT, 0644);
114     if (fd == -1) {
115         t_error("%s error in open normal_file.txt! \n", __func__);
116         return;
117     }
118     close(fd);
119 
120     result = snprintf(file, sizeof(file), "%s/non-executable_file.txt", path);
121     if (result >= sizeof(file)) {
122         t_error("%s error in snprintf! \n", __func__);
123     }
124     // Create non-executable file
125     fd = open(file, O_WRONLY | O_CREAT, 0666);
126     if (fd == -1) {
127         t_error("%s error in open normal_file.txt! \n", __func__);
128         return;
129     }
130     close(fd);
131 
132     result = snprintf(file, sizeof(file), "%s/unauthorized_file.txt", path);
133     if (result >= sizeof(file)) {
134         t_error("%s error in snprintf! \n", __func__);
135     }
136     // Create unauthorized file
137     fd = open(file, O_WRONLY | O_CREAT, 0000);
138     if (fd == -1) {
139         t_error("%s error in open normal_file.txt! \n", __func__);
140         return;
141     }
142     close(fd);
143 
144     result = snprintf(file, sizeof(file), "%s/.hidden_file.txt", path);
145     if (result >= sizeof(file)) {
146         t_error("%s error in snprintf! \n", __func__);
147     }
148     // Create Hidden Files
149     fd = open(file, O_WRONLY | O_CREAT, 0644);
150     if (fd == -1) {
151         t_error("%s error in open hidden_file.txt! \n", __func__);
152         return;
153     }
154     close(fd);
155 
156     result = snprintf(file, sizeof(file), "%s/read_only_file.txt", path);
157     if (result >= sizeof(file)) {
158         t_error("%s error in snprintf! \n", __func__);
159     }
160     //Create Read-only files
161     fd = open(file, O_WRONLY | O_CREAT, 0444);
162     if (fd == -1) {
163         t_error("%s error in open read_only_file.txt! \n", __func__);
164         return;
165     }
166     close(fd);
167 
168     result = snprintf(file, sizeof(file), "%s/symlink_to_normal_file", path);
169     if (result >= sizeof(file)) {
170         t_error("%s error in snprintf! \n", __func__);
171     }
172     // Create Symbolic links
173     if (symlink("normal_file.txt", file) == -1) {
174         t_error("%s error in open symlink_to_normal_file.txt! \n", __func__);
175         return;
176     }
177 }
178 
nftw_build_testDir()179 void nftw_build_testDir()
180 {
181     nftw_build_testfile(TEST_NFTW_PATH);
182     char path[PATH_MAX];
183     int result = snprintf(path, sizeof(path), "%s", TEST_NFTW_PATH);
184     if (result >= sizeof(path)) {
185         t_error("%s error in snprintf! \n", __func__);
186     }
187     for (int i = 0 ; i < TEST_PATH_DEPTH ; i++) {
188         result = snprintf(path, sizeof(path), "%s/data", path);
189         if (result >= sizeof(path)) {
190             t_error("%s error in snprintf! \n", __func__);
191         }
192         nftw_build_testfile(path);
193     }
194 }
195 
196 /**
197  * @tc.name      : nftw_0100
198  * @tc.desc      : Traverse directory /data
199  * @tc.level     : Level 0
200  */
nftw_0100(void)201 void nftw_0100(void)
202 {
203     int flag[TEST_FLAG_SIZE] = {FTW_PHYS, FTW_MOUNT, FTW_CHDIR, FTW_DEPTH};
204     int i;
205     for (i = 0; i < TEST_FLAG_SIZE; i++) {
206         int ret = nftw(TEST_NFTW_PATH, nftw_callback, TEST_FD_LIMIT, flag[i]);
207         EXPECT_EQ("nftw_0100", ret, 0);
208     }
209 }
210 
211 /**
212  * @tc.name      : nftw_0200
213  * @tc.desc      : Traverse directory /data, but the maximum number of file descriptors is 0
214  * @tc.level     : Level 0
215  */
nftw_0200(void)216 void nftw_0200(void)
217 {
218     int ret = nftw(TEST_NFTW_PATH, nftw_callback, 0, FTW_PHYS);
219     EXPECT_EQ("nftw_0200", ret, 0);
220 }
221 
222 /**
223  * @tc.name      : nftw_0300
224  * @tc.desc      : The file path length exceeds PATH_MAX, traverse the directory
225  * @tc.level     : Level 2
226  */
nftw_0300(void)227 void nftw_0300(void)
228 {
229     char path[PATH_MAX * TEST_DIGIT_TWO];
230     memset(path, 'a', sizeof(path));
231     path[PATH_MAX * TEST_DIGIT_TWO - 1] = 0;
232     int ret = nftw(path, nftw_callback, TEST_FD_LIMIT, FTW_PHYS);
233     EXPECT_EQ("nftw_0300", ret, -1);
234     EXPECT_EQ("nftw_0300", errno, ENAMETOOLONG);
235 }
236 
main(void)237 int main(void)
238 {
239     pthread_mutex_lock(&g_mutex);
240     nftw_build_testDir();
241     nftw_0100();
242     nftw_0200();
243     nftw_0300();
244     remove_directory(TEST_NFTW_PATH);
245     pthread_mutex_unlock(&g_mutex);
246     return t_status;
247 }