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 #include "manager/dump_implement.h"
16 #include "iservice_registry.h"
17 #include "hilog_wrapper.h"
18 #include "util/config_utils.h"
19 #include "factory/cpu_dumper_factory.h"
20 #include "factory/file_dumper_factory.h"
21 #include "factory/env_param_dumper_factory.h"
22 #include "factory/cmd_dumper_factory.h"
23 #include "factory/api_dumper_factory.h"
24 #include "factory/properties_dumper_factory.h"
25 #include "factory/sa_dumper_factory.h"
26 #include "factory/list_dumper_factory.h"
27 #include "factory/version_dumper_factory.h"
28 #include "factory/column_rows_filter_factory.h"
29 #include "factory/file_format_dump_filter_factory.h"
30 #include "factory/fd_output_factory.h"
31 #include "factory/zip_output_factory.h"
32 #include "factory/dumper_group_factory.h"
33 #include "factory/memory_dumper_factory.h"
34 #include "factory/traffic_dumper_factory.h"
35 #include "dump_utils.h"
36 #include "string_ex.h"
37 #include "file_ex.h"
38 #include "util/string_utils.h"
39 #include "common/dumper_constant.h"
40 #include "securec.h"
41 #include "parameters.h"
42 #include "parameter.h"
43 namespace OHOS {
44 namespace HiviewDFX {
45
DumpImplement()46 DumpImplement::DumpImplement()
47 {
48 AddExecutorFactoryToMap();
49 }
50
~DumpImplement()51 DumpImplement::~DumpImplement()
52 {
53 }
54
AddExecutorFactoryToMap()55 void DumpImplement::AddExecutorFactoryToMap()
56 {
57 ptrExecutorFactoryMap_ = std::make_shared<ExecutorFactoryMap>();
58 ptrExecutorFactoryMap_->insert(std::make_pair(DumperConstant::CPU_DUMPER, std::make_shared<CPUDumperFactory>()));
59 ptrExecutorFactoryMap_->insert(std::make_pair(DumperConstant::FILE_DUMPER, std::make_shared<FileDumperFactory>()));
60 ptrExecutorFactoryMap_->insert(
61 std::make_pair(DumperConstant::ENV_PARAM_DUMPER, std::make_shared<EnvParamDumperFactory>()));
62 ptrExecutorFactoryMap_->insert(std::make_pair(DumperConstant::CMD_DUMPER, std::make_shared<CMDDumperFactory>()));
63 ptrExecutorFactoryMap_->insert(std::make_pair(DumperConstant::API_DUMPER, std::make_shared<APIDumperFactory>()));
64 ptrExecutorFactoryMap_->insert(
65 std::make_pair(DumperConstant::PROPERTIES_DUMPER, std::make_shared<PropertiesDumperFactory>()));
66 ptrExecutorFactoryMap_->insert(std::make_pair(DumperConstant::LIST_DUMPER, std::make_shared<ListDumperFactory>()));
67 ptrExecutorFactoryMap_->insert(
68 std::make_pair(DumperConstant::VERSION_DUMPER, std::make_shared<VersionDumperFactory>()));
69 ptrExecutorFactoryMap_->insert(std::make_pair(DumperConstant::SA_DUMPER, std::make_shared<SADumperFactory>()));
70 ptrExecutorFactoryMap_->insert(
71 std::make_pair(DumperConstant::COLUMN_ROWS_FILTER, std::make_shared<ColumnRowsFilterFactory>()));
72 ptrExecutorFactoryMap_->insert(
73 std::make_pair(DumperConstant::FILE_FORMAT_DUMP_FILTER, std::make_shared<FileFormatDumpFilterFactory>()));
74 ptrExecutorFactoryMap_->insert(std::make_pair(DumperConstant::GROUP, std::make_shared<DumperGroupFactory>()));
75 ptrExecutorFactoryMap_->insert(
76 std::make_pair(DumperConstant::MEMORY_DUMPER, std::make_shared<MemoryDumperFactory>()));
77 ptrExecutorFactoryMap_->insert(
78 std::make_pair(DumperConstant::TRAFFIC_DUMPER, std::make_shared<TrafficDumperFactory>()));
79 }
80
Main(int argc,char * argv[],const std::shared_ptr<RawParam> & reqCtl)81 DumpStatus DumpImplement::Main(int argc, char *argv[], const std::shared_ptr<RawParam> &reqCtl)
82 {
83 std::shared_ptr<DumperParameter> ptrDumperParameter = std::make_shared<DumperParameter>();
84 ptrDumperParameter->setClientCallback(reqCtl);
85 ptrDumperParameter->SetPid(reqCtl->GetPid());
86 ptrDumperParameter->SetUid(reqCtl->GetUid());
87 DumpStatus ret = CmdParse(argc, argv, ptrDumperParameter);
88 if (ret != DumpStatus::DUMP_OK) {
89 DUMPER_HILOGE(MODULE_COMMON, "Parse cmd FAIL!!!");
90 return ret;
91 }
92
93 ConfigUtils::GetDumperConfigs(ptrDumperParameter);
94 std::vector<std::shared_ptr<DumpCfg>> &configs = ptrDumperParameter->GetExecutorConfigList();
95 DUMPER_HILOGD(MODULE_COMMON, "debug|Main configs size is %{public}zu", configs.size());
96 if (configs.size() == 0) {
97 DUMPER_HILOGE(MODULE_COMMON, "Executor config list is empty, so can not dump.");
98 return DumpStatus::DUMP_FAIL;
99 }
100 bool isZip = ptrDumperParameter->GetOpts().IsDumpZip();
101 std::vector<std::shared_ptr<HidumperExecutor>> hidumperExecutors;
102 setExecutorList(hidumperExecutors, configs, isZip);
103
104 if (hidumperExecutors.empty()) {
105 DUMPER_HILOGE(MODULE_COMMON, "Executor list is empty, so dump fail.");
106 return DumpStatus::DUMP_FAIL;
107 }
108
109 reqCtl->SetProgressEnabled(isZip);
110 if (isZip) {
111 reqCtl->SetTitle(",The result is:" + path_);
112 } else {
113 reqCtl->SetTitle("");
114 }
115 HidumperExecutor::StringMatrix dumpDatas = std::make_shared<std::vector<std::vector<std::string>>>();
116 ret = DumpDatas(hidumperExecutors, ptrDumperParameter, dumpDatas);
117 if (ret != DumpStatus::DUMP_OK) {
118 DUMPER_HILOGE(MODULE_COMMON, "DUMP FAIL!!!");
119 return ret;
120 }
121 return DumpStatus::DUMP_OK;
122 }
123
CmdParse(int argc,char * argv[],std::shared_ptr<DumperParameter> & dumpParameter)124 DumpStatus DumpImplement::CmdParse(int argc, char *argv[], std::shared_ptr<DumperParameter> &dumpParameter)
125 {
126 if (argc > ARG_MAX_COUNT) {
127 LOG_ERR("too many arguments(%d), limit size %d.\n", argc, ARG_MAX_COUNT);
128 return DumpStatus::DUMP_FAIL;
129 }
130 for (int i = 0; i < argc; i++) {
131 if (argv[i] == nullptr) {
132 LOG_ERR("argument(%d) is null.\n", i);
133 return DumpStatus::DUMP_FAIL;
134 }
135 size_t len = strlen(argv[i]);
136 if (len == 0) {
137 LOG_ERR("argument(%d) is empty.\n", i);
138 return DumpStatus::DUMP_FAIL;
139 }
140 if (len > SINGLE_ARG_MAXLEN) {
141 LOG_ERR("too long argument(%d), limit size %d.\n", i, SINGLE_ARG_MAXLEN);
142 return DumpStatus::DUMP_FAIL;
143 }
144 }
145 DumperOpts opts;
146 DumpStatus status = CmdParseWithParameter(dumpParameter, argc, argv, opts);
147 if (status != DumpStatus::DUMP_OK) {
148 return status;
149 }
150 if (!opts.IsSelectAny()) {
151 // 注:hidumper不添加任何参数时,dump全部内容;IPC方式dump时,仅dump 当前进程的CPU和memory情况
152 int clientPid = dumpParameter->GetPid(); // to be set value
153 if (IsHidumperClientProcess(clientPid)) {
154 opts.AddSelectAll();
155 opts.isAppendix_ = true;
156 } else {
157 opts.isDumpCpuFreq_ = true;
158 opts.isDumpCpuUsage_ = true;
159 opts.cpuUsagePid_ = clientPid;
160 opts.isDumpMem_ = true;
161 opts.memPid_ = clientPid;
162 }
163 dumpParameter->SetPid(clientPid);
164 }
165
166 dumpParameter->SetOpts(opts);
167 return DumpStatus::DUMP_OK;
168 }
169
IsHidumperClientProcess(int pid)170 bool DumpImplement::IsHidumperClientProcess(int pid)
171 {
172 bool ret = false;
173 std::string procName;
174 if (DumpCommonUtils::GetProcessNameByPid(pid, procName)) {
175 ret = (procName.find("hidumper") != std::string::npos);
176 }
177 DUMPER_HILOGD(
178 MODULE_COMMON, "debug|ret=%{public}d, pid=%{public}d, procName=%{public}s", ret, pid, procName.c_str());
179 return ret;
180 }
181
CmdParseWithParameter(int argc,char * argv[],DumperOpts & opts_)182 DumpStatus DumpImplement::CmdParseWithParameter(int argc, char *argv[], DumperOpts &opts_)
183 {
184 optind = 0; // reset getopt_long
185 opterr = 0; // getopt not show error info
186 const char optStr[] = "-ht:lcsa:epv";
187 bool loop = true;
188 while (loop) {
189 int optionIndex = 0;
190 static struct option longOptions[] = {{"cpufreq", no_argument, 0, 0},
191 {"cpuusage", optional_argument, 0, 0},
192 {"mem", optional_argument, 0, 0},
193 {"net", no_argument, 0, 0},
194 {"storage", no_argument, 0, 0},
195 {"zip", no_argument, 0, 0},
196 {"test", no_argument, 0, 0},
197 {"mem-smaps", required_argument, 0, 0},
198 {0, 0, 0, 0}};
199 int c = getopt_long(argc, argv, optStr, longOptions, &optionIndex);
200 if (c == -1) {
201 break;
202 } else if (c == 0) {
203 DumpStatus status = ParseLongCmdOption(argc, opts_, longOptions, optionIndex, argv);
204 if (status != DumpStatus::DUMP_OK) {
205 return status;
206 }
207 std::string debugMode = "0";
208 debugMode = OHOS::system::GetParameter("const.debuggable", debugMode);
209 std::string buildVersion = GetDisplayVersion();
210 if (opts_.isShowSmaps_ && debugMode == "0" && buildVersion.find("log") != std::string::npos) {
211 break;
212 }
213 if (opts_.isShowSmaps_ && debugMode == "0") {
214 CmdHelp();
215 return DumpStatus::DUMP_HELP;
216 }
217 } else if (c == 'h') {
218 CmdHelp();
219 return DumpStatus::DUMP_HELP;
220 } else if (c == '?') {
221 CheckIncorrectCmdOption(optStr, argv);
222 return DumpStatus::DUMP_INVALID_ARG;
223 } else {
224 DumpStatus status = ParseShortCmdOption(c, opts_, argc, argv);
225 if (status != DumpStatus::DUMP_OK) {
226 return status;
227 }
228 }
229 }
230 DumpStatus status = CheckProcessAlive(opts_);
231 if (status != DumpStatus::DUMP_OK) {
232 return status;
233 }
234 RemoveDuplicateString(opts_);
235 return DumpStatus::DUMP_OK;
236 }
237
CmdParseWithParameter(std::shared_ptr<DumperParameter> & dumpParameter,int argc,char * argv[],DumperOpts & opts)238 DumpStatus DumpImplement::CmdParseWithParameter(std::shared_ptr<DumperParameter> &dumpParameter, int argc, char *argv[],
239 DumperOpts &opts)
240 {
241 DUMPER_HILOGD(MODULE_COMMON, "enter|");
242 std::lock_guard<std::mutex> lock(mutexCmdLock_); // lock for optind value safe
243 ptrReqCtl_ = dumpParameter->getClientCallback();
244 DumpStatus ret = CmdParseWithParameter(argc, argv, opts);
245 if (ret == DumpStatus::DUMP_OK) {
246 std::string errorStr;
247 if (!opts.CheckOptions(errorStr)) {
248 SendErrorMessage(invalidError_ + errorStr);
249 ret = DumpStatus::DUMP_INVALID_ARG;
250 }
251 }
252 ptrReqCtl_ = nullptr;
253 DUMPER_HILOGD(MODULE_COMMON, "leave|ret=%{public}d", ret);
254 return ret;
255 }
256
SetCmdParameter(int argc,char * argv[],DumperOpts & opts_)257 DumpStatus DumpImplement::SetCmdParameter(int argc, char *argv[], DumperOpts &opts_)
258 {
259 DumpStatus status = DumpStatus::DUMP_OK;
260 DUMPER_HILOGD(MODULE_COMMON,
261 "debug|SetCmdParameter optind is %{public}d"
262 " argc is %{public}d",
263 optind,
264 argc);
265 if (optind > 1 && optind <= argc) {
266 if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "--cpuusage")) {
267 status = SetCmdIntegerParameter(argv[optind - 1], opts_.cpuUsagePid_);
268 } else if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "--log")) {
269 opts_.logArgs_.push_back(argv[optind - 1]);
270 } else if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "--mem")) {
271 status = SetCmdIntegerParameter(argv[optind - 1], opts_.memPid_);
272 } else if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "--net")) {
273 status = SetCmdIntegerParameter(argv[optind - 1], opts_.netPid_);
274 } else if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "--storage")) {
275 status = SetCmdIntegerParameter(argv[optind - 1], opts_.storagePid_);
276 } else if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "-c")) {
277 opts_.systemArgs_.push_back(argv[optind - 1]);
278 } else if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "-p")) {
279 status = SetCmdIntegerParameter(argv[optind - 1], opts_.processPid_);
280 } else if (IsSADumperOption(argv)) {
281 opts_.abilitieNames_.push_back(argv[optind - 1]);
282 } else {
283 std::string optionName = RemoveCharacterFromStr(argv[optind - 1], '-');
284 std::string errorStr = unrecognizedError_ + optionName;
285 SendErrorMessage(errorStr);
286 return DumpStatus::DUMP_FAIL;
287 }
288 }
289 return status;
290 }
291
GetTime()292 std::string DumpImplement::GetTime()
293 {
294 struct timeval curTime;
295 gettimeofday(&curTime, nullptr);
296 int milli = curTime.tv_usec / 1000;
297
298 char buffer[80] = {0};
299 struct tm nowTime;
300 localtime_r(&curTime.tv_sec, &nowTime);
301 (void)strftime(buffer, sizeof(buffer), "%Y%m%d-%H%M%S", &nowTime);
302
303 char currentTime[84] = {0};
304 if (sprintf_s(currentTime, sizeof(currentTime), "%s-%03d", buffer, milli) < 0) {
305 return "";
306 };
307
308 return currentTime;
309 }
310
ParseLongCmdOption(int argc,DumperOpts & opts_,const struct option longOptions[],const int & optionIndex,char * argv[])311 DumpStatus DumpImplement::ParseLongCmdOption(int argc, DumperOpts &opts_, const struct option longOptions[],
312 const int &optionIndex, char *argv[])
313 {
314 path_ = "";
315 if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "cpufreq")) {
316 opts_.isDumpCpuFreq_ = true;
317 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "cpuusage")) {
318 opts_.isDumpCpuUsage_ = true;
319 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "log")) {
320 opts_.isDumpLog_ = true;
321 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "mem")) {
322 opts_.isDumpMem_ = true;
323 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "net")) {
324 opts_.isDumpNet_ = true;
325 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "storage")) {
326 opts_.isDumpStorage_ = true;
327 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "zip")) {
328 path_ = ZIP_FOLDER + GetTime() + ".zip";
329 opts_.path_ = path_;
330 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "test")) {
331 opts_.isTest_ = true;
332 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "mem-smaps")) {
333 opts_.isShowSmaps_ = true;
334 DumpStatus status;
335 if (ARG_INDEX_OFFSET_LAST_OPTION < 0 || ARG_INDEX_OFFSET_LAST_OPTION >= argc) {
336 status = DumpStatus::DUMP_FAIL;
337 } else {
338 status = SetCmdIntegerParameter(argv[ARG_INDEX_OFFSET_LAST_OPTION], opts_.memPid_);
339 }
340 if (status != DumpStatus::DUMP_OK) {
341 return status;
342 }
343 }
344 return DumpStatus::DUMP_OK;
345 }
346
ParseShortCmdOption(int c,DumperOpts & opts_,int argc,char * argv[])347 DumpStatus DumpImplement::ParseShortCmdOption(int c, DumperOpts &opts_, int argc, char *argv[])
348 {
349 switch (c) {
350 case 'a': {
351 if (opts_.isDumpSystemAbility_) {
352 SplitStr(optarg, " ", opts_.abilitieArgs_);
353 } else {
354 std::string optionName = RemoveCharacterFromStr(argv[optind - 1], '-');
355 std::string errorStr = unrecognizedError_ + optionName;
356 SendErrorMessage(errorStr);
357 return DumpStatus::DUMP_INVALID_ARG;
358 }
359 break;
360 }
361 case 'c':
362 opts_.isDumpSystem_ = true;
363 break;
364 case 'e':
365 opts_.isFaultLog_ = true;
366 break;
367 case 'l':
368 opts_.isDumpList_ = true;
369 break;
370 case 's':
371 opts_.isDumpSystemAbility_ = true;
372 break;
373 case 'p':
374 opts_.isDumpProcesses_ = true;
375 break;
376 case 'v':
377 opts_.isShowSmapsInfo_ = true;
378 break;
379 case 't': {
380 DumpStatus timeOutStatus = SetCmdIntegerParameter(optarg, opts_.timeout_);
381 if (timeOutStatus != DumpStatus::DUMP_OK) {
382 return timeOutStatus;
383 }
384 opts_.timeout_ = (opts_.timeout_ == 0) ? INT32_MAX : opts_.timeout_;
385 break;
386 }
387 default: {
388 DumpStatus status = SetCmdParameter(argc, argv, opts_);
389 if (status != DumpStatus::DUMP_OK) {
390 return status;
391 }
392 break;
393 }
394 }
395 return DumpStatus::DUMP_OK;
396 }
397
SetCmdIntegerParameter(const std::string & str,int & value)398 DumpStatus DumpImplement::SetCmdIntegerParameter(const std::string &str, int &value)
399 {
400 if (!IsNumericStr(str)) {
401 DUMPER_HILOGE(MODULE_COMMON, "Invalid string arg %{public}s", str.c_str());
402 std::string errorStr = invalidError_ + str;
403 SendErrorMessage(errorStr);
404 return DumpStatus::DUMP_INVALID_ARG;
405 }
406 return StrToInt(str, value) ? DumpStatus::DUMP_OK : DumpStatus::DUMP_FAIL;
407 }
408
CmdHelp()409 void DumpImplement::CmdHelp()
410 {
411 const char *str =
412 "usage:\n"
413 " -h |help text for the tool\n"
414 " -lc |a list of system information clusters\n"
415 " -ls |a list of system abilities\n"
416 " -c |all system information clusters\n"
417 " -c [base system] |system information clusters labeled \"base\" and \"system\"\n"
418 " -s |all system abilities\n"
419 " -s [SA0 SA1] |system abilities labeled \"SA0\" and \"SA1\"\n"
420 " -s [SA] -a ['-h'] |system ability labeled \"SA\" with arguments \"-h\" specified\n"
421 " -e |faultlogs of crash history\n"
422 " --net [pid] |dump network information; if pid is specified,"
423 " dump traffic usage of specified pid\n"
424 " --storage [pid] |dump storage information; if pid is specified, dump /proc/pid/io\n"
425 " -p |processes information, include list and infromation of processes"
426 " and threads\n"
427 " -p [pid] |dump threads under pid, includes smap, block channel,"
428 " execute time, mountinfo\n"
429 " --cpuusage [pid] |dump cpu usage by processes and category; if PID is specified,"
430 " dump category usage of specified pid\n"
431 " --cpufreq |dump real CPU frequency of each core\n"
432 " --mem [pid] |dump memory usage of total; dump memory usage of specified"
433 " pid if pid was specified\n"
434 " --zip |compress output to /data/log/hidumper\n"
435 " --mem-smaps pid [-v] |display statistic in /proc/pid/smaps, use -v specify more details\n";
436 if (ptrReqCtl_ == nullptr) {
437 return;
438 }
439 int rawParamFd = ptrReqCtl_->GetOutputFd();
440 if (rawParamFd < 0) {
441 return;
442 }
443 SaveStringToFd(rawParamFd, str);
444 }
445
setExecutorList(std::vector<std::shared_ptr<HidumperExecutor>> & executors,const std::vector<std::shared_ptr<DumpCfg>> & configs,bool isZip)446 void DumpImplement::setExecutorList(std::vector<std::shared_ptr<HidumperExecutor>> &executors,
447 const std::vector<std::shared_ptr<DumpCfg>> &configs, bool isZip)
448 {
449 std::shared_ptr<HidumperExecutor> ptrOutput;
450
451 for (size_t i = 0; i < configs.size(); i++) {
452 std::shared_ptr<ExecutorFactory> ptrExecutorFactory;
453 if ((configs[i]->class_) == DumperConstant::FD_OUTPUT) {
454 if (isZip) {
455 ptrExecutorFactory = std::make_shared<ZipOutputFactory>();
456 } else {
457 ptrExecutorFactory = std::make_shared<FDOutputFactory>();
458 }
459
460 if (ptrOutput.get() == nullptr) {
461 ptrOutput = ptrExecutorFactory->CreateExecutor();
462 }
463 ptrOutput->SetDumpConfig(configs[i]);
464 executors.push_back(ptrOutput);
465 continue;
466 } else {
467 ExecutorFactoryMap::iterator it = ptrExecutorFactoryMap_->find(configs[i]->class_);
468 if (it != ptrExecutorFactoryMap_->end()) {
469 ptrExecutorFactory = it->second;
470 }
471 }
472
473 if (ptrExecutorFactory.get() == nullptr) {
474 DUMPER_HILOGE(MODULE_COMMON, "configs[%{public}zu].class_ is %{public}d", i, configs[i]->class_);
475 continue;
476 }
477 std::shared_ptr<HidumperExecutor> ptrExecutor = ptrExecutorFactory->CreateExecutor();
478 if (ptrExecutor != nullptr) {
479 configs[i]->executor_ = ptrExecutor;
480 ptrExecutor->SetDumpConfig(configs[i]);
481 }
482 executors.push_back(ptrExecutor);
483 }
484
485 // must clear.
486 for (auto cfg : configs) {
487 cfg->executor_ = nullptr;
488 }
489 }
490
DumpDatas(const std::vector<std::shared_ptr<HidumperExecutor>> & executors,const std::shared_ptr<DumperParameter> & dumpParameter,HidumperExecutor::StringMatrix dumpDatas)491 DumpStatus DumpImplement::DumpDatas(const std::vector<std::shared_ptr<HidumperExecutor>> &executors,
492 const std::shared_ptr<DumperParameter> &dumpParameter,
493 HidumperExecutor::StringMatrix dumpDatas)
494 {
495 auto callback = dumpParameter->getClientCallback();
496
497 std::string groupName = "";
498 std::vector<size_t> loopStack;
499 const size_t executorSum = executors.size();
500 for (size_t index = 0; index < executorSum; index++) {
501 callback->UpdateProgress(executors.size(), index);
502 if (callback->IsCanceled()) {
503 break;
504 }
505
506 auto dumpCfg = executors[index]->GetDumpConfig();
507 if (dumpCfg->IsDumper() && CheckGroupName(groupName, dumpCfg->section_)) {
508 AddGroupTitle(groupName, dumpDatas);
509 }
510
511 DumpStatus ret = DumpStatus::DUMP_FAIL;
512 ret = executors[index]->DoPreExecute(dumpParameter, dumpDatas);
513 if (ret != DumpStatus::DUMP_OK) {
514 continue;
515 }
516
517 ret = executors[index]->DoExecute();
518 if ((ret != DumpStatus::DUMP_OK) && (ret != DumpStatus::DUMP_MORE_DATA)) {
519 continue;
520 }
521
522 ret = executors[index]->DoAfterExecute();
523 if (dumpCfg->IsDumper() && dumpCfg->CanLoop() && (ret == DumpStatus::DUMP_MORE_DATA)) {
524 loopStack.push_back(index);
525 }
526
527 if (dumpCfg->IsOutput() || dumpCfg->IsGroup()) {
528 if (!loopStack.empty()) {
529 index = loopStack.back() - 1; // the 1 will add back by end for.
530 }
531 loopStack.clear(); // clear now.
532 }
533 }
534 for (auto executor : executors) {
535 executor->Reset();
536 }
537 callback->UpdateProgress(executors.size(), executors.size());
538 return DumpStatus::DUMP_OK;
539 }
540
AddGroupTitle(const std::string & groupName,HidumperExecutor::StringMatrix dumpDatas)541 void DumpImplement::AddGroupTitle(const std::string &groupName, HidumperExecutor::StringMatrix dumpDatas)
542 {
543 /**
544 * @brief The group title is followed
545 * '
546 * -------------------------------[groupName]-------------------------------
547 * '
548 */
549 std::vector<std::string> lineData;
550 lineData.push_back("");
551 dumpDatas->push_back(lineData);
552 std::vector<std::string>().swap(lineData);
553 lineData.push_back("-------------------------------[");
554 lineData.push_back(groupName);
555 lineData.push_back("]-------------------------------");
556 dumpDatas->push_back(lineData);
557 std::vector<std::string>().swap(lineData);
558 lineData.push_back("");
559 dumpDatas->push_back(lineData);
560 std::vector<std::string>().swap(lineData);
561 }
562
CheckGroupName(std::string & lastName,const std::string & curName)563 bool DumpImplement::CheckGroupName(std::string &lastName, const std::string &curName)
564 {
565 if (curName.compare("") == 0) {
566 return false;
567 }
568
569 if (lastName.compare(curName) == 0) {
570 return false;
571 }
572
573 lastName.assign(curName);
574 return true;
575 }
576
GetSystemAbilityManager()577 const sptr<ISystemAbilityManager> DumpImplement::GetSystemAbilityManager()
578 {
579 sam_ = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
580 if (sam_ == nullptr) {
581 DUMPER_HILOGE(MODULE_COMMON, "SystemAbilityManager not found.");
582 }
583 return sam_;
584 }
585
CheckIncorrectCmdOption(const char * optStr,char * argv[])586 void DumpImplement::CheckIncorrectCmdOption(const char *optStr, char *argv[])
587 {
588 if (optopt == 0) {
589 SendErrorMessage(unrecognizedError_ + RemoveCharacterFromStr(argv[optind - 1], '-'));
590 } else if (!IsShortOptionReqArg(optStr)) {
591 std::string errorStr = unrecognizedError_;
592 errorStr += optopt;
593 SendErrorMessage(errorStr);
594 }
595 }
596
IsShortOptionReqArg(const char * optStr)597 bool DumpImplement::IsShortOptionReqArg(const char *optStr)
598 {
599 int len = strlen(optStr);
600 for (int i = 0; i < len; i++) {
601 if (optStr[i] == optopt) {
602 SendErrorMessage(requireError_ + optStr[i]);
603 return true;
604 }
605 }
606 return false;
607 }
608
SendErrorMessage(const std::string & errorStr)609 void DumpImplement::SendErrorMessage(const std::string &errorStr)
610 {
611 if (ptrReqCtl_ == nullptr) {
612 return;
613 }
614 int rawParamFd = ptrReqCtl_->GetOutputFd();
615 if (rawParamFd < 0) {
616 return;
617 }
618 SaveStringToFd(rawParamFd, errorStr + "\n");
619 }
620
SendPidErrorMessage(int pid)621 void DumpImplement::SendPidErrorMessage(int pid)
622 {
623 if (ptrReqCtl_ == nullptr) {
624 return;
625 }
626 int rawParamFd = ptrReqCtl_->GetOutputFd();
627 if (rawParamFd < 0) {
628 return;
629 }
630 dprintf(rawParamFd, pidError_.c_str(), pid);
631 }
632
RemoveCharacterFromStr(const std::string & str,const char character)633 std::string DumpImplement::RemoveCharacterFromStr(const std::string &str, const char character)
634 {
635 std::string strTmp = str;
636 while (strTmp.find(character) != std::string::npos) {
637 strTmp.erase(strTmp.find(character), 1);
638 }
639 return strTmp;
640 }
641
IsLongOption(const std::string & str,const struct option longOptions[],int size)642 bool DumpImplement::IsLongOption(const std::string &str, const struct option longOptions[], int size)
643 {
644 for (int i = 0; i < (size - 1); i++) {
645 if (StringUtils::GetInstance().IsSameStr(str, longOptions[i].name)) {
646 return true;
647 }
648 }
649 return false;
650 }
651
IsSADumperOption(char * argv[])652 bool DumpImplement::IsSADumperOption(char *argv[])
653 {
654 for (int i = optind - 2; i > 0; i--) {
655 if (IsSubStr(argv[i], "-")) {
656 return StringUtils::GetInstance().IsSameStr(argv[i], "-s")
657 || StringUtils::GetInstance().IsSameStr(argv[i], "-a");
658 }
659 }
660 return false;
661 }
662
CheckProcessAlive(const DumperOpts & opts_)663 DumpStatus DumpImplement::CheckProcessAlive(const DumperOpts &opts_)
664 {
665 if ((opts_.cpuUsagePid_ > -1) && !DumpUtils::CheckProcessAlive(opts_.cpuUsagePid_)) {
666 SendPidErrorMessage(opts_.cpuUsagePid_);
667 return DumpStatus::DUMP_FAIL;
668 }
669 if ((opts_.memPid_ > -1) && !DumpUtils::CheckProcessAlive(opts_.memPid_)) {
670 SendPidErrorMessage(opts_.memPid_);
671 return DumpStatus::DUMP_FAIL;
672 }
673 if ((opts_.processPid_ > -1) && !DumpUtils::CheckProcessAlive(opts_.processPid_)) {
674 SendPidErrorMessage(opts_.processPid_);
675 return DumpStatus::DUMP_FAIL;
676 }
677 if ((opts_.storagePid_ > -1) && !DumpUtils::CheckProcessAlive(opts_.storagePid_)) {
678 SendPidErrorMessage(opts_.storagePid_);
679 return DumpStatus::DUMP_FAIL;
680 }
681 if ((opts_.netPid_ > -1) && !DumpUtils::CheckProcessAlive(opts_.netPid_)) {
682 SendPidErrorMessage(opts_.netPid_);
683 return DumpStatus::DUMP_FAIL;
684 }
685 return DumpStatus::DUMP_OK;
686 }
687
RemoveDuplicateString(DumperOpts & opts_)688 void DumpImplement::RemoveDuplicateString(DumperOpts &opts_)
689 {
690 DumpUtils::RemoveDuplicateString(opts_.logArgs_); // remove duplicate log names
691 DumpUtils::RemoveDuplicateString(opts_.systemArgs_); // remove duplicate system names
692 DumpUtils::RemoveDuplicateString(opts_.abilitieNames_); // remove duplicate ability names
693 }
694 } // namespace HiviewDFX
695 } // namespace OHOS
696