• 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 <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