• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "dfx_util.h"
17 
18 #if defined(is_mingw) && is_mingw
19 #include <memoryapi.h>
20 #include <windows.h>
21 #endif
22 #ifndef is_host
23 #include <cctype>
24 #include <climits>
25 #include <cstdio>
26 #include <cstdlib>
27 #include <cstring>
28 #include <ctime>
29 #include <securec.h>
30 #include <sys/types.h>
31 #include <sys/time.h>
32 #include <fcntl.h>
33 #include <pthread.h>
34 #include <unistd.h>
35 #include <dirent.h>
36 #endif
37 #include <sys/stat.h>
38 
39 #include "dfx_log.h"
40 
41 #ifdef LOG_DOMAIN
42 #undef LOG_DOMAIN
43 #define LOG_DOMAIN 0xD002D11
44 #endif
45 
46 #ifdef LOG_TAG
47 #undef LOG_TAG
48 #define LOG_TAG "DfxUtil"
49 #endif
50 
51 namespace OHOS {
52 namespace HiviewDFX {
53 #ifndef is_host
TrimAndDupStr(const std::string & source,std::string & str)54 bool TrimAndDupStr(const std::string &source, std::string &str)
55 {
56     if (source.empty()) {
57         return false;
58     }
59 
60     const char *begin = source.data();
61     const char *end = begin + source.size();
62     if (begin == end) {
63         DFXLOG_ERROR("%s", "Source is empty");
64         return false;
65     }
66 
67     while ((begin < end) && isspace(*begin)) {
68         begin++;
69     }
70 
71     while ((begin < end) && isspace(*(end - 1))) {
72         end--;
73     }
74 
75     if (begin == end) {
76         return false;
77     }
78 
79     uint32_t maxStrLen = NAME_BUF_LEN;
80     uint32_t offset = static_cast<uint32_t>(end - begin);
81     if (maxStrLen > offset) {
82         maxStrLen = offset;
83     }
84 
85     str.assign(begin, maxStrLen);
86     return true;
87 }
88 
GetTimeMilliSeconds(void)89 uint64_t GetTimeMilliSeconds(void)
90 {
91     struct timespec ts;
92     (void)clock_gettime(CLOCK_REALTIME, &ts);
93     return ((uint64_t)ts.tv_sec * NUMBER_ONE_THOUSAND) + // 1000 : second to millisecond convert ratio
94         (((uint64_t)ts.tv_nsec) / NUMBER_ONE_MILLION); // 1000000 : nanosecond to millisecond convert ratio
95 }
96 
GetCurrentTimeStr(uint64_t current)97 std::string GetCurrentTimeStr(uint64_t current)
98 {
99     time_t now = time(nullptr);
100     uint64_t millsecond = 0;
101     const uint64_t ratio = NUMBER_ONE_THOUSAND;
102     if (current > static_cast<uint64_t>(now)) {
103         millsecond = current % ratio;
104         now = static_cast<time_t>(current / ratio);
105     }
106 
107     auto tm = std::localtime(&now);
108     char seconds[128] = {0}; // 128 : time buffer size
109     if (tm == nullptr || strftime(seconds, sizeof(seconds) - 1, "%Y-%m-%d %H:%M:%S", tm) == 0) {
110         return "invalid timestamp\n";
111     }
112 
113     char millBuf[256] = {0}; // 256 : milliseconds buffer size
114     int ret = snprintf_s(millBuf, sizeof(millBuf), sizeof(millBuf) - 1,
115         "%s.%03u\n", seconds, millsecond);
116     if (ret <= 0) {
117         return "invalid timestamp\n";
118     }
119     return std::string(millBuf, strlen(millBuf));
120 }
121 
ReadDirFiles(const std::string & path,std::vector<std::string> & files)122 bool ReadDirFiles(const std::string& path, std::vector<std::string>& files)
123 {
124     DIR *dir = opendir(path.c_str());
125     if (dir == nullptr) {
126         return false;
127     }
128 
129     struct dirent *ent;
130     while ((ent = readdir(dir)) != nullptr) {
131         // current dir OR parent dir
132         if ((strcmp(ent->d_name, ".") == 0) || (strcmp(ent->d_name, "..") == 0)) {
133             continue;
134         }
135         files.emplace_back(std::string(ent->d_name));
136     }
137     (void)closedir(dir);
138     return (files.size() > 0);
139 }
140 
ReadDirFilesByPid(const int & pid,std::vector<std::string> & files)141 bool ReadDirFilesByPid(const int& pid, std::vector<std::string>& files)
142 {
143     char path[PATH_LEN] = {0};
144 #if is_ohos
145     if (pid == getprocpid()) {
146 #else
147     if (pid == getpid()) {
148 #endif
149         if (snprintf_s(path, sizeof(path), sizeof(path) - 1, PROC_SELF_TASK_PATH) <= 0) {
150             return false;
151         }
152     } else {
153         if (snprintf_s(path, sizeof(path), sizeof(path) - 1, "/proc/%d/task", pid) <= 0) {
154             return false;
155         }
156     }
157 
158     char realPath[PATH_MAX];
159     if (!realpath(path, realPath)) {
160         return false;
161     }
162     return ReadDirFiles(realPath, files);
163 }
164 
165 bool VerifyFilePath(const std::string& filePath, const std::vector<const std::string>& validPaths)
166 {
167     if (validPaths.size() == 0) {
168         return true;
169     }
170 
171     for (auto validPath : validPaths) {
172         if (filePath.find(validPath) == 0) {
173             return true;
174         }
175     }
176     return false;
177 }
178 #endif
179 
180 off_t GetFileSize(const int& fd)
181 {
182     off_t fileSize = 0;
183     if (fd >= 0) {
184         struct stat fileStat;
185         if (fstat(fd, &fileStat) == 0) {
186             fileSize = fileStat.st_size;
187         }
188     }
189     return fileSize;
190 }
191 
192 bool ReadFdToString(int fd, std::string& content)
193 {
194     content.clear();
195     struct stat sb;
196     if (fstat(fd, &sb) != -1 && sb.st_size > 0) {
197         content.reserve(sb.st_size);
198     }
199 
200     char buf[BUFSIZ] __attribute__((__uninitialized__));
201     ssize_t n;
202     while ((n = OHOS_TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
203         content.append(buf, n);
204     }
205     return (n == 0);
206 }
207 }   // namespace HiviewDFX
208 }   // namespace OHOS
209 
210 // this will also used for libunwinder head (out of namespace)
211 #if defined(is_mingw) && is_mingw
GetLastErrorString()212 std::string GetLastErrorString()
213 {
214     LPVOID lpMsgBuf;
215     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
216                       FORMAT_MESSAGE_IGNORE_INSERTS,
217                   NULL, GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, NULL);
218     std::string error((LPTSTR)lpMsgBuf);
219     LocalFree(lpMsgBuf);
220     return error;
221 }
222 
mmap(void * addr,size_t length,int prot,int flags,int fd,size_t offset)223 void *mmap(void *addr, size_t length, int prot, int flags, int fd, size_t offset)
224 {
225     HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
226     if (FileHandle == INVALID_HANDLE_VALUE) {
227         return MMAP_FAILED;
228     }
229 
230     LOGD("fd is %d", fd);
231 
232     HANDLE FileMappingHandle = ::CreateFileMappingW(FileHandle, 0, PAGE_READONLY, 0, 0, 0);
233     if (FileMappingHandle == nullptr) {
234         LOGE("CreateFileMappingW %zu Failed with %ld:%s", length, GetLastError(), GetLastErrorString().c_str());
235         return MMAP_FAILED;
236     }
237 
238     void *mapAddr = ::MapViewOfFile(FileMappingHandle, FILE_MAP_READ, 0, 0, 0);
239     if (mapAddr == nullptr) {
240         LOGE("MapViewOfFile %zu Failed with %ld:%s", length, GetLastError(), GetLastErrorString().c_str());
241         return MMAP_FAILED;
242     }
243 
244     // Close all the handles except for the view. It will keep the other handles
245     // alive.
246     ::CloseHandle(FileMappingHandle);
247     return mapAddr;
248 }
249 
munmap(void * addr,size_t)250 int munmap(void *addr, size_t)
251 {
252     /*
253         On success, munmap() returns 0.  On failure, it returns -1, and
254         errno is set to indicate the error (probably to EINVAL).
255 
256         UnmapViewOfFile function (memoryapi.h)
257 
258         If the function succeeds, the return value is nonzero.
259         If the function fails, the return value is zero. To get extended error information, call
260     GetLastError.
261     */
262     return !UnmapViewOfFile(addr);
263 }
264 #endif
265