1 /*
2 * Copyright (c) 2022-2024 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
16 #include "b_hiaudit/hi_audit.h"
17
18 #include <chrono>
19 #include <ctime>
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <iomanip>
23 #include <sstream>
24 #include <sys/time.h>
25 #include <unistd.h>
26
27 #include "filemgmt_libhilog.h"
28 #include "b_hiaudit/zip_util.h"
29 #include "b_hiaudit/hi_audit.h"
30
31 namespace OHOS::FileManagement::Backup {
32 namespace {
33 const HiAuditConfig HIAUDIT_CONFIG = { "/data/log/hiaudit/app_file_service/", "appfileservice",
34 2 * 1024, 3 * 1204 * 1024, 10 };
35 const HiAuditConfig HIAUDIT_CONFIG_EXT = { "/data/storage/el2/log/hiaudit/", "appfileservice",
36 2 * 1024, 3 * 1204 * 1024, 10 };
37 constexpr int8_t MILLISECONDS_LENGTH = 3;
38 constexpr int64_t SEC_TO_MILLISEC = 1000;
39 constexpr int MAX_TIME_BUFF = 64; // 64 : for example 2021-05-27-01-01-01
40 const std::string HIAUDIT_LOG_NAME = HIAUDIT_CONFIG.logPath + HIAUDIT_CONFIG.logName + "_audit.csv";
41 const std::string HIAUDIT_LOG_NAME_EXT = HIAUDIT_CONFIG_EXT.logPath + HIAUDIT_CONFIG_EXT.logName + "_audit.csv";
42 }
43
HiAudit(bool isSaJob)44 HiAudit::HiAudit(bool isSaJob)
45 {
46 isSaJob_ = isSaJob;
47 Init();
48 }
49
~HiAudit()50 HiAudit::~HiAudit()
51 {
52 if (writeFd_ >= 0) {
53 close(writeFd_);
54 }
55 }
56
GetInstance(bool isSaJob)57 HiAudit &HiAudit::GetInstance(bool isSaJob)
58 {
59 static HiAudit hiAudit(isSaJob);
60 return hiAudit;
61 }
62
Init()63 void HiAudit::Init()
64 {
65 std::lock_guard<std::mutex> lock(mutex_);
66 if (isSaJob_) {
67 hiAuditConfig_ = HIAUDIT_CONFIG;
68 } else {
69 hiAuditConfig_ = HIAUDIT_CONFIG_EXT;
70 }
71 if (!MkLogDirSuccess()) {
72 HILOGE("Init, Create log dir failed");
73 return;
74 }
75 std::string logFilePath = hiAuditConfig_.logPath + hiAuditConfig_.logName + "_audit.csv";
76 writeFd_ =
77 open(logFilePath.c_str(), O_CREAT | O_APPEND | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
78 if (writeFd_ < 0) {
79 HILOGE("Init, open error, logFilePath is:%{public}s, errno:%{public}d", logFilePath.c_str(), errno);
80 }
81 struct stat st;
82 writeLogSize_ = stat(HIAUDIT_LOG_NAME.c_str(), &st) ? 0 : static_cast<uint64_t>(st.st_size);
83 HILOGI("Init, writeLogSize: %{public}u", writeLogSize_.load());
84 }
85
GetMilliseconds()86 uint64_t HiAudit::GetMilliseconds()
87 {
88 auto now = std::chrono::system_clock::now();
89 auto millisecs = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
90 return millisecs.count();
91 }
92
GetFormattedTimestamp(time_t timeStamp, const std::string &format)93 std::string HiAudit::GetFormattedTimestamp(time_t timeStamp, const std::string &format)
94 {
95 auto seconds = timeStamp / SEC_TO_MILLISEC;
96 char date[MAX_TIME_BUFF] = {0};
97 struct tm result {};
98 if (localtime_r(&seconds, &result) != nullptr) {
99 strftime(date, MAX_TIME_BUFF, format.c_str(), &result);
100 }
101 return std::string(date);
102 }
103
GetFormattedTimestampEndWithMilli()104 std::string HiAudit::GetFormattedTimestampEndWithMilli()
105 {
106 uint64_t milliSeconds = GetMilliseconds();
107 std::string formattedTimeStamp = GetFormattedTimestamp(milliSeconds, "%Y%m%d%H%M%S");
108 std::stringstream ss;
109 ss << formattedTimeStamp;
110 milliSeconds = milliSeconds % SEC_TO_MILLISEC;
111 ss << std::setfill('0') << std::setw(MILLISECONDS_LENGTH) << milliSeconds;
112 return ss.str();
113 }
114
Write(const AuditLog &auditLog)115 void HiAudit::Write(const AuditLog &auditLog)
116 {
117 HILOGI("write");
118 std::lock_guard<std::mutex> lock(mutex_);
119 if (writeLogSize_ == 0) {
120 WriteToFile(auditLog.TitleString());
121 }
122 std::string writeLog =
123 GetFormattedTimestampEndWithMilli() + ", " + hiAuditConfig_.logName + ", NO, " + auditLog.ToString();
124 HILOGI("write %{public}s.", writeLog.c_str());
125 if (writeLog.length() > hiAuditConfig_.logSize) {
126 writeLog = writeLog.substr(0, hiAuditConfig_.logSize);
127 }
128 writeLog = writeLog + "\n";
129 WriteToFile(writeLog);
130 }
131
GetWriteFilePath()132 void HiAudit::GetWriteFilePath()
133 {
134 if (writeLogSize_ < hiAuditConfig_.fileSize) {
135 return;
136 }
137 close(writeFd_);
138 ZipAuditLog();
139 CleanOldAuditFile();
140 if (!MkLogDirSuccess()) {
141 HILOGE("Create log dir failed");
142 return;
143 }
144 std::string logFilePath = hiAuditConfig_.logPath + hiAuditConfig_.logName + "_audit.csv";
145 writeFd_ =
146 open(logFilePath.c_str(), O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
147 if (writeFd_ < 0) {
148 HILOGE("GetWriteFilePath, Open fd error, errno:%{public}d", errno);
149 }
150 writeLogSize_ = 0;
151 }
152
CleanOldAuditFile()153 void HiAudit::CleanOldAuditFile()
154 {
155 uint32_t zipFileSize = 0;
156 std::string oldestAuditFile;
157 if (!MkLogDirSuccess()) {
158 HILOGE("Create log dir failed");
159 return;
160 }
161 DIR *dir = opendir(hiAuditConfig_.logPath.c_str());
162 if (dir == NULL) {
163 HILOGE("open dir error, errno:%{public}d", errno);
164 return;
165 }
166 struct dirent* ptr = nullptr;
167 while ((ptr = readdir(dir)) != nullptr) {
168 if (std::string(ptr->d_name).find(hiAuditConfig_.logName) != std::string::npos &&
169 std::string(ptr->d_name).find("zip") != std::string::npos) {
170 zipFileSize = zipFileSize + 1;
171 if (oldestAuditFile.empty()) {
172 oldestAuditFile = hiAuditConfig_.logPath + std::string(ptr->d_name);
173 continue;
174 }
175 struct stat st;
176 stat((hiAuditConfig_.logPath + std::string(ptr->d_name)).c_str(), &st);
177 struct stat oldestSt;
178 stat(oldestAuditFile.c_str(), &oldestSt);
179 if (st.st_mtime < oldestSt.st_mtime) {
180 oldestAuditFile = HIAUDIT_CONFIG.logPath + std::string(ptr->d_name);
181 }
182 }
183 }
184 closedir(dir);
185 if (zipFileSize > hiAuditConfig_.fileCount) {
186 remove(oldestAuditFile.c_str());
187 }
188 }
189
WriteToFile(const std::string &content)190 void HiAudit::WriteToFile(const std::string &content)
191 {
192 GetWriteFilePath();
193 if (writeFd_ < 0) {
194 HILOGE("Write content to file error, fd is invalid");
195 return;
196 }
197 write(writeFd_, content.c_str(), content.length());
198 writeLogSize_ = writeLogSize_ + content.length();
199 }
200
ZipAuditLog()201 void HiAudit::ZipAuditLog()
202 {
203 if (!MkLogDirSuccess()) {
204 HILOGE("Create log dir failed");
205 return;
206 }
207 std::string zipFileName = hiAuditConfig_.logPath + hiAuditConfig_.logName + "_audit_" +
208 GetFormattedTimestamp(GetMilliseconds(), "%Y%m%d%H%M%S");
209 std::string logFilePath = hiAuditConfig_.logPath + hiAuditConfig_.logName + "_audit.csv";
210 std::rename(logFilePath.c_str(), (zipFileName + ".csv").c_str());
211 zipFile compressZip = ZipUtil::CreateZipFile(zipFileName + ".zip");
212 if (compressZip == nullptr) {
213 HILOGW("open zip file failed.");
214 return;
215 }
216 if (ZipUtil::AddFileInZip(compressZip, zipFileName + ".csv", KEEP_NONE_PARENT_PATH) ==
217 0) {
218 remove((zipFileName + ".csv").c_str());
219 }
220 ZipUtil::CloseZipFile(compressZip);
221 }
222
MkLogDirSuccess()223 bool HiAudit::MkLogDirSuccess()
224 {
225 if (access(hiAuditConfig_.logPath.data(), F_OK) != 0) {
226 int ret = mkdir(hiAuditConfig_.logPath.data(), S_IRWXU | S_IRWXG);
227 if (ret != 0 || errno != 0 || errno != EEXIST) {
228 if (access(hiAuditConfig_.logPath.data(), F_OK) != 0) {
229 HILOGE("create log dir failed");
230 return false;
231 }
232 }
233 }
234 return true;
235 }
236 } // namespace OHOS::FileManagement::Backup