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 
16 #include "dfx_cutil.h"
17 
18 #include <fcntl.h>
19 #include <stdio.h>
20 #include <syscall.h>
21 #include <unistd.h>
22 #include <sys/time.h>
23 #include <time.h>
24 #include <securec.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include "dfx_define.h"
28 
29 static const char PID_STR_NAME[] = "Pid:";
30 
ReadStringFromFile(const char * path,char * dst,size_t dstSz)31 static bool ReadStringFromFile(const char* path, char* dst, size_t dstSz)
32 {
33     if ((dst == NULL) || (path == NULL)) {
34         return false;
35     }
36     char name[NAME_BUF_LEN];
37     char nameFilter[NAME_BUF_LEN];
38     (void)memset_s(name, sizeof(name), '\0', sizeof(name));
39     (void)memset_s(nameFilter, sizeof(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     ssize_t nRead = OHOS_TEMP_FAILURE_RETRY(read(fd, name, NAME_BUF_LEN - 1));
48     if (nRead <= 0) {
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     if (memcpy_s(dst, dstSz, nameFilter, strlen(nameFilter) + 1) != 0) {
65         close(fd);
66         return false;
67     }
68 
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_s(threadNamePath, sizeof(threadNamePath), sizeof(threadNamePath) - 1, "/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         return pid;
98     }
99 
100     char buf[LINE_BUF_SIZE];
101     int i = 0;
102     char b;
103     while (1) {
104         ssize_t nRead = OHOS_TEMP_FAILURE_RETRY(read(fd, &b, sizeof(char)));
105         if (nRead <= 0 || b == '\0') {
106             break;
107         }
108 
109         if (b == '\n' || i == LINE_BUF_SIZE) {
110             if (strncmp(buf, PID_STR_NAME, strlen(PID_STR_NAME)) == 0) {
111                 (void)sscanf_s(buf, "%*[^0-9]%d", &pid);
112                 break;
113             }
114             i = 0;
115             (void)memset_s(buf, sizeof(buf), '\0', sizeof(buf));
116             continue;
117         }
118         buf[i] = b;
119         i++;
120     }
121     close(fd);
122     return pid;
123 }
124 
GetTimeMilliseconds(void)125 uint64_t GetTimeMilliseconds(void)
126 {
127     struct timespec ts;
128     (void)clock_gettime(CLOCK_REALTIME, &ts);
129     return ((uint64_t)ts.tv_sec * NUMBER_ONE_THOUSAND) + // 1000 : second to millisecond convert ratio
130         (((uint64_t)ts.tv_nsec) / NUMBER_ONE_MILLION); // 1000000 : nanosecond to millisecond convert ratio
131 }
132 
TrimAndDupStr(const char * src,char * dst)133 bool TrimAndDupStr(const char* src, char* dst)
134 {
135     if ((src == NULL) || (dst == NULL)) {
136         return false;
137     }
138 
139     size_t i = 0, j = 0;
140     for (; i < strlen(src); ++i) {
141         if (src[i] != ' ') {
142             dst[j++] = src[i];
143         }
144     }
145     for (; j <= i; j++) {
146         dst[j] = '\0';
147     }
148 
149     dst = strchr(dst, '\n');
150     if (dst != NULL) {
151         *dst = '\0';
152     }
153     return true;
154 }
155 
GetAbsTimeMilliSeconds(void)156 uint64_t GetAbsTimeMilliSeconds(void)
157 {
158     struct timespec ts;
159     (void)clock_gettime(CLOCK_MONOTONIC, &ts);
160     return ((uint64_t)(ts.tv_sec) * NUMBER_ONE_THOUSAND) +
161         ((uint64_t)(ts.tv_nsec) / NUMBER_ONE_MILLION);
162 }
163 
ParseSiValue(siginfo_t * si,uint64_t * endTime,int * tid)164 void ParseSiValue(siginfo_t* si, uint64_t* endTime, int* tid)
165 {
166     const int flagOffset = 63;
167     if (((uint64_t)si->si_value.sival_ptr & (1ULL << flagOffset)) != 0) {
168         *endTime = (uint64_t)si->si_value.sival_ptr & (~(1ULL << flagOffset));
169         *tid = 0;
170     } else {
171         *endTime = 0;
172         *tid = si->si_value.sival_int;
173     }
174 }
175