• 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 "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