• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "dump_common_utils.h"
16 #include <file_ex.h>
17 #include <securec.h>
18 #include <string_ex.h>
19 #include <dirent.h>
20 #include <fstream>
21 #include <iostream>
22 #include "hilog_wrapper.h"
23 using namespace std;
24 namespace OHOS {
25 namespace HiviewDFX {
26 namespace {
27 constexpr int LINE_ITEM_MIN = 2;
28 constexpr int LINE_KEY = 0;
29 constexpr int LINE_VALUE = 1;
30 constexpr int LINE_VALUE_0 = 0;
31 constexpr int UNSET = -1;
32 static const std::string CPU_STR = "cpu";
33 }
34 
CpuInfo()35 DumpCommonUtils::CpuInfo::CpuInfo()
36 {
37     id_ = UNSET;
38 }
39 
GetCpuInfos(std::vector<CpuInfo> & infos)40 bool DumpCommonUtils::GetCpuInfos(std::vector<CpuInfo> &infos)
41 {
42     std::vector<std::string> names;
43     if (!GetNamesInFolder("/sys/devices/system/cpu/", names)) {
44         return false;
45     }
46     for (size_t i = 0; i < names.size(); i++) {
47         std::string name = names[i];
48         if (!StartWith(name, CPU_STR)) {
49             continue;
50         }
51         std::string cpuId = name.substr(CPU_STR.size());
52         if (cpuId.empty() || (!IsNumericStr(cpuId))) {
53             continue;
54         }
55         CpuInfo cpuInfo;
56         StrToInt(cpuId, cpuInfo.id_);
57         infos.push_back(cpuInfo);
58     }
59     return true;
60 }
61 
PidInfo()62 DumpCommonUtils::PidInfo::PidInfo()
63 {
64     Reset();
65 }
66 
Reset()67 void DumpCommonUtils::PidInfo::Reset()
68 {
69     pid_ = UNSET;
70     uid_ = UNSET;
71     gid_ = UNSET;
72     ppid_ = UNSET;
73     name_.clear();
74     cmdline_.clear();
75 }
76 
GetPidInfos(std::vector<PidInfo> & infos,bool all)77 bool DumpCommonUtils::GetPidInfos(std::vector<PidInfo> &infos, bool all)
78 {
79     std::vector<std::string> names;
80     if (!GetNamesInFolder("/proc/", names)) {
81         return false;
82     }
83     for (size_t i = 0; i < names.size(); i++) {
84         std::string name = names[i];
85         if (name.empty()) {
86             continue;
87         }
88         if (!IsNumericStr(name)) {
89             continue;
90         }
91         PidInfo pidInfo;
92         StrToInt(name, pidInfo.pid_);
93         GetProcessInfo(pidInfo.pid_, pidInfo);
94         if (all) {
95             GetProcessNameByPid(pidInfo.pid_, pidInfo.cmdline_);
96         }
97         infos.push_back(pidInfo);
98     }
99     return true;
100 }
101 
IsUserPid(const std::string & pid)102 bool DumpCommonUtils::IsUserPid(const std::string &pid)
103 {
104     string filename = "/proc/" + pid + "/smaps";
105     std::ifstream in(filename);
106     if (in) {
107         string line;
108         getline(in, line);
109         if (!line.empty()) {
110             return true;
111         }
112         in.close();
113     }
114     return false;
115 }
116 
GetUserPids(std::vector<int> & pids)117 bool DumpCommonUtils::GetUserPids(std::vector<int> &pids)
118 {
119     std::vector<std::string> files;
120     if (!GetNamesInFolder("/proc/", files)) {
121         return false;
122     }
123 
124     for (auto file : files) {
125         if (file.empty()) {
126             continue;
127         }
128         if (!IsNumericStr(file)) {
129             continue;
130         }
131 
132         if (!IsUserPid(file)) {
133             continue;
134         }
135 
136         int pid;
137         StrToInt(file, pid);
138 
139         pids.push_back(pid);
140     }
141     return true;
142 }
143 
GetLinesInFile(const std::string & file,std::vector<std::string> & lines)144 bool DumpCommonUtils::GetLinesInFile(const std::string& file, std::vector<std::string>& lines)
145 {
146     std::string content;
147     if (!LoadStringFromFile(file, content)) {
148         return false;
149     }
150     SplitStr(content, "\n", lines);
151     return true;
152 }
153 
GetNamesInFolder(const std::string & folder,std::vector<std::string> & names)154 bool DumpCommonUtils::GetNamesInFolder(const std::string& folder, std::vector<std::string>& names)
155 {
156     bool ret = false;
157     DIR* dir = nullptr;
158     if ((dir = opendir(folder.c_str())) != nullptr) {
159         dirent* ptr = nullptr;
160         while ((ptr = readdir(dir)) != nullptr) {
161             std::string name = ptr->d_name;
162             if ((name == ".") || (name == "..")) {
163                 continue;
164             }
165             names.push_back(name);
166         }
167         closedir(dir);
168         ret = true;
169     }
170     return ret;
171 }
172 
StartWith(const std::string & str,const std::string & head)173 bool DumpCommonUtils::StartWith(const std::string& str, const std::string& head)
174 {
175     if (str.length() < head.length()) {
176         return false;
177     }
178     return (str.compare(0, head.size(), head) == 0);
179 }
180 
GetProcessNameByPid(int pid,std::string & name)181 bool DumpCommonUtils::GetProcessNameByPid(int pid, std::string& name)
182 {
183     char filesysdir[128] = { 0 };
184     if (sprintf_s(filesysdir, sizeof(filesysdir), "/proc/%d/cmdline", pid) < 0) {
185         return false;
186     }
187     std::string filePath = filesysdir;
188     std::string content;
189     if (!LoadStringFromFile(filePath, content)) {
190         return false;
191     }
192     name = content;
193     return true;
194 }
195 
GetProcessInfo(int pid,PidInfo & info)196 bool DumpCommonUtils::GetProcessInfo(int pid, PidInfo &info)
197 {
198     info.Reset();
199     char filesysdir[128] = { 0 };
200     if (sprintf_s(filesysdir, sizeof(filesysdir), "/proc/%d/status", pid) < 0) {
201         return false;
202     }
203     std::string file = filesysdir;
204     std::vector<std::string> lines;
205     if (!GetLinesInFile(file, lines)) {
206         return false;
207     }
208     const std::string splitKeyValueToken = ":";
209     const std::string splitValuesToken = "\t";
210     for (size_t i = 0; i < lines.size(); i++) {
211         std::vector<std::string> keyValue;
212         SplitStr(lines[i], splitKeyValueToken, keyValue);
213         if (keyValue.size() < LINE_ITEM_MIN) {
214             continue;
215         }
216         std::string key = keyValue[LINE_KEY];
217         std::string val = TrimStr(keyValue[LINE_VALUE], '\t');
218         std::vector<std::string> values;
219         SplitStr(val, splitValuesToken, values, true);
220         if (values.empty()) {
221             continue;
222         }
223         std::string val0 = values[LINE_VALUE_0];
224         if (key == "Pid") {
225             StrToInt(val0, info.pid_);
226         } else if (key == "PPid") {
227             StrToInt(val0, info.ppid_);
228         } else if (key == "Uid") {
229             StrToInt(val0, info.uid_);
230         } else if (key == "Gid") {
231             StrToInt(val0, info.gid_);
232         } else if (key == "Name") {
233             info.name_ = val;
234         } else {
235             continue;
236         }
237         if ((info.pid_ > UNSET) && (info.ppid_ > UNSET) && (info.uid_ > UNSET) && (info.gid_ > UNSET)) {
238             return true;
239         }
240     }
241     return false;
242 }
243 } // namespace HiviewDFX
244 } // namespace OHOS
245