1 /*
2 * Copyright (c) 2024 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 "hidebug_util.h"
17
18 #include <cstring>
19 #include <ctime>
20 #include <fcntl.h>
21 #include <thread>
22 #include <vector>
23
24 #include <sys/stat.h>
25 #include <sys/xattr.h>
26 #include <unistd.h>
27
28 #include "application_context.h"
29 #include "directory_ex.h"
30 #include "file_ex.h"
31 #include "parameters.h"
32 #include "storage_acl.h"
33
34 #include "hilog/log.h"
35
36 namespace OHOS {
37 namespace HiviewDFX {
38 namespace {
39
40 #undef LOG_DOMAIN
41 #define LOG_DOMAIN 0xD002D0A
42 #undef LOG_TAG
43 #define LOG_TAG "CommonUtil"
44
GetNanoSecondsTimestamp(clockid_t clockId)45 int64_t GetNanoSecondsTimestamp(clockid_t clockId)
46 {
47 struct timespec times{};
48 if (clock_gettime(clockId, ×) == -1) {
49 return -1;
50 }
51 constexpr int64_t secondToNanosecond = 1 * 1000 * 1000 * 1000;
52 return times.tv_sec * secondToNanosecond + times.tv_nsec;
53 }
54 }
55
GetElapsedNanoSecondsSinceBoot()56 int64_t GetElapsedNanoSecondsSinceBoot()
57 {
58 return GetNanoSecondsTimestamp(CLOCK_BOOTTIME);
59 }
60
GetRealNanoSecondsTimestamp()61 int64_t GetRealNanoSecondsTimestamp()
62 {
63 return GetNanoSecondsTimestamp(CLOCK_REALTIME);
64 }
65
GetProcessDir(DirectoryType type)66 std::string GetProcessDir(DirectoryType type)
67 {
68 auto context = OHOS::AbilityRuntime::Context::GetApplicationContext();
69 if (!context) {
70 return "";
71 }
72 switch (type) {
73 case DirectoryType::CACHE:
74 return context->GetCacheDir();
75 case DirectoryType::FILE:
76 return context->GetFilesDir();
77 default:
78 return "";
79 }
80 }
81
SplitStr(const std::string & origin,char delimiter,const std::function<bool (std::string &)> & filter)82 std::vector<std::string> SplitStr(const std::string& origin, char delimiter,
83 const std::function<bool(std::string&)>& filter)
84 {
85 std::vector<std::string> tokens;
86 size_t index = 0;
87 for (size_t i = 0; i <= origin.length(); ++i) {
88 if (i == origin.length() || origin[i] == delimiter) {
89 std::string token = origin.substr(index, i - index);
90 if (!filter || filter(token)) {
91 tokens.emplace_back(std::move(token));
92 }
93 index = i + 1;
94 }
95 }
96 return tokens;
97 }
98
GetXAttr(const std::string & fileName,const std::string & key,std::string & value,size_t maxLength)99 bool GetXAttr(const std::string& fileName, const std::string& key, std::string& value, size_t maxLength)
100 {
101 std::string readValue = std::string(maxLength + 1, '\0');
102 if (getxattr(fileName.c_str(), key.c_str(), readValue.data(), maxLength) == -1) {
103 HILOG_ERROR(LOG_CORE, "failed to getxattr %{public}s from %{public}s because of %{public}s.",
104 key.c_str(), fileName.c_str(), strerror(errno));
105 return false;
106 }
107 value = readValue.c_str();
108 return true;
109 }
110
SetXAttr(const std::string & fileName,const std::string & key,const std::string & value)111 bool SetXAttr(const std::string& fileName, const std::string& key, const std::string& value)
112 {
113 if (setxattr(fileName.c_str(), key.c_str(), value.c_str(), value.size(), 0) != 0) {
114 HILOG_ERROR(LOG_CORE, "failed to setxattr %{public}s to %{public}s because of %{public}s.",
115 key.c_str(), fileName.c_str(), strerror(errno));
116 return false;
117 }
118 return true;
119 }
120
IsLegalPath(const std::string & path)121 bool IsLegalPath(const std::string& path)
122 {
123 return !path.empty() && path.find("./") == std::string::npos;
124 }
125
GetFileSize(const std::string & path)126 uint64_t GetFileSize(const std::string& path)
127 {
128 struct stat statBuf{};
129 if (stat(path.c_str(), &statBuf) == 0) {
130 return statBuf.st_size;
131 }
132 return 0;
133 }
134
CreateFile(const std::string & path)135 bool CreateFile(const std::string &path)
136 {
137 if (access(path.c_str(), F_OK) == 0) {
138 return access(path.c_str(), W_OK) == 0;
139 }
140 const mode_t defaultMode = S_IRUSR | S_IWUSR | S_IRGRP; // -rw-r-----
141 int fd = creat(path.c_str(), defaultMode);
142 if (fd == -1) {
143 HILOG_ERROR(LOG_CORE, "file create failed, errno = %{public}d", errno);
144 return false;
145 }
146 close(fd);
147 return true;
148 }
149
CreateDirectory(const std::string & path,unsigned mode)150 bool CreateDirectory(const std::string &path, unsigned mode)
151 {
152 std::vector<std::string> subPaths = SplitStr(path, '/', [](std::string& subPath) {
153 return !subPath.empty();
154 });
155 std::string currentPath;
156 for (const auto& subPath : subPaths) {
157 currentPath += "/" + subPath;
158 if (mkdir(currentPath.c_str(), mode) != 0 && errno != EEXIST) {
159 HILOG_ERROR(LOG_CORE, "directory %{public}s create failed, errno = %{public}d", currentPath.c_str(), errno);
160 return false;
161 }
162 }
163 return true;
164 }
165
OpenFile(const std::string & path,const std::string & mode)166 std::unique_ptr<SmartFile> SmartFile::OpenFile(const std::string& path, const std::string& mode)
167 {
168 if (!IsLegalPath(path)) {
169 HILOG_ERROR(LOG_CORE, "illegal file path %{public}s .", path.c_str());
170 return nullptr;
171 }
172 auto file = fopen(path.c_str(), mode.c_str());
173 if (file == nullptr) {
174 HILOG_ERROR(LOG_CORE, "can not open file %{public}s for %{public}s because of %{public}s.", path.c_str(),
175 mode.c_str(), strerror(errno));
176 return nullptr;
177 }
178 return std::unique_ptr<SmartFile>(new (std::nothrow) SmartFile(file));
179 }
180
~SmartFile()181 SmartFile::~SmartFile()
182 {
183 if (fclose(file_) != 0) {
184 HILOG_ERROR(LOG_CORE, "failed close file because of %{public}s.", strerror(errno));
185 }
186 }
187
Write(const void * __restrict dataPtr,size_t itemSize,size_t dataNum)188 bool SmartFile::Write(const void *__restrict dataPtr, size_t itemSize, size_t dataNum)
189 {
190 errno = 0;
191 if (fwrite(dataPtr, itemSize, dataNum, file_) != dataNum) {
192 HILOG_ERROR(LOG_CORE, "failed to write file because of %{public}s.", strerror(errno));
193 return false;
194 }
195 return true;
196 }
197
Read(void * __restrict dataPtr,size_t itemSize,size_t dataNum)198 size_t SmartFile::Read(void *__restrict dataPtr, size_t itemSize, size_t dataNum)
199 {
200 return fread(dataPtr, itemSize, dataNum, file_);
201 }
202
IsBetaVersion()203 bool IsBetaVersion()
204 {
205 return OHOS::system::GetParameter("const.logsystem.versiontype", "") == "beta";
206 }
207
IsDebuggableHap()208 bool IsDebuggableHap()
209 {
210 const char* debuggableEnv = getenv("HAP_DEBUGGABLE");
211 return debuggableEnv != nullptr && strcmp(debuggableEnv, "true") == 0;
212 }
213
IsDeveloperOptionsEnabled()214 bool IsDeveloperOptionsEnabled()
215 {
216 return OHOS::system::GetBoolParameter("const.security.developermode.state", false);
217 }
218
CheckVersionType(const std::string & type,const std::string & key)219 bool CheckVersionType(const std::string& type, const std::string& key)
220 {
221 auto versionType = OHOS::system::GetParameter(key, "unknown");
222 return (versionType.find(type) != std::string::npos);
223 }
224
CreateResourceLimitDir()225 bool CreateResourceLimitDir()
226 {
227 constexpr mode_t defaultLogDirMode = 0770;
228 const std::string resourceLimitDir = "/data/storage/el2/log/resourcelimit/";
229 if (!OHOS::FileExists(resourceLimitDir)) {
230 OHOS::ForceCreateDirectory(resourceLimitDir);
231 OHOS::ChangeModeDirectory(resourceLimitDir, defaultLogDirMode);
232 }
233 if (OHOS::StorageDaemon::AclSetAccess(resourceLimitDir, "g:1201:rwx") != 0) {
234 HILOG_ERROR(LOG_CORE, "CreateSanBoxDir Failed to AclSetAccess");
235 return false;
236 }
237 return true;
238 }
239 }
240 }
241