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