1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License.
5800b99b8Sopenharmony_ci * You may obtain a copy of the License at
6800b99b8Sopenharmony_ci *
7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8800b99b8Sopenharmony_ci *
9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and
13800b99b8Sopenharmony_ci * limitations under the License.
14800b99b8Sopenharmony_ci */
15800b99b8Sopenharmony_ci
16800b99b8Sopenharmony_ci#include "dfx_util.h"
17800b99b8Sopenharmony_ci
18800b99b8Sopenharmony_ci#if defined(is_mingw) && is_mingw
19800b99b8Sopenharmony_ci#include <memoryapi.h>
20800b99b8Sopenharmony_ci#include <windows.h>
21800b99b8Sopenharmony_ci#endif
22800b99b8Sopenharmony_ci#ifndef is_host
23800b99b8Sopenharmony_ci#include <cctype>
24800b99b8Sopenharmony_ci#include <climits>
25800b99b8Sopenharmony_ci#include <cstdio>
26800b99b8Sopenharmony_ci#include <cstdlib>
27800b99b8Sopenharmony_ci#include <cstring>
28800b99b8Sopenharmony_ci#include <ctime>
29800b99b8Sopenharmony_ci#include <securec.h>
30800b99b8Sopenharmony_ci#include <sys/types.h>
31800b99b8Sopenharmony_ci#include <sys/time.h>
32800b99b8Sopenharmony_ci#include <fcntl.h>
33800b99b8Sopenharmony_ci#include <pthread.h>
34800b99b8Sopenharmony_ci#include <unistd.h>
35800b99b8Sopenharmony_ci#include <dirent.h>
36800b99b8Sopenharmony_ci#endif
37800b99b8Sopenharmony_ci#include <sys/stat.h>
38800b99b8Sopenharmony_ci
39800b99b8Sopenharmony_ci#include "dfx_log.h"
40800b99b8Sopenharmony_ci
41800b99b8Sopenharmony_ci#ifdef LOG_DOMAIN
42800b99b8Sopenharmony_ci#undef LOG_DOMAIN
43800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11
44800b99b8Sopenharmony_ci#endif
45800b99b8Sopenharmony_ci
46800b99b8Sopenharmony_ci#ifdef LOG_TAG
47800b99b8Sopenharmony_ci#undef LOG_TAG
48800b99b8Sopenharmony_ci#define LOG_TAG "DfxUtil"
49800b99b8Sopenharmony_ci#endif
50800b99b8Sopenharmony_ci
51800b99b8Sopenharmony_cinamespace OHOS {
52800b99b8Sopenharmony_cinamespace HiviewDFX {
53800b99b8Sopenharmony_ci#ifndef is_host
54800b99b8Sopenharmony_cibool TrimAndDupStr(const std::string &source, std::string &str)
55800b99b8Sopenharmony_ci{
56800b99b8Sopenharmony_ci    if (source.empty()) {
57800b99b8Sopenharmony_ci        return false;
58800b99b8Sopenharmony_ci    }
59800b99b8Sopenharmony_ci
60800b99b8Sopenharmony_ci    const char *begin = source.data();
61800b99b8Sopenharmony_ci    const char *end = begin + source.size();
62800b99b8Sopenharmony_ci    if (begin == end) {
63800b99b8Sopenharmony_ci        DFXLOGE("Source is empty");
64800b99b8Sopenharmony_ci        return false;
65800b99b8Sopenharmony_ci    }
66800b99b8Sopenharmony_ci
67800b99b8Sopenharmony_ci    while ((begin < end) && isspace(*begin)) {
68800b99b8Sopenharmony_ci        begin++;
69800b99b8Sopenharmony_ci    }
70800b99b8Sopenharmony_ci
71800b99b8Sopenharmony_ci    while ((begin < end) && isspace(*(end - 1))) {
72800b99b8Sopenharmony_ci        end--;
73800b99b8Sopenharmony_ci    }
74800b99b8Sopenharmony_ci
75800b99b8Sopenharmony_ci    if (begin == end) {
76800b99b8Sopenharmony_ci        return false;
77800b99b8Sopenharmony_ci    }
78800b99b8Sopenharmony_ci
79800b99b8Sopenharmony_ci    uint32_t maxStrLen = NAME_BUF_LEN;
80800b99b8Sopenharmony_ci    uint32_t offset = static_cast<uint32_t>(end - begin);
81800b99b8Sopenharmony_ci    if (maxStrLen > offset) {
82800b99b8Sopenharmony_ci        maxStrLen = offset;
83800b99b8Sopenharmony_ci    }
84800b99b8Sopenharmony_ci
85800b99b8Sopenharmony_ci    str.assign(begin, maxStrLen);
86800b99b8Sopenharmony_ci    return true;
87800b99b8Sopenharmony_ci}
88800b99b8Sopenharmony_ci
89800b99b8Sopenharmony_ciuint64_t GetTimeMilliSeconds(void)
90800b99b8Sopenharmony_ci{
91800b99b8Sopenharmony_ci    struct timespec ts;
92800b99b8Sopenharmony_ci    (void)clock_gettime(CLOCK_REALTIME, &ts);
93800b99b8Sopenharmony_ci    return ((uint64_t)ts.tv_sec * NUMBER_ONE_THOUSAND) + // 1000 : second to millisecond convert ratio
94800b99b8Sopenharmony_ci        (((uint64_t)ts.tv_nsec) / NUMBER_ONE_MILLION); // 1000000 : nanosecond to millisecond convert ratio
95800b99b8Sopenharmony_ci}
96800b99b8Sopenharmony_ci
97800b99b8Sopenharmony_ciuint64_t GetAbsTimeMilliSeconds(void)
98800b99b8Sopenharmony_ci{
99800b99b8Sopenharmony_ci    struct timespec ts;
100800b99b8Sopenharmony_ci    (void)clock_gettime(CLOCK_MONOTONIC, &ts);
101800b99b8Sopenharmony_ci    return (static_cast<uint64_t>(ts.tv_sec) * NUMBER_ONE_THOUSAND) +
102800b99b8Sopenharmony_ci        (static_cast<uint64_t>(ts.tv_nsec) / NUMBER_ONE_MILLION);
103800b99b8Sopenharmony_ci}
104800b99b8Sopenharmony_ci
105800b99b8Sopenharmony_cistd::string GetCurrentTimeStr(uint64_t current)
106800b99b8Sopenharmony_ci{
107800b99b8Sopenharmony_ci    time_t now = time(nullptr);
108800b99b8Sopenharmony_ci    uint64_t millsecond = 0;
109800b99b8Sopenharmony_ci    const uint64_t ratio = NUMBER_ONE_THOUSAND;
110800b99b8Sopenharmony_ci    if (current > static_cast<uint64_t>(now)) {
111800b99b8Sopenharmony_ci        millsecond = current % ratio;
112800b99b8Sopenharmony_ci        now = static_cast<time_t>(current / ratio);
113800b99b8Sopenharmony_ci    }
114800b99b8Sopenharmony_ci
115800b99b8Sopenharmony_ci    auto tm = std::localtime(&now);
116800b99b8Sopenharmony_ci    char seconds[128] = {0}; // 128 : time buffer size
117800b99b8Sopenharmony_ci    if (tm == nullptr || strftime(seconds, sizeof(seconds) - 1, "%Y-%m-%d %H:%M:%S", tm) == 0) {
118800b99b8Sopenharmony_ci        return "invalid timestamp\n";
119800b99b8Sopenharmony_ci    }
120800b99b8Sopenharmony_ci
121800b99b8Sopenharmony_ci    char millBuf[256] = {0}; // 256 : milliseconds buffer size
122800b99b8Sopenharmony_ci    int ret = snprintf_s(millBuf, sizeof(millBuf), sizeof(millBuf) - 1,
123800b99b8Sopenharmony_ci        "%s.%03u\n", seconds, millsecond);
124800b99b8Sopenharmony_ci    if (ret <= 0) {
125800b99b8Sopenharmony_ci        return "invalid timestamp\n";
126800b99b8Sopenharmony_ci    }
127800b99b8Sopenharmony_ci    return std::string(millBuf, strlen(millBuf));
128800b99b8Sopenharmony_ci}
129800b99b8Sopenharmony_ci
130800b99b8Sopenharmony_cibool ReadDirFiles(const std::string& path, std::vector<std::string>& files)
131800b99b8Sopenharmony_ci{
132800b99b8Sopenharmony_ci    DIR *dir = opendir(path.c_str());
133800b99b8Sopenharmony_ci    if (dir == nullptr) {
134800b99b8Sopenharmony_ci        return false;
135800b99b8Sopenharmony_ci    }
136800b99b8Sopenharmony_ci
137800b99b8Sopenharmony_ci    struct dirent *ent;
138800b99b8Sopenharmony_ci    while ((ent = readdir(dir)) != nullptr) {
139800b99b8Sopenharmony_ci        // current dir OR parent dir
140800b99b8Sopenharmony_ci        if ((strcmp(ent->d_name, ".") == 0) || (strcmp(ent->d_name, "..") == 0)) {
141800b99b8Sopenharmony_ci            continue;
142800b99b8Sopenharmony_ci        }
143800b99b8Sopenharmony_ci        files.emplace_back(std::string(ent->d_name));
144800b99b8Sopenharmony_ci    }
145800b99b8Sopenharmony_ci    (void)closedir(dir);
146800b99b8Sopenharmony_ci    return (files.size() > 0);
147800b99b8Sopenharmony_ci}
148800b99b8Sopenharmony_ci
149800b99b8Sopenharmony_cibool VerifyFilePath(const std::string& filePath, const std::vector<const std::string>& validPaths)
150800b99b8Sopenharmony_ci{
151800b99b8Sopenharmony_ci    if (validPaths.size() == 0) {
152800b99b8Sopenharmony_ci        return true;
153800b99b8Sopenharmony_ci    }
154800b99b8Sopenharmony_ci
155800b99b8Sopenharmony_ci    for (auto validPath : validPaths) {
156800b99b8Sopenharmony_ci        if (filePath.find(validPath) == 0) {
157800b99b8Sopenharmony_ci            return true;
158800b99b8Sopenharmony_ci        }
159800b99b8Sopenharmony_ci    }
160800b99b8Sopenharmony_ci    return false;
161800b99b8Sopenharmony_ci}
162800b99b8Sopenharmony_ci
163800b99b8Sopenharmony_civoid ParseSiValue(siginfo_t& si, uint64_t& endTime, int& tid)
164800b99b8Sopenharmony_ci{
165800b99b8Sopenharmony_ci    const int flagOffset = 63;
166800b99b8Sopenharmony_ci    if ((reinterpret_cast<uint64_t>(si.si_value.sival_ptr) & (1ULL << flagOffset)) != 0) {
167800b99b8Sopenharmony_ci        endTime = reinterpret_cast<uint64_t>(si.si_value.sival_ptr) & (~(1ULL << flagOffset));
168800b99b8Sopenharmony_ci        tid = 0;
169800b99b8Sopenharmony_ci    } else {
170800b99b8Sopenharmony_ci        endTime = 0;
171800b99b8Sopenharmony_ci        tid = si.si_value.sival_int;
172800b99b8Sopenharmony_ci    }
173800b99b8Sopenharmony_ci}
174800b99b8Sopenharmony_ci#endif
175800b99b8Sopenharmony_ci
176800b99b8Sopenharmony_cioff_t GetFileSize(const int& fd)
177800b99b8Sopenharmony_ci{
178800b99b8Sopenharmony_ci    off_t fileSize = 0;
179800b99b8Sopenharmony_ci    if (fd >= 0) {
180800b99b8Sopenharmony_ci        struct stat fileStat;
181800b99b8Sopenharmony_ci        if (fstat(fd, &fileStat) == 0) {
182800b99b8Sopenharmony_ci            fileSize = fileStat.st_size;
183800b99b8Sopenharmony_ci        }
184800b99b8Sopenharmony_ci    }
185800b99b8Sopenharmony_ci    return fileSize;
186800b99b8Sopenharmony_ci}
187800b99b8Sopenharmony_ci
188800b99b8Sopenharmony_cibool ReadFdToString(int fd, std::string& content)
189800b99b8Sopenharmony_ci{
190800b99b8Sopenharmony_ci    content.clear();
191800b99b8Sopenharmony_ci    struct stat sb;
192800b99b8Sopenharmony_ci    if (fstat(fd, &sb) != -1 && sb.st_size > 0) {
193800b99b8Sopenharmony_ci        content.reserve(sb.st_size);
194800b99b8Sopenharmony_ci    }
195800b99b8Sopenharmony_ci
196800b99b8Sopenharmony_ci    char buf[BUFSIZ] __attribute__((__uninitialized__));
197800b99b8Sopenharmony_ci    ssize_t n;
198800b99b8Sopenharmony_ci    while ((n = OHOS_TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
199800b99b8Sopenharmony_ci        content.append(buf, n);
200800b99b8Sopenharmony_ci    }
201800b99b8Sopenharmony_ci    return (n == 0);
202800b99b8Sopenharmony_ci}
203800b99b8Sopenharmony_ci}   // namespace HiviewDFX
204800b99b8Sopenharmony_ci}   // namespace OHOS
205800b99b8Sopenharmony_ci
206800b99b8Sopenharmony_ci// this will also used for libunwinder head (out of namespace)
207800b99b8Sopenharmony_ci#if defined(is_mingw) && is_mingw
208800b99b8Sopenharmony_cistd::string GetLastErrorString()
209800b99b8Sopenharmony_ci{
210800b99b8Sopenharmony_ci    LPVOID lpMsgBuf;
211800b99b8Sopenharmony_ci    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
212800b99b8Sopenharmony_ci                      FORMAT_MESSAGE_IGNORE_INSERTS,
213800b99b8Sopenharmony_ci                  NULL, GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, NULL);
214800b99b8Sopenharmony_ci    std::string error((LPTSTR)lpMsgBuf);
215800b99b8Sopenharmony_ci    LocalFree(lpMsgBuf);
216800b99b8Sopenharmony_ci    return error;
217800b99b8Sopenharmony_ci}
218800b99b8Sopenharmony_ci
219800b99b8Sopenharmony_civoid *mmap(void *addr, size_t length, int prot, int flags, int fd, size_t offset)
220800b99b8Sopenharmony_ci{
221800b99b8Sopenharmony_ci    HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
222800b99b8Sopenharmony_ci    if (FileHandle == INVALID_HANDLE_VALUE) {
223800b99b8Sopenharmony_ci        return MMAP_FAILED;
224800b99b8Sopenharmony_ci    }
225800b99b8Sopenharmony_ci
226800b99b8Sopenharmony_ci    DFXLOGD("fd is %{public}d", fd);
227800b99b8Sopenharmony_ci
228800b99b8Sopenharmony_ci    HANDLE FileMappingHandle = ::CreateFileMappingW(FileHandle, 0, PAGE_READONLY, 0, 0, 0);
229800b99b8Sopenharmony_ci    if (FileMappingHandle == nullptr) {
230800b99b8Sopenharmony_ci        DFXLOGE("CreateFileMappingW %{public}zu Failed with %{public}ld:%{public}s",
231800b99b8Sopenharmony_ci            length, GetLastError(), GetLastErrorString().c_str());
232800b99b8Sopenharmony_ci        return MMAP_FAILED;
233800b99b8Sopenharmony_ci    }
234800b99b8Sopenharmony_ci
235800b99b8Sopenharmony_ci    void *mapAddr = ::MapViewOfFile(FileMappingHandle, FILE_MAP_READ, 0, 0, 0);
236800b99b8Sopenharmony_ci    if (mapAddr == nullptr) {
237800b99b8Sopenharmony_ci        DFXLOGE("MapViewOfFile %{public}zu Failed with %{public}ld:%{public}s",
238800b99b8Sopenharmony_ci            length, GetLastError(), GetLastErrorString().c_str());
239800b99b8Sopenharmony_ci        return MMAP_FAILED;
240800b99b8Sopenharmony_ci    }
241800b99b8Sopenharmony_ci
242800b99b8Sopenharmony_ci    // Close all the handles except for the view. It will keep the other handles
243800b99b8Sopenharmony_ci    // alive.
244800b99b8Sopenharmony_ci    ::CloseHandle(FileMappingHandle);
245800b99b8Sopenharmony_ci    return mapAddr;
246800b99b8Sopenharmony_ci}
247800b99b8Sopenharmony_ci
248800b99b8Sopenharmony_ciint munmap(void *addr, size_t)
249800b99b8Sopenharmony_ci{
250800b99b8Sopenharmony_ci    /*
251800b99b8Sopenharmony_ci        On success, munmap() returns 0.  On failure, it returns -1, and
252800b99b8Sopenharmony_ci        errno is set to indicate the error (probably to EINVAL).
253800b99b8Sopenharmony_ci
254800b99b8Sopenharmony_ci        UnmapViewOfFile function (memoryapi.h)
255800b99b8Sopenharmony_ci
256800b99b8Sopenharmony_ci        If the function succeeds, the return value is nonzero.
257800b99b8Sopenharmony_ci        If the function fails, the return value is zero. To get extended error information, call
258800b99b8Sopenharmony_ci    GetLastError.
259800b99b8Sopenharmony_ci    */
260800b99b8Sopenharmony_ci    return !UnmapViewOfFile(addr);
261800b99b8Sopenharmony_ci}
262800b99b8Sopenharmony_ci#endif
263