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
29 namespace OHOS {
30 namespace Storage {
31 namespace DistributedFile {
32 namespace Utils {
33 using namespace std;
34
35 namespace {
36 static const uint32_t STAT_MODE_DIR = 0771;
37 }
38
GetAnonyString(const std::string &value)39 std::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
SysEventWrite(string &uid)63 void 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
SysEventFileParse(int64_t maxTime)78 void 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
RadarDotsReportOpenSession(struct RadarInfo &info)88 void 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
RadarDotsOpenSession(const std::string funcName, const std::string &sessionName, const std::string &peerSssionName, int32_t errCode, StageRes state)122 void 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
RadarDotsReportSendFile(struct RadarInfo &info)135 void 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
RadarDotsSendFile(const std::string funcName, const std::string &sessionName, const std::string &peerSssionName, int32_t errCode, StageRes state)169 void 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
ForceCreateDirectory(const string &path, function<void(const string &)> onSubDirCreated)182 void 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
ForceCreateDirectory(const string &path)204 void ForceCreateDirectory(const string &path)
205 {
206 ForceCreateDirectory(path, nullptr);
207 }
208
ForceCreateDirectory(const string &path, mode_t mode)209 void 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
ForceCreateDirectory(const string &path, mode_t mode, uid_t uid, gid_t gid)218 void 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
ForceRemoveDirectory(const string &path)227 void ForceRemoveDirectory(const string &path)
228 {
229 if (!OHOS::ForceRemoveDirectory(path)) {
230 LOGE("failed to forcibly remove directory, errno:%{public}d", errno);
231 }
232 }
233
ForceRemoveDirectoryDeepFirst(const string& path)234 bool 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
IsFile(const std::string &path)282 bool 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
IsFolder(const std::string &name)295 bool 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
GetFilePath(const std::string &name)308 std::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
ChangeOwnerRecursive(const std::string &path, uid_t uid, gid_t gid)334 int32_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
IsInt32(const nlohmann::json &jsonObj, const std::string &key)365 bool 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