• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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