1 /*
2 * Copyright (c) 2021-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 "bundle_exception_handler.h"
17
18 #include <dirent.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21
22 #include "bundle_constants.h"
23 #include "bundle_permission_mgr.h"
24 #include "installd_client.h"
25
26 namespace OHOS {
27 namespace AppExecFwk {
BundleExceptionHandler(const std::shared_ptr<IBundleDataStorage> & dataStorage)28 BundleExceptionHandler::BundleExceptionHandler(const std::shared_ptr<IBundleDataStorage> &dataStorage)
29 : dataStorage_(dataStorage)
30 {
31 APP_LOGD("create bundle excepetion handler instance");
32 }
33
~BundleExceptionHandler()34 BundleExceptionHandler::~BundleExceptionHandler()
35 {
36 APP_LOGD("destroy bundle excepetion handler instance");
37 }
38
39
HandleInvalidBundle(InnerBundleInfo & info,bool & isBundleValid)40 void BundleExceptionHandler::HandleInvalidBundle(InnerBundleInfo &info, bool &isBundleValid)
41 {
42 auto mark = info.GetInstallMark();
43 if (mark.status == InstallExceptionStatus::INSTALL_FINISH) {
44 APP_LOGD("bundle %{public}s is under correct installation status", info.GetBundleName().c_str());
45 return;
46 }
47
48 std::string appCodePath = Constants::BUNDLE_CODE_DIR + info.GetBundleName();
49 auto moduleDir = appCodePath + Constants::PATH_SEPARATOR + mark.packageName;
50 auto moduleDataDir = info.GetBundleName() + Constants::HAPS + mark.packageName;
51
52 // install and update failed before service restart
53 if (mark.status == InstallExceptionStatus::INSTALL_START &&
54 RemoveBundleAndDataDir(appCodePath, info.GetBundleName(), info.GetUserId())) {
55 DeleteBundleInfoFromStorage(info);
56 isBundleValid = false;
57 } else if (mark.status == InstallExceptionStatus::UPDATING_EXISTED_START) {
58 if (InstalldClient::GetInstance()->RemoveDir(moduleDir + Constants::TMP_SUFFIX) == ERR_OK) {
59 info.SetInstallMark(mark.bundleName, mark.packageName, InstallExceptionStatus::INSTALL_FINISH);
60 info.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
61 }
62 } else if (mark.status == InstallExceptionStatus::UPDATING_NEW_START &&
63 RemoveBundleAndDataDir(moduleDir, moduleDataDir, info.GetUserId())) {
64 info.SetInstallMark(mark.bundleName, mark.packageName, InstallExceptionStatus::INSTALL_FINISH);
65 info.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
66 } else if (mark.status == InstallExceptionStatus::UNINSTALL_BUNDLE_START &&
67 RemoveBundleAndDataDir(appCodePath, info.GetBundleName(), info.GetUserId())) { // continue to uninstall
68 DeleteBundleInfoFromStorage(info);
69 isBundleValid = false;
70 } else if (mark.status == InstallExceptionStatus::UNINSTALL_PACKAGE_START) {
71 if (info.IsOnlyModule(mark.packageName) &&
72 RemoveBundleAndDataDir(appCodePath, info.GetBundleName(), info.GetUserId())) {
73 DeleteBundleInfoFromStorage(info);
74 isBundleValid = false;
75 return;
76 }
77 if (RemoveBundleAndDataDir(moduleDir, moduleDataDir, info.GetUserId())) {
78 info.RemoveModuleInfo(mark.packageName);
79 info.SetInstallMark(mark.bundleName, mark.packageName, InstallExceptionStatus::INSTALL_FINISH);
80 info.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
81 }
82 } else if (mark.status == InstallExceptionStatus::UPDATING_FINISH) {
83 if (InstalldClient::GetInstance()->RenameModuleDir(moduleDir + Constants::TMP_SUFFIX, moduleDir) == ERR_OK) {
84 info.SetInstallMark(mark.bundleName, mark.packageName, InstallExceptionStatus::INSTALL_FINISH);
85 }
86 } else {
87 APP_LOGD("bundle %{public}s is under unknown installation status", info.GetBundleName().c_str());
88 }
89 }
90
RemoveBundleAndDataDir(const std::string & bundleDir,const std::string & bundleOrMoudleDir,int32_t userId) const91 bool BundleExceptionHandler::RemoveBundleAndDataDir(const std::string &bundleDir,
92 const std::string &bundleOrMoudleDir, int32_t userId) const
93 {
94 ErrCode result = InstalldClient::GetInstance()->RemoveDir(bundleDir);
95 if (result != ERR_OK) {
96 APP_LOGE("fail to remove bundle dir %{public}s, error is %{public}d", bundleDir.c_str(), result);
97 return false;
98 }
99
100 if (bundleOrMoudleDir.find(Constants::HAPS) != std::string::npos) {
101 result = InstalldClient::GetInstance()->RemoveModuleDataDir(bundleOrMoudleDir, userId);
102 if (result != ERR_OK) {
103 APP_LOGE("fail to remove module data dir %{public}s, error is %{public}d", bundleOrMoudleDir.c_str(),
104 result);
105 return false;
106 }
107 } else {
108 result = InstalldClient::GetInstance()->RemoveBundleDataDir(bundleOrMoudleDir, userId);
109 if (result != ERR_OK) {
110 APP_LOGE("fail to remove bundle data dir %{public}s, error is %{public}d", bundleOrMoudleDir.c_str(),
111 result);
112 return false;
113 }
114 }
115 return true;
116 }
117
DeleteBundleInfoFromStorage(const InnerBundleInfo & info)118 void BundleExceptionHandler::DeleteBundleInfoFromStorage(const InnerBundleInfo &info)
119 {
120 auto storage = dataStorage_.lock();
121 if (storage) {
122 APP_LOGD("remove bundle info of %{public}s from the storage", info.GetBundleName().c_str());
123 storage->DeleteStorageBundleInfo(info);
124 } else {
125 APP_LOGE(" fail to remove bundle info of %{public}s from the storage", info.GetBundleName().c_str());
126 }
127 }
128 } // namespace AppExecFwkConstants
129 } // namespace OHOS