• 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     auto mark = info.GetInstallMark();
43     if (mark.status == InstallExceptionStatus::INSTALL_FINISH) {
44         APP_LOGD("bundle %{public}s is under correct installation status", info.GetBundleName().c_str());
45         return;
46     }
47 
48     std::string appCodePath = Constants::BUNDLE_CODE_DIR + info.GetBundleName();
49     auto moduleDir = appCodePath + Constants::PATH_SEPARATOR + mark.packageName;
50     auto moduleDataDir = info.GetBundleName() + Constants::HAPS + mark.packageName;
51 
52     // install and update failed before service restart
53     if (mark.status == InstallExceptionStatus::INSTALL_START &&
54         RemoveBundleAndDataDir(appCodePath, info.GetBundleName(), info.GetUserId())) {
55         DeleteBundleInfoFromStorage(info);
56         isBundleValid = false;
57     } else if (mark.status == InstallExceptionStatus::UPDATING_EXISTED_START) {
58         if (InstalldClient::GetInstance()->RemoveDir(moduleDir + Constants::TMP_SUFFIX) == ERR_OK) {
59             info.SetInstallMark(mark.bundleName, mark.packageName, InstallExceptionStatus::INSTALL_FINISH);
60             info.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
61         }
62     } else if (mark.status == InstallExceptionStatus::UPDATING_NEW_START &&
63         RemoveBundleAndDataDir(moduleDir, moduleDataDir, info.GetUserId())) {
64         info.SetInstallMark(mark.bundleName, mark.packageName, InstallExceptionStatus::INSTALL_FINISH);
65         info.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
66     } else if (mark.status == InstallExceptionStatus::UNINSTALL_BUNDLE_START &&
67         RemoveBundleAndDataDir(appCodePath, info.GetBundleName(), info.GetUserId())) {  // continue to uninstall
68         DeleteBundleInfoFromStorage(info);
69         isBundleValid = false;
70     } else if (mark.status == InstallExceptionStatus::UNINSTALL_PACKAGE_START) {
71         if (info.IsOnlyModule(mark.packageName) &&
72             RemoveBundleAndDataDir(appCodePath, info.GetBundleName(), info.GetUserId())) {
73             DeleteBundleInfoFromStorage(info);
74             isBundleValid = false;
75             return;
76         }
77         if (RemoveBundleAndDataDir(moduleDir, moduleDataDir, info.GetUserId())) {
78             info.RemoveModuleInfo(mark.packageName);
79             info.SetInstallMark(mark.bundleName, mark.packageName, InstallExceptionStatus::INSTALL_FINISH);
80             info.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
81         }
82     } else if (mark.status == InstallExceptionStatus::UPDATING_FINISH) {
83         if (InstalldClient::GetInstance()->RenameModuleDir(moduleDir + Constants::TMP_SUFFIX, moduleDir) == ERR_OK) {
84             info.SetInstallMark(mark.bundleName, mark.packageName, InstallExceptionStatus::INSTALL_FINISH);
85         }
86     } else {
87         APP_LOGD("bundle %{public}s is under unknown installation status", info.GetBundleName().c_str());
88     }
89 }
90 
RemoveBundleAndDataDir(const std::string & bundleDir,const std::string & bundleOrMoudleDir,int32_t userId) const91 bool BundleExceptionHandler::RemoveBundleAndDataDir(const std::string &bundleDir,
92     const std::string &bundleOrMoudleDir, int32_t userId) const
93 {
94     ErrCode result = InstalldClient::GetInstance()->RemoveDir(bundleDir);
95     if (result != ERR_OK) {
96         APP_LOGE("fail to remove bundle dir %{public}s, error is %{public}d", bundleDir.c_str(), result);
97         return false;
98     }
99 
100     if (bundleOrMoudleDir.find(Constants::HAPS) != std::string::npos) {
101         result = InstalldClient::GetInstance()->RemoveModuleDataDir(bundleOrMoudleDir, userId);
102         if (result != ERR_OK) {
103             APP_LOGE("fail to remove module data dir %{public}s, error is %{public}d", bundleOrMoudleDir.c_str(),
104                 result);
105             return false;
106         }
107     } else {
108         result = InstalldClient::GetInstance()->RemoveBundleDataDir(bundleOrMoudleDir, userId);
109         if (result != ERR_OK) {
110             APP_LOGE("fail to remove bundle data dir %{public}s, error is %{public}d", bundleOrMoudleDir.c_str(),
111                 result);
112             return false;
113         }
114     }
115     return true;
116 }
117 
DeleteBundleInfoFromStorage(const InnerBundleInfo & info)118 void BundleExceptionHandler::DeleteBundleInfoFromStorage(const InnerBundleInfo &info)
119 {
120     auto storage = dataStorage_.lock();
121     if (storage) {
122         APP_LOGD("remove bundle info of %{public}s from the storage", info.GetBundleName().c_str());
123         storage->DeleteStorageBundleInfo(info);
124     } else {
125         APP_LOGE(" fail to remove bundle info of %{public}s from the storage", info.GetBundleName().c_str());
126     }
127 }
128 }  // namespace AppExecFwkConstants
129 }  // namespace OHOS