1 /*
2  * Copyright (c) 2023 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 "freeze_json_util.h"
17 
18 #include <list>
19 #include <map>
20 #include <fcntl.h>
21 #include <fstream>
22 #include <sstream>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 
26 #include "file_util.h"
27 #include "string_util.h"
28 
29 namespace OHOS {
30 namespace HiviewDFX {
31 namespace FreezeJsonUtil {
IncludeWith(std::list<std::string> list,const std::string & target)32 bool IncludeWith(std::list<std::string> list, const std::string& target)
33 {
34     for (auto it = list.begin(); it != list.end(); it++) {
35         if (target == *it) {
36             return true;
37         }
38     }
39     return false;
40 }
41 
IsAppFreeze(const std::string & eventName)42 bool IsAppFreeze(const std::string& eventName)
43 {
44     return IncludeWith(APPFREEZE_TYPE_LIST, eventName);
45 }
46 
GetFilePath(long pid,long uid,unsigned long long timestamp)47 std::string GetFilePath(long pid, long uid, unsigned long long timestamp)
48 {
49     std::stringstream ss;
50     ss << LOGGER_FREEZEJSON_LOG_PATH << "/" << pid << "-" << uid << "-" << timestamp;
51     return ss.str();
52 }
53 
GetFd(const std::string & filePath)54 int GetFd(const std::string& filePath)
55 {
56     if (!FileUtil::FileExists(LOGGER_FREEZEJSON_LOG_PATH)) {
57         FileUtil::ForceCreateDirectory(LOGGER_FREEZEJSON_LOG_PATH);
58     }
59     if (!FileUtil::IsLegalPath(filePath)) {
60         return -1;
61     }
62     return open(filePath.c_str(), O_CREAT | O_RDWR | O_APPEND, DEFAULT_LOG_FILE_MODE);
63 }
64 
DelFile(const std::string & filePath)65 bool DelFile(const std::string& filePath)
66 {
67     if (!FileUtil::FileExists(filePath)) {
68         return true;
69     }
70     return FileUtil::RemoveFile(filePath);
71 }
72 
CountSubStr(const std::string & str,const std::string & subStr)73 int CountSubStr(const std::string& str, const std::string& subStr)
74 {
75     size_t pos = 0;
76     int count = 0;
77     while ((pos = str.find(subStr, pos)) < str.size()) {
78         count++;
79         pos += subStr.size();
80     }
81     return count;
82 }
83 
FormatCollect(std::map<std::string,std::list<std::string>> & collectMap,FreezeJsonCollector & jsonCollector)84 void FormatCollect(std::map<std::string, std::list<std::string>>& collectMap, FreezeJsonCollector& jsonCollector)
85 {
86     if (!collectMap["timestamp"].empty()) {
87         jsonCollector.timestamp = std::stoull(collectMap["timestamp"].front());
88     }
89 
90     if (!collectMap["pid"].empty()) {
91         jsonCollector.pid = std::stol(collectMap["pid"].front());
92     }
93 
94     if (!collectMap["uid"].empty()) {
95         jsonCollector.uid = std::stol(collectMap["uid"].front());
96     }
97 
98     if (!collectMap["domain"].empty()) {
99         jsonCollector.domain = collectMap["domain"].front();
100     }
101 
102     if (!collectMap["stringId"].empty()) {
103         jsonCollector.stringId = collectMap["stringId"].front();
104     }
105 
106     if (!collectMap["package_name"].empty()) {
107         jsonCollector.package_name = collectMap["package_name"].front();
108     }
109 
110     if (!collectMap["process_name"].empty()) {
111         jsonCollector.process_name = collectMap["process_name"].front();
112     }
113 
114     if (!collectMap["message"].empty()) {
115         // use the earliest message
116         jsonCollector.message = collectMap["message"].front();
117     }
118 
119     if (!collectMap["peer_binder"].empty()) {
120         // use the earliest peer_binder
121         jsonCollector.peer_binder = collectMap["peer_binder"].front();
122     }
123 
124     if (!collectMap["event_handler"].empty()) {
125         // use the latest peer_binder
126         jsonCollector.event_handler = *(collectMap["event_handler"].rbegin());
127         if (collectMap["event_handler"].size() != 1) {
128             std::string flag = "Event {";
129             jsonCollector.event_handler_3s_size =
130                 std::to_string(CountSubStr(*(collectMap["event_handler"].begin()), flag));
131             jsonCollector.event_handler_6s_size =
132                 std::to_string(CountSubStr(*(collectMap["event_handler"].rbegin()), flag));
133         }
134     }
135 
136     if (!collectMap["stack"].empty()) {
137         // use the earliest peer_binder
138         jsonCollector.stack = collectMap["stack"].front();
139     }
140 
141     if (!collectMap["appRunningUniqueId"].empty()) {
142         jsonCollector.appRunningUniqueId = collectMap["appRunningUniqueId"].front();
143     }
144 }
145 
LoadCollectorFromFile(const std::string & filePath,FreezeJsonCollector & jsonCollector)146 void LoadCollectorFromFile(const std::string& filePath, FreezeJsonCollector& jsonCollector)
147 {
148     std::map<std::string, std::list<std::string>> collectMap;
149     std::string lineStr;
150     if (!FileUtil::FileExists(filePath)) {
151         return;
152     }
153     std::ifstream jsonFile(filePath);
154     while (std::getline(jsonFile, lineStr)) {
155         std::string::size_type pos = lineStr.find(COMMON_EQUAL);
156         if (pos == std::string::npos) {
157             continue;
158         }
159         std::string key = lineStr.substr(0, pos);
160         if (!IncludeWith(KEY_IN_LOGFILE, key)) {
161             continue;
162         }
163         std::string value = lineStr.substr(pos + COMMON_EQUAL.size());
164         collectMap[key].push_back(value);
165     }
166     jsonFile.close();
167     FormatCollect(collectMap, jsonCollector);
168 }
169 
HasBeenWrapped(const std::string & target)170 bool HasBeenWrapped(const std::string& target)
171 {
172     std::string::size_type minLen = 2;
173     if (target.size() < minLen) {
174         return false;
175     }
176     char head = target[0];
177     char foot = target[target.size() - 1];
178     return (head == COMMON_QUOTE[0] && foot == COMMON_QUOTE[0]) ||
179         (head == COMMON_LEFT_BRACE[0] && foot == COMMON_RIGHT_BRACE[0]) ||
180         (head == COMMON_LEFT_SQUARE_BRACKET[0] && foot == COMMON_RIGHT_SQUARE_BREAKET[0]);
181 }
182 
WrapByParenthesis(const std::string & wrapped)183 std::string WrapByParenthesis(const std::string& wrapped)
184 {
185     return COMMON_LEFT_PARENTHESIS + wrapped + COMMON_RIGHT_PARENTHESIS;
186 }
187 
WrapBySquareBracket(const std::string & wrapped)188 std::string WrapBySquareBracket(const std::string& wrapped)
189 {
190     return COMMON_LEFT_SQUARE_BRACKET + wrapped + COMMON_RIGHT_SQUARE_BREAKET;
191 }
192 
WrapByBrace(const std::string & wrapped)193 std::string WrapByBrace(const std::string& wrapped)
194 {
195     return COMMON_LEFT_BRACE + wrapped + COMMON_RIGHT_BRACE;
196 }
197 
MergeKeyValueList(std::list<std::string> & list)198 std::string MergeKeyValueList(std::list<std::string>& list)
199 {
200     std::stringstream jsonSs;
201     if (!list.empty()) {
202         auto it = list.begin();
203         jsonSs << *it;
204         it++;
205         while (it != list.end()) {
206             jsonSs << COMMON_COMMA << *it;
207             it++;
208         }
209     }
210     return WrapByBrace(jsonSs.str());
211 }
212 
213 } // namespace FreezeJsonUtil
214 } // namespace HiviewDFX
215 } // namespace OHOS