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