1 /*
2 * Copyright (c) 2021-2023 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 "faultlog_manager.h"
16
17 #include <cstdint>
18 #include <memory>
19 #include <mutex>
20 #include <string>
21 #include <vector>
22
23 #include <fcntl.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27
28 #include "constants.h"
29 #include "defines.h"
30 #include "file_util.h"
31 #include "log_store_ex.h"
32 #include "hiview_logger.h"
33 #include "time_util.h"
34
35 #include "faultlog_database.h"
36 #include "faultlog_formatter.h"
37 #include "faultlog_info.h"
38 #include "faultlog_util.h"
39
40 namespace OHOS {
41 namespace HiviewDFX {
42 using namespace FaultLogger;
43 DEFINE_LOG_LABEL(0xD002D11, "FaultLogManager");
CreateLogFileFilter(time_t time,int32_t id,int32_t faultLogType,const std::string & module)44 LogStoreEx::LogFileFilter CreateLogFileFilter(time_t time, int32_t id, int32_t faultLogType, const std::string& module)
45 {
46 LogStoreEx::LogFileFilter filter = [time, id, faultLogType, module](const LogFile &file) {
47 FaultLogInfo info = ExtractInfoFromFileName(file.name_);
48 if (info.time <= time) {
49 return false;
50 }
51
52 if ((id != -1) && (info.id != id)) {
53 return false;
54 }
55
56 if ((faultLogType != 0) && (info.faultLogType != faultLogType)) {
57 return false;
58 }
59
60 if ((!module.empty()) && (info.module != module)) {
61 return false;
62 }
63 return true;
64 };
65 return filter;
66 }
67
~FaultLogManager()68 FaultLogManager::~FaultLogManager()
69 {
70 if (faultLogDb_ != nullptr) {
71 delete faultLogDb_;
72 faultLogDb_ = nullptr;
73 }
74 }
75
CreateTempFaultLogFile(time_t time,int32_t id,int32_t faultType,const std::string & module) const76 int32_t FaultLogManager::CreateTempFaultLogFile(time_t time, int32_t id, int32_t faultType,
77 const std::string &module) const
78 {
79 FaultLogInfo info;
80 info.time = time;
81 info.id = id;
82 info.faultLogType = faultType;
83 info.module = module;
84 auto fileName = GetFaultLogName(info);
85 return store_->CreateLogFile(fileName);
86 }
87
Init()88 void FaultLogManager::Init()
89 {
90 store_ = std::make_unique<LogStoreEx>(FaultLogger::DEFAULT_FAULTLOG_FOLDER, true);
91 LogStoreEx::LogFileComparator comparator = [](const LogFile &lhs, const LogFile &rhs) {
92 FaultLogInfo lhsInfo = ExtractInfoFromFileName(lhs.name_);
93 FaultLogInfo rhsInfo = ExtractInfoFromFileName(rhs.name_);
94 return lhsInfo.time > rhsInfo.time;
95 };
96 store_->SetLogFileComparator(comparator);
97 store_->Init();
98 faultLogDb_ = new FaultLogDatabase(looper_);
99 }
100
SaveFaultLogToFile(FaultLogInfo & info) const101 std::string FaultLogManager::SaveFaultLogToFile(FaultLogInfo &info) const
102 {
103 auto fileName = GetFaultLogName(info);
104 std::string filePath = std::string(FaultLogger::DEFAULT_FAULTLOG_FOLDER) + fileName;
105 if (FileUtil::FileExists(filePath)) {
106 HIVIEW_LOGI("logfile %{public}s already exist.", filePath.c_str());
107 return "";
108 }
109 auto fd = store_->CreateLogFile(fileName);
110 if (fd < 0) {
111 return "";
112 }
113
114 FaultLogger::WriteDfxLogToFile(fd);
115 FaultLogger::WriteFaultLogToFile(fd, info.faultLogType, info.sectionMap);
116 FaultLogger::WriteLogToFile(fd, info.logPath);
117 if (info.sectionMap.count("HILOG") == 1) {
118 FileUtil::SaveStringToFd(fd, "\nHiLog:\n");
119 FileUtil::SaveStringToFd(fd, info.sectionMap["HILOG"]);
120 }
121 FaultLogger::LimitCppCrashLog(fd, info.faultLogType);
122 close(fd);
123
124 std::string logFile = info.logPath;
125 if (logFile != "" && FileUtil::FileExists(logFile)) {
126 if (!FileUtil::RemoveFile(logFile)) {
127 HIVIEW_LOGW("remove logFile %{public}s failed.", logFile.c_str());
128 } else {
129 HIVIEW_LOGI("remove logFile %{public}s.", logFile.c_str());
130 }
131 }
132 store_->ClearSameLogFilesIfNeeded(CreateLogFileFilter(0, info.id, info.faultLogType, info.module),
133 MAX_FAULT_LOG_PER_HAP);
134 info.logPath = std::string(FaultLogger::DEFAULT_FAULTLOG_FOLDER) + fileName;
135 HIVIEW_LOGI("create log %{public}s", fileName.c_str());
136 return fileName;
137 }
138
GetFaultInfoList(const std::string & module,int32_t id,int32_t faultType,int32_t maxNum) const139 std::list<FaultLogInfo> FaultLogManager::GetFaultInfoList(const std::string& module,
140 int32_t id, int32_t faultType, int32_t maxNum) const
141 {
142 std::list<FaultLogInfo> ret;
143 if (faultLogDb_ != nullptr) {
144 ret = faultLogDb_->GetFaultInfoList(module, id, faultType, maxNum);
145 HIVIEW_LOGI("Find %{public}zu fault records for uid:%{public}d type:%{public}d",
146 ret.size(), id, faultType);
147 }
148 return ret;
149 }
150
SaveFaultInfoToRawDb(FaultLogInfo & info) const151 void FaultLogManager::SaveFaultInfoToRawDb(FaultLogInfo& info) const
152 {
153 if (faultLogDb_ != nullptr) {
154 faultLogDb_->SaveFaultLogInfo(info);
155 }
156 }
157
ReduceLogFileListSize(std::list<std::string> & infoVec,int32_t maxNum) const158 void FaultLogManager::ReduceLogFileListSize(std::list<std::string> &infoVec, int32_t maxNum) const
159 {
160 if ((maxNum < 0) || (infoVec.size() <= static_cast<uint32_t>(maxNum))) {
161 return;
162 }
163
164 auto begin = infoVec.begin();
165 std::advance(begin, maxNum);
166 infoVec.erase(begin, infoVec.end());
167 }
168
GetFaultLogFileList(const std::string & module,time_t time,int32_t id,int32_t faultType,int32_t maxNum) const169 std::list<std::string> FaultLogManager::GetFaultLogFileList(const std::string &module, time_t time, int32_t id,
170 int32_t faultType, int32_t maxNum) const
171 {
172 LogStoreEx::LogFileFilter filter = CreateLogFileFilter(time, id, faultType, module);
173 auto vec = store_->GetLogFiles(filter);
174 std::list<std::string> ret;
175 std::transform(vec.begin(), vec.end(), std::back_inserter(ret), [](const LogFile &file) { return file.path_; });
176 ReduceLogFileListSize(ret, maxNum);
177 return ret;
178 }
179
GetFaultLogContent(const std::string & name,std::string & content) const180 bool FaultLogManager::GetFaultLogContent(const std::string &name, std::string &content) const
181 {
182 auto path = std::string(FaultLogger::DEFAULT_FAULTLOG_FOLDER) + name;
183 return FileUtil::LoadStringFromFile(path, content);
184 }
185
IsProcessedFault(int32_t pid,int32_t uid,int32_t faultType)186 bool FaultLogManager::IsProcessedFault(int32_t pid, int32_t uid, int32_t faultType)
187 {
188 if (faultLogDb_ == nullptr) {
189 return false;
190 }
191
192 return faultLogDb_->IsFaultExist(pid, uid, faultType);
193 }
194 } // namespace HiviewDFX
195 } // namespace OHOS
196