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