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 "installd_client.h"
19
20 namespace OHOS {
21 namespace AppExecFwk {
BundleExceptionHandler(const std::shared_ptr<IBundleDataStorage> &dataStorage)22 BundleExceptionHandler::BundleExceptionHandler(const std::shared_ptr<IBundleDataStorage> &dataStorage)
23 : dataStorage_(dataStorage)
24 {
25 APP_LOGD("create bundle excepetion handler instance");
26 }
27
~BundleExceptionHandler()28 BundleExceptionHandler::~BundleExceptionHandler()
29 {
30 APP_LOGD("destroy bundle excepetion handler instance");
31 }
32
33
HandleInvalidBundle(InnerBundleInfo &info, bool &isBundleValid)34 void BundleExceptionHandler::HandleInvalidBundle(InnerBundleInfo &info, bool &isBundleValid)
35 {
36 std::string appCodePath = std::string(Constants::BUNDLE_CODE_DIR) +
37 ServiceConstants::PATH_SEPARATOR + info.GetBundleName();
38 if (!IsBundleHapPathExist(info)) {
39 RemoveBundleAndDataDir(appCodePath, info.GetBundleName(), info.GetUserId());
40 DeleteBundleInfoFromStorage(info);
41 isBundleValid = false;
42 return;
43 }
44 InnerHandleInvalidBundle(info, isBundleValid);
45 }
46
RemoveBundleAndDataDir(const std::string &bundleDir, const std::string &bundleOrMoudleDir, int32_t userId) const47 bool BundleExceptionHandler::RemoveBundleAndDataDir(const std::string &bundleDir,
48 const std::string &bundleOrMoudleDir, int32_t userId) const
49 {
50 ErrCode result = InstalldClient::GetInstance()->RemoveDir(bundleDir);
51 if (result != ERR_OK) {
52 APP_LOGE("fail to remove bundle dir %{public}s, error is %{public}d", bundleDir.c_str(), result);
53 return false;
54 }
55
56 if (bundleOrMoudleDir.find(ServiceConstants::HAPS) != std::string::npos) {
57 result = InstalldClient::GetInstance()->RemoveModuleDataDir(bundleOrMoudleDir, userId);
58 if (result != ERR_OK) {
59 APP_LOGE("fail to remove module data dir %{public}s, error is %{public}d", bundleOrMoudleDir.c_str(),
60 result);
61 return false;
62 }
63 } else {
64 result = InstalldClient::GetInstance()->RemoveBundleDataDir(bundleOrMoudleDir, userId);
65 if (result != ERR_OK) {
66 APP_LOGE("fail to remove bundle data dir %{public}s, error is %{public}d", bundleOrMoudleDir.c_str(),
67 result);
68 return false;
69 }
70 }
71 return true;
72 }
73
DeleteBundleInfoFromStorage(const InnerBundleInfo &info)74 void BundleExceptionHandler::DeleteBundleInfoFromStorage(const InnerBundleInfo &info)
75 {
76 auto storage = dataStorage_.lock();
77 if (storage) {
78 APP_LOGD("remove bundle info of %{public}s from the storage", info.GetBundleName().c_str());
79 storage->DeleteStorageBundleInfo(info);
80 } else {
81 APP_LOGE(" fail to remove bundle info of %{public}s from the storage", info.GetBundleName().c_str());
82 }
83 }
84
IsBundleHapPathExist(const InnerBundleInfo &info)85 bool BundleExceptionHandler::IsBundleHapPathExist(const InnerBundleInfo &info)
86 {
87 if (info.IsPreInstallApp() || (info.GetApplicationBundleType() != BundleType::APP)) {
88 APP_LOGD("bundleName:%{public}s no need to check", info.GetBundleName().c_str());
89 return true;
90 }
91 APP_LOGD("start, need to check bundleName:%{public}s hap file", info.GetBundleName().c_str());
92 const auto innerModuleInfos = info.GetInnerModuleInfos();
93 for (const auto &item : innerModuleInfos) {
94 if (!item.second.hapPath.empty()) {
95 bool isExist = false;
96 if (InstalldClient::GetInstance()->IsExistFile(item.second.hapPath, isExist) != ERR_OK) {
97 APP_LOGW("bundleName:%{public}s check hap path failed", info.GetBundleName().c_str());
98 continue;
99 }
100 if (!isExist) {
101 APP_LOGE("bundleName:%{public}s hap Path is not exist", info.GetBundleName().c_str());
102 return false;
103 }
104 }
105 }
106 return true;
107 }
108
InnerHandleInvalidBundle(InnerBundleInfo &info, bool &isBundleValid)109 void BundleExceptionHandler::InnerHandleInvalidBundle(InnerBundleInfo &info, bool &isBundleValid)
110 {
111 auto mark = info.GetInstallMark();
112 if (mark.status == InstallExceptionStatus::INSTALL_FINISH) {
113 return;
114 }
115 APP_LOGI_NOFUNC("%{public}s status is %{public}d", info.GetBundleName().c_str(), mark.status);
116 std::string appCodePath = std::string(Constants::BUNDLE_CODE_DIR) +
117 ServiceConstants::PATH_SEPARATOR + info.GetBundleName();
118 auto moduleDir = appCodePath + ServiceConstants::PATH_SEPARATOR + mark.packageName;
119 auto moduleDataDir = info.GetBundleName() + ServiceConstants::HAPS + mark.packageName;
120
121 // install and update failed before service restart
122 if (mark.status == InstallExceptionStatus::INSTALL_START) {
123 // unable to distinguish which user failed the installation
124 (void)RemoveBundleAndDataDir(appCodePath, info.GetBundleName(), info.GetUserId());
125 DeleteBundleInfoFromStorage(info);
126 isBundleValid = false;
127 } else if (mark.status == InstallExceptionStatus::UPDATING_EXISTED_START) {
128 if (InstalldClient::GetInstance()->RemoveDir(moduleDir + ServiceConstants::TMP_SUFFIX) == ERR_OK) {
129 info.SetInstallMark(mark.bundleName, mark.packageName, InstallExceptionStatus::INSTALL_FINISH);
130 info.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
131 }
132 } else if (mark.status == InstallExceptionStatus::UPDATING_NEW_START &&
133 RemoveBundleAndDataDir(moduleDir, moduleDataDir, info.GetUserId())) {
134 info.SetInstallMark(mark.bundleName, mark.packageName, InstallExceptionStatus::INSTALL_FINISH);
135 info.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
136 } else if (mark.status == InstallExceptionStatus::UNINSTALL_BUNDLE_START &&
137 RemoveBundleAndDataDir(appCodePath, info.GetBundleName(), info.GetUserId())) { // continue to uninstall
138 DeleteBundleInfoFromStorage(info);
139 isBundleValid = false;
140 } else if (mark.status == InstallExceptionStatus::UNINSTALL_PACKAGE_START) {
141 if (info.IsOnlyModule(mark.packageName) &&
142 RemoveBundleAndDataDir(appCodePath, info.GetBundleName(), info.GetUserId())) {
143 DeleteBundleInfoFromStorage(info);
144 isBundleValid = false;
145 return;
146 }
147 if (RemoveBundleAndDataDir(moduleDir, moduleDataDir, info.GetUserId())) {
148 info.RemoveModuleInfo(mark.packageName);
149 info.SetInstallMark(mark.bundleName, mark.packageName, InstallExceptionStatus::INSTALL_FINISH);
150 info.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
151 }
152 } else if (mark.status == InstallExceptionStatus::UPDATING_FINISH) {
153 if (InstalldClient::GetInstance()->RenameModuleDir(moduleDir + ServiceConstants::TMP_SUFFIX, moduleDir) !=
154 ERR_OK) {
155 APP_LOGI_NOFUNC("%{public}s rename module failed, may not exist", info.GetBundleName().c_str());
156 }
157 info.SetInstallMark(mark.bundleName, mark.packageName, InstallExceptionStatus::INSTALL_FINISH);
158 }
159 }
160 } // namespace AppExecFwkConstants
161 } // namespace OHOS