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