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