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 "include/GetLog.h"
16 #include "include/sp_utils.h"
17 #include "include/smartperf_command.h"
18 #include <fstream>
19 #include <filesystem>
20 #include <vector>
21 #include <chrono>
22 #include <ctime>
23 namespace OHOS {
24 namespace SmartPerf {
GetHilogInMemory(std::vector<std::filesystem::path> & fileList)25 void GetLog::GetHilogInMemory(std::vector<std::filesystem::path> &fileList)
26 {
27 // Get current hilog in "hilog" command
28 std::string hilogTmp = hilogFileDir + "hilogTmp";
29 std::string cmd = CMD_COMMAND_MAP.at(CmdCommand::GET_HILOG) + hilogTmp;
30 std::string cmdResult;
31 if (!SPUtils::LoadCmd(cmd, cmdResult)) {
32 WLOGE("Failed to GetHilogCommand files: %s", hilogTmp.c_str());
33 }
34 if (std::filesystem::exists(hilogTmp)) {
35 currentLogSize += std::filesystem::file_size(hilogTmp);
36 fileList.push_back(hilogTmp);
37 }
38 }
39
RemoveLogFile()40 void GetLog::RemoveLogFile()
41 {
42 // Process before and after send
43 SPUtils::RemoveDirOrFile(logFilePath);
44 SPUtils::RemoveDirOrFile(hilogFileDir);
45 SPUtils::RemoveDirOrFile(daemonLogFileDir);
46
47 currentLogSize = 0;
48 }
49
GenerateDaemonLogFile()50 void GetLog::GenerateDaemonLogFile()
51 {
52 const std::string preLogFileName = "log.";
53 std::filesystem::path dirPath(LOG_FILE_DIR); // Log file directory
54 std::vector<std::filesystem::path> files; // Log file vector to tar
55
56 SPUtils::CreateDir(daemonLogFileDir); // Create daemonLog directory
57
58 // Save current working directory to restore it later
59 // Change directory to handle relative paths in tar operations
60 std::string originPath;
61 if (std::filesystem::current_path().string().empty()) {
62 WLOGE("Failed to get current working directory");
63 return;
64 }
65 originPath = std::filesystem::current_path().string();
66 std::filesystem::current_path(LOG_FILE_DIR);
67
68 // Get all log files in LOG_FILE_DIR
69 for (const auto& entry : std::filesystem::directory_iterator(dirPath)) {
70 if (std::filesystem::is_regular_file(entry)) {
71 if (entry.path().filename().string().substr(0, preLogFileName.length()) != preLogFileName) {
72 continue; // Skip files that don't start with "log."
73 }
74 files.push_back(entry.path());
75 }
76 }
77
78 // Sort log files by last write time
79 std::sort(files.begin(), files.end(), [](const auto& a, const auto& b) {
80 return std::filesystem::last_write_time(a) > std::filesystem::last_write_time(b);
81 });
82
83 // Build tar command with relative paths only, respecting size limit
84 std::string cpCommand = "";
85 for (const auto& file : files) {
86 uintmax_t fileSize = std::filesystem::file_size(file);
87 if (currentLogSize + fileSize > logMaxSize) {
88 break; // Stop if adding this file would exceed the limit
89 }
90 currentLogSize += fileSize;
91 std::string filename = file.filename().string();
92 cpCommand += filename + " ";
93 }
94 cpCommand += daemonLogFileDir;
95 SPUtils::CopyFiles(cpCommand);
96
97 std::filesystem::current_path(originPath.c_str());
98 WLOGI("Created tar archive of daemonLog files successfully");
99 }
100
to_time_t(const std::filesystem::file_time_type & ftime)101 std::time_t to_time_t(const std::filesystem::file_time_type &ftime)
102 {
103 auto systemTime = std::chrono::time_point_cast<std::chrono::system_clock::duration>
104 (ftime - std::filesystem::file_time_type::clock::now() + std::chrono::system_clock::now());
105 return std::chrono::system_clock::to_time_t(systemTime);
106 }
107
GetHilogInData(std::vector<std::filesystem::path> & otherFiles,std::vector<std::filesystem::path> & logFiles)108 void GetLog::GetHilogInData(std::vector<std::filesystem::path> &otherFiles,
109 std::vector<std::filesystem::path> &logFiles)
110 {
111 std::filesystem::path dirPath(systemHilogFileDir);
112
113 try {
114 if (std::filesystem::exists(dirPath)) {
115 WLOGI("Success read hilog dir");
116 }
117 } catch (const std::filesystem::filesystem_error &e) {
118 WLOGE("GetHilogFiles error: %s", e.what());
119 return;
120 }
121
122 for (const auto& entry : std::filesystem::directory_iterator(dirPath)) {
123 if (!std::filesystem::is_regular_file(entry)) {
124 continue;
125 }
126
127 std::string extension = entry.path().extension().string();
128 if (extension == ".log" || extension == ".zip") {
129 otherFiles.push_back(entry.path());
130 continue;
131 }
132
133 if (extension != ".gz") {
134 continue;
135 }
136
137 // Handle .gz files
138 auto fileTime = std::filesystem::last_write_time(entry.path());
139 auto fileTimeT = to_time_t(fileTime);
140 auto nowT = to_time_t(std::filesystem::file_time_type::clock::now());
141 if (std::localtime(&fileTimeT) == nullptr || std::localtime(&nowT) == nullptr) {
142 WLOGE("Get local time is null");
143 return;
144 }
145 std::tm* fileTm = std::localtime(&fileTimeT);
146 std::tm* nowTm = std::localtime(&nowT);
147 if (fileTm == nullptr || nowTm == nullptr) {
148 WLOGE("Get local time ptr is null");
149 return;
150 }
151
152 bool isSameDay = (fileTm->tm_year == nowTm->tm_year) &&
153 (fileTm->tm_mon == nowTm->tm_mon) &&
154 (fileTm->tm_mday == nowTm->tm_mday);
155
156 if (isSameDay) {
157 logFiles.push_back(entry.path());
158 }
159 }
160 }
161
GenerateHilogFile()162 void GetLog::GenerateHilogFile()
163 {
164 std::vector<std::filesystem::path> filesLog; // Log file vector to tar
165 std::vector<std::filesystem::path> filesOther; // Other file vector to tar
166
167 SPUtils::CreateDir(hilogFileDir);
168 std::string originPath;
169 if (std::filesystem::current_path().string().empty()) {
170 WLOGE("Failed to get current working directory");
171 return;
172 }
173 originPath = std::filesystem::current_path().string();
174 GetHilogInMemory(filesLog);
175 GetHilogInData(filesOther, filesLog);
176
177 if (filesLog.empty() && filesOther.empty()) {
178 WLOGE("Failed to get hilog files");
179 return;
180 }
181
182 // Sort hilog files by last write time
183 std::sort(filesLog.begin(), filesLog.end(), [](const auto& a, const auto& b) {
184 return std::filesystem::last_write_time(a) > std::filesystem::last_write_time(b);
185 });
186
187 // cd LOG_FILE_DIR
188 std::filesystem::current_path(systemHilogFileDir);
189 // Build tokar command with relative paths only
190 std::string cpCommand = "";
191 for (const auto& file : filesOther) {
192 uintmax_t fileSize = std::filesystem::file_size(file);
193 if (currentLogSize + fileSize > logMaxSize) {
194 break; // Stop if adding this file would exceed the limit
195 }
196 currentLogSize += fileSize;
197 std::string filename = file.filename().string();
198 cpCommand += filename + " ";
199 }
200 for (const auto& file : filesLog) {
201 uintmax_t fileSize = std::filesystem::file_size(file);
202 if (currentLogSize + fileSize > logMaxSize) {
203 break; // Stop if adding this file would exceed the limit
204 }
205 currentLogSize += fileSize;
206 std::string filename = file.filename().string();
207 cpCommand += filename + " ";
208 }
209 cpCommand += hilogFileDir;
210 SPUtils::CopyFiles(cpCommand);
211
212 std::filesystem::current_path(originPath.c_str());
213 WLOGI("Created tar archive of hilog files successfully");
214 }
215
TarLogFile()216 void GetLog::TarLogFile()
217 {
218 GenerateDaemonLogFile();
219 GenerateHilogFile();
220
221 std::string originPath;
222 if (std::filesystem::current_path().string().empty()) {
223 WLOGE("Failed to get current working directory");
224 return;
225 }
226 originPath = std::filesystem::current_path().string();
227
228 // cd LOG_FILE_DIR
229 std::filesystem::current_path(LOG_FILE_DIR);
230
231 // Check if directories exist
232 if (!std::filesystem::exists("daemonLog")) {
233 WLOGE("One or both directories do not exist");
234 std::filesystem::current_path(originPath.c_str());
235 return;
236 }
237
238 // Build tar command with relative paths
239 std::string tarCommand = logFilePath + " hilog daemonLog";
240 SPUtils::TarFiles(tarCommand);
241
242 // Restore original working directory
243 std::filesystem::current_path(originPath.c_str());
244 WLOGI("Created tar archive of log files successfully");
245 }
246
ItemData()247 std::map<std::string, std::string> GetLog::ItemData()
248 {
249 // Remove old log tar file
250 RemoveLogFile();
251 // Create tar archive of log files
252 TarLogFile();
253 // Return empty map to satisfy interface
254 return std::map<std::string, std::string>();
255 }
256
257 } // namespace SmartPerf
258 } // namespace OHOS