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 "dump_utils.h"
16
17 #include <cerrno>
18 #include <csignal>
19 #include <fcntl.h>
20 #include <poll.h>
21 #include <set>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 #include <fstream>
25 #include <iostream>
26
27 #include <sys/prctl.h>
28 #include <sys/resource.h>
29 #include <sys/times.h>
30 #include <sys/types.h>
31 #include <sys/wait.h>
32
33 #include "common.h"
34 #include "datetime_ex.h"
35 #include "securec.h"
36 #include "string_ex.h"
37
38 #include "system_ability_definition.h"
39 #include "hilog_wrapper.h"
40
41 namespace OHOS {
42 namespace HiviewDFX {
IgnorePipeQuit()43 void DumpUtils::IgnorePipeQuit()
44 {
45 signal(SIGPIPE, SIG_IGN); // protect from pipe quit
46 }
47
IgnoreStdoutCache()48 void DumpUtils::IgnoreStdoutCache()
49 {
50 setvbuf(stdout, nullptr, _IONBF, 0); // never cache stdout
51 }
52
IgnoreOom()53 void DumpUtils::IgnoreOom()
54 {
55 setpriority(PRIO_PROCESS, 0, TOP_PRIORITY); // protect from OOM
56 }
57
SetAdj(int adj)58 void DumpUtils::SetAdj(int adj)
59 {
60 int fd = FdToWrite(FILE_CUR_OOM_ADJ);
61 if (fd < 0) {
62 return;
63 }
64 dprintf(fd, "%d", adj);
65 close(fd);
66 }
67
BoostPriority()68 void DumpUtils::BoostPriority()
69 {
70 IgnoreOom();
71 IgnorePipeQuit();
72 IgnoreStdoutCache();
73 SetAdj(TOP_OOM_ADJ);
74 }
75
ErrnoToMsg(const int & error)76 std::string DumpUtils::ErrnoToMsg(const int &error)
77 {
78 const int bufSize = 128;
79 char buf[bufSize] = {0};
80 strerror_r(error, buf, bufSize);
81 return buf;
82 }
83
FdToRead(const std::string & file)84 int DumpUtils::FdToRead(const std::string &file)
85 {
86 char path[PATH_MAX] = {0};
87 if (realpath(file.c_str(), path) == nullptr) {
88 DUMPER_HILOGD(MODULE_COMMON, "realpath, no such file. path=[%{public}s], file=[%{public}s]",
89 path, file.c_str());
90 return -1;
91 }
92
93 if (file != std::string(path)) {
94 DUMPER_HILOGI(MODULE_COMMON, "fail to check consistency. path=[%{public}s], file=[%{public}s]",
95 path, file.c_str());
96 }
97
98 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC | O_NONBLOCK));
99 if (fd == -1) {
100 DUMPER_HILOGD(MODULE_COMMON, "open [%{public}s] %{public}s", path, ErrnoToMsg(errno).c_str());
101 }
102 return fd;
103 }
104
FdToWrite(const std::string & file)105 int DumpUtils::FdToWrite(const std::string &file)
106 {
107 std::string split = "/";
108 auto pos = file.find_last_of(split);
109 if (pos == std::string::npos) {
110 DUMPER_HILOGD(MODULE_COMMON, "file path:[%{public}s] error", file.c_str());
111 return -1;
112 }
113 std::string tempPath = file.substr(0, pos + 1);
114 std::string name = file.substr(pos + 1);
115
116 char path[PATH_MAX] = {0};
117 if (realpath(tempPath.c_str(), path) != nullptr) {
118 std::string fileName = path + split + name;
119 int fd = TEMP_FAILURE_RETRY(open(fileName.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
120 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
121 if (fd == -1) {
122 DUMPER_HILOGD(MODULE_COMMON, "open [%{public}s] %{public}s",
123 fileName.c_str(), ErrnoToMsg(errno).c_str());
124 }
125 return fd;
126 }
127 DUMPER_HILOGD(MODULE_COMMON, "realpath, no such file. path=[%{public}s], tempPath=[%{public}s]",
128 path, tempPath.c_str());
129 return -1;
130 }
131
FileWriteable(const std::string & file)132 bool DumpUtils::FileWriteable(const std::string &file)
133 {
134 int fd = FdToWrite(file);
135 if (fd >= 0) {
136 close(fd);
137 return true;
138 }
139 return false;
140 }
141
CheckProcessAlive(uint32_t pid)142 bool DumpUtils::CheckProcessAlive(uint32_t pid)
143 {
144 char path[PATH_MAX] = {0};
145 char pathPid[PATH_MAX] = {0};
146 int ret = sprintf_s(pathPid, PATH_MAX, "/proc/%u", pid);
147 if (ret < 0) {
148 return false;
149 }
150 if (realpath(pathPid, path) != nullptr) { // path exist
151 if (access(path, F_OK) == 0) { // can be read
152 return true;
153 }
154 }
155 return false;
156 }
157
RemoveDuplicateString(std::vector<std::string> & strList)158 void DumpUtils::RemoveDuplicateString(std::vector<std::string> &strList)
159 {
160 std::vector<std::string> tmpVtr;
161 std::set<std::string> tmpSet;
162 for (auto &it : strList) {
163 auto ret = tmpSet.insert(it);
164 if (ret.second) {
165 tmpVtr.push_back(it);
166 }
167 }
168 strList = tmpVtr;
169 }
170
StrToId(const std::string & name)171 int DumpUtils::StrToId(const std::string &name)
172 {
173 int id = 0;
174 auto iter = std::find_if(saNameMap_.begin(), saNameMap_.end(), [&](const std::pair<int, std::string> &item) {
175 return name.compare(item.second) == 0;
176 });
177 if (iter == saNameMap_.end()) {
178 if (!StrToInt(name, id)) { // Decimal string
179 return 0; // invalid ability ID
180 }
181 } else {
182 id = iter->first;
183 }
184 return id;
185 }
186
ConvertSaIdToSaName(const std::string & saIdStr)187 std::string DumpUtils::ConvertSaIdToSaName(const std::string &saIdStr)
188 {
189 int saId = StrToId(saIdStr);
190 auto iter = saNameMap_.find(saId);
191 if (iter == saNameMap_.end()) {
192 return saIdStr;
193 }
194 return iter->second;
195 }
196
DirectoryExists(const std::string & path)197 bool DumpUtils::DirectoryExists(const std::string &path)
198 {
199 struct stat fileInfo;
200 if (stat(path.c_str(), &fileInfo) == 0) {
201 return S_ISDIR(fileInfo.st_mode);
202 }
203 return false;
204 }
205
PathIsValid(const std::string & path)206 bool DumpUtils::PathIsValid(const std::string &path)
207 {
208 return access(path.c_str(), F_OK) == 0;
209 }
210
CopyFile(const std::string & src,const std::string & des)211 bool DumpUtils::CopyFile(const std::string &src, const std::string &des)
212 {
213 std::ifstream fin(src);
214 std::ofstream fout(des);
215 if ((!fin.is_open()) || (!fout.is_open())) {
216 return false;
217 }
218 fout << fin.rdbuf();
219 if (fout.fail()) {
220 fout.clear();
221 }
222 fout.flush();
223 return true;
224 }
225 } // namespace HiviewDFX
226 } // namespace OHOS
227