From 3eb55cc50604a0e0e4d2fbebd2f4b22a9385cc17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=99=9F=E9=92=B0?= Date: Wed, 11 Sep 2024 17:38:56 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8Duser0=E5=A4=87=E4=BB=BD?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 张晟钰 --- .../native/backup_ext/include/ext_extension.h | 9 + .../backup_ext/include/ext_extension_stub.h | 1 + .../native/backup_ext/src/ext_extension.cpp | 167 +++++++++++++--- .../backup_ext/src/ext_extension_stub.cpp | 12 ++ .../backup_kit_inner/impl/i_extension.h | 1 + .../impl/i_extension_ipc_interface_code.h | 1 + .../include/module_external/bms_adapter.h | 2 + .../backup_sa/include/module_ipc/service.h | 18 ++ .../include/module_ipc/svc_extension_proxy.h | 1 + .../src/module_external/bms_adapter.cpp | 15 ++ services/backup_sa/src/module_ipc/service.cpp | 11 +- .../src/module_ipc/service_incremental.cpp | 41 ++++ .../svc_extension_incremental_proxy.cpp | 21 ++ .../mock/module_external/bms_adapter_mock.cpp | 5 + .../module_ipc/svc_extension_proxy_mock.cpp | 5 + .../backup_impl/include/ext_extension_mock.h | 5 + .../backup_ext/ext_extension_stub_test.cpp | 33 ++++ utils/include/b_filesystem/b_dir.h | 27 +++ utils/include/b_jsonutil/b_jsonutil.h | 24 ++- utils/include/b_resources/b_constants.h | 3 + utils/src/b_filesystem/b_dir.cpp | 186 +++++++++++++++++- utils/src/b_jsonutil/b_jsonutil.cpp | 173 ++++++++++++++-- 22 files changed, 708 insertions(+), 53 deletions(-) diff --git a/frameworks/native/backup_ext/include/ext_extension.h b/frameworks/native/backup_ext/include/ext_extension.h index 11dbc6557..41b9b1ff8 100644 --- a/frameworks/native/backup_ext/include/ext_extension.h +++ b/frameworks/native/backup_ext/include/ext_extension.h @@ -57,6 +57,7 @@ public: void AsyncTaskRestoreForUpgrade(void); void ExtClear(void); void AsyncTaskIncrementalRestoreForUpgrade(void); + ErrCode User0OnBackup() override; public: explicit BackupExtExtension(const std::shared_ptr &extension, @@ -161,6 +162,14 @@ private: void AsyncTaskOnBackup(); + bool IfAllowToBackupRestore(); + + void AsyncTaskUser0Backup(); + + void DoUser0Backup(const BJsonEntityExtensionConfig &usrConfig); + + int User0DoBackup(const BJsonEntityExtensionConfig &usrConfig); + int DoIncrementalBackup(const std::vector &allFiles, const std::vector &smallFiles, const std::vector &bigFiles); diff --git a/frameworks/native/backup_ext/include/ext_extension_stub.h b/frameworks/native/backup_ext/include/ext_extension_stub.h index 86949011a..d969b3e9b 100644 --- a/frameworks/native/backup_ext/include/ext_extension_stub.h +++ b/frameworks/native/backup_ext/include/ext_extension_stub.h @@ -43,6 +43,7 @@ private: ErrCode CmdGetIncrementalBackupFileHandle(MessageParcel &data, MessageParcel &reply); ErrCode CmdGetBackupInfo(MessageParcel &data, MessageParcel &reply); ErrCode CmdUpdateFdSendRate(MessageParcel &data, MessageParcel &reply); + ErrCode CmdHandleUser0Backup(MessageParcel &data, MessageParcel &reply); private: using ExtensionInterface = int32_t (ExtExtensionStub::*)(MessageParcel &data, MessageParcel &reply); diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index a73d7bf8c..e96eb551e 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -528,15 +528,7 @@ ErrCode BackupExtExtension::HandleBackup(bool isClearData) { HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); SetClearDataFlag(isClearData); - if (extension_ == nullptr) { - HILOGE("Failed to handle backup, extension is nullptr"); - return BError(BError::Codes::EXT_INVAL_ARG, "Extension is nullptr").GetCode(); - } - string usrConfig = extension_->GetUsrConfig(); - BJsonCachedEntity cachedEntity(usrConfig); - auto cache = cachedEntity.Structuralize(); - if (!cache.GetAllowToBackupRestore()) { - HILOGE("Application does not allow backup or restore"); + if (!IfAllowToBackupRestore()) { return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore") .GetCode(); } @@ -952,8 +944,8 @@ ErrCode BackupExtExtension::RestoreFilesForSpecialCloneCloud() HILOGE("Failed to delete the backup index %{public}s", INDEX_FILE_RESTORE.c_str()); } auto endTime = std::chrono::system_clock::now(); - radarRestoreInfo_.totalFileSpendTime = - std::chrono::duration_cast(endTime - startTime).count(); + radarRestoreInfo_.totalFileSpendTime = static_cast( + std::chrono::duration_cast(endTime - startTime).count()); RecordDoRestoreRes(bundleName_, "BackupExtExtension::RestoreFilesForSpecialCloneCloud", radarRestoreInfo_); HILOGI("End do restore for SpecialCloneCloud."); return ERR_OK; @@ -1045,7 +1037,8 @@ void BackupExtExtension::RestoreBigFiles(bool appendTargetPath) RestoreBigFileAfter(filePath, item.sta); } auto end = std::chrono::system_clock::now(); - radarRestoreInfo_.bigFileSpendTime = std::chrono::duration_cast(end - start).count(); + radarRestoreInfo_.bigFileSpendTime = + static_cast(std::chrono::duration_cast(end - start).count()); HILOGI("End Restore Big Files"); } @@ -1208,8 +1201,8 @@ void BackupExtExtension::AsyncTaskIncrementalRestore() // delete 1.tar/manage.json ptr->DeleteBackupIncrementalTars(); auto endTime = std::chrono::system_clock::now(); - ptr->radarRestoreInfo_.totalFileSpendTime = - std::chrono::duration_cast(endTime - startTime).count(); + ptr->radarRestoreInfo_.totalFileSpendTime = static_cast( + std::chrono::duration_cast(endTime - startTime).count()); RecordDoRestoreRes(ptr->bundleName_, "BackupExtExtension::AsyncTaskIncrementalRestore", ptr->radarRestoreInfo_); if (ret == ERR_OK) { @@ -1637,15 +1630,7 @@ ErrCode BackupExtExtension::HandleIncrementalBackup(UniqueFd incrementalFd, Uniq HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); try { HILOGI("Start HandleIncrementalBackup"); - if (extension_ == nullptr) { - HILOGE("Failed to handle incremental backup, extension is nullptr"); - return BError(BError::Codes::EXT_INVAL_ARG, "Extension is nullptr").GetCode(); - } - string usrConfig = extension_->GetUsrConfig(); - BJsonCachedEntity cachedEntity(usrConfig); - auto cache = cachedEntity.Structuralize(); - if (!cache.GetAllowToBackupRestore()) { - HILOGE("Application does not allow backup or restore"); + if (!IfAllowToBackupRestore()) { return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore") .GetCode(); } @@ -1661,15 +1646,7 @@ ErrCode BackupExtExtension::IncrementalOnBackup(bool isClearData) { HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); SetClearDataFlag(isClearData); - if (extension_ == nullptr) { - HILOGE("Failed to handle incremental onBackup, extension is nullptr"); - return BError(BError::Codes::EXT_INVAL_ARG, "Extension is nullptr").GetCode(); - } - string usrConfig = extension_->GetUsrConfig(); - BJsonCachedEntity cachedEntity(usrConfig); - auto cache = cachedEntity.Structuralize(); - if (!cache.GetAllowToBackupRestore()) { - HILOGE("Application does not allow backup or restore"); + if (!IfAllowToBackupRestore()) { return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore") .GetCode(); } @@ -2050,4 +2027,130 @@ int BackupExtExtension::DoIncrementalBackup(const vector smallFiles.size(), allFiles.size()); return err; } + +bool BackupExtExtension::IfAllowToBackupRestore() +{ + if (extension_ == nullptr) { + HILOGE("Failed to handle backup, extension is nullptr"); + return false; + } + string usrConfig = extension_->GetUsrConfig(); + BJsonCachedEntity cachedEntity(usrConfig); + auto cache = cachedEntity.Structuralize(); + if (!cache.GetAllowToBackupRestore()) { + HILOGE("Application does not allow backup or restore"); + return false; + } + return true; +} + +ErrCode BackupExtExtension::User0OnBackup() +{ + HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); + if (!IfAllowToBackupRestore()) { + return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore") + .GetCode(); + } + AsyncTaskUser0Backup(); + return ERR_OK; +} + +void BackupExtExtension::AsyncTaskUser0Backup() +{ + HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); + auto task = [obj {wptr(this)}]() { + auto ptr = obj.promote(); + BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released"); + const string config = ptr->extension_->GetUsrConfig(); + try { + HILOGI("Do backup, start fwk timer begin."); + bool isFwkStart; + ptr->StartFwkTimer(isFwkStart); + if (!isFwkStart) { + HILOGE("Do backup, start fwk timer fail."); + return; + } + HILOGI("Do backup, start fwk timer end."); + BJsonCachedEntity cachedEntity(config); + auto cache = cachedEntity.Structuralize(); + auto ret = ptr->User0DoBackup(cache); + if (ret != ERR_OK) { + HILOGE("User0DoBackup, err = %{pubilc}d", ret); + ptr->AppIncrementalDone(BError::GetCodeByErrno(ret)); + } + } catch (const BError &e) { + HILOGE("extension: AsyncTaskBackup error, err code:%{public}d", e.GetCode()); + ptr->AppIncrementalDone(e.GetCode()); + } catch (const exception &e) { + HILOGE("Catched an unexpected low-level exception %{public}s", e.what()); + ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode()); + } catch (...) { + HILOGE("Failed to restore the ext bundle"); + ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode()); + } + }; + + threadPool_.AddTask([task]() { + try { + task(); + } catch (...) { + HILOGE("Failed to add task to thread pool"); + } + }); +} + +void BackupExtExtension::DoUser0Backup(const BJsonEntityExtensionConfig &usrConfig) +{ + HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); + string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP); + if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) { + throw BError(errno); + } + vector includes = usrConfig.GetIncludes(); + vector excludes = usrConfig.GetExcludes(); + auto task = [obj {wptr(this)}, includes, excludes]() { + auto ptr = obj.promote(); + BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released"); + try { + auto [bigFile, smallFile] = BDir::GetBackupList(includes, excludes); + vector allFiles; + vector smallFiles; + vector bigFiles; + BDir::GetUser0FileStat(move(bigFile), move(smallFile), allFiles, smallFiles, bigFiles); + auto ret = ptr->DoIncrementalBackup(allFiles, smallFiles, bigFiles); + ptr->AppIncrementalDone(ret); + HILOGI("User0 backup app done %{public}d", ret); + } catch (const BError &e) { + ptr->AppIncrementalDone(e.GetCode()); + } catch (const exception &e) { + ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode()); + } catch (...) { + HILOGE("Failed to restore the ext bundle"); + ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode()); + } + }; + + threadPool_.AddTask([task]() { + try { + task(); + } catch (...) { + HILOGE("Failed to add task to thread pool"); + } + }); +} + +int BackupExtExtension::User0DoBackup(const BJsonEntityExtensionConfig &usrConfig) +{ + HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); + HILOGI("Start Do User0Backup"); + if (extension_ == nullptr) { + HILOGE("Failed to do backup, extension is nullptr"); + return BError(BError::Codes::EXT_INVAL_ARG); + } + if (extension_->GetExtensionAction() != BConstants::ExtensionAction::BACKUP) { + return EPERM; + } + DoUser0Backup(usrConfig); + return ERR_OK; +} } // namespace OHOS::FileManagement::Backup diff --git a/frameworks/native/backup_ext/src/ext_extension_stub.cpp b/frameworks/native/backup_ext/src/ext_extension_stub.cpp index 1589df3b4..9e7b43539 100644 --- a/frameworks/native/backup_ext/src/ext_extension_stub.cpp +++ b/frameworks/native/backup_ext/src/ext_extension_stub.cpp @@ -51,6 +51,8 @@ ExtExtensionStub::ExtExtensionStub() &ExtExtensionStub::CmdIncrementalOnBackup; opToInterfaceMap_[static_cast(IExtensionInterfaceCode::CMD_UPDATE_FD_SENDRATE)] = &ExtExtensionStub::CmdUpdateFdSendRate; + opToInterfaceMap_[static_cast(IExtensionInterfaceCode::CMD_HANDLE_USER_0_BACKUP)] = + &ExtExtensionStub::CmdHandleUser0Backup; } int32_t ExtExtensionStub::OnRemoteRequest(uint32_t code, @@ -245,4 +247,14 @@ ErrCode ExtExtensionStub::CmdUpdateFdSendRate(MessageParcel &data, MessageParcel } return BError(BError::Codes::OK); } + +ErrCode ExtExtensionStub::CmdHandleUser0Backup(MessageParcel &data, MessageParcel &reply) +{ + HILOGD("CmdHandleUser0Backup Begin"); + int ret = User0OnBackup(); + if (!reply.WriteInt32(ret)) { + return BError(BError::Codes::EXT_BROKEN_IPC, "Failed to send out the ret").GetCode(); + } + return BError(BError::Codes::OK); +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/i_extension.h b/interfaces/inner_api/native/backup_kit_inner/impl/i_extension.h index 387ec3b0e..a20fb4cdd 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/i_extension.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/i_extension.h @@ -40,6 +40,7 @@ public: virtual std::tuple GetIncrementalBackupFileHandle() = 0; virtual ErrCode GetBackupInfo(std::string &result) = 0; virtual ErrCode UpdateFdSendRate(std::string &bundleName, int32_t sendRate) = 0; + virtual ErrCode User0OnBackup() = 0; }; } // namespace OHOS::FileManagement::Backup diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/i_extension_ipc_interface_code.h b/interfaces/inner_api/native/backup_kit_inner/impl/i_extension_ipc_interface_code.h index 15478e015..40c2f1208 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/i_extension_ipc_interface_code.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/i_extension_ipc_interface_code.h @@ -31,6 +31,7 @@ enum class IExtensionInterfaceCode { CMD_GET_BACKUP_INFO, CMD_INCREMENTAL_ON_BACKUP, CMD_UPDATE_FD_SENDRATE, + CMD_HANDLE_USER_0_BACKUP, }; } // namespace OHOS::FileManagement::Backup diff --git a/services/backup_sa/include/module_external/bms_adapter.h b/services/backup_sa/include/module_external/bms_adapter.h index 352363577..4e94ebfea 100644 --- a/services/backup_sa/include/module_external/bms_adapter.h +++ b/services/backup_sa/include/module_external/bms_adapter.h @@ -65,6 +65,8 @@ public: static std::vector GetBundleInfosForSA(); static void GetBundleInfoForSA(std::string bundleName, std::vector &bundleInfos); + + static bool IsUser0BundleName(std::string bundleName, int32_t userId); private: static bool GetCurBundleExtenionInfo(AppExecFwk::BundleInfo &installedBundle, const std::string &bundleName, std::vector &extensionInfos, sptr bms, diff --git a/services/backup_sa/include/module_ipc/service.h b/services/backup_sa/include/module_ipc/service.h index 0f5243666..040974d2b 100644 --- a/services/backup_sa/include/module_ipc/service.h +++ b/services/backup_sa/include/module_ipc/service.h @@ -376,6 +376,24 @@ private: std::vector &restoreBundleNames, RestoreTypeEnum restoreType); void SetCurrentSessProperties(BJsonEntityCaps::BundleInfo &info, std::map &isClearDataFlags); + + /** + * @brief add useridinfo to current backup session + * + * @param bundleNames: bundleNames list + * @param userId: userId + * + */ + void SetCurrentBackupSessProperties(const std::vector &bundleNames, int32_t userId); + + /** + * @brief send userid to app + * + * @param bundleName: bundleName + * @param userId: userId + * + */ + void SendUserIdToApp(std::string &bundleName, int32_t userId); /** * @brief 通知权限模块 diff --git a/services/backup_sa/include/module_ipc/svc_extension_proxy.h b/services/backup_sa/include/module_ipc/svc_extension_proxy.h index a20ef5112..4e5b9932a 100644 --- a/services/backup_sa/include/module_ipc/svc_extension_proxy.h +++ b/services/backup_sa/include/module_ipc/svc_extension_proxy.h @@ -35,6 +35,7 @@ public: std::tuple GetIncrementalBackupFileHandle() override; ErrCode GetBackupInfo(std::string &result) override; ErrCode UpdateFdSendRate(std::string &bundleName, int32_t sendRate) override; + ErrCode User0OnBackup() override; public: explicit SvcExtensionProxy(const sptr &remote) : IRemoteProxy(remote) {} diff --git a/services/backup_sa/src/module_external/bms_adapter.cpp b/services/backup_sa/src/module_external/bms_adapter.cpp index 7ba365a81..afd2f460c 100644 --- a/services/backup_sa/src/module_external/bms_adapter.cpp +++ b/services/backup_sa/src/module_external/bms_adapter.cpp @@ -500,4 +500,19 @@ bool BundleMgrAdapter::GetCurBundleExtenionInfo(AppExecFwk::BundleInfo &installe HILOGI("bundleName:%{public}s, extensionInfos size:%{public}zu", bundleName.c_str(), extensionInfos.size()); return true; } + +bool BundleMgrAdapter::IsUser0BundleName(std::string bundleName, int32_t userId) +{ + auto bms = GetBundleManager(); + AppExecFwk::BundleInfo installedBundle; + if (!bms->GetBundleInfo(bundleName, AppExecFwk::GET_BUNDLE_WITH_EXTENSION_INFO, installedBundle, userId)) { + throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get bundle infos"); + } + if (installedBundle.applicationInfo.singleton == true) { + HILOGI("bundleName:%{public}s is zero user bundle", bundleName.c_str()); + return true; + } + HILOGI("bundleName:%{public}s is not zero user bundle", bundleName.c_str()); + return false; +} } // namespace OHOS::FileManagement::Backup diff --git a/services/backup_sa/src/module_ipc/service.cpp b/services/backup_sa/src/module_ipc/service.cpp index ca646bca9..71c623458 100644 --- a/services/backup_sa/src/module_ipc/service.cpp +++ b/services/backup_sa/src/module_ipc/service.cpp @@ -461,12 +461,15 @@ ErrCode Service::AppendBundlesRestoreSession(UniqueFd fd, const vectorIncreaseSessionCnt(__PRETTY_FUNCTION__); if (userId != DEFAULT_INVAL_VALUE) { /* multi user scenario */ session_->SetSessionUserId(userId); + } else { + session_->SetSessionUserId(GetUserIdDefault()); } VerifyCaller(IServiceReverse::Scenario::RESTORE); std::vector bundleNamesOnly; std::map isClearDataFlags; std::map> bundleNameDetailMap = - BJsonUtil::BuildBundleInfos(bundleNames, bundleInfos, bundleNamesOnly, userId, isClearDataFlags); + BJsonUtil::BuildBundleInfos(bundleNames, bundleInfos, bundleNamesOnly, + session_->GetSessionUserId(), isClearDataFlags); auto restoreInfos = GetRestoreBundleNames(move(fd), session_, bundleNames); auto restoreBundleNames = SvcRestoreDepsManager::GetInstance().GetRestoreBundleNames(restoreInfos, restoreType); HandleExceptionOnAppendBundles(session_, bundleNames, restoreBundleNames); @@ -518,6 +521,9 @@ void Service::SetCurrentSessProperties(std::vector session_->SetBundleVersionName(restoreInfo.name, restoreInfo.versionName); session_->SetBundleDataSize(restoreInfo.name, restoreInfo.spaceOccupied); session_->SetBackupExtName(restoreInfo.name, restoreInfo.extensionName); + if (BundleMgrAdapter::IsUser0BundleName(restoreInfo.name, session_->GetSessionUserId())) { + SendUserIdToApp(restoreInfo.name, session_->GetSessionUserId()); + } } HILOGI("End"); } @@ -536,6 +542,8 @@ ErrCode Service::AppendBundlesRestoreSession(UniqueFd fd, session_->IncreaseSessionCnt(__PRETTY_FUNCTION__); if (userId != DEFAULT_INVAL_VALUE) { /* multi user scenario */ session_->SetSessionUserId(userId); + } else { + session_->SetSessionUserId(GetUserIdDefault()); } VerifyCaller(IServiceReverse::Scenario::RESTORE); auto restoreInfos = GetRestoreBundleNames(move(fd), session_, bundleNames); @@ -643,6 +651,7 @@ ErrCode Service::AppendBundlesBackupSession(const vector &bundleName VerifyCaller(IServiceReverse::Scenario::BACKUP); auto backupInfos = BundleMgrAdapter::GetBundleInfos(bundleNames, session_->GetSessionUserId()); session_->AppendBundles(bundleNames); + SetCurrentBackupSessProperties(bundleNames, session_->GetSessionUserId()); for (auto info : backupInfos) { session_->SetBundleDataSize(info.name, info.spaceOccupied); session_->SetBackupExtName(info.name, info.extensionName); diff --git a/services/backup_sa/src/module_ipc/service_incremental.cpp b/services/backup_sa/src/module_ipc/service_incremental.cpp index 0405cdda2..850f6247e 100644 --- a/services/backup_sa/src/module_ipc/service_incremental.cpp +++ b/services/backup_sa/src/module_ipc/service_incremental.cpp @@ -155,6 +155,15 @@ void Service::StartGetFdTask(std::string bundleName, wptr ptr) if (!proxy) { throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty"); } + // distinguish whether it is 0 user + if (BundleMgrAdapter::IsUser0BundleName(bundleName, session_->GetSessionUserId())) { + auto ret = proxy->User0OnBackup(); + if (ret) { + thisPtr->ClearSessionAndSchedInfo(bundleName); + thisPtr->NoticeClientFinish(bundleName, BError(BError::Codes::EXT_ABILITY_DIED)); + } + return; + } int64_t lastTime = session->GetLastIncrementalTime(bundleName); std::vector bundleNames; bundleNames.emplace_back(BIncrementalData {bundleName, lastTime}); @@ -256,6 +265,7 @@ ErrCode Service::AppendBundlesIncrementalBackupSession(const std::vectorGetSessionUserId()); session_->AppendBundles(bundleNames); + SetCurrentBackupSessProperties(bundleNames, session_->GetSessionUserId()); for (auto info : backupInfos) { session_->SetBundleDataSize(info.name, info.spaceOccupied); session_->SetBackupExtName(info.name, info.extensionName); @@ -581,4 +591,35 @@ void Service::NotifyCallerCurAppIncrementDone(ErrCode errCode, const std::string session_->GetServiceReverseProxy()->IncrementalRestoreOnBundleFinished(errCode, callerName); } } + +void Service::SendUserIdToApp(string &bundleName, int32_t userId) +{ + if (session_ == nullptr) { + HILOGI("session_ is nullptr"); + return; + } + HILOGI("SetCurrentBackupSessProperties bundleName : %{public}s", bundleName.c_str()); + string detailInfo; + if (!BJsonUtil::BuildBundleInfoJson(userId, detailInfo)) { + HILOGI("BuildBundleInfoJson failed, bundleName : %{public}s", bundleName.c_str()); + return; + } + HILOGI("current bundle, unicast info: %{public}s", detailInfo.c_str()); + session_->SetBackupExtInfo(bundleName, detailInfo); +} + +void Service::SetCurrentBackupSessProperties(const vector &bundleNames, int32_t userId) +{ + HILOGI("start SetCurrentBackupSessProperties"); + std::map> bundleNameDetailMap; + std::vector bundleDetailInfos; + for (auto item : bundleNames) { + std::string bundleName = item; + if (!BundleMgrAdapter::IsUser0BundleName(bundleName, userId)) { + continue; + } + SendUserIdToApp(bundleName, userId); + } + HILOGI("end SetCurrentBackupSessProperties"); +} } // namespace OHOS::FileManagement::Backup diff --git a/services/backup_sa/src/module_ipc/svc_extension_incremental_proxy.cpp b/services/backup_sa/src/module_ipc/svc_extension_incremental_proxy.cpp index 434ac777c..03dbb4fe3 100644 --- a/services/backup_sa/src/module_ipc/svc_extension_incremental_proxy.cpp +++ b/services/backup_sa/src/module_ipc/svc_extension_incremental_proxy.cpp @@ -124,6 +124,27 @@ ErrCode SvcExtensionProxy::IncrementalOnBackup(bool isClearData) return BError(BError::Codes::OK); } +ErrCode SvcExtensionProxy::User0OnBackup() +{ + HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); + HILOGD("Start"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + data.WriteInterfaceToken(GetDescriptor()); + + MessageParcel reply; + MessageOption option; + int32_t ret = Remote()->SendRequest(static_cast(IExtensionInterfaceCode::CMD_HANDLE_USER_0_BACKUP), + data, reply, option); + if (ret != NO_ERROR) { + HILOGE("Received error %{public}d when doing IPC", ret); + return ErrCode(ret); + } + + HILOGD("Successful"); + return reply.ReadInt32(); +} + tuple SvcExtensionProxy::GetIncrementalBackupFileHandle() { HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); diff --git a/tests/mock/module_external/bms_adapter_mock.cpp b/tests/mock/module_external/bms_adapter_mock.cpp index 2d93374af..2a1232d03 100644 --- a/tests/mock/module_external/bms_adapter_mock.cpp +++ b/tests/mock/module_external/bms_adapter_mock.cpp @@ -75,4 +75,9 @@ string BundleMgrAdapter::GetExtName(string bundleName, int32_t userId) { return "BackupExtensionAbility"; } + +bool BundleMgrAdapter::IsUser0BundleName(std::string bundleName, int32_t userId) +{ + return true; +} } // namespace OHOS::FileManagement::Backup diff --git a/tests/mock/module_ipc/svc_extension_proxy_mock.cpp b/tests/mock/module_ipc/svc_extension_proxy_mock.cpp index c7032836b..bb000e090 100644 --- a/tests/mock/module_ipc/svc_extension_proxy_mock.cpp +++ b/tests/mock/module_ipc/svc_extension_proxy_mock.cpp @@ -73,6 +73,11 @@ ErrCode SvcExtensionProxy::UpdateFdSendRate(std::string &bundleName, int32_t sen return 0; } +ErrCode SvcExtensionProxy::User0OnBackup() +{ + return 0; +} + tuple SvcExtensionProxy::GetIncrementalBackupFileHandle() { return {UniqueFd(-1), UniqueFd(-1)}; diff --git a/tests/unittests/backup_api/backup_impl/include/ext_extension_mock.h b/tests/unittests/backup_api/backup_impl/include/ext_extension_mock.h index 6ff7362e0..b5070b41f 100644 --- a/tests/unittests/backup_api/backup_impl/include/ext_extension_mock.h +++ b/tests/unittests/backup_api/backup_impl/include/ext_extension_mock.h @@ -139,6 +139,11 @@ public: return BError(BError::Codes::OK); }; + ErrCode User0OnBackup() override + { + return BError(BError::Codes::OK); + }; + private: int32_t nHandleBackupNum_ = 0; }; diff --git a/tests/unittests/backup_ext/ext_extension_stub_test.cpp b/tests/unittests/backup_ext/ext_extension_stub_test.cpp index ba73c7db6..8755506fc 100644 --- a/tests/unittests/backup_ext/ext_extension_stub_test.cpp +++ b/tests/unittests/backup_ext/ext_extension_stub_test.cpp @@ -38,6 +38,7 @@ public: MOCK_METHOD((std::tuple), GetIncrementalBackupFileHandle, ()); MOCK_METHOD(ErrCode, GetBackupInfo, (std::string &result)); MOCK_METHOD(ErrCode, UpdateFdSendRate, (std::string &bundleName, int32_t sendRate)); + MOCK_METHOD(ErrCode, User0OnBackup, ()); }; class ExtExtensionStubTest : public testing::Test { @@ -560,4 +561,36 @@ HWTEST_F(ExtExtensionStubTest, SUB_backup_ext_ExtExtensionStub_CmdUpdateSendRate } GTEST_LOG_(INFO) << "ExtExtensionStubTest-end SUB_backup_ext_ExtExtensionStub_CmdUpdateSendRate_0100"; } + +/** + * @tc.number: SUB_backup_ext_ExtExtensionStub_CmdUser0_0100 + * @tc.name: SUB_backup_ext_ExtExtensionStub_CmdUser0_0100 + * @tc.desc: 测试 CmdHandleUser0Backup 各个分支成功与失败 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: issues + */ +HWTEST_F(ExtExtensionStubTest, SUB_backup_ext_ExtExtensionStub_CmdUser0_0100, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ExtExtensionStubTest-begin SUB_backup_ext_ExtExtensionStub_CmdUser0_0100"; + try { + MessageParcel data; + MessageParcel reply; + EXPECT_CALL(*stub, User0OnBackup()).WillOnce(Return(0)); + EXPECT_CALL(*messageParcelMock, WriteInt32(_)).WillOnce(Return(false)); + EXPECT_TRUE(stub != nullptr); + auto err = stub->CmdHandleUser0Backup(data, reply); + EXPECT_EQ(err, BError(BError::Codes::EXT_BROKEN_IPC)); + + EXPECT_CALL(*stub, User0OnBackup()).WillOnce(Return(0)); + EXPECT_CALL(*messageParcelMock, WriteInt32(_)).WillOnce(Return(true)); + err = stub->CmdHandleUser0Backup(data, reply); + EXPECT_EQ(err, BError(BError::Codes::OK)); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "ExtExtensionStubTest-an exception occurred by CmdHandleClear."; + } + GTEST_LOG_(INFO) << "ExtExtensionStubTest-end SUB_backup_ext_ExtExtensionStub_CmdUser0_0100"; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/utils/include/b_filesystem/b_dir.h b/utils/include/b_filesystem/b_dir.h index e1e728d29..576cbc80e 100644 --- a/utils/include/b_filesystem/b_dir.h +++ b/utils/include/b_filesystem/b_dir.h @@ -26,6 +26,7 @@ #include #include +#include "b_json/b_report_entity.h" #include "errors.h" namespace OHOS::FileManagement::Backup { @@ -56,6 +57,32 @@ public: * @return std::vector 目录集合 */ static std::vector GetDirs(const std::vector &paths); + + /** + * @brief 从给定的includes和excludes目录中获取所有的大文件和小文件 + * + * @param includes 需要包含的文件及目录集合 + * @param excludes 需要排除的文件及目录集合 + * @return 大文件和小文件的集合 + */ + static std::tuple, std::vector> GetBackupList( + const std::vector &includes, const std::vector &excludes); + + /** + * @brief 获取bigfile和smaillfile的文件信息并生成清单 + * + * @param bigFile 需要包含的文件及目录集合 + * @param smallFile 需要排除的文件及目录集合 + * @param allFiles 生成的所有文件信息清单 + * @param smallFiles 生成的小文件信息清单 + * @param bigFiles 生成的大文件信息清单 + * @return + */ + static void GetUser0FileStat(std::vector bigFile, + std::vector smallFile, + std::vector &allFiles, + std::vector &smallFiles, + std::vector &bigFiles); }; } // namespace OHOS::FileManagement::Backup diff --git a/utils/include/b_jsonutil/b_jsonutil.h b/utils/include/b_jsonutil/b_jsonutil.h index c1d3e76bf..910a19704 100644 --- a/utils/include/b_jsonutil/b_jsonutil.h +++ b/utils/include/b_jsonutil/b_jsonutil.h @@ -64,10 +64,11 @@ public: * @param bundleDetails 结构体对象 * @param bundleDetailInfo bundle信息 * @param isClearData 框架是否清理标志 + * @param userId userId * */ static void ParseBundleInfoJson(const std::string &bundleInfo, std::vector &bundleDetails, - BJsonUtil::BundleDetailInfo bundleDetailInfo, bool &isClearData); + BJsonUtil::BundleDetailInfo bundleDetailInfo, bool &isClearData, int32_t userId); /** * @brief 根据业务类型和bundleName确定唯一的bundleInfo @@ -126,6 +127,27 @@ public: * */ static bool BuildOnProcessRetInfo(std::string &jsonStr, std::string onProcessRet); + + /** + * @brief 构建包含userId的detailInfo + * + * @param userId userId + * @param detailInfo 包含userId的detailInfo + * + * @return 是否组建成功 + * + */ + static bool BuildBundleInfoJson(int32_t userId, std::string &detailInfo); + + /** + * @brief 判断传入的bundleinfo中是否包含unicast字段 + * + * @param bundleinfo json串 + * + * @return 是否包含unicast字段 + * + */ + static bool HasUnicastInfo(std::string &bundleInfo); }; } // namespace OHOS::FileManagement::Backup diff --git a/utils/include/b_resources/b_constants.h b/utils/include/b_resources/b_constants.h index a1a614246..849f07ecf 100644 --- a/utils/include/b_resources/b_constants.h +++ b/utils/include/b_resources/b_constants.h @@ -220,6 +220,9 @@ static inline std::string LAST_INCREMENTAL_TIME = "lastIncrementalTime"; static inline std::string PARAMETERS = "parameters"; static inline std::string PRIORITY = "priority"; +// unicast +const std::string UNICAST_TYPE = "unicast"; + // 雷达打点引用到的常量 constexpr int32_t MS_1000 = 1000; constexpr uint8_t INDEX = 3; diff --git a/utils/src/b_filesystem/b_dir.cpp b/utils/src/b_filesystem/b_dir.cpp index d99581d28..37c40224a 100644 --- a/utils/src/b_filesystem/b_dir.cpp +++ b/utils/src/b_filesystem/b_dir.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ #include #include "b_error/b_error.h" +#include "b_filesystem/b_file_hash.h" #include "b_resources/b_constants.h" #include "directory_ex.h" #include "errors.h" @@ -78,7 +80,7 @@ static uint32_t CheckOverLongPath(const string &path) { uint32_t len = path.length(); if (len >= PATH_MAX_LEN) { - size_t found = path.find_last_of('/'); + size_t found = path.find_last_of(BConstants::FILE_SEPARATOR_CHAR); string sub = path.substr(found + 1); HILOGE("Path over long, length:%{public}d, fileName:%{public}s.", len, sub.c_str()); } @@ -94,8 +96,8 @@ static tuple, map> GetDirFiles if (IsEmptyDirectory(path)) { string newPath = path; - if (path.at(path.size()-1) != '/') { - newPath += '/'; + if (path.at(path.size()-1) != BConstants::FILE_SEPARATOR_CHAR) { + newPath += BConstants::FILE_SEPARATOR_CHAR; } smallFiles.insert(make_pair(newPath, 0)); return {ERR_OK, files, smallFiles}; @@ -186,7 +188,7 @@ static set ExpandPathWildcard(const vector &vec, bool onlyPath) for (auto it = expandPath.begin(); it != expandPath.end(); ++it) { filteredPath.insert(*it); - if (onlyPath && *it->rbegin() != '/') { + if (onlyPath && *it->rbegin() != BConstants::FILE_SEPARATOR_CHAR) { continue; } auto jt = it; @@ -225,7 +227,7 @@ tuple, map> BDir::GetBigFiles( continue; } string excludeItem = item; - if (excludeItem.at(item.size() - 1) == '/') { + if (excludeItem.at(item.size() - 1) == BConstants::FILE_SEPARATOR_CHAR) { excludeItem += "*"; } if (fnmatch(excludeItem.data(), str.data(), FNM_LEADING_DIR) == 0) { @@ -253,6 +255,180 @@ tuple, map> BDir::GetBigFiles( return {ERR_OK, move(bigFiles), move(resSmallFiles)}; } +void BDir::GetUser0FileStat(vector bigFile, + vector smallFile, + vector &allFiles, + vector &smallFiles, + vector &bigFiles) +{ + for (const auto &item : smallFile) { + struct ReportFileInfo storageFiles; + storageFiles.filePath = item; + if (filesystem::is_directory(item)) { + storageFiles.isDir = 1; + storageFiles.userTar = 0; + } else { + storageFiles.isDir = 0; + auto [res, fileHash] = BackupFileHash::HashWithSHA256(item); + if (fileHash.empty()) { + continue; + } + storageFiles.hash = fileHash; + storageFiles.userTar = 1; + } + struct stat sta = {}; + if (stat(item.c_str(), &sta) != 0) { + throw BError(BError::Codes::EXT_INVAL_ARG, "Get file stat failed"); + } + storageFiles.size = sta.st_size; + storageFiles.mode = to_string(static_cast(sta.st_mode)); + int64_t lastUpdateTime = static_cast(sta.st_mtime); + storageFiles.mtime = lastUpdateTime; + allFiles.push_back(storageFiles); + smallFiles.push_back(storageFiles); + } + for (const auto &item : bigFile) { + struct ReportFileInfo storageFiles; + storageFiles.filePath = item; + auto [res, fileHash] = BackupFileHash::HashWithSHA256(item); + if (fileHash.empty()) { + continue; + } + storageFiles.hash = fileHash; + struct stat sta = {}; + if (stat(item.c_str(), &sta) != 0) { + throw BError(BError::Codes::EXT_INVAL_ARG, "Get file stat failed"); + } + storageFiles.size = sta.st_size; + storageFiles.mode = to_string(static_cast(sta.st_mode)); + int64_t lastUpdateTime = static_cast(sta.st_mtime); + storageFiles.mtime = lastUpdateTime; + storageFiles.userTar = 1; + allFiles.push_back(storageFiles); + bigFiles.push_back(storageFiles); + } + HILOGI("get FileStat end, bigfiles = %{public}zu, smallFiles = %{public}zu, allFiles = %{public}zu,", + bigFiles.size(), smallFiles.size(), allFiles.size()); +} + +static tuple, vector> IsNotPath(const string &path, vector &bigFiles, + vector &smallFiles, off_t size) +{ + struct stat sta = {}; + if (CheckOverLongPath(path) >= PATH_MAX_LEN || stat(path.data(), &sta) == -1) { + return {}; + } + if (sta.st_size <= size) { + smallFiles.push_back(path); + HILOGI("bigfiles = %{public}zu, smallfiles = %{public}zu", bigFiles.size(), smallFiles.size()); + return {bigFiles, smallFiles}; + } + bigFiles.push_back(path); + HILOGI("bigfiles = %{public}zu, smallfiles = %{public}zu", bigFiles.size(), smallFiles.size()); + return {bigFiles, smallFiles}; +} + +static tuple, vector> GetUser0DirFilesDetail(const string &path, off_t size = -1) +{ + vector bigFiles; + vector smallFiles; + if (IsEmptyDirectory(path)) { + string newPath = path; + if (path.at(path.size()-1) != BConstants::FILE_SEPARATOR_CHAR) { + newPath += BConstants::FILE_SEPARATOR_CHAR; + } + smallFiles.push_back(path); + return {bigFiles, smallFiles}; + } + if (filesystem::is_regular_file(path)) { + return IsNotPath(path, bigFiles, smallFiles, size); + } + unique_ptr> dir = {opendir(path.c_str()), closedir}; + if (!dir) { + HILOGE("Invalid directory path: %{private}s", path.c_str()); + return {}; + } + struct dirent *ptr = nullptr; + while (!!(ptr = readdir(dir.get()))) { + // current dir OR parent dir + if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) { + continue; + } else if (ptr->d_type == DT_REG) { + struct stat sta = {}; + string fileName = IncludeTrailingPathDelimiter(path) + string(ptr->d_name); + if (CheckOverLongPath(fileName) >= PATH_MAX_LEN || stat(fileName.data(), &sta) == -1) { + continue; + } + if (sta.st_size <= size) { + smallFiles.push_back(fileName); + continue; + } + + bigFiles.push_back(fileName); + } else if (ptr->d_type != DT_DIR) { + HILOGE("Not support file type"); + continue; + } + // DT_DIR type + auto [subBigFiles, subSmallFiles] = + GetUser0DirFilesDetail(IncludeTrailingPathDelimiter(path) + string(ptr->d_name), size); + bigFiles.insert(bigFiles.end(), subBigFiles.begin(), subBigFiles.end()); + smallFiles.insert(smallFiles.end(), subSmallFiles.begin(), subSmallFiles.end()); + } + HILOGI("bigfiles = %{public}zu, smallfiles = %{public}zu", bigFiles.size(), smallFiles.size()); + return {bigFiles, smallFiles}; +} + +tuple, vector> BDir::GetBackupList(const vector &includes, + const vector &excludes) +{ + HILOGI("start get bigfiles and smallfiles"); + set inc = ExpandPathWildcard(includes, false); + vector bigFiles; + vector smallFiles; + for (const auto &item : inc) { + auto [bigFile, smallFile] = GetUser0DirFilesDetail(item, BConstants::BIG_FILE_BOUNDARY); + bigFiles.insert(bigFiles.end(), bigFile.begin(), bigFile.end()); + smallFiles.insert(smallFiles.end(), smallFile.begin(), smallFile.end()); + } + HILOGI("end bigfiles = %{public}zu, smallfiles = %{public}zu", bigFiles.size(), smallFiles.size()); + auto isMatch = [](const vector &s, const string &str) -> bool { + if (str.empty()) { + return false; + } + for (const string &item : s) { + if (item.empty()) { + continue; + } + string excludeItem = item; + if (excludeItem.at(item.size() - 1) == BConstants::FILE_SEPARATOR_CHAR) { + excludeItem += "*"; + } + if (fnmatch(excludeItem.data(), str.data(), FNM_LEADING_DIR) == 0) { + return true; + } + } + return false; + }; + + for (auto item = bigFiles.begin(); item != bigFiles.end();) { + if (isMatch(excludes, *item)) { + item = bigFiles.erase(item); + } else { + ++item; + } + } + for (auto item = smallFiles.begin(); item != smallFiles.end();) { + if (isMatch(excludes, *item)) { + item = smallFiles.erase(item); + } else { + ++item; + } + } + HILOGI("End compare bigfiles = %{public}zu, smallfiles = %{public}zu", bigFiles.size(), smallFiles.size()); + return {bigFiles, smallFiles}; +} + vector BDir::GetDirs(const vector &paths) { vector wildcardPath(paths.begin(), paths.end()); diff --git a/utils/src/b_jsonutil/b_jsonutil.cpp b/utils/src/b_jsonutil/b_jsonutil.cpp index 492a6ea92..5e6ce289e 100644 --- a/utils/src/b_jsonutil/b_jsonutil.cpp +++ b/utils/src/b_jsonutil/b_jsonutil.cpp @@ -22,6 +22,7 @@ #include "cJSON.h" #include "b_error/b_error.h" +#include "b_resources/b_constants.h" #include "filemgmt_libhilog.h" #include "b_utils/b_time.h" @@ -90,7 +91,7 @@ std::map> BJsonUtil::Build bundleDetailInfo.bundleName = bundleNameOnly; bundleDetailInfo.bundleIndex = bundleIndex; bundleDetailInfo.userId = userId; - ParseBundleInfoJson(bundleInfo, bundleDetailInfos, bundleDetailInfo, isClearData); + ParseBundleInfoJson(bundleInfo, bundleDetailInfos, bundleDetailInfo, isClearData, userId); isClearDataFlags[bundleName] = isClearData; bundleNameDetailMap[bundleName] = bundleDetailInfos; } @@ -98,27 +99,58 @@ std::map> BJsonUtil::Build return bundleNameDetailMap; } -void BJsonUtil::ParseBundleInfoJson(const std::string &bundleInfo, std::vector &bundleDetails, - BJsonUtil::BundleDetailInfo bundleDetailInfo, bool &isClearData) +// 传递的bundleinfo不包含unicast字段时 需要拼接unicast字段 +static bool AddUnicastInfo(std::string &bundleInfo) { cJSON *root = cJSON_Parse(bundleInfo.c_str()); if (root == nullptr) { HILOGE("Parse json error,root is null"); - return; + return false; } - cJSON *clearBackupData = cJSON_GetObjectItem(root, "clearBackupData"); - if (clearBackupData == nullptr || !cJSON_IsString(clearBackupData) || (clearBackupData->valuestring == nullptr)) { - HILOGE("Parse json error."); - } else { - std::string value = clearBackupData->valuestring; - isClearData = value.compare("false") != 0; - HILOGI("bundleName:%{public}s clear data falg:%{public}d", bundleDetailInfo.bundleName.c_str(), isClearData); + cJSON *info = cJSON_CreateObject(); + if (info == nullptr) { + cJSON_Delete(root); + return false; + } + cJSON_AddStringToObject(info, "type", "unicast"); + cJSON *details = cJSON_CreateArray(); + if (details == nullptr) { + cJSON_Delete(root); + cJSON_Delete(info); + return false; + } + cJSON_AddItemToArray(details, {}); + cJSON_AddItemToObject(info, "details", details); + cJSON *infos = cJSON_GetObjectItem(root, "infos"); + if (infos == nullptr || !cJSON_IsArray(infos)) { + cJSON_Delete(root); + cJSON_Delete(info); + return false; + } + cJSON_AddItemToArray(infos, info); + char *jsonStr = cJSON_Print(root); + if (jsonStr == nullptr) { + cJSON_Delete(root); + return false; + } + bundleInfo = string(jsonStr); + cJSON_Delete(root); + free(jsonStr); + return true; +} + +bool BJsonUtil::HasUnicastInfo(std::string &bundleInfo) +{ + cJSON *root = cJSON_Parse(bundleInfo.c_str()); + if (root == nullptr) { + HILOGE("Parse json error,root is null"); + return false; } cJSON *infos = cJSON_GetObjectItem(root, "infos"); if (infos == nullptr || !cJSON_IsArray(infos) || cJSON_GetArraySize(infos) == 0) { HILOGE("Parse json error, infos is not array"); cJSON_Delete(root); - return; + return false; } int infosCount = cJSON_GetArraySize(infos); for (int i = 0; i < infosCount; i++) { @@ -126,26 +158,94 @@ void BJsonUtil::ParseBundleInfoJson(const std::string &bundleInfo, std::vectorvaluestring == nullptr)) { HILOGE("Parse json type element error"); cJSON_Delete(root); + continue; + } + if (string(type->valuestring).compare(BConstants::UNICAST_TYPE) == 0) { + cJSON_Delete(root); + return true; + } + } + cJSON_Delete(root); + return false; +} + +static void InsertBundleDetailInfo(cJSON *infos, int infosCount, + std::vector &bundleDetails, + BJsonUtil::BundleDetailInfo bundleDetailInfo, + int32_t userId) +{ + for (int i = 0; i < infosCount; i++) { + cJSON *infoItem = cJSON_GetArrayItem(infos, i); + if (!cJSON_IsObject(infoItem)) { + HILOGE("Parse json error, info item is not an object"); + return; + } + cJSON *type = cJSON_GetObjectItem(infoItem, "type"); + if (type == nullptr || !cJSON_IsString(type) || (type->valuestring == nullptr)) { + HILOGE("Parse json type element error"); return; } bundleDetailInfo.type = type->valuestring; cJSON *details = cJSON_GetObjectItem(infoItem, "details"); if (details == nullptr || !cJSON_IsArray(details)) { HILOGE("Parse json details element error"); - cJSON_Delete(root); return; } + if (bundleDetailInfo.type.compare(BConstants::UNICAST_TYPE) == 0) { + cJSON *detail = cJSON_CreateObject(); + if (detail == nullptr) { + HILOGE("creat json error"); + return; + } + const char *const zeroUserId = static_cast(to_string(userId).c_str()); + cJSON_AddStringToObject(detail, "type", "userId"); + cJSON_AddStringToObject(detail, "detail", zeroUserId); + cJSON_AddItemToArray(details, detail); + } char *detailInfos = cJSON_Print(details); bundleDetailInfo.detail = std::string(detailInfos); bundleDetails.emplace_back(bundleDetailInfo); cJSON_free(detailInfos); } +} + +void BJsonUtil::ParseBundleInfoJson(const std::string &bundleInfo, std::vector &bundleDetails, + BJsonUtil::BundleDetailInfo bundleDetailInfo, bool &isClearData, int32_t userId) +{ + string bundleInfoCopy = move(bundleInfo); + if (!HasUnicastInfo(bundleInfoCopy)) { + if (!AddUnicastInfo(bundleInfoCopy)) { + HILOGE("AddUnicastInfo failed"); + return; + } + } + cJSON *root = cJSON_Parse(bundleInfoCopy.c_str()); + if (root == nullptr) { + HILOGE("Parse json error,root is null"); + return; + } + cJSON *clearBackupData = cJSON_GetObjectItem(root, "clearBackupData"); + if (clearBackupData == nullptr || !cJSON_IsString(clearBackupData) || (clearBackupData->valuestring == nullptr)) { + HILOGE("Parse json error."); + } else { + std::string value = clearBackupData->valuestring; + isClearData = value.compare("false") != 0; + HILOGI("bundleName:%{public}s clear data falg:%{public}d", bundleDetailInfo.bundleName.c_str(), isClearData); + } + cJSON *infos = cJSON_GetObjectItem(root, "infos"); + if (infos == nullptr || !cJSON_IsArray(infos) || cJSON_GetArraySize(infos) == 0) { + HILOGE("Parse json error, infos is not array"); + cJSON_Delete(root); + return; + } + int infosCount = cJSON_GetArraySize(infos); + InsertBundleDetailInfo(infos, infosCount, bundleDetails, bundleDetailInfo, userId); cJSON_Delete(root); } @@ -269,3 +369,48 @@ bool OHOS::FileManagement::Backup::BJsonUtil::BuildOnProcessRetInfo(std::string cJSON_free(data); return true; } + +bool OHOS::FileManagement::Backup::BJsonUtil::BuildBundleInfoJson(int32_t userId, string &detailInfo) +{ + cJSON *root = cJSON_CreateObject(); + if (root == nullptr) { + return false; + } + cJSON *infos = cJSON_CreateArray(); + if (infos == nullptr) { + cJSON_Delete(root); + return false; + } + cJSON_AddItemToObject(root, "infos", infos); + cJSON *info = cJSON_CreateObject(); + if (info == nullptr) { + cJSON_Delete(root); + return false; + } + cJSON_AddStringToObject(info, "type", "unicast"); + cJSON_AddItemToArray(infos, info); + cJSON *details = cJSON_CreateArray(); + if (details == nullptr) { + cJSON_Delete(root); + return false; + } + cJSON_AddItemToObject(info, "details", details); + cJSON *detail = cJSON_CreateObject(); + if (detail == nullptr) { + cJSON_Delete(root); + return false; + } + const char *const zeroUserId = static_cast(to_string(userId).c_str()); + cJSON_AddStringToObject(detail, "type", "userId"); + cJSON_AddStringToObject(detail, "detail", zeroUserId); + cJSON_AddItemToArray(details, detail); + char *jsonStr = cJSON_Print(root); + if (jsonStr == nullptr) { + cJSON_Delete(root); + return false; + } + detailInfo = string(jsonStr); + cJSON_Delete(root); + free(jsonStr); + return true; +} -- Gitee From 045bbc0e590bfdb222e17f647d92648483b6d52b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=99=9F=E9=92=B0?= Date: Fri, 13 Sep 2024 14:00:43 +0000 Subject: [PATCH 2/2] update services/backup_sa/src/module_external/bms_adapter.cpp. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 张晟钰 --- services/backup_sa/src/module_external/bms_adapter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/backup_sa/src/module_external/bms_adapter.cpp b/services/backup_sa/src/module_external/bms_adapter.cpp index afd2f460c..59b73f550 100644 --- a/services/backup_sa/src/module_external/bms_adapter.cpp +++ b/services/backup_sa/src/module_external/bms_adapter.cpp @@ -506,7 +506,8 @@ bool BundleMgrAdapter::IsUser0BundleName(std::string bundleName, int32_t userId) auto bms = GetBundleManager(); AppExecFwk::BundleInfo installedBundle; if (!bms->GetBundleInfo(bundleName, AppExecFwk::GET_BUNDLE_WITH_EXTENSION_INFO, installedBundle, userId)) { - throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get bundle infos"); + HILOGI("GetBundleInfo failed, bundleName:%{public}s", bundleName.c_str()); + return false; } if (installedBundle.applicationInfo.singleton == true) { HILOGI("bundleName:%{public}s is zero user bundle", bundleName.c_str()); -- Gitee