• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "parse_util.h"
17 
18 #include <cinttypes>
19 #include <dlfcn.h>
20 #include <fstream>
21 #include <sstream>
22 #include "datetime_ex.h"
23 
24 #include "sam_log.h"
25 #include "string_ex.h"
26 
27 namespace OHOS {
28 using std::string;
29 
30 namespace {
31 const auto XML_TAG_PROFILE = "profile";
32 const auto XML_TAG_INFO = "info";
33 const auto XML_TAG_SYSTEM_ABILITY = "systemability";
34 const auto XML_TAG_PROCESS = "process";
35 const auto XML_TAG_LIB_PATH = "libpath";
36 const auto XML_TAG_NAME = "name";
37 const auto XML_TAG_DEPEND = "depend";
38 const auto XML_TAG_DEPEND_TIMEOUT = "depend-time-out";
39 const auto XML_TAG_RUN_ON_CREATE = "run-on-create";
40 const auto XML_TAG_DISTRIBUTED = "distributed";
41 const auto XML_TAG_DUMP_LEVEL = "dump-level";
42 const auto XML_TAG_CAPABILITY = "capability";
43 const auto XML_TAG_PERMISSION = "permission";
44 const auto XML_TAG_BOOT_PHASE = "bootphase";
45 const auto XML_TAG_SAID = "said";
46 }
47 
~ParseUtil()48 ParseUtil::~ParseUtil()
49 {
50     ClearResource();
51 }
52 
CloseHandle(SaProfile & saProfile)53 void ParseUtil::CloseHandle(SaProfile& saProfile)
54 {
55     if (saProfile.handle == nullptr) {
56         return;
57     }
58     int32_t ret = dlclose(saProfile.handle);
59     if (ret) {
60         HILOGW("close handle failed with errno:%{public}d!", errno);
61     }
62     saProfile.handle = nullptr;
63 }
64 
CloseSo()65 void ParseUtil::CloseSo()
66 {
67     for (auto& saProfile : saProfiles_) {
68         CloseHandle(saProfile);
69     }
70 }
71 
CloseSo(int32_t systemAbilityId)72 void ParseUtil::CloseSo(int32_t systemAbilityId)
73 {
74     for (auto& saProfile : saProfiles_) {
75         if (saProfile.saId == systemAbilityId) {
76             CloseHandle(saProfile);
77             break;
78         }
79     }
80 }
81 
ClearResource()82 void ParseUtil::ClearResource()
83 {
84     CloseSo();
85     saProfiles_.clear();
86 }
87 
OpenSo()88 void ParseUtil::OpenSo()
89 {
90     for (auto& saProfile : saProfiles_) {
91         if (saProfile.runOnCreate) {
92             OpenSo(saProfile);
93         }
94     }
95 }
96 
OpenSo(SaProfile & saProfile)97 void ParseUtil::OpenSo(SaProfile& saProfile)
98 {
99     if (saProfile.handle == nullptr) {
100         int64_t begin = GetTickCount();
101         DlHandle handle = dlopen(Str16ToStr8(saProfile.libPath).c_str(), RTLD_NOW);
102         HILOGI("[PerformanceTest] SA:%{public}d OpenSo spend %{public}" PRId64 " ms",
103             saProfile.saId, GetTickCount() - begin);
104         if (handle == nullptr) {
105             std::vector<string> libPathVec;
106             string fileName = "";
107             SplitStr(Str16ToStr8(saProfile.libPath), "/", libPathVec);
108             if ((libPathVec.size() > 0)) {
109                 fileName = libPathVec[libPathVec.size() - 1];
110             }
111             HILOGE("dlopen %{public}s failed with errno:%s!", fileName.c_str(), dlerror());
112             return;
113         }
114         saProfile.handle = handle;
115     } else {
116         HILOGI("SA:%{public}d handle is not null", saProfile.saId);
117     }
118 }
119 
LoadSaLib(int32_t systemAbilityId)120 bool ParseUtil::LoadSaLib(int32_t systemAbilityId)
121 {
122     for (auto& saProfile : saProfiles_) {
123         if (saProfile.saId == systemAbilityId) {
124             OpenSo(saProfile);
125             return true;
126         }
127     }
128     return false;
129 }
130 
GetAllSaProfiles() const131 const std::list<SaProfile>& ParseUtil::GetAllSaProfiles() const
132 {
133     return saProfiles_;
134 }
135 
GetProfile(int32_t saId,SaProfile & saProfile)136 bool ParseUtil::GetProfile(int32_t saId, SaProfile& saProfile)
137 {
138     auto iter = std::find_if(saProfiles_.begin(), saProfiles_.end(), [saId](auto saProfile) {
139         return saProfile.saId == saId;
140     });
141     if (iter != saProfiles_.end()) {
142         saProfile = *iter;
143         return true;
144     }
145     return false;
146 }
147 
RemoveSaProfile(int32_t saId)148 void ParseUtil::RemoveSaProfile(int32_t saId)
149 {
150     saProfiles_.remove_if([saId] (auto saInfo) -> bool { return saInfo.saId == saId; });
151 }
152 
ParseSAProp(const string & nodeName,const string & nodeContent,SaProfile & saProfile)153 void ParseUtil::ParseSAProp(const string& nodeName, const string& nodeContent, SaProfile& saProfile)
154 {
155     if (nodeName == XML_TAG_NAME) {
156         StrToInt(nodeContent.c_str(), saProfile.saId);
157     } else if (nodeName == XML_TAG_LIB_PATH) {
158         saProfile.libPath = Str8ToStr16(nodeContent);
159     } else if (nodeName == XML_TAG_DEPEND) {
160         saProfile.dependSa.emplace_back(Str8ToStr16(nodeContent));
161     } else if (nodeName == XML_TAG_DEPEND_TIMEOUT) {
162         StrToInt(nodeContent.c_str(), saProfile.dependTimeout);
163     } else if (nodeName == XML_TAG_RUN_ON_CREATE) {
164         std::istringstream(nodeContent) >> std::boolalpha >> saProfile.runOnCreate;
165     } else if (nodeName == XML_TAG_DISTRIBUTED) {
166         std::istringstream(nodeContent) >> std::boolalpha >> saProfile.distributed;
167     } else if (nodeName == XML_TAG_DUMP_LEVEL) {
168         std::stringstream ss(nodeContent);
169         ss >> saProfile.dumpLevel;
170     } else if (nodeName == XML_TAG_CAPABILITY) {
171         saProfile.capability = Str8ToStr16(nodeContent);
172     } else if (nodeName == XML_TAG_PERMISSION) {
173         saProfile.permission = Str8ToStr16(nodeContent);
174     } else if (nodeName == XML_TAG_BOOT_PHASE) {
175         saProfile.bootPhase = Str8ToStr16(nodeContent);
176     }
177 }
178 
ParseSystemAbility(const xmlNode & rootNode,const std::u16string & process)179 bool ParseUtil::ParseSystemAbility(const xmlNode& rootNode, const std::u16string& process)
180 {
181     auto currNodePtr = rootNode.xmlChildrenNode;
182     if (currNodePtr == nullptr) {
183         return false;
184     }
185     SaProfile saProfile;
186     saProfile.process = process;
187     for (; currNodePtr != nullptr; currNodePtr = currNodePtr->next) {
188         if (currNodePtr->name == nullptr || currNodePtr->type == XML_COMMENT_NODE) {
189             continue;
190         }
191         auto contentPtr = xmlNodeGetContent(currNodePtr);
192         if (contentPtr == nullptr) {
193             continue;
194         }
195         string nodeName(reinterpret_cast<const char*>(currNodePtr->name));
196         string nodeContent(reinterpret_cast<char*>(contentPtr));
197         ParseSAProp(nodeName, nodeContent, saProfile);
198         xmlFree(contentPtr);
199     }
200     saProfiles_.emplace_back(saProfile);
201     return true;
202 }
203 
ParseProcess(const xmlNodePtr & rootNode,std::u16string & processName)204 bool ParseUtil::ParseProcess(const xmlNodePtr& rootNode, std::u16string& processName)
205 {
206     if (rootNode->name == nullptr || rootNode->type == XML_COMMENT_NODE) {
207         return false;
208     }
209     auto contentPtr = xmlNodeGetContent(rootNode);
210     if (contentPtr == nullptr) {
211         return false;
212     }
213     string nodeContent(reinterpret_cast<char*>(contentPtr));
214     processName = Str8ToStr16(nodeContent);
215     xmlFree(contentPtr);
216     return true;
217 }
218 
ParseSaProfiles(const string & profilePath)219 bool ParseUtil::ParseSaProfiles(const string& profilePath)
220 {
221     HILOGI("xmlFile:%{private}s", profilePath.c_str());
222     std::string realPath = GetRealPath(profilePath);
223     if (!CheckPathExist(realPath.c_str())) {
224         HILOGE("bad profile path!");
225         return false;
226     }
227     std::unique_ptr<xmlDoc, decltype(&xmlFreeDoc)> ptrDoc(
228         xmlReadFile(realPath.c_str(), nullptr, XML_PARSE_NOBLANKS), xmlFreeDoc);
229 
230     if (ptrDoc == nullptr) {
231         HILOGE("xmlReadFile error!");
232         return false;
233     }
234     xmlNodePtr rootNodePtr = xmlDocGetRootElement(ptrDoc.get());
235     if (!CheckRootTag(rootNodePtr)) {
236         HILOGW("wrong root element tag!");
237         return false;
238     }
239     bool isParseCorrect = false;
240     xmlNodePtr currNodePtr = rootNodePtr->xmlChildrenNode;
241     std::u16string process = u"";
242     for (; currNodePtr != nullptr; currNodePtr = currNodePtr->next) {
243         if (currNodePtr->name == nullptr || currNodePtr->type == XML_COMMENT_NODE) {
244             continue;
245         }
246 
247         string nodeName(reinterpret_cast<const char*>(currNodePtr->name));
248         HILOGI("profile nodeName:%{public}s", nodeName.c_str());
249         if (nodeName == XML_TAG_PROCESS && process.empty()) {
250             if (!ParseProcess(currNodePtr, process)) {
251                 HILOGW("profile %{public}s wrong tag!", currNodePtr->name);
252                 return false;
253             }
254         }
255         if (nodeName == XML_TAG_SYSTEM_ABILITY) {
256             if (!ParseSystemAbility(*currNodePtr, process)) {
257                 HILOGW("profile %{public}s wrong tag!", currNodePtr->name);
258                 return false;
259             }
260             isParseCorrect = true;
261         }
262     }
263     procName_ = process;
264     return isParseCorrect;
265 }
266 
GetProcessName() const267 std::u16string ParseUtil::GetProcessName() const
268 {
269     return procName_;
270 }
271 
GetRealPath(const string & profilePath) const272 std::string ParseUtil::GetRealPath(const string& profilePath) const
273 {
274     char path[PATH_MAX] = {'\0'};
275     if (realpath(profilePath.c_str(), path) == nullptr) {
276         HILOGE("get real path fail");
277         return "";
278     }
279     std::string realPath(path);
280     return realPath;
281 }
282 
CheckPathExist(const string & profilePath)283 bool ParseUtil::CheckPathExist(const string& profilePath)
284 {
285     std::ifstream profileStream(profilePath.c_str());
286     return profileStream.good();
287 }
288 
ParseTrustConfig(const string & profilePath,std::map<std::u16string,std::set<int32_t>> & values)289 bool ParseUtil::ParseTrustConfig(const string& profilePath,
290     std::map<std::u16string, std::set<int32_t>>& values)
291 {
292     HILOGI("config path:%{private}s", profilePath.c_str());
293     std::string realPath = GetRealPath(profilePath);
294     if (!CheckPathExist(realPath.c_str())) {
295         HILOGE("bad profile path!");
296         return false;
297     }
298     std::unique_ptr<xmlDoc, decltype(&xmlFreeDoc)> docPtr(
299         xmlReadFile(realPath.c_str(), nullptr, XML_PARSE_NOBLANKS), xmlFreeDoc);
300     if (docPtr == nullptr) {
301         HILOGE("ParseTrustConfig xmlReadFile error!");
302         return false;
303     }
304     xmlNodePtr rootNodePtr = xmlDocGetRootElement(docPtr.get());
305     if (!CheckRootTag(rootNodePtr)) {
306         HILOGW("ParseTrustConfig wrong root element tag!");
307         return false;
308     }
309 
310     return ParseTrustConfigInner(rootNodePtr, values);
311 }
312 
CheckRootTag(const xmlNodePtr & rootNodePtr)313 bool ParseUtil::CheckRootTag(const xmlNodePtr& rootNodePtr)
314 {
315     if (rootNodePtr == nullptr || rootNodePtr->name == nullptr ||
316         (xmlStrcmp(rootNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_PROFILE)) != 0 &&
317         xmlStrcmp(rootNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_INFO)) != 0)) {
318         return false;
319     }
320     return true;
321 }
322 
ParseTrustConfigInner(const xmlNodePtr & rootNodePtr,std::map<std::u16string,std::set<int32_t>> & values)323 bool ParseUtil::ParseTrustConfigInner(const xmlNodePtr& rootNodePtr,
324     std::map<std::u16string, std::set<int32_t>>& values)
325 {
326     xmlNodePtr currNodePtr = rootNodePtr->xmlChildrenNode;
327     if (currNodePtr == nullptr) {
328         return false;
329     }
330     std::u16string processName = u"";
331     for (; currNodePtr != nullptr; currNodePtr = currNodePtr->next) {
332         if (currNodePtr->name == nullptr || currNodePtr->type == XML_COMMENT_NODE) {
333             continue;
334         }
335 
336         string nodeName(reinterpret_cast<const char*>(currNodePtr->name));
337         HILOGI("profile nodeName:%{public}s", nodeName.c_str());
338 
339         if (nodeName == XML_TAG_NAME && processName.empty()) {
340             // parse process name
341             if (!ParseProcess(currNodePtr, processName)) {
342                 HILOGE("ParseTrustConfigInner wrong name tag!");
343                 return false;
344             }
345         } else if (nodeName == XML_TAG_SAID) {
346             // parse said
347             int32_t saId = -1;
348             if (!ParseSaId(currNodePtr, saId)) {
349                 HILOGE("ParseTrustConfigInner wrong said tag!");
350                 continue;
351             }
352             auto& saIds = values[processName];
353             saIds.emplace(saId);
354         }
355     }
356     return true;
357 }
358 
ParseSaId(const xmlNodePtr & rootNode,int32_t & saId)359 bool ParseUtil::ParseSaId(const xmlNodePtr& rootNode, int32_t& saId)
360 {
361     if (rootNode->name == nullptr || rootNode->type == XML_COMMENT_NODE) {
362         return false;
363     }
364     auto contentPtr = xmlNodeGetContent(rootNode);
365     if (contentPtr == nullptr) {
366         return false;
367     }
368     string nodeContent(reinterpret_cast<char*>(contentPtr));
369     bool ret = StrToInt(nodeContent.c_str(), saId);
370     xmlFree(contentPtr);
371     return ret;
372 }
373 } // namespace OHOS
374