• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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