1 /*
2 * Copyright (c) 2021-2022 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 /* This files contains process dump common tool functions. */
17
18 #include "dfx_util.h"
19
20 #include <cctype>
21 #include <climits>
22 #include <cstdio>
23 #include <cstdlib>
24 #include <cstring>
25 #include <ctime>
26 #include <fstream>
27 #include <iostream>
28 #include <securec.h>
29 #include <unistd.h>
30 #include "dfx_define.h"
31 #include "dfx_logger.h"
32
33 namespace OHOS {
34 namespace HiviewDFX {
35 static const int ARGS_COUNT_ONE = 1;
36 static const int ARGS_COUNT_TWO = 2;
GetProcStatusByPath(const std::string & path,struct ProcInfo & procInfo)37 static int GetProcStatusByPath(const std::string& path, struct ProcInfo& procInfo)
38 {
39 char buf[STATUS_LINE_SIZE];
40 FILE *fp = fopen(path.c_str(), "r");
41 if (fp == nullptr) {
42 return -1;
43 }
44
45 int pid = 0;
46 int ppid = 0;
47 int tid = 0;
48 while (!feof(fp)) {
49 if (fgets(buf, STATUS_LINE_SIZE, fp) == nullptr) {
50 fclose(fp);
51 return -1;
52 }
53
54 if (strncmp(buf, PID_STR_NAME, strlen(PID_STR_NAME)) == 0) {
55 // Pid: 1892
56 if (sscanf_s(buf, "%*[^0-9]%d", &pid) != ARGS_COUNT_ONE) {
57 DfxLogError("sscanf_s failed.");
58 }
59 procInfo.pid = pid;
60 if (procInfo.pid == getpid()) {
61 procInfo.ns = false;
62 procInfo.tid = gettid();
63 procInfo.ppid = getppid();
64 break;
65 }
66 procInfo.ns = true;
67 continue;
68 }
69
70 if (strncmp(buf, PPID_STR_NAME, strlen(PPID_STR_NAME)) == 0) {
71 // PPid: 240
72 if (sscanf_s(buf, "%*[^0-9]%d", &ppid) != ARGS_COUNT_ONE) {
73 DfxLogError("sscanf_s failed.");
74 }
75 procInfo.ppid = ppid;
76 continue;
77 }
78
79 // NSpid: 1892 1
80 if (strncmp(buf, NSPID_STR_NAME, strlen(NSPID_STR_NAME)) == 0) {
81 if (sscanf_s(buf, "%*[^0-9]%d%*[^0-9]%d", &pid, &tid) != ARGS_COUNT_TWO) {
82 DfxLogError("sscanf_s failed.");
83 }
84 procInfo.tid = tid;
85 break;
86 }
87 }
88 (void)fclose(fp);
89 return 0;
90 }
91
GetRealTargetPid()92 int GetRealTargetPid()
93 {
94 ProcInfo procInfo;
95 (void)memset_s(&procInfo, sizeof(procInfo), 0, sizeof(struct ProcInfo));
96 if (GetProcStatus(procInfo) == -1) {
97 return -1;
98 }
99
100 return procInfo.ppid;
101 }
102
GetProcStatusByPid(int realPid,struct ProcInfo & procInfo)103 int GetProcStatusByPid(int realPid, struct ProcInfo& procInfo)
104 {
105 std::string path = "/proc/" + std::to_string(realPid) + "/status";
106 return GetProcStatusByPath(path, procInfo);
107 }
108
GetProcStatus(struct ProcInfo & procInfo)109 int GetProcStatus(struct ProcInfo& procInfo)
110 {
111 return GetProcStatusByPath(PROC_SELF_STATUS_PATH, procInfo);
112 }
113
ReadStringFromFile(const std::string & path,std::string & buf,size_t len)114 bool ReadStringFromFile(const std::string &path, std::string &buf, size_t len)
115 {
116 if (len <= 1) {
117 return false;
118 }
119
120 char realPath[PATH_MAX] = {0};
121 if (!realpath(path.c_str(), realPath)) {
122 return false;
123 }
124
125 std::ifstream file;
126 file.open(realPath);
127 if (!file.is_open()) {
128 return false;
129 }
130
131 std::istreambuf_iterator<char> start(file);
132 std::istreambuf_iterator<char> end;
133 std::string str(start, end);
134 buf = str.substr(0, len);
135 file.close();
136 return true;
137 }
138
TrimAndDupStr(const std::string & source,std::string & str)139 bool TrimAndDupStr(const std::string &source, std::string &str)
140 {
141 if (source.empty()) {
142 return false;
143 }
144
145 const char *begin = source.data();
146 const char *end = begin + source.size();
147 if (begin == end) {
148 DfxLogError("Source is empty");
149 return false;
150 }
151
152 while ((begin < end) && isspace(*begin)) {
153 begin++;
154 }
155
156 while ((begin < end) && isspace(*(end - 1))) {
157 end--;
158 }
159
160 if (begin == end) {
161 return false;
162 }
163
164 uint32_t maxStrLen = NAME_LEN;
165 uint32_t offset = static_cast<uint32_t>(end - begin);
166 if (maxStrLen > offset) {
167 maxStrLen = offset;
168 }
169
170 str.assign(begin, maxStrLen);
171 return true;
172 }
173
GetCurrentTimeStr(uint64_t current)174 std::string GetCurrentTimeStr(uint64_t current)
175 {
176 time_t now = time(nullptr);
177 uint64_t millsecond = 0;
178 const uint64_t ratio = 1000;
179 if (current > static_cast<uint64_t>(now)) {
180 millsecond = current % ratio;
181 now = static_cast<time_t>(current / ratio);
182 }
183
184 auto tm = std::localtime(&now);
185 char seconds[128] = {0}; // 128 : time buffer size
186 if (tm == nullptr || strftime(seconds, sizeof(seconds) - 1, "%Y-%m-%d %H:%M:%S", tm) == 0) {
187 return "invalid timestamp\n";
188 }
189
190 char millBuf[256] = {0}; // 256 : milliseconds buffer size
191 int ret = snprintf_s(millBuf, sizeof(millBuf), sizeof(millBuf) - 1,
192 "%s.%03u\n", seconds, millsecond);
193 if (ret <= 0) {
194 return "invalid timestamp\n";
195 }
196 return std::string(millBuf, strlen(millBuf));
197 }
198
PrintFormat(char * buf,int size,const char * format,...)199 int PrintFormat(char *buf, int size, const char *format, ...)
200 {
201 int ret = -1;
202 va_list args;
203 va_start(args, format);
204 ret = vsnprintf_s(buf, size, size - 1, format, args);
205 va_end(args);
206 if (ret <= 0) {
207 DfxLogError("snprintf_s failed.");
208 }
209 return ret;
210 }
211 } // namespace HiviewDFX
212 } // namespace OHOS
213