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