• 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 "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