1570af302Sopenharmony_ci/** 2570af302Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3570af302Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4570af302Sopenharmony_ci * you may not use this file except in compliance with the License. 5570af302Sopenharmony_ci * You may obtain a copy of the License at 6570af302Sopenharmony_ci * 7570af302Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8570af302Sopenharmony_ci * 9570af302Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10570af302Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11570af302Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12570af302Sopenharmony_ci * See the License for the specific language governing permissions and 13570af302Sopenharmony_ci * limitations under the License. 14570af302Sopenharmony_ci */ 15570af302Sopenharmony_ci 16570af302Sopenharmony_ci#include <errno.h> 17570af302Sopenharmony_ci#include <ftw.h> 18570af302Sopenharmony_ci#include <limits.h> 19570af302Sopenharmony_ci#include <fcntl.h> 20570af302Sopenharmony_ci#include <unistd.h> 21570af302Sopenharmony_ci#include <stdlib.h> 22570af302Sopenharmony_ci#include <dirent.h> 23570af302Sopenharmony_ci#include <pthread.h> 24570af302Sopenharmony_ci#include <sys/stat.h> 25570af302Sopenharmony_ci#include "functionalext.h" 26570af302Sopenharmony_ci 27570af302Sopenharmony_ci#define TEST_FD_LIMIT 128 28570af302Sopenharmony_ci#define TEST_FLAG_SIZE 4 29570af302Sopenharmony_ci#define TEST_DIGIT_TWO 2 30570af302Sopenharmony_ci#define TEST_PATH_DEPTH 5 31570af302Sopenharmony_ci#define TEST_NFTW_PATH "/data/local/tmp/nftwPath" 32570af302Sopenharmony_ci 33570af302Sopenharmony_cipthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; 34570af302Sopenharmony_ci 35570af302Sopenharmony_cistatic int nftw_callback(const char *pathname, const struct stat *sb, int flag, struct FTW *ftw) 36570af302Sopenharmony_ci{ 37570af302Sopenharmony_ci EXPECT_TRUE("nftw_callback", pathname != NULL); 38570af302Sopenharmony_ci EXPECT_TRUE("nftw_callback", sb != NULL); 39570af302Sopenharmony_ci if (flag == FTW_NS) { 40570af302Sopenharmony_ci struct stat st; 41570af302Sopenharmony_ci EXPECT_EQ("nftw_callback", stat(pathname, &st), -1); 42570af302Sopenharmony_ci return 0; 43570af302Sopenharmony_ci } 44570af302Sopenharmony_ci 45570af302Sopenharmony_ci if (S_ISDIR(sb->st_mode)) { 46570af302Sopenharmony_ci if (access(pathname, R_OK) == 0) { 47570af302Sopenharmony_ci EXPECT_TRUE("nftw_callback", flag == FTW_D || flag == FTW_DP); 48570af302Sopenharmony_ci } else { 49570af302Sopenharmony_ci EXPECT_EQ("nftw_callback", flag, FTW_DNR); 50570af302Sopenharmony_ci } 51570af302Sopenharmony_ci } else if (S_ISLNK(sb->st_mode)) { 52570af302Sopenharmony_ci EXPECT_TRUE("nftw_callback", flag == FTW_SL || flag == FTW_SLN); 53570af302Sopenharmony_ci } else { 54570af302Sopenharmony_ci EXPECT_EQ("nftw_callback", flag, FTW_F); 55570af302Sopenharmony_ci } 56570af302Sopenharmony_ci return 0; 57570af302Sopenharmony_ci} 58570af302Sopenharmony_ci 59570af302Sopenharmony_civoid remove_directory(const char *path) 60570af302Sopenharmony_ci{ 61570af302Sopenharmony_ci DIR *dir; 62570af302Sopenharmony_ci struct dirent *entry; 63570af302Sopenharmony_ci char filepath[PATH_MAX]; 64570af302Sopenharmony_ci 65570af302Sopenharmony_ci if (!(dir = opendir(path))) { 66570af302Sopenharmony_ci return; 67570af302Sopenharmony_ci } 68570af302Sopenharmony_ci 69570af302Sopenharmony_ci while ((entry = readdir(dir)) != NULL) { 70570af302Sopenharmony_ci if (entry->d_type == DT_DIR) { 71570af302Sopenharmony_ci if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { 72570af302Sopenharmony_ci continue; 73570af302Sopenharmony_ci } 74570af302Sopenharmony_ci 75570af302Sopenharmony_ci int result = snprintf(filepath, sizeof(filepath), "%s/%s", path, entry->d_name); 76570af302Sopenharmony_ci if (result >= sizeof(filepath)) { 77570af302Sopenharmony_ci t_error("%s error in snprintf! \n", __func__); 78570af302Sopenharmony_ci } 79570af302Sopenharmony_ci remove_directory(filepath); 80570af302Sopenharmony_ci } else { 81570af302Sopenharmony_ci int result = snprintf(filepath, sizeof(filepath), "%s/%s", path, entry->d_name); 82570af302Sopenharmony_ci if (result >= sizeof(filepath)) { 83570af302Sopenharmony_ci t_error("%s error in snprintf! \n", __func__); 84570af302Sopenharmony_ci } 85570af302Sopenharmony_ci if (remove(filepath) == -1) { 86570af302Sopenharmony_ci t_error("%s error in remove test nftw filepath! \n", __func__); 87570af302Sopenharmony_ci } 88570af302Sopenharmony_ci } 89570af302Sopenharmony_ci } 90570af302Sopenharmony_ci 91570af302Sopenharmony_ci closedir(dir); 92570af302Sopenharmony_ci 93570af302Sopenharmony_ci // Now we can remove the empty directory 94570af302Sopenharmony_ci if (rmdir(path) == -1) { 95570af302Sopenharmony_ci t_error("%s error in rmdir test nftw path! \n", __func__); 96570af302Sopenharmony_ci } 97570af302Sopenharmony_ci} 98570af302Sopenharmony_ci 99570af302Sopenharmony_civoid nftw_build_testfile(const char *path) 100570af302Sopenharmony_ci{ 101570af302Sopenharmony_ci // Create directory 102570af302Sopenharmony_ci if (mkdir(path, 0755) == -1) { 103570af302Sopenharmony_ci t_error("%s error in mkdir test nftw path! %s \n", __func__, path); 104570af302Sopenharmony_ci return; 105570af302Sopenharmony_ci } 106570af302Sopenharmony_ci 107570af302Sopenharmony_ci char file[PATH_MAX]; 108570af302Sopenharmony_ci int result = snprintf(file, sizeof(file), "%s/normal_file.txt", path); 109570af302Sopenharmony_ci if (result >= sizeof(file)) { 110570af302Sopenharmony_ci t_error("%s error in snprintf! \n", __func__); 111570af302Sopenharmony_ci } 112570af302Sopenharmony_ci // Create plain file 113570af302Sopenharmony_ci int fd = open(file, O_WRONLY | O_CREAT, 0644); 114570af302Sopenharmony_ci if (fd == -1) { 115570af302Sopenharmony_ci t_error("%s error in open normal_file.txt! \n", __func__); 116570af302Sopenharmony_ci return; 117570af302Sopenharmony_ci } 118570af302Sopenharmony_ci close(fd); 119570af302Sopenharmony_ci 120570af302Sopenharmony_ci result = snprintf(file, sizeof(file), "%s/non-executable_file.txt", path); 121570af302Sopenharmony_ci if (result >= sizeof(file)) { 122570af302Sopenharmony_ci t_error("%s error in snprintf! \n", __func__); 123570af302Sopenharmony_ci } 124570af302Sopenharmony_ci // Create non-executable file 125570af302Sopenharmony_ci fd = open(file, O_WRONLY | O_CREAT, 0666); 126570af302Sopenharmony_ci if (fd == -1) { 127570af302Sopenharmony_ci t_error("%s error in open normal_file.txt! \n", __func__); 128570af302Sopenharmony_ci return; 129570af302Sopenharmony_ci } 130570af302Sopenharmony_ci close(fd); 131570af302Sopenharmony_ci 132570af302Sopenharmony_ci result = snprintf(file, sizeof(file), "%s/unauthorized_file.txt", path); 133570af302Sopenharmony_ci if (result >= sizeof(file)) { 134570af302Sopenharmony_ci t_error("%s error in snprintf! \n", __func__); 135570af302Sopenharmony_ci } 136570af302Sopenharmony_ci // Create unauthorized file 137570af302Sopenharmony_ci fd = open(file, O_WRONLY | O_CREAT, 0000); 138570af302Sopenharmony_ci if (fd == -1) { 139570af302Sopenharmony_ci t_error("%s error in open normal_file.txt! \n", __func__); 140570af302Sopenharmony_ci return; 141570af302Sopenharmony_ci } 142570af302Sopenharmony_ci close(fd); 143570af302Sopenharmony_ci 144570af302Sopenharmony_ci result = snprintf(file, sizeof(file), "%s/.hidden_file.txt", path); 145570af302Sopenharmony_ci if (result >= sizeof(file)) { 146570af302Sopenharmony_ci t_error("%s error in snprintf! \n", __func__); 147570af302Sopenharmony_ci } 148570af302Sopenharmony_ci // Create Hidden Files 149570af302Sopenharmony_ci fd = open(file, O_WRONLY | O_CREAT, 0644); 150570af302Sopenharmony_ci if (fd == -1) { 151570af302Sopenharmony_ci t_error("%s error in open hidden_file.txt! \n", __func__); 152570af302Sopenharmony_ci return; 153570af302Sopenharmony_ci } 154570af302Sopenharmony_ci close(fd); 155570af302Sopenharmony_ci 156570af302Sopenharmony_ci result = snprintf(file, sizeof(file), "%s/read_only_file.txt", path); 157570af302Sopenharmony_ci if (result >= sizeof(file)) { 158570af302Sopenharmony_ci t_error("%s error in snprintf! \n", __func__); 159570af302Sopenharmony_ci } 160570af302Sopenharmony_ci //Create Read-only files 161570af302Sopenharmony_ci fd = open(file, O_WRONLY | O_CREAT, 0444); 162570af302Sopenharmony_ci if (fd == -1) { 163570af302Sopenharmony_ci t_error("%s error in open read_only_file.txt! \n", __func__); 164570af302Sopenharmony_ci return; 165570af302Sopenharmony_ci } 166570af302Sopenharmony_ci close(fd); 167570af302Sopenharmony_ci 168570af302Sopenharmony_ci result = snprintf(file, sizeof(file), "%s/symlink_to_normal_file", path); 169570af302Sopenharmony_ci if (result >= sizeof(file)) { 170570af302Sopenharmony_ci t_error("%s error in snprintf! \n", __func__); 171570af302Sopenharmony_ci } 172570af302Sopenharmony_ci // Create Symbolic links 173570af302Sopenharmony_ci if (symlink("normal_file.txt", file) == -1) { 174570af302Sopenharmony_ci t_error("%s error in open symlink_to_normal_file.txt! \n", __func__); 175570af302Sopenharmony_ci return; 176570af302Sopenharmony_ci } 177570af302Sopenharmony_ci} 178570af302Sopenharmony_ci 179570af302Sopenharmony_civoid nftw_build_testDir() 180570af302Sopenharmony_ci{ 181570af302Sopenharmony_ci nftw_build_testfile(TEST_NFTW_PATH); 182570af302Sopenharmony_ci char path[PATH_MAX]; 183570af302Sopenharmony_ci int result = snprintf(path, sizeof(path), "%s", TEST_NFTW_PATH); 184570af302Sopenharmony_ci if (result >= sizeof(path)) { 185570af302Sopenharmony_ci t_error("%s error in snprintf! \n", __func__); 186570af302Sopenharmony_ci } 187570af302Sopenharmony_ci for (int i = 0 ; i < TEST_PATH_DEPTH ; i++) { 188570af302Sopenharmony_ci result = snprintf(path, sizeof(path), "%s/data", path); 189570af302Sopenharmony_ci if (result >= sizeof(path)) { 190570af302Sopenharmony_ci t_error("%s error in snprintf! \n", __func__); 191570af302Sopenharmony_ci } 192570af302Sopenharmony_ci nftw_build_testfile(path); 193570af302Sopenharmony_ci } 194570af302Sopenharmony_ci} 195570af302Sopenharmony_ci 196570af302Sopenharmony_ci/** 197570af302Sopenharmony_ci * @tc.name : nftw_0100 198570af302Sopenharmony_ci * @tc.desc : Traverse directory /data 199570af302Sopenharmony_ci * @tc.level : Level 0 200570af302Sopenharmony_ci */ 201570af302Sopenharmony_civoid nftw_0100(void) 202570af302Sopenharmony_ci{ 203570af302Sopenharmony_ci int flag[TEST_FLAG_SIZE] = {FTW_PHYS, FTW_MOUNT, FTW_CHDIR, FTW_DEPTH}; 204570af302Sopenharmony_ci int i; 205570af302Sopenharmony_ci for (i = 0; i < TEST_FLAG_SIZE; i++) { 206570af302Sopenharmony_ci int ret = nftw(TEST_NFTW_PATH, nftw_callback, TEST_FD_LIMIT, flag[i]); 207570af302Sopenharmony_ci EXPECT_EQ("nftw_0100", ret, 0); 208570af302Sopenharmony_ci } 209570af302Sopenharmony_ci} 210570af302Sopenharmony_ci 211570af302Sopenharmony_ci/** 212570af302Sopenharmony_ci * @tc.name : nftw_0200 213570af302Sopenharmony_ci * @tc.desc : Traverse directory /data, but the maximum number of file descriptors is 0 214570af302Sopenharmony_ci * @tc.level : Level 0 215570af302Sopenharmony_ci */ 216570af302Sopenharmony_civoid nftw_0200(void) 217570af302Sopenharmony_ci{ 218570af302Sopenharmony_ci int ret = nftw(TEST_NFTW_PATH, nftw_callback, 0, FTW_PHYS); 219570af302Sopenharmony_ci EXPECT_EQ("nftw_0200", ret, 0); 220570af302Sopenharmony_ci} 221570af302Sopenharmony_ci 222570af302Sopenharmony_ci/** 223570af302Sopenharmony_ci * @tc.name : nftw_0300 224570af302Sopenharmony_ci * @tc.desc : The file path length exceeds PATH_MAX, traverse the directory 225570af302Sopenharmony_ci * @tc.level : Level 2 226570af302Sopenharmony_ci */ 227570af302Sopenharmony_civoid nftw_0300(void) 228570af302Sopenharmony_ci{ 229570af302Sopenharmony_ci char path[PATH_MAX * TEST_DIGIT_TWO]; 230570af302Sopenharmony_ci memset(path, 'a', sizeof(path)); 231570af302Sopenharmony_ci path[PATH_MAX * TEST_DIGIT_TWO - 1] = 0; 232570af302Sopenharmony_ci int ret = nftw(path, nftw_callback, TEST_FD_LIMIT, FTW_PHYS); 233570af302Sopenharmony_ci EXPECT_EQ("nftw_0300", ret, -1); 234570af302Sopenharmony_ci EXPECT_EQ("nftw_0300", errno, ENAMETOOLONG); 235570af302Sopenharmony_ci} 236570af302Sopenharmony_ci 237570af302Sopenharmony_ciint main(void) 238570af302Sopenharmony_ci{ 239570af302Sopenharmony_ci pthread_mutex_lock(&g_mutex); 240570af302Sopenharmony_ci nftw_build_testDir(); 241570af302Sopenharmony_ci nftw_0100(); 242570af302Sopenharmony_ci nftw_0200(); 243570af302Sopenharmony_ci nftw_0300(); 244570af302Sopenharmony_ci remove_directory(TEST_NFTW_PATH); 245570af302Sopenharmony_ci pthread_mutex_unlock(&g_mutex); 246570af302Sopenharmony_ci return t_status; 247570af302Sopenharmony_ci}