• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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