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