• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 "executor/cmd_dumper.h"
16 
17 #include "dump_common_utils.h"
18 #include "securec.h"
19 
20 namespace OHOS {
21 namespace HiviewDFX {
22 const std::string CMD_PREFIX = "/system/bin/";
CMDDumper()23 CMDDumper::CMDDumper() : fp_(nullptr)
24 {
25 }
26 
~CMDDumper()27 CMDDumper::~CMDDumper()
28 {
29     if (fp_ != nullptr) {
30         pclose(fp_);
31         fp_ = nullptr;
32     }
33 }
34 
PreExecute(const std::shared_ptr<DumperParameter> & parameter,StringMatrix dumpDatas)35 DumpStatus CMDDumper::PreExecute(const std::shared_ptr<DumperParameter>& parameter,
36     StringMatrix dumpDatas)
37 {
38     if (dumpDatas.get() == nullptr) {
39         return DumpStatus::DUMP_FAIL;
40     }
41     std::string cmd = ptrDumpCfg_->target_;
42     if (ptrDumpCfg_->args_ != nullptr) {
43         if (ptrDumpCfg_->args_->HasPid()) {
44             int pid = ptrDumpCfg_->args_->GetPid();
45             if (ptrDumpCfg_->name_ == "dumper_stack" && !DumpCommonUtils::IsUserPid(std::to_string(pid))) {
46                 return DumpStatus::DUMP_FAIL;
47             }
48             ReplacePidInCmd(cmd, pid);
49         }
50         if (ptrDumpCfg_->args_->HasCpuId()) {
51             int cpuId = ptrDumpCfg_->args_->GetCpuId();
52             ReplaceCpuIdInCmd(cmd, cpuId);
53         }
54     }
55     cmd_ = cmd;
56     needLoop_ = (ptrDumpCfg_->loop_ == DumperConstant::LOOP);
57     if (fp_ == nullptr) {
58         if ((fp_ = popen((CMD_PREFIX + cmd_).c_str(), "r")) == nullptr) {
59             return DumpStatus::DUMP_FAIL;
60         }
61     }
62     dumpDatas_ = dumpDatas;
63 
64     // Add only once!
65     if (lineData_.size() <= 0) {
66         std::string lineStr = "\ncmd is: ";
67         lineStr = lineStr + cmd_ + "\n\n";
68         lineData_.push_back(lineStr);
69         dumpDatas_->push_back(lineData_);
70     }
71     return DumpStatus::DUMP_OK;
72 }
73 
Execute()74 DumpStatus CMDDumper::Execute()
75 {
76     DumpStatus ret = DumpStatus::DUMP_OK;
77     if (needLoop_) {
78         // cmd dump one line
79         return ReadLineInCmd();
80     } else {
81         // cmd dump all line
82         do {
83             if (IsCanceled()) {
84                 break;
85             }
86             ret = ReadLineInCmd();
87         } while (ret == DumpStatus::DUMP_MORE_DATA);
88     }
89     return ret;
90 }
91 
AfterExecute()92 DumpStatus CMDDumper::AfterExecute()
93 {
94     if (moreData_ && IsTimeout()) {
95         DUMPER_HILOGE(MODULE_COMMON, "error|cmd timeout");
96         std::vector<std::string> line_vector_timeout;
97         line_vector_timeout.push_back(GetTimeoutStr());
98         dumpDatas_->push_back(line_vector_timeout);
99         moreData_ = false;
100     }
101 
102     if (!moreData_) {
103         if (fp_ != nullptr) {
104             pclose(fp_);
105             fp_ = nullptr;
106         }
107         return DumpStatus::DUMP_OK;
108     }
109     return DumpStatus::DUMP_MORE_DATA;
110 }
111 
112 // provide interface to others
GetCmdInterface(const std::string & cmd,StringMatrix dumpDatas)113 DumpStatus CMDDumper::GetCmdInterface(const std::string& cmd, StringMatrix dumpDatas)
114 {
115     DumpStatus ret = DumpStatus::DUMP_MORE_DATA;
116     FILE* fp = popen((CMD_PREFIX + cmd).c_str(), "r");
117     if (fp == nullptr) {
118         return DumpStatus::DUMP_FAIL;
119     }
120     do {
121         ret = GetLineData(fp, dumpDatas);
122     } while (ret == DumpStatus::DUMP_MORE_DATA);
123     pclose(fp);
124     return ret;
125 }
126 
GetLineData(FILE * fp,StringMatrix dumpDatas)127 DumpStatus CMDDumper::GetLineData(FILE* fp, StringMatrix dumpDatas)
128 {
129     DumpStatus ret = DumpStatus::DUMP_MORE_DATA;
130     char* line_buffer = nullptr;
131     size_t len = 0;
132     ssize_t read = 0;
133     read = getline(&line_buffer, &len, fp);
134     if (read != -1) {
135         if (line_buffer[read - 1] == '\n') {
136             line_buffer[read - 1] = '\0'; // replease \n
137         }
138         std::string line = line_buffer;
139         std::vector<std::string> line_vector;
140         line_vector.push_back(line);
141         dumpDatas->push_back(line_vector);
142     } else {
143         if (feof(fp) == 0) { // ferror()
144             ret = DumpStatus::DUMP_FAIL;
145         } else {
146             ret = DumpStatus::DUMP_OK;
147         }
148     }
149     if (line_buffer != nullptr) {
150         free(line_buffer);
151         line_buffer = nullptr;
152     }
153     return ret;
154 }
155 
156 // read one line
ReadLineInCmd()157 DumpStatus CMDDumper::ReadLineInCmd()
158 {
159     if (fp_ == nullptr) {
160         return DumpStatus::DUMP_FAIL;
161     }
162     DumpStatus ret = GetLineData(fp_, dumpDatas_);
163     moreData_ = (ret == DumpStatus::DUMP_MORE_DATA);
164     return ret;
165 }
166 
ReplacePidInCmd(std::string & cmd,int pid)167 void CMDDumper::ReplacePidInCmd(std::string &cmd, int pid)
168 {
169     size_t pos = cmd.find("%pid");
170     if (pos != std::string::npos) {
171         cmd = cmd.replace(pos, strlen("%pid"), std::to_string(pid));
172         cmd_ = cmd;
173     }
174 }
175 
ReplaceCpuIdInCmd(std::string & cmd,int cpuId)176 void CMDDumper::ReplaceCpuIdInCmd(std::string &cmd, int cpuId)
177 {
178     size_t pos = cmd.find("%cpuid");
179     if (pos != std::string::npos) {
180         cmd = cmd.replace(pos, strlen("%cpuid"), std::to_string(cpuId));
181         cmd_ = cmd;
182     }
183 }
184 } // namespace HiviewDFX
185 } // namespace OHOS
186