• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 "backup_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 <filesystem>
25 #include <sys/time.h>
26 #include <unistd.h>
27 
28 #include "backup_zip_util.h"
29 #include "media_log.h"
30 #include "media_file_utils.h"
31 
32 namespace OHOS::Media {
33 struct BackupHiAuditConfig {
34     std::string logPath;
35     std::string logName;
36     uint32_t logSize;
37     uint32_t fileSize;
38     uint32_t fileCount;
39 };
40 
41 const BackupHiAuditConfig HIAUDIT_CONFIG = { "/data/storage/el2/log/audit/", "media_library_backup", 2 * 1024,
42     3 * 1024 * 1024, 10 };
43 constexpr int8_t MILLISECONDS_LENGTH = 3;
44 constexpr int64_t SEC_TO_MILLISEC = 1000;
45 constexpr int MAX_TIME_BUFF = 64;
46 const std::string HIAUDIT_LOG_NAME = HIAUDIT_CONFIG.logPath + HIAUDIT_CONFIG.logName + "_audit.csv";
47 // LCOV_EXCL_START
BackupHiAudit()48 BackupHiAudit::BackupHiAudit()
49 {
50     Init();
51 }
52 
~BackupHiAudit()53 BackupHiAudit::~BackupHiAudit()
54 {
55     if (writeFd_ >= 0) {
56         close(writeFd_);
57     }
58 }
59 
GetInstance()60 BackupHiAudit& BackupHiAudit::GetInstance()
61 {
62     static BackupHiAudit hiAudit;
63     return hiAudit;
64 }
65 
Init()66 void BackupHiAudit::Init()
67 {
68     if (!std::filesystem::exists(HIAUDIT_CONFIG.logPath)) {
69         if (!MediaFileUtils::CreateDirectory(HIAUDIT_CONFIG.logPath)) {
70             MEDIA_ERR_LOG("Create hiaudit log dir  %{public}s failed", HIAUDIT_CONFIG.logPath.c_str());
71             return ;
72         }
73         std::filesystem::permissions(HIAUDIT_CONFIG.logPath,
74             std::filesystem::perms::owner_all | std::filesystem::perms::group_all | std::filesystem::perms::others_all,
75             std::filesystem::perm_options::replace);
76     }
77 
78     std::lock_guard<std::mutex> lock(mutex_);
79     writeFd_ = open(HIAUDIT_LOG_NAME.c_str(), O_CREAT | O_APPEND | O_RDWR,
80         S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
81     if (writeFd_ < 0) {
82         MEDIA_ERR_LOG("writeFd_ open error errno: %{public}d", errno);
83     }
84     struct stat st;
85     writeLogSize_ = stat(HIAUDIT_LOG_NAME.c_str(), &st) ? 0 : static_cast<uint64_t>(st.st_size);
86     MEDIA_INFO_LOG("writeLogSize: %{public}u", writeLogSize_.load());
87 }
88 
GetMilliseconds()89 uint64_t BackupHiAudit::GetMilliseconds()
90 {
91     auto now = std::chrono::system_clock::now();
92     auto millisecs = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
93     return millisecs.count();
94 }
95 
GetFormattedTimestamp(time_t timeStamp,const std::string & format)96 std::string BackupHiAudit::GetFormattedTimestamp(time_t timeStamp, const std::string& format)
97 {
98     auto seconds = timeStamp / SEC_TO_MILLISEC;
99     char date[MAX_TIME_BUFF] = {0};
100     struct tm result {};
101     if (localtime_r(&seconds, &result) != nullptr) {
102         strftime(date, MAX_TIME_BUFF, format.c_str(), &result);
103     }
104     return std::string(date);
105 }
106 
GetFormattedTimestampEndWithMilli()107 std::string BackupHiAudit::GetFormattedTimestampEndWithMilli()
108 {
109     uint64_t milliSeconds = GetMilliseconds();
110     std::string formattedTimeStamp = GetFormattedTimestamp(milliSeconds, "%Y%m%d%H%M%S");
111     std::stringstream ss;
112     ss << formattedTimeStamp;
113     milliSeconds = milliSeconds % SEC_TO_MILLISEC;
114     ss << std::setfill('0') << std::setw(MILLISECONDS_LENGTH) << milliSeconds;
115     return ss.str();
116 }
117 
Write(const BackupAuditLog & auditLog)118 void BackupHiAudit::Write(const BackupAuditLog& auditLog)
119 {
120     std::lock_guard<std::mutex> lock(mutex_);
121     if (writeLogSize_ == 0) {
122         WriteToFile(auditLog.TitleString() + "\n");
123     }
124     std::string writeLog = GetFormattedTimestampEndWithMilli() + "," +
125         HIAUDIT_CONFIG.logName + ",NO," + auditLog.ToString();
126     if (writeLog.length() > HIAUDIT_CONFIG.logSize) {
127         MEDIA_INFO_LOG("write exceeds %{public}u: %{public}s.", HIAUDIT_CONFIG.logSize, writeLog.c_str());
128         writeLog = writeLog.substr(0, HIAUDIT_CONFIG.logSize);
129     }
130     writeLog = writeLog + "\n";
131     WriteToFile(writeLog);
132 }
133 
GetWriteFilePath()134 void BackupHiAudit::GetWriteFilePath()
135 {
136     if (writeLogSize_ < HIAUDIT_CONFIG.fileSize) {
137         return;
138     }
139 
140     close(writeFd_);
141     ZipAuditLog();
142     CleanOldAuditFile();
143 
144     writeFd_ = open(HIAUDIT_LOG_NAME.c_str(), O_CREAT | O_TRUNC | O_RDWR,
145         S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
146     CHECK_AND_PRINT_LOG(writeFd_ >= 0, "fd open error errno: %{public}d", errno);
147 
148     writeLogSize_ = 0;
149 }
150 
CleanOldAuditFile()151 void BackupHiAudit::CleanOldAuditFile()
152 {
153     DIR* dir = opendir(HIAUDIT_CONFIG.logPath.c_str());
154     CHECK_AND_RETURN_LOG(dir != nullptr, "failed open dir, errno: %{public}d.", errno);
155 
156     uint32_t zipFileSize = 0;
157     std::string oldestAuditFile;
158     struct dirent *ptr = nullptr;
159     while ((ptr = readdir(dir)) != nullptr) {
160         if (std::string(ptr->d_name).find(HIAUDIT_CONFIG.logName) != std::string::npos &&
161             std::string(ptr->d_name).find("zip") != std::string::npos) {
162             zipFileSize = zipFileSize + 1;
163             if (oldestAuditFile.empty()) {
164                 oldestAuditFile = HIAUDIT_CONFIG.logPath + std::string(ptr->d_name);
165                 continue;
166             }
167             struct stat st;
168             stat((HIAUDIT_CONFIG.logPath + std::string(ptr->d_name)).c_str(), &st);
169             struct stat oldestSt;
170             stat(oldestAuditFile.c_str(), &oldestSt);
171             if (st.st_mtime < oldestSt.st_mtime) {
172                 oldestAuditFile = HIAUDIT_CONFIG.logPath + std::string(ptr->d_name);
173             }
174         }
175     }
176     closedir(dir);
177     if (zipFileSize > HIAUDIT_CONFIG.fileCount) {
178         remove(oldestAuditFile.c_str());
179     }
180 }
181 
WriteToFile(const std::string & content)182 void BackupHiAudit::WriteToFile(const std::string& content)
183 {
184     GetWriteFilePath();
185     if (writeFd_ < 0) {
186         MEDIA_ERR_LOG("fd invalid.");
187         return;
188     }
189     write(writeFd_, content.c_str(), content.length());
190     writeLogSize_ = writeLogSize_ + content.length();
191 }
192 
ZipAuditLog()193 void BackupHiAudit::ZipAuditLog()
194 {
195     std::string zipFileName = HIAUDIT_CONFIG.logPath + HIAUDIT_CONFIG.logName + "_audit_" +
196         GetFormattedTimestamp(GetMilliseconds(), "%Y%m%d%H%M%S");
197     std::rename(HIAUDIT_LOG_NAME.c_str(), (zipFileName + ".csv").c_str());
198     zipFile compressZip = BackupZipUtil::CreateZipFile(zipFileName + ".zip");
199     if (compressZip == nullptr) {
200         MEDIA_WARN_LOG("open zip file failed.");
201         return;
202     }
203     if (BackupZipUtil::AddFileInZip(compressZip, zipFileName + ".csv", KEEP_NONE_PARENT_PATH) == 0) {
204         remove((zipFileName + ".csv").c_str());
205     }
206     BackupZipUtil::CloseZipFile(compressZip);
207 }
208 // LCOV_EXCL_STOP
209 } // namespace OHOS::Media