• 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 "hi_audit.h"
17 
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <iomanip>
21 #include <sstream>
22 #include <unistd.h>
23 
24 #include "storage_service_log.h"
25 #include "zip_util.h"
26 
27 namespace OHOS {
28 struct HiAuditConfig {
29     std::string logPath;
30     std::string logName;
31     uint32_t logSize; // kb
32     uint32_t fileSize;
33     uint32_t fileCount;
34 };
35 
36 const HiAuditConfig HIAUDIT_CONFIG = {
37     "/data/log/hiaudit/storageservice/", "storageservice", 2 * 1024, 3 * 1024 * 1024, 10};
38 constexpr int8_t MILLISECONDS_LENGTH = 3;
39 constexpr int64_t SEC_TO_MILLISEC = 1000;
40 constexpr int MAX_TIME_BUFF = 64; // 64 : for example 2021-05-27-01-01-01
41 const std::string HIAUDIT_LOG_NAME = HIAUDIT_CONFIG.logPath + HIAUDIT_CONFIG.logName + "_audit.csv";
42 
HiAudit()43 HiAudit::HiAudit()
44 {
45     Init();
46 }
47 
~HiAudit()48 HiAudit::~HiAudit()
49 {
50     if (writeFd_ >= 0) {
51         close(writeFd_);
52     }
53 }
54 
GetInstance()55 HiAudit& HiAudit::GetInstance()
56 {
57     static HiAudit hiAudit;
58     return hiAudit;
59 }
60 
Init()61 void HiAudit::Init()
62 {
63     if (access(HIAUDIT_CONFIG.logPath.c_str(), F_OK) != 0) {
64         int32_t ret = mkdir(HIAUDIT_CONFIG.logPath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
65         if (ret != 0) {
66             LOGE("Failed to create directory %{public}s.", HIAUDIT_CONFIG.logPath.c_str());
67         }
68     }
69 
70     std::lock_guard<std::mutex> lock(mutex_);
71     writeFd_ = open(HIAUDIT_LOG_NAME.c_str(), O_CREAT | O_APPEND | O_RDWR,
72         S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
73     if (writeFd_ < 0) {
74         LOGE("writeFd_ open error");
75     }
76     struct stat st;
77     writeLogSize_ = stat(HIAUDIT_LOG_NAME.c_str(), &st) ? 0 : static_cast<uint64_t>(st.st_size);
78     LOGI("writeLogSize: %{public}u", writeLogSize_.load());
79 }
80 
GetMilliseconds()81 uint64_t HiAudit::GetMilliseconds()
82 {
83     auto now = std::chrono::system_clock::now();
84     auto millisecs = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
85     return millisecs.count();
86 }
87 
GetFormattedTimestamp(time_t timeStamp,const std::string & format)88 std::string HiAudit::GetFormattedTimestamp(time_t timeStamp, const std::string& format)
89 {
90     auto seconds = timeStamp / SEC_TO_MILLISEC;
91     char date[MAX_TIME_BUFF] = {0};
92     struct tm result {};
93     if (localtime_r(&seconds, &result) != nullptr) {
94         strftime(date, MAX_TIME_BUFF, format.c_str(), &result);
95     }
96     return std::string(date);
97 }
98 
GetFormattedTimestampEndWithMilli()99 std::string HiAudit::GetFormattedTimestampEndWithMilli()
100 {
101     uint64_t milliSeconds = GetMilliseconds();
102     std::string formattedTimeStamp = GetFormattedTimestamp(milliSeconds, "%Y%m%d%H%M%S");
103     std::stringstream ss;
104     ss << formattedTimeStamp;
105     milliSeconds = milliSeconds % SEC_TO_MILLISEC;
106     ss << std::setfill('0') << std::setw(MILLISECONDS_LENGTH) << milliSeconds;
107     return ss.str();
108 }
109 
Write(const AuditLog & auditLog)110 void HiAudit::Write(const AuditLog& auditLog)
111 {
112     LOGI("write storageservice audit log");
113     std::lock_guard<std::mutex> lock(mutex_);
114     if (writeLogSize_ == 0) {
115         WriteToFile(auditLog.TitleString() + "\n");
116     }
117     std::string writeLog = GetFormattedTimestampEndWithMilli() + ", " +
118         HIAUDIT_CONFIG.logName + ", NO, " + auditLog.ToString();
119     LOGI("write %{public}s.", writeLog.c_str());
120     if (writeLog.length() > HIAUDIT_CONFIG.logSize) {
121         writeLog = writeLog.substr(0, HIAUDIT_CONFIG.logSize);
122     }
123     writeLog = writeLog + "\n";
124     WriteToFile(writeLog);
125 }
126 
GetWriteFilePath()127 void HiAudit::GetWriteFilePath()
128 {
129     if (writeLogSize_ < HIAUDIT_CONFIG.fileSize) {
130         return;
131     }
132 
133     close(writeFd_);
134     ZipAuditLog();
135     CleanOldAuditFile();
136 
137     writeFd_ = open(HIAUDIT_LOG_NAME.c_str(), O_CREAT | O_TRUNC | O_RDWR,
138         S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
139     if (writeFd_ < 0) {
140         LOGE("fd open error");
141     }
142 
143     writeLogSize_ = 0;
144 }
145 
CleanOldAuditFile()146 void HiAudit::CleanOldAuditFile()
147 {
148     uint32_t zipFileSize = 0;
149     std::string oldestAuditFile;
150     DIR* dir = opendir(HIAUDIT_CONFIG.logPath.c_str());
151     if (dir == nullptr) {
152         LOGE("failed open dir, errno: %{public}d.", errno);
153         return;
154     }
155     while (true) {
156         struct dirent* ptr = readdir(dir);
157         if (ptr == nullptr) {
158             break;
159         }
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 HiAudit::WriteToFile(const std::string& content)
183 {
184     GetWriteFilePath();
185     if (writeFd_ < 0) {
186         LOGE("fd invalid.");
187         return;
188     }
189     write(writeFd_, content.c_str(), content.length());
190     writeLogSize_ = writeLogSize_ + content.length();
191 }
192 
ZipAuditLog()193 void HiAudit::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 = StorageDaemon::ZipUtil::CreateZipFile(zipFileName + ".zip");
199     if (compressZip == nullptr) {
200         LOGW("open zip file failed.");
201         return;
202     }
203     if (StorageDaemon::ZipUtil::AddFileInZip(compressZip, zipFileName + ".csv", StorageDaemon::KEEP_NONE_PARENT_PATH) ==
204         0) {
205         remove((zipFileName + ".csv").c_str());
206     }
207     StorageDaemon::ZipUtil::CloseZipFile(compressZip);
208 }
209 } // namespace OHOS