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 "inner_shared_bundle_installer.h"
17
18 #include "app_log_wrapper.h"
19 #include "app_provision_info_manager.h"
20 #include "bundle_mgr_service.h"
21 #include "bundle_util.h"
22 #include "installd_client.h"
23 #include "shared/base_shared_bundle_info.h"
24
25 namespace OHOS {
26 namespace AppExecFwk {
27 using namespace OHOS::Security;
28 namespace {
29 const std::string HSP_VERSION_PREFIX = "v";
30 const int32_t MAX_FILE_NUMBER = 2;
31 }
32
InnerSharedBundleInstaller(const std::string & path)33 InnerSharedBundleInstaller::InnerSharedBundleInstaller(const std::string &path)
34 : sharedBundlePath_(path), bundleInstallChecker_(std::make_unique<BundleInstallChecker>())
35 {
36 APP_LOGI("inner shared bundle installer instance is created");
37 }
38
~InnerSharedBundleInstaller()39 InnerSharedBundleInstaller::~InnerSharedBundleInstaller()
40 {
41 APP_LOGI("inner shared bundle installer instance is destroyed");
42 BundleUtil::DeleteTempDirs(toDeleteTempHspPath_);
43 }
44
ParseFiles(const InstallCheckParam & checkParam)45 ErrCode InnerSharedBundleInstaller::ParseFiles(const InstallCheckParam &checkParam)
46 {
47 APP_LOGD("parsing shared bundle files, path : %{private}s", sharedBundlePath_.c_str());
48 ErrCode result = ERR_OK;
49
50 // check file paths
51 std::vector<std::string> inBundlePaths;
52 result = BundleUtil::CheckFilePath({sharedBundlePath_}, inBundlePaths);
53 CHECK_RESULT(result, "hsp files check failed %{public}d");
54
55 if (!checkParam.isPreInstallApp) {
56 // copy the haps to the dir which cannot be accessed from caller
57 result = CopyHspToSecurityDir(inBundlePaths);
58 CHECK_RESULT(result, "copy file failed %{public}d");
59 }
60
61 // check number and type of the hsp and sig files
62 std::vector<std::string> bundlePaths;
63 result = ObtainHspFileAndSignatureFilePath(inBundlePaths, bundlePaths, signatureFileDir_);
64 CHECK_RESULT(result, "obtain hsp file path or signature file path failed due to %{public}d");
65
66 // check syscap
67 result = bundleInstallChecker_->CheckSysCap(bundlePaths);
68 CHECK_RESULT(result, "hap syscap check failed %{public}d");
69
70 // verify signature info for all haps
71 std::vector<Security::Verify::HapVerifyResult> hapVerifyResults;
72 result = bundleInstallChecker_->CheckMultipleHapsSignInfo(bundlePaths, hapVerifyResults);
73 CHECK_RESULT(result, "hap files check signature info failed %{public}d");
74
75 // parse bundle infos
76 result = bundleInstallChecker_->ParseHapFiles(bundlePaths, checkParam, hapVerifyResults, parsedBundles_);
77 CHECK_RESULT(result, "parse haps file failed %{public}d");
78
79 // check device type
80 result = bundleInstallChecker_->CheckDeviceType(parsedBundles_);
81 CHECK_RESULT(result, "check device type failed %{public}d");
82
83 // check label info
84 result = CheckAppLabelInfo();
85 CHECK_RESULT(result, "check label info failed %{public}d");
86
87 // check native file
88 result = bundleInstallChecker_->CheckMultiNativeFile(parsedBundles_);
89 CHECK_RESULT(result, "native so is incompatible in all haps %{public}d");
90
91 AddAppProvisionInfo(bundleName_, hapVerifyResults[0].GetProvisionInfo());
92 return result;
93 }
94
Install(const InstallParam & installParam)95 ErrCode InnerSharedBundleInstaller::Install(const InstallParam &installParam)
96 {
97 if (parsedBundles_.empty()) {
98 APP_LOGD("no bundle to install");
99 return ERR_OK;
100 }
101
102 ErrCode result = ERR_OK;
103 for (auto &item : parsedBundles_) {
104 result = ExtractSharedBundles(item.first, item.second);
105 CHECK_RESULT(result, "extract shared bundles failed %{public}d");
106 }
107
108 MergeBundleInfos();
109
110 result = SavePreInstallInfo(installParam);
111 CHECK_RESULT(result, "save pre install info failed %{public}d");
112
113 result = SaveBundleInfoToStorage();
114 CHECK_RESULT(result, "save bundle info to storage failed %{public}d");
115
116 // save specifiedDistributionType and additionalInfo
117 SaveInstallParamInfo(bundleName_, installParam);
118
119 APP_LOGD("install shared bundle successfully: %{public}s", bundleName_.c_str());
120 return result;
121 }
122
RollBack()123 void InnerSharedBundleInstaller::RollBack()
124 {
125 // delete created directories
126 for (auto iter = createdDirs_.crbegin(); iter != createdDirs_.crend(); ++iter) {
127 ErrCode err = InstalldClient::GetInstance()->RemoveDir(*iter);
128 if (err != ERR_OK) {
129 APP_LOGE("clean dir of %{public}s failed: %{public}s", bundleName_.c_str(), iter->c_str());
130 }
131 }
132
133 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
134 if (dataMgr == nullptr) {
135 APP_LOGE("get dataMgr failed");
136 return;
137 }
138
139 // rollback database
140 if (!isBundleExist_) {
141 if (dataMgr->DeleteSharedBundleInfo(bundleName_)) {
142 APP_LOGE("rollback new bundle failed : %{public}s", bundleName_.c_str());
143 }
144 if (!DelayedSingleton<AppProvisionInfoManager>::GetInstance()->DeleteAppProvisionInfo(bundleName_)) {
145 APP_LOGE("bundleName: %{public}s delete appProvisionInfo failed.", bundleName_.c_str());
146 }
147 return;
148 }
149
150 if (dataMgr->UpdateInnerBundleInfo(oldBundleInfo_)) {
151 APP_LOGE("rollback old bundle failed : %{public}s", bundleName_.c_str());
152 }
153 }
154
CheckDependency(const Dependency & dependency) const155 bool InnerSharedBundleInstaller::CheckDependency(const Dependency &dependency) const
156 {
157 if (dependency.bundleName != bundleName_) {
158 APP_LOGE("bundle name not match : %{public}s, %{public}s", bundleName_.c_str(), dependency.bundleName.c_str());
159 return false;
160 }
161
162 for (const auto &item : parsedBundles_) {
163 const auto bundleInfo = item.second;
164 BaseSharedBundleInfo sharedBundle;
165 bool isModuleExist = bundleInfo.GetMaxVerBaseSharedBundleInfo(dependency.moduleName, sharedBundle);
166 if (isModuleExist && dependency.versionCode <= sharedBundle.versionCode) {
167 return true;
168 }
169 }
170
171 APP_LOGE("dependency not match");
172 return false;
173 }
174
SendBundleSystemEvent(const EventInfo & eventTemplate) const175 void InnerSharedBundleInstaller::SendBundleSystemEvent(const EventInfo &eventTemplate) const
176 {
177 EventInfo eventInfo = eventTemplate;
178 eventInfo.bundleName = bundleName_;
179 eventInfo.versionCode = newBundleInfo_.GetBaseBundleInfo().versionCode;
180 GetInstallEventInfo(eventInfo);
181
182 BundleEventType eventType = isBundleExist_ ? BundleEventType::UPDATE : BundleEventType::INSTALL;
183 EventReport::SendBundleSystemEvent(eventType, eventInfo);
184 }
185
CheckAppLabelInfo()186 ErrCode InnerSharedBundleInstaller::CheckAppLabelInfo()
187 {
188 if (parsedBundles_.empty()) {
189 return ERR_OK;
190 }
191 bundleName_ = parsedBundles_.begin()->second.GetBundleName();
192
193 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
194 if (dataMgr == nullptr) {
195 APP_LOGE("Get dataMgr shared_ptr nullptr");
196 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
197 }
198
199 isBundleExist_ = dataMgr->FetchInnerBundleInfo(bundleName_, oldBundleInfo_);
200 if (isBundleExist_) {
201 ErrCode ret = CheckBundleTypeWithInstalledVersion();
202 CHECK_RESULT(ret, "check bundle type with installed version failed %{public}d");
203
204 // check old InnerBundleInfo together
205 parsedBundles_.emplace(bundleName_, oldBundleInfo_);
206 } else {
207 if (parsedBundles_.begin()->second.GetApplicationBundleType() != BundleType::SHARED) {
208 APP_LOGE("installing bundle is not hsp");
209 return ERR_APPEXECFWK_INSTALL_PARAM_ERROR;
210 }
211 }
212
213 ErrCode result = bundleInstallChecker_->CheckAppLabelInfo(parsedBundles_);
214 if (isBundleExist_) {
215 parsedBundles_.erase(bundleName_);
216 }
217 return result;
218 }
219
CheckBundleTypeWithInstalledVersion()220 ErrCode InnerSharedBundleInstaller::CheckBundleTypeWithInstalledVersion()
221 {
222 if (oldBundleInfo_.GetApplicationBundleType() != BundleType::SHARED) {
223 APP_LOGE("old bundle is not shared");
224 return ERR_APPEXECFWK_INSTALL_COMPATIBLE_POLICY_NOT_SAME;
225 }
226
227 for (const auto &item : parsedBundles_) {
228 auto& sharedModules = item.second.GetInnerSharedModuleInfos();
229 if (sharedModules.empty() || sharedModules.begin()->second.empty()) {
230 APP_LOGW("inner shared module infos not found (%{public}s)", item.second.GetBundleName().c_str());
231 continue;
232 }
233
234 auto& sharedModule = sharedModules.begin()->second.front();
235 BaseSharedBundleInfo installedSharedModule;
236 if (oldBundleInfo_.GetMaxVerBaseSharedBundleInfo(sharedModule.moduleName, installedSharedModule) &&
237 installedSharedModule.versionCode > sharedModule.versionCode) {
238 APP_LOGE("installing lower version shared package");
239 return ERR_APPEXECFWK_INSTALL_VERSION_DOWNGRADE;
240 }
241 }
242 return ERR_OK;
243 }
244
MkdirIfNotExist(const std::string & dir)245 ErrCode InnerSharedBundleInstaller::MkdirIfNotExist(const std::string &dir)
246 {
247 bool isDirExist = false;
248 ErrCode result = InstalldClient::GetInstance()->IsExistDir(dir, isDirExist);
249 CHECK_RESULT(result, "check if dir exist failed %{public}d");
250 if (!isDirExist) {
251 result = InstalldClient::GetInstance()->CreateBundleDir(dir);
252 CHECK_RESULT(result, "create dir failed %{public}d");
253 createdDirs_.emplace_back(dir);
254 }
255 return result;
256 }
257
ExtractSharedBundles(const std::string & bundlePath,InnerBundleInfo & newInfo)258 ErrCode InnerSharedBundleInstaller::ExtractSharedBundles(const std::string &bundlePath, InnerBundleInfo &newInfo)
259 {
260 ErrCode result = ERR_OK;
261 std::string bundleDir = Constants::BUNDLE_CODE_DIR + Constants::PATH_SEPARATOR + bundleName_;
262 result = MkdirIfNotExist(bundleDir);
263 CHECK_RESULT(result, "check bundle dir failed %{public}d");
264 newInfo.SetAppCodePath(bundleDir);
265
266 uint32_t versionCode = newInfo.GetVersionCode();
267 std::string versionDir = bundleDir + Constants::PATH_SEPARATOR + HSP_VERSION_PREFIX + std::to_string(versionCode);
268 result = MkdirIfNotExist(versionDir);
269 CHECK_RESULT(result, "check version dir failed %{public}d");
270
271 auto &moduleName = newInfo.GetInnerModuleInfos().begin()->second.moduleName;
272 std::string moduleDir = versionDir + Constants::PATH_SEPARATOR + moduleName;
273 result = MkdirIfNotExist(moduleDir);
274 CHECK_RESULT(result, "check module dir failed %{public}d");
275
276 result = ProcessNativeLibrary(bundlePath, moduleDir, moduleName, versionDir, newInfo);
277 CHECK_RESULT(result, "ProcessNativeLibrary failed %{public}d");
278
279 if (newInfo.IsPreInstallApp()) {
280 // preInstallApp does not need to copy hsp
281 newInfo.SetModuleHapPath(bundlePath);
282 } else {
283 // save hsp and so files to installation dir
284 std::string realHspPath = moduleDir + Constants::PATH_SEPARATOR + moduleName +
285 Constants::INSTALL_SHARED_FILE_SUFFIX;
286 result = SaveHspToRealInstallationDir(bundlePath, moduleDir, moduleName, realHspPath);
287 CHECK_RESULT(result, "save hsp file failed %{public}d");
288 newInfo.SetModuleHapPath(realHspPath);
289 }
290 newInfo.AddModuleSrcDir(moduleDir);
291 newInfo.AddModuleResPath(moduleDir);
292 newInfo.UpdateSharedModuleInfo();
293 return ERR_OK;
294 }
295
MergeBundleInfos()296 void InnerSharedBundleInstaller::MergeBundleInfos()
297 {
298 auto iter = parsedBundles_.begin();
299 if (isBundleExist_) {
300 newBundleInfo_ = oldBundleInfo_;
301 } else {
302 newBundleInfo_ = iter->second;
303 ++iter;
304 }
305
306 for (; iter != parsedBundles_.end(); ++iter) {
307 const auto ¤tBundle = iter->second;
308 const auto& infos = currentBundle.GetInnerSharedModuleInfos();
309 if (infos.empty()) {
310 continue;
311 }
312
313 const auto& innerModuleInfos = infos.begin()->second;
314 if (!innerModuleInfos.empty()) {
315 const auto& innerModuleInfo = innerModuleInfos.front();
316 newBundleInfo_.InsertInnerSharedModuleInfo(innerModuleInfo.modulePackage, innerModuleInfo);
317 }
318 // update version
319 if (newBundleInfo_.GetBaseBundleInfo().versionCode < currentBundle.GetBaseBundleInfo().versionCode) {
320 newBundleInfo_.UpdateBaseBundleInfo(currentBundle.GetBaseBundleInfo(), false);
321 newBundleInfo_.UpdateBaseApplicationInfo(currentBundle.GetBaseApplicationInfo(), false);
322 }
323 }
324
325 newBundleInfo_.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
326 newBundleInfo_.SetHideDesktopIcon(true);
327 }
328
SavePreInstallInfo(const InstallParam & installParam)329 ErrCode InnerSharedBundleInstaller::SavePreInstallInfo(const InstallParam &installParam)
330 {
331 if (!installParam.needSavePreInstallInfo) {
332 APP_LOGD("no need to save pre install info");
333 return ERR_OK;
334 }
335
336 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
337 if (dataMgr == nullptr) {
338 APP_LOGE("get dataMgr failed");
339 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
340 }
341
342 PreInstallBundleInfo preInstallBundleInfo;
343 dataMgr->GetPreInstallBundleInfo(bundleName_, preInstallBundleInfo);
344 preInstallBundleInfo.SetVersionCode(newBundleInfo_.GetBaseBundleInfo().versionCode);
345 for (const auto &item : parsedBundles_) {
346 preInstallBundleInfo.AddBundlePath(item.first);
347 }
348 #ifdef USE_PRE_BUNDLE_PROFILE
349 preInstallBundleInfo.SetRemovable(installParam.removable);
350 #else
351 preInstallBundleInfo.SetRemovable(newBundleInfo_.IsRemovable());
352 #endif
353 dataMgr->SavePreInstallBundleInfo(bundleName_, preInstallBundleInfo);
354
355 return ERR_OK;
356 }
357
SaveBundleInfoToStorage()358 ErrCode InnerSharedBundleInstaller::SaveBundleInfoToStorage()
359 {
360 // update install mark
361 std::string packageName;
362 newBundleInfo_.SetInstallMark(bundleName_, packageName, InstallExceptionStatus::INSTALL_FINISH);
363
364 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
365 if (dataMgr == nullptr) {
366 APP_LOGE("get dataMgr failed");
367 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
368 }
369
370 if (isBundleExist_) {
371 if (!dataMgr->UpdateInnerBundleInfo(newBundleInfo_)) {
372 APP_LOGE("save bundle failed : %{public}s", bundleName_.c_str());
373 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
374 }
375 return ERR_OK;
376 }
377
378 dataMgr->UpdateBundleInstallState(bundleName_, InstallState::INSTALL_START);
379 if (!dataMgr->AddInnerBundleInfo(bundleName_, newBundleInfo_)) {
380 dataMgr->UpdateBundleInstallState(bundleName_, InstallState::INSTALL_FAIL);
381 APP_LOGE("save bundle failed : %{public}s", bundleName_.c_str());
382 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
383 }
384 dataMgr->UpdateBundleInstallState(bundleName_, InstallState::INSTALL_SUCCESS);
385 return ERR_OK;
386 }
387
GetInstallEventInfo(EventInfo & eventInfo) const388 void InnerSharedBundleInstaller::GetInstallEventInfo(EventInfo &eventInfo) const
389 {
390 APP_LOGD("GetInstallEventInfo start, bundleName:%{public}s", bundleName_.c_str());
391 eventInfo.fingerprint = newBundleInfo_.GetCertificateFingerprint();
392 eventInfo.appDistributionType = newBundleInfo_.GetAppDistributionType();
393 eventInfo.hideDesktopIcon = newBundleInfo_.IsHideDesktopIcon();
394 eventInfo.timeStamp = BundleUtil::GetCurrentTimeMs();
395
396 // report hapPath and hashValue
397 for (const auto &info : parsedBundles_) {
398 for (const auto &innerModuleInfo : info.second.GetInnerModuleInfos()) {
399 eventInfo.filePath.push_back(innerModuleInfo.second.hapPath);
400 eventInfo.hashValue.push_back(innerModuleInfo.second.hashValue);
401 }
402 }
403 }
404
AddAppProvisionInfo(const std::string & bundleName,const Security::Verify::ProvisionInfo & provisionInfo) const405 void InnerSharedBundleInstaller::AddAppProvisionInfo(const std::string &bundleName,
406 const Security::Verify::ProvisionInfo &provisionInfo) const
407 {
408 AppProvisionInfo appProvisionInfo = bundleInstallChecker_->ConvertToAppProvisionInfo(provisionInfo);
409 if (!DelayedSingleton<AppProvisionInfoManager>::GetInstance()->AddAppProvisionInfo(
410 bundleName, appProvisionInfo)) {
411 APP_LOGW("bundleName: %{public}s add appProvisionInfo failed.", bundleName.c_str());
412 }
413 }
414
SaveInstallParamInfo(const std::string & bundleName,const InstallParam & installParam) const415 void InnerSharedBundleInstaller::SaveInstallParamInfo(
416 const std::string &bundleName, const InstallParam &installParam) const
417 {
418 if (!installParam.specifiedDistributionType.empty()) {
419 if (!DelayedSingleton<AppProvisionInfoManager>::GetInstance()->SetSpecifiedDistributionType(
420 bundleName, installParam.specifiedDistributionType)) {
421 APP_LOGW("bundleName: %{public}s SetSpecifiedDistributionType failed.", bundleName.c_str());
422 }
423 }
424 if (!installParam.additionalInfo.empty()) {
425 if (!DelayedSingleton<AppProvisionInfoManager>::GetInstance()->SetAdditionalInfo(
426 bundleName, installParam.additionalInfo)) {
427 APP_LOGW("bundleName: %{public}s SetAdditionalInfo failed.", bundleName.c_str());
428 }
429 }
430 }
431
CopyHspToSecurityDir(std::vector<std::string> & bundlePaths)432 ErrCode InnerSharedBundleInstaller::CopyHspToSecurityDir(std::vector<std::string> &bundlePaths)
433 {
434 for (size_t index = 0; index < bundlePaths.size(); ++index) {
435 auto destination = BundleUtil::CopyFileToSecurityDir(bundlePaths[index], DirType::STREAM_INSTALL_DIR,
436 toDeleteTempHspPath_);
437 if (destination.empty()) {
438 APP_LOGE("copy file %{public}s to security dir failed", bundlePaths[index].c_str());
439 return ERR_APPEXECFWK_INSTALL_COPY_HAP_FAILED;
440 }
441 bundlePaths[index] = destination;
442 }
443 return ERR_OK;
444 }
445
ObtainHspFileAndSignatureFilePath(const std::vector<std::string> & inBundlePaths,std::vector<std::string> & bundlePaths,std::string & signatureFilePath)446 ErrCode InnerSharedBundleInstaller::ObtainHspFileAndSignatureFilePath(const std::vector<std::string> &inBundlePaths,
447 std::vector<std::string> &bundlePaths, std::string &signatureFilePath)
448 {
449 if (inBundlePaths.empty() || inBundlePaths.size() > MAX_FILE_NUMBER) {
450 APP_LOGE("number of files in single shared lib path is illegal");
451 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
452 }
453 if (inBundlePaths.size() == 1) {
454 if (!BundleUtil::EndWith(inBundlePaths[0], Constants::INSTALL_SHARED_FILE_SUFFIX)) {
455 APP_LOGE("invalid file in shared bundle dir");
456 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
457 }
458 bundlePaths.emplace_back(inBundlePaths[0]);
459 return ERR_OK;
460 }
461 int32_t numberOfHsp = 0;
462 int32_t numberOfSignatureFile = 0;
463 for (const auto &path : inBundlePaths) {
464 if ((path.find(Constants::INSTALL_SHARED_FILE_SUFFIX) == std::string::npos) &&
465 (path.find(Constants::CODE_SIGNATURE_FILE_SUFFIX) == std::string::npos)) {
466 APP_LOGE("only hsp or sig file can be contained in shared bundle dir");
467 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
468 }
469 if (BundleUtil::EndWith(path, Constants::INSTALL_SHARED_FILE_SUFFIX)) {
470 numberOfHsp++;
471 bundlePaths.emplace_back(path);
472 }
473 if (BundleUtil::EndWith(path, Constants::CODE_SIGNATURE_FILE_SUFFIX)) {
474 numberOfSignatureFile++;
475 signatureFilePath = path;
476 }
477 if ((numberOfHsp >= MAX_FILE_NUMBER) || (numberOfSignatureFile >= MAX_FILE_NUMBER)) {
478 APP_LOGE("only one hsp and one signature file can be contained in a single shared bundle dir");
479 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
480 }
481 }
482 APP_LOGD("signatureFilePath is %{public}s", signatureFilePath.c_str());
483 return ERR_OK;
484 }
485
SaveHspToRealInstallationDir(const std::string & bundlePath,const std::string & moduleDir,const std::string & moduleName,const std::string & realHspPath)486 ErrCode InnerSharedBundleInstaller::SaveHspToRealInstallationDir(const std::string &bundlePath,
487 const std::string &moduleDir,
488 const std::string &moduleName,
489 const std::string &realHspPath)
490 {
491 // 1. create temp dir
492 ErrCode result = ERR_OK;
493 std::string tempHspDir = moduleDir + Constants::PATH_SEPARATOR + moduleName;
494 result = MkdirIfNotExist(tempHspDir);
495 CHECK_RESULT(result, "create tempHspDir dir failed %{public}d");
496
497 // 2. copy hsp to installation dir, and then to verify code signature of hsp
498 std::string tempHspPath = tempHspDir + Constants::PATH_SEPARATOR + moduleName +
499 Constants::INSTALL_SHARED_FILE_SUFFIX;
500 result = InstalldClient::GetInstance()->CopyFile(bundlePath, tempHspPath, signatureFileDir_);
501 CHECK_RESULT(result, "copy hsp to install dir failed %{public}d");
502
503 // 3. move hsp to real installation dir
504 APP_LOGD("move file from temp path %{public}s to real path %{public}s", tempHspPath.c_str(), realHspPath.c_str());
505 result = InstalldClient::GetInstance()->MoveFile(tempHspPath, realHspPath);
506 CHECK_RESULT(result, "move hsp to install dir failed %{public}d");
507
508 // 4. remove temp dir
509 result = InstalldClient::GetInstance()->RemoveDir(tempHspDir);
510 if (result != ERR_OK) {
511 APP_LOGW("remove temp hsp dir %{public}s failed, error is %{public}d", tempHspDir.c_str(), result);
512 }
513 return ERR_OK;
514 }
515
MoveSoToRealPath(const std::string & moduleName,const std::string & versionDir)516 ErrCode InnerSharedBundleInstaller::MoveSoToRealPath(const std::string &moduleName, const std::string &versionDir)
517 {
518 // 1. move so files to real installation dir
519 std::string realSoPath = versionDir + Constants::PATH_SEPARATOR + nativeLibraryPath_ +
520 Constants::PATH_SEPARATOR;
521 ErrCode result = MkdirIfNotExist(realSoPath);
522 CHECK_RESULT(result, "check module dir failed %{public}d");
523
524 std::string tempNativeLibraryPath = ObtainTempSoPath(moduleName, nativeLibraryPath_);
525 if (tempNativeLibraryPath.empty()) {
526 APP_LOGI("no so libs existed");
527 return ERR_OK;
528 }
529 std::string tempSoPath = versionDir + Constants::PATH_SEPARATOR + tempNativeLibraryPath;
530 APP_LOGD("move so files from path %{public}s to path %{public}s", tempSoPath.c_str(), realSoPath.c_str());
531 result = InstalldClient::GetInstance()->MoveFiles(tempSoPath, realSoPath);
532 if (result != ERR_OK) {
533 APP_LOGE("move file to real path failed %{public}d", result);
534 return ERR_APPEXECFWK_INSTALLD_MOVE_FILE_FAILED;
535 }
536
537 // 2. remove so temp dir
538 std::string deleteTempDir = versionDir + Constants::PATH_SEPARATOR + moduleName + Constants::TMP_SUFFIX;
539 result = InstalldClient::GetInstance()->RemoveDir(deleteTempDir);
540 if (result != ERR_OK) {
541 APP_LOGW("remove hsp temp so dir %{public}s failed, error is %{public}d", deleteTempDir.c_str(), result);
542 }
543 return ERR_OK;
544 }
545
ObtainTempSoPath(const std::string & moduleName,const std::string & nativeLibPath)546 std::string InnerSharedBundleInstaller::ObtainTempSoPath(const std::string &moduleName,
547 const std::string &nativeLibPath)
548 {
549 std::string tempSoPath;
550 if (nativeLibPath.empty()) {
551 APP_LOGE("invalid native libs path");
552 return tempSoPath;
553 }
554 tempSoPath = nativeLibPath;
555 auto pos = tempSoPath.find(moduleName);
556 if (pos == std::string::npos) {
557 tempSoPath = moduleName + Constants::TMP_SUFFIX + Constants::PATH_SEPARATOR + tempSoPath;
558 } else {
559 std::string innerTempStr = moduleName + Constants::TMP_SUFFIX;
560 tempSoPath.replace(pos, moduleName.length(), innerTempStr);
561 }
562 return tempSoPath + Constants::PATH_SEPARATOR;
563 }
564
ProcessNativeLibrary(const std::string & bundlePath,const std::string & moduleDir,const std::string & moduleName,const std::string & versionDir,InnerBundleInfo & newInfo)565 ErrCode InnerSharedBundleInstaller::ProcessNativeLibrary(
566 const std::string &bundlePath,
567 const std::string &moduleDir,
568 const std::string &moduleName,
569 const std::string &versionDir,
570 InnerBundleInfo &newInfo)
571 {
572 std::string cpuAbi;
573 if (!newInfo.FetchNativeSoAttrs(moduleName, cpuAbi, nativeLibraryPath_)) {
574 return ERR_OK;
575 }
576 if (newInfo.IsCompressNativeLibs(moduleName)) {
577 std::string tempNativeLibraryPath = ObtainTempSoPath(moduleName, nativeLibraryPath_);
578 if (tempNativeLibraryPath.empty()) {
579 return ERR_APPEXECFWK_INSTALLD_EXTRACT_FILES_FAILED;
580 }
581 std::string tempSoPath = versionDir + Constants::PATH_SEPARATOR + tempNativeLibraryPath;
582 APP_LOGD("tempSoPath=%{public}s,cpuAbi=%{public}s, bundlePath=%{public}s",
583 tempSoPath.c_str(), cpuAbi.c_str(), bundlePath.c_str());
584 auto result = InstalldClient::GetInstance()->ExtractModuleFiles(bundlePath, moduleDir, tempSoPath, cpuAbi);
585 CHECK_RESULT(result, "extract module files failed %{public}d");
586 // verify hap or hsp code signature for compressed so files
587 result = InstalldClient::GetInstance()->VerifyCodeSignature(bundlePath, cpuAbi, tempSoPath,
588 signatureFileDir_);
589 CHECK_RESULT(result, "fail to VerifyCodeSignature, error is %{public}d");
590 // move so to real path
591 result = MoveSoToRealPath(moduleName, versionDir);
592 CHECK_RESULT(result, "move so to real path failed %{public}d");
593 } else {
594 std::vector<std::string> fileNames;
595 auto result = InstalldClient::GetInstance()->GetNativeLibraryFileNames(bundlePath, cpuAbi, fileNames);
596 CHECK_RESULT(result, "fail to GetNativeLibraryFileNames, error is %{public}d");
597 newInfo.SetNativeLibraryFileNames(moduleName, fileNames);
598 }
599 return ERR_OK;
600 }
601 } // namespace AppExecFwk
602 } // namespace OHOS
603