• 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     DUMPER_HILOGI(MODULE_COMMON, "info|CMDDumper Execute");
77     DumpStatus ret = DumpStatus::DUMP_OK;
78     if (needLoop_) {
79         // cmd dump one line
80         return ReadLineInCmd();
81     } else {
82         // cmd dump all line
83         do {
84             if (IsCanceled()) {
85                 break;
86             }
87             ret = ReadLineInCmd();
88         } while (ret == DumpStatus::DUMP_MORE_DATA);
89     }
90     DUMPER_HILOGI(MODULE_COMMON, "info|CMDDumper Execute end");
91     return ret;
92 }
93 
AfterExecute()94 DumpStatus CMDDumper::AfterExecute()
95 {
96     if (moreData_ && IsTimeout()) {
97         DUMPER_HILOGE(MODULE_COMMON, "error|cmd timeout");
98         std::vector<std::string> line_vector_timeout;
99         line_vector_timeout.push_back(GetTimeoutStr());
100         dumpDatas_->push_back(line_vector_timeout);
101         moreData_ = false;
102     }
103 
104     if (!moreData_) {
105         if (fp_ != nullptr) {
106             pclose(fp_);
107             fp_ = nullptr;
108         }
109         return DumpStatus::DUMP_OK;
110     }
111     return DumpStatus::DUMP_MORE_DATA;
112 }
113 
114 // provide interface to others
GetCmdInterface(const std::string & cmd,StringMatrix dumpDatas)115 DumpStatus CMDDumper::GetCmdInterface(const std::string& cmd, StringMatrix dumpDatas)
116 {
117     DumpStatus ret = DumpStatus::DUMP_MORE_DATA;
118     FILE* fp = popen((CMD_PREFIX + cmd).c_str(), "r");
119     if (fp == nullptr) {
120         return DumpStatus::DUMP_FAIL;
121     }
122     do {
123         ret = GetLineData(fp, dumpDatas);
124     } while (ret == DumpStatus::DUMP_MORE_DATA);
125     pclose(fp);
126     return ret;
127 }
128 
GetLineData(FILE * fp,StringMatrix dumpDatas)129 DumpStatus CMDDumper::GetLineData(FILE* fp, StringMatrix dumpDatas)
130 {
131     DumpStatus ret = DumpStatus::DUMP_MORE_DATA;
132     char* line_buffer = nullptr;
133     size_t len = 0;
134     ssize_t read = 0;
135     read = getline(&line_buffer, &len, fp);
136     if (read != -1) {
137         if (line_buffer[read - 1] == '\n') {
138             line_buffer[read - 1] = '\0'; // replease \n
139         }
140         std::string line = line_buffer;
141         std::vector<std::string> line_vector;
142         line_vector.push_back(line);
143         dumpDatas->push_back(line_vector);
144     } else {
145         if (feof(fp) == 0) { // ferror()
146             ret = DumpStatus::DUMP_FAIL;
147         } else {
148             ret = DumpStatus::DUMP_OK;
149         }
150     }
151     if (line_buffer != nullptr) {
152         free(line_buffer);
153         line_buffer = nullptr;
154     }
155     return ret;
156 }
157 
158 // read one line
ReadLineInCmd()159 DumpStatus CMDDumper::ReadLineInCmd()
160 {
161     if (fp_ == nullptr) {
162         return DumpStatus::DUMP_FAIL;
163     }
164     DumpStatus ret = GetLineData(fp_, dumpDatas_);
165     moreData_ = (ret == DumpStatus::DUMP_MORE_DATA);
166     return ret;
167 }
168 
ReplacePidInCmd(std::string & cmd,int pid)169 void CMDDumper::ReplacePidInCmd(std::string &cmd, int pid)
170 {
171     size_t pos = cmd.find("%pid");
172     if (pos != std::string::npos) {
173         cmd = cmd.replace(pos, strlen("%pid"), std::to_string(pid));
174         cmd_ = cmd;
175     }
176 }
177 
ReplaceCpuIdInCmd(std::string & cmd,int cpuId)178 void CMDDumper::ReplaceCpuIdInCmd(std::string &cmd, int cpuId)
179 {
180     size_t pos = cmd.find("%cpuid");
181     if (pos != std::string::npos) {
182         cmd = cmd.replace(pos, strlen("%cpuid"), std::to_string(cpuId));
183         cmd_ = cmd;
184     }
185 }
186 } // namespace HiviewDFX
187 } // namespace OHOS
188