1 /*
2  * Copyright (c) 2022-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 #ifndef DFX_MUSL_CUTIL_H
16 #define DFX_MUSL_CUTIL_H
17 
18 #include <stdbool.h>
19 #include <stddef.h>
20 #include <stdint.h>
21 #include <syscall.h>
22 #include <time.h>
23 #include <unistd.h>
24 #include "dfx_define.h"
25 #include "musl_log.h"
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 #ifdef ENABLE_MUSL_CUTIL
32 static const char PID_STR_NAME[] = "Pid:";
33 
ReadStringFromFile(const char* path, char* dst, size_t dstSz)34 static bool ReadStringFromFile(const char* path, char* dst, size_t dstSz)
35 {
36     char name[NAME_BUF_LEN];
37     char nameFilter[NAME_BUF_LEN];
38     memset(name, 0, sizeof(name));
39     memset(nameFilter, 0, sizeof(nameFilter));
40 
41     int fd = -1;
42     fd = OHOS_TEMP_FAILURE_RETRY(open(path, O_RDONLY));
43     if (fd < 0) {
44         return false;
45     }
46 
47     int nRead = OHOS_TEMP_FAILURE_RETRY(read(fd, name, NAME_BUF_LEN -1));
48     if (nRead == -1) {
49         close(fd);
50         return false;
51     }
52 
53     char* p = name;
54     int i = 0;
55     while (*p != '\0') {
56         if ((*p == '\n') || (i == NAME_BUF_LEN)) {
57             break;
58         }
59         nameFilter[i] = *p;
60         p++, i++;
61     }
62     nameFilter[NAME_BUF_LEN - 1] = '\0';
63 
64     size_t cpyLen = strlen(nameFilter) + 1;
65     if (cpyLen > dstSz) {
66         cpyLen = dstSz;
67     }
68     memcpy(dst, nameFilter, cpyLen);
69     close(fd);
70     return true;
71 }
72 
GetThreadName(char* buffer, size_t bufferSz)73 bool GetThreadName(char* buffer, size_t bufferSz)
74 {
75     return ReadStringFromFile(PROC_SELF_COMM_PATH, buffer, bufferSz);
76 }
77 
GetThreadNameByTid(int32_t tid, char* buffer, size_t bufferSz)78 bool GetThreadNameByTid(int32_t tid, char* buffer, size_t bufferSz)
79 {
80     char threadNamePath[NAME_BUF_LEN] = { 0 };
81     if (snprintf(threadNamePath, sizeof(threadNamePath), "/proc/%d/comm", tid) <= 0) {
82         return false;
83     }
84     return ReadStringFromFile(threadNamePath, buffer, bufferSz);
85 }
86 
GetProcessName(char* buffer, size_t bufferSz)87 bool GetProcessName(char* buffer, size_t bufferSz)
88 {
89     return ReadStringFromFile(PROC_SELF_CMDLINE_PATH, buffer, bufferSz);
90 }
91 
GetRealPid(void)92 pid_t GetRealPid(void)
93 {
94     pid_t pid = syscall(SYS_getpid);
95     int fd = OHOS_TEMP_FAILURE_RETRY(open(PROC_SELF_STATUS_PATH, O_RDONLY));
96     if (fd < 0) {
97         DFXLOGE("GetRealPid:: open failed! pid:(%{public}ld), errno:(%{public}d).", pid, errno);
98         return pid;
99     }
100 
101     char buf[LINE_BUF_SIZE] = {0};
102     int i = 0;
103     char b;
104     ssize_t nRead = 0;
105     while (1) {
106         nRead = OHOS_TEMP_FAILURE_RETRY(read(fd, &b, sizeof(char)));
107         if (nRead <= 0 || b == '\0') {
108             DFXLOGE("GetRealPid:: read failed! pid:(%{public}ld), errno:(%{public}d), " \
109                 "nRead(%{public}zd), readchar(%{public}02X).",
110                 pid, errno, nRead, b);
111             break;
112         }
113 
114         if (b == '\n' || i == LINE_BUF_SIZE) {
115             if (strncmp(buf, PID_STR_NAME, strlen(PID_STR_NAME)) != 0) {
116                 i = 0;
117                 (void)memset(buf, '\0', sizeof(buf));
118                 continue;
119             }
120             if (sscanf(buf, "%*[^0-9]%d", &pid) < 0) {
121                 DFXLOGE("GetRealPid:: sscanf failed! pid:(%{public}ld), errno:(%{public}d), buf(%{public}s).",
122                     pid, errno, buf);
123             }
124             break;
125         }
126         buf[i] = b;
127         i++;
128     }
129     close(fd);
130     return pid;
131 }
132 
GetTimeMilliseconds(void)133 uint64_t GetTimeMilliseconds(void)
134 {
135     struct timespec ts;
136     (void)clock_gettime(CLOCK_REALTIME, &ts);
137     return ((uint64_t)ts.tv_sec * NUMBER_ONE_THOUSAND) + // 1000 : second to millisecond convert ratio
138         (((uint64_t)ts.tv_nsec) / NUMBER_ONE_MILLION); // 1000000 : nanosecond to millisecond convert ratio
139 }
140 
141 #endif
142 #ifdef __cplusplus
143 }
144 #endif
145 #endif