1 /*
2  * Copyright (c) 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 "quick_fix_deleter.h"
17 
18 #include "app_log_tag_wrapper.h"
19 #include "bundle_mgr_service.h"
20 #include "installd_client.h"
21 #include "scope_guard.h"
22 
23 namespace OHOS {
24 namespace AppExecFwk {
25 namespace {
26 const std::string PATCH_DIR = "patch";
27 }
QuickFixDeleter(const std::string & bundleName)28 QuickFixDeleter::QuickFixDeleter(const std::string &bundleName) : bundleName_(bundleName)
29 {
30     LOG_I(BMS_TAG_DEFAULT, "enter QuickFixDeleter");
31 }
32 
Execute()33 ErrCode QuickFixDeleter::Execute()
34 {
35     LOG_I(BMS_TAG_DEFAULT, "start execute");
36     auto ret = DeleteQuickFix();
37     if (ret != ERR_OK) {
38         LOG_E(BMS_TAG_DEFAULT, "DeleteQuickFix is failed");
39     }
40     return ret;
41 }
42 
DeleteQuickFix()43 ErrCode QuickFixDeleter::DeleteQuickFix()
44 {
45     LOG_I(BMS_TAG_DEFAULT, "DeleteQuickFix start");
46     if (bundleName_.empty()) {
47         LOG_E(BMS_TAG_DEFAULT, "InnerDeleteQuickFix failed due to empty bundleName");
48         return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
49     }
50     if (GetQuickFixDataMgr() != ERR_OK) {
51         LOG_E(BMS_TAG_DEFAULT, "quickFixDataMgr is nullptr");
52         return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
53     }
54     InnerAppQuickFix innerAppQuickFix;
55     // 1. query quick fix info form db
56     if (!quickFixDataMgr_->QueryInnerAppQuickFix(bundleName_, innerAppQuickFix)) {
57         LOG_I(BMS_TAG_DEFAULT, "no patch in the db");
58         return ERR_OK;
59     }
60     // 2. update quick fix status
61     if (!quickFixDataMgr_->UpdateQuickFixStatus(QuickFixStatus::DELETE_START, innerAppQuickFix)) {
62         LOG_E(BMS_TAG_DEFAULT, "update quickfix status %{public}d failed", QuickFixStatus::DELETE_START);
63         return ERR_BUNDLEMANAGER_QUICK_FIX_INVALID_PATCH_STATUS;
64     }
65     // 3. utilize stateGuard to rollback quick fix info status in db
66     ScopeGuard stateGuard([&] {
67         quickFixDataMgr_->UpdateQuickFixStatus(QuickFixStatus::SWITCH_END, innerAppQuickFix);
68     });
69 
70     // 4. to delete patch path
71     ErrCode errCode = ToDeletePatchDir(innerAppQuickFix);
72     if (errCode != ERR_OK) {
73         LOG_E(BMS_TAG_DEFAULT, "ToDeletePatchDir failed");
74         return errCode;
75     }
76     // 5. to remove deployingAppqfInfo from cache
77     errCode = RemoveDeployingInfo(bundleName_);
78     if (errCode != ERR_OK) {
79         LOG_E(BMS_TAG_DEFAULT, "RemoveDeployingInfo failed");
80         return errCode;
81     }
82     // 6. to remove old patch info from db
83     if (!quickFixDataMgr_->DeleteInnerAppQuickFix(bundleName_)) {
84         LOG_E(BMS_TAG_DEFAULT, "InnerDeleteQuickFix failed");
85         return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
86     }
87     stateGuard.Dismiss();
88     return ERR_OK;
89 }
90 
ToDeletePatchDir(const InnerAppQuickFix & innerAppQuickFix)91 ErrCode QuickFixDeleter::ToDeletePatchDir(const InnerAppQuickFix &innerAppQuickFix)
92 {
93     LOG_I(BMS_TAG_DEFAULT, "start to delete patch dir");
94     std::string bundleName = innerAppQuickFix.GetAppQuickFix().bundleName;
95     auto res = InnerDeletePatchDir(innerAppQuickFix.GetAppQuickFix().deployedAppqfInfo, bundleName);
96     if (res != ERR_OK) {
97         LOG_E(BMS_TAG_DEFAULT, "delete patch dir of deployedAppqfInfo failed");
98         return res;
99     }
100     res = InnerDeletePatchDir(innerAppQuickFix.GetAppQuickFix().deployingAppqfInfo, bundleName);
101     if (res != ERR_OK) {
102         LOG_E(BMS_TAG_DEFAULT, "delete patch dir of deployingAppqfInfo failed");
103         return res;
104     }
105     return ERR_OK;
106 }
107 
InnerDeletePatchDir(const AppqfInfo & appqfInfo,const std::string & bundleName)108 ErrCode QuickFixDeleter::InnerDeletePatchDir(const AppqfInfo &appqfInfo, const std::string &bundleName)
109 {
110     if (appqfInfo.hqfInfos.empty()) {
111         LOG_D(BMS_TAG_DEFAULT, "no patch info in bundleInfo");
112         return ERR_OK;
113     }
114 
115     if (appqfInfo.type == QuickFixType::UNKNOWN) {
116         LOG_E(BMS_TAG_DEFAULT, "unknown quick fix type");
117         return ERR_BUNDLEMANAGER_QUICK_FIX_UNKNOWN_QUICK_FIX_TYPE;
118     }
119 
120     std::string patchPath = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR +
121         bundleName + ServiceConstants::PATH_SEPARATOR;
122     if (appqfInfo.type == QuickFixType::PATCH) {
123         if (appqfInfo.nativeLibraryPath.substr(0,
124             appqfInfo.nativeLibraryPath.find(ServiceConstants::PATH_SEPARATOR)) == PATCH_DIR) {
125             patchPath += PATCH_DIR;
126         } else {
127             patchPath += ServiceConstants::PATCH_PATH + std::to_string(appqfInfo.versionCode);
128         }
129     }
130     if (appqfInfo.type == QuickFixType::HOT_RELOAD) {
131         patchPath += ServiceConstants::HOT_RELOAD_PATH + std::to_string(appqfInfo.versionCode);
132     }
133 
134     LOG_D(BMS_TAG_DEFAULT, "patch path is %{public}s", patchPath.c_str());
135     if (InstalldClient::GetInstance()->RemoveDir(patchPath) != ERR_OK) {
136         LOG_E(BMS_TAG_DEFAULT, "RemoveDir patch path or hot reload path failed");
137         return ERR_BUNDLEMANAGER_QUICK_FIX_REMOVE_PATCH_PATH_FAILED;
138     }
139 
140     return ERR_OK;
141 }
142 
GetQuickFixDataMgr()143 ErrCode QuickFixDeleter::GetQuickFixDataMgr()
144 {
145     if (quickFixDataMgr_ == nullptr) {
146         quickFixDataMgr_ = DelayedSingleton<QuickFixDataMgr>::GetInstance();
147         if (quickFixDataMgr_ == nullptr) {
148             LOG_E(BMS_TAG_DEFAULT, "quickFix dataMgr is nullptr");
149             return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
150         }
151     }
152     return ERR_OK;
153 }
154 
GetDataMgr()155 ErrCode QuickFixDeleter::GetDataMgr()
156 {
157     if (dataMgr_ == nullptr) {
158         dataMgr_ = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
159         if (dataMgr_ == nullptr) {
160             LOG_E(BMS_TAG_DEFAULT, "dataMgr_ is nullptr");
161             return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
162         }
163     }
164     return ERR_OK;
165 }
166 
RemoveDeployingInfo(const std::string & bundleName)167 ErrCode QuickFixDeleter::RemoveDeployingInfo(const std::string &bundleName)
168 {
169     if (GetDataMgr() != ERR_OK) {
170         LOG_E(BMS_TAG_DEFAULT, "get data mar failed");
171         return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
172     }
173     InnerBundleInfo innerBundleInfo;
174     auto isExisted = dataMgr_->GetInnerBundleInfo(bundleName, innerBundleInfo);
175     if (isExisted) {
176         AppQuickFix appQuickFix = innerBundleInfo.GetAppQuickFix();
177         if (appQuickFix.deployingAppqfInfo.hqfInfos.empty()) {
178             dataMgr_->EnableBundle(bundleName_);
179             return ERR_OK;
180         }
181         appQuickFix.deployingAppqfInfo = AppqfInfo();
182         innerBundleInfo.SetAppQuickFix(appQuickFix);
183         innerBundleInfo.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
184         if (!dataMgr_->UpdateQuickFixInnerBundleInfo(bundleName, innerBundleInfo)) {
185             LOG_E(BMS_TAG_DEFAULT, "update quickfix innerbundleInfo failed");
186             return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
187         }
188     }
189     return ERR_OK;
190 }
191 } // AppExecFwk
192 } // OHOS