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/sa_dumper.h"
16 #include <cstdio>
17 #include <thread>
18 #include <unistd.h>
19 #include "dump_utils.h"
20 #include "securec.h"
21
22 namespace OHOS {
23 namespace HiviewDFX {
24 namespace {
25 const int PIPE_LENGTH = 2;
26 const int PIPE_INIT = 0;
27 const int PIPE_READ = 0;
28 const int PIPE_WRITE = 1;
29 const int LINE_LENGTH = 256;
30 const char *SEPARATOR_TEMPLATE = "\n----------------------------------%s---------------------------------\n";
31
32 using StringMatrix = std::shared_ptr<std::vector<std::vector<std::string>>>;
33
34 // UString class
35 class UString {
36 public:
UString(const std::u16string & String)37 explicit UString(const std::u16string &String)
38 {
39 string_ = std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> {}.to_bytes(String);
40 }
41
42 public:
GetString() const43 const char *GetString() const
44 {
45 return string_.c_str();
46 }
GetInteger() const47 int GetInteger() const
48 {
49 return stoi(string_);
50 }
51
52 private:
53 std::string string_;
54 };
55
56 // MatrixWriter
57 class MatrixWriter {
58 public:
MatrixWriter(StringMatrix Data)59 explicit MatrixWriter(StringMatrix Data) : spData_(Data)
60 {
61 }
62
63 public:
WriteLine(const char * Line)64 void WriteLine(const char *Line)
65 {
66 if (spData_) {
67 std::vector<std::string> lines;
68 lines.push_back(Line);
69 spData_->push_back(lines);
70 } else {
71 printf("%s\n", Line);
72 }
73 }
74
75 private:
76 StringMatrix spData_;
77 };
78
79 // PipeReader
80 class PipeReader {
81 public:
PipeReader(int Id,StringMatrix Data)82 PipeReader(int Id, StringMatrix Data) : id_(Id), spData_(Data)
83 {
84 fds_[PIPE_READ] = PIPE_INIT;
85 fds_[PIPE_WRITE] = PIPE_INIT;
86 pipe(fds_);
87 }
~PipeReader()88 ~PipeReader()
89 {
90 if (wt_.joinable()) {
91 wt_.join();
92 }
93 }
94
95 public:
GetWritePipe()96 int GetWritePipe()
97 {
98 return fds_[PIPE_WRITE];
99 }
Run()100 void Run()
101 {
102 wt_ = std::thread(Execute, id_, fds_[PIPE_READ], spData_);
103 }
Stop()104 void Stop()
105 {
106 close(fds_[PIPE_WRITE]);
107 }
Execute(int id,int fd,StringMatrix Data)108 static void Execute(int id, int fd, StringMatrix Data)
109 {
110 char *buff = (char *)malloc(LINE_LENGTH);
111 if (buff == nullptr) {
112 return;
113 }
114 FILE *fp = fdopen(fd, "r");
115 if (fp != nullptr) {
116 size_t size = LINE_LENGTH;
117 for (int i = 1;; ++i) {
118 int len = getline(&buff, &size, fp);
119 if (len <= 0) {
120 break;
121 }
122 if (buff[--len] == '\n') {
123 buff[len] = 0;
124 }
125 MatrixWriter(Data).WriteLine(buff);
126 }
127 fclose(fp);
128 }
129 free(buff);
130 }
131
132 private:
133 int id_;
134 StringMatrix spData_;
135 int fds_[PIPE_LENGTH];
136 std::thread wt_;
137 };
138 } // namespace
139
SADumper(void)140 SADumper::SADumper(void)
141 {
142 }
143
~SADumper(void)144 SADumper::~SADumper(void)
145 {
146 }
147
PreExecute(const std::shared_ptr<DumperParameter> & parameter,StringMatrix dump_datas)148 DumpStatus SADumper::PreExecute(const std::shared_ptr<DumperParameter> ¶meter, StringMatrix dump_datas)
149 {
150 result_ = dump_datas;
151 names_ = ptrDumpCfg_->args_->GetNameList();
152 StringVector args = ptrDumpCfg_->args_->GetArgList();
153 if (!args.empty() && names_.size() == 1) {
154 std::transform(args.begin(), args.end(), std::back_inserter(args_), Str8ToStr16);
155 }
156 return DumpStatus::DUMP_OK;
157 }
158
GetData(const std::string & name,const sptr<ISystemAbilityManager> & sam)159 DumpStatus SADumper::GetData(const std::string &name, const sptr<ISystemAbilityManager> &sam)
160 {
161 int id = DumpUtils::StrToId(name);
162 if (id == 0) {
163 DUMPER_HILOGD(MODULE_SERVICE, "no such ability id '%{public}s'\n", name.c_str());
164 return DumpStatus::DUMP_FAIL;
165 }
166 sptr<IRemoteObject> sa = sam->CheckSystemAbility(id);
167 if (sa == nullptr) {
168 DUMPER_HILOGD(MODULE_SERVICE, "no such system ability %{public}s\n", name.c_str());
169 return DumpStatus::DUMP_FAIL;
170 }
171 char line[LINE_LENGTH] = {};
172 int ret = sprintf_s(line, sizeof(line), SEPARATOR_TEMPLATE,
173 DumpUtils::ConvertSaIdToSaName(name).c_str());
174 if (ret < 0) {
175 DUMPER_HILOGD(MODULE_SERVICE, "print separator line fail!");
176 return DumpStatus::DUMP_FAIL;
177 }
178 MatrixWriter(result_).WriteLine(line);
179 PipeReader reader(id, result_);
180 reader.Run();
181 if (sa->Dump(reader.GetWritePipe(), args_) != ERR_OK) {
182 DUMPER_HILOGD(MODULE_SERVICE, "system ability:%{public}s dump fail!\n", name.c_str());
183 }
184 reader.Stop();
185 return DumpStatus::DUMP_OK;
186 }
187
Execute()188 DumpStatus SADumper::Execute()
189 {
190 sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
191 if (sam == nullptr) {
192 DUMPER_HILOGD(MODULE_SERVICE, "get samgr fail!");
193 return DumpStatus::DUMP_FAIL;
194 }
195 if (names_.empty()) {
196 U16StringVector vct = sam->ListSystemAbilities();
197 std::transform(vct.begin(), vct.end(), std::back_inserter(names_), Str16ToStr8);
198 }
199 for (size_t i = 0; i < names_.size(); ++i) {
200 if (GetData(names_[i], sam) != DumpStatus::DUMP_OK) {
201 DUMPER_HILOGD(MODULE_SERVICE, "system ability:%{public}s execute fail!\n", names_[i].c_str());
202 }
203 }
204 return DumpStatus::DUMP_OK;
205 }
206
AfterExecute()207 DumpStatus SADumper::AfterExecute()
208 {
209 return DumpStatus::DUMP_OK;
210 }
211 } // namespace HiviewDFX
212 } // namespace OHOS
213