1/* 2 * Copyright (c) 2021 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 "utils_directory.h" 17 18#include <cstring> 19#include <dirent.h> 20#include <sys/types.h> 21#include <system_error> 22#include <unistd.h> 23 24#include "dfs_error.h" 25#include "directory_ex.h" 26#include "hisysevent.h" 27#include "utils_log.h" 28 29namespace OHOS { 30namespace Storage { 31namespace DistributedFile { 32namespace Utils { 33using namespace std; 34 35namespace { 36 static const uint32_t STAT_MODE_DIR = 0771; 37} 38 39std::string GetAnonyString(const std::string &value) 40{ 41 constexpr size_t shortIdLength = 20; 42 constexpr size_t plaintextLength = 4; 43 constexpr size_t minIdLength = 3; 44 std::string res; 45 std::string tmpStr("******"); 46 size_t strLen = value.length(); 47 if (strLen < minIdLength) { 48 return tmpStr; 49 } 50 51 if (strLen <= shortIdLength) { 52 res += value[0]; 53 res += tmpStr; 54 res += value[strLen - 1]; 55 } else { 56 res.append(value, 0, plaintextLength); 57 res += tmpStr; 58 res.append(value, strLen - plaintextLength, plaintextLength); 59 } 60 return res; 61} 62 63void SysEventWrite(string &uid) 64{ 65 if (uid.empty()) { 66 LOGE("uid is empty."); 67 return; 68 } 69 int32_t ret = DEMO_SYNC_SYS_EVENT("PERMISSION_EXCEPTION", 70 HiviewDFX::HiSysEvent::EventType::SECURITY, 71 "CALLER_UID", uid, 72 "PERMISSION_NAME", "account"); 73 if (ret != ERR_OK) { 74 LOGE("report PERMISSION_EXCEPTION error %{public}d", ret); 75 } 76} 77 78void SysEventFileParse(int64_t maxTime) 79{ 80 int32_t ret = DEMO_SYNC_SYS_EVENT("INDEX_FILE_PARSE", 81 HiviewDFX::HiSysEvent::EventType::STATISTIC, 82 "MAX_TIME", maxTime); 83 if (ret != ERR_OK) { 84 LOGE("report INDEX_FILE_PARSE error %{public}d", ret); 85 } 86} 87 88void RadarDotsReportOpenSession(struct RadarInfo &info) 89{ 90 int32_t res = ERR_OK; 91 if (info.state == StageRes::STAGE_SUCCESS) { 92 res = DEMO_SYNC_SYS_EVENT(DISTRIBUTEDFILE_CONNECT_BEHAVIOR, 93 HiviewDFX::HiSysEvent::EventType::BEHAVIOR, 94 "ORG_PKG", ORGPKGNAME, 95 "TO_CALL_PKG", SOFTBUSNAME, 96 "FUNC", info.funcName, 97 "BIZ_SCENE", static_cast<int32_t>(BizScene::DFS_CONNECT), 98 "BIZ_STAGE", static_cast<int32_t>(BizStage::DFS_OPEN_SESSION), 99 "BIZ_STATE", static_cast<int32_t>(BizState::BIZ_STATE_START), 100 "STAGE_RES", static_cast<int32_t>(StageRes::STAGE_SUCCESS), 101 "LOCAL_SESS_NAME", info.localSessionName, 102 "PEER_SESS_NAME", info.peerSessionName); 103 } else { 104 res = DEMO_SYNC_SYS_EVENT(DISTRIBUTEDFILE_CONNECT_BEHAVIOR, 105 HiviewDFX::HiSysEvent::EventType::BEHAVIOR, 106 "ORG_PKG", ORGPKGNAME, 107 "TO_CALL_PKG", SOFTBUSNAME, 108 "FUNC", info.funcName, 109 "BIZ_SCENE", static_cast<int32_t>(BizScene::DFS_CONNECT), 110 "BIZ_STAGE", static_cast<int32_t>(BizStage::DFS_OPEN_SESSION), 111 "BIZ_STATE", static_cast<int32_t>(BizState::BIZ_STATE_END), 112 "STAGE_RES", static_cast<int32_t>(StageRes::STAGE_FAIL), 113 "LOCAL_SESS_NAME", info.localSessionName, 114 "PEER_SESS_NAME", info.peerSessionName, 115 "ERROR_CODE", std::abs(info.errCode)); 116 } 117 if (res != ERR_OK) { 118 LOGE("report RadarDotsReportOpenSession error %{public}d", res); 119 } 120} 121 122void RadarDotsOpenSession(const std::string funcName, const std::string &sessionName, 123 const std::string &peerSssionName, int32_t errCode, StageRes state) 124{ 125 struct RadarInfo info = { 126 .funcName = funcName, 127 .localSessionName = sessionName, 128 .peerSessionName = peerSssionName, 129 .errCode = errCode, 130 .state = state, 131 }; 132 RadarDotsReportOpenSession(info); 133} 134 135void RadarDotsReportSendFile(struct RadarInfo &info) 136{ 137 int32_t res = ERR_OK; 138 if (info.state == StageRes::STAGE_SUCCESS) { 139 res = DEMO_SYNC_SYS_EVENT(DISTRIBUTEDFILE_CONNECT_BEHAVIOR, 140 HiviewDFX::HiSysEvent::EventType::BEHAVIOR, 141 "ORG_PKG", ORGPKGNAME, 142 "TO_CALL_PKG", SOFTBUSNAME, 143 "FUNC", info.funcName, 144 "BIZ_SCENE", static_cast<int32_t>(BizScene::DFS_CONNECT), 145 "BIZ_STAGE", static_cast<int32_t>(BizStage::DFS_SENDFILE), 146 "BIZ_STATE", static_cast<int32_t>(BizState::BIZ_STATE_END), 147 "STAGE_RES", static_cast<int32_t>(StageRes::STAGE_SUCCESS), 148 "LOCAL_SESS_NAME", info.localSessionName, 149 "PEER_SESS_NAME", info.peerSessionName); 150 } else { 151 res = DEMO_SYNC_SYS_EVENT(DISTRIBUTEDFILE_CONNECT_BEHAVIOR, 152 HiviewDFX::HiSysEvent::EventType::BEHAVIOR, 153 "ORG_PKG", ORGPKGNAME, 154 "TO_CALL_PKG", SOFTBUSNAME, 155 "FUNC", info.funcName, 156 "BIZ_SCENE", static_cast<int32_t>(BizScene::DFS_CONNECT), 157 "BIZ_STAGE", static_cast<int32_t>(BizStage::DFS_SENDFILE), 158 "BIZ_STATE", static_cast<int32_t>(BizState::BIZ_STATE_END), 159 "STAGE_RES", static_cast<int32_t>(StageRes::STAGE_FAIL), 160 "LOCAL_SESS_NAME", info.localSessionName, 161 "PEER_SESS_NAME", info.peerSessionName, 162 "ERROR_CODE", std::abs(info.errCode)); 163 } 164 if (res != ERR_OK) { 165 LOGE("report RadarDotsReportSendFile error %{public}d", res); 166 } 167} 168 169void RadarDotsSendFile(const std::string funcName, const std::string &sessionName, 170 const std::string &peerSssionName, int32_t errCode, StageRes state) 171{ 172 struct RadarInfo info = { 173 .funcName = funcName, 174 .localSessionName = sessionName, 175 .peerSessionName = peerSssionName, 176 .errCode = errCode, 177 .state = state, 178 }; 179 RadarDotsReportSendFile(info); 180} 181 182void ForceCreateDirectory(const string &path, function<void(const string &)> onSubDirCreated) 183{ 184 string::size_type index = 0; 185 do { 186 string subPath; 187 index = path.find('/', index + 1); 188 if (index == string::npos) { 189 subPath = path; 190 } else { 191 subPath = path.substr(0, index); 192 } 193 194 if (access(subPath.c_str(), F_OK) != 0) { 195 if (mkdir(subPath.c_str(), STAT_MODE_DIR) != 0) { 196 LOGE("failed to mkdir, errno:%{public}d", errno); 197 return; 198 } 199 onSubDirCreated(subPath); 200 } 201 } while (index != string::npos); 202} 203 204void ForceCreateDirectory(const string &path) 205{ 206 ForceCreateDirectory(path, nullptr); 207} 208 209void ForceCreateDirectory(const string &path, mode_t mode) 210{ 211 ForceCreateDirectory(path, [mode](const string &subPath) { 212 if (chmod(subPath.c_str(), mode) == -1) { 213 LOGE("failed to chmod, errno:%{public}d", errno); 214 } 215 }); 216} 217 218void ForceCreateDirectory(const string &path, mode_t mode, uid_t uid, gid_t gid) 219{ 220 ForceCreateDirectory(path, [mode, uid, gid](const string &subPath) { 221 if (chmod(subPath.c_str(), mode) == -1 || chown(subPath.c_str(), uid, gid) == -1) { 222 LOGE("failed to chmod or chown, errno:%{public}d", errno); 223 } 224 }); 225} 226 227void ForceRemoveDirectory(const string &path) 228{ 229 if (!OHOS::ForceRemoveDirectory(path)) { 230 LOGE("failed to forcibly remove directory, errno:%{public}d", errno); 231 } 232} 233 234bool ForceRemoveDirectoryDeepFirst(const string& path) 235{ 236 string subPath; 237 bool ret = true; 238 DIR *dir = opendir(path.c_str()); 239 if (dir == nullptr) { 240 LOGE("opendir failed, path = %{public}s, err:%{public}d", GetAnonyString(path).c_str(), errno); 241 return false; 242 } 243 244 while (true) { 245 struct dirent *ptr = readdir(dir); 246 if (ptr == nullptr) { 247 break; 248 } 249 250 // current dir OR parent dir 251 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) { 252 continue; 253 } 254 subPath = IncludeTrailingPathDelimiter(path) + string(ptr->d_name); 255 if (ptr->d_type == DT_DIR) { 256 if (!ForceRemoveDirectoryDeepFirst(subPath)) { 257 ret = false; 258 } 259 } else if (access(subPath.c_str(), F_OK) == 0) { 260 if (remove(subPath.c_str()) != 0) { 261 closedir(dir); 262 LOGE("remove failed, subPath = %{public}s, err:%{public}d", 263 GetAnonyString(subPath).c_str(), errno); 264 return false; 265 } 266 } 267 } 268 closedir(dir); 269 270 string currentPath = ExcludeTrailingPathDelimiter(path); 271 if (access(currentPath.c_str(), F_OK) == 0) { 272 if (remove(currentPath.c_str()) != 0) { 273 LOGE("remove failed, currentPath = %{public}s, err:%{public}d", 274 GetAnonyString(currentPath).c_str(), errno); 275 return false; 276 } 277 } 278 279 return ret && (access(path.c_str(), F_OK) != 0); 280} 281 282bool IsFile(const std::string &path) 283{ 284 if (path.empty()) { 285 return false; 286 } 287 struct stat buf = {}; 288 if (stat(path.c_str(), &buf) != 0) { 289 LOGE("stat failed, errno = %{public}d", errno); 290 return false; 291 } 292 return S_ISREG(buf.st_mode); 293} 294 295bool IsFolder(const std::string &name) 296{ 297 if (name.empty()) { 298 return false; 299 } 300 struct stat buf = {}; 301 if (stat(name.c_str(), &buf) != 0) { 302 LOGE("stat failed, errno = %{public}d", errno); 303 return false; 304 } 305 return S_ISDIR(buf.st_mode); 306} 307 308std::vector<std::string> GetFilePath(const std::string &name) 309{ 310 std::vector<std::string> path; 311 if (!IsFolder(name)) { 312 path.emplace_back(name); 313 return path; 314 } 315 auto dir = opendir(name.data()); 316 struct dirent *ent = nullptr; 317 if (dir) { 318 while ((ent = readdir(dir)) != nullptr) { 319 auto tmpPath = std::string(name).append("/").append(ent->d_name); 320 if (strcmp(ent->d_name, "..") == 0 || strcmp(ent->d_name, ".") == 0) { 321 continue; 322 } else if (IsFolder(tmpPath)) { 323 auto dirPath = GetFilePath(tmpPath); 324 path.insert(path.end(), dirPath.begin(), dirPath.end()); 325 } else { 326 path.emplace_back(tmpPath); 327 } 328 } 329 closedir(dir); 330 } 331 return path; 332} 333 334int32_t ChangeOwnerRecursive(const std::string &path, uid_t uid, gid_t gid) 335{ 336 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), &closedir); 337 if (dir == nullptr) { 338 LOGE("Directory is null"); 339 return -1; 340 } 341 342 struct dirent *entry = nullptr; 343 while ((entry = readdir(dir.get())) != nullptr) { 344 if (entry->d_type == DT_DIR) { 345 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { 346 continue; 347 } 348 std::string subPath = path + "/" + entry->d_name; 349 if (chown(subPath.c_str(), uid, gid) == -1) { 350 LOGE("Change owner recursive failed"); 351 return -1; 352 } 353 return ChangeOwnerRecursive(subPath, uid, gid); 354 } else { 355 std::string filePath = path + "/" + entry->d_name; 356 if (chown(filePath.c_str(), uid, gid) == -1) { 357 LOGE("Change owner recursive failed"); 358 return -1; 359 } 360 } 361 } 362 return 0; 363} 364 365bool IsInt32(const nlohmann::json &jsonObj, const std::string &key) 366{ 367 bool res = jsonObj.contains(key) && jsonObj[key].is_number_integer() && jsonObj[key] >= INT32_MIN && 368 jsonObj[key] <= INT32_MAX; 369 if (!res) { 370 LOGE("the key %{public}s in jsonObj is invalid.", key.c_str()); 371 } 372 return res; 373} 374} // namespace Utils 375} // namespace DistributedFile 376} // namespace Storage 377} // namespace OHOS