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 "file_util.h" 16 17#include <dirent.h> 18#include <fstream> 19#include <iostream> 20#include <sys/stat.h> 21#include <sys/types.h> 22#include <sys/xattr.h> 23#include <unistd.h> 24 25namespace OHOS { 26namespace HiviewDFX { 27namespace FileUtil { 28namespace { 29const char PATH_DELIMITER = '/'; 30constexpr mode_t FILE_PERM_600 = S_IRUSR | S_IWUSR; 31} 32bool IsFileExists(const std::string& file) 33{ 34 return access(file.c_str(), F_OK) == 0; 35} 36 37bool IsFile(const std::string& file) 38{ 39 struct stat statBuf {}; 40 return lstat(file.c_str(), &statBuf) == 0 ? S_ISREG(statBuf.st_mode) : false; 41} 42 43bool IsDirectory(const std::string& dir) 44{ 45 struct stat statBuf {}; 46 return lstat(dir.c_str(), &statBuf) == 0 ? S_ISDIR(statBuf.st_mode) : false; 47} 48 49bool RemoveFile(const std::string& file) 50{ 51 return !IsFileExists(file) || (remove(file.c_str()) == 0); 52} 53 54bool RemoveDirectory(const std::string& dir) 55{ 56 return !IsFileExists(dir) || (rmdir(dir.c_str()) == 0); 57} 58 59bool ForceCreateDirectory(const std::string& dir) 60{ 61 std::string::size_type index = 0; 62 do { 63 std::string subPath; 64 index = dir.find('/', index + 1); // (index + 1) means the next char traversed 65 if (index == std::string::npos) { 66 subPath = dir; 67 } else { 68 subPath = dir.substr(0, index); 69 } 70 71 if (!IsFileExists(subPath) && mkdir(subPath.c_str(), S_IRWXU) != 0) { 72 return false; 73 } 74 } while (index != std::string::npos); 75 return IsFileExists(dir); 76} 77 78bool ForceRemoveDirectory(const std::string& dir, bool isDeleteSelf) 79{ 80 if (IsFile(dir)) { 81 return RemoveFile(dir); 82 } else if (IsDirectory(dir)) { 83 DIR* dirPtr = opendir(dir.c_str()); 84 if (dirPtr == nullptr) { 85 return false; 86 } 87 struct dirent* dirInfo = nullptr; 88 while ((dirInfo = readdir(dirPtr)) != nullptr) { 89 // do not process the special dir 90 if (strcmp(dirInfo->d_name, ".") == 0 || strcmp(dirInfo->d_name, "..") == 0) { 91 continue; 92 } 93 std::string filePath = GetFilePathByDir(dir, dirInfo->d_name); 94 if (!ForceRemoveDirectory(filePath)) { 95 closedir(dirPtr); 96 return false; 97 } 98 } 99 closedir(dirPtr); 100 if (isDeleteSelf && !RemoveDirectory(dir)) { 101 return false; 102 } 103 } else { 104 return false; 105 } 106 return true; 107} 108 109void GetDirFiles(const std::string& dir, std::vector<std::string>& files) 110{ 111 DIR* dirPtr = opendir(dir.c_str()); 112 if (dirPtr == nullptr) { 113 return; 114 } 115 116 struct dirent* ent = nullptr; 117 while ((ent = readdir(dirPtr)) != nullptr) { 118 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { 119 continue; 120 } 121 std::string filePath = GetFilePathByDir(dir, ent->d_name); 122 if (IsFile(filePath)) { // do not process subdirectory 123 files.push_back(filePath); 124 } 125 } 126 closedir(dirPtr); 127} 128 129uint64_t GetDirSize(const std::string& dir) 130{ 131 std::vector<std::string> files; 132 GetDirFiles(dir, files); 133 uint64_t totalSize = 0; 134 struct stat statBuf {}; 135 for (auto& file : files) { 136 if (stat(file.c_str(), &statBuf) == 0) { 137 totalSize += static_cast<uint64_t>(statBuf.st_size); 138 } 139 } 140 return totalSize; 141} 142 143uint64_t GetFileSize(const std::string& file) 144{ 145 struct stat statBuf {}; 146 return stat(file.c_str(), &statBuf) == 0 ? static_cast<uint64_t>(statBuf.st_size) : 0; 147} 148 149bool ChangeMode(const std::string& file, const mode_t& mode) 150{ 151 return (chmod(file.c_str(), mode) == 0); 152} 153 154bool CreateFile(const std::string& file, const mode_t& mode) 155{ 156 if (IsFileExists(file)) { 157 return true; 158 } 159 std::ofstream fout(file); 160 if (!fout.is_open()) { 161 return false; 162 } 163 fout.flush(); 164 fout.close(); 165 return ChangeMode(file, mode); 166} 167 168bool SaveStringToFile(const std::string& file, const std::string& content, bool isTrunc) 169{ 170 if (content.empty()) { 171 return true; 172 } 173 174 if (!CreateFile(file, FILE_PERM_600)) { 175 return false; 176 } 177 std::ofstream os; 178 if (isTrunc) { 179 os.open(file.c_str(), std::ios::out | std::ios::trunc); 180 } else { 181 os.open(file.c_str(), std::ios::out | std::ios::app); 182 } 183 if (!os.is_open()) { 184 return false; 185 } 186 187 os.write(content.c_str(), content.length()); 188 if (os.fail()) { 189 os.close(); 190 return false; 191 } 192 os.close(); 193 return true; 194} 195 196std::string GetFilePathByDir(const std::string& dir, const std::string& fileName) 197{ 198 if (dir.empty()) { 199 return fileName; 200 } 201 std::string filePath = dir; 202 if (filePath.back() != '/') { 203 filePath.push_back(PATH_DELIMITER); 204 } 205 filePath.append(fileName); 206 return filePath; 207} 208 209bool LoadLinesFromFile(const std::string& filePath, std::vector<std::string>& lines) 210{ 211 std::ifstream file(filePath); 212 if (file.is_open()) { 213 std::string line; 214 while (std::getline(file, line)) { 215 lines.emplace_back(line); 216 } 217 file.close(); 218 return true; 219 } 220 return false; 221} 222 223bool SetDirXattr(const std::string& dir, const std::string& name, const std::string& value) 224{ 225 return setxattr(dir.c_str(), name.c_str(), value.c_str(), strlen(value.c_str()), 0) == 0; 226} 227} // namespace FileUtil 228} // namespace HiviewDFX 229} // namespace OHOS 230