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