1020a203aSopenharmony_ci/*
2020a203aSopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4020a203aSopenharmony_ci * you may not use this file except in compliance with the License.
5020a203aSopenharmony_ci * You may obtain a copy of the License at
6020a203aSopenharmony_ci *
7020a203aSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8020a203aSopenharmony_ci *
9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12020a203aSopenharmony_ci * See the License for the specific language governing permissions and
13020a203aSopenharmony_ci * limitations under the License.
14020a203aSopenharmony_ci */
15020a203aSopenharmony_ci#include "faultlog_manager.h"
16020a203aSopenharmony_ci
17020a203aSopenharmony_ci#include <cstdint>
18020a203aSopenharmony_ci#include <memory>
19020a203aSopenharmony_ci#include <mutex>
20020a203aSopenharmony_ci#include <string>
21020a203aSopenharmony_ci#include <vector>
22020a203aSopenharmony_ci
23020a203aSopenharmony_ci#include <fcntl.h>
24020a203aSopenharmony_ci#include <sys/stat.h>
25020a203aSopenharmony_ci#include <sys/types.h>
26020a203aSopenharmony_ci#include <unistd.h>
27020a203aSopenharmony_ci
28020a203aSopenharmony_ci#include "defines.h"
29020a203aSopenharmony_ci#include "file_util.h"
30020a203aSopenharmony_ci#include "log_store_ex.h"
31020a203aSopenharmony_ci#include "hiview_logger.h"
32020a203aSopenharmony_ci#include "time_util.h"
33020a203aSopenharmony_ci
34020a203aSopenharmony_ci#include "faultlog_database.h"
35020a203aSopenharmony_ci#include "faultlog_formatter.h"
36020a203aSopenharmony_ci#include "faultlog_info.h"
37020a203aSopenharmony_ci#include "faultlog_util.h"
38020a203aSopenharmony_ci
39020a203aSopenharmony_cinamespace OHOS {
40020a203aSopenharmony_cinamespace HiviewDFX {
41020a203aSopenharmony_cinamespace {
42020a203aSopenharmony_ciconstexpr char DEFAULT_FAULTLOG_FOLDER[] = "/data/log/faultlog/faultlogger/";
43020a203aSopenharmony_ciconstexpr int32_t MAX_FAULT_LOG_PER_HAP = 10;
44020a203aSopenharmony_ci}
45020a203aSopenharmony_ci
46020a203aSopenharmony_ciDEFINE_LOG_LABEL(0xD002D11, "FaultLogManager");
47020a203aSopenharmony_ciLogStoreEx::LogFileFilter CreateLogFileFilter(time_t time, int32_t id, int32_t faultLogType, const std::string& module)
48020a203aSopenharmony_ci{
49020a203aSopenharmony_ci    LogStoreEx::LogFileFilter filter = [time, id, faultLogType, module](const LogFile &file) {
50020a203aSopenharmony_ci        FaultLogInfo info = ExtractInfoFromFileName(file.name_);
51020a203aSopenharmony_ci        if (info.time <= time) {
52020a203aSopenharmony_ci            return false;
53020a203aSopenharmony_ci        }
54020a203aSopenharmony_ci
55020a203aSopenharmony_ci        if ((id != -1) && (info.id != id)) {
56020a203aSopenharmony_ci            return false;
57020a203aSopenharmony_ci        }
58020a203aSopenharmony_ci
59020a203aSopenharmony_ci        if ((faultLogType != 0) && (info.faultLogType != faultLogType)) {
60020a203aSopenharmony_ci            return false;
61020a203aSopenharmony_ci        }
62020a203aSopenharmony_ci
63020a203aSopenharmony_ci        if ((!module.empty()) && (info.module != module)) {
64020a203aSopenharmony_ci            return false;
65020a203aSopenharmony_ci        }
66020a203aSopenharmony_ci        return true;
67020a203aSopenharmony_ci    };
68020a203aSopenharmony_ci    return filter;
69020a203aSopenharmony_ci}
70020a203aSopenharmony_ci
71020a203aSopenharmony_ciFaultLogManager::~FaultLogManager()
72020a203aSopenharmony_ci{
73020a203aSopenharmony_ci    if (faultLogDb_ != nullptr) {
74020a203aSopenharmony_ci        delete faultLogDb_;
75020a203aSopenharmony_ci        faultLogDb_ = nullptr;
76020a203aSopenharmony_ci    }
77020a203aSopenharmony_ci}
78020a203aSopenharmony_ci
79020a203aSopenharmony_ciint32_t FaultLogManager::CreateTempFaultLogFile(time_t time, int32_t id, int32_t faultType,
80020a203aSopenharmony_ci    const std::string &module) const
81020a203aSopenharmony_ci{
82020a203aSopenharmony_ci    FaultLogInfo info;
83020a203aSopenharmony_ci    info.time = time;
84020a203aSopenharmony_ci    info.id = id;
85020a203aSopenharmony_ci    info.faultLogType = faultType;
86020a203aSopenharmony_ci    info.module = module;
87020a203aSopenharmony_ci    auto fileName = GetFaultLogName(info);
88020a203aSopenharmony_ci    return store_->CreateLogFile(fileName);
89020a203aSopenharmony_ci}
90020a203aSopenharmony_ci
91020a203aSopenharmony_civoid FaultLogManager::Init()
92020a203aSopenharmony_ci{
93020a203aSopenharmony_ci    store_ = std::make_unique<LogStoreEx>(DEFAULT_FAULTLOG_FOLDER, true);
94020a203aSopenharmony_ci    LogStoreEx::LogFileComparator comparator = [](const LogFile &lhs, const LogFile &rhs) {
95020a203aSopenharmony_ci        FaultLogInfo lhsInfo = ExtractInfoFromFileName(lhs.name_);
96020a203aSopenharmony_ci        FaultLogInfo rhsInfo = ExtractInfoFromFileName(rhs.name_);
97020a203aSopenharmony_ci        return lhsInfo.time > rhsInfo.time;
98020a203aSopenharmony_ci    };
99020a203aSopenharmony_ci    store_->SetLogFileComparator(comparator);
100020a203aSopenharmony_ci    store_->Init();
101020a203aSopenharmony_ci    faultLogDb_ = new FaultLogDatabase(looper_);
102020a203aSopenharmony_ci}
103020a203aSopenharmony_ci
104020a203aSopenharmony_cistd::string FaultLogManager::SaveFaultLogToFile(FaultLogInfo &info) const
105020a203aSopenharmony_ci{
106020a203aSopenharmony_ci    auto fileName = GetFaultLogName(info);
107020a203aSopenharmony_ci    std::string filePath = std::string(DEFAULT_FAULTLOG_FOLDER) + fileName;
108020a203aSopenharmony_ci    if (FileUtil::FileExists(filePath)) {
109020a203aSopenharmony_ci        HIVIEW_LOGI("logfile %{public}s already exist.", filePath.c_str());
110020a203aSopenharmony_ci        return "";
111020a203aSopenharmony_ci    }
112020a203aSopenharmony_ci    auto fd = store_->CreateLogFile(fileName);
113020a203aSopenharmony_ci    if (fd < 0) {
114020a203aSopenharmony_ci        return "";
115020a203aSopenharmony_ci    }
116020a203aSopenharmony_ci
117020a203aSopenharmony_ci    FaultLogger::WriteDfxLogToFile(fd);
118020a203aSopenharmony_ci    FaultLogger::WriteFaultLogToFile(fd, info.faultLogType, info.sectionMap);
119020a203aSopenharmony_ci    FaultLogger::WriteLogToFile(fd, info.logPath);
120020a203aSopenharmony_ci    if (info.sectionMap.count("HILOG") == 1) {
121020a203aSopenharmony_ci        FileUtil::SaveStringToFd(fd, "\nHiLog:\n");
122020a203aSopenharmony_ci        FileUtil::SaveStringToFd(fd, info.sectionMap["HILOG"]);
123020a203aSopenharmony_ci    }
124020a203aSopenharmony_ci    FaultLogger::LimitCppCrashLog(fd, info.faultLogType);
125020a203aSopenharmony_ci    close(fd);
126020a203aSopenharmony_ci
127020a203aSopenharmony_ci    std::string logFile = info.logPath;
128020a203aSopenharmony_ci    if (logFile != "" && FileUtil::FileExists(logFile)) {
129020a203aSopenharmony_ci        if (!FileUtil::RemoveFile(logFile)) {
130020a203aSopenharmony_ci            HIVIEW_LOGW("remove logFile %{public}s failed.", logFile.c_str());
131020a203aSopenharmony_ci        } else {
132020a203aSopenharmony_ci            HIVIEW_LOGI("remove logFile %{public}s.", logFile.c_str());
133020a203aSopenharmony_ci        }
134020a203aSopenharmony_ci    }
135020a203aSopenharmony_ci    store_->ClearSameLogFilesIfNeeded(CreateLogFileFilter(0, info.id, info.faultLogType, info.module),
136020a203aSopenharmony_ci        MAX_FAULT_LOG_PER_HAP);
137020a203aSopenharmony_ci    info.logPath = std::string(DEFAULT_FAULTLOG_FOLDER) + fileName;
138020a203aSopenharmony_ci    HIVIEW_LOGI("create log %{public}s", fileName.c_str());
139020a203aSopenharmony_ci    return fileName;
140020a203aSopenharmony_ci}
141020a203aSopenharmony_ci
142020a203aSopenharmony_cistd::list<FaultLogInfo> FaultLogManager::GetFaultInfoList(const std::string& module,
143020a203aSopenharmony_ci    int32_t id, int32_t faultType, int32_t maxNum) const
144020a203aSopenharmony_ci{
145020a203aSopenharmony_ci    std::list<FaultLogInfo> ret;
146020a203aSopenharmony_ci    if (faultLogDb_ != nullptr) {
147020a203aSopenharmony_ci        ret = faultLogDb_->GetFaultInfoList(module, id, faultType, maxNum);
148020a203aSopenharmony_ci        HIVIEW_LOGI("Find %{public}zu fault records for uid:%{public}d type:%{public}d",
149020a203aSopenharmony_ci            ret.size(), id, faultType);
150020a203aSopenharmony_ci    }
151020a203aSopenharmony_ci    return ret;
152020a203aSopenharmony_ci}
153020a203aSopenharmony_ci
154020a203aSopenharmony_civoid FaultLogManager::SaveFaultInfoToRawDb(FaultLogInfo& info) const
155020a203aSopenharmony_ci{
156020a203aSopenharmony_ci    if (faultLogDb_ != nullptr) {
157020a203aSopenharmony_ci        faultLogDb_->SaveFaultLogInfo(info);
158020a203aSopenharmony_ci    }
159020a203aSopenharmony_ci}
160020a203aSopenharmony_ci
161020a203aSopenharmony_civoid FaultLogManager::ReduceLogFileListSize(std::list<std::string> &infoVec, int32_t maxNum) const
162020a203aSopenharmony_ci{
163020a203aSopenharmony_ci    if ((maxNum < 0) || (infoVec.size() <= static_cast<uint32_t>(maxNum))) {
164020a203aSopenharmony_ci        return;
165020a203aSopenharmony_ci    }
166020a203aSopenharmony_ci
167020a203aSopenharmony_ci    auto begin = infoVec.begin();
168020a203aSopenharmony_ci    std::advance(begin, maxNum);
169020a203aSopenharmony_ci    infoVec.erase(begin, infoVec.end());
170020a203aSopenharmony_ci}
171020a203aSopenharmony_ci
172020a203aSopenharmony_cistd::list<std::string> FaultLogManager::GetFaultLogFileList(const std::string &module, time_t time, int32_t id,
173020a203aSopenharmony_ci                                                            int32_t faultType, int32_t maxNum) const
174020a203aSopenharmony_ci{
175020a203aSopenharmony_ci    LogStoreEx::LogFileFilter filter = CreateLogFileFilter(time, id, faultType, module);
176020a203aSopenharmony_ci    auto vec = store_->GetLogFiles(filter);
177020a203aSopenharmony_ci    std::list<std::string> ret;
178020a203aSopenharmony_ci    std::transform(vec.begin(), vec.end(), std::back_inserter(ret), [](const LogFile &file) { return file.path_; });
179020a203aSopenharmony_ci    ReduceLogFileListSize(ret, maxNum);
180020a203aSopenharmony_ci    return ret;
181020a203aSopenharmony_ci}
182020a203aSopenharmony_ci
183020a203aSopenharmony_cibool FaultLogManager::GetFaultLogContent(const std::string &name, std::string &content) const
184020a203aSopenharmony_ci{
185020a203aSopenharmony_ci    auto path = std::string(DEFAULT_FAULTLOG_FOLDER) + name;
186020a203aSopenharmony_ci    return FileUtil::LoadStringFromFile(path, content);
187020a203aSopenharmony_ci}
188020a203aSopenharmony_ci
189020a203aSopenharmony_cibool FaultLogManager::IsProcessedFault(int32_t pid, int32_t uid, int32_t faultType)
190020a203aSopenharmony_ci{
191020a203aSopenharmony_ci    if (faultLogDb_ == nullptr) {
192020a203aSopenharmony_ci        return false;
193020a203aSopenharmony_ci    }
194020a203aSopenharmony_ci
195020a203aSopenharmony_ci    return faultLogDb_->IsFaultExist(pid, uid, faultType);
196020a203aSopenharmony_ci}
197020a203aSopenharmony_ci} // namespace HiviewDFX
198020a203aSopenharmony_ci} // namespace OHOS
199