1 /*
2 * Copyright (c) 2023-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 "common_utils.h"
17
18 #include <cinttypes>
19 #include <unistd.h>
20 #include <cstdio>
21 #include <fstream>
22 #include <fcntl.h>
23 #include <sstream>
24 #include <sys/utsname.h>
25
26 #include "common_define.h"
27 #include "hilog/log.h"
28 #include "parameters.h"
29 #include "securec.h"
30
31 namespace OHOS {
32 namespace HiviewDFX {
33 namespace Hitrace {
34 #ifdef LOG_DOMAIN
35 #undef LOG_DOMAIN
36 #define LOG_DOMAIN 0xD002D33
37 #endif
38 #ifdef LOG_TAG
39 #undef LOG_TAG
40 #define LOG_TAG "HitraceUtils"
41 #endif
42 namespace {
43 const std::string CPUFREQ_PREFIX = "/sys/devices/system/cpu/cpu";
44 const std::string CPUFREQ_AFTERFIX = "/cpufreq/scaling_cur_freq";
45 }
46
CanonicalizeSpecPath(const char * src)47 std::string CanonicalizeSpecPath(const char* src)
48 {
49 if (src == nullptr || strlen(src) >= PATH_MAX) {
50 HILOG_ERROR(LOG_CORE, "CanonicalizeSpecPath: %{pubilc}s failed.", src);
51 return "";
52 }
53 char resolvedPath[PATH_MAX] = { 0 };
54
55 if (access(src, F_OK) == 0) {
56 if (realpath(src, resolvedPath) == nullptr) {
57 HILOG_ERROR(LOG_CORE, "CanonicalizeSpecPath: realpath %{pubilc}s failed.", src);
58 return "";
59 }
60 } else {
61 std::string fileName(src);
62 if (fileName.find("..") == std::string::npos) {
63 if (sprintf_s(resolvedPath, PATH_MAX, "%s", src) == -1) {
64 HILOG_ERROR(LOG_CORE, "CanonicalizeSpecPath: sprintf_s %{pubilc}s failed.", src);
65 return "";
66 }
67 } else {
68 HILOG_ERROR(LOG_CORE, "CanonicalizeSpecPath: find .. src failed.");
69 return "";
70 }
71 }
72
73 std::string res(resolvedPath);
74 return res;
75 }
76
MarkClockSync(const std::string & traceRootPath)77 bool MarkClockSync(const std::string& traceRootPath)
78 {
79 constexpr unsigned int bufferSize = 128;
80 char buffer[bufferSize] = { 0 };
81 std::string resolvedPath = CanonicalizeSpecPath((traceRootPath + TRACE_MARKER_NODE).c_str());
82 int fd = open(resolvedPath.c_str(), O_WRONLY);
83 if (fd == -1) {
84 HILOG_ERROR(LOG_CORE, "MarkClockSync: oepn %{public}s fail, errno(%{public}d)", resolvedPath.c_str(), errno);
85 return false;
86 }
87
88 // write realtime_ts
89 struct timespec rts = {0, 0};
90 if (clock_gettime(CLOCK_REALTIME, &rts) == -1) {
91 HILOG_ERROR(LOG_CORE, "MarkClockSync: get realtime error, errno(%{public}d)", errno);
92 close(fd);
93 return false;
94 }
95 constexpr unsigned int nanoSeconds = 1000000000; // seconds converted to nanoseconds
96 constexpr unsigned int nanoToMill = 1000000; // millisecond converted to nanoseconds
97 int len = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1,
98 "trace_event_clock_sync: realtime_ts=%" PRId64 "\n",
99 static_cast<int64_t>((rts.tv_sec * nanoSeconds + rts.tv_nsec) / nanoToMill));
100 if (len < 0) {
101 HILOG_ERROR(LOG_CORE, "MarkClockSync: entering realtime_ts into buffer error, errno(%{public}d)", errno);
102 close(fd);
103 return false;
104 }
105
106 if (write(fd, buffer, len) < 0) {
107 HILOG_ERROR(LOG_CORE, "MarkClockSync: writing realtime error, errno(%{public}d)", errno);
108 }
109
110 // write parent_ts
111 struct timespec mts = {0, 0};
112 if (clock_gettime(CLOCK_MONOTONIC, &mts) == -1) {
113 HILOG_ERROR(LOG_CORE, "MarkClockSync: get parent_ts error, errno(%{public}d)", errno);
114 close(fd);
115 return false;
116 }
117 constexpr float nanoToSecond = 1000000000.0f; // consistent with the ftrace timestamp format
118 len = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "trace_event_clock_sync: parent_ts=%f\n",
119 static_cast<float>(((static_cast<float>(mts.tv_sec)) * nanoSeconds + mts.tv_nsec) / nanoToSecond));
120 if (len < 0) {
121 HILOG_ERROR(LOG_CORE, "MarkClockSync: entering parent_ts into buffer error, errno(%{public}d)", errno);
122 close(fd);
123 return false;
124 }
125 if (write(fd, buffer, len) < 0) {
126 HILOG_ERROR(LOG_CORE, "MarkClockSync: writing parent_ts error, errno(%{public}d)", errno);
127 }
128 close(fd);
129 return true;
130 }
131
IsNumber(const std::string & str)132 bool IsNumber(const std::string& str)
133 {
134 if (str.empty()) {
135 return false;
136 }
137 for (auto c : str) {
138 if (!isdigit(c)) {
139 return false;
140 }
141 }
142 return true;
143 }
144
GetCpuProcessors()145 int GetCpuProcessors()
146 {
147 int processors = 0;
148 processors = sysconf(_SC_NPROCESSORS_CONF);
149 return (processors == 0) ? 1 : processors;
150 }
151
ReadCurrentCpuFrequencies(std::string & freqs)152 void ReadCurrentCpuFrequencies(std::string& freqs)
153 {
154 int cpuNum = GetCpuProcessors();
155 std::ifstream file;
156 std::string line;
157 for (int i = 0; i < cpuNum; ++i) {
158 std::string freq = "0";
159 std::string cpuFreqPath = CPUFREQ_PREFIX + std::to_string(i) + CPUFREQ_AFTERFIX;
160 file.open(cpuFreqPath);
161 if (file.is_open()) {
162 if (std::getline(file, line)) {
163 std::istringstream iss(line);
164 iss >> freq;
165 }
166 file.close();
167 }
168 freqs += "cpu_id=" + std::to_string(i) + " state=" + freq;
169 if (i != cpuNum - 1) {
170 freqs += ",";
171 }
172 }
173 }
174
SetPropertyInner(const std::string & property,const std::string & value)175 bool SetPropertyInner(const std::string& property, const std::string& value)
176 {
177 bool result = OHOS::system::SetParameter(property, value);
178 if (!result) {
179 fprintf(stderr, "Error: Failed to set %s property.\n", property.c_str());
180 }
181 return result;
182 }
183
GetPropertyInner(const std::string & property,const std::string & value)184 std::string GetPropertyInner(const std::string& property, const std::string& value)
185 {
186 return OHOS::system::GetParameter(property, value);
187 }
188
IsHmKernel()189 bool IsHmKernel()
190 {
191 bool isHM = false;
192 utsname unameBuf;
193 if ((uname(&unameBuf)) == 0) {
194 std::string osRelease = unameBuf.release;
195 isHM = osRelease.find("HongMeng") != std::string::npos;
196 }
197 return isHM;
198 }
199
IsDeveloperMode()200 bool IsDeveloperMode()
201 {
202 return OHOS::system::GetBoolParameter("const.security.developermode.state", false);
203 }
204
IsRootVersion()205 bool IsRootVersion()
206 {
207 return OHOS::system::GetBoolParameter("const.debuggable", false);
208 }
209
IsTraceMounted(std::string & traceRootPath)210 bool IsTraceMounted(std::string& traceRootPath)
211 {
212 if (access((DEBUGFS_TRACING_DIR + TRACE_MARKER_NODE).c_str(), F_OK) != -1) {
213 traceRootPath = DEBUGFS_TRACING_DIR;
214 return true;
215 }
216 if (access((TRACEFS_DIR + TRACE_MARKER_NODE).c_str(), F_OK) != -1) {
217 traceRootPath = TRACEFS_DIR;
218 return true;
219 }
220 return false;
221 }
222
GetFilePath(const std::string & fileName,const std::string & traceRootPath)223 std::string GetFilePath(const std::string& fileName, const std::string& traceRootPath)
224 {
225 return traceRootPath + fileName;
226 }
227
ReadFileInner(const std::string & filename)228 std::string ReadFileInner(const std::string& filename)
229 {
230 std::string resolvedPath = CanonicalizeSpecPath(filename.c_str());
231 std::ifstream fileIn(resolvedPath.c_str());
232 if (!fileIn.is_open()) {
233 HILOG_ERROR(LOG_CORE, "ReadFile: %{public}s open failed.", filename.c_str());
234 return "";
235 }
236 std::string str((std::istreambuf_iterator<char>(fileIn)), std::istreambuf_iterator<char>());
237 fileIn.close();
238 return str;
239 }
240
ReadFile(const std::string & filename,const std::string & traceRootPath)241 std::string ReadFile(const std::string& filename, const std::string& traceRootPath)
242 {
243 std::string filePath = GetFilePath(filename, traceRootPath);
244 return ReadFileInner(filePath);
245 }
246
IsTracingOn(const std::string & traceRootPath)247 bool IsTracingOn(const std::string& traceRootPath)
248 {
249 const std::string enable = "1";
250 if (ReadFile(TRACING_ON_NODE, traceRootPath).substr(0, enable.size()) == enable) {
251 HILOG_INFO(LOG_CORE, "tracing_on is 1.");
252 return true;
253 }
254 HILOG_INFO(LOG_CORE, "tracing_on is 0.");
255 return false;
256 }
257
StringToInt(const std::string & str,int & val)258 bool StringToInt(const std::string &str, int &val)
259 {
260 char *endPtr = nullptr;
261 errno = 0;
262 long num = std::strtol(str.c_str(), &endPtr, OHOS::HiviewDFX::Hitrace::DECIMAL_SCALE);
263 if (endPtr == str.c_str() || *endPtr != '\0' || errno != 0 || num > INT_MAX || num < INT_MIN) {
264 HILOG_ERROR(LOG_CORE, "get int failed, str: %s", str.c_str());
265 return false;
266 }
267 val = static_cast<int>(num);
268 return true;
269 }
270
StringToInt64(const std::string & str,int64_t & val)271 bool StringToInt64(const std::string &str, int64_t &val)
272 {
273 char *endPtr = nullptr;
274 errno = 0;
275 int64_t num = std::strtoll(str.c_str(), &endPtr, OHOS::HiviewDFX::Hitrace::DECIMAL_SCALE);
276 if (endPtr == str.c_str() || *endPtr != '\0' || errno != 0 || num > LLONG_MAX || num < LLONG_MIN) {
277 HILOG_ERROR(LOG_CORE, "get int64 failed, str: %s", str.c_str());
278 return false;
279 }
280 val = num;
281 return true;
282 }
283
StringToUint64(const std::string & str,uint64_t & val)284 bool StringToUint64(const std::string &str, uint64_t &val)
285 {
286 char *endPtr = nullptr;
287 errno = 0;
288 uint64_t num = std::strtoull(str.c_str(), &endPtr, OHOS::HiviewDFX::Hitrace::DECIMAL_SCALE);
289 if (endPtr == str.c_str() || *endPtr != '\0' || errno != 0 || num > ULLONG_MAX || str.c_str()[0] == '-') {
290 HILOG_ERROR(LOG_CORE, "get uint64 failed, str: %s", str.c_str());
291 return false;
292 }
293 val = num;
294 return true;
295 }
296
StringToDouble(const std::string & str,double & val)297 bool StringToDouble(const std::string &str, double &val)
298 {
299 char *endPtr = nullptr;
300 errno = 0;
301 double num = std::strtod(str.c_str(), &endPtr);
302 if (endPtr == str.c_str() || *endPtr != '\0' || errno != 0) {
303 HILOG_ERROR(LOG_CORE, "get double failed, str: %s", str.c_str());
304 return false;
305 }
306 val = num;
307 return true;
308 }
309 } // namespace Hitrace
310 } // namespace HiviewDFX
311 } // namespace OHOS
312