• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "audit.h"
16 
17 #include <cstdint>
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 
21 #include "file_util.h"
22 #include "time_util.h"
23 
24 namespace OHOS {
25 namespace HiviewDFX {
26 namespace {
27 static const char AUDIT_LOG_PATH[] = "/data/log/faultlog/hiview_audit.log.0";
28 static const char AUDIT_LOG_PATH_BAK[] = "/data/log/faultlog/hiview_audit.log.1";
29 }
30 
~Audit()31 Audit::~Audit()
32 {
33     enabled_ = false;
34 }
35 
WriteAuditEvent(StatsEvent eventType,uint64_t eventId,const std::string & digest)36 bool Audit::WriteAuditEvent(StatsEvent eventType, uint64_t eventId, const std::string& digest)
37 {
38     static auto& instance = Audit::GetInstance();
39     if (!instance.IsEnabled()) {
40         return false;
41     }
42 
43     if (digest.empty() || (digest.length() >= MAX_AUDIT_LOG_SIZE)) {
44         return false;
45     }
46 
47     std::string out;
48     out.append(std::to_string(TimeUtil::GenerateTimestamp()));
49     out.push_back(DOMAIN_DELIMITER);
50     out.append(std::to_string(eventId));
51     out.push_back(DOMAIN_DELIMITER);
52     out.append(std::to_string(eventType));
53     out.push_back(DOMAIN_DELIMITER);
54     out.append(digest);
55     out.append("\n");
56     instance.WriteEvent(out);
57     return true;
58 }
59 
GetAuditLog(bool loadFromFile,std::list<std::string> & ret)60 bool Audit::GetAuditLog(bool loadFromFile, std::list<std::string>& ret)
61 {
62     static auto& instance = Audit::GetInstance();
63     if (!instance.IsEnabled()) {
64         return false;
65     }
66 
67     instance.GetAuditLogInner(loadFromFile, ret);
68     return true;
69 }
70 
IsEnabled()71 bool Audit::IsEnabled()
72 {
73     static auto& instance = Audit::GetInstance();
74     return instance.enabled_;
75 }
76 
GetAuditLogInner(bool loadFromFile,std::list<std::string> & ret)77 void Audit::GetAuditLogInner(bool loadFromFile, std::list<std::string>& ret)
78 {
79     if (!loadFromFile) {
80         return;
81     }
82 
83     std::lock_guard<std::mutex> lock(mutex_);
84     std::string activeFile = GetLogFilePath(true);
85     ReadLogFromFile(activeFile, ret);
86     std::string inactiveFile = GetLogFilePath(false);
87     ReadLogFromFile(inactiveFile, ret);
88 }
89 
90 // call once in platform initialization
Init(bool isBeta)91 void Audit::Init(bool isBeta)
92 {
93     if (init_) {
94         return;
95     }
96 
97     std::call_once(initFlag_, [&]() { enabled_ = isBeta; });
98     std::lock_guard<std::mutex> lock(mutex_);
99     useBak_ = IsBackupFileActive();
100     std::string path = useBak_ ? AUDIT_LOG_PATH_BAK : AUDIT_LOG_PATH;
101     writeFd_ = UniqueFd(FileUtil::Open(path, O_CREAT | O_APPEND | O_RDWR,
102                         S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH));
103     if (writeFd_.Get() < 0) {
104         enabled_ = false;
105     }
106     writeLogCount_ = 0;
107     init_ = true;
108 }
109 
Clear()110 void Audit::Clear()
111 {
112     std::lock_guard<std::mutex> lock(mutex_);
113     std::fstream logFile(AUDIT_LOG_PATH, std::ios::out);
114     std::fstream bakLogFile(AUDIT_LOG_PATH_BAK, std::ios::out);
115 }
116 
WriteEvent(const std::string & content)117 void Audit::WriteEvent(const std::string& content)
118 {
119     std::lock_guard<std::mutex> lock(mutex_);
120     SaveToFileLocked(content);
121 }
122 
IsActiveLogFileSizeReachTheashold()123 bool Audit::IsActiveLogFileSizeReachTheashold()
124 {
125     writeLogCount_ = 0;
126     const auto& path = GetLogFilePath(true);
127     struct stat sb;
128     if (stat(path.c_str(), &sb) == -1) {
129         return false;
130     }
131 
132     return sb.st_size >= MAX_DISK_LOG_SIZE;
133 }
134 
IsBackupFileActive()135 bool Audit::IsBackupFileActive()
136 {
137     struct stat originLogFileStat;
138     if (stat(AUDIT_LOG_PATH, &originLogFileStat) == -1) {
139         return false;
140     }
141 
142     struct stat bakLogFileStat;
143     if (stat(AUDIT_LOG_PATH_BAK, &bakLogFileStat) == -1) {
144         return false;
145     }
146 
147     if (originLogFileStat.st_size == 0) {
148         return false;
149     }
150 
151     return bakLogFileStat.st_mtime >= originLogFileStat.st_mtime;
152 }
153 
SaveToFileLocked(const std::string & content)154 void Audit::SaveToFileLocked(const std::string& content)
155 {
156     if ((writeLogCount_ > MAX_MEMORY_LOG_COUNT) && IsActiveLogFileSizeReachTheashold()) {
157         SwitchActiveFile();
158     }
159 
160     int fd = writeFd_.Get();
161     if (fd > 0 && content.length() < MAX_AUDIT_LOG_SIZE) {
162         // no need to check the result.
163         write(fd, content.c_str(), content.length());
164     }
165     writeLogCount_ = writeLogCount_ + 1;
166 }
167 
ReadLogFromFile(const std::string & path,std::list<std::string> & ret)168 bool Audit::ReadLogFromFile(const std::string& path, std::list<std::string>& ret)
169 {
170     std::list<std::string> fileLog;
171     std::ifstream logFile(path);
172     std::string line;
173     if (logFile.good()) {
174         while (getline(logFile, line)) {
175             fileLog.push_back(line);
176         }
177     } else {
178         logFile.close();
179         return false;
180     }
181     logFile.close();
182     ret.insert(ret.begin(), fileLog.begin(), fileLog.end());
183     return true;
184 }
185 
GetLogFilePath(bool active)186 const std::string Audit::GetLogFilePath(bool active)
187 {
188     if ((useBak_ && active) || (!useBak_ && !active)) {
189         return AUDIT_LOG_PATH_BAK;
190     }
191     return AUDIT_LOG_PATH;
192 }
193 
SwitchActiveFile()194 void Audit::SwitchActiveFile()
195 {
196     useBak_ = !useBak_;
197     const auto& path = GetLogFilePath(true);
198     writeFd_ = UniqueFd(FileUtil::Open(path, O_CREAT | O_TRUNC | O_RDWR,
199         S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH));
200 }
201 } // namespace HiviewDFX
202 } // namespace OHOS
203