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 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
251 continue;
252 }
253 subPath = IncludeTrailingPathDelimiter(path) + string(ptr->d_name);
254 if (ptr->d_type == DT_DIR) {
255 if (!ForceRemoveDirectoryDeepFirst(subPath)) {
256 ret = false;
257 }
258 } else if (access(subPath.c_str(), F_OK) == 0) {
259 if (remove(subPath.c_str()) != 0) {
260 closedir(dir);
261 LOGE("remove failed, subPath = %{public}s, err:%{public}d",
262 GetAnonyString(subPath).c_str(), errno);
263 return false;
264 }
265 }
266 }
267 closedir(dir);
268
269 string currentPath = ExcludeTrailingPathDelimiter(path);
270 if (access(currentPath.c_str(), F_OK) == 0) {
271 if (remove(currentPath.c_str()) != 0) {
272 LOGE("remove failed, currentPath = %{public}s, err:%{public}d",
273 GetAnonyString(currentPath).c_str(), errno);
274 return false;
275 }
276 }
277
278 return ret && (access(path.c_str(), F_OK) != 0);
279 }
280
IsFile(const std::string & path)281 bool IsFile(const std::string &path)
282 {
283 if (path.empty()) {
284 return false;
285 }
286 struct stat buf = {};
287 if (stat(path.c_str(), &buf) != 0) {
288 LOGE("stat failed, errno = %{public}d", errno);
289 return false;
290 }
291 return S_ISREG(buf.st_mode);
292 }
293
IsFolder(const std::string & name)294 bool IsFolder(const std::string &name)
295 {
296 if (name.empty()) {
297 return false;
298 }
299 struct stat buf = {};
300 if (stat(name.c_str(), &buf) != 0) {
301 LOGE("stat failed, errno = %{public}d", errno);
302 return false;
303 }
304 return S_ISDIR(buf.st_mode);
305 }
306
GetFilePath(const std::string & name)307 std::vector<std::string> GetFilePath(const std::string &name)
308 {
309 std::vector<std::string> path;
310 if (!IsFolder(name)) {
311 path.emplace_back(name);
312 return path;
313 }
314 auto dir = opendir(name.data());
315 struct dirent *ent = nullptr;
316 if (dir) {
317 while ((ent = readdir(dir)) != nullptr) {
318 auto tmpPath = std::string(name).append("/").append(ent->d_name);
319 if (strcmp(ent->d_name, "..") == 0 || strcmp(ent->d_name, ".") == 0) {
320 continue;
321 } else if (IsFolder(tmpPath)) {
322 auto dirPath = GetFilePath(tmpPath);
323 path.insert(path.end(), dirPath.begin(), dirPath.end());
324 } else {
325 path.emplace_back(tmpPath);
326 }
327 }
328 closedir(dir);
329 }
330 return path;
331 }
332
ChangeOwnerRecursive(const std::string & path,uid_t uid,gid_t gid)333 int32_t ChangeOwnerRecursive(const std::string &path, uid_t uid, gid_t gid)
334 {
335 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), &closedir);
336 if (dir == nullptr) {
337 LOGE("Directory is null");
338 return -1;
339 }
340
341 struct dirent *entry = nullptr;
342 while ((entry = readdir(dir.get())) != nullptr) {
343 if (entry->d_type == DT_DIR) {
344 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
345 continue;
346 }
347 std::string subPath = path + "/" + entry->d_name;
348 if (chown(subPath.c_str(), uid, gid) == -1) {
349 LOGE("Change owner recursive failed");
350 return -1;
351 }
352 return ChangeOwnerRecursive(subPath, uid, gid);
353 } else {
354 std::string filePath = path + "/" + entry->d_name;
355 if (chown(filePath.c_str(), uid, gid) == -1) {
356 LOGE("Change owner recursive failed");
357 return -1;
358 }
359 }
360 }
361 return 0;
362 }
363
IsInt32(const nlohmann::json & jsonObj,const std::string & key)364 bool IsInt32(const nlohmann::json &jsonObj, const std::string &key)
365 {
366 bool res = jsonObj.contains(key) && jsonObj[key].is_number_integer() && jsonObj[key] >= INT32_MIN &&
367 jsonObj[key] <= INT32_MAX;
368 if (!res) {
369 LOGE("the key %{public}s in jsonObj is invalid.", key.c_str());
370 }
371 return res;
372 }
373 } // namespace Utils
374 } // namespace DistributedFile
375 } // namespace Storage
376 } // namespace OHOS