diff --git a/services/backup_sa/BUILD.gn b/services/backup_sa/BUILD.gn index 16e1f65298e300a8e232a5ae33c56d9d6d5da3af..d589c50d61658aebc83f3f42b224eb935b04e540 100644 --- a/services/backup_sa/BUILD.gn +++ b/services/backup_sa/BUILD.gn @@ -24,6 +24,7 @@ ohos_shared_library("backup_sa") { "src/module_ipc/service_stub.cpp", "src/module_ipc/svc_backup_connection.cpp", "src/module_ipc/svc_extension_proxy.cpp", + "src/module_ipc/svc_restore_deps_manager.cpp", "src/module_ipc/svc_session_manager.cpp", "src/module_sched/sched_scheduler.cpp", ] diff --git a/services/backup_sa/include/module_ipc/service.h b/services/backup_sa/include/module_ipc/service.h index d1f163d3593ae575e44cfe837c5aa3ece83c9281..b45d1ae6eb4b46ba6fcdcbdc14d9bf584338fe2a 100644 --- a/services/backup_sa/include/module_ipc/service.h +++ b/services/backup_sa/include/module_ipc/service.h @@ -137,6 +137,7 @@ private: * */ void OnStartSched(); + /** * @brief 通知客户端程序扩展能力处理结果 * @@ -145,6 +146,14 @@ private: */ void NoticeClientFinish(const std::string &bundleName, ErrCode errCode); + /** + * @brief 处理有依赖的应用恢复 + * + * @param bundleName 应用名称 + * + */ + void HandleRestoreDepsBundle(const std::string &bundleName); + private: static sptr instance_; static std::mutex instanceLock_; diff --git a/services/backup_sa/include/module_ipc/svc_restore_deps_manager.h b/services/backup_sa/include/module_ipc/svc_restore_deps_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..d830cb2b6152558e181544e9b3adc3858efd8147 --- /dev/null +++ b/services/backup_sa/include/module_ipc/svc_restore_deps_manager.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_FILEMGMT_BACKUP_SVC_RESTORE_DEPS_MANAGER_H +#define OHOS_FILEMGMT_BACKUP_SVC_RESTORE_DEPS_MANAGER_H + +#include +#include +#include +#include + +#include "b_json/b_json_entity_caps.h" +#include "i_service.h" + +namespace OHOS::FileManagement::Backup { + +class SvcRestoreDepsManager { +public: + static SvcRestoreDepsManager &GetInstance() + { + static SvcRestoreDepsManager manager; + return manager; + } + struct RestoreInfo { + RestoreTypeEnum restoreType_ {RESTORE_DATA_WAIT_SEND}; + set fileNames_ {}; + }; + + vector GetRestoreBundleNames(const vector &infos, RestoreTypeEnum restoreType); + map GetRestoreBundleMap(); + void AddRestoredBundles(const string &bundleName); + vector GetAllBundles() const; + bool IsAllBundlesRestored() const; + void UpdateToRestoreBundleMap(const string &bundleName, const string &fileName); + +private: + SvcRestoreDepsManager() {} + ~SvcRestoreDepsManager() = default; + SvcRestoreDepsManager(const SvcRestoreDepsManager &manager) = delete; + SvcRestoreDepsManager &operator=(const SvcRestoreDepsManager &manager) = delete; + + void BuildDepsMap(const vector &infos); + vector SplitString(const string &srcStr, const string &separator); + bool IsAllDepsRestored(const string &bundleName); + + mutable std::shared_mutex lock_; + map> depsMap_ {}; + vector allBundles_ {}; // 所有的应用 + map toRestoreBundleMap_ {}; // 有依赖的应用 + set restoredBundles_ {}; // 已经恢复完成的应用 +}; + +} // namespace OHOS::FileManagement::Backup + +#endif // OHOS_FILEMGMT_BACKUP_SVC_RESTORE_DEPS_MANAGER_H diff --git a/services/backup_sa/src/module_external/bms_adapter.cpp b/services/backup_sa/src/module_external/bms_adapter.cpp index 571bce2a051057ce4ef9f1effb7bda7c1c866a74..1e4da6bd4aa82ab59cd1257eb4d0b59388b0b36f 100644 --- a/services/backup_sa/src/module_external/bms_adapter.cpp +++ b/services/backup_sa/src/module_external/bms_adapter.cpp @@ -61,7 +61,7 @@ static sptr GetBundleManager() return iface_cast(bundleObj); } -static tuple GetAllowAndExtName(const vector &extensionInfos) +static tuple GetAllowAndExtName(const vector &extensionInfos) { for (auto &&ext : extensionInfos) { if (ext.type != AppExecFwk::ExtensionAbilityType::BACKUP) { @@ -74,10 +74,10 @@ static tuple GetAllowAndExtName(const vector cachedEntity(out[0], ext.bundleName); auto cache = cachedEntity.Structuralize(); - return {cache.GetAllowToBackupRestore(), ext.name}; + return {cache.GetAllowToBackupRestore(), ext.name, cache.GetRestoreDeps()}; } HILOGI("No backup extension ability found"); - return {false, ""}; + return {false, "", ""}; } static int64_t GetBundleStats(const string &bundleName, int32_t userId) @@ -117,11 +117,11 @@ vector BundleMgrAdapter::GetBundleInfos(int32_t use HILOGI("Unsupported applications, name : %{public}s", installedBundle.name.data()); continue; } - auto [allToBackup, extName] = GetAllowAndExtName(installedBundle.extensionInfos); + auto [allToBackup, extName, restoreDeps] = GetAllowAndExtName(installedBundle.extensionInfos); auto dataSize = GetBundleStats(installedBundle.name, userId); bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {installedBundle.name, installedBundle.versionCode, installedBundle.versionName, dataSize, allToBackup, - extName}); + extName, false, restoreDeps}); } return bundleInfos; } @@ -141,11 +141,11 @@ vector BundleMgrAdapter::GetBundleInfos(const vecto HILOGI("Unsupported applications, name : %{public}s", installedBundle.name.data()); continue; } - auto [allToBackup, extName] = GetAllowAndExtName(installedBundle.extensionInfos); + auto [allToBackup, extName, restoreDeps] = GetAllowAndExtName(installedBundle.extensionInfos); auto dataSize = GetBundleStats(installedBundle.name, userId); bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {installedBundle.name, installedBundle.versionCode, installedBundle.versionName, dataSize, allToBackup, - extName}); + extName, false, restoreDeps}); } return bundleInfos; } diff --git a/services/backup_sa/src/module_ipc/service.cpp b/services/backup_sa/src/module_ipc/service.cpp index 8f85c320c0524e1303b5d06aa34ea73102aa5ddc..d7cd3c3be145d6604abb9e9e766264f7542aed8c 100644 --- a/services/backup_sa/src/module_ipc/service.cpp +++ b/services/backup_sa/src/module_ipc/service.cpp @@ -50,6 +50,7 @@ #include "ipc_skeleton.h" #include "module_external/bms_adapter.h" #include "module_ipc/svc_backup_connection.h" +#include "module_ipc/svc_restore_deps_manager.h" #include "parameter.h" #include "system_ability_definition.h" @@ -230,6 +231,19 @@ ErrCode Service::Start() return BError(BError::Codes::OK); } +static void GetRestoreBundleNames(const vector &bundleInfos, + vector &restoreBundleNames, + RestoreTypeEnum restoreType, + const vector &bundleNames) +{ + vector restoreBundleInfos {}; + for (auto &bundleInfo : bundleInfos) { + if (find(bundleNames.begin(), bundleNames.end(), bundleInfo.name) != bundleNames.end()) { + restoreBundleInfos.emplace_back(bundleInfo); + } + } + restoreBundleNames = SvcRestoreDepsManager::GetInstance().GetRestoreBundleNames(restoreBundleInfos, restoreType); +} ErrCode Service::AppendBundlesRestoreSession(UniqueFd fd, const vector &bundleNames, RestoreTypeEnum restoreType, @@ -247,8 +261,13 @@ ErrCode Service::AppendBundlesRestoreSession(UniqueFd fd, if (!bundleInfos.size()) { throw BError(BError::Codes::SA_INVAL_ARG, "Json entity caps is empty"); } - session_->AppendBundles(bundleNames); - for (auto bundleName : bundleNames) { + vector restoreBundleNames {}; + GetRestoreBundleNames(bundleInfos, restoreBundleNames, restoreType, bundleNames); + if (restoreBundleNames.empty()) { + return BError(BError::Codes::OK); + } + session_->AppendBundles(restoreBundleNames); + for (auto bundleName : restoreBundleNames) { HILOGD("bundleName: %{public}s", bundleName.c_str()); for (auto &&bundleInfo : bundleInfos) { if (bundleInfo.name != bundleName) { @@ -474,6 +493,7 @@ ErrCode Service::GetFileHandle(const string &bundleName, const string &fileName) if (!regex_match(fileName, regex("^[0-9a-zA-Z_.]+$"))) { throw BError(BError::Codes::SA_INVAL_ARG, "Filename is not alphanumeric"); } + SvcRestoreDepsManager::GetInstance().UpdateToRestoreBundleMap(bundleName, fileName); session_->SetExtFileNameRequest(bundleName, fileName); auto action = session_->GetServiceSchedAction(bundleName); if (action == BConstants::ServiceSchedAction::RUNNING) { @@ -657,6 +677,7 @@ void Service::ClearSessionAndSchedInfo(const string &bundleName) try { session_->RemoveExtInfo(bundleName); sched_->RemoveExtConn(bundleName); + HandleRestoreDepsBundle(bundleName); sched_->Sched(); } catch (const BError &e) { return; @@ -669,6 +690,45 @@ void Service::ClearSessionAndSchedInfo(const string &bundleName) } } +void Service::HandleRestoreDepsBundle(const string &bundleName) +{ + if (session_->GetScenario() != IServiceReverse::Scenario::RESTORE) { + return; + } + HILOGI("Begin, bundleName: %{public}s", bundleName.c_str()); + SvcRestoreDepsManager::GetInstance().AddRestoredBundles(bundleName); + // 该应用恢复完成,判断依赖hap的前置hap是否全部恢复完成,如果成了,追加该依赖hap + auto restoreBundleMap = SvcRestoreDepsManager::GetInstance().GetRestoreBundleMap(); + if (restoreBundleMap.empty()) { + HILOGI("restoreBundleMap is empty."); + return; + } + // 启动恢复会话 + vector restoreBundleNames {}; + for (auto &bundle : restoreBundleMap) { + HILOGI("Start restore session, bundle: %{public}s", bundle.first.c_str()); + restoreBundleNames.emplace_back(bundle.first); + } + session_->AppendBundles(restoreBundleNames); + for (auto &bundle : restoreBundleMap) { + for (auto &bundleInfo : SvcRestoreDepsManager::GetInstance().GetAllBundles()) { + if (bundle.first != bundleInfo.name) { + continue; + } + SvcRestoreDepsManager::RestoreInfo info = bundle.second; + session_->SetNeedToInstall(bundleInfo.name, bundleInfo.needToInstall); + session_->SetBundleRestoreType(bundleInfo.name, info.restoreType_); + session_->SetBundleVersionCode(bundleInfo.name, bundleInfo.versionCode); + session_->SetBundleVersionName(bundleInfo.name, bundleInfo.versionName); + session_->SetBundleDataSize(bundleInfo.name, bundleInfo.spaceOccupied); + for (auto &fileName : info.fileNames_) { + session_->SetExtFileNameRequest(bundleInfo.name, fileName); + } + } + } + HILOGI("End"); +} + void Service::OnAllBundlesFinished(ErrCode errCode) { if (session_->IsOnAllBundlesFinished()) { diff --git a/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp b/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f760ba8df4be6ef90faedf063b2f0999d4dce7c --- /dev/null +++ b/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "module_ipc/svc_restore_deps_manager.h" + +#include "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; + +vector SvcRestoreDepsManager::GetRestoreBundleNames(const vector &bundleInfos, + RestoreTypeEnum restoreType) +{ + unique_lock lock(lock_); + vector restoreBundleNames {}; // 需要恢复的应用列表 + BuildDepsMap(bundleInfos); // 构建依赖Map + + for (auto &bundleInfo : bundleInfos) { + string restoreDeps = bundleInfo.restoreDeps; + if (restoreDeps.empty()) { + // 将没有依赖的应用加入到需要恢复的应用列表 + restoreBundleNames.emplace_back(bundleInfo.name); + } else { + RestoreInfo info {}; + info.restoreType_ = restoreType; + toRestoreBundleMap_.insert(make_pair(bundleInfo.name, info)); + + // 如果该应用的依赖项已经完成备份,也需要加到需要恢复的应用列表 + if (IsAllDepsRestored(bundleInfo.name)) { + restoreBundleNames.emplace_back(bundleInfo.name); + toRestoreBundleMap_.erase(bundleInfo.name); + } + } + } + + return restoreBundleNames; +} + +map SvcRestoreDepsManager::GetRestoreBundleMap() +{ + unique_lock lock(lock_); + map restoreBundleMap {}; // 需要恢复的应用列表 + for (auto it = toRestoreBundleMap_.begin(); it != toRestoreBundleMap_.end();) { // 所有有依赖的应用 + // 如果该应用的依赖项已经完成备份,也需要加到 restoreBundleNames + string bundleName = it->first; + if (IsAllDepsRestored(bundleName)) { + RestoreInfo restoreInfo = it->second; + restoreBundleMap.insert(make_pair(bundleName, restoreInfo)); + toRestoreBundleMap_.erase(it++); + } else { + it++; + } + } + return restoreBundleMap; +} + +bool SvcRestoreDepsManager::IsAllDepsRestored(const string &bundle) +{ + if (depsMap_.find(bundle) == depsMap_.end()) { + return false; + } + bool isAllDepsRestored = true; + vector depList = depsMap_[bundle]; + for (auto &dep : depList) { + if (find(restoredBundles_.begin(), restoredBundles_.end(), dep) == restoredBundles_.end()) { + isAllDepsRestored = false; + break; + } + } + return isAllDepsRestored; +} + +void SvcRestoreDepsManager::BuildDepsMap(const vector &bundleInfos) +{ + for (auto &bundleInfo : bundleInfos) { + if (depsMap_.find(bundleInfo.name) != depsMap_.end()) { + continue; + } + allBundles_.emplace_back(bundleInfo); + + vector depsList {}; + string restoreDeps = bundleInfo.restoreDeps; + if (restoreDeps.find(",") != string::npos) { + depsList = SplitString(restoreDeps, ","); + } else { + if (!restoreDeps.empty()) { + depsList.emplace_back(restoreDeps); + } + } + + depsMap_.insert(make_pair(bundleInfo.name, depsList)); + } +} + +vector SvcRestoreDepsManager::SplitString(const string &srcStr, const string &separator) +{ + HILOGI("srcStr:%{public}s, separator:%{public}s", srcStr.c_str(), separator.c_str()); + vector dst; + if (srcStr.empty() || separator.empty()) { + return dst; + } + size_t start = 0; + size_t index = srcStr.find_first_of(separator, 0); + while (index != srcStr.npos) { + if (start != index) { + string tempStr = srcStr.substr(start, index - start); + tempStr.erase(0, tempStr.find_first_not_of(" ")); + tempStr.erase(tempStr.find_last_not_of(" ") + 1); + tempStr.erase(tempStr.find_last_not_of("\r") + 1); + dst.push_back(tempStr); + } + start = index + 1; + index = srcStr.find_first_of(separator, start); + } + + if (!srcStr.substr(start).empty()) { + string tempStr = srcStr.substr(start); + tempStr.erase(0, tempStr.find_first_not_of(" ")); + tempStr.erase(tempStr.find_last_not_of(" ") + 1); + tempStr.erase(tempStr.find_last_not_of("\r") + 1); + dst.push_back(tempStr); + } + return dst; +} + +void SvcRestoreDepsManager::AddRestoredBundles(const string &bundleName) +{ + unique_lock lock(lock_); + restoredBundles_.insert(bundleName); +} + +vector SvcRestoreDepsManager::GetAllBundles() const +{ + return allBundles_; +} + +bool SvcRestoreDepsManager::IsAllBundlesRestored() const +{ + return toRestoreBundleMap_.empty(); +} + +void SvcRestoreDepsManager::UpdateToRestoreBundleMap(const string &bundleName, const string &fileName) +{ + unique_lock lock(lock_); + auto it = toRestoreBundleMap_.find(bundleName); + if (it != toRestoreBundleMap_.end()) { + it->second.fileNames_.insert(fileName); + } +} + +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/services/backup_sa/src/module_ipc/svc_session_manager.cpp b/services/backup_sa/src/module_ipc/svc_session_manager.cpp index 9c9d3390d4660d0f944bff5008d6fdf54397cf1a..95baf0f3bda1f1f2506c08175aa8e7257bca5384 100644 --- a/services/backup_sa/src/module_ipc/svc_session_manager.cpp +++ b/services/backup_sa/src/module_ipc/svc_session_manager.cpp @@ -29,6 +29,7 @@ #include "b_resources/b_constants.h" #include "filemgmt_libhilog.h" #include "module_ipc/service.h" +#include "module_ipc/svc_restore_deps_manager.h" namespace OHOS::FileManagement::Backup { using namespace std; @@ -428,10 +429,13 @@ bool SvcSessionManager::IsOnAllBundlesFinished() } auto iter = find_if(impl_.backupExtNameMap.begin(), impl_.backupExtNameMap.end(), [](const auto &it) { return it.second.isBundleFinished == false; }); - if (iter == impl_.backupExtNameMap.end() && impl_.isAppendFinish) { - return true; + bool isAllBundlesFinished = (iter == impl_.backupExtNameMap.end() && impl_.isAppendFinish); + if (impl_.scenario == IServiceReverse::Scenario::RESTORE) { + bool isAllBundlesRestored = SvcRestoreDepsManager::GetInstance().IsAllBundlesRestored(); + isAllBundlesFinished = (isAllBundlesFinished && isAllBundlesRestored); } - return false; + HILOGI("isAllBundlesFinished:%{public}d", isAllBundlesFinished); + return isAllBundlesFinished; } bool SvcSessionManager::IsOnOnStartSched() @@ -498,10 +502,13 @@ bool SvcSessionManager::GetNeedToInstall(const std::string &bundleName) bool SvcSessionManager::NeedToUnloadService() { unique_lock lock(lock_); - if (!impl_.clientToken || !impl_.clientProxy || !impl_.backupExtNameMap.size()) { - return true; + bool isNeedToUnloadService = (!impl_.clientToken || !impl_.clientProxy || !impl_.backupExtNameMap.size()); + if (impl_.scenario == IServiceReverse::Scenario::RESTORE) { + bool isAllBundlesRestored = SvcRestoreDepsManager::GetInstance().IsAllBundlesRestored(); + isNeedToUnloadService = (isNeedToUnloadService && isAllBundlesRestored); } - return false; + HILOGI("isNeedToUnloadService:%{public}d", isNeedToUnloadService); + return isNeedToUnloadService; } void SvcSessionManager::SetBundleRestoreType(const std::string &bundleName, RestoreTypeEnum restoreType) diff --git a/tests/unittests/backup_sa/module_ipc/BUILD.gn b/tests/unittests/backup_sa/module_ipc/BUILD.gn index b585d02e4c41080849d204033c5644ca6cd49614..a03c96a4836466859085273ce23c3090f7154b75 100644 --- a/tests/unittests/backup_sa/module_ipc/BUILD.gn +++ b/tests/unittests/backup_sa/module_ipc/BUILD.gn @@ -59,6 +59,7 @@ ohos_unittest("backup_service_test") { sources = [ "${path_backup_mock}/accesstoken/accesstoken_kit_mock.cpp", "${path_backup}/services/backup_sa/src/module_ipc/service.cpp", + "${path_backup}/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp", "service_test.cpp", ] sources += backup_mock_src @@ -103,6 +104,7 @@ ohos_unittest("backup_service_session_test") { sources = [ "${path_backup_mock}/affwk/service_registry_mock.cpp", "${path_backup_mock}/bundle_manager/src/mock_bundle_manager.cpp", + "${path_backup}/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp", "${path_backup}/services/backup_sa/src/module_ipc/svc_session_manager.cpp", "svc_session_manager_test.cpp", ] diff --git a/tools/backup_tool/src/tools_op_restore.cpp b/tools/backup_tool/src/tools_op_restore.cpp index f527f20e8f9e50c38c6c11da01860f3b08c7f2fb..53c1b301b32ee49f3cf9f4a13f66178cbf2768c7 100644 --- a/tools/backup_tool/src/tools_op_restore.cpp +++ b/tools/backup_tool/src/tools_op_restore.cpp @@ -249,16 +249,8 @@ static bool GetRealPath(string &path) return true; } -static int32_t InitPathCapFile(const string &pathCapFile, vector bundleNames) +static int32_t InitFd(UniqueFd &fd, const vector &bundleNames) { - StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Init"); - string realPath = pathCapFile; - if (!GetRealPath(realPath)) { - fprintf(stderr, "path to realpath error"); - return -errno; - } - - UniqueFd fd(open(realPath.data(), O_RDWR, S_IRWXU)); if (fd < 0) { fprintf(stderr, "Failed to open file error: %d %s\n", errno, strerror(errno)); FinishTrace(HITRACE_TAG_FILEMANAGEMENT); @@ -279,7 +271,15 @@ static int32_t InitPathCapFile(const string &pathCapFile, vector bundleN cachedEntity.Persist(); fd = move(cachedEntity.GetFd()); } - auto ctx = make_shared(); + return 0; +} + +static int32_t InitRestoreSession(shared_ptr ctx) +{ + if (!ctx) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + return -1; + } ctx->session_ = BSessionRestore::Init( BSessionRestore::Callbacks {.onFileReady = bind(OnFileReady, ctx, placeholders::_1, placeholders::_2), .onBundleStarted = bind(OnBundleStarted, ctx, placeholders::_1, placeholders::_2), @@ -291,10 +291,51 @@ static int32_t InitPathCapFile(const string &pathCapFile, vector bundleN FinishTrace(HITRACE_TAG_FILEMANAGEMENT); return -EPERM; } - int ret = ctx->session_->AppendBundles(move(fd), bundleNames); + return 0; +} + +static int32_t InitPathCapFile(const string &pathCapFile, vector bundleNames, bool depMode) +{ + StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Init"); + string realPath = pathCapFile; + if (!GetRealPath(realPath)) { + fprintf(stderr, "path to realpath error"); + return -errno; + } + + UniqueFd fd(open(realPath.data(), O_RDWR, S_IRWXU)); + int32_t ret = InitFd(fd, bundleNames); if (ret != 0) { - printf("restore append bundles error: %d\n", ret); - return -ret; + printf("Failed to get fd error:%d\n", ret); + return ret; + } + auto ctx = make_shared(); + ret = InitRestoreSession(ctx); + if (ret != 0) { + printf("Failed to init restore session error:%d\n", ret); + return ret; + } + + if (depMode) { + for (auto &bundleName : bundleNames) { + UniqueFd fd(open(realPath.data(), O_RDWR, S_IRWXU)); + if (fd < 0) { + fprintf(stderr, "Failed to open file error: %d %s\n", errno, strerror(errno)); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return -errno; + } + int ret = ctx->session_->AppendBundles(move(fd), {bundleName}); + if (ret != 0) { + printf("restore append bundles error: %d\n", ret); + return -ret; + } + } + } else { + ret = ctx->session_->AppendBundles(move(fd), bundleNames); + if (ret != 0) { + printf("restore append bundles error: %d\n", ret); + return -ret; + } } ctx->SetBundleFinishedCount(bundleNames.size()); RestoreApp(ctx, bundleNames); @@ -304,15 +345,21 @@ static int32_t InitPathCapFile(const string &pathCapFile, vector bundleN static int Exec(map> &mapArgToVal) { + bool depMode = false; + if (mapArgToVal.find("depMode") != mapArgToVal.end()) { + string strFlag = *(mapArgToVal["depMode"].begin()); + depMode = (strFlag == "true"); + } + if (mapArgToVal.find("pathCapFile") == mapArgToVal.end() || mapArgToVal.find("bundles") == mapArgToVal.end()) { return -EPERM; } - return InitPathCapFile(*(mapArgToVal["pathCapFile"].begin()), mapArgToVal["bundles"]); + return InitPathCapFile(*(mapArgToVal["pathCapFile"].begin()), mapArgToVal["bundles"], depMode); } bool RestoreRegister() { - return ToolsOp::Register(ToolsOp{ ToolsOp::Descriptor { + return ToolsOp::Register(ToolsOp {ToolsOp::Descriptor { .opName = {"restore"}, .argList = {{ .paramName = "pathCapFile", @@ -321,9 +368,13 @@ bool RestoreRegister() { .paramName = "bundles", .repeatable = true, + }, + { + .paramName = "depMode", + .repeatable = false, }}, .funcGenHelpMsg = GenHelpMsg, .funcExec = Exec, - } }); + }}); } } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/utils/include/b_json/b_json_entity_caps.h b/utils/include/b_json/b_json_entity_caps.h index 9ab7bc2128eb62cb2bf0c20747ac33427b165226..14afc43f1fb4f50dc3bc610a988ceb40e5d60a82 100644 --- a/utils/include/b_json/b_json_entity_caps.h +++ b/utils/include/b_json/b_json_entity_caps.h @@ -30,6 +30,7 @@ public: bool allToBackup; std::string extensionName; bool needToInstall {false}; + std::string restoreDeps; }; public: @@ -57,6 +58,7 @@ public: arrObj["allToBackup"] = item.allToBackup; arrObj["extensionName"] = item.extensionName; arrObj["needToInstall"] = item.needToInstall; + arrObj["restoreDeps"] = item.restoreDeps; obj_["bundleInfos"].append(arrObj); } } @@ -81,6 +83,16 @@ public: return obj_["deviceType"].asString(); } + std::string GetRestoreDeps() + { + if (!obj_ || !obj_.isMember("restoreDeps") || !obj_["restoreDeps"].isString()) { + HILOGI("Failed to get field restoreDeps"); + return ""; + } + + return obj_["restoreDeps"].asString(); + } + std::vector GetBundleInfos() { if (!obj_ || !obj_.isMember("bundleInfos") || !obj_["bundleInfos"].isArray()) { @@ -91,14 +103,15 @@ public: for (const auto &item : obj_["bundleInfos"]) { if (!item || !item["name"].isString() || !item["versionCode"].isUInt() || !item["versionName"].isString() || !item["spaceOccupied"].isInt64() || !item["allToBackup"].isBool() || - !item["extensionName"].isString() || !item["needToInstall"].isBool()) { + !item["extensionName"].isString() || !item["needToInstall"].isBool() || + !item["restoreDeps"].isString()) { HILOGI("Failed to get field bundleInfos, type error"); return {}; } bundleInfos.emplace_back(BundleInfo {item["name"].asString(), item["versionCode"].asUInt(), item["versionName"].asString(), item["spaceOccupied"].asInt64(), item["allToBackup"].asBool(), item["extensionName"].asString(), - item["needToInstall"].asBool()}); + item["needToInstall"].asBool(), item["restoreDeps"].asString()}); } return bundleInfos; } diff --git a/utils/include/b_json/b_json_entity_extension_config.h b/utils/include/b_json/b_json_entity_extension_config.h index 54f00232497c0786ce07ce0718847957bbe5ec51..e6fbdb774507c5ca5411cdcc7502b76ec7865dfa 100644 --- a/utils/include/b_json/b_json_entity_extension_config.h +++ b/utils/include/b_json/b_json_entity_extension_config.h @@ -55,6 +55,13 @@ public: */ bool GetFullBackupOnly() const; + /** + * @brief 从JSon对象中获取应用依赖项 + * + * @return 应用依赖项: 该应用恢复依赖的应用 + */ + std::string GetRestoreDeps() const; + public: std::string GetJSonSource(std::string_view jsonFromRealWorld, std::any option); diff --git a/utils/src/b_json/b_json_entity_extension_config.cpp b/utils/src/b_json/b_json_entity_extension_config.cpp index 726c1ed30764497b15a10aeb787ba48c852f73c0..f6e7e751e214e05deaf0d0a944f80e608c2938f8 100644 --- a/utils/src/b_json/b_json_entity_extension_config.cpp +++ b/utils/src/b_json/b_json_entity_extension_config.cpp @@ -140,4 +140,15 @@ string BJsonEntityExtensionConfig::GetJSonSource(string_view jsonFromRealWorld, } return BFile::ReadFile(UniqueFd(open(jsonFilePath.c_str(), O_RDONLY))).get(); } + +string BJsonEntityExtensionConfig::GetRestoreDeps() const +{ + if (!obj_ || !obj_.isMember("restoreDeps") || !obj_["restoreDeps"].isString()) { + HILOGE("Failed to init field restoreDeps"); + return ""; + } + + return obj_["restoreDeps"].asString(); +} + } // namespace OHOS::FileManagement::Backup