• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "install_exception_mgr.h"
17 
18 #include "app_log_wrapper.h"
19 #include "appexecfwk_errors.h"
20 #include "bundle_mgr_service.h"
21 #include "bundle_service_constants.h"
22 #include "bundle_constants.h"
23 #include "installd_client.h"
24 
25 namespace OHOS {
26 namespace AppExecFwk {
27 
InstallExceptionMgr()28 InstallExceptionMgr::InstallExceptionMgr()
29 {
30     installExceptionMgr_ = std::make_shared<InstallExceptionMgrRdb>();
31 }
32 
~InstallExceptionMgr()33 InstallExceptionMgr::~InstallExceptionMgr()
34 {
35 }
36 
SaveBundleExceptionInfo(const std::string & bundleName,const InstallExceptionInfo & installExceptionInfo)37 ErrCode InstallExceptionMgr::SaveBundleExceptionInfo(
38     const std::string &bundleName, const InstallExceptionInfo &installExceptionInfo)
39 {
40     if (installExceptionMgr_ == nullptr) {
41         APP_LOGE("installExceptionMgr_ is null");
42         return ERR_APPEXECFWK_NULL_PTR;
43     }
44     return installExceptionMgr_->SaveBundleExceptionInfo(bundleName, installExceptionInfo);
45 }
46 
DeleteBundleExceptionInfo(const std::string & bundleName)47 ErrCode InstallExceptionMgr::DeleteBundleExceptionInfo(const std::string &bundleName)
48 {
49     if (installExceptionMgr_ == nullptr) {
50         APP_LOGE("installExceptionMgr_ is null");
51         return ERR_APPEXECFWK_NULL_PTR;
52     }
53     return installExceptionMgr_->DeleteBundleExceptionInfo(bundleName);
54 }
55 
HandleBundleExceptionInfo(const std::string & bundleName,const InstallExceptionInfo & installExceptionInfo)56 void InstallExceptionMgr::HandleBundleExceptionInfo(
57     const std::string &bundleName, const InstallExceptionInfo &installExceptionInfo)
58 {
59     APP_LOGI("bundle %{public}s install exception status %{public}d", bundleName.c_str(),
60         static_cast<int32_t>(installExceptionInfo.status));
61     switch (installExceptionInfo.status) {
62         case InstallRenameExceptionStatus::RENAME_RELA_TO_OLD_PATH :
63         case InstallRenameExceptionStatus::RENAME_NEW_TO_RELA_PATH : {
64             InnerBundleInfo bundleInfo;
65             auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
66             if ((dataMgr != nullptr) && (!dataMgr->FetchInnerBundleInfo(bundleName, bundleInfo))) {
67                 APP_LOGW("bundle %{public}s not exist", bundleName.c_str());
68             }
69             if (bundleInfo.GetVersionCode() <= installExceptionInfo.versionCode) {
70                 std::string realPath = std::string(Constants::BUNDLE_CODE_DIR) + ServiceConstants::PATH_SEPARATOR +
71                     bundleName;
72                 std::string oldPath = std::string(Constants::BUNDLE_CODE_DIR) + ServiceConstants::PATH_SEPARATOR +
73                     std::string(ServiceConstants::BUNDLE_OLD_CODE_DIR) + bundleName;
74                 ErrCode result = InstalldClient::GetInstance()->RenameModuleDir(oldPath, realPath);
75                 if (result == ERR_OK) {
76                     (void)DeleteBundleExceptionInfo(bundleName);
77                 } else {
78                     APP_LOGE("rename module dir failed, error is %{public}d, errno %{public}d", result, errno);
79                 }
80                 std::string newPath = std::string(Constants::BUNDLE_CODE_DIR) + ServiceConstants::PATH_SEPARATOR +
81                     std::string(ServiceConstants::BUNDLE_NEW_CODE_DIR) + bundleName;
82                 result = InstalldClient::GetInstance()->RemoveDir(newPath);
83                 if (result != ERR_OK) {
84                     APP_LOGE("remove dir failed, error is %{public}d, errno %{public}d", result, errno);
85                 }
86                 return;
87             }
88         }
89         case InstallRenameExceptionStatus::DELETE_OLD_PATH : {
90             std::string oldPath = std::string(Constants::BUNDLE_CODE_DIR) + ServiceConstants::PATH_SEPARATOR +
91                 std::string(ServiceConstants::BUNDLE_OLD_CODE_DIR) + bundleName;
92             ErrCode result = InstalldClient::GetInstance()->RemoveDir(oldPath);
93             if (result == ERR_OK) {
94                 (void)DeleteBundleExceptionInfo(bundleName);
95             } else {
96                 APP_LOGE("remove dir failed, error is %{public}d, errno %{public}d", result, errno);
97             }
98             break;
99         }
100         default :
101             APP_LOGE("bundle %{public}s install unknown exception status %{public}d",
102                 bundleName.c_str(), static_cast<int32_t>(installExceptionInfo.status));
103             (void)DeleteBundleExceptionInfo(bundleName);
104     }
105 }
106 
HandleAllBundleExceptionInfo()107 void InstallExceptionMgr::HandleAllBundleExceptionInfo()
108 {
109     APP_LOGI("handle exception start");
110     if (installExceptionMgr_ == nullptr) {
111         APP_LOGE("installExceptionMgr_ is null");
112         return;
113     }
114     std::map<std::string, InstallExceptionInfo> bundleExceptionInfos;
115     installExceptionMgr_->GetAllBundleExceptionInfo(bundleExceptionInfos);
116     for (const auto &exceptionInfo : bundleExceptionInfos) {
117         HandleBundleExceptionInfo(exceptionInfo.first, exceptionInfo.second);
118     }
119     // process +old- +new- path throw scan code path
120     std::vector<std::string> allCodePath;
121     ErrCode result = InstalldClient::GetInstance()->ScanDir(Constants::BUNDLE_CODE_DIR,
122         ScanMode::SUB_FILE_DIR, ResultMode::RELATIVE_PATH, allCodePath);
123     if (result != ERR_OK) {
124         APP_LOGW("ScanDir code path failed");
125         return;
126     }
127     for (const auto &codePath : allCodePath) {
128         if (codePath.find(ServiceConstants::BUNDLE_OLD_CODE_DIR) == 0) {
129             APP_LOGI("+old- code path %{public}s", codePath.c_str());
130             std::string bundleName = codePath.substr(std::string(ServiceConstants::BUNDLE_OLD_CODE_DIR).size());
131             if (bundleName.empty()) {
132                 continue;
133             }
134             std::string oldCodePath = std::string(Constants::BUNDLE_CODE_DIR) +
135                 ServiceConstants::PATH_SEPARATOR + codePath;
136             std::string realCodePath = std::string(Constants::BUNDLE_CODE_DIR) +
137                 ServiceConstants::PATH_SEPARATOR + bundleName;
138             ErrCode result = InstalldClient::GetInstance()->RenameModuleDir(oldCodePath, realCodePath);
139             if (result != ERR_OK) {
140                 APP_LOGW("rename +old- to real code path failed, error is %{public}d", result);
141             }
142             continue;
143         }
144         if (codePath.find(ServiceConstants::BUNDLE_NEW_CODE_DIR) == 0) {
145             APP_LOGI("+new- code path %{public}s", codePath.c_str());
146             std::string newCodePath = std::string(Constants::BUNDLE_CODE_DIR) +
147                 ServiceConstants::PATH_SEPARATOR + codePath;
148             (void)InstalldClient::GetInstance()->RemoveDir(newCodePath);
149         }
150     }
151     APP_LOGI("handle exception end");
152 }
153 } // AppExecFwk
154 } // OHOS
155