100600bfbSopenharmony_ci/* 200600bfbSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 300600bfbSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 400600bfbSopenharmony_ci * you may not use this file except in compliance with the License. 500600bfbSopenharmony_ci * You may obtain a copy of the License at 600600bfbSopenharmony_ci * 700600bfbSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 800600bfbSopenharmony_ci * 900600bfbSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1000600bfbSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1100600bfbSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1200600bfbSopenharmony_ci * See the License for the specific language governing permissions and 1300600bfbSopenharmony_ci * limitations under the License. 1400600bfbSopenharmony_ci */ 1500600bfbSopenharmony_ci#include "dump_common_utils.h" 1600600bfbSopenharmony_ci#include <file_ex.h> 1700600bfbSopenharmony_ci#include <securec.h> 1800600bfbSopenharmony_ci#include <string_ex.h> 1900600bfbSopenharmony_ci#include <dirent.h> 2000600bfbSopenharmony_ci#include <fstream> 2100600bfbSopenharmony_ci#include <iostream> 2200600bfbSopenharmony_ci#include "hilog_wrapper.h" 2300600bfbSopenharmony_ci#include "sys/stat.h" 2400600bfbSopenharmony_ci#include "util/string_utils.h" 2500600bfbSopenharmony_ci#include "util/file_utils.h" 2600600bfbSopenharmony_ci 2700600bfbSopenharmony_ciusing namespace std; 2800600bfbSopenharmony_cinamespace OHOS { 2900600bfbSopenharmony_cinamespace HiviewDFX { 3000600bfbSopenharmony_cinamespace { 3100600bfbSopenharmony_ciconstexpr int LINE_ITEM_MIN = 2; 3200600bfbSopenharmony_ciconstexpr int LINE_KEY = 0; 3300600bfbSopenharmony_ciconstexpr int LINE_VALUE = 1; 3400600bfbSopenharmony_ciconstexpr int LINE_VALUE_0 = 0; 3500600bfbSopenharmony_ciconstexpr int UNSET = -1; 3600600bfbSopenharmony_cistatic const std::string CPU_STR = "cpu"; 3700600bfbSopenharmony_ci} 3800600bfbSopenharmony_ci 3900600bfbSopenharmony_cistd::vector<std::string> DumpCommonUtils::GetSubNodes(const std::string &path, bool digit) 4000600bfbSopenharmony_ci{ 4100600bfbSopenharmony_ci std::vector<std::string> subNodes; 4200600bfbSopenharmony_ci auto dir = opendir(path.c_str()); 4300600bfbSopenharmony_ci if (dir == nullptr) { 4400600bfbSopenharmony_ci return subNodes; 4500600bfbSopenharmony_ci } 4600600bfbSopenharmony_ci for (struct dirent *ent = readdir(dir); ent != nullptr; ent = readdir(dir)) { 4700600bfbSopenharmony_ci std::string childNode = ent->d_name; 4800600bfbSopenharmony_ci if (childNode == "." || childNode == "..") { 4900600bfbSopenharmony_ci continue; 5000600bfbSopenharmony_ci } 5100600bfbSopenharmony_ci if (digit && !IsNumericStr(childNode)) { 5200600bfbSopenharmony_ci continue; 5300600bfbSopenharmony_ci } 5400600bfbSopenharmony_ci subNodes.push_back(childNode); 5500600bfbSopenharmony_ci } 5600600bfbSopenharmony_ci closedir(dir); 5700600bfbSopenharmony_ci return subNodes; 5800600bfbSopenharmony_ci} 5900600bfbSopenharmony_ci 6000600bfbSopenharmony_ci// the parameter of path should be full. 6100600bfbSopenharmony_cibool DumpCommonUtils::IsDirectory(const std::string &path) 6200600bfbSopenharmony_ci{ 6300600bfbSopenharmony_ci struct stat statBuffer; 6400600bfbSopenharmony_ci if (stat(path.c_str(), &statBuffer) == 0 && S_ISDIR(statBuffer.st_mode)) { 6500600bfbSopenharmony_ci return true; 6600600bfbSopenharmony_ci } 6700600bfbSopenharmony_ci return false; 6800600bfbSopenharmony_ci} 6900600bfbSopenharmony_ci 7000600bfbSopenharmony_cistd::vector<std::string> DumpCommonUtils::GetSubDir(const std::string &path, bool digit) 7100600bfbSopenharmony_ci{ 7200600bfbSopenharmony_ci std::vector<std::string> subDirs; 7300600bfbSopenharmony_ci auto dir = opendir(path.c_str()); 7400600bfbSopenharmony_ci if (dir == nullptr) { 7500600bfbSopenharmony_ci DUMPER_HILOGE(MODULE_SERVICE, "failed to open dir: %{public}s, errno: %{public}d", path.c_str(), errno); 7600600bfbSopenharmony_ci return subDirs; 7700600bfbSopenharmony_ci } 7800600bfbSopenharmony_ci for (struct dirent *ent = readdir(dir); ent != nullptr; ent = readdir(dir)) { 7900600bfbSopenharmony_ci std::string childNode = ent->d_name; 8000600bfbSopenharmony_ci if (childNode == "." || childNode == "..") { 8100600bfbSopenharmony_ci continue; 8200600bfbSopenharmony_ci } 8300600bfbSopenharmony_ci if (digit && !IsNumericStr(childNode)) { 8400600bfbSopenharmony_ci continue; 8500600bfbSopenharmony_ci } 8600600bfbSopenharmony_ci if (!IsDirectory(path + "/" + childNode)) { 8700600bfbSopenharmony_ci continue; // skip directory 8800600bfbSopenharmony_ci } 8900600bfbSopenharmony_ci subDirs.push_back(childNode); 9000600bfbSopenharmony_ci } 9100600bfbSopenharmony_ci closedir(dir); 9200600bfbSopenharmony_ci return subDirs; 9300600bfbSopenharmony_ci} 9400600bfbSopenharmony_ci 9500600bfbSopenharmony_cistd::vector<int32_t> DumpCommonUtils::GetAllPids() 9600600bfbSopenharmony_ci{ 9700600bfbSopenharmony_ci std::string path = "/proc"; 9800600bfbSopenharmony_ci std::vector<int32_t> pids; 9900600bfbSopenharmony_ci std::vector<std::string> allPids = GetSubDir(path, true); 10000600bfbSopenharmony_ci for (const auto &pid : allPids) { 10100600bfbSopenharmony_ci if (!IsNumericStr(pid)) { 10200600bfbSopenharmony_ci continue; 10300600bfbSopenharmony_ci } 10400600bfbSopenharmony_ci pids.push_back(std::stoi(pid)); 10500600bfbSopenharmony_ci } 10600600bfbSopenharmony_ci return pids; 10700600bfbSopenharmony_ci} 10800600bfbSopenharmony_ci 10900600bfbSopenharmony_ciDumpCommonUtils::CpuInfo::CpuInfo() 11000600bfbSopenharmony_ci{ 11100600bfbSopenharmony_ci id_ = UNSET; 11200600bfbSopenharmony_ci} 11300600bfbSopenharmony_ci 11400600bfbSopenharmony_cibool DumpCommonUtils::GetCpuInfos(std::vector<CpuInfo> &infos) 11500600bfbSopenharmony_ci{ 11600600bfbSopenharmony_ci std::vector<std::string> names; 11700600bfbSopenharmony_ci if (!GetNamesInFolder("/sys/devices/system/cpu/", names)) { 11800600bfbSopenharmony_ci return false; 11900600bfbSopenharmony_ci } 12000600bfbSopenharmony_ci for (size_t i = 0; i < names.size(); i++) { 12100600bfbSopenharmony_ci std::string name = names[i]; 12200600bfbSopenharmony_ci if (!StartWith(name, CPU_STR)) { 12300600bfbSopenharmony_ci continue; 12400600bfbSopenharmony_ci } 12500600bfbSopenharmony_ci std::string cpuId = name.substr(CPU_STR.size()); 12600600bfbSopenharmony_ci if (cpuId.empty() || (!IsNumericStr(cpuId))) { 12700600bfbSopenharmony_ci continue; 12800600bfbSopenharmony_ci } 12900600bfbSopenharmony_ci CpuInfo cpuInfo; 13000600bfbSopenharmony_ci StrToInt(cpuId, cpuInfo.id_); 13100600bfbSopenharmony_ci infos.push_back(cpuInfo); 13200600bfbSopenharmony_ci } 13300600bfbSopenharmony_ci return true; 13400600bfbSopenharmony_ci} 13500600bfbSopenharmony_ci 13600600bfbSopenharmony_ciDumpCommonUtils::PidInfo::PidInfo() 13700600bfbSopenharmony_ci{ 13800600bfbSopenharmony_ci Reset(); 13900600bfbSopenharmony_ci} 14000600bfbSopenharmony_ci 14100600bfbSopenharmony_civoid DumpCommonUtils::PidInfo::Reset() 14200600bfbSopenharmony_ci{ 14300600bfbSopenharmony_ci pid_ = UNSET; 14400600bfbSopenharmony_ci uid_ = UNSET; 14500600bfbSopenharmony_ci gid_ = UNSET; 14600600bfbSopenharmony_ci ppid_ = UNSET; 14700600bfbSopenharmony_ci name_.clear(); 14800600bfbSopenharmony_ci cmdline_.clear(); 14900600bfbSopenharmony_ci} 15000600bfbSopenharmony_ci 15100600bfbSopenharmony_cibool DumpCommonUtils::GetPidInfos(std::vector<PidInfo> &infos, bool all) 15200600bfbSopenharmony_ci{ 15300600bfbSopenharmony_ci std::vector<std::string> names; 15400600bfbSopenharmony_ci if (!GetNamesInFolder("/proc/", names)) { 15500600bfbSopenharmony_ci return false; 15600600bfbSopenharmony_ci } 15700600bfbSopenharmony_ci for (size_t i = 0; i < names.size(); i++) { 15800600bfbSopenharmony_ci std::string name = names[i]; 15900600bfbSopenharmony_ci if (name.empty()) { 16000600bfbSopenharmony_ci continue; 16100600bfbSopenharmony_ci } 16200600bfbSopenharmony_ci if (!IsNumericStr(name)) { 16300600bfbSopenharmony_ci continue; 16400600bfbSopenharmony_ci } 16500600bfbSopenharmony_ci PidInfo pidInfo; 16600600bfbSopenharmony_ci StrToInt(name, pidInfo.pid_); 16700600bfbSopenharmony_ci GetProcessInfo(pidInfo.pid_, pidInfo); 16800600bfbSopenharmony_ci if (all) { 16900600bfbSopenharmony_ci GetProcessNameByPid(pidInfo.pid_, pidInfo.cmdline_); 17000600bfbSopenharmony_ci } 17100600bfbSopenharmony_ci infos.push_back(pidInfo); 17200600bfbSopenharmony_ci } 17300600bfbSopenharmony_ci return true; 17400600bfbSopenharmony_ci} 17500600bfbSopenharmony_ci 17600600bfbSopenharmony_cibool DumpCommonUtils::IsUserPid(const std::string &pid) 17700600bfbSopenharmony_ci{ 17800600bfbSopenharmony_ci string path = "/proc/" + pid + "/smaps"; 17900600bfbSopenharmony_ci string lineContent; 18000600bfbSopenharmony_ci bool ret = FileUtils::GetInstance().LoadStringFromProcCb(path, true, false, [&](const string& line) -> void { 18100600bfbSopenharmony_ci lineContent += line; 18200600bfbSopenharmony_ci }); 18300600bfbSopenharmony_ci if (!ret) { 18400600bfbSopenharmony_ci return false; 18500600bfbSopenharmony_ci } 18600600bfbSopenharmony_ci if (!lineContent.empty()) { 18700600bfbSopenharmony_ci return true; 18800600bfbSopenharmony_ci } 18900600bfbSopenharmony_ci return false; 19000600bfbSopenharmony_ci} 19100600bfbSopenharmony_ci 19200600bfbSopenharmony_cibool DumpCommonUtils::GetUserPids(std::vector<int> &pids) 19300600bfbSopenharmony_ci{ 19400600bfbSopenharmony_ci std::vector<std::string> files; 19500600bfbSopenharmony_ci if (!GetNamesInFolder("/proc/", files)) { 19600600bfbSopenharmony_ci return false; 19700600bfbSopenharmony_ci } 19800600bfbSopenharmony_ci 19900600bfbSopenharmony_ci for (auto file : files) { 20000600bfbSopenharmony_ci if (file.empty()) { 20100600bfbSopenharmony_ci continue; 20200600bfbSopenharmony_ci } 20300600bfbSopenharmony_ci if (!IsNumericStr(file)) { 20400600bfbSopenharmony_ci continue; 20500600bfbSopenharmony_ci } 20600600bfbSopenharmony_ci 20700600bfbSopenharmony_ci if (!IsUserPid(file)) { 20800600bfbSopenharmony_ci continue; 20900600bfbSopenharmony_ci } 21000600bfbSopenharmony_ci 21100600bfbSopenharmony_ci int pid; 21200600bfbSopenharmony_ci StrToInt(file, pid); 21300600bfbSopenharmony_ci 21400600bfbSopenharmony_ci pids.push_back(pid); 21500600bfbSopenharmony_ci } 21600600bfbSopenharmony_ci return true; 21700600bfbSopenharmony_ci} 21800600bfbSopenharmony_ci 21900600bfbSopenharmony_cibool DumpCommonUtils::GetLinesInFile(const std::string& file, std::vector<std::string>& lines) 22000600bfbSopenharmony_ci{ 22100600bfbSopenharmony_ci std::string content; 22200600bfbSopenharmony_ci bool ret = FileUtils::GetInstance().LoadStringFromProcCb(file, false, false, [&](const std::string& line) -> void { 22300600bfbSopenharmony_ci content += line; 22400600bfbSopenharmony_ci }); 22500600bfbSopenharmony_ci if (!ret) { 22600600bfbSopenharmony_ci return false; 22700600bfbSopenharmony_ci } 22800600bfbSopenharmony_ci SplitStr(content, "\n", lines); 22900600bfbSopenharmony_ci return true; 23000600bfbSopenharmony_ci} 23100600bfbSopenharmony_ci 23200600bfbSopenharmony_cibool DumpCommonUtils::GetNamesInFolder(const std::string& folder, std::vector<std::string>& names) 23300600bfbSopenharmony_ci{ 23400600bfbSopenharmony_ci bool ret = false; 23500600bfbSopenharmony_ci DIR* dir = nullptr; 23600600bfbSopenharmony_ci if ((dir = opendir(folder.c_str())) != nullptr) { 23700600bfbSopenharmony_ci dirent* ptr = nullptr; 23800600bfbSopenharmony_ci while ((ptr = readdir(dir)) != nullptr) { 23900600bfbSopenharmony_ci std::string name = ptr->d_name; 24000600bfbSopenharmony_ci if ((name == ".") || (name == "..")) { 24100600bfbSopenharmony_ci continue; 24200600bfbSopenharmony_ci } 24300600bfbSopenharmony_ci names.push_back(name); 24400600bfbSopenharmony_ci } 24500600bfbSopenharmony_ci closedir(dir); 24600600bfbSopenharmony_ci ret = true; 24700600bfbSopenharmony_ci } 24800600bfbSopenharmony_ci return ret; 24900600bfbSopenharmony_ci} 25000600bfbSopenharmony_ci 25100600bfbSopenharmony_cibool DumpCommonUtils::StartWith(const std::string& str, const std::string& head) 25200600bfbSopenharmony_ci{ 25300600bfbSopenharmony_ci if (str.length() < head.length()) { 25400600bfbSopenharmony_ci return false; 25500600bfbSopenharmony_ci } 25600600bfbSopenharmony_ci return (str.compare(0, head.size(), head) == 0); 25700600bfbSopenharmony_ci} 25800600bfbSopenharmony_ci 25900600bfbSopenharmony_cibool DumpCommonUtils::GetProcessNameByPid(int pid, std::string& name) 26000600bfbSopenharmony_ci{ 26100600bfbSopenharmony_ci char filesysdir[128] = { 0 }; 26200600bfbSopenharmony_ci if (sprintf_s(filesysdir, sizeof(filesysdir), "/proc/%d/cmdline", pid) < 0) { 26300600bfbSopenharmony_ci return false; 26400600bfbSopenharmony_ci } 26500600bfbSopenharmony_ci std::string filePath = filesysdir; 26600600bfbSopenharmony_ci std::string content; 26700600bfbSopenharmony_ci bool ret = FileUtils::GetInstance().LoadStringFromProcCb(filePath, false, false, [&](const string& line) -> void { 26800600bfbSopenharmony_ci content += line; 26900600bfbSopenharmony_ci }); 27000600bfbSopenharmony_ci if (!ret) { 27100600bfbSopenharmony_ci return false; 27200600bfbSopenharmony_ci } 27300600bfbSopenharmony_ci vector<string> names; 27400600bfbSopenharmony_ci StringUtils::GetInstance().StringSplit(content, " ", names); 27500600bfbSopenharmony_ci if (names.empty()) { 27600600bfbSopenharmony_ci return false; 27700600bfbSopenharmony_ci } 27800600bfbSopenharmony_ci vector<string> longNames; 27900600bfbSopenharmony_ci StringUtils::GetInstance().StringSplit(names[0], "/", longNames); 28000600bfbSopenharmony_ci if (longNames.empty()) { 28100600bfbSopenharmony_ci return false; 28200600bfbSopenharmony_ci } 28300600bfbSopenharmony_ci if (names[0].find("/bin") != std::string::npos) { 28400600bfbSopenharmony_ci name = longNames[longNames.size() - 1]; 28500600bfbSopenharmony_ci } else { 28600600bfbSopenharmony_ci name = names[0]; 28700600bfbSopenharmony_ci } 28800600bfbSopenharmony_ci return true; 28900600bfbSopenharmony_ci} 29000600bfbSopenharmony_ci 29100600bfbSopenharmony_cibool DumpCommonUtils::GetProcessInfo(int pid, PidInfo &info) 29200600bfbSopenharmony_ci{ 29300600bfbSopenharmony_ci info.Reset(); 29400600bfbSopenharmony_ci char filesysdir[128] = { 0 }; 29500600bfbSopenharmony_ci if (sprintf_s(filesysdir, sizeof(filesysdir), "/proc/%d/status", pid) < 0) { 29600600bfbSopenharmony_ci return false; 29700600bfbSopenharmony_ci } 29800600bfbSopenharmony_ci std::string file = filesysdir; 29900600bfbSopenharmony_ci std::vector<std::string> lines; 30000600bfbSopenharmony_ci if (!GetLinesInFile(file, lines)) { 30100600bfbSopenharmony_ci return false; 30200600bfbSopenharmony_ci } 30300600bfbSopenharmony_ci const std::string splitKeyValueToken = ":"; 30400600bfbSopenharmony_ci const std::string splitValuesToken = "\t"; 30500600bfbSopenharmony_ci for (size_t i = 0; i < lines.size(); i++) { 30600600bfbSopenharmony_ci std::vector<std::string> keyValue; 30700600bfbSopenharmony_ci SplitStr(lines[i], splitKeyValueToken, keyValue); 30800600bfbSopenharmony_ci if (keyValue.size() < LINE_ITEM_MIN) { 30900600bfbSopenharmony_ci continue; 31000600bfbSopenharmony_ci } 31100600bfbSopenharmony_ci std::string key = keyValue[LINE_KEY]; 31200600bfbSopenharmony_ci std::string val = TrimStr(keyValue[LINE_VALUE], '\t'); 31300600bfbSopenharmony_ci std::vector<std::string> values; 31400600bfbSopenharmony_ci SplitStr(val, splitValuesToken, values, true); 31500600bfbSopenharmony_ci if (values.empty()) { 31600600bfbSopenharmony_ci continue; 31700600bfbSopenharmony_ci } 31800600bfbSopenharmony_ci std::string val0 = values[LINE_VALUE_0]; 31900600bfbSopenharmony_ci if (key == "Pid") { 32000600bfbSopenharmony_ci StrToInt(val0, info.pid_); 32100600bfbSopenharmony_ci } else if (key == "PPid") { 32200600bfbSopenharmony_ci StrToInt(val0, info.ppid_); 32300600bfbSopenharmony_ci } else if (key == "Uid") { 32400600bfbSopenharmony_ci StrToInt(val0, info.uid_); 32500600bfbSopenharmony_ci } else if (key == "Gid") { 32600600bfbSopenharmony_ci StrToInt(val0, info.gid_); 32700600bfbSopenharmony_ci } else if (key == "Name") { 32800600bfbSopenharmony_ci info.name_ = val; 32900600bfbSopenharmony_ci } else { 33000600bfbSopenharmony_ci continue; 33100600bfbSopenharmony_ci } 33200600bfbSopenharmony_ci if ((info.pid_ > UNSET) && (info.ppid_ > UNSET) && (info.uid_ > UNSET) && (info.gid_ > UNSET)) { 33300600bfbSopenharmony_ci return true; 33400600bfbSopenharmony_ci } 33500600bfbSopenharmony_ci } 33600600bfbSopenharmony_ci return false; 33700600bfbSopenharmony_ci} 33800600bfbSopenharmony_ci 33900600bfbSopenharmony_ciint DumpCommonUtils::FindDigitIndex(const std::string& fullFileName) 34000600bfbSopenharmony_ci{ 34100600bfbSopenharmony_ci for (size_t i = 0; i < fullFileName.size(); i++) { 34200600bfbSopenharmony_ci if (std::isdigit(fullFileName[i])) { 34300600bfbSopenharmony_ci return i; 34400600bfbSopenharmony_ci } 34500600bfbSopenharmony_ci } 34600600bfbSopenharmony_ci return static_cast<int>(fullFileName.size()); 34700600bfbSopenharmony_ci} 34800600bfbSopenharmony_ci} // namespace HiviewDFX 34900600bfbSopenharmony_ci} // namespace OHOS 350