diff --git a/frameworks/native/backup_kit_inner/src/b_incremental_data.cpp b/frameworks/native/backup_kit_inner/src/b_incremental_data.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb8e8dbba688f16a57abaec109d67c79034de305 --- /dev/null +++ b/frameworks/native/backup_kit_inner/src/b_incremental_data.cpp @@ -0,0 +1,65 @@ +/* + * 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 "b_incremental_data.h" + +#include "filemgmt_libhilog.h" +#include "message_parcel.h" + +namespace OHOS { +namespace FileManagement { +namespace Backup { +using namespace std; + +bool BIncrementalData::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString(bundleName) || !parcel.WriteInt64(lastIncrementalTime) || + !parcel.WriteString(backupParameters) || !parcel.WriteString(backupPriority)) { + HILOGE("Failed"); + return false; + } + auto msgParcel = static_cast(&parcel); + msgParcel->WriteFileDescriptor(manifestFd); + return true; +} + +bool BIncrementalData::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.ReadString(bundleName) || !parcel.ReadInt64(lastIncrementalTime) || + !parcel.ReadString(backupParameters) || !parcel.ReadString(backupPriority)) { + HILOGE("Failed"); + return false; + } + auto msgParcel = static_cast(&parcel); + manifestFd = msgParcel->ReadFileDescriptor(); + return true; +} + +BIncrementalData *BIncrementalData::Unmarshalling(Parcel &parcel) +{ + try { + auto result = make_unique(); + if (!result->ReadFromParcel(parcel)) { + return nullptr; + } + return result.release(); + } catch (const bad_alloc &e) { + HILOGE("Failed to unmarshall BIncrementalData because of %{public}s", e.what()); + } + return nullptr; +} +} // namespace Backup +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_data.h b/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_data.h new file mode 100644 index 0000000000000000000000000000000000000000..0052e61f4bfe09b87061dcf5c7450808c140bd7d --- /dev/null +++ b/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_data.h @@ -0,0 +1,47 @@ +/* + * 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_B_INCREMENTAL_DATA_H +#define OHOS_FILEMGMT_BACKUP_B_INCREMENTAL_DATA_H + +#include +#include + +#include "parcel.h" +#include "unique_fd.h" + +namespace OHOS::FileManagement::Backup { +struct BIncrementalData : public Parcelable { + std::string bundleName; + int64_t lastIncrementalTime; + int32_t manifestFd; + std::string backupParameters; + std::string backupPriority; + + BIncrementalData() = default; + BIncrementalData(std::string name, int64_t nTime, int fd, std::string parameters = "", std::string priority = "") + : bundleName(name), lastIncrementalTime(nTime), manifestFd(fd), backupParameters(parameters), + backupPriority(priority) + { + } + ~BIncrementalData() override = default; + + bool ReadFromParcel(Parcel &parcel); + bool Marshalling(Parcel &parcel) const override; + static BIncrementalData *Unmarshalling(Parcel &parcel); +}; +} // namespace OHOS::FileManagement::Backup + +#endif // OHOS_FILEMGMT_BACKUP_B_INCREMENTAL_DATA_H diff --git a/services/backup_sa/include/module_external/bms_adapter.h b/services/backup_sa/include/module_external/bms_adapter.h index 7af9bedff1cc049afc013260865c8badff76be75..7297a5fe6fcd50bb477c72d502b2408135141ebe 100644 --- a/services/backup_sa/include/module_external/bms_adapter.h +++ b/services/backup_sa/include/module_external/bms_adapter.h @@ -21,6 +21,8 @@ #include "b_json/b_json_entity_caps.h" #include "bundlemgr/bundle_mgr_interface.h" +#include "b_incremental_data.h" +#include "istorage_manager.h" namespace OHOS::FileManagement::Backup { class InnerReceiverImpl; @@ -49,6 +51,16 @@ public: * @brief Get app gallery bundle name */ static std::string GetAppGalleryBundleName(); + + /** + * @brief Get the bundle infos object for incremental backup + * + * @param incrementalDataList bundle Name and time list + * @param userId User ID + * @return std::vector + */ + static std::vector GetBundleInfosForIncremental(const std::vector &incrementalDataList, + int32_t userId); }; } // namespace OHOS::FileManagement::Backup #endif // OHOS_FILEMGMT_BACKUP_BUNDLE_MGR_ADAPTER_H diff --git a/services/backup_sa/include/module_external/sms_adapter.h b/services/backup_sa/include/module_external/sms_adapter.h index 5dd16545bc8c2cde2bf7bb00d7e1574e2adaaf89..d1aa7ff201099eecfc14668b68e6d6b8b6aa3ed2 100644 --- a/services/backup_sa/include/module_external/sms_adapter.h +++ b/services/backup_sa/include/module_external/sms_adapter.h @@ -17,7 +17,8 @@ #define OHOS_FILEMGMT_BACKUP_STORAGE_MGR_ADAPTER_H #include - +#include +#include #include "istorage_manager.h" namespace OHOS::FileManagement::Backup { @@ -37,6 +38,19 @@ public: * @param userId user id */ static int64_t GetUserStorageStats(const std::string &bundleName, int32_t userId); + + /** + * @brief Get the user storage stats object + * + * @param userId user id + * @param bundleNames + * @param incrementalBackTimes + * @param pkgFileSizes bundle backup file size + * @param pkgStatPaths stat file path + */ + static int32_t GetBundleStatsForIncrease(uint32_t userId, const std::vector &bundleNames, + const std::vector &incrementalBackTimes, std::vector &pkgFileSizes, + std::vector &pkgStatPaths); }; } // namespace OHOS::FileManagement::Backup #endif // OHOS_FILEMGMT_BACKUP_STORAGE_MGR_ADAPTER_H \ No newline at end of file diff --git a/services/backup_sa/src/module_external/bms_adapter.cpp b/services/backup_sa/src/module_external/bms_adapter.cpp index fbc7e4526c68ae2485ba59072718bf3fe989a346..d068dffdd247416c2e9c9a442eb3142518d5f786 100644 --- a/services/backup_sa/src/module_external/bms_adapter.cpp +++ b/services/backup_sa/src/module_external/bms_adapter.cpp @@ -14,7 +14,10 @@ */ #include "module_external/bms_adapter.h" +#include "module_external/sms_adapter.h" +#include +#include #include #include "b_error/b_error.h" @@ -99,8 +102,8 @@ static int64_t GetBundleStats(const string &bundleName, int32_t userId) bundleStats[i] = 0; } } - int64_t dataSize_ = bundleStats[LOCAL] + bundleStats[DISTRIBUTED] + bundleStats[DATABASE]; - return dataSize_; + int64_t dataSize = bundleStats[LOCAL] + bundleStats[DISTRIBUTED] + bundleStats[DATABASE]; + return dataSize; } vector BundleMgrAdapter::GetBundleInfos(int32_t userId) @@ -163,4 +166,99 @@ string BundleMgrAdapter::GetAppGalleryBundleName() } return bundleName; } + +static tuple, vector> GetBackupExtConfig( + const vector &extensionInfos) +{ + for (auto &&ext : extensionInfos) { + if (ext.type != AppExecFwk::ExtensionAbilityType::BACKUP) { + continue; + } + vector out; + AppExecFwk::BundleMgrClient client; + if (!client.GetResConfigFile(ext, "ohos.extension.backup", out) || out.size() == 0) { + throw BError(BError::Codes::SA_INVAL_ARG, "Failed to get resconfigfile of bundle " + ext.bundleName); + } + BJsonCachedEntity cachedEntity(out[0], ext.bundleName); + auto cache = cachedEntity.Structuralize(); + return {cache.GetAllowToBackupRestore(), ext.name, cache.GetRestoreDeps(), cache.GetSupportScene(), + cache.GetIncludes(), cache.GetExcludes()}; + } + HILOGI("No backup extension ability found"); + return {false, "", "", "", {}, {}}; +} + +static bool CreateIPCInteractionFiles(int32_t userId, const string &bundleName, int64_t lastIncrementalTime, + const vector &includes, const vector &excludes) +{ + // backup_sa bundle path + string backupSaBundleDir = BConstants::BACKUP_PATH_PREFIX + to_string(userId) + BConstants::BACKUP_PATH_SURFFIX + + bundleName + to_string(BConstants::FILE_SEPARATOR_CHAR); + if (access(backupSaBundleDir.data(), F_OK) != 0 && mkdir(backupSaBundleDir.data(), S_IRWXU | S_IRWXG) != 0) { + HILOGE("Failed to create folder in backup_sa"); + return false; + } + // backup_sa include/exclude + string incExFilePath = backupSaBundleDir + BConstants::BACKUP_INCEXC_SYMBOL + to_string(lastIncrementalTime); + std::ofstream incExcFile; + incExcFile.open(incExFilePath.data(), std::ios::out | std::ios::trunc); + if (!incExcFile.is_open()) { + HILOGE("Cannot create file"); + return false; + } + incExcFile << BConstants::BACKUP_INCLUDE << std::endl; + for (auto &include : includes) { + incExcFile << include << std::endl; + } + incExcFile << BConstants::BACKUP_EXCLUDE << std::endl; + for (auto &exclude : excludes) { + incExcFile << exclude << std::endl; + } + return true; +} + +std::vector GetBundleInfosForIncremental( + const std::vector &incrementalDataList, int32_t userId) +{ + std::vector bundleNames; + std::vector incrementalBackTimes; + vector bundleInfos; + auto bms = GetBundleManager(); + for (auto const &bundleNameTime : incrementalDataList) { + auto bundleName = bundleNameTime.bundleName; + HILOGI("Begin Get bundleName:%{public}s", bundleName.c_str()); + 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 info"); + } + if (installedBundle.applicationInfo.codePath == HMOS_HAP_CODE_PATH || + installedBundle.applicationInfo.codePath == LINUX_HAP_CODE_PATH) { + HILOGI("Unsupported applications, name : %{public}s", installedBundle.name.data()); + continue; + } + auto [allToBackup, extName, restoreDeps, supportScene, includes, excludes] = + GetBackupExtConfig(installedBundle.extensionInfos); + bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {installedBundle.name, installedBundle.versionCode, + installedBundle.versionName, 0, allToBackup, + extName, restoreDeps, supportScene}); + if (!CreateIPCInteractionFiles(userId, bundleName, bundleNameTime.lastIncrementalTime, includes, excludes)) { + HILOGE("Failed to write include/exclude files, name : %{public}s", installedBundle.name.data()); + continue; + } + bundleNames.emplace_back(bundleName); + incrementalBackTimes.emplace_back(bundleNameTime.lastIncrementalTime); + } + + std::vector pkgFileSizes; + std::vector pkgStatPaths; + StorageMgrAdapter::GetBundleStatsForIncrease(userId, bundleNames , incrementalBackTimes, pkgFileSizes, pkgStatPaths); + + std::vector newBundleInfos; + for (size_t i = 0; bundleInfos.size(); i++) { + BJsonEntityCaps::BundleInfo newBundleInfo = bundleInfos[i]; + newBundleInfo.spaceOccupied = pkgFileSizes[i]; + newBundleInfos.emplace_back(newBundleInfo); + } + return newBundleInfos; +} } // namespace OHOS::FileManagement::Backup diff --git a/services/backup_sa/src/module_external/sms_adapter.cpp b/services/backup_sa/src/module_external/sms_adapter.cpp index e6613ed2cb8cdd575d5e52129d938f80a1d5cb15..679842ee76b50658b7320e790f17dd069d75ace7 100644 --- a/services/backup_sa/src/module_external/sms_adapter.cpp +++ b/services/backup_sa/src/module_external/sms_adapter.cpp @@ -69,4 +69,15 @@ int64_t StorageMgrAdapter::GetUserStorageStats(const std::string &bundleName, in } return 0; } + +int32_t StorageMgrAdapter::GetBundleStatsForIncrease(uint32_t userId, const std::vector &bundleNames, + const std::vector &incrementalBackTimes, std::vector &pkgFileSizes, + std::vector &pkgStatPaths) +{ + auto storageMgr = GetStorageManager(); + if (storageMgr->GetBundleStatsForIncrease(userId, bundleNames, incrementalBackTimes, pkgFileSizes, pkgStatPaths)) { + throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get user storage stats"); + } + return 0; +} } // namespace OHOS::FileManagement::Backup diff --git a/utils/include/b_resources/b_constants.h b/utils/include/b_resources/b_constants.h index 9f4ae877b689f5fc4318fb3a35a792b5c087b3fd..679b623d23925a1dceb6cf55fbbca0e42ff7dbaa 100644 --- a/utils/include/b_resources/b_constants.h +++ b/utils/include/b_resources/b_constants.h @@ -70,6 +70,15 @@ static inline std::string BACKUP_DEBUG_OVERRIDE_EXTENSION_CONFIG_KEY = "backup.d static inline std::string BACKUP_DEBUG_OVERRIDE_ACCOUNT_CONFIG_KEY = "backup.debug.overrideAccountConfig"; static inline std::string BACKUP_DEBUG_OVERRIDE_ACCOUNT_NUMBER_KEY = "backup.debug.overrideAccountNumber"; +// 增量备份相关处理目录 +constexpr char FILE_SEPARATOR_CHAR = '/'; +static const std::string BACKUP_PATH_PREFIX = "/data/service/el2/"; +static const std::string BACKUP_PATH_SURFFIX = "/backup/backup_sa/"; +static const std::string BACKUP_INCEXC_SYMBOL = "incExc_"; +static const std::string BACKUP_STAT_SYMBOL = "stat_"; +static const std::string BACKUP_INCLUDE = "INCLUDES"; +static const std::string BACKUP_EXCLUDE = "EXCLUDES"; + // 应用备份数据暂存路径 static inline std::string_view SA_BUNDLE_BACKUP_BACKUP = "/backup/"; static inline std::string_view SA_BUNDLE_BACKUP_RESTORE = "/restore/";