• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 <filesystem>
18 
19 #include "constants.h"
20 #include "defines.h"
21 #include "file_util.h"
22 #include "log_store_ex.h"
23 #include "hiview_logger.h"
24 
25 #include "faultlog_database.h"
26 #include "faultlog_formatter.h"
27 #include "faultlog_util.h"
28 
29 // define Fdsan Domain
30 #ifndef FDSAN_DOMAIN
31 #undef FDSAN_DOMAIN
32 #endif
33 #define FDSAN_DOMAIN 0xD002D11
34 
35 namespace OHOS {
36 namespace HiviewDFX {
37 using namespace FaultLogger;
38 namespace {
39 constexpr int32_t MAX_FAULT_LOG_PER_HAP = 10;
40 constexpr uint32_t WARNING_LOG_MAX_SIZE = 3 * 1024 * 1024;
41 constexpr uint32_t WARNING_LOG_MIN_KEEP_NUM = 15;
42 }
43 
44 DEFINE_LOG_LABEL(0xD002D11, "FaultLogManager");
CreateLogFileFilter(time_t time,int32_t id,int32_t faultLogType,const std::string & module)45 LogStoreEx::LogFileFilter CreateLogFileFilter(time_t time, int32_t id, int32_t faultLogType, const std::string& module)
46 {
47     LogStoreEx::LogFileFilter filter = [time, id, faultLogType, module](const LogFile &file) {
48         FaultLogInfo info = ExtractInfoFromFileName(file.name_);
49         if (info.time <= time) {
50             return false;
51         }
52 
53         if ((id != -1) && (info.id != id)) {
54             return false;
55         }
56 
57         if ((faultLogType != 0) && (info.faultLogType != faultLogType)) {
58             return false;
59         }
60 
61         if ((!module.empty()) && (info.module != module)) {
62             return false;
63         }
64         return true;
65     };
66     return filter;
67 }
68 
CreateTempFaultLogFile(time_t time,int32_t id,int32_t faultType,const std::string & module) const69 int32_t FaultLogManager::CreateTempFaultLogFile(time_t time, int32_t id, int32_t faultType,
70     const std::string &module) const
71 {
72     FaultLogInfo info;
73     info.time = time;
74     info.id = id;
75     info.faultLogType = faultType;
76     info.module = module;
77     auto fileName = GetFaultLogName(info);
78     return store_->CreateLogFile(fileName);
79 }
80 
Init()81 void FaultLogManager::Init()
82 {
83     store_ = std::make_unique<LogStoreEx>(FAULTLOG_FAULT_LOGGER_FOLDER, true);
84     LogStoreEx::LogFileComparator comparator = [](const LogFile &lhs, const LogFile &rhs) {
85         FaultLogInfo lhsInfo = ExtractInfoFromFileName(lhs.name_);
86         FaultLogInfo rhsInfo = ExtractInfoFromFileName(rhs.name_);
87         return lhsInfo.time > rhsInfo.time;
88     };
89     store_->SetLogFileComparator(comparator);
90     store_->Init();
91     faultLogDb_ = std::make_unique<FaultLogDatabase>(looper_);
92     InitWarningLogStore();
93 }
94 
InitWarningLogStore()95 void FaultLogManager::InitWarningLogStore()
96 {
97     warningLogStore_ = std::make_unique<LogStoreEx>(FAULTLOG_WARNING_LOG_FOLDER, true);
98     warningLogStore_->SetMaxSize(WARNING_LOG_MAX_SIZE);
99     warningLogStore_->SetMinKeepingFileNumber(WARNING_LOG_MIN_KEEP_NUM);
100     LogStoreEx::LogFileComparator warningLogComparator = [](const LogFile &lhs, const LogFile &rhs) {
101         return (rhs < lhs);
102     };
103     warningLogStore_->SetLogFileComparator(warningLogComparator);
104     warningLogStore_->Init();
105 }
106 
SaveFaultLogToFile(FaultLogInfo & info) const107 std::string FaultLogManager::SaveFaultLogToFile(FaultLogInfo& info) const
108 {
109     std::string fileName = GetFaultLogName(info);
110     std::string filePath = GetFaultLogFilePath(info.faultLogType, fileName);
111     if (FileUtil::FileExists(filePath)) {
112         HIVIEW_LOGI("logfile %{public}s already exist.", filePath.c_str());
113         return "";
114     }
115     int fd = GetFaultLogFileFd(info.faultLogType, fileName);
116     if (fd < 0) {
117         if (info.faultLogType == FaultLogType::SYS_WARNING) {
118             if (access(FAULTLOG_WARNING_LOG_FOLDER, F_OK) != 0) {
119                 HIVIEW_LOGE("%{public}s does not exist!!!", FAULTLOG_WARNING_LOG_FOLDER);
120             }
121         } else if (access(FAULTLOG_FAULT_LOGGER_FOLDER, F_OK) != 0) {
122             HIVIEW_LOGE("%{public}s does not exist!!!", FAULTLOG_FAULT_LOGGER_FOLDER);
123         }
124         return "";
125     }
126     uint64_t ownerTag = fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, FDSAN_DOMAIN);
127     fdsan_exchange_owner_tag(fd, 0, ownerTag);
128 
129     FaultLogger::WriteDfxLogToFile(fd);
130     FaultLogger::WriteFaultLogToFile(fd, info.faultLogType, info.sectionMap);
131     FaultLogger::WriteLogToFile(fd, info.logPath, info.sectionMap);
132     if (info.sectionMap.count(FaultKey::HILOG) == 1) {
133         FileUtil::SaveStringToFd(fd, "\nHiLog:\n");
134         FileUtil::SaveStringToFd(fd, info.sectionMap[FaultKey::HILOG]);
135     }
136     fdsan_close_with_tag(fd, ownerTag);
137 
138     RemoveOldFile(info);
139     info.logPath = filePath;
140     HIVIEW_LOGI("create log %{public}s", fileName.c_str());
141     return fileName;
142 }
143 
GetFaultLogFilePath(int32_t faultLogType,const std::string & fileName) const144 std::string FaultLogManager::GetFaultLogFilePath(int32_t faultLogType, const std::string& fileName) const
145 {
146     return (faultLogType == FaultLogType::SYS_WARNING) ?
147         std::string(FAULTLOG_WARNING_LOG_FOLDER) + fileName : std::string(FAULTLOG_FAULT_LOGGER_FOLDER) + fileName;
148 }
149 
GetFaultLogFileFd(int32_t faultLogType,const std::string & fileName) const150 int FaultLogManager::GetFaultLogFileFd(int32_t faultLogType, const std::string& fileName) const
151 {
152     return (faultLogType == FaultLogType::SYS_WARNING) ?
153         warningLogStore_->CreateLogFile(fileName): store_->CreateLogFile(fileName);
154 }
155 
RemoveOldFile(FaultLogInfo & info) const156 void FaultLogManager::RemoveOldFile(FaultLogInfo& info) const
157 {
158     std::string logFile = info.logPath;
159     if (logFile != "" && FileUtil::FileExists(logFile)) {
160         if (!FileUtil::RemoveFile(logFile)) {
161             HIVIEW_LOGW("remove logFile %{public}s failed.", logFile.c_str());
162         } else {
163             HIVIEW_LOGI("remove logFile %{public}s.", logFile.c_str());
164         }
165     }
166     store_->ClearSameLogFilesIfNeeded(CreateLogFileFilter(0, info.id, info.faultLogType, info.module),
167         MAX_FAULT_LOG_PER_HAP);
168 }
169 
GetFaultInfoList(const std::string & module,int32_t id,int32_t faultType,int32_t maxNum) const170 std::list<FaultLogInfo> FaultLogManager::GetFaultInfoList(const std::string& module,
171     int32_t id, int32_t faultType, int32_t maxNum) const
172 {
173     std::list<FaultLogInfo> ret;
174     if (faultLogDb_ != nullptr) {
175         ret = faultLogDb_->GetFaultInfoList(module, id, faultType, maxNum);
176         HIVIEW_LOGI("Find %{public}zu fault records for uid:%{public}d type:%{public}d",
177             ret.size(), id, faultType);
178     }
179     return ret;
180 }
181 
SaveFaultInfoToRawDb(FaultLogInfo & info) const182 void FaultLogManager::SaveFaultInfoToRawDb(FaultLogInfo& info) const
183 {
184     if (faultLogDb_ != nullptr) {
185         faultLogDb_->SaveFaultLogInfo(info);
186     }
187 }
188 
ReduceLogFileListSize(std::list<std::string> & infoVec,int32_t maxNum) const189 void FaultLogManager::ReduceLogFileListSize(std::list<std::string>& infoVec, int32_t maxNum) const
190 {
191     if ((maxNum < 0) || (infoVec.size() <= static_cast<uint32_t>(maxNum))) {
192         return;
193     }
194 
195     auto begin = infoVec.begin();
196     std::advance(begin, maxNum);
197     infoVec.erase(begin, infoVec.end());
198 }
199 
GetFaultLogFileList(const std::string & module,time_t time,int32_t id,int32_t faultType,int32_t maxNum) const200 std::list<std::string> FaultLogManager::GetFaultLogFileList(const std::string& module, time_t time, int32_t id,
201                                                             int32_t faultType, int32_t maxNum) const
202 {
203     LogStoreEx::LogFileFilter filter = CreateLogFileFilter(time, id, faultType, module);
204     auto vec = store_->GetLogFiles(filter);
205     std::list<std::string> ret;
206     std::transform(vec.begin(), vec.end(), std::back_inserter(ret), [](const LogFile &file) { return file.path_; });
207     ReduceLogFileListSize(ret, maxNum);
208     return ret;
209 }
210 
GetFaultLogContent(const std::string & name,std::string & content) const211 bool FaultLogManager::GetFaultLogContent(const std::string& name, std::string& content) const
212 {
213     auto path = std::string(FAULTLOG_FAULT_LOGGER_FOLDER);
214     std::string matchName;
215     for (const auto& entry : std::filesystem::directory_iterator(path)) {
216         std::filesystem::path filePath = entry.path();
217         std::string fileName = filePath.filename().string();
218         if (fileName.find(name) != std::string::npos && matchName.compare(fileName) < 0) {
219             matchName = fileName;
220             continue;
221         }
222     }
223     if (matchName.empty()) {
224         return false;
225     }
226     path = path + matchName;
227     return FileUtil::LoadStringFromFile(path, content);
228 }
229 
IsProcessedFault(int32_t pid,int32_t uid,int32_t faultType)230 bool FaultLogManager::IsProcessedFault(int32_t pid, int32_t uid, int32_t faultType)
231 {
232     if (faultLogDb_ == nullptr) {
233         return false;
234     }
235 
236     return faultLogDb_->IsFaultExist(pid, uid, faultType);
237 }
238 } // namespace HiviewDFX
239 } // namespace OHOS
240