From 1217c82016aec898f4d814212cacba624e1ab34c Mon Sep 17 00:00:00 2001 From: huaqingsimeng <1004904143@qq.com> Date: Mon, 3 Apr 2023 07:44:36 +0000 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=81=A2=E5=A4=8D=E6=97=B6?= =?UTF-8?q?=E5=AE=89=E8=A3=85=E5=BA=94=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- services/backup_sa/BUILD.gn | 1 + .../include/module_external/bms_adapter.h | 8 ++ .../module_external/inner_receiver_impl.h | 44 ++++++++++ .../include/module_ipc/svc_session_manager.h | 35 ++++++++ .../include/module_sched/sched_scheduler.h | 17 ++++ .../src/module_external/bms_adapter.cpp | 32 ++++++- .../module_external/inner_receiver_impl.cpp | 44 ++++++++++ services/backup_sa/src/module_ipc/service.cpp | 41 +++++++-- .../src/module_ipc/svc_session_manager.cpp | 83 +++++++++++++++---- .../src/module_sched/sched_scheduler.cpp | 57 ++++++++++++- tools/backup_tool/src/tools_op_restore.cpp | 44 +++++++--- utils/include/b_json/b_json_entity_caps.h | 70 +++++++++++----- utils/include/b_resources/b_constants.h | 11 ++- utils/src/b_filesystem/b_file.cpp | 4 + utils/src/b_json/b_json_entity_ext_manage.cpp | 8 ++ 15 files changed, 440 insertions(+), 59 deletions(-) create mode 100644 services/backup_sa/include/module_external/inner_receiver_impl.h create mode 100644 services/backup_sa/src/module_external/inner_receiver_impl.cpp diff --git a/services/backup_sa/BUILD.gn b/services/backup_sa/BUILD.gn index 317fc0770..d065d2e5b 100644 --- a/services/backup_sa/BUILD.gn +++ b/services/backup_sa/BUILD.gn @@ -17,6 +17,7 @@ import("//foundation/filemanagement/app_file_service/backup.gni") ohos_shared_library("backup_sa") { sources = [ "src/module_external/bms_adapter.cpp", + "src/module_external/inner_receiver_impl.cpp", "src/module_external/sms_adapter.cpp", "src/module_ipc/service.cpp", "src/module_ipc/service_reverse_proxy.cpp", diff --git a/services/backup_sa/include/module_external/bms_adapter.h b/services/backup_sa/include/module_external/bms_adapter.h index 2c8fee0b0..3671396d9 100644 --- a/services/backup_sa/include/module_external/bms_adapter.h +++ b/services/backup_sa/include/module_external/bms_adapter.h @@ -41,6 +41,14 @@ public: * @return std::vector */ static std::vector GetBundleInfos(const std::vector &bundleNames); + + /** + * @brief Install bundle + * + * @param bundleName bundle name + * @param bundleFilePath bundle file path + */ + static ErrCode Install(wptr statusReceiver, const std::string &bundleFilePath); }; } // namespace OHOS::FileManagement::Backup #endif // OHOS_FILEMGMT_BACKUP_BUNDLE_MGR_ADAPTER_H \ No newline at end of file diff --git a/services/backup_sa/include/module_external/inner_receiver_impl.h b/services/backup_sa/include/module_external/inner_receiver_impl.h new file mode 100644 index 000000000..933603f9d --- /dev/null +++ b/services/backup_sa/include/module_external/inner_receiver_impl.h @@ -0,0 +1,44 @@ +/* + * 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_INNERRECEIVER_H +#define OHOS_FILEMGMT_BACKUP_INNERRECEIVER_H + +#include + +#include + +#include "status_receiver_host.h" + +namespace OHOS::FileManagement::Backup { +class SchedScheduler; + +class InnerReceiverImpl : public AppExecFwk::StatusReceiverHost { +public: + virtual void OnStatusNotify(const int progress) override; + virtual void OnFinished(const int32_t resultCode, const std::string &resultMsg) override; + + std::string GetBundleName(); + +public: + InnerReceiverImpl(const std::string &bundleName, wptr sched) + : bundleName_(bundleName), sched_(sched) {}; + +private: + std::string bundleName_; + wptr sched_; +}; +} // namespace OHOS::FileManagement::Backup +#endif // OHOS_FILEMGMT_BACKUP_INNERRECEIVER_H \ No newline at end of file diff --git a/services/backup_sa/include/module_ipc/svc_session_manager.h b/services/backup_sa/include/module_ipc/svc_session_manager.h index 6d228aa31..82308a60c 100644 --- a/services/backup_sa/include/module_ipc/svc_session_manager.h +++ b/services/backup_sa/include/module_ipc/svc_session_manager.h @@ -44,6 +44,8 @@ struct BackupExtInfo { sptr backUpConnection; std::set fileNameInfo; BConstants::ServiceSchedAction schedAction {BConstants::ServiceSchedAction::WAIT}; + bool bNeedToInstall {false}; + std::string installState; }; class Service; @@ -237,6 +239,39 @@ public: */ bool IsOnOnStartSched(); + /** + * @brief Set the Install State object + * + * @param bundleName + * @param state + */ + void SetInstallState(const std::string &bundleName, const std::string &state); + + /** + * @brief Get the Install State object + * + * @param bundleName + * @return std::string + */ + std::string GetInstallState(const std::string &bundleName); + + /** + * @brief Set the Need To Install object + * + * @param bundleName + * @param needToInstall + */ + void SetNeedToInstall(const std::string &bundleName, bool needToInstall); + + /** + * @brief Get the Need To Install object + * + * @param bundleName + * @return true + * @return false + */ + bool GetNeedToInstall(const std::string &bundleName); + private: /** * @brief 获取backup extension ability diff --git a/services/backup_sa/include/module_sched/sched_scheduler.h b/services/backup_sa/include/module_sched/sched_scheduler.h index b84f4c134..63dfd299d 100644 --- a/services/backup_sa/include/module_sched/sched_scheduler.h +++ b/services/backup_sa/include/module_sched/sched_scheduler.h @@ -16,6 +16,7 @@ #ifndef OHOS_FILEMGMT_BACKUP_SCHED_SCHEDULER_H #define OHOS_FILEMGMT_BACKUP_SCHED_SCHEDULER_H +#include #include #include #include @@ -53,6 +54,14 @@ public: */ void RemoveExtConn(const std::string &bundleName); + /** + * @brief install success + * + * @param bundleName + * @param resultCode + */ + void InstallSuccess(const std::string &bundleName, const int32_t resultCode); + void StartTimer() { extTime_.Setup(); @@ -73,6 +82,14 @@ public: bundleTimeVec_.clear(); } +private: + /** + * @brief install state + * + * @param bundleName + */ + void InstallingState(const std::string &bundleName); + private: mutable std::shared_mutex lock_; OHOS::ThreadPool threadPool_; diff --git a/services/backup_sa/src/module_external/bms_adapter.cpp b/services/backup_sa/src/module_external/bms_adapter.cpp index e9af164e7..2f57d4141 100644 --- a/services/backup_sa/src/module_external/bms_adapter.cpp +++ b/services/backup_sa/src/module_external/bms_adapter.cpp @@ -15,9 +15,6 @@ #include "module_external/bms_adapter.h" -#include -#include -#include #include #include "b_error/b_error.h" @@ -28,6 +25,7 @@ #include "filemgmt_libhilog.h" #include "install_param.h" #include "iservice_registry.h" +#include "module_external/inner_receiver_impl.h" #include "module_external/sms_adapter.h" #include "module_ipc/service.h" #include "module_ipc/svc_session_manager.h" @@ -108,4 +106,32 @@ vector BundleMgrAdapter::GetBundleInfos(const vecto } return bundleInfos; } + +ErrCode BundleMgrAdapter::Install(wptr statusReceiver, const string &bundleFilePath) +{ + HILOGI("Begin"); + auto bms = GetBundleManager(); + AppExecFwk::BundleInfo bundleInfo; + if (!bms->GetBundleArchiveInfo(bundleFilePath, AppExecFwk::BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo)) { + return BError(BError::Codes::SA_BROKEN_IPC, "Failed to get bundle archive info").GetCode(); + } + auto receiver = statusReceiver.promote(); + if (receiver == nullptr) { + return BError(BError::Codes::SA_BROKEN_IPC, "Failed to get receiver").GetCode(); + } + // check bundle name + if (bundleInfo.name != receiver->GetBundleName()) { + return BError(BError::Codes::SA_INVAL_ARG, "Bundle name is not match").GetCode(); + } + + auto install = bms->GetBundleInstaller(); + if (!install) { + return BError(BError::Codes::SA_BROKEN_IPC, "Failed to get bundle installer").GetCode(); + } + + AppExecFwk::InstallParam installParam; + installParam.installFlag = AppExecFwk::InstallFlag::REPLACE_EXISTING; + installParam.userId = AppExecFwk::Constants::START_USERID; + return install->StreamInstall({bundleFilePath}, installParam, receiver); +} } // namespace OHOS::FileManagement::Backup diff --git a/services/backup_sa/src/module_external/inner_receiver_impl.cpp b/services/backup_sa/src/module_external/inner_receiver_impl.cpp new file mode 100644 index 000000000..039159798 --- /dev/null +++ b/services/backup_sa/src/module_external/inner_receiver_impl.cpp @@ -0,0 +1,44 @@ +/* + * 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_external/inner_receiver_impl.h" + +#include "b_error/b_error.h" +#include "filemgmt_libhilog.h" +#include "module_ipc/svc_session_manager.h" +#include "module_sched/sched_scheduler.h" +#include "module_ipc/service.h" + +namespace OHOS::FileManagement::Backup { +void InnerReceiverImpl::OnStatusNotify(const int progress) +{ + HILOGI("OnStatusNotify %{public}d", progress); +} +void InnerReceiverImpl::OnFinished(const int32_t resultCode, const std::string &resultMsg) +{ + HILOGI("Finished to install %{public}s, resultCode = %{public}d resultMsg = %{public}s", bundleName_.c_str(), + resultCode, resultMsg.c_str()); + + auto sched = sched_.promote(); + if (sched == nullptr) { + throw BError(BError::Codes::SA_INVAL_ARG, std::string("Failed to promote bundleContext")); + } + sched->InstallSuccess(bundleName_, resultCode); +} +std::string InnerReceiverImpl::GetBundleName() +{ + return bundleName_; +} +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/services/backup_sa/src/module_ipc/service.cpp b/services/backup_sa/src/module_ipc/service.cpp index 2060897ca..718a40409 100644 --- a/services/backup_sa/src/module_ipc/service.cpp +++ b/services/backup_sa/src/module_ipc/service.cpp @@ -74,16 +74,16 @@ void Service::OnStop() UniqueFd Service::GetLocalCapabilities() { try { + HILOGI("Begin"); VerifyCaller(); - struct statfs fsInfo = {}; - if (statfs(BConstants::SA_BUNDLE_BACKUP_ROOT_DIR.data(), &fsInfo) == -1) { - throw BError(errno); - } - BJsonCachedEntity cachedEntity( UniqueFd(open(BConstants::SA_BUNDLE_BACKUP_ROOT_DIR.data(), O_TMPFILE | O_RDWR, 0600))); auto cache = cachedEntity.Structuralize(); + + cache.SetSystemFullName(GetOSFullName()); cache.SetDeviceType(GetDeviceType()); + auto bundleInfos = BundleMgrAdapter::GetBundleInfos(); + cache.SetBundleInfos(bundleInfos); cachedEntity.Persist(); return move(cachedEntity.GetFd()); @@ -213,7 +213,21 @@ ErrCode Service::AppendBundlesRestoreSession(UniqueFd fd, const vectorGetScenario()); + BJsonCachedEntity cachedEntity(move(fd)); + auto cache = cachedEntity.Structuralize(); + auto bundleInfos = cache.GetBundleInfos(); + if (!bundleInfos.size()) { + throw BError(BError::Codes::SA_INVAL_ARG, "Json entity caps is empty"); + } session_->AppendBundles(bundleNames); + for (auto bundleName : bundleNames) { + for (auto &&bundleInfo : bundleInfos) { + if (bundleInfo.name != bundleName) { + continue; + } + session_->SetNeedToInstall(bundleInfo.name, bundleInfo.needToInstall); + } + } Start(); Finish(); OnStartSched(); @@ -246,6 +260,11 @@ ErrCode Service::PublishFile(const BFileInfo &fileInfo) HILOGI("Begin"); VerifyCaller(IServiceReverse::Scenario::RESTORE); + if (fileInfo.fileName == BConstants::RESTORE_INSTALL_PATH) { + session_->SetInstallState(fileInfo.owner, "OK"); + sched_->Sched(fileInfo.owner); + return BError(BError::Codes::OK); + } if (!regex_match(fileInfo.fileName, regex("^[0-9a-zA-Z_.]+$"))) { throw BError(BError::Codes::SA_INVAL_ARG, "Filename is not alphanumeric"); } @@ -386,11 +405,21 @@ ErrCode Service::GetFileHandle(const string &bundleName, const string &fileName) try { HILOGI("Begin"); VerifyCaller(IServiceReverse::Scenario::RESTORE); + if (fileName == BConstants::RESTORE_INSTALL_PATH && regex_match(bundleName, regex("^[0-9a-zA-Z_.]+$"))) { + session_->SetInstallState(bundleName, string(BConstants::RESTORE_INSTALL_PATH)); + auto action = session_->GetServiceSchedAction(bundleName); + if (action == BConstants::ServiceSchedAction::INSTALLING) { + sched_->Sched(bundleName); + } + return BError(BError::Codes::OK); + } + if (!regex_match(fileName, regex("^[0-9a-zA-Z_.]+$"))) { + throw BError(BError::Codes::SA_INVAL_ARG, "Filename is not alphanumeric"); + } session_->SetExtFileNameRequest(bundleName, fileName); auto action = session_->GetServiceSchedAction(bundleName); if (action == BConstants::ServiceSchedAction::RUNNING) { sched_->Sched(bundleName); - return BError(BError::Codes::OK); } return BError(BError::Codes::OK); } catch (const BError &e) { 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 f7663495a..93bed6437 100644 --- a/services/backup_sa/src/module_ipc/svc_session_manager.cpp +++ b/services/backup_sa/src/module_ipc/svc_session_manager.cpp @@ -18,10 +18,13 @@ #include #include #include +#include #include #include #include "b_error/b_error.h" +#include "b_file_info.h" +#include "b_json/b_json_entity_caps.h" #include "b_json/b_json_entity_ext_manage.h" #include "b_resources/b_constants.h" #include "filemgmt_libhilog.h" @@ -339,7 +342,7 @@ void SvcSessionManager::SetServiceSchedAction(const string &bundleName, BConstan auto it = GetBackupExtNameMap(bundleName); it->second.schedAction = action; - if (it->second.schedAction == BConstants::ServiceSchedAction::START) { + if (it->second.schedAction == BConstants::ServiceSchedAction::INSTALLING) { extConnectNum_++; } } @@ -351,8 +354,19 @@ string SvcSessionManager::GetBackupExtName(const string &bundleName) if (!impl_.clientToken) { throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); } - auto it = GetBackupExtNameMap(bundleName); - return it->second.backupExtName; + string name = bundleName; + VerifyBundleName(name); + auto bundleInfos = BundleMgrAdapter::GetBundleInfos({bundleName}); + for (auto &&bundleInfo : bundleInfos) { + if (!bundleInfo.allToBackup || bundleInfo.extensionName.empty()) { + throw BError(BError::Codes::SA_INVAL_ARG, + string(bundleInfo.name).append(" is not allow to backup or extension name is empty")); + } + if (bundleInfo.name == bundleName) { + return bundleInfo.extensionName; + } + } + throw BError(BError::Codes::SA_INVAL_ARG, "Could not find the extension name"); } void SvcSessionManager::AppendBundles(const vector &bundleNames) @@ -362,18 +376,11 @@ void SvcSessionManager::AppendBundles(const vector &bundleNames) if (!impl_.clientToken) { throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); } - - auto bundleInfos = BundleMgrAdapter::GetBundleInfos(bundleNames); - for (auto &&bundleInfo : bundleInfos) { - if (!bundleInfo.allToBackup || bundleInfo.extensionName.empty()) { - throw BError(BError::Codes::SA_INVAL_ARG, - string(bundleInfo.name).append(" is not allow to backup or extension name is empty")); - } + + for (auto &&bundleName : bundleNames) { BackupExtInfo info {}; - info.backupExtName = bundleInfo.extensionName; - info.backUpConnection = GetBackupExtAbility(bundleInfo.name); - - impl_.backupExtNameMap.insert(make_pair(bundleInfo.name, info)); + info.backUpConnection = GetBackupExtAbility(bundleName); + impl_.backupExtNameMap.insert(make_pair(bundleName, info)); } } @@ -423,4 +430,52 @@ bool SvcSessionManager::IsOnOnStartSched() return false; } + +void SvcSessionManager::SetInstallState(const string &bundleName, const string &state) +{ + HILOGI("Begin"); + unique_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + + auto it = GetBackupExtNameMap(bundleName); + it->second.installState = state; +} + +string SvcSessionManager::GetInstallState(const string &bundleName) +{ + HILOGI("Begin"); + unique_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + + auto it = GetBackupExtNameMap(bundleName); + return it->second.installState; +} + +void SvcSessionManager::SetNeedToInstall(const std::string &bundleName, bool needToInstall) +{ + HILOGI("Begin"); + unique_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + + auto it = GetBackupExtNameMap(bundleName); + it->second.bNeedToInstall = needToInstall; +} + +bool SvcSessionManager::GetNeedToInstall(const std::string &bundleName) +{ + HILOGI("Begin"); + unique_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + + auto it = GetBackupExtNameMap(bundleName); + return it->second.bNeedToInstall; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/services/backup_sa/src/module_sched/sched_scheduler.cpp b/services/backup_sa/src/module_sched/sched_scheduler.cpp index 9257b89f6..e54e26a23 100644 --- a/services/backup_sa/src/module_sched/sched_scheduler.cpp +++ b/services/backup_sa/src/module_sched/sched_scheduler.cpp @@ -20,8 +20,15 @@ #include #include +#include + +#include +#include + #include "b_error/b_error.h" #include "filemgmt_libhilog.h" +#include "module_external/bms_adapter.h" +#include "module_external/inner_receiver_impl.h" #include "module_ipc/service.h" #include "module_ipc/svc_session_manager.h" @@ -36,7 +43,7 @@ void SchedScheduler::Sched(string bundleName) } BConstants::ServiceSchedAction action = sessionPtr_->GetServiceSchedAction(bundleName); if (action == BConstants::ServiceSchedAction::WAIT) { - sessionPtr_->SetServiceSchedAction(bundleName, BConstants::ServiceSchedAction::START); + sessionPtr_->SetServiceSchedAction(bundleName, BConstants::ServiceSchedAction::INSTALLING); } } HILOGE("Sched bundleName %{public}s", bundleName.data()); @@ -58,6 +65,7 @@ void SchedScheduler::Sched(string bundleName) void SchedScheduler::ExecutingQueueTasks(const string &bundleName) { HILOGE("start"); + InstallingState(bundleName); BConstants::ServiceSchedAction action = sessionPtr_->GetServiceSchedAction(bundleName); if (action == BConstants::ServiceSchedAction::START) { // 注册启动定时器 @@ -106,4 +114,51 @@ void SchedScheduler::RemoveExtConn(const string &bundleName) bundleTimeVec_.erase(iter); } } + +void SchedScheduler::InstallingState(const string &bundleName) +{ + BConstants::ServiceSchedAction action = sessionPtr_->GetServiceSchedAction(bundleName); + if (action == BConstants::ServiceSchedAction::INSTALLING) { + IServiceReverse::Scenario scenario = sessionPtr_->GetScenario(); + if (scenario == IServiceReverse::Scenario::BACKUP || !sessionPtr_->GetNeedToInstall(bundleName)) { + sessionPtr_->SetServiceSchedAction(bundleName, BConstants::ServiceSchedAction::START); + return; + } + string state = sessionPtr_->GetInstallState(bundleName); + string path = string(BConstants::SA_BUNDLE_BACKUP_ROOT_DIR).append(bundleName); + string filePath = path + "/bundle.hap"; + if (state == BConstants::RESTORE_INSTALL_PATH) { + if (!ForceCreateDirectory(path)) { + throw BError(BError::Codes::SA_INVAL_ARG, string("Failed to create directory")); + } + sessionPtr_->GetServiceReverseProxy()->RestoreOnFileReady( + bundleName, state, + UniqueFd(open(filePath.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IROTH))); + } else if (state == "OK") { + if (access(filePath.data(), F_OK) != 0) { + throw BError(BError::Codes::SA_INVAL_ARG, string("File already exists")); + } + sptr statusReceiver = sptr(new InnerReceiverImpl(bundleName, wptr(this))); + ErrCode err = BundleMgrAdapter::Install(statusReceiver, filePath); + if (err != ERR_OK) { + InstallSuccess(bundleName, err); + } + } + } +} + +void SchedScheduler::InstallSuccess(const std::string &bundleName, const int32_t resultCode) +{ + if (!resultCode) { + sessionPtr_->SetServiceSchedAction(bundleName, BConstants::ServiceSchedAction::START); + Sched(bundleName); + } else { + sessionPtr_->GetServiceReverseProxy()->RestoreOnBundleStarted(resultCode, bundleName); + sessionPtr_->RemoveExtInfo(bundleName); + } + string path = string(BConstants::SA_BUNDLE_BACKUP_ROOT_DIR).append(bundleName); + if (!ForceRemoveDirectory(path)) { + HILOGE("RemoveDirectory failed"); + } +} }; // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tools/backup_tool/src/tools_op_restore.cpp b/tools/backup_tool/src/tools_op_restore.cpp index 419e315f3..64a6ad29c 100644 --- a/tools/backup_tool/src/tools_op_restore.cpp +++ b/tools/backup_tool/src/tools_op_restore.cpp @@ -33,6 +33,7 @@ #include "b_error/b_error.h" #include "b_filesystem/b_dir.h" #include "b_filesystem/b_file.h" +#include "b_json/b_json_entity_caps.h" #include "b_json/b_json_entity_ext_manage.h" #include "b_resources/b_constants.h" #include "backup_kit_inner.h" @@ -129,10 +130,17 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq { printf("FileReady owner = %s, fileName = %s, sn = %u, fd = %d\n", fileInfo.owner.c_str(), fileInfo.fileName.c_str(), fileInfo.sn, fd.Get()); - if (!regex_match(fileInfo.fileName, regex("^[0-9a-zA-Z_.]+$"))) { + if (!regex_match(fileInfo.fileName, regex("^[0-9a-zA-Z_.]+$")) && + fileInfo.fileName != BConstants::RESTORE_INSTALL_PATH) { throw BError(BError::Codes::TOOL_INVAL_ARG, "Filename is not alphanumeric"); } - string tmpPath = string(BConstants::BACKUP_TOOL_RECEIVE_DIR) + fileInfo.owner + "/" + fileInfo.fileName; + string tmpPath; + if (fileInfo.fileName == BConstants::RESTORE_INSTALL_PATH) { + printf("OnFileReady bundle hap\n"); + tmpPath = string(BConstants::BACKUP_TOOL_INSTALL_DIR) + fileInfo.owner + ".hap"; + } else { + tmpPath = string(BConstants::BACKUP_TOOL_RECEIVE_DIR) + fileInfo.owner + "/" + fileInfo.fileName; + } if (access(tmpPath.data(), F_OK) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } @@ -145,7 +153,9 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq if (ret != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, "PublishFile error"); } - ctx->UpdateBundleSentFiles(fileInfo.owner, fileInfo.fileName); + if (fileInfo.fileName != BConstants::RESTORE_INSTALL_PATH) { + ctx->UpdateBundleSentFiles(fileInfo.owner, fileInfo.fileName); + } ctx->TryNotify(); } @@ -207,6 +217,12 @@ static void RestoreApp(shared_ptr restore, vector &bundleNa if (err != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, "error path"); } + // install bundle.hap + string installPath = string(BConstants::BACKUP_TOOL_INSTALL_DIR) + bundleName + ".hap"; + if (access(installPath.data(), F_OK) == 0) { + printf("install bundle hap %s\n", installPath.c_str()); + restore->session_->GetFileHandle(bundleName, string(BConstants::RESTORE_INSTALL_PATH)); + } for (auto &filePath : filePaths) { string fileName = filePath.substr(filePath.rfind("/") + 1); restore->session_->GetFileHandle(bundleName, fileName); @@ -220,18 +236,26 @@ static int32_t InitPathCapFile(const string &pathCapFile, vector bundleN { StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Init"); - UniqueFd fd(open(pathCapFile.data(), O_RDWR | O_CREAT, S_IRWXU)); + UniqueFd fd(open(pathCapFile.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)); if (fd < 0) { fprintf(stderr, "Failed to open file error: %d %s\n", errno, strerror(errno)); FinishTrace(HITRACE_TAG_FILEMANAGEMENT); return -errno; } - auto proxy = ServiceProxy::GetInstance(); - if (!proxy) { - fprintf(stderr, "Get an empty backup sa proxy\n"); - return -EFAULT; + + BJsonCachedEntity cachedEntity(move(fd)); + auto cache = cachedEntity.Structuralize(); + vector bundleInfos; + for (auto name : bundleNames) { + string installPath = string(BConstants::BACKUP_TOOL_INSTALL_DIR) + name + ".hap"; + bool needToInstall = false; + if (access(installPath.data(), F_OK) == 0) { + needToInstall = true; + } + bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {.name = name, .needToInstall = needToInstall}); } - BFile::SendFile(fd, proxy->GetLocalCapabilities()); + cache.SetBundleInfos(bundleInfos); + cachedEntity.Persist(); auto ctx = make_shared(); ctx->session_ = BSessionRestore::Init( @@ -245,7 +269,7 @@ static int32_t InitPathCapFile(const string &pathCapFile, vector bundleN FinishTrace(HITRACE_TAG_FILEMANAGEMENT); return -EPERM; } - int ret = ctx->session_->AppendBundles(move(fd), bundleNames); + int ret = ctx->session_->AppendBundles(move(cachedEntity.GetFd()), bundleNames); if (ret != 0) { printf("restore append bundles error: %d", ret); throw BError(BError::Codes::TOOL_INVAL_ARG, "restore append bundles error"); diff --git a/utils/include/b_json/b_json_entity_caps.h b/utils/include/b_json/b_json_entity_caps.h index 6a104f78a..9ab7bc212 100644 --- a/utils/include/b_json/b_json_entity_caps.h +++ b/utils/include/b_json/b_json_entity_caps.h @@ -29,54 +29,80 @@ public: int64_t spaceOccupied; bool allToBackup; std::string extensionName; + bool needToInstall {false}; }; public: - uint64_t GetFreeDiskSpace() + void SetSystemFullName(std::string systemFullName) { - if (!obj_ || !obj_.isMember("freeDiskSpace") || !obj_["freeDiskSpace"].isUInt64()) { - HILOGE("Failed to init field FreeDiskSpace"); - return 0; - } - - return obj_["freeDiskSpace"].asUInt64(); - } - - void SetFreeDiskSpace(uint64_t freeDiskSpace) - { - obj_["freeDiskSpace"] = freeDiskSpace; + obj_["systemFullName"] = systemFullName; } - void SetOSFullName(std::string osFullName) + void SetDeviceType(std::string deviceType) { - obj_["OSFullName"] = osFullName; + obj_["deviceType"] = deviceType; } - void SetDeviceType(std::string deviceType) + void SetBundleInfos(std::vector bundleInfos) { - obj_["deviceType"] = deviceType; + if (obj_.isMember("bundleInfos")) { + obj_["bundleInfos"].clear(); + } + for (const auto &item : bundleInfos) { + Json::Value arrObj; + arrObj["name"] = item.name; + arrObj["versionCode"] = item.versionCode; + arrObj["versionName"] = item.versionName; + arrObj["spaceOccupied"] = item.spaceOccupied; + arrObj["allToBackup"] = item.allToBackup; + arrObj["extensionName"] = item.extensionName; + arrObj["needToInstall"] = item.needToInstall; + obj_["bundleInfos"].append(arrObj); + } } - std::string GetOSFullName() + std::string GetSystemFullName() { - if (!obj_ || !obj_.isMember("OSFullName") || !obj_["OSFullName"].isString()) { - HILOGE("Failed to get field OSFullName"); + if (!obj_ || !obj_.isMember("systemFullName") || !obj_["systemFullName"].isString()) { + HILOGI("Failed to get field systemFullName"); return ""; } - return obj_["OSFullName"].asString(); + return obj_["systemFullName"].asString(); } std::string GetDeviceType() { if (!obj_ || !obj_.isMember("deviceType") || !obj_["deviceType"].isString()) { - HILOGE("Failed to get field deviceType"); + HILOGI("Failed to get field deviceType"); return ""; } return obj_["deviceType"].asString(); } + std::vector GetBundleInfos() + { + if (!obj_ || !obj_.isMember("bundleInfos") || !obj_["bundleInfos"].isArray()) { + HILOGI("Failed to get field get bundleInfos"); + return {}; + } + std::vector bundleInfos; + 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()) { + 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()}); + } + return bundleInfos; + } + public: /** * @brief 构造方法,具备T(Json::Value&, std::any)能力的构造函数 @@ -86,7 +112,7 @@ public: */ explicit BJsonEntityCaps(Json::Value &obj, std::any option = std::any()) : BJsonEntity(obj, option) { - SetFreeDiskSpace(GetFreeDiskSpace()); + SetBundleInfos(GetBundleInfos()); } BJsonEntityCaps() = delete; diff --git a/utils/include/b_resources/b_constants.h b/utils/include/b_resources/b_constants.h index 7acbe234b..9a61caa0a 100644 --- a/utils/include/b_resources/b_constants.h +++ b/utils/include/b_resources/b_constants.h @@ -32,9 +32,10 @@ enum class ExtensionAction { enum ServiceSchedAction { WAIT = 0, - START = 1, - RUNNING = 2, - FINISH = 3, + INSTALLING = 1, + START, + RUNNING, + FINISH, }; enum EntryKey { @@ -111,6 +112,7 @@ static inline std::string_view BACKUP_TOOL_RECEIVE_DIR = "/data/backup/received/ static inline std::string_view PATH_BUNDLE_BACKUP_HOME = "/data/storage/el2/backup"; static inline std::string_view SA_BUNDLE_BACKUP_TOOL_DIR = "/data/service/el2/100/backup/backup_tool/"; static inline std::string_view BACKUP_TOOL_LINK_DIR = "/data/backup"; +static inline std::string_view BACKUP_TOOL_INSTALL_DIR = "/data/backup/install/"; // 备份恢复配置文件暂存路径 static inline std::string_view BACKUP_CONFIG_EXTENSION_PATH = "/data/storage/el2/base/temp/"; @@ -121,6 +123,9 @@ static inline std::string_view EXT_BACKUP_MANAGE = "manage.json"; // 包管理元数据配置文件 static inline std::string_view BACKUP_CONFIG_JSON = "backup_config.json"; +// 恢复应用安装包路径 +static inline std::string_view RESTORE_INSTALL_PATH = "/data/storage/el2/restore/bundle.hap"; + // 应用默认备份的目录,其均为相对根路径的路径。为避免模糊匹配,务必以斜线为结尾。 static inline std::array PATHES_TO_BACKUP = { "data/storage/el2/database/", diff --git a/utils/src/b_filesystem/b_file.cpp b/utils/src/b_filesystem/b_file.cpp index e653b32bc..aa8c36370 100644 --- a/utils/src/b_filesystem/b_file.cpp +++ b/utils/src/b_filesystem/b_file.cpp @@ -73,6 +73,10 @@ void BFile::SendFile(int outFd, int inFd) if (ret == -1) { throw BError(errno); } + ret = ftruncate(outFd, offset); + if (ret == -1) { + throw BError(errno); + } } void BFile::Write(const UniqueFd &fd, const string &str) diff --git a/utils/src/b_json/b_json_entity_ext_manage.cpp b/utils/src/b_json/b_json_entity_ext_manage.cpp index 79fef1a72..9d5ccca90 100644 --- a/utils/src/b_json/b_json_entity_ext_manage.cpp +++ b/utils/src/b_json/b_json_entity_ext_manage.cpp @@ -18,7 +18,9 @@ #include #include +#include "b_error/b_error.h" #include "b_json/b_json_entity_ext_manage.h" +#include "b_resources/b_constants.h" #include "filemgmt_libhilog.h" #include "json/value.h" @@ -91,6 +93,9 @@ void BJsonEntityExtManage::SetExtManage(const mapfirst; + if (item->second.first == BConstants::RESTORE_INSTALL_PATH) { + throw BError(BError::Codes::UTILS_INVAL_JSON_ENTITY, "Failed to set ext manage, invalid path"); + } value["information"]["path"] = item->second.first; value["information"]["stat"] = Stat2JsonValue(item->second.second); set lks = FindLinks(item, index); @@ -142,6 +147,9 @@ map> BJsonEntityExtManage::GetExtManageInfo() struct stat sta = {}; string path = item["information"].isMember("path") ? item["information"]["path"].asString() : ""; + if (path == BConstants::RESTORE_INSTALL_PATH) { + throw BError(BError::Codes::UTILS_INVAL_JSON_ENTITY, "Failed to get ext manage info, invalid path"); + } if (item["information"].isMember("stat")) { sta = JsonValue2Stat(item["information"]["stat"]); } -- Gitee