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