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