1 /*
2 * Copyright (c) 2021-2023 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 "dfx_util.h"
17
18 #include <cctype>
19 #include <climits>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <cstring>
23 #include <ctime>
24 #include <securec.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/time.h>
28 #include <fcntl.h>
29 #include <pthread.h>
30 #include <unistd.h>
31 #include <dirent.h>
32 #include "dfx_define.h"
33 #include "dfx_log.h"
34
35 #ifdef LOG_DOMAIN
36 #undef LOG_DOMAIN
37 #define LOG_DOMAIN 0xD002D11
38 #endif
39
40 #ifdef LOG_TAG
41 #undef LOG_TAG
42 #define LOG_TAG "DfxUtil"
43 #endif
44
45 namespace OHOS {
46 namespace HiviewDFX {
TrimAndDupStr(const std::string & source,std::string & str)47 bool TrimAndDupStr(const std::string &source, std::string &str)
48 {
49 if (source.empty()) {
50 return false;
51 }
52
53 const char *begin = source.data();
54 const char *end = begin + source.size();
55 if (begin == end) {
56 DFXLOG_ERROR("Source is empty");
57 return false;
58 }
59
60 while ((begin < end) && isspace(*begin)) {
61 begin++;
62 }
63
64 while ((begin < end) && isspace(*(end - 1))) {
65 end--;
66 }
67
68 if (begin == end) {
69 return false;
70 }
71
72 uint32_t maxStrLen = NAME_LEN;
73 uint32_t offset = static_cast<uint32_t>(end - begin);
74 if (maxStrLen > offset) {
75 maxStrLen = offset;
76 }
77
78 str.assign(begin, maxStrLen);
79 return true;
80 }
81
GetTimeMilliSeconds(void)82 uint64_t GetTimeMilliSeconds(void)
83 {
84 struct timespec ts;
85 (void)clock_gettime(CLOCK_REALTIME, &ts);
86 return ((uint64_t)ts.tv_sec * NUMBER_ONE_THOUSAND) + // 1000 : second to millisecond convert ratio
87 (((uint64_t)ts.tv_nsec) / NUMBER_ONE_MILLION); // 1000000 : nanosecond to millisecond convert ratio
88 }
89
GetCurrentTimeStr(uint64_t current)90 std::string GetCurrentTimeStr(uint64_t current)
91 {
92 time_t now = time(nullptr);
93 uint64_t millsecond = 0;
94 const uint64_t ratio = NUMBER_ONE_THOUSAND;
95 if (current > static_cast<uint64_t>(now)) {
96 millsecond = current % ratio;
97 now = static_cast<time_t>(current / ratio);
98 }
99
100 auto tm = std::localtime(&now);
101 char seconds[128] = {0}; // 128 : time buffer size
102 if (tm == nullptr || strftime(seconds, sizeof(seconds) - 1, "%Y-%m-%d %H:%M:%S", tm) == 0) {
103 return "invalid timestamp\n";
104 }
105
106 char millBuf[256] = {0}; // 256 : milliseconds buffer size
107 int ret = snprintf_s(millBuf, sizeof(millBuf), sizeof(millBuf) - 1,
108 "%s.%03u\n", seconds, millsecond);
109 if (ret <= 0) {
110 return "invalid timestamp\n";
111 }
112 return std::string(millBuf, strlen(millBuf));
113 }
114
ReadDirFiles(const std::string & path,std::vector<std::string> & files)115 bool ReadDirFiles(const std::string& path, std::vector<std::string>& files)
116 {
117 DIR *dir = opendir(path.c_str());
118 if (dir == nullptr) {
119 return false;
120 }
121
122 struct dirent *ent;
123 while ((ent = readdir(dir)) != nullptr) {
124 // current dir OR parent dir
125 if ((strcmp(ent->d_name, ".") == 0) || (strcmp(ent->d_name, "..") == 0)) {
126 continue;
127 }
128 files.emplace_back(std::string(ent->d_name));
129 }
130 (void)closedir(dir);
131 return (files.size() > 0);
132 }
133
ReadDirFilesByPid(const int & pid,std::vector<std::string> & files)134 bool ReadDirFilesByPid(const int& pid, std::vector<std::string>& files)
135 {
136 char path[PATH_LEN] = {0};
137 if (pid == getpid()) {
138 if (snprintf_s(path, sizeof(path), sizeof(path) - 1, PROC_SELF_TASK_PATH) <= 0) {
139 return false;
140 }
141 } else {
142 if (snprintf_s(path, sizeof(path), sizeof(path) - 1, "/proc/%d/task", pid) <= 0) {
143 return false;
144 }
145 }
146
147 char realPath[PATH_MAX];
148 if (!realpath(path, realPath)) {
149 return false;
150 }
151 return ReadDirFiles(realPath, files);
152 }
153
VerifyFilePath(const std::string & filePath,const std::vector<const std::string> & validPaths)154 bool VerifyFilePath(const std::string& filePath, const std::vector<const std::string>& validPaths)
155 {
156 if (validPaths.size() == 0) {
157 return true;
158 }
159
160 for (auto validPath : validPaths) {
161 if (filePath.find(validPath) == 0) {
162 return true;
163 }
164 }
165 return false;
166 }
167
GetFileSize(const int & fd)168 off_t GetFileSize(const int& fd)
169 {
170 off_t fileSize = 0;
171 if (fd >= 0) {
172 struct stat fileStat;
173 if (fstat(fd, &fileStat) == 0) {
174 fileSize = fileStat.st_size;
175 }
176 }
177 return fileSize;
178 }
179
GetStackRange(uintptr_t & stackBottom,uintptr_t & stackTop)180 int GetStackRange(uintptr_t& stackBottom, uintptr_t& stackTop)
181 {
182 pthread_attr_t tattr;
183 void *base = nullptr;
184 size_t size = 0;
185 pthread_getattr_np(pthread_self(), &tattr);
186 int ret = pthread_attr_getstack(&tattr, &base, &size);
187 stackBottom = reinterpret_cast<uintptr_t>(base);
188 stackTop = reinterpret_cast<uintptr_t>(base) + size;
189 return ret;
190 }
191 } // namespace HiviewDFX
192 } // namespace OHOS
193