From bf8f22262fc1e0d1461b9fa3c342b842d31d3386 Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Fri, 29 Dec 2023 10:35:33 +0800 Subject: [PATCH 01/35] =?UTF-8?q?=E5=A4=87=E4=BB=BD=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E5=A2=9E=E9=87=8F=E9=9C=80=E6=B1=82=E8=81=94=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- bundle.json | 6 +- .../native/backup_ext/include/ext_extension.h | 26 ++ .../backup_ext/include/ext_extension_stub.h | 3 + .../native/backup_ext/src/ext_extension.cpp | 392 ++++++++++++++++++ .../backup_ext/src/ext_extension_stub.cpp | 52 +++ .../include/service_reverse.h | 16 + .../include/service_reverse_stub.h | 10 + .../src/b_incremental_backup_session.cpp | 107 +++++ .../src/b_incremental_data.cpp | 65 +++ .../src/b_incremental_restore_session.cpp | 125 ++++++ .../backup_kit_inner/src/b_session_backup.cpp | 10 + .../src/b_session_restore.cpp | 10 + .../src/b_session_restore_async.cpp | 10 + .../src/service_incremental_proxy.cpp | 263 ++++++++++++ .../src/service_incremental_reverse.cpp | 115 +++++ .../src/service_reverse_stub.cpp | 90 ++++ .../native/backup_kit_inner/BUILD.gn | 5 + .../backup_kit_inner/backup_kit_inner.h | 2 + .../impl/b_incremental_backup_session.h | 79 ++++ .../impl/b_incremental_data.h | 47 +++ .../impl/b_incremental_restore_session.h | 97 +++++ .../backup_kit_inner/impl/b_session_backup.h | 7 + .../backup_kit_inner/impl/b_session_restore.h | 7 + .../impl/b_session_restore_async.h | 7 + .../backup_kit_inner/impl/i_extension.h | 3 + .../impl/i_extension_ipc_interface_code.h | 3 + .../native/backup_kit_inner/impl/i_service.h | 10 + .../impl/i_service_ipc_interface_code.h | 8 + .../backup_kit_inner/impl/i_service_reverse.h | 13 + .../i_service_reverse_ipc_interface_code.h | 8 + .../backup_kit_inner/impl/service_proxy.h | 11 + interfaces/kits/js/BUILD.gn | 1 + .../kits/js/backup/incremental_backup_data.h | 100 +++++ .../kits/js/backup/local_capabilities.cpp | 90 +++- interfaces/kits/js/backup/module.cpp | 2 + .../js/backup/session_backup_n_exporter.cpp | 38 +- .../js/backup/session_backup_n_exporter.h | 1 + .../session_incremental_backup_n_exporter.cpp | 379 +++++++++++++++++ .../session_incremental_backup_n_exporter.h | 36 ++ .../js/backup/session_restore_n_exporter.cpp | 146 ++++++- .../js/backup/session_restore_n_exporter.h | 1 + services/backup.para | 5 +- services/backup_sa/BUILD.gn | 2 + .../backup_sa/include/module_ipc/service.h | 19 + .../module_ipc/service_reverse_proxy.h | 10 + .../include/module_ipc/service_stub.h | 12 + .../include/module_ipc/svc_extension_proxy.h | 4 + .../include/module_ipc/svc_session_manager.h | 29 ++ .../include/module_sched/sched_scheduler.h | 6 +- services/backup_sa/src/module_ipc/service.cpp | 31 +- .../src/module_ipc/service_incremental.cpp | 321 ++++++++++++++ .../service_incremental_reverse_proxy.cpp | 183 ++++++++ .../backup_sa/src/module_ipc/service_stub.cpp | 175 ++++++++ .../src/module_ipc/svc_extension_proxy.cpp | 73 ++++ .../src/module_ipc/svc_session_manager.cpp | 37 ++ .../src/module_sched/sched_scheduler.cpp | 9 + tests/mock/b_filesystem/b_file_mock.cpp | 6 + .../b_session_backup_mock.cpp | 5 + .../b_session_restore_async_mock.cpp | 5 + .../b_session_restore_mock.cpp | 5 + .../backup_kit_inner/service_proxy_mock.cpp | 40 ++ tests/mock/module_ipc/service_mock.cpp | 40 ++ .../module_ipc/service_reverse_proxy_mock.cpp | 16 + tests/mock/module_ipc/service_stub_mock.cpp | 52 +++ .../module_ipc/svc_extension_proxy_mock.cpp | 15 + .../module_ipc/svc_session_manager_mock.cpp | 12 + .../module_sched/sched_scheduler_mock.cpp | 2 + tests/moduletests/backup_kit_inner/BUILD.gn | 1 + .../backup_impl/include/ext_extension_mock.h | 15 + .../backup_impl/include/i_service_mock.h | 40 ++ .../include/service_reverse_mock.h | 10 + .../backup_impl/service_reverse_stub_test.cpp | 8 + tests/unittests/backup_sa/module_ipc/BUILD.gn | 2 + .../module_ipc/service_stub_test.cpp | 39 ++ .../backup_utils/b_filesystem/b_file_test.cpp | 54 +++ tools/backup_tool/BUILD.gn | 1 + .../include/tools_op_incremental_backup.h | 24 ++ tools/backup_tool/src/main.cpp | 2 + tools/backup_tool/src/tools_op_backup.cpp | 1 + .../src/tools_op_incremental_backup.cpp | 305 ++++++++++++++ tools/backup_tool/src/tools_op_restore.cpp | 3 +- utils/BUILD.gn | 5 + utils/include/b_filesystem/b_file.h | 7 + utils/include/b_filesystem/b_file_hash.h | 32 ++ utils/include/b_ohos/startup/backup_para.h | 14 + utils/include/b_resources/b_constants.h | 8 + utils/src/b_filesystem/b_file.cpp | 56 +++ utils/src/b_filesystem/b_file_hash.cpp | 105 +++++ utils/src/b_ohos/startup/backup_para.cpp | 20 + 89 files changed, 4221 insertions(+), 46 deletions(-) create mode 100644 frameworks/native/backup_kit_inner/src/b_incremental_backup_session.cpp create mode 100644 frameworks/native/backup_kit_inner/src/b_incremental_data.cpp create mode 100644 frameworks/native/backup_kit_inner/src/b_incremental_restore_session.cpp create mode 100644 frameworks/native/backup_kit_inner/src/service_incremental_proxy.cpp create mode 100644 frameworks/native/backup_kit_inner/src/service_incremental_reverse.cpp create mode 100644 interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_backup_session.h create mode 100644 interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_data.h create mode 100644 interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_restore_session.h create mode 100644 interfaces/kits/js/backup/incremental_backup_data.h create mode 100644 interfaces/kits/js/backup/session_incremental_backup_n_exporter.cpp create mode 100644 interfaces/kits/js/backup/session_incremental_backup_n_exporter.h create mode 100644 services/backup_sa/src/module_ipc/service_incremental.cpp create mode 100644 services/backup_sa/src/module_ipc/service_incremental_reverse_proxy.cpp create mode 100644 tools/backup_tool/include/tools_op_incremental_backup.h create mode 100644 tools/backup_tool/src/tools_op_incremental_backup.cpp create mode 100644 utils/include/b_filesystem/b_file_hash.h create mode 100644 utils/src/b_filesystem/b_file_hash.cpp diff --git a/bundle.json b/bundle.json index 0d0c382c7..991496713 100644 --- a/bundle.json +++ b/bundle.json @@ -41,7 +41,8 @@ ], "third_party": [ "bounds_checking_function", - "jsoncpp" + "jsoncpp", + "openssl" ] }, "adapted_system_type": [ "small", "standard" ], @@ -108,6 +109,9 @@ "header_base": "//foundation/filemanagement/app_file_service/interfaces/inner_api/native/backup_kit_inner", "header_files": [ "backup_kit_inner.h", + "impl/b_incremental_backup_session.h", + "impl/b_incremental_data.h", + "impl/b_incremental_restore_session.h", "impl/b_session_restore.h", "impl/b_session_restore_async.h", "impl/b_file_info.h", diff --git a/frameworks/native/backup_ext/include/ext_extension.h b/frameworks/native/backup_ext/include/ext_extension.h index c39e05fcd..8fd2b1799 100644 --- a/frameworks/native/backup_ext/include/ext_extension.h +++ b/frameworks/native/backup_ext/include/ext_extension.h @@ -25,6 +25,7 @@ #include "ext_backup_js.h" #include "ext_extension_stub.h" #include "thread_pool.h" +#include "unique_fd.h" namespace OHOS::FileManagement::Backup { class BackupExtExtension : public ExtExtensionStub { @@ -34,6 +35,9 @@ public: ErrCode PublishFile(const std::string &fileName) override; ErrCode HandleBackup() override; ErrCode HandleRestore() override; + ErrCode GetIncrementalFileHandle(const std::string &fileName) override; + ErrCode PublishIncrementalFile(const std::string &fileName) override; + ErrCode HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) override; void AsyncTaskRestoreForUpgrade(void); @@ -95,6 +99,28 @@ private: void AsyncTaskOnBackup(); + /** + * @brief IncrementalBackup + * + * @param incrementalFd storage fd + * @param manifestFd 云空间 fd + */ + int DoIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd); + + /** + * @brief AsyncTaskOnIncrementalBackup + * + * @param incrementalFd storage fd + * @param manifestFd 云空间 fd + */ + void AsyncTaskOnIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd); + + /** + * @brief extension incremental backup restore is done + * + * @param errCode + */ + void AppIncrementalDone(ErrCode errCode); private: std::shared_mutex lock_; std::shared_ptr extension_; diff --git a/frameworks/native/backup_ext/include/ext_extension_stub.h b/frameworks/native/backup_ext/include/ext_extension_stub.h index 806bf8595..08ccc2a88 100644 --- a/frameworks/native/backup_ext/include/ext_extension_stub.h +++ b/frameworks/native/backup_ext/include/ext_extension_stub.h @@ -36,6 +36,9 @@ private: ErrCode CmdHandleBackup(MessageParcel &data, MessageParcel &reply); ErrCode CmdPublishFile(MessageParcel &data, MessageParcel &reply); ErrCode CmdHandleRestore(MessageParcel &data, MessageParcel &reply); + ErrCode CmdGetIncrementalFileHandle(MessageParcel &data, MessageParcel &reply); + ErrCode CmdPublishIncrementalFile(MessageParcel &data, MessageParcel &reply); + ErrCode CmdHandleIncrementalBackup(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 083e4d7d4..52c24cf52 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -16,9 +16,12 @@ #include "ext_extension.h" #include +#include #include +#include #include #include +#include #include #include @@ -36,6 +39,7 @@ #include "b_error/b_excep_utils.h" #include "b_filesystem/b_dir.h" #include "b_filesystem/b_file.h" +#include "b_filesystem/b_file_hash.h" #include "b_json/b_json_cached_entity.h" #include "b_json/b_json_entity_ext_manage.h" #include "b_resources/b_constants.h" @@ -53,7 +57,24 @@ const string INDEX_FILE_BACKUP = string(BConstants::PATH_BUNDLE_BACKUP_HOME). const string INDEX_FILE_RESTORE = string(BConstants::PATH_BUNDLE_BACKUP_HOME). append(BConstants::SA_BUNDLE_BACKUP_RESTORE). append(BConstants::EXT_BACKUP_MANAGE); + +const string INDEX_FILE_INCREMENTAL_BACKUP = string(BConstants::PATH_BUNDLE_BACKUP_HOME). + append(BConstants::SA_BUNDLE_BACKUP_BACKUP); using namespace std; +struct FileInfo { + string filePath; + string mode; + string isDir; + int64_t size; + string lmtime; + string fileHash; + string isIncr = "0"; // 是否增量 +}; + +namespace { +const int64_t DEFAULT_SLICE_SIZE = 100 * 1024 * 1024; // 分片文件大小为100M +const uint32_t MAX_FILE_COUNT = 6000; // 单个tar包最多包含6000个文件 +} // namespace void BackupExtExtension::VerifyCaller() { @@ -805,4 +826,375 @@ ErrCode BackupExtExtension::HandleRestore() return 0; } + +static map GetIncrementalFile(const UniqueFd &fd) +{ + vector> infos = BFile::ReadIncrementalFile(fd); + map files; + if (infos.begin() != infos.end()) { + for (auto info : infos) { + string filePath = info.find("path") != info.end() ? info.find("path")->second : ""; + string mode = info.find("mode") != info.end() ? info.find("mode")->second : ""; + string dir = info.find("dir") != info.end() ? info.find("dir")->second : "0"; + int64_t size = 0; + try { + size = info.find("size") != info.end() ? stoll(info.find("size")->second) : 0; + } catch (const std::out_of_range &e) { + size = 0; + } + string mtime = info.find("mtime") != info.end() ? info.find("mtime")->second : "0"; + string isIncr = info.find("isIncr") != info.end() ? info.find("isIncr")->second : "0"; + string hash = info.find("hash") != info.end() ? info.find("hash")->second : ""; + struct FileInfo file; + file.filePath = filePath; + file.mode = mode; + file.isDir = dir; + file.lmtime = mtime; + file.size = size; + file.fileHash = hash; + file.isIncr = isIncr; + files.try_emplace(filePath, file); + } + } + return files; +} + +static tuple, map, map, + map> CompareFiles(const UniqueFd &cloudFd, const UniqueFd &storageFd) +{ + map cloudFiles = GetIncrementalFile(cloudFd); + map storageFiles = GetIncrementalFile(storageFd); + map allFiles = {}; + map smallFiles = {}; + map bigFiles = {}; + map bigInfos = {}; + for (auto &item : storageFiles) { + // 进行文件对比 + string path = item.first; + if (cloudFiles.find(path) == cloudFiles.end() || (item.second.isIncr == "1" + && (cloudFiles[path].size != item.second.size || cloudFiles[path].lmtime != item.second.lmtime))) { + auto [res, fileHash] = BFileHash::HashWithSHA256(path); + if (fileHash.empty()) { + continue; + } + item.second.fileHash = fileHash; + item.second.isIncr = "1"; + } else { + item.second.fileHash = cloudFiles[path].fileHash; + } + if (cloudFiles.find(path) == cloudFiles.end() || + (item.second.isIncr == "1" && cloudFiles.find(path)->second.fileHash != item.second.fileHash)) { + // 在云空间简报里不存在或者hash不一致 + // 区分大小文件 + struct stat sta = {}; + if (stat(path.c_str(), &sta) == -1) { + continue; + } + if (sta.st_size < BConstants::BIG_FILE_BOUNDARY) { + HILOGI("compareFiles Find small file"); + item.second.size = sta.st_size; + smallFiles.try_emplace(path, item.second); + } else { + HILOGI("compareFiles Find big file"); + bigFiles.try_emplace(path, sta); + bigInfos.try_emplace(path, item.second); + } + } + allFiles.try_emplace(path, item.second); + } + HILOGI("compareFiles Find small files total: %{public}d", smallFiles.size()); + HILOGI("compareFiles Find big files total: %{public}d", bigFiles.size()); + return {allFiles, smallFiles, bigFiles, bigInfos}; +} + +static void WriteFile(const string &filename, const map &srcFiles) +{ + fstream f; + f.open(filename.data(), ios::out); + // 前面2行先填充进去 + f << "version=1.0&attrNum=6" << endl; + f << "path;mode;dir;size;mtime;hash" << endl; + for (auto item : srcFiles) { + struct FileInfo info = item.second; + string str = item.first + ";" + info.mode + ";" + info.isDir + ";" + to_string(info.size); + str += ";" + info.lmtime + ";" + info.fileHash + ";"; + f << str << endl; + } + f.close(); + HILOGI("WriteFile path: %{public}s", filename.c_str()); +} + +/** + * 获取增量的大文件的信息 +*/ +static TarMap GetIncrmentBigInfos(const map &files) +{ + auto getStringHash = [](const TarMap &m, const string &str) -> string { + ostringstream strHex; + strHex << hex; + + hash strHash; + size_t szHash = strHash(str); + strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash; + string name = strHex.str(); + for (int i = 0; m.find(name) != m.end(); ++i, strHex.str("")) { + szHash = strHash(str + to_string(i)); + strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash; + name = strHex.str(); + } + + return name; + }; + + TarMap bigFiles; + for (const auto &item : files) { + string md5Name = getStringHash(bigFiles, item.first); + if (!md5Name.empty()) { + bigFiles.emplace(md5Name, make_tuple(item.first, item.second, true)); + } + } + + return bigFiles; +} + +/** + * 增量tar包和简报信息回传 +*/ +static ErrCode IncrementalTarFileReady(const TarMap &bigFileInfo, const map &srcFiles, sptr proxy) +{ + string tarFile = bigFileInfo.begin()->first; + string manageFile = ""; + if (tarFile.rfind(".tar") != string::npos) { + manageFile = tarFile.substr(0, tarFile.length() - 4).append(".txt"); + } else { + manageFile = tarFile + ".txt"; + } + + string file = string(INDEX_FILE_INCREMENTAL_BACKUP).append(manageFile); + WriteFile(file, srcFiles); + + string tarName = string(INDEX_FILE_INCREMENTAL_BACKUP).append(tarFile); + ErrCode ret = + proxy->AppIncrementalFileReady(tarName, UniqueFd(open(tarName.data(), O_RDONLY)), + UniqueFd(open(file.data(), O_RDONLY))); + if (SUCCEEDED(ret)) { + HILOGI("IncrementalTarFileReady: The application is packaged successfully"); + // 删除文件 + RemoveFile(file); + RemoveFile(tarName); + } else { + HILOGI("IncrementalTarFileReady interface fails to be invoked: %{public}d", ret); + } + return ret; +} + +/** + * 增量大文件和简报信息回传 +*/ +static ErrCode IncrementalBigFileReady(const TarMap &pkgInfo, const map &bigInfos, sptr proxy) +{ + ErrCode ret {ERR_OK}; + for (auto &item : pkgInfo) { + if (item.first.empty()) { + continue; + } + auto [path, sta, isBeforeTar] = item.second; + + UniqueFd fd(open(path.data(), O_RDONLY)); + if (fd < 0) { + HILOGE("IncrementalBigFileReady open file failed, file name is %{public}s, err = %{public}d", + path.c_str(), errno); + continue; + } + + struct FileInfo info = bigInfos.find(path)->second; + string file = string(INDEX_FILE_INCREMENTAL_BACKUP).append(item.first).append(".txt"); + HILOGE("IncrementalBigFileReady write name is %{public}s", path.c_str()); + map bigInfo; + bigInfo.try_emplace(path, info); + WriteFile(file, bigInfo); + + ret = proxy->AppIncrementalFileReady(item.first, std::move(fd), UniqueFd(open(file.data(), O_RDONLY))); + if (SUCCEEDED(ret)) { + HILOGI("IncrementalBigFileReady : The application is packaged successfully, package name is %{public}s", + item.first.c_str()); + RemoveFile(file); + } else { + HILOGI( + "IncrementalBigFileReady interface fails to be invoked: %{public}d", ret); + } + } + return ret; +} + +ErrCode BackupExtExtension::GetIncrementalFileHandle(const string &fileName) +{ + HILOGI("begin"); + return BError(BError::Codes::OK); +} + +ErrCode BackupExtExtension::PublishIncrementalFile(const string &fileName) +{ + HILOGI("begin"); + return BError(BError::Codes::OK); +} + +ErrCode BackupExtExtension::HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) +{ + string usrConfig = extension_->GetUsrConfig(); + BJsonCachedEntity cachedEntity(usrConfig); + auto cache = cachedEntity.Structuralize(); + if (!cache.GetAllowToBackupRestore()) { + HILOGE("Application does not allow backup or restore"); + return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore") + .GetCode(); + } + AsyncTaskOnIncrementalBackup(move(incrementalFd), move(manifestFd)); + return 0; +} + +void BackupExtExtension::AsyncTaskOnIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) +{ + auto task = [obj {wptr(this)}, ifd(incrementalFd.Get()), mfd(manifestFd.Get())]() { + auto ptr = obj.promote(); + try { + BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, + "Ext extension handle have been already released"); + BExcepUltils::BAssert(ptr->extension_, BError::Codes::EXT_INVAL_ARG, + "extension handle have been already released"); + + auto ret = ptr->DoIncrementalBackup(UniqueFd(ifd), UniqueFd(mfd)); + ptr->AppIncrementalDone(ret); + HILOGE("Incremental backup app done %{public}d", ret); + } catch (const BError &e) { + 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"); + } + }); +} + +static void IncrementalPacket(const map &infos, TarMap &tar, sptr proxy) +{ + HILOGE("IncrementalPacket begin"); + string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP); + int64_t totalSize = 0; + uint32_t fileCount = 0; + vector packFiles; + map tarInfos; + for (auto small : infos) { + totalSize += small.second.size; + fileCount += 1; + packFiles.emplace_back(small.first); + tarInfos.try_emplace(small.first, small.second); + if (totalSize >= DEFAULT_SLICE_SIZE || fileCount >= MAX_FILE_COUNT) { + TarMap tarMap {}; + TarFile::GetInstance().Packet(packFiles, "part", path, tarMap); + tar.insert(tarMap.begin(), tarMap.end()); + // 执行tar包回传功能 + IncrementalTarFileReady(tarMap, tarInfos, proxy); + totalSize = 0; + fileCount = 0; + packFiles.clear(); + tarInfos.clear(); + } + } + if (fileCount > 0) { + // 打包回传 + TarMap tarMap {}; + TarFile::GetInstance().Packet(packFiles, "part", path, tarMap); + IncrementalTarFileReady(tarMap, tarInfos, proxy); + tar.insert(tarMap.begin(), tarMap.end()); + packFiles.clear(); + tarInfos.clear(); + } +} + +static ErrCode IncrementalAllFileReady(const TarMap &pkgInfo, const map &srcFiles, + sptr proxy) +{ + BJsonCachedEntity cachedEntity( + UniqueFd(open(INDEX_FILE_BACKUP.data(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR))); + auto cache = cachedEntity.Structuralize(); + cache.SetExtManage(pkgInfo); + cachedEntity.Persist(); + close(cachedEntity.GetFd().Release()); + + string file = string(INDEX_FILE_INCREMENTAL_BACKUP).append("all.txt"); + WriteFile(file, srcFiles); + UniqueFd fd(open(INDEX_FILE_BACKUP.data(), O_RDONLY)); + UniqueFd manifestFd(open(file.data(), O_RDONLY)); + ErrCode ret = + proxy->AppIncrementalFileReady(string(BConstants::EXT_BACKUP_MANAGE), std::move(fd), std::move(manifestFd)); + if (SUCCEEDED(ret)) { + HILOGI("IncrementalAllFileReady successfully"); + RemoveFile(file); + } else { + HILOGI( + "successfully but the IncrementalAllFileReady interface fails to be invoked: %{public}d", ret); + } + return ret; +} + +int BackupExtExtension::DoIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) +{ + HILOGI("Do increment backup"); + if (extension_->GetExtensionAction() != BConstants::ExtensionAction::BACKUP) { + return EPERM; + } + + 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); + } + + // 获取增量文件和全量数据 + auto [allFiles, smallFiles, bigFiles, bigInfos] = CompareFiles(manifestFd, incrementalFd); + if (smallFiles.size() == 0 && bigFiles.size() == 0) { + // 没有增量,则不需要上传 + return ERR_OK; + } + + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno)); + } + // tar包数据 + TarMap tarMap; + IncrementalPacket(smallFiles, tarMap, proxy); + HILOGI("Do increment backup, IncrementalPacket end"); + + // 最后回传大文件 + TarMap bigMap = GetIncrmentBigInfos(bigFiles); + IncrementalBigFileReady(bigMap, bigInfos, proxy); + HILOGI("Do increment backup, IncrementalBigFileReady end"); + bigMap.insert(tarMap.begin(), tarMap.end()); + + // 回传manage.json和全量文件 + IncrementalAllFileReady(bigMap, allFiles, proxy); + HILOGI("Do increment backup, IncrementalAllFileReady end"); + return ERR_OK; +} + +void BackupExtExtension::AppIncrementalDone(ErrCode errCode) +{ + auto proxy = ServiceProxy::GetInstance(); + BExcepUltils::BAssert(proxy, BError::Codes::EXT_BROKEN_IPC, "Failed to obtain the ServiceProxy handle"); + auto ret = proxy->AppIncrementalDone(errCode); + if (ret != ERR_OK) { + HILOGE("Failed to notify the app done. err = %{public}d", ret); + } +} } // 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 c98380a37..373caeefa 100644 --- a/frameworks/native/backup_ext/src/ext_extension_stub.cpp +++ b/frameworks/native/backup_ext/src/ext_extension_stub.cpp @@ -37,6 +37,12 @@ ExtExtensionStub::ExtExtensionStub() &ExtExtensionStub::CmdPublishFile; opToInterfaceMap_[static_cast(IExtensionInterfaceCode::CMD_HANDLE_RESTORE)] = &ExtExtensionStub::CmdHandleRestore; + opToInterfaceMap_[static_cast(IExtensionInterfaceCode::CMD_GET_INCREMENTAL_FILE_HANDLE)] = + &ExtExtensionStub::CmdGetIncrementalFileHandle; + opToInterfaceMap_[static_cast(IExtensionInterfaceCode::CMD_PUBLISH_INCREMENTAL_FILE)] = + &ExtExtensionStub::CmdPublishIncrementalFile; + opToInterfaceMap_[static_cast(IExtensionInterfaceCode::CMD_HANDLE_INCREMENTAL_BACKUP)] = + &ExtExtensionStub::CmdHandleIncrementalBackup; } int32_t ExtExtensionStub::OnRemoteRequest(uint32_t code, @@ -128,4 +134,50 @@ ErrCode ExtExtensionStub::CmdHandleRestore(MessageParcel &data, MessageParcel &r } return BError(BError::Codes::OK); } + +ErrCode ExtExtensionStub::CmdGetIncrementalFileHandle(MessageParcel &data, MessageParcel &reply) +{ + HILOGI("Begin"); + string fileName; + if (!data.ReadString(fileName)) { + return BError(BError::Codes::EXT_INVAL_ARG, "Failed to receive fileName").GetCode(); + } + + ErrCode res = GetIncrementalFileHandle(fileName); + if (!reply.WriteInt32(res)) { + return BError(BError::Codes::EXT_BROKEN_IPC, "Failed to send out the file").GetCode(); + } + return BError(BError::Codes::OK); +} + +ErrCode ExtExtensionStub::CmdPublishIncrementalFile(MessageParcel &data, MessageParcel &reply) +{ + HILOGI("Begin"); + string fileName; + if (!data.ReadString(fileName)) { + return BError(BError::Codes::EXT_INVAL_ARG, "Failed to receive fileName"); + } + + ErrCode res = PublishIncrementalFile(fileName); + if (!reply.WriteInt32(res)) { + stringstream ss; + ss << "Failed to send the result " << res; + return BError(BError::Codes::EXT_BROKEN_IPC, ss.str()).GetCode(); + } + return BError(BError::Codes::OK); +} + +ErrCode ExtExtensionStub::CmdHandleIncrementalBackup(MessageParcel &data, MessageParcel &reply) +{ + HILOGI("Begin"); + UniqueFd incrementalFd(data.ReadFileDescriptor()); + UniqueFd manifestFd(data.ReadFileDescriptor()); + ErrCode res = HandleIncrementalBackup(move(incrementalFd), move(manifestFd)); + if (!reply.WriteInt32(res)) { + stringstream ss; + ss << "Failed to send the result " << res; + return BError(BError::Codes::EXT_BROKEN_IPC, ss.str()).GetCode(); + } + return BError(BError::Codes::OK); +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/frameworks/native/backup_kit_inner/include/service_reverse.h b/frameworks/native/backup_kit_inner/include/service_reverse.h index f0810e14a..92b22c47e 100644 --- a/frameworks/native/backup_kit_inner/include/service_reverse.h +++ b/frameworks/native/backup_kit_inner/include/service_reverse.h @@ -18,6 +18,8 @@ #include "b_session_backup.h" #include "b_session_restore.h" +#include "b_incremental_backup_session.h" +#include "b_incremental_restore_session.h" #include "service_reverse_stub.h" namespace OHOS::FileManagement::Backup { @@ -33,16 +35,30 @@ public: void RestoreOnAllBundlesFinished(int32_t errCode) override; void RestoreOnFileReady(std::string bundleName, std::string fileName, int fd) override; + void IncrementalBackupOnFileReady(std::string bundleName, std::string fileName, int fd, int manifestFd) override; + void IncrementalBackupOnBundleStarted(int32_t errCode, std::string bundleName) override; + void IncrementalBackupOnBundleFinished(int32_t errCode, std::string bundleName) override; + void IncrementalBackupOnAllBundlesFinished(int32_t errCode) override; + + void IncrementalRestoreOnBundleStarted(int32_t errCode, std::string bundleName) override; + void IncrementalRestoreOnBundleFinished(int32_t errCode, std::string bundleName) override; + void IncrementalRestoreOnAllBundlesFinished(int32_t errCode) override; + void IncrementalRestoreOnFileReady(std::string bundleName, std::string fileName, int fd, int manifestFd) override; + public: ServiceReverse() = delete; explicit ServiceReverse(BSessionRestore::Callbacks callbacks); explicit ServiceReverse(BSessionBackup::Callbacks callbacks); + explicit ServiceReverse(BIncrementalBackupSession::Callbacks callbacks); + explicit ServiceReverse(BIncrementalRestoreSession::Callbacks callbacks); ~ServiceReverse() override = default; private: Scenario scenario_ {Scenario::UNDEFINED}; BSessionBackup::Callbacks callbacksBackup_; BSessionRestore::Callbacks callbacksRestore_; + BIncrementalBackupSession::Callbacks callbacksIncrementalBackup_; + BIncrementalRestoreSession::Callbacks callbacksIncrementalRestore_; }; } // namespace OHOS::FileManagement::Backup diff --git a/frameworks/native/backup_kit_inner/include/service_reverse_stub.h b/frameworks/native/backup_kit_inner/include/service_reverse_stub.h index 5c46907b2..ea1e5f8be 100644 --- a/frameworks/native/backup_kit_inner/include/service_reverse_stub.h +++ b/frameworks/native/backup_kit_inner/include/service_reverse_stub.h @@ -43,6 +43,16 @@ private: int32_t CmdRestoreOnBundleFinished(MessageParcel &data, MessageParcel &reply); int32_t CmdRestoreOnAllBundlesFinished(MessageParcel &data, MessageParcel &reply); int32_t CmdRestoreOnFileReady(MessageParcel &data, MessageParcel &reply); + + int32_t CmdIncrementalBackupOnFileReady(MessageParcel &data, MessageParcel &reply); + int32_t CmdIncrementalBackupOnBundleStarted(MessageParcel &data, MessageParcel &reply); + int32_t CmdIncrementalBackupOnBundleFinished(MessageParcel &data, MessageParcel &reply); + int32_t CmdIncrementalBackupOnAllBundlesFinished(MessageParcel &data, MessageParcel &reply); + + int32_t CmdIncrementalRestoreOnBundleStarted(MessageParcel &data, MessageParcel &reply); + int32_t CmdIncrementalRestoreOnBundleFinished(MessageParcel &data, MessageParcel &reply); + int32_t CmdIncrementalRestoreOnAllBundlesFinished(MessageParcel &data, MessageParcel &reply); + int32_t CmdIncrementalRestoreOnFileReady(MessageParcel &data, MessageParcel &reply); }; } // namespace OHOS::FileManagement::Backup diff --git a/frameworks/native/backup_kit_inner/src/b_incremental_backup_session.cpp b/frameworks/native/backup_kit_inner/src/b_incremental_backup_session.cpp new file mode 100644 index 000000000..9d17428c1 --- /dev/null +++ b/frameworks/native/backup_kit_inner/src/b_incremental_backup_session.cpp @@ -0,0 +1,107 @@ +/* + * 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_backup_session.h" + +#include "b_error/b_error.h" +#include "filemgmt_libhilog.h" +#include "service_proxy.h" +#include "service_reverse.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; + +BIncrementalBackupSession::~BIncrementalBackupSession() +{ + if (!deathRecipient_) { + HILOGI("Death Recipient is nullptr"); + return; + } + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + return; + } + auto remoteObject = proxy->AsObject(); + if (remoteObject != nullptr) { + remoteObject->RemoveDeathRecipient(deathRecipient_); + } + deathRecipient_ = nullptr; +} + +unique_ptr BIncrementalBackupSession::Init(Callbacks callbacks) +{ + try { + auto backup = make_unique(); + ServiceProxy::InvaildInstance(); + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + HILOGI("Failed to get backup service"); + return nullptr; + } + + int32_t res = proxy->InitIncrementalBackupSession(sptr(new ServiceReverse(callbacks))); + if (res != 0) { + HILOGE("Failed to Backup because of %{public}d", res); + return nullptr; + } + + backup->RegisterBackupServiceDied(callbacks.onBackupServiceDied); + return backup; + } catch (const exception &e) { + HILOGE("Failed to Backup because of %{public}s", e.what()); + } + return nullptr; +} + +void BIncrementalBackupSession::RegisterBackupServiceDied(function functor) +{ + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr || !functor) { + return; + } + auto remoteObj = proxy->AsObject(); + if (!remoteObj) { + throw BError(BError::Codes::SA_BROKEN_IPC, "Proxy's remote object can't be nullptr"); + } + + auto callback = [functor](const wptr &obj) { + ServiceProxy::InvaildInstance(); + HILOGI("Backup service died"); + functor(); + }; + deathRecipient_ = sptr(new SvcDeathRecipient(callback)); + remoteObj->AddDeathRecipient(deathRecipient_); +} + +ErrCode BIncrementalBackupSession::AppendBundles(vector bundlesToBackup) +{ + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + return BError(BError::Codes::SDK_BROKEN_IPC, "Failed to get backup service").GetCode(); + } + + return proxy->AppendBundlesIncrementalBackupSession(bundlesToBackup); +} + +ErrCode BIncrementalBackupSession::Release() +{ + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + return BError(BError::Codes::SDK_BROKEN_IPC, "Failed to get backup service").GetCode(); + } + + return proxy->Release(); +} +} // namespace OHOS::FileManagement::Backup \ No newline at end of file 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 000000000..2b4388685 --- /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.WriteInt32(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.ReadInt32(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/frameworks/native/backup_kit_inner/src/b_incremental_restore_session.cpp b/frameworks/native/backup_kit_inner/src/b_incremental_restore_session.cpp new file mode 100644 index 000000000..9a9fe5abc --- /dev/null +++ b/frameworks/native/backup_kit_inner/src/b_incremental_restore_session.cpp @@ -0,0 +1,125 @@ +/* + * 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_restore_session.h" + +#include "b_error/b_error.h" +#include "filemgmt_libhilog.h" +#include "service_proxy.h" +#include "service_reverse.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; + +BIncrementalRestoreSession::~BIncrementalRestoreSession() +{ + if (!deathRecipient_) { + HILOGI("Death Recipient is nullptr"); + return; + } + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + return; + } + auto remoteObject = proxy->AsObject(); + if (remoteObject != nullptr) { + remoteObject->RemoveDeathRecipient(deathRecipient_); + } + deathRecipient_ = nullptr; +} + +unique_ptr BIncrementalRestoreSession::Init(Callbacks callbacks) +{ + try { + auto restore = make_unique(); + ServiceProxy::InvaildInstance(); + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + HILOGI("Failed to get backup service"); + return nullptr; + } + int32_t res = proxy->InitRestoreSession(new ServiceReverse(callbacks)); + if (res != 0) { + HILOGE("Failed to Restore because of %{public}d", res); + return nullptr; + } + + restore->RegisterBackupServiceDied(callbacks.onBackupServiceDied); + return restore; + } catch (const exception &e) { + HILOGE("Failed to Restore because of %{public}s", e.what()); + } + return nullptr; +} + +ErrCode BIncrementalRestoreSession::PublishFile(BFileInfo fileInfo) +{ + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + return BError(BError::Codes::SDK_BROKEN_IPC, "Failed to get backup service").GetCode(); + } + return proxy->PublishIncrementalFile(fileInfo); +} + +ErrCode BIncrementalRestoreSession::GetFileHandle(const string &bundleName, const string &fileName) +{ + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + return BError(BError::Codes::SDK_BROKEN_IPC, "Failed to get backup service").GetCode(); + } + + return proxy->GetIncrementalFileHandle(bundleName, fileName); +} + +ErrCode BIncrementalRestoreSession::AppendBundles(UniqueFd remoteCap, vector bundlesToRestore) +{ + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + return BError(BError::Codes::SDK_BROKEN_IPC, "Failed to get backup service").GetCode(); + } + + return proxy->AppendBundlesRestoreSession(move(remoteCap), bundlesToRestore); +} + +ErrCode BIncrementalRestoreSession::Release() +{ + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + return BError(BError::Codes::SDK_BROKEN_IPC, "Failed to get backup service").GetCode(); + } + + return proxy->Release(); +} + +void BIncrementalRestoreSession::RegisterBackupServiceDied(function functor) +{ + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr || !functor) { + return; + } + auto remoteObj = proxy->AsObject(); + if (!remoteObj) { + throw BError(BError::Codes::SA_BROKEN_IPC, "Proxy's remote object can't be nullptr"); + } + + auto callback = [functor](const wptr &obj) { + HILOGI("Backup service died"); + ServiceProxy::InvaildInstance(); + functor(); + }; + deathRecipient_ = sptr(new SvcDeathRecipient(callback)); + remoteObj->AddDeathRecipient(deathRecipient_); +} +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/frameworks/native/backup_kit_inner/src/b_session_backup.cpp b/frameworks/native/backup_kit_inner/src/b_session_backup.cpp index e89285aba..d96ef7847 100644 --- a/frameworks/native/backup_kit_inner/src/b_session_backup.cpp +++ b/frameworks/native/backup_kit_inner/src/b_session_backup.cpp @@ -114,4 +114,14 @@ ErrCode BSessionBackup::Finish() return proxy->Finish(); } + +ErrCode BSessionBackup::Release() +{ + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + return BError(BError::Codes::SDK_BROKEN_IPC, "Failed to get backup service").GetCode(); + } + + return proxy->Release(); +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/frameworks/native/backup_kit_inner/src/b_session_restore.cpp b/frameworks/native/backup_kit_inner/src/b_session_restore.cpp index 59a6d67e4..f41ea469b 100644 --- a/frameworks/native/backup_kit_inner/src/b_session_restore.cpp +++ b/frameworks/native/backup_kit_inner/src/b_session_restore.cpp @@ -113,6 +113,16 @@ ErrCode BSessionRestore::Finish() return proxy->Finish(); } +ErrCode BSessionRestore::Release() +{ + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + return BError(BError::Codes::SDK_BROKEN_IPC, "Failed to get backup service").GetCode(); + } + + return proxy->Release(); +} + void BSessionRestore::RegisterBackupServiceDied(std::function functor) { auto proxy = ServiceProxy::GetInstance(); diff --git a/frameworks/native/backup_kit_inner/src/b_session_restore_async.cpp b/frameworks/native/backup_kit_inner/src/b_session_restore_async.cpp index a0a38653c..4416e873b 100644 --- a/frameworks/native/backup_kit_inner/src/b_session_restore_async.cpp +++ b/frameworks/native/backup_kit_inner/src/b_session_restore_async.cpp @@ -104,6 +104,16 @@ ErrCode BSessionRestoreAsync::AppendBundles(UniqueFd remoteCap, return proxy->AppendBundlesRestoreSession(move(remoteCap), bundlesToRestore, restoreType, userId); } +ErrCode BSessionRestoreAsync::Release() +{ + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + return BError(BError::Codes::SDK_BROKEN_IPC, "Failed to get backup service").GetCode(); + } + + return proxy->Release(); +} + void BSessionRestoreAsync::RegisterBackupServiceDied(std::function functor) { auto proxy = ServiceProxy::GetInstance(); diff --git a/frameworks/native/backup_kit_inner/src/service_incremental_proxy.cpp b/frameworks/native/backup_kit_inner/src/service_incremental_proxy.cpp new file mode 100644 index 000000000..ea227c5a3 --- /dev/null +++ b/frameworks/native/backup_kit_inner/src/service_incremental_proxy.cpp @@ -0,0 +1,263 @@ +/* + * 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 "service_proxy.h" + +#include "iservice_registry.h" +#include "system_ability_definition.h" + +#include "b_error/b_error.h" +#include "b_error/b_excep_utils.h" +#include "b_resources/b_constants.h" +#include "filemgmt_libhilog.h" +#include "svc_death_recipient.h" +#include "unique_fd.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; + +ErrCode ServiceProxy::Release() +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor())) { + return BError(BError::Codes::SDK_INVAL_ARG, "Failed to write descriptor").GetCode(); + } + + MessageParcel reply; + MessageOption option; + int32_t ret = Remote()->SendRequest(static_cast(IServiceInterfaceCode::SERVICE_CMD_RELSEASE_SESSION), + data, reply, option); + if (ret != NO_ERROR) { + string str = "Failed to send out the request because of " + to_string(ret); + return BError(BError::Codes::SDK_INVAL_ARG, str.data()).GetCode(); + } + return reply.ReadInt32(); +} + +UniqueFd ServiceProxy::GetLocalCapabilitiesIncremental(const vector &bundleNames) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor())) { + HILOGE("Failed to write descriptor"); + return UniqueFd(-EPERM); + } + + if (!WriteParcelableVector(bundleNames, data)) { + HILOGE("Failed to send the bundleNames"); + return UniqueFd(-EPERM); + } + + MessageParcel reply; + MessageOption option; + option.SetWaitTime(BConstants::IPC_MAX_WAIT_TIME); + int32_t ret = Remote()->SendRequest( + static_cast(IServiceInterfaceCode::SERVICE_CMD_GET_LOCAL_CAPABILITIES_INCREMENTAL), data, reply, + option); + if (ret != NO_ERROR) { + HILOGE("Received error %{public}d when doing IPC", ret); + return UniqueFd(-ret); + } + UniqueFd fd(reply.ReadFileDescriptor()); + return UniqueFd(fd.Release()); +} + +ErrCode ServiceProxy::InitIncrementalBackupSession(sptr remote) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor())) { + HILOGE("Failed to write descriptor"); + return BError(BError::Codes::SDK_INVAL_ARG, "Failed to write descriptor").GetCode(); + } + + MessageParcel reply; + MessageOption option; + + if (!remote) { + HILOGE("Empty reverse stub"); + return BError(BError::Codes::SDK_INVAL_ARG, "Empty reverse stub").GetCode(); + } + if (!data.WriteRemoteObject(remote->AsObject().GetRefPtr())) { + HILOGE("Failed to send the reverse stub"); + return BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the reverse stub").GetCode(); + } + + int32_t ret = Remote()->SendRequest( + static_cast(IServiceInterfaceCode::SERVICE_CMD_INIT_INCREMENTAL_BACKUP_SESSION), data, reply, option); + if (ret != NO_ERROR) { + HILOGE("Received error %{public}d when doing IPC", ret); + return BError(BError::Codes::SDK_INVAL_ARG, "Received error when doing IPC").GetCode(); + } + return reply.ReadInt32(); +} + +ErrCode ServiceProxy::AppendBundlesIncrementalBackupSession(const vector &bundlesToBackup) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor())) { + HILOGE("Failed to write descriptor"); + return BError(BError::Codes::SDK_INVAL_ARG, "Failed to write descriptor").GetCode(); + } + + if (!WriteParcelableVector(bundlesToBackup, data)) { + HILOGE("Failed to send the bundleNames"); + return UniqueFd(-EPERM); + } + + MessageParcel reply; + MessageOption option; + + int32_t ret = Remote()->SendRequest( + static_cast(IServiceInterfaceCode::SERVICE_CMD_APPEND_BUNDLES_INCREMENTAL_BACKUP_SESSION), data, + reply, option); + if (ret != NO_ERROR) { + HILOGE("Received error %{public}d when doing IPC", ret); + return BError(BError::Codes::SDK_INVAL_ARG, "Received error when doing IPC").GetCode(); + } + return reply.ReadInt32(); +} + +ErrCode ServiceProxy::PublishIncrementalFile(const BFileInfo &fileInfo) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor())) { + return BError(BError::Codes::SDK_INVAL_ARG, "Failed to write descriptor").GetCode(); + } + + if (!data.WriteParcelable(&fileInfo)) { + HILOGE("Failed to send the fileInfo"); + return -EPIPE; + } + + MessageParcel reply; + MessageOption option; + int32_t ret = Remote()->SendRequest( + static_cast(IServiceInterfaceCode::SERVICE_CMD_PUBLISH_INCREMENTAL_FILE), data, reply, option); + if (ret != NO_ERROR) { + string str = "Failed to send out the request because of " + to_string(ret); + return BError(BError::Codes::SDK_INVAL_ARG, str.data()).GetCode(); + } + return reply.ReadInt32(); +} + +ErrCode ServiceProxy::AppIncrementalFileReady(const std::string &fileName, UniqueFd fd, UniqueFd manifestFd) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor())) { + return BError(BError::Codes::SDK_INVAL_ARG, "Failed to write descriptor").GetCode(); + } + + if (!data.WriteString(fileName)) { + return BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the filename").GetCode(); + } + if (!data.WriteFileDescriptor(fd)) { + return BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the fd").GetCode(); + } + if (!data.WriteFileDescriptor(manifestFd)) { + return BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the fd").GetCode(); + } + + MessageParcel reply; + MessageOption option; + int32_t ret = Remote()->SendRequest( + static_cast(IServiceInterfaceCode::SERVICE_CMD_APP_INCREMENTAL_FILE_READY), data, reply, option); + if (ret != NO_ERROR) { + string str = "Failed to send out the request because of " + to_string(ret); + return BError(BError::Codes::SDK_INVAL_ARG, str.data()).GetCode(); + } + return reply.ReadInt32(); +} + +ErrCode ServiceProxy::AppIncrementalDone(ErrCode errCode) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor())) { + return BError(BError::Codes::SDK_INVAL_ARG, "Failed to write descriptor").GetCode(); + } + + if (!data.WriteInt32(errCode)) { + return BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the errCode").GetCode(); + } + + MessageParcel reply; + MessageOption option; + int32_t ret = Remote()->SendRequest(static_cast(IServiceInterfaceCode::SERVICE_CMD_APP_INCREMENTAL_DONE), + data, reply, option); + if (ret != NO_ERROR) { + string str = "Failed to send out the request because of " + to_string(ret); + return BError(BError::Codes::SDK_INVAL_ARG, str.data()).GetCode(); + } + return reply.ReadInt32(); +} + +ErrCode ServiceProxy::GetIncrementalFileHandle(const std::string &bundleName, const std::string &fileName) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor())) { + return BError(BError::Codes::SDK_INVAL_ARG, "Failed to write descriptor").GetCode(); + } + + if (!data.WriteString(bundleName)) { + return BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the bundleName").GetCode(); + } + if (!data.WriteString(fileName)) { + return BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the fileName").GetCode(); + } + + MessageParcel reply; + MessageOption option; + option.SetFlags(MessageOption::TF_ASYNC); + int32_t ret = Remote()->SendRequest( + static_cast(IServiceInterfaceCode::SERVICE_CMD_GET_INCREMENTAL_FILE_NAME), data, reply, option); + if (ret != NO_ERROR) { + string str = "Failed to send out the request because of " + to_string(ret); + return BError(BError::Codes::SDK_INVAL_ARG, str.data()).GetCode(); + } + return ret; +} + +template +bool ServiceProxy::WriteParcelableVector(const std::vector &parcelableVector, Parcel &data) +{ + if (!data.WriteUint32(parcelableVector.size())) { + HILOGE("failed to WriteInt32 for parcelableVector.size()"); + return false; + } + + for (const auto &parcelable : parcelableVector) { + if (!data.WriteParcelable(&parcelable)) { + HILOGE("failed to WriteParcelable for parcelable"); + return false; + } + } + + return true; +} +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/frameworks/native/backup_kit_inner/src/service_incremental_reverse.cpp b/frameworks/native/backup_kit_inner/src/service_incremental_reverse.cpp new file mode 100644 index 000000000..5378ac946 --- /dev/null +++ b/frameworks/native/backup_kit_inner/src/service_incremental_reverse.cpp @@ -0,0 +1,115 @@ +/* + * 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 "service_reverse.h" + +#include "b_error/b_error.h" +#include "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; + +void ServiceReverse::IncrementalBackupOnFileReady(string bundleName, string fileName, int fd, int manifestFd) +{ + HILOGI("begin"); + if (scenario_ != Scenario::BACKUP || !callbacksIncrementalBackup_.onFileReady) { + HILOGI("Error scenario or callback is nullptr"); + return; + } + BFileInfo bFileInfo(bundleName, fileName, 0); + callbacksIncrementalBackup_.onFileReady(bFileInfo, UniqueFd(fd), UniqueFd(manifestFd)); +} + +void ServiceReverse::IncrementalBackupOnBundleStarted(int32_t errCode, string bundleName) +{ + HILOGI("begin"); + if (scenario_ != Scenario::BACKUP || !callbacksIncrementalBackup_.onBundleStarted) { + HILOGI("Error scenario or callback is nullptr"); + return; + } + callbacksIncrementalBackup_.onBundleStarted(errCode, bundleName); +} + +void ServiceReverse::IncrementalBackupOnBundleFinished(int32_t errCode, string bundleName) +{ + HILOGI("begin"); + if (scenario_ != Scenario::BACKUP || !callbacksIncrementalBackup_.onBundleFinished) { + HILOGI("Error scenario or callback is nullptr"); + return; + } + callbacksIncrementalBackup_.onBundleFinished(errCode, bundleName); +} + +void ServiceReverse::IncrementalBackupOnAllBundlesFinished(int32_t errCode) +{ + HILOGI("errCode = %{public}d", errCode); + if (scenario_ != Scenario::BACKUP || !callbacksIncrementalBackup_.onAllBundlesFinished) { + HILOGI("Error scenario or callback is nullptr"); + return; + } + callbacksIncrementalBackup_.onAllBundlesFinished(errCode); +} + +void ServiceReverse::IncrementalRestoreOnBundleStarted(int32_t errCode, string bundleName) +{ + HILOGI("begin"); + if (scenario_ != Scenario::RESTORE || !callbacksIncrementalRestore_.onBundleStarted) { + HILOGI("Error scenario or callback is nullptr"); + return; + } + callbacksIncrementalRestore_.onBundleStarted(errCode, bundleName); +} + +void ServiceReverse::IncrementalRestoreOnBundleFinished(int32_t errCode, string bundleName) +{ + HILOGI("begin"); + if (scenario_ != Scenario::RESTORE || !callbacksIncrementalRestore_.onBundleFinished) { + HILOGI("Error scenario or callback is nullptr"); + return; + } + callbacksIncrementalRestore_.onBundleFinished(errCode, bundleName); +} + +void ServiceReverse::IncrementalRestoreOnAllBundlesFinished(int32_t errCode) +{ + HILOGI("errCode = %{public}d", errCode); + if (scenario_ != Scenario::RESTORE || !callbacksIncrementalRestore_.onAllBundlesFinished) { + HILOGI("Error scenario or callback is nullptr"); + return; + } + callbacksIncrementalRestore_.onAllBundlesFinished(errCode); +} + +void ServiceReverse::IncrementalRestoreOnFileReady(string bundleName, string fileName, int fd, int manifestFd) +{ + HILOGI("begin"); + if (scenario_ != Scenario::RESTORE || !callbacksIncrementalRestore_.onFileReady) { + HILOGI("Error scenario or callback is nullptr"); + return; + } + BFileInfo bFileInfo(bundleName, fileName, 0); + callbacksIncrementalRestore_.onFileReady(bFileInfo, UniqueFd(fd), UniqueFd(manifestFd)); +} + +ServiceReverse::ServiceReverse(BIncrementalBackupSession::Callbacks callbacks) + : scenario_(Scenario::BACKUP), callbacksIncrementalBackup_(callbacks) +{ +} + +ServiceReverse::ServiceReverse(BIncrementalRestoreSession::Callbacks callbacks) + : scenario_(Scenario::RESTORE), callbacksIncrementalRestore_(callbacks) +{ +} +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/frameworks/native/backup_kit_inner/src/service_reverse_stub.cpp b/frameworks/native/backup_kit_inner/src/service_reverse_stub.cpp index 7cfcb79c0..cda7f3521 100644 --- a/frameworks/native/backup_kit_inner/src/service_reverse_stub.cpp +++ b/frameworks/native/backup_kit_inner/src/service_reverse_stub.cpp @@ -63,6 +63,30 @@ ServiceReverseStub::ServiceReverseStub() &ServiceReverseStub::CmdRestoreOnAllBundlesFinished; opToInterfaceMap_[static_cast(IServiceReverseInterfaceCode::SERVICER_RESTORE_ON_FILE_READY)] = &ServiceReverseStub::CmdRestoreOnFileReady; + + opToInterfaceMap_[static_cast(IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_BACKUP_ON_FILE_READY)] = + &ServiceReverseStub::CmdIncrementalBackupOnFileReady; + opToInterfaceMap_[static_cast( + IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_BACKUP_ON_SUB_TASK_STARTED)] = + &ServiceReverseStub::CmdIncrementalBackupOnBundleStarted; + opToInterfaceMap_[static_cast( + IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_BACKUP_ON_SUB_TASK_FINISHED)] = + &ServiceReverseStub::CmdIncrementalBackupOnBundleFinished; + opToInterfaceMap_[static_cast( + IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_BACKUP_ON_TASK_FINISHED)] = + &ServiceReverseStub::CmdIncrementalBackupOnAllBundlesFinished; + + opToInterfaceMap_[static_cast( + IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_RESTORE_ON_SUB_TASK_STARTED)] = + &ServiceReverseStub::CmdIncrementalRestoreOnBundleStarted; + opToInterfaceMap_[static_cast( + IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_RESTORE_ON_SUB_TASK_FINISHED)] = + &ServiceReverseStub::CmdIncrementalRestoreOnBundleFinished; + opToInterfaceMap_[static_cast( + IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_RESTORE_ON_TASK_FINISHED)] = + &ServiceReverseStub::CmdIncrementalRestoreOnAllBundlesFinished; + opToInterfaceMap_[static_cast(IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_RESTORE_ON_FILE_READY)] = + &ServiceReverseStub::CmdIncrementalRestoreOnFileReady; } int32_t ServiceReverseStub::CmdBackupOnFileReady(MessageParcel &data, MessageParcel &reply) @@ -128,4 +152,70 @@ int32_t ServiceReverseStub::CmdRestoreOnFileReady(MessageParcel &data, MessagePa RestoreOnFileReady(bundleName, fileName, fd); return BError(BError::Codes::OK); } + +int32_t ServiceReverseStub::CmdIncrementalBackupOnFileReady(MessageParcel &data, MessageParcel &reply) +{ + auto bundleName = data.ReadString(); + auto fileName = data.ReadString(); + int fd = data.ReadFileDescriptor(); + int manifestFd = data.ReadFileDescriptor(); + IncrementalBackupOnFileReady(bundleName, fileName, fd, manifestFd); + return BError(BError::Codes::OK); +} + +int32_t ServiceReverseStub::CmdIncrementalBackupOnBundleStarted(MessageParcel &data, MessageParcel &reply) +{ + int32_t errCode = data.ReadInt32(); + auto bundleName = data.ReadString(); + IncrementalBackupOnBundleStarted(errCode, bundleName); + return BError(BError::Codes::OK); +} + +int32_t ServiceReverseStub::CmdIncrementalBackupOnBundleFinished(MessageParcel &data, MessageParcel &reply) +{ + int32_t errCode = data.ReadInt32(); + auto bundleName = data.ReadString(); + IncrementalBackupOnBundleFinished(errCode, bundleName); + return BError(BError::Codes::OK); +} + +int32_t ServiceReverseStub::CmdIncrementalBackupOnAllBundlesFinished(MessageParcel &data, MessageParcel &reply) +{ + int32_t errCode = data.ReadInt32(); + IncrementalBackupOnAllBundlesFinished(errCode); + return BError(BError::Codes::OK); +} + +int32_t ServiceReverseStub::CmdIncrementalRestoreOnBundleStarted(MessageParcel &data, MessageParcel &reply) +{ + int32_t errCode = data.ReadInt32(); + auto bundleName = data.ReadString(); + IncrementalRestoreOnBundleStarted(errCode, bundleName); + return BError(BError::Codes::OK); +} + +int32_t ServiceReverseStub::CmdIncrementalRestoreOnBundleFinished(MessageParcel &data, MessageParcel &reply) +{ + int32_t errCode = data.ReadInt32(); + auto bundleName = data.ReadString(); + IncrementalRestoreOnBundleFinished(errCode, bundleName); + return BError(BError::Codes::OK); +} + +int32_t ServiceReverseStub::CmdIncrementalRestoreOnAllBundlesFinished(MessageParcel &data, MessageParcel &reply) +{ + int32_t errCode = data.ReadInt32(); + IncrementalRestoreOnAllBundlesFinished(errCode); + return BError(BError::Codes::OK); +} + +int32_t ServiceReverseStub::CmdIncrementalRestoreOnFileReady(MessageParcel &data, MessageParcel &reply) +{ + auto bundleName = data.ReadString(); + auto fileName = data.ReadString(); + int fd = data.ReadFileDescriptor(); + int manifestFd = data.ReadFileDescriptor(); + IncrementalRestoreOnFileReady(bundleName, fileName, fd, manifestFd); + 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/BUILD.gn b/interfaces/inner_api/native/backup_kit_inner/BUILD.gn index 5d4dcbd28..02da6b9fd 100644 --- a/interfaces/inner_api/native/backup_kit_inner/BUILD.gn +++ b/interfaces/inner_api/native/backup_kit_inner/BUILD.gn @@ -43,9 +43,14 @@ ohos_shared_library("backup_kit_inner") { sources = [ "${path_backup}/frameworks/native/backup_kit_inner/src/b_file_info.cpp", + "${path_backup}/frameworks/native/backup_kit_inner/src/b_incremental_backup_session.cpp", + "${path_backup}/frameworks/native/backup_kit_inner/src/b_incremental_data.cpp", + "${path_backup}/frameworks/native/backup_kit_inner/src/b_incremental_restore_session.cpp", "${path_backup}/frameworks/native/backup_kit_inner/src/b_session_backup.cpp", "${path_backup}/frameworks/native/backup_kit_inner/src/b_session_restore.cpp", "${path_backup}/frameworks/native/backup_kit_inner/src/b_session_restore_async.cpp", + "${path_backup}/frameworks/native/backup_kit_inner/src/service_incremental_proxy.cpp", + "${path_backup}/frameworks/native/backup_kit_inner/src/service_incremental_reverse.cpp", "${path_backup}/frameworks/native/backup_kit_inner/src/service_proxy.cpp", "${path_backup}/frameworks/native/backup_kit_inner/src/service_reverse.cpp", "${path_backup}/frameworks/native/backup_kit_inner/src/service_reverse_stub.cpp", diff --git a/interfaces/inner_api/native/backup_kit_inner/backup_kit_inner.h b/interfaces/inner_api/native/backup_kit_inner/backup_kit_inner.h index 7277da994..dfe4e48a4 100644 --- a/interfaces/inner_api/native/backup_kit_inner/backup_kit_inner.h +++ b/interfaces/inner_api/native/backup_kit_inner/backup_kit_inner.h @@ -16,6 +16,8 @@ #ifndef OHOS_FILEMGMT_BACKUP_BACKUP_KIT_INNER_H #define OHOS_FILEMGMT_BACKUP_BACKUP_KIT_INNER_H +#include "impl/b_incremental_backup_session.h" +#include "impl/b_incremental_restore_session.h" #include "impl/b_session_backup.h" #include "impl/b_session_restore.h" #include "impl/b_session_restore_async.h" diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_backup_session.h b/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_backup_session.h new file mode 100644 index 000000000..c0805aa79 --- /dev/null +++ b/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_backup_session.h @@ -0,0 +1,79 @@ +/* + * 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_BACKUP_BACKUP_H +#define OHOS_FILEMGMT_BACKUP_B_INCREMENTAL_BACKUP_BACKUP_H + +#include +#include +#include + +#include "b_file_info.h" +#include "b_incremental_data.h" +#include "errors.h" +#include "svc_death_recipient.h" +#include "unique_fd.h" + +namespace OHOS::FileManagement::Backup { +class BIncrementalBackupSession { +public: + struct Callbacks { + std::function onFileReady; // 当备份服务有文件待发送时执行的回调 + std::function onBundleStarted; // 当启动某个应用的备份流程结束时执行的回调函数 + std::function onBundleFinished; // 当某个应用的备份流程结束或意外中止时执行的回调函数 + std::function onAllBundlesFinished; // 当整个备份流程结束或意外中止时执行的回调函数 + std::function onBackupServiceDied; // 当备份服务意外死亡时执行的回调函数 + }; + +public: + /** + * @brief 获取一个用于控制备份流程的会话 + * + * @param callbacks 注册回调 + * @return std::unique_ptr 指向会话的智能指针。失败时为空指针 + */ + static std::unique_ptr Init(Callbacks callbacks); + + /** + * @brief 用于追加应用,现阶段仅支持在Start之前调用 + * + * @param bundlesToBackup 待备份的应用清单 + * @return ErrCode 规范错误码 + */ + ErrCode AppendBundles(std::vector bundlesToBackup); + + /** + * @brief 用于结束服务 + * + * @return ErrCode 规范错误码 + */ + ErrCode Release(); + + /** + * @brief 注册备份服务意外死亡时执行的回调函数 + * + * @param functor 回调函数 + */ + void RegisterBackupServiceDied(std::function functor); + +public: + ~BIncrementalBackupSession(); + +private: + sptr deathRecipient_; +}; +} // namespace OHOS::FileManagement::Backup + +#endif // OHOS_FILEMGMT_BACKUP_B_INCREMENTAL_BACKUP_BACKUP_H \ 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 000000000..1c7a25c96 --- /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; + int32_t backupPriority; + + BIncrementalData() = default; + BIncrementalData(std::string name, int64_t nTime, int fd = -1, std::string parameters = "", int32_t priority = 0) + : 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/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_restore_session.h b/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_restore_session.h new file mode 100644 index 000000000..53293d2d9 --- /dev/null +++ b/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_restore_session.h @@ -0,0 +1,97 @@ +/* + * 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_RESTORE_RESTORE_H +#define OHOS_FILEMGMT_BACKUP_B_INCREMENTAL_RESTORE_RESTORE_H + +#include +#include +#include + +#include "b_file_info.h" +#include "b_incremental_data.h" +#include "errors.h" +#include "svc_death_recipient.h" +#include "unique_fd.h" + +namespace OHOS::FileManagement::Backup { +class BIncrementalRestoreSession { +public: + struct Callbacks { + std::function onFileReady; // 当备份服务有文件待发送时执行的回调 + std::function onBundleStarted; // 当启动某个应用的恢复流程结束时执行的回调函数 + std::function onBundleFinished; // 当某个应用的恢复流程结束或意外中止时执行的回调函数 + std::function onAllBundlesFinished; // 当整个恢复流程结束或意外中止时执行的回调函数 + std::function onBackupServiceDied; // 当备份服务意外死亡时执行的回调函数 + }; + +public: + /** + * @brief 获取一个用于控制恢复流程的会话 + * + * @param callbacks 注册的回调函数 + * @return std::unique_ptr 指向BRestoreSession的智能指针。失败时为空指针 + */ + static std::unique_ptr Init(Callbacks callbacks); + + /** + * @brief 通知备份服务文件内容已就绪 + * + * @param fileInfo 文件描述信息 + * @return ErrCode 规范错误码 + * @see GetFileHandle + */ + ErrCode PublishFile(BFileInfo fileInfo); + + /** + * @brief 请求恢复流程所需的真实文件 + * + * @param bundleName 应用名称 + * @param fileName 文件名称 + */ + ErrCode GetFileHandle(const std::string &bundleName, const std::string &fileName); + + /** + * @brief 用于追加应用,现阶段仅支持在Start之前调用 + * + * @param remoteCap 已打开的保存远端设备能力的Json文件。可使用GetLocalCapabilities方法获取 + * @param bundlesToRestore 待恢复的应用清单 + * @return ErrCode 规范错误码 + */ + ErrCode AppendBundles(UniqueFd remoteCap, std::vector bundlesToRestore); + + /** + * @brief 用于结束服务 + * + * @return ErrCode 规范错误码 + */ + ErrCode Release(); + + /** + * @brief 注册备份服务意外死亡时执行的回调函数 + * + * @param functor 回调函数 + */ + void RegisterBackupServiceDied(std::function functor); + +public: + ~BIncrementalRestoreSession(); + +private: + sptr deathRecipient_; +}; +} // namespace OHOS::FileManagement::Backup + +#endif // OHOS_FILEMGMT_BACKUP_B_INCREMENTAL_RESTORE_RESTORE_H \ No newline at end of file diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/b_session_backup.h b/interfaces/inner_api/native/backup_kit_inner/impl/b_session_backup.h index 059e3b798..bed22250c 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/b_session_backup.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/b_session_backup.h @@ -67,6 +67,13 @@ public: */ ErrCode Start(); + /** + * @brief 用于结束服务 + * + * @return ErrCode 规范错误码 + */ + ErrCode Release(); + /** * @brief 注册备份服务意外死亡时执行的回调函数 * diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/b_session_restore.h b/interfaces/inner_api/native/backup_kit_inner/impl/b_session_restore.h index 4654a7bc5..14e730a21 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/b_session_restore.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/b_session_restore.h @@ -85,6 +85,13 @@ public: */ ErrCode Start(); + /** + * @brief 用于结束服务 + * + * @return ErrCode 规范错误码 + */ + ErrCode Release(); + /** * @brief 注册备份服务意外死亡时执行的回调函数 * diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/b_session_restore_async.h b/interfaces/inner_api/native/backup_kit_inner/impl/b_session_restore_async.h index 8c4e949d2..2b6e0ddcc 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/b_session_restore_async.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/b_session_restore_async.h @@ -86,6 +86,13 @@ public: RestoreTypeEnum restoreType = RestoreTypeEnum::RESTORE_DATA_WAIT_SEND, int32_t userId = DEFAULT_INVAL_VALUE); + /** + * @brief 用于结束服务 + * + * @return ErrCode 规范错误码 + */ + ErrCode Release(); + public: explicit BSessionRestoreAsync(Callbacks callbacks) : callbacks_(callbacks) {}; ~BSessionRestoreAsync(); 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 ac9e5c09d..c21393e67 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 @@ -32,6 +32,9 @@ public: virtual ErrCode HandleBackup() = 0; virtual ErrCode PublishFile(const std::string &fileName) = 0; virtual ErrCode HandleRestore() = 0; + virtual ErrCode GetIncrementalFileHandle(const std::string &fileName) = 0; + virtual ErrCode PublishIncrementalFile(const std::string &fileName) = 0; + virtual ErrCode HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) = 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 50a8be51a..091f87107 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 @@ -24,6 +24,9 @@ enum class IExtensionInterfaceCode { CMD_PUBLISH_FILE, CMD_HANDLE_BACKUP, CMD_HANDLE_RESTORE, + CMD_GET_INCREMENTAL_FILE_HANDLE, + CMD_PUBLISH_INCREMENTAL_FILE, + CMD_HANDLE_INCREMENTAL_BACKUP, }; } // namespace OHOS::FileManagement::Backup diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/i_service.h b/interfaces/inner_api/native/backup_kit_inner/impl/i_service.h index e8bb2202a..869a3ca98 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/i_service.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/i_service.h @@ -22,6 +22,7 @@ #include #include "b_file_info.h" +#include "b_incremental_data.h" #include "i_service_ipc_interface_code.h" #include "i_service_reverse.h" #include "iremote_broker.h" @@ -50,6 +51,15 @@ public: int32_t userId = DEFAULT_INVAL_VALUE) = 0; virtual ErrCode AppendBundlesBackupSession(const std::vector &bundleNames) = 0; virtual ErrCode Finish() = 0; + virtual ErrCode Release() = 0; + virtual UniqueFd GetLocalCapabilitiesIncremental(const std::vector &bundleNames) = 0; + virtual ErrCode InitIncrementalBackupSession(sptr remote) = 0; + virtual ErrCode AppendBundlesIncrementalBackupSession(const std::vector &bundlesToBackup) = 0; + + virtual ErrCode PublishIncrementalFile(const BFileInfo &fileInfo) = 0; + virtual ErrCode AppIncrementalFileReady(const std::string &fileName, UniqueFd fd, UniqueFd manifestFd) = 0; + virtual ErrCode AppIncrementalDone(ErrCode errCode) = 0; + virtual ErrCode GetIncrementalFileHandle(const std::string &bundleName, const std::string &fileName) = 0; DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.Filemanagement.Backup.IService") }; diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/i_service_ipc_interface_code.h b/interfaces/inner_api/native/backup_kit_inner/impl/i_service_ipc_interface_code.h index 797921043..0e224a108 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/i_service_ipc_interface_code.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/i_service_ipc_interface_code.h @@ -30,6 +30,14 @@ enum class IServiceInterfaceCode { SERVICE_CMD_APPEND_BUNDLES_RESTORE_SESSION, SERVICE_CMD_APPEND_BUNDLES_BACKUP_SESSION, SERVICE_CMD_FINISH, + SERVICE_CMD_RELSEASE_SESSION, + SERVICE_CMD_GET_LOCAL_CAPABILITIES_INCREMENTAL, + SERVICE_CMD_INIT_INCREMENTAL_BACKUP_SESSION, + SERVICE_CMD_APPEND_BUNDLES_INCREMENTAL_BACKUP_SESSION, + SERVICE_CMD_PUBLISH_INCREMENTAL_FILE, + SERVICE_CMD_APP_INCREMENTAL_FILE_READY, + SERVICE_CMD_APP_INCREMENTAL_DONE, + SERVICE_CMD_GET_INCREMENTAL_FILE_NAME, }; } // namespace OHOS::FileManagement::Backup diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/i_service_reverse.h b/interfaces/inner_api/native/backup_kit_inner/impl/i_service_reverse.h index 0d0f9a7fe..0f959c9c0 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/i_service_reverse.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/i_service_reverse.h @@ -41,6 +41,19 @@ public: virtual void RestoreOnAllBundlesFinished(int32_t errCode) = 0; virtual void RestoreOnFileReady(std::string bundleName, std::string fileName, int fd) = 0; + virtual void IncrementalBackupOnFileReady(std::string bundleName, std::string fileName, int fd, int manifestFd) = 0; + virtual void IncrementalBackupOnBundleStarted(int32_t errCode, std::string bundleName) = 0; + virtual void IncrementalBackupOnBundleFinished(int32_t errCode, std::string bundleName) = 0; + virtual void IncrementalBackupOnAllBundlesFinished(int32_t errCode) = 0; + + virtual void IncrementalRestoreOnBundleStarted(int32_t errCode, std::string bundleName) = 0; + virtual void IncrementalRestoreOnBundleFinished(int32_t errCode, std::string bundleName) = 0; + virtual void IncrementalRestoreOnAllBundlesFinished(int32_t errCode) = 0; + virtual void IncrementalRestoreOnFileReady(std::string bundleName, + std::string fileName, + int fd, + int manifestFd) = 0; + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.FileManagement.Backup.IServiceReverse") }; } // namespace OHOS::FileManagement::Backup diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/i_service_reverse_ipc_interface_code.h b/interfaces/inner_api/native/backup_kit_inner/impl/i_service_reverse_ipc_interface_code.h index 5fc63b67e..b99203b22 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/i_service_reverse_ipc_interface_code.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/i_service_reverse_ipc_interface_code.h @@ -27,6 +27,14 @@ enum class IServiceReverseInterfaceCode { SERVICER_RESTORE_ON_SUB_TASK_FINISHED, SERVICER_RESTORE_ON_TASK_FINISHED, SERVICER_RESTORE_ON_FILE_READY, + SERVICER_INCREMENTAL_BACKUP_ON_FILE_READY, + SERVICER_INCREMENTAL_BACKUP_ON_SUB_TASK_STARTED, + SERVICER_INCREMENTAL_BACKUP_ON_SUB_TASK_FINISHED, + SERVICER_INCREMENTAL_BACKUP_ON_TASK_FINISHED, + SERVICER_INCREMENTAL_RESTORE_ON_SUB_TASK_STARTED, + SERVICER_INCREMENTAL_RESTORE_ON_SUB_TASK_FINISHED, + SERVICER_INCREMENTAL_RESTORE_ON_TASK_FINISHED, + SERVICER_INCREMENTAL_RESTORE_ON_FILE_READY, }; } // namespace OHOS::FileManagement::Backup diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/service_proxy.h b/interfaces/inner_api/native/backup_kit_inner/impl/service_proxy.h index 5273921a2..67a93868a 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/service_proxy.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/service_proxy.h @@ -42,12 +42,23 @@ public: int32_t userId = DEFAULT_INVAL_VALUE) override; ErrCode AppendBundlesBackupSession(const std::vector &bundleNames) override; ErrCode Finish() override; + ErrCode Release() override; + UniqueFd GetLocalCapabilitiesIncremental(const std::vector &bundleNames) override; + ErrCode InitIncrementalBackupSession(sptr remote) override; + ErrCode AppendBundlesIncrementalBackupSession(const std::vector &bundlesToBackup) override; + + ErrCode PublishIncrementalFile(const BFileInfo &fileInfo) override; + ErrCode AppIncrementalFileReady(const std::string &fileName, UniqueFd fd, UniqueFd manifestFd) override; + ErrCode AppIncrementalDone(ErrCode errCode) override; + ErrCode GetIncrementalFileHandle(const std::string &bundleName, const std::string &fileName) override; public: explicit ServiceProxy(const sptr &impl) : IRemoteProxy(impl) {} ~ServiceProxy() override {} public: + template + bool WriteParcelableVector(const std::vector &parcelableVector, Parcel &data); static sptr GetInstance(); static void InvaildInstance(); diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index ee1a7758b..3b1649759 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -150,6 +150,7 @@ ohos_shared_library("backup") { "${path_backup_js}/backup/prop_n_exporter.cpp", "${path_backup_js}/backup/session_backup_n_exporter.cpp", "${path_backup_js}/backup/session_restore_n_exporter.cpp", + "${path_backup_js}/backup/session_incremental_backup_n_exporter.cpp", ] deps = [ diff --git a/interfaces/kits/js/backup/incremental_backup_data.h b/interfaces/kits/js/backup/incremental_backup_data.h new file mode 100644 index 000000000..5cb08c819 --- /dev/null +++ b/interfaces/kits/js/backup/incremental_backup_data.h @@ -0,0 +1,100 @@ +/* + * 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 INTERFACES_KITS_JS_SRC_MOD_BACKUP_INCREMENTAL_BACKUP_DATA_H +#define INTERFACES_KITS_JS_SRC_MOD_BACKUP_INCREMENTAL_BACKUP_DATA_H + +#include +#include +#include +#include + +#include "filemgmt_libn.h" + +namespace OHOS::FileManagement::Backup { +struct IncrementalBackupTime +{ + IncrementalBackupTime(const LibN::NVal &data) { + LibN::NVal name = data.GetProp("bundleName"); + if (name.val_ != nullptr) { + auto [succ, str, ignore] = name.ToUTF8String(); + if (succ) { + bundleName = std::string(str.get()); + } + } + + LibN::NVal time = data.GetProp("lastIncrementalTime"); + if (time.val_ != nullptr) { + auto [succ, tm] = time.ToInt32(); + if (succ) { + lastIncrementalTime = tm; + } + } + } + std::string bundleName = ""; + int64_t lastIncrementalTime = 0; +}; + +struct FileManifestData +{ + FileManifestData(const LibN::NVal &data) { + LibN::NVal fd = data.GetProp("manifestFd"); + if (fd.val_ != nullptr) { + auto [succ, tmp] = fd.ToInt32(); + if (succ) { + manifestFd = tmp; + } + } + } + int32_t manifestFd = -1; +}; + +struct BackupParams +{ + BackupParams(const LibN::NVal &data) { + LibN::NVal para = data.GetProp("parameters"); + if (para.val_ != nullptr) { + auto [succ, str, ignore] = para.ToUTF8String(); + if (succ) { + parameters = std::string(str.get()); + } + } + } + std::string parameters = ""; +}; + +struct BackupPriority +{ + BackupPriority(const LibN::NVal &data) { + LibN::NVal pr = data.GetProp("priority"); + if (pr.val_ != nullptr) { + auto [succ, tmp] = pr.ToInt32(); + if (succ) { + priority = tmp; + } + } + } + int32_t priority = -1; +}; + +struct IncrementalBackupData : public IncrementalBackupTime, public FileManifestData, public BackupParams, public BackupPriority +{ + IncrementalBackupData(const LibN::NVal &data) + : IncrementalBackupTime(data), + FileManifestData(data), + BackupParams(data), + BackupPriority(data) {}; +}; +} // namespace OHOS::FileManagement::Backup +#endif // INTERFACES_KITS_JS_SRC_MOD_BACKUP_INCREMENTAL_BACKUP_DATA_H \ No newline at end of file diff --git a/interfaces/kits/js/backup/local_capabilities.cpp b/interfaces/kits/js/backup/local_capabilities.cpp index d3b9e9eb3..0678dbcd8 100644 --- a/interfaces/kits/js/backup/local_capabilities.cpp +++ b/interfaces/kits/js/backup/local_capabilities.cpp @@ -18,27 +18,23 @@ #include "filemgmt_libn.h" #include "service_proxy.h" +#include "incremental_backup_data.h" + namespace OHOS::FileManagement::Backup { using namespace std; using namespace LibN; -napi_value LocalCapabilities::Async(napi_env env, napi_callback_info info) +static napi_value AsyncCallback(napi_env env, const NFuncArg& funcArg) { - HILOGI("called LocalCapabilities::Async begin"); - NFuncArg funcArg(env, info); - if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) { - HILOGE("Number of arguments unmatched"); - NError(EINVAL).ThrowErr(env); - return nullptr; - } + HILOGI("called LocalCapabilities::AsyncCallback begin"); auto fd = make_shared(); auto cbExec = [fd]() -> NError { - HILOGI("called LocalCapabilities::Async cbExec"); + HILOGI("called LocalCapabilities::AsyncCallback cbExec"); ServiceProxy::InvaildInstance(); auto proxy = ServiceProxy::GetInstance(); if (!proxy) { - HILOGI("called LocalCapabilities::Async cbExec, failed to get proxy"); + HILOGI("called LocalCapabilities::AsyncCallback cbExec, failed to get proxy"); return NError(errno); } *fd = proxy->GetLocalCapabilities(); @@ -63,4 +59,78 @@ napi_value LocalCapabilities::Async(napi_env env, napi_callback_info info) return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_LOCALCAPABILITIES_NAME, cbExec, cbCompl).val_; } } + +static std::vector ParseDataList(napi_env env, const napi_value& value) +{ + uint32_t size = 0; + napi_status status = napi_get_array_length(env, value, &size); + if (status != napi_ok || size == 0) { + HILOGI("Get array length failed or array length is zero!"); + return {}; + } + + napi_value result; + std::vector backupData; + for (uint32_t i = 0; i < size; i++) { + status = napi_get_element(env, value, i, &result); + if (status != napi_ok) { + HILOGE("Get element failed! index is :%{public}u", i); + } else { + backupData.emplace_back(NVal(env, result)); + } + } + return backupData; +} + +static napi_value AsyncDataList(napi_env env, const NFuncArg& funcArg) +{ + HILOGI("called LocalCapabilities::AsyncDataList begin"); + + std::vector backupData = ParseDataList(env, funcArg[NARG_POS::FIRST]); + auto fd = make_shared(); + auto cbExec = [fd, backupData { move(backupData) }]() -> NError { + HILOGI("called LocalCapabilities::AsyncDataList cbExec"); + ServiceProxy::InvaildInstance(); + auto proxy = ServiceProxy::GetInstance(); + if (!proxy) { + HILOGI("called LocalCapabilities::AsyncDataList cbExec, failed to get proxy"); + return NError(errno); + } + *fd = proxy->GetLocalCapabilities(/*backupData*/); + return NError(ERRNO_NOERR); + }; + auto cbCompl = [fd](napi_env env, NError err) -> NVal { + if (err) { + return {env, err.GetNapiErr(env)}; + } + NVal obj = NVal::CreateObject(env); + obj.AddProp({NVal::DeclareNapiProperty("fd", NVal::CreateInt32(env, fd->Release()).val_)}); + return {obj}; + }; + + HILOGI("called LocalCapabilities::Async::promise"); + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_LOCALCAPABILITIES_NAME, cbExec, cbCompl).val_; +} + +napi_value LocalCapabilities::Async(napi_env env, napi_callback_info info) +{ + HILOGI("called LocalCapabilities::Async begin"); + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + if (funcArg.GetArgc() == 1) { + bool result = 0; + napi_status status = napi_is_array(env, funcArg[NARG_POS::FIRST], &result); + if (status == napi_ok && result) { + return AsyncDataList(env, funcArg); + } + } + + return AsyncCallback(env, funcArg); +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/interfaces/kits/js/backup/module.cpp b/interfaces/kits/js/backup/module.cpp index 59f88491b..3fa55d585 100644 --- a/interfaces/kits/js/backup/module.cpp +++ b/interfaces/kits/js/backup/module.cpp @@ -21,6 +21,7 @@ #include "prop_n_exporter.h" #include "session_backup_n_exporter.h" #include "session_restore_n_exporter.h" +#include "session_incremental_backup_n_exporter.h" namespace OHOS::FileManagement::Backup { using namespace std; @@ -32,6 +33,7 @@ static napi_value Export(napi_env env, napi_value exports) products.emplace_back(make_unique(env, exports)); products.emplace_back(make_unique(env, exports)); products.emplace_back(make_unique(env, exports)); + products.emplace_back(make_unique(env, exports)); for (auto &&product : products) { if (!product->Export()) { HILOGE("INNER BUG. Failed to export class %{public}s for module file.backup", diff --git a/interfaces/kits/js/backup/session_backup_n_exporter.cpp b/interfaces/kits/js/backup/session_backup_n_exporter.cpp index 713527c7f..bc624935c 100644 --- a/interfaces/kits/js/backup/session_backup_n_exporter.cpp +++ b/interfaces/kits/js/backup/session_backup_n_exporter.cpp @@ -289,10 +289,46 @@ napi_value SessionBackupNExporter::AppendBundles(napi_env env, napi_callback_inf } } +napi_value SessionBackupNExporter::Release(napi_env env, napi_callback_info cbinfo) +{ + HILOGI("called SessionBackup::Release begin"); + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto backupEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!(backupEntity && backupEntity->session)) { + HILOGE("Failed to get backupSession entity."); + NError(EPERM).ThrowErr(env); + return nullptr; + } + + auto cbExec = [session {backupEntity->session.get()}]() -> NError { + if (!session) { + return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode()); + } + return NError(session->Release()); + }; + auto cbCompl = [](napi_env env, NError err) -> NVal { + return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env); + }; + + HILOGE("Called SessionBackup::Release end."); + + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_; +} + bool SessionBackupNExporter::Export() { HILOGI("called SessionBackupNExporter::Export begin"); - vector props = {NVal::DeclareNapiFunction("appendBundles", AppendBundles)}; + vector props = { + NVal::DeclareNapiFunction("appendBundles", AppendBundles), + NVal::DeclareNapiFunction("release", Release), + }; auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props)); if (!succ) { diff --git a/interfaces/kits/js/backup/session_backup_n_exporter.h b/interfaces/kits/js/backup/session_backup_n_exporter.h index afa3c96b2..75dd410b7 100644 --- a/interfaces/kits/js/backup/session_backup_n_exporter.h +++ b/interfaces/kits/js/backup/session_backup_n_exporter.h @@ -27,6 +27,7 @@ public: static napi_value Constructor(napi_env env, napi_callback_info cbinfo); static napi_value AppendBundles(napi_env env, napi_callback_info cbinfo); + static napi_value Release(napi_env env, napi_callback_info cbinfo); SessionBackupNExporter(napi_env env, napi_value exports); ~SessionBackupNExporter() override; diff --git a/interfaces/kits/js/backup/session_incremental_backup_n_exporter.cpp b/interfaces/kits/js/backup/session_incremental_backup_n_exporter.cpp new file mode 100644 index 000000000..cf0e0e742 --- /dev/null +++ b/interfaces/kits/js/backup/session_incremental_backup_n_exporter.cpp @@ -0,0 +1,379 @@ +/* + * 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 "session_incremental_backup_n_exporter.h" + +#include +#include + +#include "b_error/b_error.h" +#include "b_filesystem/b_file.h" +#include "b_resources/b_constants.h" +#include "b_incremental_backup_session.h" +#include "backup_kit_inner.h" +#include "directory_ex.h" +#include "filemgmt_libhilog.h" +#include "general_callbacks.h" +#include "incremental_backup_data.h" +#include "b_incremental_data.h" +#include "service_proxy.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; +using namespace LibN; + +struct BackupEntity { + unique_ptr session; + shared_ptr callbacks; +}; + +static void OnFileReady(weak_ptr pCallbacks, const BFileInfo &fileInfo, UniqueFd fd, UniqueFd manifestFd) +{ + if (pCallbacks.expired()) { + HILOGI("callbacks is unbound"); + return; + } + auto callbacks = pCallbacks.lock(); + if (!callbacks) { + HILOGI("callback function onFileReady has already been released"); + return; + } + if (!bool(callbacks->onFileReady)) { + HILOGI("callback function onFileReady is undefined"); + return; + } + + auto cbCompl = [bundleName {fileInfo.owner}, fileName {fileInfo.fileName}, + fd {make_shared(fd.Release())}, + manifestFd {make_shared(fd.Release())}](napi_env env, NError err) -> NVal { + if (err) { + return {env, err.GetNapiErr(env)}; + } + NVal obj = NVal::CreateObject(env); + obj.AddProp({NVal::DeclareNapiProperty("bundleName", NVal::CreateUTF8String(env, bundleName).val_), + NVal::DeclareNapiProperty("uri", NVal::CreateUTF8String(env, fileName).val_), + NVal::DeclareNapiProperty("fd", NVal::CreateInt32(env, fd->Release()).val_), + NVal::DeclareNapiProperty("manifestFd", NVal::CreateInt32(env, manifestFd->Release()).val_)}); + + return {obj}; + }; + + callbacks->onFileReady.ThreadSafeSchedule(cbCompl); +} + +static void onBundleBegin(weak_ptr pCallbacks, ErrCode err, const BundleName name) +{ + if (pCallbacks.expired()) { + HILOGI("callbacks is unbound"); + return; + } + auto callbacks = pCallbacks.lock(); + if (!callbacks) { + HILOGI("callback function onBundleBegin has already been released"); + return; + } + if (!bool(callbacks->onBundleBegin)) { + HILOGI("callback function onBundleBegin is undefined"); + return; + } + + auto cbCompl = [name {name}, errCode {err}](napi_env env, NError err) -> NVal { + NVal bundleName = NVal::CreateUTF8String(env, name); + if (!err && errCode == 0) { + return bundleName; + } + + NVal res; + if (err) { + res = NVal {env, err.GetNapiErr(env)}; + } else { + res = NVal {env, NError(errCode).GetNapiErr(env)}; + } + napi_status status = napi_set_named_property(env, res.val_, FILEIO_TAG_ERR_DATA.c_str(), bundleName.val_); + if (status != napi_ok) { + HILOGE("Failed to set data property, status %{public}d, bundleName %{public}s", status, name.c_str()); + } + + return res; + }; + + callbacks->onBundleBegin.ThreadSafeSchedule(cbCompl); +} + +static void onBundleEnd(weak_ptr pCallbacks, ErrCode err, const BundleName name) +{ + if (pCallbacks.expired()) { + HILOGI("callbacks is unbound"); + return; + } + auto callbacks = pCallbacks.lock(); + if (!callbacks) { + HILOGI("callback function onBundleEnd has already been released"); + return; + } + if (!bool(callbacks->onBundleEnd)) { + HILOGI("callback function onBundleEnd is undefined"); + return; + } + + auto cbCompl = [name {name}, errCode {err}](napi_env env, NError err) -> NVal { + NVal bundleName = NVal::CreateUTF8String(env, name); + if (!err && errCode == 0) { + return bundleName; + } + + NVal res; + if (err) { + res = NVal {env, err.GetNapiErr(env)}; + } else { + res = NVal {env, NError(errCode).GetNapiErr(env)}; + } + napi_status status = napi_set_named_property(env, res.val_, FILEIO_TAG_ERR_DATA.c_str(), bundleName.val_); + if (status != napi_ok) { + HILOGE("Failed to set data property, status %{public}d, bundleName %{public}s", status, name.c_str()); + } + + return res; + }; + + callbacks->onBundleEnd.ThreadSafeSchedule(cbCompl); +} + +static void onAllBundlesEnd(weak_ptr pCallbacks, ErrCode err) +{ + if (pCallbacks.expired()) { + HILOGI("callbacks is unbound"); + return; + } + auto callbacks = pCallbacks.lock(); + if (!callbacks) { + HILOGI("callback function onAllBundlesEnd has already been released"); + return; + } + if (!bool(callbacks->onAllBundlesEnd)) { + HILOGI("callback function onAllBundlesEnd is undefined"); + return; + } + + auto cbCompl = [errCode {err}](napi_env env, NError err) -> NVal { + if (!err && errCode == 0) { + return NVal::CreateUndefined(env); + } + + NVal res; + if (err) { + res = NVal {env, err.GetNapiErr(env)}; + } else { + res = NVal {env, NError(errCode).GetNapiErr(env)}; + } + + return res; + }; + + callbacks->onAllBundlesEnd.ThreadSafeSchedule(cbCompl); +} + +static void OnBackupServiceDied(weak_ptr pCallbacks) +{ + if (pCallbacks.expired()) { + HILOGI("callbacks is unbound"); + return; + } + auto callbacks = pCallbacks.lock(); + if (!callbacks) { + HILOGI("js callback function onBackupServiceDied has already been released"); + return; + } + if (!bool(callbacks->onBackupServiceDied)) { + HILOGI("callback function onBackupServiceDied is undefined"); + return; + } + + auto cbCompl = [](napi_env env, NError err) -> NVal { + return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env); + }; + + callbacks->onBackupServiceDied.ThreadSafeSchedule(cbCompl); +} + +napi_value SessionIncrementalBackupNExporter::Constructor(napi_env env, napi_callback_info cbinfo) +{ + HILOGI("called SessionIncrementalBackup::Constructor begin"); + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::ONE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + NVal callbacks(env, funcArg[NARG_POS::FIRST]); + if (!callbacks.TypeIs(napi_object)) { + HILOGE("First argument is not an object."); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + NVal ptr(env, funcArg.GetThisVar()); + auto backupEntity = std::make_unique(); + backupEntity->callbacks = make_shared(env, ptr, callbacks); + backupEntity->session = BIncrementalBackupSession::Init(BIncrementalBackupSession::Callbacks { + .onFileReady = bind(OnFileReady, backupEntity->callbacks, placeholders::_1, placeholders::_2, placeholders::_3), + .onBundleStarted = bind(onBundleBegin, backupEntity->callbacks, placeholders::_1, placeholders::_2), + .onBundleFinished = bind(onBundleEnd, backupEntity->callbacks, placeholders::_1, placeholders::_2), + .onAllBundlesFinished = bind(onAllBundlesEnd, backupEntity->callbacks, placeholders::_1), + .onBackupServiceDied = bind(OnBackupServiceDied, backupEntity->callbacks)}); + if (!backupEntity->session) { + NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to init backup").GetCode()).ThrowErr(env); + return nullptr; + } + if (!NClass::SetEntityFor(env, funcArg.GetThisVar(), move(backupEntity))) { + HILOGE("Failed to set BackupEntity entity"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + HILOGI("called SessionIncrementalBackup::Constructor end"); + return funcArg.GetThisVar(); +} + +static std::vector ParseDataList(napi_env env, const napi_value& value) +{ + uint32_t size = 0; + napi_status status = napi_get_array_length(env, value, &size); + if (status != napi_ok || size == 0) { + HILOGI("Get array length failed or array length is zero!"); + return {}; + } + + napi_value result; + std::vector backupData; + for (uint32_t i = 0; i < size; i++) { + status = napi_get_element(env, value, i, &result); + if (status != napi_ok) { + HILOGE("Get element failed! index is :%{public}u", i); + } else { + IncrementalBackupData data(NVal(env, result)); + backupData.emplace_back(data.bundleName, + data.lastIncrementalTime, + data.manifestFd, + data.parameters, + data.priority); + } + } + return backupData; +} + +napi_value SessionIncrementalBackupNExporter::AppendBundles(napi_env env, napi_callback_info cbinfo) +{ + HILOGI("called SessionIncrementalBackup::AppendBundles begin"); + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::ONE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto bundles = ParseDataList(env, funcArg[NARG_POS::FIRST]); + + auto backupEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!(backupEntity && backupEntity->session)) { + HILOGE("Failed to get backupSession entity."); + NError(EPERM).ThrowErr(env); + return nullptr; + } + + auto cbExec = [session {backupEntity->session.get()}, bundles { move(bundles) }]() -> NError { + if (!session) { + return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode()); + } + return NError(session->AppendBundles(bundles)); + }; + auto cbCompl = [](napi_env env, NError err) -> NVal { + return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env); + }; + + HILOGE("Called SessionIncrementalBackup::AppendBundles end."); + + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_; +} + +napi_value SessionIncrementalBackupNExporter::Release(napi_env env, napi_callback_info cbinfo) +{ + HILOGI("called SessionIncrementalBackup::Release begin"); + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto backupEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!(backupEntity && backupEntity->session)) { + HILOGE("Failed to get backupSession entity."); + NError(EPERM).ThrowErr(env); + return nullptr; + } + + auto cbExec = [session {backupEntity->session.get()}]() -> NError { + if (!session) { + return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode()); + } + return NError(session->Release()); + }; + auto cbCompl = [](napi_env env, NError err) -> NVal { + return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env); + }; + + HILOGE("Called SessionIncrementalBackup::Release end."); + + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_; +} + +bool SessionIncrementalBackupNExporter::Export() +{ + HILOGI("called SessionIncrementalBackupNExporter::Export begin"); + vector props = { + NVal::DeclareNapiFunction("appendBundles", AppendBundles), + NVal::DeclareNapiFunction("release", Release), + }; + + auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props)); + if (!succ) { + HILOGE("Failed to define class"); + NError(EIO).ThrowErr(exports_.env_); + return false; + } + succ = NClass::SaveClass(exports_.env_, className, classValue); + if (!succ) { + HILOGE("Failed to save class"); + NError(EIO).ThrowErr(exports_.env_); + return false; + } + + HILOGI("called SessionIncrementalBackupNExporter::Export end"); + return exports_.AddProp(className, classValue); +} + +string SessionIncrementalBackupNExporter::GetClassName() +{ + return SessionIncrementalBackupNExporter::className; +} + +SessionIncrementalBackupNExporter::SessionIncrementalBackupNExporter(napi_env env, napi_value exports) + : NExporter(env, exports) {} + +SessionIncrementalBackupNExporter::~SessionIncrementalBackupNExporter() {} +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/interfaces/kits/js/backup/session_incremental_backup_n_exporter.h b/interfaces/kits/js/backup/session_incremental_backup_n_exporter.h new file mode 100644 index 000000000..3baa8d73f --- /dev/null +++ b/interfaces/kits/js/backup/session_incremental_backup_n_exporter.h @@ -0,0 +1,36 @@ +/* + * 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 INTERFACES_KITS_JS_SRC_MOD_BACKUP_PROPERTIES_SESSION_INCREMENTAL_BACKUP_N_EXPORTER_H +#define INTERFACES_KITS_JS_SRC_MOD_BACKUP_PROPERTIES_SESSION_INCREMENTAL_BACKUP_N_EXPORTER_H + +#include "n_exporter.h" + +namespace OHOS::FileManagement::Backup { +class SessionIncrementalBackupNExporter final : public LibN::NExporter { +public: + inline static const std::string className = "SessionIncrementalBackup"; + + bool Export() override; + std::string GetClassName() override; + + static napi_value Constructor(napi_env env, napi_callback_info cbinfo); + static napi_value AppendBundles(napi_env env, napi_callback_info cbinfo); + static napi_value Release(napi_env env, napi_callback_info cbinfo); + + SessionIncrementalBackupNExporter(napi_env env, napi_value exports); + ~SessionIncrementalBackupNExporter() override; +}; +} // namespace OHOS::FileManagement::Backup +#endif // INTERFACES_KITS_JS_SRC_MOD_BACKUP_PROPERTIES_SESSION_INCREMENTAL_BACKUP_N_EXPORTER_H \ No newline at end of file diff --git a/interfaces/kits/js/backup/session_restore_n_exporter.cpp b/interfaces/kits/js/backup/session_restore_n_exporter.cpp index 53d9c0df0..1703d1e22 100644 --- a/interfaces/kits/js/backup/session_restore_n_exporter.cpp +++ b/interfaces/kits/js/backup/session_restore_n_exporter.cpp @@ -20,9 +20,11 @@ #include "b_error/b_error.h" #include "b_filesystem/b_dir.h" #include "b_filesystem/b_file.h" +#include "b_incremental_restore_session.h" #include "b_resources/b_constants.h" #include "b_session_restore.h" #include "backup_kit_inner.h" +#include "b_ohos/startup/backup_para.h" #include "filemgmt_libhilog.h" #include "general_callbacks.h" #include "service_proxy.h" @@ -32,11 +34,12 @@ using namespace std; using namespace LibN; struct RestoreEntity { - unique_ptr session; + unique_ptr sessionWhole; + unique_ptr sessionSheet; shared_ptr callbacks; }; -static void OnFileReady(weak_ptr pCallbacks, const BFileInfo &fileInfo, UniqueFd fd) +static void OnFileReadyWhole(weak_ptr pCallbacks, const BFileInfo &fileInfo, UniqueFd fd) { if (pCallbacks.expired()) { HILOGI("callbacks is unbound"); @@ -68,6 +71,44 @@ static void OnFileReady(weak_ptr pCallbacks, const BFileInfo & callbacks->onFileReady.ThreadSafeSchedule(cbCompl); } +static void OnFileReadySheet(weak_ptr pCallbacks, + const BFileInfo &fileInfo, + UniqueFd fd, + UniqueFd manifestFd) +{ + if (pCallbacks.expired()) { + HILOGI("callbacks is unbound"); + return; + } + auto callbacks = pCallbacks.lock(); + if (!callbacks) { + HILOGI("callback function onFileReady has already been released"); + return; + } + if (!bool(callbacks->onFileReady)) { + HILOGI("callback function onFileReady is undefined"); + return; + } + + auto cbCompl = [bundleName {fileInfo.owner}, + fileName {fileInfo.fileName}, + fd {make_shared(fd.Release())}, + manifestFd {make_shared(fd.Release())}](napi_env env, NError err) -> NVal { + if (err) { + return {env, err.GetNapiErr(env)}; + } + NVal obj = NVal::CreateObject(env); + obj.AddProp({NVal::DeclareNapiProperty("bundleName", NVal::CreateUTF8String(env, bundleName).val_), + NVal::DeclareNapiProperty("uri", NVal::CreateUTF8String(env, fileName).val_), + NVal::DeclareNapiProperty("fd", NVal::CreateInt32(env, fd->Release()).val_), + NVal::DeclareNapiProperty("manifestFd", NVal::CreateInt32(env, manifestFd->Release()).val_)}); + + return {obj}; + }; + + callbacks->onFileReady.ThreadSafeSchedule(cbCompl); +} + static void onBundleBegin(weak_ptr pCallbacks, ErrCode err, const BundleName name) { if (pCallbacks.expired()) { @@ -221,15 +262,28 @@ napi_value SessionRestoreNExporter::Constructor(napi_env env, napi_callback_info } NVal ptr(env, funcArg.GetThisVar()); + bool bSheet = BackupPara().GetBackupOverrideIncrementalRestore(); auto restoreEntity = std::make_unique(); restoreEntity->callbacks = make_shared(env, ptr, callbacks); - restoreEntity->session = BSessionRestore::Init(BSessionRestore::Callbacks { - .onFileReady = bind(OnFileReady, restoreEntity->callbacks, placeholders::_1, placeholders::_2), - .onBundleStarted = bind(onBundleBegin, restoreEntity->callbacks, placeholders::_1, placeholders::_2), - .onBundleFinished = bind(onBundleEnd, restoreEntity->callbacks, placeholders::_1, placeholders::_2), - .onAllBundlesFinished = bind(onAllBundlesEnd, restoreEntity->callbacks, placeholders::_1), - .onBackupServiceDied = bind(OnBackupServiceDied, restoreEntity->callbacks)}); - if (!restoreEntity->session) { + if (bSheet) { + restoreEntity->sessionWhole = nullptr; + restoreEntity->sessionSheet = BIncrementalRestoreSession::Init(BIncrementalRestoreSession::Callbacks { + .onFileReady = + bind(OnFileReadySheet, restoreEntity->callbacks, placeholders::_1, placeholders::_2, placeholders::_3), + .onBundleStarted = bind(onBundleBegin, restoreEntity->callbacks, placeholders::_1, placeholders::_2), + .onBundleFinished = bind(onBundleEnd, restoreEntity->callbacks, placeholders::_1, placeholders::_2), + .onAllBundlesFinished = bind(onAllBundlesEnd, restoreEntity->callbacks, placeholders::_1), + .onBackupServiceDied = bind(OnBackupServiceDied, restoreEntity->callbacks)}); + } else { + restoreEntity->sessionSheet = nullptr; + restoreEntity->sessionWhole = BSessionRestore::Init(BSessionRestore::Callbacks { + .onFileReady = bind(OnFileReadyWhole, restoreEntity->callbacks, placeholders::_1, placeholders::_2), + .onBundleStarted = bind(onBundleBegin, restoreEntity->callbacks, placeholders::_1, placeholders::_2), + .onBundleFinished = bind(onBundleEnd, restoreEntity->callbacks, placeholders::_1, placeholders::_2), + .onAllBundlesFinished = bind(onAllBundlesEnd, restoreEntity->callbacks, placeholders::_1), + .onBackupServiceDied = bind(OnBackupServiceDied, restoreEntity->callbacks)}); + } + if (!restoreEntity->sessionWhole && !restoreEntity->sessionSheet) { NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to init restore").GetCode()).ThrowErr(env); return nullptr; } @@ -270,17 +324,20 @@ napi_value SessionRestoreNExporter::AppendBundles(napi_env env, napi_callback_in } auto restoreEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); - if (!(restoreEntity && restoreEntity->session)) { + if (!(restoreEntity && (restoreEntity->sessionWhole || restoreEntity->sessionSheet))) { HILOGE("Failed to get RestoreSession entity."); NError(EPERM).ThrowErr(env); return nullptr; } - auto cbExec = [session {restoreEntity->session.get()}, fd {fd}, bundles {bundles}]() -> NError { - if (!session) { + auto cbExec = [entity {restoreEntity}, fd {fd}, bundles {bundles}]() -> NError { + if (!(entity && (entity->sessionWhole || entity->sessionSheet))) { return NError(BError(BError::Codes::SDK_INVAL_ARG, "restore session is nullptr").GetCode()); } - return NError(session->AppendBundles(UniqueFd(fd), bundles)); + if (entity->sessionWhole) { + return NError(entity->sessionWhole->AppendBundles(UniqueFd(fd), bundles)); + } + return NError(entity->sessionSheet->AppendBundles(UniqueFd(fd), bundles)); }; auto cbCompl = [](napi_env env, NError err) -> NVal { return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env); @@ -343,19 +400,22 @@ napi_value SessionRestoreNExporter::PublishFile(napi_env env, napi_callback_info } auto restoreEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); - if (!(restoreEntity && restoreEntity->session)) { + if (!(restoreEntity && (restoreEntity->sessionWhole || restoreEntity->sessionSheet))) { HILOGE("Failed to get RestoreSession entity."); NError(EPERM).ThrowErr(env); return nullptr; } - auto cbExec = [session {restoreEntity->session.get()}, bundleName {string(bundleName.get())}, - fileName {string(fileName.get())}]() -> NError { - if (!session) { + auto cbExec = [entity {restoreEntity}, bundleName {string(bundleName.get())}, + fileName {string(fileName.get())}]() -> NError { + if (!(entity && (entity->sessionWhole || entity->sessionSheet))) { return NError(BError(BError::Codes::SDK_INVAL_ARG, "restore session is nullptr").GetCode()); } BFileInfo fileInfo(bundleName, fileName, 0); - return NError(session->PublishFile(fileInfo)); + if (entity->sessionWhole) { + return NError(entity->sessionWhole->PublishFile(fileInfo)); + } + return NError(entity->sessionSheet->PublishFile(fileInfo)); }; auto cbCompl = [](napi_env env, NError err) -> NVal { return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env); @@ -397,20 +457,23 @@ napi_value SessionRestoreNExporter::GetFileHandle(napi_env env, napi_callback_in } auto restoreEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); - if (!(restoreEntity && restoreEntity->session)) { + if (!(restoreEntity && (restoreEntity->sessionWhole || restoreEntity->sessionSheet))) { HILOGE("Failed to get RestoreSession entity."); NError(EPERM).ThrowErr(env); return nullptr; } - auto cbExec = [session {restoreEntity->session.get()}, bundleName {string(bundleName.get())}, - fileName {string(fileName.get())}]() -> NError { - if (!session) { + auto cbExec = [entity {restoreEntity}, bundleName {string(bundleName.get())}, + fileName {string(fileName.get())}]() -> NError { + if (!(entity && (entity->sessionWhole || entity->sessionSheet))) { return NError(BError(BError::Codes::SDK_INVAL_ARG, "restore session is nullptr").GetCode()); } string bundle = bundleName; string file = fileName; - return NError(session->GetFileHandle(bundle, file)); + if (entity->sessionWhole) { + return NError(entity->sessionWhole->GetFileHandle(bundle, file)); + } + return NError(entity->sessionSheet->GetFileHandle(bundle, file)); }; auto cbCompl = [](napi_env env, NError err) -> NVal { return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env); @@ -427,6 +490,42 @@ napi_value SessionRestoreNExporter::GetFileHandle(napi_env env, napi_callback_in } } +napi_value SessionRestoreNExporter::Release(napi_env env, napi_callback_info cbinfo) +{ + HILOGI("called SessionRestore::Release begin"); + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto restoreEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!(restoreEntity && (restoreEntity->sessionWhole || restoreEntity->sessionSheet))) { + HILOGE("Failed to get RestoreSession entity."); + NError(EPERM).ThrowErr(env); + return nullptr; + } + + auto cbExec = [entity {restoreEntity}]() -> NError { + if (!(entity && (entity->sessionWhole || entity->sessionSheet))) { + return NError(BError(BError::Codes::SDK_INVAL_ARG, "restore session is nullptr").GetCode()); + } + if (entity->sessionWhole) { + return NError(entity->sessionWhole->Release()); + } + return NError(entity->sessionSheet->Release()); + }; + auto cbCompl = [](napi_env env, NError err) -> NVal { + return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env); + }; + + HILOGE("Called SessionRestore::Release end."); + + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_; +} + bool SessionRestoreNExporter::Export() { HILOGI("called SessionRestoreNExporter::Export begin"); @@ -434,6 +533,7 @@ bool SessionRestoreNExporter::Export() NVal::DeclareNapiFunction("appendBundles", AppendBundles), NVal::DeclareNapiFunction("publishFile", PublishFile), NVal::DeclareNapiFunction("getFileHandle", GetFileHandle), + NVal::DeclareNapiFunction("release", Release), }; auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props)); diff --git a/interfaces/kits/js/backup/session_restore_n_exporter.h b/interfaces/kits/js/backup/session_restore_n_exporter.h index b389b55f5..21fc812a2 100644 --- a/interfaces/kits/js/backup/session_restore_n_exporter.h +++ b/interfaces/kits/js/backup/session_restore_n_exporter.h @@ -32,6 +32,7 @@ public: static napi_value AppendBundles(napi_env env, napi_callback_info cbinfo); static napi_value PublishFile(napi_env env, napi_callback_info cbinfo); static napi_value GetFileHandle(napi_env env, napi_callback_info cbinfo); + static napi_value Release(napi_env env, napi_callback_info cbinfo); SessionRestoreNExporter(napi_env env, napi_value exports); ~SessionRestoreNExporter() override; diff --git a/services/backup.para b/services/backup.para index 8f4a7ef77..f4817d298 100644 --- a/services/backup.para +++ b/services/backup.para @@ -14,4 +14,7 @@ backup.debug.overrideExtensionConfig=false backup.debug.overrideAccountConfig=false -backup.debug.overrideAccountNumber=0 \ No newline at end of file +backup.debug.overrideAccountNumber=0 + +backup.overrideBackupSARelease=false +backup.overrideIncrementalRestore=false \ No newline at end of file diff --git a/services/backup_sa/BUILD.gn b/services/backup_sa/BUILD.gn index e89cb1f28..6a42bd130 100644 --- a/services/backup_sa/BUILD.gn +++ b/services/backup_sa/BUILD.gn @@ -29,6 +29,8 @@ ohos_shared_library("backup_sa") { "src/module_app_gallery/app_gallery_dispose_proxy.cpp", "src/module_external/bms_adapter.cpp", "src/module_external/sms_adapter.cpp", + "src/module_ipc/service_incremental_reverse_proxy.cpp", + "src/module_ipc/service_incremental.cpp", "src/module_ipc/service.cpp", "src/module_ipc/service_reverse_proxy.cpp", "src/module_ipc/service_stub.cpp", diff --git a/services/backup_sa/include/module_ipc/service.h b/services/backup_sa/include/module_ipc/service.h index 2a2e639bc..8c966e4e0 100644 --- a/services/backup_sa/include/module_ipc/service.h +++ b/services/backup_sa/include/module_ipc/service.h @@ -46,6 +46,16 @@ public: int32_t userId = DEFAULT_INVAL_VALUE) override; ErrCode AppendBundlesBackupSession(const std::vector &bundleNames) override; ErrCode Finish() override; + ErrCode Release() override; + + UniqueFd GetLocalCapabilitiesIncremental(const std::vector &bundleNames) override; + ErrCode InitIncrementalBackupSession(sptr remote) override; + ErrCode AppendBundlesIncrementalBackupSession(const std::vector &bundlesToBackup) override; + + ErrCode PublishIncrementalFile(const BFileInfo &fileInfo) override; + ErrCode AppIncrementalFileReady(const std::string &fileName, UniqueFd fd, UniqueFd manifestFd) override; + ErrCode AppIncrementalDone(ErrCode errCode) override; + ErrCode GetIncrementalFileHandle(const std::string &bundleName, const std::string &fileName) override; // 以下都是非IPC接口 public: @@ -168,6 +178,15 @@ private: */ void HandleRestoreDepsBundle(const std::string &bundleName); + /** + * @brief 增量备份恢复逻辑处理 + * + * @param bundleName + * @return true + * @return false + */ + bool IncrementalBackup(const std::string &bundleName); + private: static sptr instance_; static std::mutex instanceLock_; diff --git a/services/backup_sa/include/module_ipc/service_reverse_proxy.h b/services/backup_sa/include/module_ipc/service_reverse_proxy.h index 5fd75cb57..a7cc854fc 100644 --- a/services/backup_sa/include/module_ipc/service_reverse_proxy.h +++ b/services/backup_sa/include/module_ipc/service_reverse_proxy.h @@ -32,6 +32,16 @@ public: void RestoreOnAllBundlesFinished(int32_t errCode) override; void RestoreOnFileReady(std::string bundleName, std::string fileName, int fd) override; + void IncrementalBackupOnFileReady(std::string bundleName, std::string fileName, int fd, int manifestFd) override; + void IncrementalBackupOnBundleStarted(int32_t errCode, std::string bundleName) override; + void IncrementalBackupOnBundleFinished(int32_t errCode, std::string bundleName) override; + void IncrementalBackupOnAllBundlesFinished(int32_t errCode) override; + + void IncrementalRestoreOnBundleStarted(int32_t errCode, std::string bundleName) override; + void IncrementalRestoreOnBundleFinished(int32_t errCode, std::string bundleName) override; + void IncrementalRestoreOnAllBundlesFinished(int32_t errCode) override; + void IncrementalRestoreOnFileReady(std::string bundleName, std::string fileName, int fd, int manifestFd) override; + public: explicit ServiceReverseProxy(const sptr &impl) : IRemoteProxy(impl) {} ~ServiceReverseProxy() override = default; diff --git a/services/backup_sa/include/module_ipc/service_stub.h b/services/backup_sa/include/module_ipc/service_stub.h index 1049e1574..4fea6bb3c 100644 --- a/services/backup_sa/include/module_ipc/service_stub.h +++ b/services/backup_sa/include/module_ipc/service_stub.h @@ -45,6 +45,18 @@ private: int32_t CmdAppendBundlesRestoreSession(MessageParcel &data, MessageParcel &reply); int32_t CmdAppendBundlesBackupSession(MessageParcel &data, MessageParcel &reply); int32_t CmdFinish(MessageParcel &data, MessageParcel &reply); + int32_t CmdRelease(MessageParcel &data, MessageParcel &reply); + int32_t CmdGetLocalCapabilitiesIncremental(MessageParcel &data, MessageParcel &reply); + int32_t CmdInitIncrementalBackupSession(MessageParcel &data, MessageParcel &reply); + int32_t CmdAppendBundlesIncrementalBackupSession(MessageParcel &data, MessageParcel &reply); + int32_t CmdPublishIncrementalFile(MessageParcel &data, MessageParcel &reply); + int32_t CmdAppIncrementalFileReady(MessageParcel &data, MessageParcel &reply); + int32_t CmdAppIncrementalDone(MessageParcel &data, MessageParcel &reply); + int32_t CmdGetIncrementalFileHandle(MessageParcel &data, MessageParcel &reply); + +public: + template + bool ReadParcelableVector(std::vector &parcelableInfos, MessageParcel &data); }; } // namespace OHOS::FileManagement::Backup 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 b47ba5ded..ac48221f0 100644 --- a/services/backup_sa/include/module_ipc/svc_extension_proxy.h +++ b/services/backup_sa/include/module_ipc/svc_extension_proxy.h @@ -18,6 +18,7 @@ #include "i_extension.h" #include "iremote_proxy.h" +#include "unique_fd.h" namespace OHOS::FileManagement::Backup { class SvcExtensionProxy : public IRemoteProxy { @@ -27,6 +28,9 @@ public: ErrCode HandleBackup() override; ErrCode PublishFile(const std::string &fileName) override; ErrCode HandleRestore() override; + ErrCode GetIncrementalFileHandle(const std::string &fileName) override; + ErrCode PublishIncrementalFile(const std::string &fileName) override; + ErrCode HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) override; public: explicit SvcExtensionProxy(const sptr &remote) : IRemoteProxy(remote) {} 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 46671ac84..9473b48b5 100644 --- a/services/backup_sa/include/module_ipc/svc_session_manager.h +++ b/services/backup_sa/include/module_ipc/svc_session_manager.h @@ -30,6 +30,7 @@ #include #include "b_file_info.h" +#include "b_incremental_data.h" #include "b_resources/b_constants.h" #include "i_service.h" #include "i_service_reverse.h" @@ -57,6 +58,10 @@ struct BackupExtInfo { /* Timer Status: true is start & false is stop */ bool timerStatus {false}; int64_t dataSize; + int64_t lastIncrementalTime; + int32_t manifestFd; + std::string backupParameters; + int32_t backupPriority; }; class Service; @@ -75,6 +80,7 @@ public: */ int32_t userId {100}; RestoreTypeEnum restoreDataType {RESTORE_DATA_WAIT_SEND}; + bool isIncrementalBackup {false}; }; public: @@ -377,6 +383,29 @@ public: */ void ClearSessionData(); + /** + * @brief Get the Is Incremental Backup object + * + * @return true + * @return false + */ + bool GetIsIncrementalBackup(); + + /** + * @brief Set the Incremental Data object + * + * @param incrementalData + */ + void SetIncrementalData(const BIncrementalData &incrementalData); + + /** + * @brief Get the Manifest Fd object + * + * @param bundleName 应用名称 + * @return int32_t + */ + int32_t GetIncrementalManifestFd(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 419c87782..5757579fe 100644 --- a/services/backup_sa/include/module_sched/sched_scheduler.h +++ b/services/backup_sa/include/module_sched/sched_scheduler.h @@ -72,11 +72,7 @@ public: */ void TryUnloadService(); - void StartTimer() - { - extTime_.Setup(); - TryUnloadServiceTimer(); - } + void StartTimer(); public: explicit SchedScheduler(wptr reversePtr, wptr sessionPtr) diff --git a/services/backup_sa/src/module_ipc/service.cpp b/services/backup_sa/src/module_ipc/service.cpp index a4f6327f2..d5afa327a 100644 --- a/services/backup_sa/src/module_ipc/service.cpp +++ b/services/backup_sa/src/module_ipc/service.cpp @@ -592,6 +592,9 @@ void Service::ExtStart(const string &bundleName) { try { HILOGE("begin %{public}s", bundleName.data()); + if (IncrementalBackup(bundleName)) { + return; + } IServiceReverse::Scenario scenario = session_->GetScenario(); auto backUpConnection = session_->GetExtConnection(bundleName); auto proxy = backUpConnection->GetBackupExtProxy(); @@ -652,7 +655,16 @@ void Service::ExtConnectFailed(const string &bundleName, ErrCode ret) try { HILOGE("begin %{public}s", bundleName.data()); IServiceReverse::Scenario scenario = session_->GetScenario(); - if (scenario == IServiceReverse::Scenario::BACKUP) { + if (scenario == IServiceReverse::Scenario::BACKUP && session_->GetIsIncrementalBackup()) { + session_->GetServiceReverseProxy()->IncrementalBackupOnBundleStarted(ret, bundleName); + } else if (scenario == IServiceReverse::Scenario::RESTORE && + BackupPara().GetBackupOverrideIncrementalRestore()) { + session_->GetServiceReverseProxy()->IncrementalRestoreOnBundleStarted(ret, bundleName); + + DisposeErr disposeErr = AppGalleryDisposeProxy::GetInstance()->EndRestore(bundleName); + HILOGI("ExtConnectFailed EndRestore, code=%{public}d, bundleName=%{public}s", disposeErr, + bundleName.c_str()); + } else if (scenario == IServiceReverse::Scenario::BACKUP) { session_->GetServiceReverseProxy()->BackupOnBundleStarted(ret, bundleName); } else if (scenario == IServiceReverse::Scenario::RESTORE) { session_->GetServiceReverseProxy()->RestoreOnBundleStarted(ret, bundleName); @@ -677,7 +689,11 @@ void Service::ExtConnectFailed(const string &bundleName, ErrCode ret) void Service::NoticeClientFinish(const string &bundleName, ErrCode errCode) { auto scenario = session_->GetScenario(); - if (scenario == IServiceReverse::Scenario::BACKUP) { + if (scenario == IServiceReverse::Scenario::BACKUP && session_->GetIsIncrementalBackup()) { + session_->GetServiceReverseProxy()->IncrementalBackupOnBundleFinished(errCode, bundleName); + } else if (scenario == IServiceReverse::Scenario::RESTORE && BackupPara().GetBackupOverrideIncrementalRestore()) { + session_->GetServiceReverseProxy()->IncrementalRestoreOnBundleFinished(errCode, bundleName); + } else if (scenario == IServiceReverse::Scenario::BACKUP) { session_->GetServiceReverseProxy()->BackupOnBundleFinished(errCode, bundleName); } else if (scenario == IServiceReverse::Scenario::RESTORE) { session_->GetServiceReverseProxy()->RestoreOnBundleFinished(errCode, bundleName); @@ -783,12 +799,19 @@ void Service::OnAllBundlesFinished(ErrCode errCode) { if (session_->IsOnAllBundlesFinished()) { IServiceReverse::Scenario scenario = session_->GetScenario(); - if (scenario == IServiceReverse::Scenario::BACKUP) { + if (scenario == IServiceReverse::Scenario::BACKUP && session_->GetIsIncrementalBackup()) { + session_->GetServiceReverseProxy()->IncrementalBackupOnAllBundlesFinished(errCode); + } else if (scenario == IServiceReverse::Scenario::RESTORE && + BackupPara().GetBackupOverrideIncrementalRestore()) { + session_->GetServiceReverseProxy()->IncrementalRestoreOnAllBundlesFinished(errCode); + } else if (scenario == IServiceReverse::Scenario::BACKUP) { session_->GetServiceReverseProxy()->BackupOnAllBundlesFinished(errCode); } else if (scenario == IServiceReverse::Scenario::RESTORE) { session_->GetServiceReverseProxy()->RestoreOnAllBundlesFinished(errCode); } - sched_->TryUnloadServiceTimer(true); + if (!BackupPara().GetBackupOverrideBackupSARelease()) { + sched_->TryUnloadServiceTimer(true); + } } } diff --git a/services/backup_sa/src/module_ipc/service_incremental.cpp b/services/backup_sa/src/module_ipc/service_incremental.cpp new file mode 100644 index 000000000..f8ede49c4 --- /dev/null +++ b/services/backup_sa/src/module_ipc/service_incremental.cpp @@ -0,0 +1,321 @@ +/* + * 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. + */ + +/* + * 注意: + * - 注意点1:本文件原则上只处理与IPC无关的业务逻辑 + * - 注意点2:This document, in principle, captures all exceptions. + * Prevent exceptions from spreading to insecure modules. + */ +#include "module_ipc/service.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "ability_manager_client.h" +#include "accesstoken_kit.h" +#include "b_error/b_error.h" +#include "b_error/b_excep_utils.h" +#include "b_file_info.h" +#include "b_json/b_json_cached_entity.h" +#include "b_json/b_json_entity_caps.h" +#include "b_ohos/startup/backup_para.h" +#include "b_process/b_multiuser.h" +#include "b_resources/b_constants.h" +#include "bundle_mgr_client.h" +#include "filemgmt_libhilog.h" +#include "ipc_skeleton.h" +#include "module_app_gallery/app_gallery_dispose_proxy.h" +#include "module_external/bms_adapter.h" +#include "module_ipc/svc_backup_connection.h" +#include "module_ipc/svc_restore_deps_manager.h" +#include "parameter.h" +#include "system_ability_definition.h" +#include "unique_fd.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; + +namespace { +constexpr int32_t DEBUG_ID = 100; +} // namespace + +static inline int32_t GetUserIdDefault() +{ + auto [isDebug, debugId] = BackupPara().GetBackupDebugOverrideAccount(); + if (isDebug && debugId > DEBUG_ID) { + return debugId; + } + auto multiuser = BMultiuser::ParseUid(IPCSkeleton::GetCallingUid()); + if ((multiuser.userId == BConstants::SYSTEM_UID) || (multiuser.userId == BConstants::XTS_UID)) { + return BConstants::DEFAULT_USER_ID; + } + return multiuser.userId; +} + +ErrCode Service::Release() +{ + HILOGI("KILL"); + VerifyCaller(session_->GetScenario()); + SessionDeactive(); + return BError(BError::Codes::OK); +} + +UniqueFd Service::GetLocalCapabilitiesIncremental(const std::vector &bundleNames) +{ + HILOGI("Begin"); + return UniqueFd(-1); +} + +ErrCode Service::InitIncrementalBackupSession(sptr remote) +{ + HILOGI("Begin"); + try { + VerifyCaller(); + session_->Active({.clientToken = IPCSkeleton::GetCallingTokenID(), + .scenario = IServiceReverse::Scenario::BACKUP, + .clientProxy = remote, + .userId = GetUserIdDefault(), + .isIncrementalBackup = true}); + return BError(BError::Codes::OK); + } catch (const BError &e) { + StopAll(nullptr, true); + return e.GetCode(); + } +} + +ErrCode Service::AppendBundlesIncrementalBackupSession(const std::vector &bundlesToBackup) +{ + try { + HILOGI("Begin"); + session_->IncreaseSessionCnt(); // BundleMgrAdapter::GetBundleInfos可能耗时 + VerifyCaller(IServiceReverse::Scenario::BACKUP); + vector bundleNames {}; + for (auto &bundle : bundlesToBackup) { + bundleNames.emplace_back(bundle.bundleName); + } + auto backupInfos = BundleMgrAdapter::GetBundleInfos(bundleNames, session_->GetSessionUserId()); + session_->AppendBundles(bundleNames); + for (auto info : backupInfos) { + session_->SetBundleDataSize(info.name, info.spaceOccupied); + session_->SetBackupExtName(info.name, info.extensionName); + if (info.allToBackup == false) { + session_->GetServiceReverseProxy()->IncrementalBackupOnBundleStarted( + BError(BError::Codes::SA_FORBID_BACKUP_RESTORE), info.name); + session_->RemoveExtInfo(info.name); + } + } + for (auto &bundleInfo : bundlesToBackup) { + session_->SetIncrementalData(bundleInfo); + } + OnStartSched(); + session_->DecreaseSessionCnt(); + return BError(BError::Codes::OK); + } catch (const BError &e) { + session_->DecreaseSessionCnt(); + HILOGE("Failed, errCode = %{public}d", e.GetCode()); + return e.GetCode(); + } catch (...) { + session_->DecreaseSessionCnt(); + HILOGI("Unexpected exception"); + return EPERM; + } +} + +ErrCode Service::PublishIncrementalFile(const BFileInfo &fileInfo) +{ + try { + HILOGI("Begin"); + VerifyCaller(IServiceReverse::Scenario::RESTORE); + + auto backUpConnection = session_->GetExtConnection(fileInfo.owner); + auto proxy = backUpConnection->GetBackupExtProxy(); + if (!proxy) { + throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty"); + } + ErrCode res = proxy->PublishIncrementalFile(fileInfo.fileName); + if (res) { + HILOGE("Failed to publish file for backup extension"); + } + + return res; + } catch (const BError &e) { + return e.GetCode(); + } catch (const exception &e) { + HILOGI("Catched an unexpected low-level exception %{public}s", e.what()); + return EPERM; + } catch (...) { + HILOGI("Unexpected exception"); + return EPERM; + } +} + +ErrCode Service::AppIncrementalFileReady(const std::string &fileName, UniqueFd fd, UniqueFd manifestFd) +{ + try { + HILOGI("Begin"); + string callerName = VerifyCallerAndGetCallerName(); + if (fileName == BConstants::EXT_BACKUP_MANAGE) { + fd = session_->OnBunleExtManageInfo(callerName, move(fd)); + } + + if (session_->GetScenario() == IServiceReverse::Scenario::RESTORE) { + session_->GetServiceReverseProxy()->IncrementalRestoreOnFileReady(callerName, fileName, move(fd), + move(manifestFd)); + return BError(BError::Codes::OK); + } + + session_->GetServiceReverseProxy()->IncrementalBackupOnFileReady(callerName, fileName, move(fd), + move(manifestFd)); + if (session_->OnBunleFileReady(callerName, fileName)) { + auto backUpConnection = session_->GetExtConnection(callerName); + auto proxy = backUpConnection->GetBackupExtProxy(); + if (!proxy) { + throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty"); + } + // 通知extension清空缓存 + proxy->HandleClear(); + // 清除Timer + session_->BundleExtTimerStop(callerName); + // 通知TOOL 备份完成 + session_->GetServiceReverseProxy()->IncrementalBackupOnBundleFinished(BError(BError::Codes::OK), + callerName); + // 断开extension + backUpConnection->DisconnectBackupExtAbility(); + ClearSessionAndSchedInfo(callerName); + } + OnAllBundlesFinished(BError(BError::Codes::OK)); + return BError(BError::Codes::OK); + } catch (const BError &e) { + return e.GetCode(); // 任意异常产生,终止监听该任务 + } catch (const exception &e) { + HILOGI("Catched an unexpected low-level exception %{public}s", e.what()); + return EPERM; + } catch (...) { + HILOGI("Unexpected exception"); + return EPERM; + } +} + +ErrCode Service::AppIncrementalDone(ErrCode errCode) +{ + try { + HILOGI("Begin"); + string callerName = VerifyCallerAndGetCallerName(); + if (session_->OnBunleFileReady(callerName)) { + auto backUpConnection = session_->GetExtConnection(callerName); + auto proxy = backUpConnection->GetBackupExtProxy(); + if (!proxy) { + throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty"); + } + proxy->HandleClear(); + session_->BundleExtTimerStop(callerName); + IServiceReverse::Scenario scenario = session_->GetScenario(); + if (scenario == IServiceReverse::Scenario::BACKUP) { + session_->GetServiceReverseProxy()->IncrementalBackupOnBundleFinished(errCode, callerName); + } else if (scenario == IServiceReverse::Scenario::RESTORE) { + session_->GetServiceReverseProxy()->IncrementalRestoreOnBundleFinished(errCode, callerName); + } + backUpConnection->DisconnectBackupExtAbility(); + ClearSessionAndSchedInfo(callerName); + } + OnAllBundlesFinished(BError(BError::Codes::OK)); + return BError(BError::Codes::OK); + } catch (const BError &e) { + return e.GetCode(); // 任意异常产生,终止监听该任务 + } catch (const exception &e) { + HILOGI("Catched an unexpected low-level exception %{public}s", e.what()); + return EPERM; + } catch (...) { + HILOGI("Unexpected exception"); + return EPERM; + } +} + +ErrCode Service::GetIncrementalFileHandle(const std::string &bundleName, const std::string &fileName) +{ + try { + HILOGI("Begin"); + VerifyCaller(IServiceReverse::Scenario::RESTORE); + auto action = session_->GetServiceSchedAction(bundleName); + if (action == BConstants::ServiceSchedAction::RUNNING) { + auto backUpConnection = session_->GetExtConnection(bundleName); + auto proxy = backUpConnection->GetBackupExtProxy(); + if (!proxy) { + throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty"); + } + int res = proxy->GetIncrementalFileHandle(fileName); + if (res) { + HILOGE("Failed to extension file handle"); + } + } else { + SvcRestoreDepsManager::GetInstance().UpdateToRestoreBundleMap(bundleName, fileName); + session_->SetExtFileNameRequest(bundleName, fileName); + } + return BError(BError::Codes::OK); + } catch (const BError &e) { + return e.GetCode(); + } catch (const exception &e) { + HILOGI("Catched an unexpected low-level exception %{public}s", e.what()); + return EPERM; + } catch (...) { + HILOGI("Unexpected exception"); + return EPERM; + } +} + +bool Service::IncrementalBackup(const string &bundleName) +{ + IServiceReverse::Scenario scenario = session_->GetScenario(); + auto backUpConnection = session_->GetExtConnection(bundleName); + auto proxy = backUpConnection->GetBackupExtProxy(); + if (!proxy) { + throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty"); + } + if (scenario == IServiceReverse::Scenario::BACKUP && session_->GetIsIncrementalBackup()) { + UniqueFd fd; + UniqueFd manifestFd(session_->GetIncrementalManifestFd(bundleName)); + auto ret = proxy->HandleIncrementalBackup(move(fd), move(manifestFd)); + session_->GetServiceReverseProxy()->IncrementalBackupOnBundleStarted(ret, bundleName); + if (ret) { + ClearSessionAndSchedInfo(bundleName); + } + return true; + } else if (scenario == IServiceReverse::Scenario::RESTORE && BackupPara().GetBackupOverrideIncrementalRestore()) { + auto ret = proxy->HandleRestore(); + session_->GetServiceReverseProxy()->IncrementalRestoreOnBundleStarted(ret, bundleName); + auto fileNameVec = session_->GetExtFileNameRequest(bundleName); + for (auto &fileName : fileNameVec) { + ret = proxy->GetIncrementalFileHandle(fileName); + if (ret) { + HILOGE("Failed to extension file handle %{public}s", fileName.c_str()); + } + } + return true; + } + return false; +} +} // namespace OHOS::FileManagement::Backup diff --git a/services/backup_sa/src/module_ipc/service_incremental_reverse_proxy.cpp b/services/backup_sa/src/module_ipc/service_incremental_reverse_proxy.cpp new file mode 100644 index 000000000..dc9b1dfc3 --- /dev/null +++ b/services/backup_sa/src/module_ipc/service_incremental_reverse_proxy.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "module_ipc/service_reverse_proxy.h" + +#include "b_error/b_error.h" +#include "b_error/b_excep_utils.h" +#include "filemgmt_libhilog.h" +#include "module_app_gallery/app_gallery_dispose_proxy.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; + +void ServiceReverseProxy::IncrementalBackupOnFileReady(string bundleName, string fileName, int fd, int manifestFd) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor()) || !data.WriteString(bundleName) || !data.WriteString(fileName) || + !data.WriteFileDescriptor(fd) || !data.WriteFileDescriptor(manifestFd)) { + throw BError(BError::Codes::SA_BROKEN_IPC); + } + + MessageParcel reply; + MessageOption option; + if (int err = Remote()->SendRequest( + static_cast(IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_BACKUP_ON_FILE_READY), data, reply, + option); + err != ERR_OK) { + throw BError(BError::Codes::SA_BROKEN_IPC, to_string(err)); + } +} + +void ServiceReverseProxy::IncrementalBackupOnBundleStarted(int32_t errCode, string bundleName) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor()) || !data.WriteInt32(errCode) || !data.WriteString(bundleName)) { + throw BError(BError::Codes::SA_BROKEN_IPC); + }; + + MessageParcel reply; + MessageOption option; + if (int err = Remote()->SendRequest( + static_cast(IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_BACKUP_ON_SUB_TASK_STARTED), data, + reply, option); + err != ERR_OK) { + throw BError(BError::Codes::SA_BROKEN_IPC, to_string(err)); + } +} + +void ServiceReverseProxy::IncrementalBackupOnBundleFinished(int32_t errCode, string bundleName) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor()) || !data.WriteInt32(errCode) || !data.WriteString(bundleName)) { + throw BError(BError::Codes::SA_BROKEN_IPC); + } + + MessageParcel reply; + MessageOption option; + if (int err = Remote()->SendRequest( + static_cast(IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_BACKUP_ON_SUB_TASK_FINISHED), data, + reply, option); + err != ERR_OK) { + throw BError(BError::Codes::SA_BROKEN_IPC, to_string(err)); + } +} + +void ServiceReverseProxy::IncrementalBackupOnAllBundlesFinished(int32_t errCode) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor()) || !data.WriteInt32(errCode)) { + throw BError(BError::Codes::SA_BROKEN_IPC); + } + + MessageParcel reply; + MessageOption option; + if (int err = Remote()->SendRequest( + static_cast(IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_BACKUP_ON_TASK_FINISHED), data, + reply, option); + err != ERR_OK) { + throw BError(BError::Codes::SA_BROKEN_IPC, to_string(err)); + } +} + +void ServiceReverseProxy::IncrementalRestoreOnBundleStarted(int32_t errCode, string bundleName) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor()) || !data.WriteInt32(errCode) || !data.WriteString(bundleName)) { + throw BError(BError::Codes::SA_BROKEN_IPC); + } + + MessageParcel reply; + MessageOption option; + if (int err = Remote()->SendRequest( + static_cast(IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_RESTORE_ON_SUB_TASK_STARTED), data, + reply, option); + err != ERR_OK) { + throw BError(BError::Codes::SA_BROKEN_IPC, to_string(err)); + } +} + +void ServiceReverseProxy::IncrementalRestoreOnBundleFinished(int32_t errCode, string bundleName) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor()) || !data.WriteInt32(errCode) || !data.WriteString(bundleName)) { + throw BError(BError::Codes::SA_BROKEN_IPC); + } + + MessageParcel reply; + MessageOption option; + if (int err = Remote()->SendRequest( + static_cast(IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_RESTORE_ON_SUB_TASK_FINISHED), + data, reply, option); + err != ERR_OK) { + throw BError(BError::Codes::SA_BROKEN_IPC, to_string(err)); + } + + DisposeErr disposeErr = AppGalleryDisposeProxy::GetInstance()->EndRestore(bundleName); + HILOGI("RestoreOnBundleFinished EndRestore, code=%{public}d, bundleName=%{public}s", disposeErr, + bundleName.c_str()); +} + +void ServiceReverseProxy::IncrementalRestoreOnAllBundlesFinished(int32_t errCode) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor()) || !data.WriteInt32(errCode)) { + throw BError(BError::Codes::SA_BROKEN_IPC); + } + + MessageParcel reply; + MessageOption option; + if (int err = Remote()->SendRequest( + static_cast(IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_RESTORE_ON_TASK_FINISHED), data, + reply, option); + err != ERR_OK) { + throw BError(BError::Codes::SA_BROKEN_IPC, to_string(err)); + } +} + +void ServiceReverseProxy::IncrementalRestoreOnFileReady(string bundleName, string fileName, int fd, int manifestFd) +{ + HILOGI("Begin"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor()) || !data.WriteString(bundleName) || !data.WriteString(fileName) || + !data.WriteFileDescriptor(fd) || !data.WriteFileDescriptor(manifestFd)) { + throw BError(BError::Codes::SA_BROKEN_IPC); + } + + MessageParcel reply; + MessageOption option; + if (int err = Remote()->SendRequest( + static_cast(IServiceReverseInterfaceCode::SERVICER_INCREMENTAL_RESTORE_ON_FILE_READY), data, + reply, option); + err != ERR_OK) { + throw BError(BError::Codes::SA_BROKEN_IPC, to_string(err)); + } +} +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/services/backup_sa/src/module_ipc/service_stub.cpp b/services/backup_sa/src/module_ipc/service_stub.cpp index eb0f9470d..327574e6d 100644 --- a/services/backup_sa/src/module_ipc/service_stub.cpp +++ b/services/backup_sa/src/module_ipc/service_stub.cpp @@ -25,6 +25,7 @@ #include "b_error/b_error.h" #include "b_error/b_excep_utils.h" +#include "b_resources/b_constants.h" #include "filemgmt_libhilog.h" #include "module_ipc/service_reverse_proxy.h" @@ -52,6 +53,23 @@ ServiceStub::ServiceStub() opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_APPEND_BUNDLES_BACKUP_SESSION)] = &ServiceStub::CmdAppendBundlesBackupSession; opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_FINISH)] = &ServiceStub::CmdFinish; + opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_RELSEASE_SESSION)] = + &ServiceStub::CmdRelease; + opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_GET_LOCAL_CAPABILITIES_INCREMENTAL)] = + &ServiceStub::CmdGetLocalCapabilitiesIncremental; + opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_INIT_INCREMENTAL_BACKUP_SESSION)] = + &ServiceStub::CmdInitIncrementalBackupSession; + opToInterfaceMap_[static_cast( + IServiceInterfaceCode::SERVICE_CMD_APPEND_BUNDLES_INCREMENTAL_BACKUP_SESSION)] = + &ServiceStub::CmdAppendBundlesIncrementalBackupSession; + opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_PUBLISH_INCREMENTAL_FILE)] = + &ServiceStub::CmdPublishIncrementalFile; + opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_APP_INCREMENTAL_FILE_READY)] = + &ServiceStub::CmdAppIncrementalFileReady; + opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_APP_INCREMENTAL_DONE)] = + &ServiceStub::CmdAppIncrementalDone; + opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_GET_INCREMENTAL_FILE_NAME)] = + &ServiceStub::CmdGetIncrementalFileHandle; } int32_t ServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) @@ -257,4 +275,161 @@ int32_t ServiceStub::CmdFinish(MessageParcel &data, MessageParcel &reply) } return BError(BError::Codes::OK); } + +int32_t ServiceStub::CmdRelease(MessageParcel &data, MessageParcel &reply) +{ + HILOGI("Begin"); + int res = Release(); + if (!reply.WriteInt32(res)) { + return BError(BError::Codes::SA_BROKEN_IPC, string("Failed to send the result ") + to_string(res)); + } + return BError(BError::Codes::OK); +} + +int32_t ServiceStub::CmdGetLocalCapabilitiesIncremental(MessageParcel &data, MessageParcel &reply) +{ + HILOGI("Begin"); + vector bundleNames; + if (!ReadParcelableVector(bundleNames, data)) { + return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive bundleNames"); + } + + UniqueFd fd(GetLocalCapabilitiesIncremental(bundleNames)); + if (!reply.WriteFileDescriptor(fd)) { + return BError(BError::Codes::SA_BROKEN_IPC, "Failed to send out the file"); + } + return BError(BError::Codes::OK); +} + +int32_t ServiceStub::CmdInitIncrementalBackupSession(MessageParcel &data, MessageParcel &reply) +{ + HILOGI("Begin"); + auto remote = data.ReadRemoteObject(); + if (!remote) { + return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive the reverse stub"); + } + auto iremote = iface_cast(remote); + if (!iremote) { + return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive the reverse stub"); + } + + int32_t res = InitIncrementalBackupSession(iremote); + if (!reply.WriteInt32(res)) { + stringstream ss; + ss << "Failed to send the result " << res; + return BError(BError::Codes::SA_BROKEN_IPC, ss.str()); + } + return BError(BError::Codes::OK); +} + +int32_t ServiceStub::CmdAppendBundlesIncrementalBackupSession(MessageParcel &data, MessageParcel &reply) +{ + HILOGI("Begin"); + vector bundlesToBackup; + if (!ReadParcelableVector(bundlesToBackup, data)) { + return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive bundleNames"); + } + + int32_t res = AppendBundlesIncrementalBackupSession(bundlesToBackup); + if (!reply.WriteInt32(res)) { + return BError(BError::Codes::SA_BROKEN_IPC, string("Failed to send the result ") + to_string(res)); + } + return BError(BError::Codes::OK); +} + +int32_t ServiceStub::CmdPublishIncrementalFile(MessageParcel &data, MessageParcel &reply) +{ + HILOGI("Begin"); + unique_ptr fileInfo(data.ReadParcelable()); + if (!fileInfo) { + return BError(BError::Codes::SA_BROKEN_IPC, "Failed to receive fileInfo"); + } + int res = PublishIncrementalFile(*fileInfo); + if (!reply.WriteInt32(res)) { + stringstream ss; + ss << "Failed to send the result " << res; + return BError(BError::Codes::SA_BROKEN_IPC, ss.str()); + } + return BError(BError::Codes::OK); +} + +int32_t ServiceStub::CmdAppIncrementalFileReady(MessageParcel &data, MessageParcel &reply) +{ + HILOGI("Begin"); + string fileName; + if (!data.ReadString(fileName)) { + return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive fileName"); + } + UniqueFd fd(data.ReadFileDescriptor()); + if (fd < 0) { + return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive fd"); + } + + UniqueFd manifestFd(data.ReadFileDescriptor()); + if (manifestFd < 0) { + return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive fd"); + } + + int res = AppIncrementalFileReady(fileName, move(fd), move(manifestFd)); + if (!reply.WriteInt32(res)) { + stringstream ss; + ss << "Failed to send the result " << res; + return BError(BError::Codes::SA_BROKEN_IPC, ss.str()); + } + return BError(BError::Codes::OK); +} + +int32_t ServiceStub::CmdAppIncrementalDone(MessageParcel &data, MessageParcel &reply) +{ + HILOGI("Begin"); + int32_t ret; + if (!data.ReadInt32(ret)) { + return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive bool flag"); + } + int res = AppIncrementalDone(ret); + if (!reply.WriteInt32(res)) { + stringstream ss; + ss << "Failed to send the result " << res; + return BError(BError::Codes::SA_BROKEN_IPC, ss.str()); + } + return BError(BError::Codes::OK); +} + +int32_t ServiceStub::CmdGetIncrementalFileHandle(MessageParcel &data, MessageParcel &reply) +{ + HILOGI("Begin"); + string bundleName; + if (!data.ReadString(bundleName)) { + return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive bundleName").GetCode(); + } + string fileName; + if (!data.ReadString(fileName)) { + return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive fileName").GetCode(); + } + + return GetIncrementalFileHandle(bundleName, fileName); +} + +template +bool ServiceStub::ReadParcelableVector(std::vector &parcelableInfos, MessageParcel &data) +{ + int32_t infoSize = 0; + if (!data.ReadInt32(infoSize)) { + HILOGE("Failed to read Parcelable size."); + return false; + } + + parcelableInfos.clear(); + infoSize = (infoSize < BConstants::MAX_PARCELABLE_VECTOR_NUM) ? infoSize : BConstants::MAX_PARCELABLE_VECTOR_NUM; + for (int32_t index = 0; index < infoSize; index++) { + sptr info = data.ReadParcelable(); + if (info == nullptr) { + HILOGE("Failed to read Parcelable infos."); + return false; + } + parcelableInfos.emplace_back(move(*info)); + } + + return true; +} } // namespace OHOS::FileManagement::Backup diff --git a/services/backup_sa/src/module_ipc/svc_extension_proxy.cpp b/services/backup_sa/src/module_ipc/svc_extension_proxy.cpp index 8d1c9276c..0eec93ecb 100644 --- a/services/backup_sa/src/module_ipc/svc_extension_proxy.cpp +++ b/services/backup_sa/src/module_ipc/svc_extension_proxy.cpp @@ -134,4 +134,77 @@ ErrCode SvcExtensionProxy::HandleRestore() HILOGI("Successful"); return reply.ReadInt32(); } + +ErrCode SvcExtensionProxy::GetIncrementalFileHandle(const string &fileName) +{ + HILOGI("Start"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + data.WriteInterfaceToken(GetDescriptor()); + + if (!data.WriteString(fileName)) { + BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the fileName"); + return ErrCode(EPERM); + } + + MessageParcel reply; + MessageOption option; + int32_t ret = Remote()->SendRequest(static_cast(IExtensionInterfaceCode::CMD_GET_INCREMENTAL_FILE_HANDLE), + data, reply, option); + if (ret != NO_ERROR) { + HILOGE("Received error %{public}d when doing IPC", ret); + return ErrCode(ret); + } + + HILOGI("Successful"); + return reply.ReadInt32(); +} + +ErrCode SvcExtensionProxy::PublishIncrementalFile(const string &fileName) +{ + HILOGI("Start"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + data.WriteInterfaceToken(GetDescriptor()); + + if (!data.WriteString(fileName)) { + BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the fileName"); + return ErrCode(EPERM); + } + + MessageParcel reply; + MessageOption option; + int32_t ret = Remote()->SendRequest(static_cast(IExtensionInterfaceCode::CMD_PUBLISH_INCREMENTAL_FILE), + data, reply, option); + if (ret != NO_ERROR) { + HILOGE("Received error %{public}d when doing IPC", ret); + return ErrCode(ret); + } + + HILOGI("Successful"); + return reply.ReadInt32(); +} + +ErrCode SvcExtensionProxy::HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) +{ + HILOGI("Start"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + data.WriteInterfaceToken(GetDescriptor()); + + data.WriteFileDescriptor(incrementalFd); + data.WriteFileDescriptor(manifestFd); + + MessageParcel reply; + MessageOption option; + int32_t ret = Remote()->SendRequest(static_cast(IExtensionInterfaceCode::CMD_HANDLE_INCREMENTAL_BACKUP), + data, reply, option); + if (ret != NO_ERROR) { + HILOGE("Received error %{public}d when doing IPC", ret); + return ErrCode(ret); + } + + HILOGI("Successful"); + return reply.ReadInt32(); +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/services/backup_sa/src/module_ipc/svc_session_manager.cpp b/services/backup_sa/src/module_ipc/svc_session_manager.cpp index 1b245feaa..b154d51e7 100644 --- a/services/backup_sa/src/module_ipc/svc_session_manager.cpp +++ b/services/backup_sa/src/module_ipc/svc_session_manager.cpp @@ -30,6 +30,7 @@ #include "filemgmt_libhilog.h" #include "module_ipc/service.h" #include "module_ipc/svc_restore_deps_manager.h" +#include "unique_fd.h" namespace OHOS::FileManagement::Backup { using namespace std; @@ -621,6 +622,10 @@ void SvcSessionManager::ClearSessionData() } // disconnect extension if (it.second.schedAction == BConstants::ServiceSchedAction::RUNNING) { + auto proxy = it.second.backUpConnection->GetBackupExtProxy(); + if (proxy && impl_.restoreDataType != RestoreTypeEnum::RESTORE_DATA_READDY) { + proxy->HandleClear(); + } it.second.backUpConnection->DisconnectBackupExtAbility(); } // clear data @@ -628,4 +633,36 @@ void SvcSessionManager::ClearSessionData() } impl_.backupExtNameMap.clear(); } + +bool SvcSessionManager::GetIsIncrementalBackup() +{ + unique_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + return impl_.isIncrementalBackup; +} + +void SvcSessionManager::SetIncrementalData(const BIncrementalData &incrementalData) +{ + unique_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + auto it = GetBackupExtNameMap(incrementalData.bundleName); + it->second.lastIncrementalTime = incrementalData.lastIncrementalTime; + it->second.manifestFd = incrementalData.manifestFd; + it->second.backupParameters = incrementalData.backupParameters; + it->second.backupPriority = incrementalData.backupPriority; +} + +int32_t SvcSessionManager::GetIncrementalManifestFd(const string &bundleName) +{ + 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.manifestFd; +} } // namespace OHOS::FileManagement::Backup diff --git a/services/backup_sa/src/module_sched/sched_scheduler.cpp b/services/backup_sa/src/module_sched/sched_scheduler.cpp index 77884b5e7..007a74a4e 100644 --- a/services/backup_sa/src/module_sched/sched_scheduler.cpp +++ b/services/backup_sa/src/module_sched/sched_scheduler.cpp @@ -28,6 +28,7 @@ #include #include "b_error/b_error.h" +#include "b_ohos/startup/backup_para.h" #include "filemgmt_libhilog.h" #include "iservice_registry.h" #include "module_external/bms_adapter.h" @@ -117,6 +118,14 @@ void SchedScheduler::RemoveExtConn(const string &bundleName) } } +void SchedScheduler::StartTimer() +{ + extTime_.Setup(); + if (!BackupPara().GetBackupOverrideBackupSARelease()) { + TryUnloadServiceTimer(); + } +} + void SchedScheduler::TryUnloadServiceTimer(bool force) { auto tryUnload = [sessionPtr {sessionPtr_}]() { diff --git a/tests/mock/b_filesystem/b_file_mock.cpp b/tests/mock/b_filesystem/b_file_mock.cpp index d3561215a..1e80a11dd 100644 --- a/tests/mock/b_filesystem/b_file_mock.cpp +++ b/tests/mock/b_filesystem/b_file_mock.cpp @@ -83,4 +83,10 @@ bool BFile::CopyFile(const string &from, const string &to) { return true; } + +vector> BFile::ReadIncrementalFile(const UniqueFd &fd) +{ + vector> infos; + return infos; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/mock/backup_kit_inner/b_session_backup_mock.cpp b/tests/mock/backup_kit_inner/b_session_backup_mock.cpp index f3a8f5193..4f34a37d7 100644 --- a/tests/mock/backup_kit_inner/b_session_backup_mock.cpp +++ b/tests/mock/backup_kit_inner/b_session_backup_mock.cpp @@ -92,4 +92,9 @@ ErrCode BSessionBackup::Finish() { return BError(BError::Codes::OK); } + +ErrCode BSessionBackup::Release() +{ + return BError(BError::Codes::OK); +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/mock/backup_kit_inner/b_session_restore_async_mock.cpp b/tests/mock/backup_kit_inner/b_session_restore_async_mock.cpp index 4068bd936..def40ed6e 100644 --- a/tests/mock/backup_kit_inner/b_session_restore_async_mock.cpp +++ b/tests/mock/backup_kit_inner/b_session_restore_async_mock.cpp @@ -96,5 +96,10 @@ ErrCode BSessionRestoreAsync::AppendBundles(UniqueFd remoteCap, void BSessionRestoreAsync::OnBackupServiceDied() {} +ErrCode BSessionRestoreAsync::Release() +{ + return BError(BError::Codes::OK); +} + void BSessionRestoreAsync::RegisterBackupServiceDied(function functor) {} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/mock/backup_kit_inner/b_session_restore_mock.cpp b/tests/mock/backup_kit_inner/b_session_restore_mock.cpp index 49d4126bc..3af358b95 100644 --- a/tests/mock/backup_kit_inner/b_session_restore_mock.cpp +++ b/tests/mock/backup_kit_inner/b_session_restore_mock.cpp @@ -96,5 +96,10 @@ ErrCode BSessionRestore::Finish() return BError(BError::Codes::OK); } +ErrCode BSessionRestore::Release() +{ + return BError(BError::Codes::OK); +} + void BSessionRestore::RegisterBackupServiceDied(function functor) {} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/mock/backup_kit_inner/service_proxy_mock.cpp b/tests/mock/backup_kit_inner/service_proxy_mock.cpp index cd0808e1a..760bd1158 100644 --- a/tests/mock/backup_kit_inner/service_proxy_mock.cpp +++ b/tests/mock/backup_kit_inner/service_proxy_mock.cpp @@ -98,6 +98,46 @@ ErrCode ServiceProxy::Finish() return BError(BError::Codes::OK); } +ErrCode ServiceProxy::Release() +{ + return BError(BError::Codes::OK); +} + +UniqueFd ServiceProxy::GetLocalCapabilitiesIncremental(const vector &bundleNames) +{ + return UniqueFd(-1); +} + +ErrCode ServiceProxy::InitIncrementalBackupSession(sptr remote) +{ + return BError(BError::Codes::OK); +} + +ErrCode ServiceProxy::AppendBundlesIncrementalBackupSession(const vector &bundlesToBackup) +{ + return BError(BError::Codes::OK); +} + +ErrCode ServiceProxy::PublishIncrementalFile(const BFileInfo &fileInfo) +{ + return BError(BError::Codes::OK); +} + +ErrCode ServiceProxy::AppIncrementalFileReady(const string &fileName, UniqueFd fd, UniqueFd manifestFd) +{ + return BError(BError::Codes::OK); +} + +ErrCode ServiceProxy::AppIncrementalDone(ErrCode errCode) +{ + return BError(BError::Codes::OK); +} + +ErrCode ServiceProxy::GetIncrementalFileHandle(const std::string &bundleName, const std::string &fileName) +{ + return BError(BError::Codes::OK); +} + sptr ServiceProxy::GetInstance() { if (!GetMockGetInstance()) { diff --git a/tests/mock/module_ipc/service_mock.cpp b/tests/mock/module_ipc/service_mock.cpp index 898c0f835..bf99081c7 100644 --- a/tests/mock/module_ipc/service_mock.cpp +++ b/tests/mock/module_ipc/service_mock.cpp @@ -129,4 +129,44 @@ void Service::OnStartSched() {} void Service::SendAppGalleryNotify(const BundleName &bundleName) {} void Service::SessionDeactive() {} + +ErrCode Service::Release() +{ + return BError(BError::Codes::OK); +} + +UniqueFd Service::GetLocalCapabilitiesIncremental(const std::vector &bundleNames) +{ + return UniqueFd(-1); +} + +ErrCode Service::InitIncrementalBackupSession(sptr remote) +{ + return BError(BError::Codes::OK); +} + +ErrCode Service::AppendBundlesIncrementalBackupSession(const std::vector &bundlesToBackup) +{ + return BError(BError::Codes::OK); +} + +ErrCode Service::PublishIncrementalFile(const BFileInfo &fileInfo) +{ + return BError(BError::Codes::OK); +} + +ErrCode Service::AppIncrementalFileReady(const string &fileName, UniqueFd fd, UniqueFd manifestFd) +{ + return BError(BError::Codes::OK); +} + +ErrCode Service::AppIncrementalDone(ErrCode errCode) +{ + return BError(BError::Codes::OK); +} + +ErrCode Service::GetIncrementalFileHandle(const string &bundleName, const string &fileName) +{ + return BError(BError::Codes::OK); +} } // namespace OHOS::FileManagement::Backup diff --git a/tests/mock/module_ipc/service_reverse_proxy_mock.cpp b/tests/mock/module_ipc/service_reverse_proxy_mock.cpp index 0f98e5e2e..456a81465 100644 --- a/tests/mock/module_ipc/service_reverse_proxy_mock.cpp +++ b/tests/mock/module_ipc/service_reverse_proxy_mock.cpp @@ -35,4 +35,20 @@ void ServiceReverseProxy::RestoreOnBundleFinished(int32_t errCode, string bundle void ServiceReverseProxy::RestoreOnAllBundlesFinished(int32_t errCode) {} void ServiceReverseProxy::RestoreOnFileReady(string bundleName, string fileName, int fd) {} + +void ServiceReverseProxy::IncrementalBackupOnFileReady(string bundleName, string fileName, int fd, int manifestFd) {} + +void ServiceReverseProxy::IncrementalBackupOnBundleStarted(int32_t errCode, string bundleName) {} + +void ServiceReverseProxy::IncrementalBackupOnBundleFinished(int32_t errCode, string bundleName) {} + +void ServiceReverseProxy::IncrementalBackupOnAllBundlesFinished(int32_t errCode) {} + +void ServiceReverseProxy::IncrementalRestoreOnBundleStarted(int32_t errCode, string bundleName) {} + +void ServiceReverseProxy::IncrementalRestoreOnBundleFinished(int32_t errCode, string bundleName) {} + +void ServiceReverseProxy::IncrementalRestoreOnAllBundlesFinished(int32_t errCode) {} + +void ServiceReverseProxy::IncrementalRestoreOnFileReady(string bundleName, string fileName, int fd, int manifestFd) {} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/mock/module_ipc/service_stub_mock.cpp b/tests/mock/module_ipc/service_stub_mock.cpp index 07e131cac..3e65392b3 100644 --- a/tests/mock/module_ipc/service_stub_mock.cpp +++ b/tests/mock/module_ipc/service_stub_mock.cpp @@ -44,6 +44,21 @@ ServiceStub::ServiceStub() opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_APPEND_BUNDLES_BACKUP_SESSION)] = &ServiceStub::CmdAppendBundlesBackupSession; opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_FINISH)] = &ServiceStub::CmdFinish; + opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_RELSEASE_SESSION)] = + &ServiceStub::CmdRelease; + opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_GET_LOCAL_CAPABILITIES_INCREMENTAL)] = + &ServiceStub::CmdGetLocalCapabilitiesIncremental; + opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_INIT_INCREMENTAL_BACKUP_SESSION)] = + &ServiceStub::CmdInitIncrementalBackupSession; + opToInterfaceMap_[static_cast( + IServiceInterfaceCode::SERVICE_CMD_APPEND_BUNDLES_INCREMENTAL_BACKUP_SESSION)] = + &ServiceStub::CmdAppendBundlesIncrementalBackupSession; + opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_PUBLISH_INCREMENTAL_FILE)] = + &ServiceStub::CmdPublishIncrementalFile; + opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_APP_INCREMENTAL_FILE_READY)] = + &ServiceStub::CmdAppIncrementalFileReady; + opToInterfaceMap_[static_cast(IServiceInterfaceCode::SERVICE_CMD_GET_INCREMENTAL_FILE_NAME)] = + &ServiceStub::CmdGetIncrementalFileHandle; } int32_t ServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) @@ -159,4 +174,41 @@ int32_t ServiceStub::CmdFinish(MessageParcel &data, MessageParcel &reply) reply.WriteInt32(res); return BError(BError::Codes::OK); } + +int32_t ServiceStub::CmdRelease(MessageParcel &data, MessageParcel &reply) +{ + int res = Release(); + reply.WriteInt32(res); + return BError(BError::Codes::OK); +} + +int32_t ServiceStub::CmdGetLocalCapabilitiesIncremental(MessageParcel &data, MessageParcel &reply) +{ + return BError(BError::Codes::OK); +} + +int32_t ServiceStub::CmdInitIncrementalBackupSession(MessageParcel &data, MessageParcel &reply) +{ + return BError(BError::Codes::OK); +} + +int32_t ServiceStub::CmdAppendBundlesIncrementalBackupSession(MessageParcel &data, MessageParcel &reply) +{ + return BError(BError::Codes::OK); +} + +int32_t ServiceStub::CmdPublishIncrementalFile(MessageParcel &data, MessageParcel &reply) +{ + return BError(BError::Codes::OK); +} + +int32_t ServiceStub::CmdAppIncrementalFileReady(MessageParcel &data, MessageParcel &reply) +{ + return BError(BError::Codes::OK); +} + +int32_t ServiceStub::CmdGetIncrementalFileHandle(MessageParcel &data, MessageParcel &reply) +{ + return BError(BError::Codes::OK); +} } // 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 2403f2d2f..6c1fbe7e3 100644 --- a/tests/mock/module_ipc/svc_extension_proxy_mock.cpp +++ b/tests/mock/module_ipc/svc_extension_proxy_mock.cpp @@ -42,4 +42,19 @@ ErrCode SvcExtensionProxy::HandleRestore() { return 0; } + +ErrCode SvcExtensionProxy::GetIncrementalFileHandle(const string &fileName) +{ + return 0; +} + +ErrCode SvcExtensionProxy::PublishIncrementalFile(const string &fileName) +{ + return 0; +} + +ErrCode SvcExtensionProxy::HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) +{ + return 0; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/mock/module_ipc/svc_session_manager_mock.cpp b/tests/mock/module_ipc/svc_session_manager_mock.cpp index 8c9ff7ab9..e5b8d488b 100644 --- a/tests/mock/module_ipc/svc_session_manager_mock.cpp +++ b/tests/mock/module_ipc/svc_session_manager_mock.cpp @@ -314,4 +314,16 @@ void SvcSessionManager::IncreaseSessionCnt() {} void SvcSessionManager::DecreaseSessionCnt() {} void SvcSessionManager::ClearSessionData() {} + +bool SvcSessionManager::GetIsIncrementalBackup() +{ + return true; +} + +void SvcSessionManager::SetIncrementalData(const BIncrementalData &incrementalData) {} + +int32_t SvcSessionManager::GetIncrementalManifestFd(const string &bundleName) +{ + return 0; +} } // namespace OHOS::FileManagement::Backup diff --git a/tests/mock/module_sched/sched_scheduler_mock.cpp b/tests/mock/module_sched/sched_scheduler_mock.cpp index 82fdc4485..65c744fa7 100644 --- a/tests/mock/module_sched/sched_scheduler_mock.cpp +++ b/tests/mock/module_sched/sched_scheduler_mock.cpp @@ -30,6 +30,8 @@ void SchedScheduler::ExecutingQueueTasks(const string &bundleName) {} void SchedScheduler::RemoveExtConn(const string &bundleName) {} +void SchedScheduler::StartTimer() {} + void SchedScheduler::TryUnloadServiceTimer(bool force) {} void SchedScheduler::TryUnloadService() {} diff --git a/tests/moduletests/backup_kit_inner/BUILD.gn b/tests/moduletests/backup_kit_inner/BUILD.gn index 71baea891..212467ce1 100644 --- a/tests/moduletests/backup_kit_inner/BUILD.gn +++ b/tests/moduletests/backup_kit_inner/BUILD.gn @@ -21,6 +21,7 @@ ohos_unittest("b_session_test") { "${path_backup}/frameworks/native/backup_kit_inner/src/b_session_backup.cpp", "${path_backup}/frameworks/native/backup_kit_inner/src/b_session_restore.cpp", "${path_backup}/frameworks/native/backup_kit_inner/src/b_session_restore_async.cpp", + "${path_backup}/frameworks/native/backup_kit_inner/src/service_incremental_reverse.cpp", "${path_backup}/frameworks/native/backup_kit_inner/src/service_reverse.cpp", "${path_backup}/frameworks/native/backup_kit_inner/src/service_reverse_stub.cpp", "b_session_backup_test.cpp", 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 bc7ed16eb..d6fe04fba 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 @@ -97,6 +97,21 @@ public: return BError(BError::Codes::OK); }; + ErrCode GetIncrementalFileHandle(const std::string &fileName) override + { + return BError(BError::Codes::OK); + }; + + ErrCode PublishIncrementalFile(const std::string &fileName) override + { + return BError(BError::Codes::OK); + }; + + ErrCode HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) override + { + return BError(BError::Codes::OK); + }; + private: int32_t nHandleBackupNum_ = 0; }; diff --git a/tests/unittests/backup_api/backup_impl/include/i_service_mock.h b/tests/unittests/backup_api/backup_impl/include/i_service_mock.h index 2af0cb1e1..3436577a1 100644 --- a/tests/unittests/backup_api/backup_impl/include/i_service_mock.h +++ b/tests/unittests/backup_api/backup_impl/include/i_service_mock.h @@ -110,6 +110,46 @@ public: { return BError(BError::Codes::OK); } + + ErrCode Release() override + { + return BError(BError::Codes::OK); + } + + UniqueFd GetLocalCapabilitiesIncremental(const std::vector &bundleNames) override + { + return UniqueFd(-1); + } + + ErrCode InitIncrementalBackupSession(sptr remote) override + { + return BError(BError::Codes::OK); + } + + ErrCode AppendBundlesIncrementalBackupSession(const std::vector &bundlesToBackup) override + { + return BError(BError::Codes::OK); + } + + ErrCode PublishIncrementalFile(const BFileInfo &fileInfo) + { + return BError(BError::Codes::OK); + } + + ErrCode AppIncrementalFileReady(const std::string &fileName, UniqueFd fd, UniqueFd manifestFd) + { + return BError(BError::Codes::OK); + } + + ErrCode AppIncrementalDone(ErrCode errCode) + { + return BError(BError::Codes::OK); + } + + ErrCode GetIncrementalFileHandle(const std::string &bundleName, const std::string &fileName) + { + return BError(BError::Codes::OK); + } }; } // namespace OHOS::FileManagement::Backup #endif // MOCK_I_SERVICE_MOCK_H \ No newline at end of file diff --git a/tests/unittests/backup_api/backup_impl/include/service_reverse_mock.h b/tests/unittests/backup_api/backup_impl/include/service_reverse_mock.h index e4f6e2a2a..9808e5d41 100644 --- a/tests/unittests/backup_api/backup_impl/include/service_reverse_mock.h +++ b/tests/unittests/backup_api/backup_impl/include/service_reverse_mock.h @@ -45,6 +45,16 @@ public: void RestoreOnBundleFinished(int32_t errCode, std::string bundleName) override {} void RestoreOnAllBundlesFinished(int32_t errCode) override {} void RestoreOnFileReady(std::string bundleName, std::string fileName, int fd) override {} + + void IncrementalBackupOnFileReady(std::string bundleName, std::string fileName, int fd, int manifestFd) override {} + void IncrementalBackupOnBundleStarted(int32_t errCode, std::string bundleName) override {} + void IncrementalBackupOnBundleFinished(int32_t errCode, std::string bundleName) override {} + void IncrementalBackupOnAllBundlesFinished(int32_t errCode) override {} + + void IncrementalRestoreOnBundleStarted(int32_t errCode, std::string bundleName) override {} + void IncrementalRestoreOnBundleFinished(int32_t errCode, std::string bundleName) override {} + void IncrementalRestoreOnAllBundlesFinished(int32_t errCode) override {} + void IncrementalRestoreOnFileReady(std::string bundleName, std::string fileName, int fd, int manifestFd) override {} }; } // namespace OHOS::FileManagement::Backup #endif // MOCK_SERVICE_REVERSE_MOCK_H \ No newline at end of file diff --git a/tests/unittests/backup_api/backup_impl/service_reverse_stub_test.cpp b/tests/unittests/backup_api/backup_impl/service_reverse_stub_test.cpp index c3f41057d..2fd0b60a7 100644 --- a/tests/unittests/backup_api/backup_impl/service_reverse_stub_test.cpp +++ b/tests/unittests/backup_api/backup_impl/service_reverse_stub_test.cpp @@ -47,6 +47,14 @@ public: MOCK_METHOD2(RestoreOnBundleFinished, void(int32_t errCode, string bundleName)); MOCK_METHOD1(RestoreOnAllBundlesFinished, void(int32_t errCode)); MOCK_METHOD3(RestoreOnFileReady, void(string bundleName, string fileName, int fd)); + MOCK_METHOD4(IncrementalBackupOnFileReady, void(string bundleName, string fileName, int fd, int manifestFd)); + MOCK_METHOD2(IncrementalBackupOnBundleStarted, void(int32_t errCode, string bundleName)); + MOCK_METHOD2(IncrementalBackupOnBundleFinished, void(int32_t errCode, string bundleName)); + MOCK_METHOD1(IncrementalBackupOnAllBundlesFinished, void(int32_t errCode)); + MOCK_METHOD2(IncrementalRestoreOnBundleStarted, void(int32_t errCode, std::string bundleName)); + MOCK_METHOD2(IncrementalRestoreOnBundleFinished, void(int32_t errCode, string bundleName)); + MOCK_METHOD1(IncrementalRestoreOnAllBundlesFinished, void(int32_t errCode)); + MOCK_METHOD4(IncrementalRestoreOnFileReady, void(string bundleName, string fileName, int fd, int manifestFd)); }; class ServiceReverseStubTest : public testing::Test { diff --git a/tests/unittests/backup_sa/module_ipc/BUILD.gn b/tests/unittests/backup_sa/module_ipc/BUILD.gn index fa9f7762e..3864c6553 100644 --- a/tests/unittests/backup_sa/module_ipc/BUILD.gn +++ b/tests/unittests/backup_sa/module_ipc/BUILD.gn @@ -68,6 +68,7 @@ ohos_unittest("backup_service_test") { "${path_backup_mock}/accesstoken/accesstoken_kit_mock.cpp", "${path_backup_mock}/module_ipc/app_gallery_dispose_proxy_mock.cpp", "${path_backup_mock}/timer/timer_mock.cpp", + "${path_backup}/services/backup_sa/src/module_ipc/service_incremental.cpp", "${path_backup}/services/backup_sa/src/module_ipc/service.cpp", "${path_backup}/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp", "service_test.cpp", @@ -217,6 +218,7 @@ ohos_unittest("backup_restore_deps_manager_test") { sources = [ "${path_backup_mock}/accesstoken/accesstoken_kit_mock.cpp", "${path_backup}/services/backup_sa/src/module_app_gallery/app_gallery_dispose_proxy.cpp", + "${path_backup}/services/backup_sa/src/module_ipc/service_incremental.cpp", "${path_backup}/services/backup_sa/src/module_ipc/service.cpp", "${path_backup}/services/backup_sa/src/module_ipc/svc_restore_deps_manager.cpp", "svc_restore_deps_manager_test.cpp", diff --git a/tests/unittests/backup_sa/module_ipc/service_stub_test.cpp b/tests/unittests/backup_sa/module_ipc/service_stub_test.cpp index 8b06ed40c..2e221933d 100644 --- a/tests/unittests/backup_sa/module_ipc/service_stub_test.cpp +++ b/tests/unittests/backup_sa/module_ipc/service_stub_test.cpp @@ -53,6 +53,15 @@ public: ErrCode(UniqueFd fd, const std::vector &bundleNames, RestoreTypeEnum restoreType, int32_t userId)); MOCK_METHOD1(AppendBundlesBackupSession, ErrCode(const std::vector &bundleNames)); MOCK_METHOD0(Finish, ErrCode()); + MOCK_METHOD0(Release, ErrCode()); + MOCK_METHOD1(GetLocalCapabilitiesIncremental, UniqueFd(const std::vector &bundleNames)); + MOCK_METHOD1(InitIncrementalBackupSession, ErrCode(sptr remote)); + MOCK_METHOD1(AppendBundlesIncrementalBackupSession, ErrCode(const std::vector &bundlesToBackup)); + + MOCK_METHOD1(PublishIncrementalFile, ErrCode(const BFileInfo &fileInfo)); + MOCK_METHOD3(AppIncrementalFileReady, ErrCode(const std::string &fileName, UniqueFd fd, UniqueFd manifestFd)); + MOCK_METHOD1(AppIncrementalDone, ErrCode(ErrCode errCode)); + MOCK_METHOD2(GetIncrementalFileHandle, ErrCode(const std::string &bundleName, const std::string &fileName)); UniqueFd InvokeGetLocalCapabilities() { if (bCapabilities_) { @@ -466,4 +475,34 @@ HWTEST_F(ServiceStubTest, SUB_backup_sa_ServiceStub_Finish_0100, testing::ext::T } GTEST_LOG_(INFO) << "ServiceStubTest-end SUB_backup_sa_ServiceStub_Finish_0100"; } + +/** + * @tc.number: SUB_backup_sa_ServiceStub_Release_0100 + * @tc.name: SUB_backup_sa_ServiceStub_Release_0100 + * @tc.desc: Test function of Release interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: I6URNZ + */ +HWTEST_F(ServiceStubTest, SUB_backup_sa_ServiceStub_Release_0100, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "ServiceStubTest-begin SUB_backup_sa_ServiceStub_Release_0100"; + try { + MockService service; + EXPECT_CALL(service, Release()).WillOnce(Return(BError(BError::Codes::OK))); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + EXPECT_TRUE(data.WriteInterfaceToken(IService::GetDescriptor())); + EXPECT_EQ(BError(BError::Codes::OK), + service.OnRemoteRequest(static_cast(IServiceInterfaceCode::SERVICE_CMD_RELSEASE_SESSION), + data, reply, option)); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "ServiceStubTest-an exception occurred by Release."; + } + GTEST_LOG_(INFO) << "ServiceStubTest-end SUB_backup_sa_ServiceStub_Release_0100"; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp b/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp index 5708ff760..e253747f9 100644 --- a/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp +++ b/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp @@ -160,4 +160,58 @@ HWTEST_F(BFileTest, b_file_Write_0100, testing::ext::TestSize.Level1) } GTEST_LOG_(INFO) << "BFileTest-end b_file_Write_0100"; } + +/** + * @brief 创建增量测试文件 + * + * @return tuple 文件路径、对比内容 + */ +static tuple GetTestIncrementalFile(const TestManager &tm) +{ + string path = tm.GetRootDirCurTest(); + string filePath = path + "incremental.txt"; + string content = "version=1.0&attrNum=6\npath;mode;dir;size;mtime;hash\n"; + string info = "a.txt;0660;0;10;123456;asd1asdasd;"; + if (bool contentCreate = SaveStringToFile(filePath, content + info, true); !contentCreate) { + throw system_error(errno, system_category()); + } + return {filePath, info}; +} + +/** + * @tc.number: SUB_backup_b_file_ReadIncrementalFile_0100 + * @tc.name: b_file_ReadIncrementalFile_0100 + * @tc.desc: 测试ReadIncrementalFile接口 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: I6F3GV + */ +HWTEST_F(BFileTest, b_file_ReadIncrementalFile_0100, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BFileTest-begin b_file_ReadIncrementalFile_0100"; + try { + TestManager tm(__func__); + const auto [filePath, content] = GetTestFile(tm); + TestManager tmInFile("b_file_ReadIncrementalFile_0100"); + string fileInPath = tmInFile.GetRootDirCurTest().append("1.txt"); + BFile::Write(UniqueFd(open(filePath.data(), O_RDWR)), fileInPath); + vector> infos = BFile::ReadIncrementalFile(UniqueFd(open(fileInPath.c_str(), O_RDONLY))); + string incrInfo = ""; + for (auto item : infos) { + string filePath = info.find("path") != info.end() ? info.find("path")->second : ""; + string mode = info.find("mode") != info.end() ? info.find("mode")->second : ""; + string dir = info.find("dir") != info.end() ? info.find("dir")->second : "0"; + string size = info.find("size") != info.end() ? stoll(info.find("size")->second) : "0"; + string mtime = info.find("mtime") != info.end() ? info.find("mtime")->second : "0"; + string hash = info.find("hash") != info.end() ? info.find("hash")->second : ""; + incrInfo += filePath + ";" + mode + ";" + dir + ";" + size + ";" + mtime + ";" + hash + ";"; + } + EXPECT_EQ(incrInfo, content); + } catch (const exception &e) { + GTEST_LOG_(INFO) << "BFileTest-an exception occurred by Write."; + e.what(); + } + GTEST_LOG_(INFO) << "BFileTest-end b_file_ReadIncrementalFile_0100"; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tools/backup_tool/BUILD.gn b/tools/backup_tool/BUILD.gn index b164c2006..83db49e08 100644 --- a/tools/backup_tool/BUILD.gn +++ b/tools/backup_tool/BUILD.gn @@ -39,6 +39,7 @@ ohos_executable("backup_tool") { "src/tools_op_backup.cpp", "src/tools_op_check_sa.cpp", "src/tools_op_help.cpp", + "src/tools_op_incremental_backup.cpp", "src/tools_op_restore.cpp", "src/tools_op_restore_async.cpp", ] diff --git a/tools/backup_tool/include/tools_op_incremental_backup.h b/tools/backup_tool/include/tools_op_incremental_backup.h new file mode 100644 index 000000000..e1d581d55 --- /dev/null +++ b/tools/backup_tool/include/tools_op_incremental_backup.h @@ -0,0 +1,24 @@ +/* + * 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_TOOLS_OP_INCREMENTAL_BACKUP_H +#define OHOS_FILEMGMT_BACKUP_TOOLS_OP_INCREMENTAL_BACKUP_H + +namespace OHOS::FileManagement::Backup { + bool IncrementalBackUpRegister(); + +} // namespace OHOS::FileManagement::Backup + +#endif // OHOS_FILEMGMT_BACKUP_TOOLS_OP_INCREMENTAL_BACKUP_H \ No newline at end of file diff --git a/tools/backup_tool/src/main.cpp b/tools/backup_tool/src/main.cpp index 4de614c58..d1cef740c 100644 --- a/tools/backup_tool/src/main.cpp +++ b/tools/backup_tool/src/main.cpp @@ -27,6 +27,7 @@ int main() #include "tools_op_help.h" #include "tools_op_restore.h" #include "tools_op_restore_async.h" +#include "tools_op_incremental_backup.h" #include #include @@ -83,6 +84,7 @@ void ToolRegister() OHOS::FileManagement::Backup::CheckSaRegister(); OHOS::FileManagement::Backup::RestoreRegister(); OHOS::FileManagement::Backup::RestoreAsyncRegister(); + OHOS::FileManagement::Backup::IncrementalBackUpRegister(); } int ParseOpAndExecute(const int argc, char *const argv[]) diff --git a/tools/backup_tool/src/tools_op_backup.cpp b/tools/backup_tool/src/tools_op_backup.cpp index d79b1ba62..e9c1e97e6 100644 --- a/tools/backup_tool/src/tools_op_backup.cpp +++ b/tools/backup_tool/src/tools_op_backup.cpp @@ -258,6 +258,7 @@ static int32_t InitPathCapFile(const string &pathCapFile, vector bundleN ctx->SetBundleFinishedCount(bundleNames.size()); ctx->Wait(); FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + ctx->session_->Release(); return 0; } diff --git a/tools/backup_tool/src/tools_op_incremental_backup.cpp b/tools/backup_tool/src/tools_op_incremental_backup.cpp new file mode 100644 index 000000000..d776b8bbd --- /dev/null +++ b/tools/backup_tool/src/tools_op_incremental_backup.cpp @@ -0,0 +1,305 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "b_error/b_error.h" +#include "b_filesystem/b_file.h" +#include "b_json/b_json_entity_ext_manage.h" +#include "b_resources/b_constants.h" +#include "backup_kit_inner.h" +#include "base/hiviewdfx/hitrace/interfaces/native/innerkits/include/hitrace_meter/hitrace_meter.h" +#include "out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/include/fcntl.h" +#include "out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/include/stdio.h" +#include "service_proxy.h" +#include "tools_op.h" +#include "tools_op_backup.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; + +class Session { +public: + void UpdateBundleReceivedFiles(const BundleName &bundleName, const string &fileName) + { + lock_guard lk(lock_); + bundleStatusMap_[bundleName].receivedFile.insert(fileName); + TryClearBundleOfMap(bundleName); + } + + void SetIndexFiles(const BundleName &bundleName, UniqueFd fd) + { + BJsonCachedEntity cachedEntity(move(fd)); + auto cache = cachedEntity.Structuralize(); + lock_guard lk(lock_); + bundleStatusMap_[bundleName].indexFile = cache.GetExtManage(); + } + + void TryNotify(bool flag = false) + { + if (flag == true) { + ready_ = true; + cv_.notify_all(); + } else if (bundleStatusMap_.size() == 0 && cnt_ == 0 && isAllBundelsFinished.load()) { + ready_ = true; + cv_.notify_all(); + } + } + + void UpdateBundleFinishedCount() + { + lock_guard lk(lock_); + cnt_--; + } + + void SetBundleFinishedCount(uint32_t cnt) + { + cnt_ = cnt; + } + + void Wait() + { + unique_lock lk(lock_); + cv_.wait(lk, [&] { return ready_; }); + } + + unique_ptr session_ = {}; + +private: + struct BundleStatus { + set receivedFile; + set indexFile; + }; + + void TryClearBundleOfMap(const BundleName &bundleName) + { + if (bundleStatusMap_[bundleName].indexFile == bundleStatusMap_[bundleName].receivedFile) { + bundleStatusMap_.erase(bundleName); + } + } + + map bundleStatusMap_; + mutable condition_variable cv_; + mutex lock_; + bool ready_ = false; + uint32_t cnt_ {0}; + +public: + std::atomic isAllBundelsFinished {false}; + string lastIncrementalTime; +}; + +static string GenHelpMsg() +{ + return "\t\tThis operation helps to backup application data.\n" + "\t\t--isLocal\t\t This parameter should be true or flase; true: local backup false: others.\n" + "\t\t--pathCapFile\t\t This parameter should be the path of the capability file.\n" + "\t\t--bundle\t\t This parameter is bundleName."; +} + +static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, UniqueFd fd, UniqueFd manifestFd) +{ + printf("FileReady owner = %s, fileName = %s, sn = %u, fd = %d, manifestFd = %d\n", fileInfo.owner.c_str(), + fileInfo.fileName.c_str(), fileInfo.sn, fd.Get(), manifestFd.Get()); + string tmpPath = string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + fileInfo.owner; + if (access(tmpPath.data(), F_OK) != 0 && mkdir(tmpPath.data(), S_IRWXU) != 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + tmpPath = tmpPath + "/" + ctx->lastIncrementalTime; + if (access(tmpPath.data(), F_OK) != 0 && mkdir(tmpPath.data(), S_IRWXU) != 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + string tmpDataPath = tmpPath + "/incremental"; + if (access(tmpDataPath.data(), F_OK) != 0 && mkdir(tmpDataPath.data(), S_IRWXU) != 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + UniqueFd fdLocal(open((tmpDataPath + "/" + fileInfo.fileName).data(), O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU)); + if (fdLocal < 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + BFile::SendFile(fdLocal, fd); + + // 简报文件保存 + string tmpmanifestPath = tmpPath + "/manifest"; + if (access(tmpDataPath.data(), F_OK) != 0 && mkdir(tmpDataPath.data(), S_IRWXU) != 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + UniqueFd fdManifest( + open((tmpmanifestPath + "/" + fileInfo.fileName + "_manifest").data(), O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU)); + if (fdManifest < 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + BFile::SendFile(fdManifest, fd); + if (fileInfo.fileName == BConstants::EXT_BACKUP_MANAGE) { + ctx->SetIndexFiles(fileInfo.owner, move(fd)); + } else { + ctx->UpdateBundleReceivedFiles(fileInfo.owner, fileInfo.fileName); + } + ctx->TryNotify(); +} + +static void OnBundleStarted(shared_ptr ctx, ErrCode err, const BundleName name) +{ + printf("BundleStarted errCode = %d, BundleName = %s\n", err, name.c_str()); + if (err != 0) { + ctx->isAllBundelsFinished.store(true); + ctx->UpdateBundleFinishedCount(); + ctx->TryNotify(); + } +} + +static void OnBundleFinished(shared_ptr ctx, ErrCode err, const BundleName name) +{ + printf("BundleFinished errCode = %d, BundleName = %s\n", err, name.c_str()); + ctx->UpdateBundleFinishedCount(); + ctx->TryNotify(); +} + +static void OnAllBundlesFinished(shared_ptr ctx, ErrCode err) +{ + ctx->isAllBundelsFinished.store(true); + if (err == 0) { + printf("all bundles backup finished end\n"); + } else { + printf("Failed to Unplanned Abort error: %d\n", err); + ctx->TryNotify(true); + return; + } + ctx->TryNotify(); +} + +static void OnBackupServiceDied(shared_ptr ctx) +{ + printf("backupServiceDied\n"); + ctx->TryNotify(true); +} + +static int32_t Init(const string &pathCapFile, + vector bundleNames, + const string &time, + const string &pathIncrementalFile) +{ + StartTrace(HITRACE_TAG_FILEMANAGEMENT, "InitPathCapFile"); + + if (access((BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR).data(), F_OK) != 0 && + mkdir((BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR).data(), S_IRWXU) != 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + + UniqueFd fdLocal(open(pathCapFile.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)); + if (fdLocal < 0) { + fprintf(stderr, "Failed to open file. error: %d %s\n", errno, strerror(errno)); + return -EPERM; + } + auto proxy = ServiceProxy::GetInstance(); + if (!proxy) { + fprintf(stderr, "Get an empty backup sa proxy\n"); + return -EPERM; + } + vector bundlesToBackup; + for (auto &bundleName : bundleNames) { + BIncrementalData data; + data.bundleName = bundleName; + data.lastIncrementalTime = atoi(time.c_str()); + data.manifestFd = open(pathIncrementalFile.data(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + bundlesToBackup.push_back(data); + } + int fd = proxy->GetLocalCapabilitiesIncremental(bundlesToBackup); + if (fd < 0) { + fprintf(stderr, "error GetLocalCapabilitiesIncremental"); + } else { + BFile::SendFile(fdLocal, fd); + } + + auto ctx = make_shared(); + ctx->session_ = BIncrementalBackupSession::Init(BIncrementalBackupSession::Callbacks { + .onFileReady = bind(OnFileReady, ctx, placeholders::_1, placeholders::_2, placeholders::_3), + .onBundleStarted = bind(OnBundleStarted, ctx, placeholders::_1, placeholders::_2), + .onBundleFinished = bind(OnBundleFinished, ctx, placeholders::_1, placeholders::_2), + .onAllBundlesFinished = bind(OnAllBundlesFinished, ctx, placeholders::_1), + .onBackupServiceDied = bind(OnBackupServiceDied, ctx)}); + if (ctx->session_ == nullptr) { + printf("Failed to init backup\n"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return -EPERM; + } + ctx->lastIncrementalTime = time; + int ret = ctx->session_->AppendBundles(bundlesToBackup); + if (ret != 0) { + printf("backup append bundles error: %d\n", ret); + throw BError(BError::Codes::TOOL_INVAL_ARG, "backup append bundles error"); + } + + ctx->SetBundleFinishedCount(bundleNames.size()); + ctx->Wait(); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + ctx->session_->Release(); + return 0; +} + +static int Exec(map> &mapArgToVal) +{ + if (mapArgToVal.find("pathCapFile") == mapArgToVal.end() || mapArgToVal.find("bundles") == mapArgToVal.end() || + mapArgToVal.find("incrementalTime") == mapArgToVal.end() || + mapArgToVal.find("incrementalFile") != mapArgToVal.end()) { + return -EPERM; + } + return Init(*(mapArgToVal["pathCapFile"].begin()), mapArgToVal["bundles"], + *(mapArgToVal["incrementalTime"].begin()), *(mapArgToVal["incrementalFile"].begin())); +} + +bool IncrementalBackUpRegister() +{ + return ToolsOp::Register(ToolsOp {ToolsOp::Descriptor { + .opName = {"incrementalbackup"}, + .argList = {{ + .paramName = "pathCapFile", + .repeatable = false, + }, + { + .paramName = "bundles", + .repeatable = true, + }, + { + .paramName = "incrementalTime", + .repeatable = false, + }, + { + .paramName = "incrementalFile", + .repeatable = false, + }}, + .funcGenHelpMsg = GenHelpMsg, + .funcExec = Exec, + }}); +} +} // 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 333099dbd..9f21842b5 100644 --- a/tools/backup_tool/src/tools_op_restore.cpp +++ b/tools/backup_tool/src/tools_op_restore.cpp @@ -160,8 +160,8 @@ static void OnBundleFinished(shared_ptr ctx, ErrCode err, const BundleN ctx->UpdateBundleFinishedCount(); if (err != 0) { ctx->isAllBundelsFinished.store(true); - ctx->ClearBundleOfMap(name); } + ctx->ClearBundleOfMap(name); ctx->TryNotify(); } @@ -286,6 +286,7 @@ static int32_t InitPathCapFile(const string &pathCapFile, vector bundleN ctx->SetBundleFinishedCount(bundleNames.size()); RestoreApp(ctx, bundleNames); ctx->Wait(); + ctx->session_->Release(); return 0; } diff --git a/utils/BUILD.gn b/utils/BUILD.gn index ff90af981..9bd937cbe 100644 --- a/utils/BUILD.gn +++ b/utils/BUILD.gn @@ -83,6 +83,7 @@ ohos_shared_library("backup_utils") { "src/b_error/b_excep_utils.cpp", "src/b_filesystem/b_dir.cpp", "src/b_filesystem/b_file.cpp", + "src/b_filesystem/b_file_hash.cpp", "src/b_json/b_json_entity_ext_manage.cpp", "src/b_json/b_json_entity_extension_config.cpp", "src/b_ohos/startup/backup_para.cpp", @@ -109,6 +110,7 @@ ohos_shared_library("backup_utils") { "${path_backup}/interfaces/inner_api/native/backup_kit_inner/impl", "${path_rust}/crates/cxx/include", "${target_gen_dir}/rust/src", + "//third_party/openssl/include", ] deps = [ @@ -116,8 +118,11 @@ ohos_shared_library("backup_utils") { ":backup_cxx_gen", ":backup_cxx_rust", "${path_jsoncpp}:jsoncpp", + "//third_party/openssl:libcrypto_shared", ] + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] + use_exceptions = true innerapi_tags = [ "platformsdk" ] part_name = "app_file_service" diff --git a/utils/include/b_filesystem/b_file.h b/utils/include/b_filesystem/b_file.h index 863f4ad4b..f9a0055ff 100644 --- a/utils/include/b_filesystem/b_file.h +++ b/utils/include/b_filesystem/b_file.h @@ -61,6 +61,13 @@ public: */ static bool CopyFile(const string &from, const string &to); + /** + * @brief read incremental file info + * + * @param fd UniqueFd + */ + static vector> ReadIncrementalFile(const UniqueFd &fd); + private: }; } // namespace OHOS::FileManagement::Backup diff --git a/utils/include/b_filesystem/b_file_hash.h b/utils/include/b_filesystem/b_file_hash.h new file mode 100644 index 000000000..8fff58760 --- /dev/null +++ b/utils/include/b_filesystem/b_file_hash.h @@ -0,0 +1,32 @@ +/* + * 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_FILE_HASH_H +#define OHOS_FILEMGMT_BACKUP_B_FILE_HASH_H + +#include +#include + +namespace OHOS::FileManagement::Backup { +using namespace std; +class BFileHash { +public: + static std::tuple HashWithMD5(const std::string &fpath); + static std::tuple HashWithSHA1(const std::string &fpath); + static std::tuple HashWithSHA256(const std::string &fpath); +}; +} // namespace OHOS::FileManagement::Backup + +#endif // OHOS_FILEMGMT_BACKUP_B_FILE_HASH_H \ No newline at end of file diff --git a/utils/include/b_ohos/startup/backup_para.h b/utils/include/b_ohos/startup/backup_para.h index 1f6cad364..bac2a4300 100644 --- a/utils/include/b_ohos/startup/backup_para.h +++ b/utils/include/b_ohos/startup/backup_para.h @@ -35,6 +35,20 @@ public: * @return int32_t值为配置项backup.debug.overrideAccountNumber值 */ std::tuple GetBackupDebugOverrideAccount(); + + /** + * @brief 获取backup.para配置项backup.overrideBackupSARelease的值 + * + * @return 获取的配置项backup.overrideBackupSARelease的值为true时则返回true,否则返回false + */ + bool GetBackupOverrideBackupSARelease(); + + /** + * @brief 获取backup.para配置项backup.overrideIncrementalRestore的值 + * + * @return 获取的配置项backup.overrideIncrementalRestore的值为true时则返回true,否则返回false + */ + bool GetBackupOverrideIncrementalRestore(); }; } // namespace OHOS::FileManagement::Backup diff --git a/utils/include/b_resources/b_constants.h b/utils/include/b_resources/b_constants.h index 9f4ae877b..e728239c4 100644 --- a/utils/include/b_resources/b_constants.h +++ b/utils/include/b_resources/b_constants.h @@ -62,6 +62,7 @@ constexpr int EXT_CONNECT_MAX_COUNT = 3; // extension 最大启动数 constexpr int EXT_CONNECT_MAX_TIME = 15000; // SA 启动 extension 等待连接最大时间 constexpr int IPC_MAX_WAIT_TIME = 3000; // IPC通讯最大等待时间(s) +constexpr int MAX_PARCELABLE_VECTOR_NUM = 10000; // backup.para内配置项的名称,该配置项值为true时可在不更新hap包的情况下,可以读取包管理元数据配置文件的内容 static inline std::string BACKUP_DEBUG_OVERRIDE_EXTENSION_CONFIG_KEY = "backup.debug.overrideExtensionConfig"; @@ -70,11 +71,18 @@ 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"; +// backup.para内配置项的名称,该配置项为true时备份恢复支持Release接口调用 +static inline std::string BACKUP_OVERRIDE_BACKUP_SA_RELEASE_KEY = "backup.overrideBackupSARelease"; + +// backup.para内配置项的名称,该配置项为true时备份恢复支持增量恢复 +static inline std::string BACKUP_OVERRIDE_INCREMENTAL_KEY = "backup.overrideIncrementalRestore"; + // 应用备份数据暂存路径 static inline std::string_view SA_BUNDLE_BACKUP_BACKUP = "/backup/"; static inline std::string_view SA_BUNDLE_BACKUP_RESTORE = "/restore/"; static inline std::string_view SA_BUNDLE_BACKUP_TMP_DIR = "/tmp/"; static inline std::string_view BACKUP_TOOL_RECEIVE_DIR = "/data/backup/received/"; +static inline std::string_view BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR = "/data/backup/incrementalreceived/"; static inline std::string_view PATH_BUNDLE_BACKUP_HOME_EL1 = "/data/storage/el1/backup"; static inline std::string_view PATH_BUNDLE_BACKUP_HOME = "/data/storage/el2/backup"; static inline std::string_view BACKUP_TOOL_LINK_DIR = "/data/backup"; diff --git a/utils/src/b_filesystem/b_file.cpp b/utils/src/b_filesystem/b_file.cpp index aa8c36370..d85b30ae9 100644 --- a/utils/src/b_filesystem/b_file.cpp +++ b/utils/src/b_filesystem/b_file.cpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "b_error/b_error.h" #include "filemgmt_libhilog.h" @@ -140,4 +142,58 @@ bool BFile::CopyFile(const string &from, const string &to) } return false; } + +static vector SplitString(string str, char sep) +{ + stringstream ss(str); + string line; + vector splitArr; + while (!ss.eof()) { + getline(ss, line, sep); + if (!line.empty() || sep == ';') { + splitArr.push_back(line); + } + } + return splitArr; +} + +vector> BFile::ReadIncrementalFile(const UniqueFd &fd) +{ + string content = ReadFile(fd).get(); + vector> infos; + + vector lines = SplitString(content, '\n'); + if (lines.begin() != lines.end()) { + // 对第2行的数据做切分 + vector keys = SplitString(lines[1], ';'); + int num = (int)keys.size() - 1; + + for (int i = 2; i < (int)lines.size(); i++) { + map info; + // 如果结尾有;,就删除后再切分 + string newLine = lines[i]; + if (newLine[newLine.length() - 1] == ';') { + newLine = newLine.substr(0, newLine.length() - 1); + } + + vector words = SplitString(newLine, ';'); + if (words.begin() != words.end()) { + string filePath = ""; + int len = words.size(); + for (int j = 1; j < (int)keys.size(); j++) { + int index = len - num - 1 + j; + info.try_emplace(keys[j], words[index]); + } + for (int j = 0; j < len - num; j++) { + filePath += words[j] + ";"; + } + filePath = filePath.substr(0, filePath.length() - 1); + info.try_emplace(keys[0], filePath); + + } + infos.emplace_back(info); + } + } + return infos; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/utils/src/b_filesystem/b_file_hash.cpp b/utils/src/b_filesystem/b_file_hash.cpp new file mode 100644 index 000000000..c3e162786 --- /dev/null +++ b/utils/src/b_filesystem/b_file_hash.cpp @@ -0,0 +1,105 @@ +/* + * 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_filesystem/b_file_hash.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace OHOS::FileManagement::Backup { +using namespace std; + +static tuple HashFinal(int err, const unique_ptr &hashBuf, size_t hashLen) +{ + if (err) { + return { err, "" }; + } + + stringstream ss; + for (size_t i = 0; i < hashLen; ++i) { + const int hexPerByte = 2; + ss << std::uppercase << std::setfill('0') << std::setw(hexPerByte) << std::hex << + static_cast(hashBuf[i]); + } + + return { err, ss.str() }; +} + +static int ForEachFileSegment(const string &fpath, function executor) +{ + unique_ptr filp = { fopen(fpath.c_str(), "r"), fclose }; + if (!filp) { + return errno; + } + + const size_t pageSize { getpagesize() }; + auto buf = make_unique(pageSize); + size_t actLen; + do { + actLen = fread(buf.get(), 1, pageSize, filp.get()); + if (actLen > 0) { + executor(buf.get(), actLen); + } + } while (actLen == pageSize); + + return ferror(filp.get()) ? errno : 0; +} + +tuple BFileHash::HashWithMD5(const string &fpath) +{ + auto res = make_unique(MD5_DIGEST_LENGTH); + MD5_CTX ctx; + MD5_Init(&ctx); + auto md5Update = [ctx = &ctx](char *buf, size_t len) { + MD5_Update(ctx, buf, len); + }; + int err = ForEachFileSegment(fpath, md5Update); + MD5_Final(res.get(), &ctx); + return HashFinal(err, res, MD5_DIGEST_LENGTH); +} + +tuple BFileHash::HashWithSHA1(const string &fpath) +{ + auto res = make_unique(SHA_DIGEST_LENGTH); + SHA_CTX ctx; + SHA1_Init(&ctx); + auto sha1Update = [ctx = &ctx](char *buf, size_t len) { + SHA1_Update(ctx, buf, len); + }; + int err = ForEachFileSegment(fpath, sha1Update); + SHA1_Final(res.get(), &ctx); + return HashFinal(err, res, SHA_DIGEST_LENGTH); +} + +tuple BFileHash::HashWithSHA256(const string &fpath) +{ + auto res = make_unique(SHA256_DIGEST_LENGTH); + SHA256_CTX ctx; + SHA256_Init(&ctx); + auto sha256Update = [ctx = &ctx](char *buf, size_t len) { + SHA256_Update(ctx, buf, len); + }; + int err = ForEachFileSegment(fpath, sha256Update); + SHA256_Final(res.get(), &ctx); + return HashFinal(err, res, SHA256_DIGEST_LENGTH); +} + +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/utils/src/b_ohos/startup/backup_para.cpp b/utils/src/b_ohos/startup/backup_para.cpp index 8047ef0e1..c3028632a 100644 --- a/utils/src/b_ohos/startup/backup_para.cpp +++ b/utils/src/b_ohos/startup/backup_para.cpp @@ -66,6 +66,26 @@ bool BackupPara::GetBackupDebugOverrideExtensionConfig() return value == "true"; } +bool BackupPara::GetBackupOverrideBackupSARelease() +{ + auto [getCfgParaValSucc, value] = + GetConfigParameterValue(BConstants::BACKUP_OVERRIDE_BACKUP_SA_RELEASE_KEY, BConstants::BACKUP_PARA_VALUE_MAX); + if (!getCfgParaValSucc) { + throw BError(BError::Codes::SA_INVAL_ARG, "Fail to get configuration parameter value of backup.para"); + } + return value == "true"; +} + +bool BackupPara::GetBackupOverrideIncrementalRestore() +{ + auto [getCfgParaValSucc, value] = + GetConfigParameterValue(BConstants::BACKUP_OVERRIDE_INCREMENTAL_KEY, BConstants::BACKUP_PARA_VALUE_MAX); + if (!getCfgParaValSucc) { + throw BError(BError::Codes::SA_INVAL_ARG, "Fail to get configuration parameter value of backup.para"); + } + return value == "true"; +} + tuple BackupPara::GetBackupDebugOverrideAccount() { auto [getCfgParaValSucc, value] = GetConfigParameterValue(BConstants::BACKUP_DEBUG_OVERRIDE_ACCOUNT_CONFIG_KEY, -- Gitee From 962bba47411a206a91c15f07a5705b30f1e42ab0 Mon Sep 17 00:00:00 2001 From: nieben Date: Fri, 29 Dec 2023 16:19:02 +0800 Subject: [PATCH 02/35] add restore code Signed-off-by: nieben --- .../native/backup_ext/include/ext_extension.h | 14 + .../native/backup_ext/include/untar_file.h | 19 ++ .../native/backup_ext/src/ext_extension.cpp | 321 +++++++++++++++++- .../native/backup_ext/src/untar_file.cpp | 107 ++++++ utils/include/b_json/b_report_entity.h | 193 +++++++++++ utils/include/b_resources/b_constants.h | 3 + 6 files changed, 645 insertions(+), 12 deletions(-) create mode 100644 utils/include/b_json/b_report_entity.h diff --git a/frameworks/native/backup_ext/include/ext_extension.h b/frameworks/native/backup_ext/include/ext_extension.h index 8fd2b1799..fdc74ecec 100644 --- a/frameworks/native/backup_ext/include/ext_extension.h +++ b/frameworks/native/backup_ext/include/ext_extension.h @@ -40,6 +40,7 @@ public: ErrCode HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) override; void AsyncTaskRestoreForUpgrade(void); + void AsyncTaskIncrementalRestoreForUpgrade(void); public: explicit BackupExtExtension(const std::shared_ptr &extension) : extension_(extension) @@ -72,6 +73,13 @@ private: */ int DoRestore(const string &fileName); + /** + * @brief incremental restore + * + * @param fileName name of the file that to be untar + */ + int DoIncrementalRestore(const string &fileName); + /** @brief clear backup restore data */ void DoClear(); @@ -97,6 +105,12 @@ private: */ void AsyncTaskRestore(); + /** + * @brief Executing Incremental Restoration Tasks Asynchronously + * + */ + void AsyncTaskIncrementalRestore(); + void AsyncTaskOnBackup(); /** diff --git a/frameworks/native/backup_ext/include/untar_file.h b/frameworks/native/backup_ext/include/untar_file.h index 1f92f88a2..fe0b12714 100644 --- a/frameworks/native/backup_ext/include/untar_file.h +++ b/frameworks/native/backup_ext/include/untar_file.h @@ -32,6 +32,8 @@ public: typedef enum { ERR_FORMAT = -1 } ErrorCode; static UntarFile &GetInstance(); int UnPacket(const std::string &tarFile, const std::string &rootPath); + int IncrementalUnPacket(const std::string &tarFile, const std::string &rootPath, + const std::unordered_map &includes); private: UntarFile() = default; @@ -46,6 +48,13 @@ private: */ int ParseTarFile(const std::string &rootPath); + /** + * @brief parse incremental tar file + * + * @param rootpath 解包的目标路径 + */ + int ParseIncrementalTarFile(const std::string &rootPath); + /** * @brief verfy check sum * @@ -112,6 +121,15 @@ private: */ void ParseFileByTypeFlag(char typeFlag, bool &isSkip, FileStatInfo &info); + /** + * @brief parse incremental file by typeFlag + * + * @param typeFlag 文件类型标志 + * @param isSkip 是否跳过当前文件 + * @param info 文件属性结构体 + */ + void ParseIncrementalFileByTypeFlag(char typeFlag, bool &isSkip, FileStatInfo &info); + /** * @brief Handle file ownership groups * @@ -128,6 +146,7 @@ private: off_t tarFileBlockCnt_ {0}; off_t pos_ {0}; size_t readCnt_ {0}; + std::unordered_map includes_; }; } // namespace OHOS::FileManagement::Backup diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index 52c24cf52..26a68408e 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -42,6 +42,7 @@ #include "b_filesystem/b_file_hash.h" #include "b_json/b_json_cached_entity.h" #include "b_json/b_json_entity_ext_manage.h" +#include "b_json/b_report_entity.h" #include "b_resources/b_constants.h" #include "b_tarball/b_tarball_factory.h" #include "filemgmt_libhilog.h" @@ -147,6 +148,78 @@ UniqueFd BackupExtExtension::GetFileHandle(const string &fileName) } } +static string ChangeFileExtension(const string &fileName, const string &fileExt) +{ + auto n = fileName.rfind("."); + if (n == string::npos) { + throw BError(BError::Codes::EXT_INVAL_ARG, "filename has no extension"); + } + + return string(fileName).replace(n, fileName.length()-n, "." + fileExt); +} + +static string GetReportFileName(const string &fileName) +{ + string reportName; + if (fileName.rfind(".") != string::npos) { + reportName = ChangeFileExtension(fileName, string(BConstants::REPORT_FILE_EXT)); + } else { + reportName = fileName + "." + string(BConstants::REPORT_FILE_EXT); + } + + return reportName; +} + +ErrCode BackupExtExtension::GetIncrementalFileHandle(const string &fileName) +{ + try { + if (extension_->GetExtensionAction() != BConstants::ExtensionAction::RESTORE) { + HILOGI("Failed to get file handle, because action is %{public}d invalid", extension_->GetExtensionAction()); + throw BError(BError::Codes::EXT_INVAL_ARG, "Action is invalid"); + } + + VerifyCaller(); + + string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE); + if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) { + string str = string("Failed to create restore folder. ").append(std::generic_category().message(errno)); + throw BError(BError::Codes::EXT_INVAL_ARG, str); + } + + string tarName = path + fileName; + if (fileName.find('/') != string::npos) { + HILOGD("GetFileHandle: fileName include path symbol, need to make hash."); + tarName = path + GenerateHashForFileName(fileName); + if (CheckIfTarSuffix(fileName)) { + tarName += ".tar"; + } + } + if (access(tarName.c_str(), F_OK) == 0) { + throw BError(BError::Codes::EXT_INVAL_ARG, string("The file already exists")); + } + UniqueFd fd = UniqueFd(open(tarName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); + + // 对应的简报文件 + string reportName = GetReportFileName(tarName); + if (access(reportName.c_str(), F_OK) == 0) { + throw BError(BError::Codes::EXT_INVAL_ARG, string("The report file already exists")); + } + UniqueFd reportFd = UniqueFd(open(reportName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); + + auto proxy = ServiceProxy::GetInstance(); + auto ret = proxy->AppIncrementalFileReady(fileName, move(fd), move(reportFd)); + if (ret != ERR_OK) { + HILOGI("Failed to AppIncrementalFileReady %{public}d", ret); + } + + return ERR_OK; + } catch (...) { + HILOGE("Failed to get incremental file handle"); + DoClear(); + return BError(BError::Codes::EXT_INVAL_ARG).GetCode(); + } +} + ErrCode BackupExtExtension::HandleClear() { HILOGI("begin clear"); @@ -284,6 +357,57 @@ ErrCode BackupExtExtension::PublishFile(const string &fileName) } } +ErrCode BackupExtExtension::PublishIncrementalFile(const string &fileName) +{ + HILOGE("begin publish incremental file. fileName is %{public}s", fileName.data()); + try { + if (extension_->GetExtensionAction() != BConstants::ExtensionAction::RESTORE) { + throw BError(BError::Codes::EXT_INVAL_ARG, "Action is invalid"); + } + VerifyCaller(); + + string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE); + string tarName = path + fileName; + // 带路径的文件名在这里转换为hash值 + if (fileName.find('/') != string::npos) { + HILOGD("PublishFile: fileName include path symbol, need to make hash."); + tarName = path + GenerateHashForFileName(fileName); + if (CheckIfTarSuffix(fileName)) { + tarName += ".tar"; + } + } + { + BExcepUltils::VerifyPath(tarName, true); + unique_lock lock(lock_); + if (find(tars_.begin(), tars_.end(), fileName) != tars_.end() || access(tarName.data(), F_OK) != 0) { + throw BError(BError::Codes::EXT_INVAL_ARG, "The file does not exist"); + } + tars_.push_back(fileName); + if (!IsAllFileReceived(tars_)) { + return ERR_OK; + } + } + + // 异步执行解压操作 + if (extension_->AllowToBackupRestore()) { + AsyncTaskIncrementalRestore(); + } + + return ERR_OK; + } catch (const BError &e) { + DoClear(); + return e.GetCode(); + } catch (const exception &e) { + HILOGE("Catched an unexpected low-level exception %{public}s", e.what()); + DoClear(); + return BError(BError::Codes::EXT_BROKEN_FRAMEWORK).GetCode(); + } catch (...) { + HILOGE("Unexpected exception"); + DoClear(); + return BError(BError::Codes::EXT_BROKEN_FRAMEWORK).GetCode(); + } +} + ErrCode BackupExtExtension::HandleBackup() { string usrConfig = extension_->GetUsrConfig(); @@ -435,6 +559,65 @@ int BackupExtExtension::DoRestore(const string &fileName) return ERR_OK; } +static unordered_map GetTarIncludes(const string &tarName) +{ + // 根据简报文件获取待解压的文件列表,如果简报文件内容为空,则进行全量解压,返回空 + unordered_map includes; + + // 获取简报文件内容 + string reportName = GetReportFileName(tarName); + + // 获取简报内容 + BReportEntity rp(UniqueFd(open(reportName.data(), O_RDONLY))); + vector infos = rp.GetReportFileInfos(); + for (auto iter : infos) { + includes.emplace(iter.filePath, true); + } + + return includes; +} + +int BackupExtExtension::DoIncrementalRestore(const string &fileName) +{ + HILOGI("Do incremental restore"); + if (extension_->GetExtensionAction() != BConstants::ExtensionAction::RESTORE) { + return EPERM; + } + // REM: 给定version + // REM: 解压启动Extension时即挂载好的备份目录中的数据 + string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE); + string tarName = path + fileName; + + // 带路径的恢复需要找到hash后的待解压文件 + if (fileName.find('/') != string::npos) { + HILOGD("DoIncrementalRestore: fileName include path symbol, need to make hash."); + string filePath = path + GenerateHashForFileName(fileName); + size_t pos = filePath.rfind('/'); + if (pos == string::npos) { + return EPERM; + } + string folderPath = filePath.substr(0, pos); + if (!ForceCreateDirectory(folderPath.data())) { + HILOGE("Failed to create directory"); + return EPERM; + } + tarName = filePath; + if (CheckIfTarSuffix(fileName)) { + tarName += ".tar"; + } + } + + // 当用户指定fullBackupOnly字段或指定版本的恢复,解压目录当前在/backup/restore + if (extension_->SpeicalVersionForCloneAndCloud() || extension_->UseFullBackupOnly()) { + UntarFile::GetInstance().IncrementalUnPacket(tarName, path, GetTarIncludes(tarName)); + } else { + UntarFile::GetInstance().IncrementalUnPacket(tarName, "/", GetTarIncludes(tarName)); + } + HILOGI("Application recovered successfully, package path is %{public}s", tarName.c_str()); + + return ERR_OK; +} + void BackupExtExtension::AsyncTaskBackup(const string config) { auto task = [obj {wptr(this)}, config]() { @@ -632,6 +815,36 @@ static void DeleteBackupTars() } } +static void DeleteBackupIncrementalTars() +{ + // The directory include tars and manage.json which would be deleted + BJsonCachedEntity cachedEntity(UniqueFd(open(INDEX_FILE_RESTORE.data(), O_RDONLY))); + auto cache = cachedEntity.Structuralize(); + auto info = cache.GetExtManage(); + auto path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE); + for (auto &item : info) { + if (ExtractFileExt(item) != "tar" || IsUserTar(item, INDEX_FILE_RESTORE)) { + continue; + } + string tarPath = path + item; + if (!RemoveFile(tarPath)) { + HILOGE("Failed to delete the backup tar %{public}s", tarPath.c_str()); + } + // 删除简报文件 + string reportPath = GetReportFileName(tarPath); + if (!RemoveFile(reportPath)) { + HILOGE("Failed to delete the backup report"); + } + } + if (!RemoveFile(INDEX_FILE_RESTORE)) { + HILOGE("Failed to delete the backup index %{public}s", INDEX_FILE_RESTORE.c_str()); + } + string reportManagePath = GetReportFileName(INDEX_FILE_RESTORE); // GetIncrementalFileHandle创建的空fd + if (!RemoveFile(reportManagePath)) { + HILOGE("Failed to delete the backup report index %{public}s", reportManagePath.c_str()); + } +} + void BackupExtExtension::AsyncTaskRestore() { auto task = [obj {wptr(this)}, tars {tars_}]() { @@ -685,6 +898,59 @@ void BackupExtExtension::AsyncTaskRestore() }); } +void BackupExtExtension::AsyncTaskIncrementalRestore() +{ + auto task = [obj {wptr(this)}, tars {tars_}]() { + auto ptr = obj.promote(); + BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, + "Ext extension handle have been already released"); + try { + // 解压 + int ret = ERR_OK; + for (auto item : tars) { // 处理要解压的tar文件 + if (ExtractFileExt(item) == "tar" && !IsUserTar(item, INDEX_FILE_RESTORE)) { + ret = ptr->DoIncrementalRestore(item); + } + } + // 恢复用户tar包以及大文件 + // 目的地址是否需要拼接path(临时目录),FullBackupOnly为true并且非特殊场景 + bool appendTargetPath = ptr->extension_->UseFullBackupOnly() && + !ptr->extension_->SpeicalVersionForCloneAndCloud(); + RestoreBigFiles(appendTargetPath); + + // delete 1.tar/manage.json + DeleteBackupIncrementalTars(); + + if (ret == ERR_OK) { + HILOGI("after extra, do incremental restore."); + ptr->AsyncTaskIncrementalRestoreForUpgrade(); + } else { + ptr->AppIncrementalDone(ret); + ptr->DoClear(); + } + } catch (const BError &e) { + 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()); + } + }; + + // REM: 这里异步化了,需要做并发控制 + // 在往线程池中投入任务之前将需要的数据拷贝副本到参数中,保证不发生读写竞争, + // 由于拷贝参数时尚运行在主线程中,故在参数拷贝过程中是线程安全的。 + threadPool_.AddTask([task]() { + try { + task(); + } catch (...) { + HILOGE("Failed to add task to thread pool"); + } + }); +} + void BackupExtExtension::AsyncTaskRestoreForUpgrade() { auto task = [obj {wptr(this)}]() { @@ -728,6 +994,49 @@ void BackupExtExtension::AsyncTaskRestoreForUpgrade() }); } +void BackupExtExtension::AsyncTaskIncrementalRestoreForUpgrade() +{ + auto task = [obj {wptr(this)}]() { + auto ptr = obj.promote(); + try { + BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, + "Ext extension handle have been already released"); + BExcepUltils::BAssert(ptr->extension_, BError::Codes::EXT_INVAL_ARG, + "extension handle have been already released"); + + auto callBackup = [obj]() { + HILOGI("begin call restore"); + auto extensionPtr = obj.promote(); + BExcepUltils::BAssert(extensionPtr, BError::Codes::EXT_BROKEN_FRAMEWORK, + "Ext extension handle have been already released"); + extensionPtr->AppIncrementalDone(BError(BError::Codes::OK)); + // 清空恢复目录 + extensionPtr->DoClear(); + }; + ptr->extension_->OnRestore(callBackup); + } catch (const BError &e) { + 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()); + } + }; + + // REM: 这里异步化了,需要做并发控制 + // 在往线程池中投入任务之前将需要的数据拷贝副本到参数中,保证不发生读写竞争, + // 由于拷贝参数时尚运行在主线程中,故在参数拷贝过程中是线程安全的。 + threadPool_.AddTask([task]() { + try { + task(); + } catch (...) { + HILOGE("Failed to add task to thread pool"); + } + }); +} + void BackupExtExtension::DoClear() { try { @@ -1027,18 +1336,6 @@ static ErrCode IncrementalBigFileReady(const TarMap &pkgInfo, const mapGetUsrConfig(); diff --git a/frameworks/native/backup_ext/src/untar_file.cpp b/frameworks/native/backup_ext/src/untar_file.cpp index 6e8ff73f2..1a3a6d9de 100644 --- a/frameworks/native/backup_ext/src/untar_file.cpp +++ b/frameworks/native/backup_ext/src/untar_file.cpp @@ -79,6 +79,26 @@ int UntarFile::UnPacket(const string &tarFile, const string &rootPath) return 0; } +int UntarFile::IncrementalUnPacket(const string &tarFile, const string &rootPath, + const unordered_map &includes) +{ + includes_ = includes; + tarFilePtr_ = fopen(tarFile.c_str(), "rb"); + if (tarFilePtr_ == nullptr) { + HILOGE("Failed to open tar file %{public}s, err = %{public}d", tarFile.c_str(), errno); + return errno; + } + + if (ParseIncrementalTarFile(rootPath) != 0) { + HILOGE("Failed to parse tar file"); + } + + fclose(tarFilePtr_); + tarFilePtr_ = nullptr; + + return 0; +} + void UntarFile::HandleTarBuffer(const string &buff, const string &name, FileStatInfo &info) { info.mode = static_cast(ParseOctalStr(&buff[0] + TMODE_BASE, TMODE_LEN)); @@ -147,6 +167,56 @@ int UntarFile::ParseTarFile(const string &rootPath) return ret; } +int UntarFile::ParseIncrementalTarFile(const string &rootPath) +{ + // re-parse tar header + rootPath_ = rootPath; + char buff[BLOCK_SIZE] = {0}; + bool isSkip = false; + FileStatInfo info {}; + + // tarFileSize + int ret = fseeko(tarFilePtr_, 0L, SEEK_END); + tarFileSize_ = ftello(tarFilePtr_); + // reback file to begin + ret = fseeko(tarFilePtr_, 0L, SEEK_SET); + + while (1) { + readCnt_ = fread(buff, 1, BLOCK_SIZE, tarFilePtr_); + if (readCnt_ < BLOCK_SIZE) { + HILOGE("Parsing tar file completed, read data count is less then block size."); + return 0; + } + // two empty continuous block indicate end of file + if (IsEmptyBlock(buff)) { + char tailBuff[BLOCK_SIZE] = {0}; + size_t tailRead = fread(tailBuff, 1, BLOCK_SIZE, tarFilePtr_); + if (tailRead == BLOCK_SIZE && IsEmptyBlock(tailBuff)) { + HILOGE("Parsing tar file completed, tailBuff is empty."); + return 0; + } + } + // check header + TarHeader *header = reinterpret_cast(buff); + if (!IsValidTarBlock(*header)) { + // when split unpack, ftell size is over than file really size [0,READ_BUFF_SIZE] + if (ftello(tarFilePtr_) > (tarFileSize_ + READ_BUFF_SIZE) || !IsEmptyBlock(buff)) { + HILOGE("Invalid tar file format"); + ret = ERR_FORMAT; + } + return ret; + } + HandleTarBuffer(string(buff, BLOCK_SIZE), header->name, info); + ParseIncrementalFileByTypeFlag(header->typeFlag, isSkip, info); + ret = HandleFileProperties(isSkip, info); + if (ret != 0) { + HILOGE("Failed to handle file property"); + } + } + + return ret; +} + void UntarFile::ParseFileByTypeFlag(char typeFlag, bool &isSkip, FileStatInfo &info) { switch (typeFlag) { @@ -179,6 +249,43 @@ void UntarFile::ParseFileByTypeFlag(char typeFlag, bool &isSkip, FileStatInfo &i } } +void UntarFile::ParseIncrementalFileByTypeFlag(char typeFlag, bool &isSkip, FileStatInfo &info) +{ + switch (typeFlag) { + case REGTYPE: + case AREGTYPE: + if (!includes_.empty() && includes_.find(info.fullPath) == includes_.end()) { // not in includes + isSkip = true; + fseeko(tarFilePtr_, pos_ + tarFileBlockCnt_ * BLOCK_SIZE, SEEK_SET); + break; + } + ParseRegularFile(info, typeFlag, isSkip); + break; + case SYMTYPE: + isSkip = false; + break; + case DIRTYPE: + CreateDir(info.fullPath, info.mode); + isSkip = false; + break; + case GNUTYPE_LONGNAME: { + size_t nameLen = static_cast(tarFileSize_); + if (nameLen < PATH_MAX_LEN) { + fread(&(info.longName[0]), sizeof(char), nameLen, tarFilePtr_); + } + isSkip = true; + fseeko(tarFilePtr_, pos_ + tarFileBlockCnt_ * BLOCK_SIZE, SEEK_SET); + break; + } + default: { + // Ignoring, skip + isSkip = true; + fseeko(tarFilePtr_, tarFileBlockCnt_ * BLOCK_SIZE, SEEK_CUR); + break; + } + } +} + void UntarFile::ParseRegularFile(FileStatInfo &info, char typeFlag, bool &isSkip) { FILE *destFile = CreateFile(info.fullPath, info.mode, typeFlag); diff --git a/utils/include/b_json/b_report_entity.h b/utils/include/b_json/b_report_entity.h new file mode 100644 index 000000000..83fad2433 --- /dev/null +++ b/utils/include/b_json/b_report_entity.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2022-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_REPORT_ENTITY_H +#define OHOS_FILEMGMT_BACKUP_B_REPORT_ENTITY_H + +#include +#include + +namespace OHOS::FileManagement::Backup { +struct ReportFileInfo { + string filePath {""}; + mode_t mode {0}; + bool isDir {false}; + off_t size {0}; + off_t mtime {0}; + string hash {""}; +}; +enum ReportFileInfoAttr {FILE_PATH, MODE, IS_DIR, SIZE, MTIME, HASH}; +class BReportEntity { +public: + ErrCode ParseReportFileInfo(ReportFileInfo &info, const std::vector &attrs) + { + try { + if (attrs[FILE_PATH].empty()) { + HILOGE("Invalid filePath:%{public}s", attrs[FILE_PATH].c_str()); + return EPERM; + } + info.filePath = attrs[FILE_PATH]; + + if (!attrs[MODE].empty()) { + info.mode = static_cast(atoi(attrs[MODE].c_str())); + } + + if (attrs[IS_DIR].empty()) { + HILOGE("Invalid isDir:%{public}s", attrs[IS_DIR].c_str()); + return EPERM; + } + info.isDir = atoi(attrs[IS_DIR].c_str()) == 1 ? true : false; + + if (!attrs[SIZE].empty()) { + info.size = static_cast(atol(attrs[SIZE].c_str())); + } + + if (!attrs[MTIME].empty()) { + info.mtime = static_cast(atol(attrs[MTIME].c_str())); + } + + info.hash = attrs[HASH]; + + return ERR_OK; + } catch (...) { + HILOGE("Failed to ParseReportFileInfo"); + return EPERM; + } + } + + std::vector SplitStringByChar(const std::string &str, const char &sep) + { + std::vector eles = {}; + std::stringstream ss = std::stringstream(str); + std::string ele = {}; + while (!ss.eof()) { + getline(ss, ele, sep); + eles.push_back(ele); + } + + return eles; + } + + ErrCode ParseInfoLine(const std::string &line) + { + try { + std::stringstream lineStream = std::stringstream(line); + std::stringstream infoStream; + std::string info = {}; + std::string key = {}; + std::vector keys = {}; + while (!lineStream.eof()) { + getline(lineStream, info, infoSep_); + keys.clear(); + keys = SplitStringByChar(info, infoAlign_); + if (keys.size() != INFO_ALIGN_NUM_) { + HILOGE("Failed to Parse info:%{public}s", info.c_str()); + continue; + } + if (keys[0] == VERSION_TAG_) { + version = keys[1]; + } else if (keys[0] == ATTR_NUM_TAG_) { + attrNum = atoi(keys[1].c_str()); + } else { + HILOGE("invalid info:%{public}s", info.c_str()); + } + } + + return ERR_OK; + } catch (...) { + HILOGE("Failed to ParseInfoLine"); + return EPERM; + } + } + + /** + * @brief 获取Report信息 + * + * @return std::vector + */ + std::vector GetReportFileInfos() + { + std::vector infos {}; + + std::unique_ptr rawBuf = BFile::ReadFile(srcFile_); + std::stringstream fileStream(rawBuf.get()); + std::string line; + std::stringstream lineStream; + std::string attr = {}; + std::vector attrs; + bool infoLine = false; + bool attrLine = false; + while (!fileStream.eof()) { + getline(fileStream, line, lineSep_); + + if (!line.empty()) { + if (!infoLine) { + infoLine = true; + ParseInfoLine(line); + continue; + } + if (!attrLine) { + attrLine = true; + continue; + } + + attrs.clear(); + attrs = SplitStringByChar(line, attrSep_); + if (attrs.size() != attrNum) { + HILOGE("Invalid line:%{public}s", line.c_str()); + continue; + } + ReportFileInfo info = {}; + auto code = ParseReportFileInfo(info, attrs); + if (code != ERR_OK) { + HILOGE("ParseReportFileInfo err:%{public}d %{public}s", code, line.c_str()); + continue; + } else { + infos.emplace_back(info); + } + } + } + + return infos; + } + +public: + /** + * @brief 构造方法 + * + * @param fd + */ + explicit BReportEntity(UniqueFd fd) : srcFile_(std::move(fd)) {} + + BReportEntity() = delete; + virtual ~BReportEntity() = default; + +public: + string version = ""; + unsigned int attrNum = 0; + +protected: + UniqueFd srcFile_; + const char lineSep_ = '\n'; + const char attrSep_ = ';'; + const char infoSep_ = '&'; + const char infoAlign_ = '='; + const unsigned int INFO_ALIGN_NUM_ = 2; + const string VERSION_TAG_ = "version"; + const string ATTR_NUM_TAG_ = "attrNum"; +}; +} // namespace OHOS::FileManagement::Backup + +#endif // OHOS_FILEMGMT_BACKUP_B_REPORT_ENTITY_H \ No newline at end of file diff --git a/utils/include/b_resources/b_constants.h b/utils/include/b_resources/b_constants.h index e728239c4..9a1296092 100644 --- a/utils/include/b_resources/b_constants.h +++ b/utils/include/b_resources/b_constants.h @@ -124,6 +124,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 REPORT_FILE_EXT = "rp"; + // 特殊版本信息 constexpr int DEFAULT_VERSION_CODE = 0; static inline std::string_view DEFAULT_VERSION_NAME = "0.0.0.0"; -- Gitee From ac4b2c61e2475e9679c340b1a835c6a6d706836c Mon Sep 17 00:00:00 2001 From: zhangkaixiang Date: Fri, 29 Dec 2023 18:04:19 +0800 Subject: [PATCH 03/35] add get local cap Signed-off-by: zhangkaixiang --- .../include/module_external/bms_adapter.h | 12 +++ .../include/module_external/sms_adapter.h | 16 ++- .../src/module_external/bms_adapter.cpp | 102 +++++++++++++++++- .../src/module_external/sms_adapter.cpp | 11 ++ utils/include/b_resources/b_constants.h | 9 ++ 5 files changed, 147 insertions(+), 3 deletions(-) diff --git a/services/backup_sa/include/module_external/bms_adapter.h b/services/backup_sa/include/module_external/bms_adapter.h index 7af9bedff..7297a5fe6 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 5dd16545b..d1aa7ff20 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 fbc7e4526..9ed603326 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 e6613ed2c..679842ee7 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 e728239c4..7b7ccea4f 100644 --- a/utils/include/b_resources/b_constants.h +++ b/utils/include/b_resources/b_constants.h @@ -71,6 +71,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"; + // backup.para内配置项的名称,该配置项为true时备份恢复支持Release接口调用 static inline std::string BACKUP_OVERRIDE_BACKUP_SA_RELEASE_KEY = "backup.overrideBackupSARelease"; -- Gitee From 3b99ebb0cd9812bd0f2182f96c050ff5c737ee5e Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Fri, 29 Dec 2023 19:21:43 +0800 Subject: [PATCH 04/35] =?UTF-8?q?=E6=96=B0=E5=A2=9Ebackup=5Ftool=20?= =?UTF-8?q?=E5=A2=9E=E9=87=8F=E9=AA=8C=E8=AF=81=E6=81=A2=E5=A4=8D=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- tools/backup_tool/BUILD.gn | 1 + .../include/tools_op_incremental_restore.h | 24 ++ tools/backup_tool/src/main.cpp | 2 + .../src/tools_op_incremental_backup.cpp | 86 ++++- .../src/tools_op_incremental_restore.cpp | 350 ++++++++++++++++++ utils/include/b_resources/b_constants.h | 4 +- 6 files changed, 449 insertions(+), 18 deletions(-) create mode 100644 tools/backup_tool/include/tools_op_incremental_restore.h create mode 100644 tools/backup_tool/src/tools_op_incremental_restore.cpp diff --git a/tools/backup_tool/BUILD.gn b/tools/backup_tool/BUILD.gn index 83db49e08..edf619c79 100644 --- a/tools/backup_tool/BUILD.gn +++ b/tools/backup_tool/BUILD.gn @@ -40,6 +40,7 @@ ohos_executable("backup_tool") { "src/tools_op_check_sa.cpp", "src/tools_op_help.cpp", "src/tools_op_incremental_backup.cpp", + "src/tools_op_incremental_restore.cpp", "src/tools_op_restore.cpp", "src/tools_op_restore_async.cpp", ] diff --git a/tools/backup_tool/include/tools_op_incremental_restore.h b/tools/backup_tool/include/tools_op_incremental_restore.h new file mode 100644 index 000000000..7cc4bcd0a --- /dev/null +++ b/tools/backup_tool/include/tools_op_incremental_restore.h @@ -0,0 +1,24 @@ +/* + * 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_TOOLS_OP_INCREMENTAL_RESTORE_H +#define OHOS_FILEMGMT_BACKUP_TOOLS_OP_INCREMENTAL_RESTORE_H + +namespace OHOS::FileManagement::Backup { + bool IncrementalRestoreRegister(); + +} // namespace OHOS::FileManagement::Backup + +#endif // OHOS_FILEMGMT_BACKUP_TOOLS_OP_INCREMENTAL_RESTORE_H \ No newline at end of file diff --git a/tools/backup_tool/src/main.cpp b/tools/backup_tool/src/main.cpp index d1cef740c..278999739 100644 --- a/tools/backup_tool/src/main.cpp +++ b/tools/backup_tool/src/main.cpp @@ -28,6 +28,7 @@ int main() #include "tools_op_restore.h" #include "tools_op_restore_async.h" #include "tools_op_incremental_backup.h" +#include "tools_op_incremental_restore.h" #include #include @@ -85,6 +86,7 @@ void ToolRegister() OHOS::FileManagement::Backup::RestoreRegister(); OHOS::FileManagement::Backup::RestoreAsyncRegister(); OHOS::FileManagement::Backup::IncrementalBackUpRegister(); + OHOS::FileManagement::Backup::IncrementalRestoreRegister(); } int ParseOpAndExecute(const int argc, char *const argv[]) diff --git a/tools/backup_tool/src/tools_op_incremental_backup.cpp b/tools/backup_tool/src/tools_op_incremental_backup.cpp index d776b8bbd..6721bfa7d 100644 --- a/tools/backup_tool/src/tools_op_incremental_backup.cpp +++ b/tools/backup_tool/src/tools_op_incremental_backup.cpp @@ -139,7 +139,8 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq if (access(tmpPath.data(), F_OK) != 0 && mkdir(tmpPath.data(), S_IRWXU) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } - string tmpDataPath = tmpPath + "/incremental"; + // 数据文件保存 路径拼接方式: /data/backup/incrementalreceived/bundleName/时间戳/incremental/文件名 + string tmpDataPath = tmpPath + string(BConstants::BACKUP_TOOL_INCREMENTAL); if (access(tmpDataPath.data(), F_OK) != 0 && mkdir(tmpDataPath.data(), S_IRWXU) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } @@ -149,18 +150,23 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq } BFile::SendFile(fdLocal, fd); - // 简报文件保存 - string tmpmanifestPath = tmpPath + "/manifest"; + // 简报文件保存 路径拼接方式: /data/backup/incrementalreceived/bundleName/时间戳/manifest/文件名.rp + string tmpmanifestPath = tmpPath + string(BConstants::BACKUP_TOOL_MANIFEST); if (access(tmpDataPath.data(), F_OK) != 0 && mkdir(tmpDataPath.data(), S_IRWXU) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } UniqueFd fdManifest( - open((tmpmanifestPath + "/" + fileInfo.fileName + "_manifest").data(), O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU)); + open((tmpmanifestPath + "/" + fileInfo.fileName + ".rp").data(), O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU)); if (fdManifest < 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } BFile::SendFile(fdManifest, fd); if (fileInfo.fileName == BConstants::EXT_BACKUP_MANAGE) { + UniqueFd fullDatFd(open((string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + fileInfo.owner + + string(BConstants::BACKUP_TOOL_MANIFEST).append(".rp")) + .data(), + O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU)); + BFile::SendFile(fullDatFd, fdManifest); ctx->SetIndexFiles(fileInfo.owner, move(fd)); } else { ctx->UpdateBundleReceivedFiles(fileInfo.owner, fileInfo.fileName); @@ -204,18 +210,45 @@ static void OnBackupServiceDied(shared_ptr ctx) ctx->TryNotify(true); } -static int32_t Init(const string &pathCapFile, - vector bundleNames, - const string &time, - const string &pathIncrementalFile) +static void BackupToolDirSoftlinkToBackupDir() { - StartTrace(HITRACE_TAG_FILEMANAGEMENT, "InitPathCapFile"); + // 判断BConstants::BACKUP_TOOL_LINK_DIR 是否是软链接 + if (access(BConstants::BACKUP_TOOL_LINK_DIR.data(), F_OK) == 0) { + struct stat inStat = {}; + if (lstat(BConstants::BACKUP_TOOL_LINK_DIR.data(), &inStat) == -1) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + + if ((inStat.st_mode & S_IFMT) == S_IFLNK) { + return; + } + // 非软连接删除重新创建 + if (!ForceRemoveDirectory(BConstants::BACKUP_TOOL_LINK_DIR.data())) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + } + + if (access(BConstants::GetSaBundleBackupToolDir(BConstants::DEFAULT_USER_ID).data(), F_OK) != 0 && + mkdir(BConstants::GetSaBundleBackupToolDir(BConstants::DEFAULT_USER_ID).data(), S_IRWXU) != 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + if (symlink(BConstants::GetSaBundleBackupToolDir(BConstants::DEFAULT_USER_ID).data(), + BConstants::BACKUP_TOOL_LINK_DIR.data()) == -1) { + HILOGE("failed to create soft link file %{public}s errno : %{public}d", + BConstants::BACKUP_TOOL_LINK_DIR.data(), errno); + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } if (access((BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR).data(), F_OK) != 0 && mkdir((BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR).data(), S_IRWXU) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } +} +static int GetLocalCapabilitiesIncremental(const string &pathCapFile, + const vector &bundleNames, + const string &time) +{ UniqueFd fdLocal(open(pathCapFile.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)); if (fdLocal < 0) { fprintf(stderr, "Failed to open file. error: %d %s\n", errno, strerror(errno)); @@ -231,7 +264,6 @@ static int32_t Init(const string &pathCapFile, BIncrementalData data; data.bundleName = bundleName; data.lastIncrementalTime = atoi(time.c_str()); - data.manifestFd = open(pathIncrementalFile.data(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); bundlesToBackup.push_back(data); } int fd = proxy->GetLocalCapabilitiesIncremental(bundlesToBackup); @@ -240,6 +272,18 @@ static int32_t Init(const string &pathCapFile, } else { BFile::SendFile(fdLocal, fd); } + return 0; +} + +static int32_t Init(const string &pathCapFile, vector bundleNames, const string &time) +{ + StartTrace(HITRACE_TAG_FILEMANAGEMENT, "InitPathCapFile"); + // SELinux backup_tool工具/data/文件夹下创建文件夹 SA服务因root用户的自定义标签无写入权限 此处调整为软链接形式 + BackupToolDirSoftlinkToBackupDir(); + + if (int ret = GetLocalCapabilitiesIncremental(pathCapFile, bundleNames, time); ret != 0) { + return ret; + } auto ctx = make_shared(); ctx->session_ = BIncrementalBackupSession::Init(BIncrementalBackupSession::Callbacks { @@ -254,6 +298,19 @@ static int32_t Init(const string &pathCapFile, return -EPERM; } ctx->lastIncrementalTime = time; + vector bundlesToBackup; + for (auto &bundleName : bundleNames) { + BIncrementalData data; + data.bundleName = bundleName; + data.lastIncrementalTime = atoi(time.c_str()); + string tmpPath = string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + bundleName; + if (access(tmpPath.data(), F_OK) != 0 && mkdir(tmpPath.data(), S_IRWXU) != 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + tmpPath = tmpPath + string(BConstants::BACKUP_TOOL_MANIFEST).append(".rp"); + data.manifestFd = open(tmpPath.data(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + bundlesToBackup.push_back(data); + } int ret = ctx->session_->AppendBundles(bundlesToBackup); if (ret != 0) { printf("backup append bundles error: %d\n", ret); @@ -270,12 +327,11 @@ static int32_t Init(const string &pathCapFile, static int Exec(map> &mapArgToVal) { if (mapArgToVal.find("pathCapFile") == mapArgToVal.end() || mapArgToVal.find("bundles") == mapArgToVal.end() || - mapArgToVal.find("incrementalTime") == mapArgToVal.end() || - mapArgToVal.find("incrementalFile") != mapArgToVal.end()) { + mapArgToVal.find("incrementalTime") == mapArgToVal.end()) { return -EPERM; } return Init(*(mapArgToVal["pathCapFile"].begin()), mapArgToVal["bundles"], - *(mapArgToVal["incrementalTime"].begin()), *(mapArgToVal["incrementalFile"].begin())); + *(mapArgToVal["incrementalTime"].begin())); } bool IncrementalBackUpRegister() @@ -293,10 +349,6 @@ bool IncrementalBackUpRegister() { .paramName = "incrementalTime", .repeatable = false, - }, - { - .paramName = "incrementalFile", - .repeatable = false, }}, .funcGenHelpMsg = GenHelpMsg, .funcExec = Exec, diff --git a/tools/backup_tool/src/tools_op_incremental_restore.cpp b/tools/backup_tool/src/tools_op_incremental_restore.cpp new file mode 100644 index 000000000..1970e9d5a --- /dev/null +++ b/tools/backup_tool/src/tools_op_incremental_restore.cpp @@ -0,0 +1,350 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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" +#include "base/hiviewdfx/hitrace/interfaces/native/innerkits/include/hitrace_meter/hitrace_meter.h" +#include "errors.h" +#include "service_proxy.h" +#include "tools_op.h" +#include "tools_op_restore.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; + +class Session { +public: + void UpdateBundleSendFiles(const BundleName &bundleName, const string &fileName) + { + lock_guard lk(lock_); + bundleStatusMap_[bundleName].sendFile.insert(fileName); + } + + void ClearBundleOfMap(const BundleName &bundleName) + { + lock_guard lk(lock_); + bundleStatusMap_.erase(bundleName); + } + + void TryNotify(bool flag = false) + { + if (flag == true) { + ready_ = true; + cv_.notify_all(); + } else if (bundleStatusMap_.size() == 0 && cnt_ == 0 && isAllBundelsFinished.load()) { + ready_ = true; + cv_.notify_all(); + } + } + + void UpdateBundleFinishedCount() + { + lock_guard lk(lock_); + cnt_--; + } + + void SetBundleFinishedCount(uint32_t cnt) + { + cnt_ = cnt; + } + + void Wait() + { + unique_lock lk(lock_); + cv_.wait(lk, [&] { return ready_; }); + } + + unique_ptr session_ = {}; + +private: + struct BundleStatus { + set sendFile; + set sentFile; + }; + + void TryClearBundleOfMap(const BundleName &bundleName) + { + if (bundleStatusMap_[bundleName].sendFile == bundleStatusMap_[bundleName].sentFile) { + bundleStatusMap_.erase(bundleName); + } + } + + map bundleStatusMap_; + mutable condition_variable cv_; + mutex lock_; + bool ready_ = false; + uint32_t cnt_ {0}; + +public: + std::atomic isAllBundelsFinished {false}; + string lastIncrementalTime; +}; + +static string GenHelpMsg() +{ + return "\t\tThis operation helps to restore application data.\n" + "\t\t--pathCapFile\t\t This parameter should be the path of the capability file.\n" + "\t\t--bundle\t\t This parameter is bundleName."; +} + +static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, UniqueFd fd, UniqueFd manifestFd) +{ + printf("FileReady owner = %s, fileName = %s, sn = %u, fd = %d\n", fileInfo.owner.c_str(), fileInfo.fileName.c_str(), + fileInfo.sn, fd.Get()); + if (fileInfo.fileName.find('/') != string::npos) { + throw BError(BError::Codes::TOOL_INVAL_ARG, "Filename is not valid"); + } + // 待恢复文件 路径拼接方式: /data/backup/incrementalreceived/bundleName/时间戳/incremental/文件名 + string tmpPath = string(BConstants::BACKUP_TOOL_RECEIVE_DIR) + fileInfo.owner + "/" + ctx->lastIncrementalTime + + string(BConstants::BACKUP_TOOL_INCREMENTAL) + "/" + fileInfo.fileName; + if (access(tmpPath.data(), F_OK) != 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + UniqueFd fdLocal(open(tmpPath.data(), O_RDONLY)); + if (fdLocal < 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + BFile::SendFile(fd, fdLocal); + // manifest文件 路径拼接方式: /data/backup/incrementalreceived/bundleName/时间戳/manifest/文件名.rp + tmpPath = string(BConstants::BACKUP_TOOL_RECEIVE_DIR) + fileInfo.owner + "/" + ctx->lastIncrementalTime + + string(BConstants::BACKUP_TOOL_MANIFEST) + "/" + fileInfo.fileName + ".rp"; + if (access(tmpPath.data(), F_OK) != 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + UniqueFd fdManifest(open(tmpPath.data(), O_RDONLY)); + if (fdManifest < 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + BFile::SendFile(manifestFd, fdManifest); + // 文件准备完成 + int ret = ctx->session_->PublishFile(fileInfo); + if (ret != 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, "PublishFile error"); + } + ctx->TryNotify(); +} + +static void OnBundleStarted(shared_ptr ctx, ErrCode err, const BundleName name) +{ + printf("BundleStarted errCode = %d, BundleName = %s\n", err, name.c_str()); + if (err != 0) { + ctx->UpdateBundleFinishedCount(); + ctx->isAllBundelsFinished.store(true); + ctx->ClearBundleOfMap(name); + ctx->TryNotify(); + } +} + +static void OnBundleFinished(shared_ptr ctx, ErrCode err, const BundleName name) +{ + printf("BundleFinished errCode = %d, BundleName = %s\n", err, name.c_str()); + ctx->UpdateBundleFinishedCount(); + if (err != 0) { + ctx->isAllBundelsFinished.store(true); + } + ctx->ClearBundleOfMap(name); + ctx->TryNotify(); +} + +static void OnAllBundlesFinished(shared_ptr ctx, ErrCode err) +{ + ctx->isAllBundelsFinished.store(true); + if (err == 0) { + printf("all bundles restore finished end\n"); + } else { + printf("Failed to Unplanned Abort error: %d\n", err); + ctx->TryNotify(true); + return; + } + ctx->TryNotify(); +} + +static void OnBackupServiceDied(shared_ptr ctx) +{ + printf("backupServiceDied\n"); + ctx->TryNotify(true); +} + +static void RestoreApp(shared_ptr restore, vector &bundleNames) +{ + StartTrace(HITRACE_TAG_FILEMANAGEMENT, "RestoreApp"); + if (!restore || !restore->session_) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + for (auto &bundleName : bundleNames) { + if (bundleName.find('/') != string::npos) { + throw BError(BError::Codes::TOOL_INVAL_ARG, "Filename is not valid"); + } + string path = string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + bundleName + "/" + + restore->lastIncrementalTime + string(BConstants::BACKUP_TOOL_INCREMENTAL); + if (access(path.data(), F_OK) != 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + const auto [err, filePaths] = BDir::GetDirFiles(path); + if (err != 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, "error path"); + } + for (auto &filePath : filePaths) { + string fileName = filePath.substr(filePath.rfind("/") + 1); + restore->session_->GetFileHandle(bundleName, fileName); + restore->UpdateBundleSendFiles(bundleName, fileName); + } + } + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); +} + +static bool GetRealPath(string &path) +{ + unique_ptr absPath = make_unique(PATH_MAX + 1); + if (realpath(path.c_str(), absPath.get()) == nullptr) { + return false; + } + + path = absPath.get(); + if (access(path.data(), F_OK) != 0) { + return false; + } + + return true; +} + +static int32_t InitRestoreSession(shared_ptr ctx) +{ + if (!ctx) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + ctx->session_ = BIncrementalRestoreSession::Init(BIncrementalRestoreSession::Callbacks { + .onFileReady = bind(OnFileReady, ctx, placeholders::_1, placeholders::_2, placeholders::_3), + .onBundleStarted = bind(OnBundleStarted, ctx, placeholders::_1, placeholders::_2), + .onBundleFinished = bind(OnBundleFinished, ctx, placeholders::_1, placeholders::_2), + .onAllBundlesFinished = bind(OnAllBundlesFinished, ctx, placeholders::_1), + .onBackupServiceDied = bind(OnBackupServiceDied, ctx)}); + if (ctx->session_ == nullptr) { + printf("Failed to init restore\n"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return -EPERM; + } + return 0; +} + +static int32_t Init(const string &pathCapFile, vector bundleNames, bool depMode, const string &time) +{ + StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Init"); + string realPath = pathCapFile; + if (!GetRealPath(realPath)) { + fprintf(stderr, "path to realpath error"); + return -errno; + } + + UniqueFd fd(open(realPath.data(), O_RDWR, S_IRWXU)); + auto ctx = make_shared(); + int32_t ret = InitRestoreSession(ctx); + if (ret != 0) { + printf("Failed to init restore session error:%d\n", ret); + return ret; + } + + if (depMode) { + for (auto &bundleName : bundleNames) { + UniqueFd fileFd(open(realPath.data(), O_RDWR, S_IRWXU)); + if (fileFd < 0) { + fprintf(stderr, "Failed to open file error: %d %s\n", errno, strerror(errno)); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return -errno; + } + int result = ctx->session_->AppendBundles(move(fileFd), {bundleName}); + if (result != 0) { + printf("restore append bundles error: %d\n", result); + return -result; + } + } + } else { + ret = ctx->session_->AppendBundles(move(fd), bundleNames); + if (ret != 0) { + printf("restore append bundles error: %d\n", ret); + return -ret; + } + } + ctx->lastIncrementalTime = time; + ctx->SetBundleFinishedCount(bundleNames.size()); + RestoreApp(ctx, bundleNames); + ctx->Wait(); + ctx->session_->Release(); + return 0; +} + +static int Exec(map> &mapArgToVal) +{ + bool depMode = false; + if (mapArgToVal.find("depMode") != mapArgToVal.end()) { + string strFlag = *(mapArgToVal["depMode"].begin()); + depMode = (strFlag == "true"); + } + + if (mapArgToVal.find("pathCapFile") == mapArgToVal.end() || mapArgToVal.find("bundles") == mapArgToVal.end() || + mapArgToVal.find("incrementalTime") == mapArgToVal.end()) { + return -EPERM; + } + return Init(*(mapArgToVal["pathCapFile"].begin()), mapArgToVal["bundles"], depMode, + *(mapArgToVal["incrementalTime"].begin())); +} + +bool IncrementalRestoreRegister() +{ + return ToolsOp::Register(ToolsOp {ToolsOp::Descriptor { + .opName = {"incrementalrestore"}, + .argList = {{ + .paramName = "pathCapFile", + .repeatable = false, + }, + { + .paramName = "bundles", + .repeatable = true, + }, + { + .paramName = "depMode", + .repeatable = false, + }, + { + .paramName = "incrementalTime", + .repeatable = false, + }}, + .funcGenHelpMsg = GenHelpMsg, + .funcExec = Exec, + }}); +} +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/utils/include/b_resources/b_constants.h b/utils/include/b_resources/b_constants.h index 26406efa0..48c9a0bc2 100644 --- a/utils/include/b_resources/b_constants.h +++ b/utils/include/b_resources/b_constants.h @@ -91,10 +91,12 @@ static inline std::string_view SA_BUNDLE_BACKUP_BACKUP = "/backup/"; static inline std::string_view SA_BUNDLE_BACKUP_RESTORE = "/restore/"; static inline std::string_view SA_BUNDLE_BACKUP_TMP_DIR = "/tmp/"; static inline std::string_view BACKUP_TOOL_RECEIVE_DIR = "/data/backup/received/"; -static inline std::string_view BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR = "/data/backup/incrementalreceived/"; static inline std::string_view PATH_BUNDLE_BACKUP_HOME_EL1 = "/data/storage/el1/backup"; static inline std::string_view PATH_BUNDLE_BACKUP_HOME = "/data/storage/el2/backup"; static inline std::string_view BACKUP_TOOL_LINK_DIR = "/data/backup"; +static inline std::string_view BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR = "/data/backup/incrementalreceived/"; +static inline std::string_view BACKUP_TOOL_MANIFEST = "/manifest"; +static inline std::string_view BACKUP_TOOL_INCREMENTAL = "/incremental"; // 多用户场景应用备份数据路径 static inline std::string GetSaBundleBackupDir(int32_t userId) -- Gitee From 13fce2e0237eb500076b012c365117b33c0efbd9 Mon Sep 17 00:00:00 2001 From: z30054037 Date: Sat, 30 Dec 2023 10:34:05 +0800 Subject: [PATCH 05/35] =?UTF-8?q?=E5=A2=9E=E9=87=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: z30054037 --- .../native/backup_ext/src/ext_extension.cpp | 114 ++++++------------ utils/include/b_json/b_report_entity.h | 111 ++++++++++++++++- 2 files changed, 146 insertions(+), 79 deletions(-) diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index 26a68408e..36d3178fa 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -62,15 +62,6 @@ const string INDEX_FILE_RESTORE = string(BConstants::PATH_BUNDLE_BACKUP_HOME). const string INDEX_FILE_INCREMENTAL_BACKUP = string(BConstants::PATH_BUNDLE_BACKUP_HOME). append(BConstants::SA_BUNDLE_BACKUP_BACKUP); using namespace std; -struct FileInfo { - string filePath; - string mode; - string isDir; - int64_t size; - string lmtime; - string fileHash; - string isIncr = "0"; // 是否增量 -}; namespace { const int64_t DEFAULT_SLICE_SIZE = 100 * 1024 * 1024; // 分片文件大小为100M @@ -1136,63 +1127,34 @@ ErrCode BackupExtExtension::HandleRestore() return 0; } -static map GetIncrementalFile(const UniqueFd &fd) +static tuple, map, map, + map> CompareFiles(const UniqueFd &cloudFd, const UniqueFd &storageFd) { - vector> infos = BFile::ReadIncrementalFile(fd); - map files; - if (infos.begin() != infos.end()) { - for (auto info : infos) { - string filePath = info.find("path") != info.end() ? info.find("path")->second : ""; - string mode = info.find("mode") != info.end() ? info.find("mode")->second : ""; - string dir = info.find("dir") != info.end() ? info.find("dir")->second : "0"; - int64_t size = 0; - try { - size = info.find("size") != info.end() ? stoll(info.find("size")->second) : 0; - } catch (const std::out_of_range &e) { - size = 0; - } - string mtime = info.find("mtime") != info.end() ? info.find("mtime")->second : "0"; - string isIncr = info.find("isIncr") != info.end() ? info.find("isIncr")->second : "0"; - string hash = info.find("hash") != info.end() ? info.find("hash")->second : ""; - struct FileInfo file; - file.filePath = filePath; - file.mode = mode; - file.isDir = dir; - file.lmtime = mtime; - file.size = size; - file.fileHash = hash; - file.isIncr = isIncr; - files.try_emplace(filePath, file); - } - } - return files; -} + BReportEntity cloudRp(UniqueFd(cloudFd.Get())); + map cloudFiles = cloudRp.GetReportInfos(); -static tuple, map, map, - map> CompareFiles(const UniqueFd &cloudFd, const UniqueFd &storageFd) -{ - map cloudFiles = GetIncrementalFile(cloudFd); - map storageFiles = GetIncrementalFile(storageFd); - map allFiles = {}; - map smallFiles = {}; + BReportEntity storageRp(UniqueFd(storageFd.Get())); + map storageFiles = storageRp.GetReportInfos(); + map allFiles = {}; + map smallFiles = {}; map bigFiles = {}; - map bigInfos = {}; + map bigInfos = {}; for (auto &item : storageFiles) { // 进行文件对比 string path = item.first; - if (cloudFiles.find(path) == cloudFiles.end() || (item.second.isIncr == "1" - && (cloudFiles[path].size != item.second.size || cloudFiles[path].lmtime != item.second.lmtime))) { + if (cloudFiles.find(path) == cloudFiles.end() || (item.second.isIncremental == true + && (cloudFiles[path].size != item.second.size || cloudFiles[path].mtime != item.second.mtime))) { auto [res, fileHash] = BFileHash::HashWithSHA256(path); if (fileHash.empty()) { continue; } - item.second.fileHash = fileHash; - item.second.isIncr = "1"; + item.second.hash = fileHash; + item.second.isIncremental = true; } else { - item.second.fileHash = cloudFiles[path].fileHash; + item.second.hash = cloudFiles[path].hash; } if (cloudFiles.find(path) == cloudFiles.end() || - (item.second.isIncr == "1" && cloudFiles.find(path)->second.fileHash != item.second.fileHash)) { + (item.second.isIncremental == true && cloudFiles.find(path)->second.hash != item.second.hash)) { // 在云空间简报里不存在或者hash不一致 // 区分大小文件 struct stat sta = {}; @@ -1216,7 +1178,7 @@ static tuple, map, map &srcFiles) +static void WriteFile(const string &filename, const map &srcFiles) { fstream f; f.open(filename.data(), ios::out); @@ -1224,9 +1186,9 @@ static void WriteFile(const string &filename, const map f << "version=1.0&attrNum=6" << endl; f << "path;mode;dir;size;mtime;hash" << endl; for (auto item : srcFiles) { - struct FileInfo info = item.second; - string str = item.first + ";" + info.mode + ";" + info.isDir + ";" + to_string(info.size); - str += ";" + info.lmtime + ";" + info.fileHash + ";"; + struct ReportFileInfo info = item.second; + string str = item.first + ";" + info.mode + ";" + to_string(info.isDir) + ";" + to_string(info.size); + str += ";" + to_string(info.mtime) + ";" + info.hash; f << str << endl; } f.close(); @@ -1269,16 +1231,13 @@ static TarMap GetIncrmentBigInfos(const map &files) /** * 增量tar包和简报信息回传 */ -static ErrCode IncrementalTarFileReady(const TarMap &bigFileInfo, const map &srcFiles, sptr proxy) +static ErrCode IncrementalTarFileReady(const TarMap &bigFileInfo, const map &srcFiles, + sptr proxy) { string tarFile = bigFileInfo.begin()->first; - string manageFile = ""; - if (tarFile.rfind(".tar") != string::npos) { - manageFile = tarFile.substr(0, tarFile.length() - 4).append(".txt"); - } else { - manageFile = tarFile + ".txt"; - } - + HILOGI("IncrementalTarFileReady: tar: %{public}s", tarFile.c_str()); + string manageFile = GetReportFileName(tarFile); + HILOGI("IncrementalTarFileReady: manageFile: %{public}s", tarFile.c_str()); string file = string(INDEX_FILE_INCREMENTAL_BACKUP).append(manageFile); WriteFile(file, srcFiles); @@ -1292,7 +1251,7 @@ static ErrCode IncrementalTarFileReady(const TarMap &bigFileInfo, const map &bigInfos, sptr proxy) +static ErrCode IncrementalBigFileReady(const TarMap &pkgInfo, const map &bigInfos, + sptr proxy) { ErrCode ret {ERR_OK}; for (auto &item : pkgInfo) { @@ -1316,10 +1276,11 @@ static ErrCode IncrementalBigFileReady(const TarMap &pkgInfo, const mapsecond; - string file = string(INDEX_FILE_INCREMENTAL_BACKUP).append(item.first).append(".txt"); - HILOGE("IncrementalBigFileReady write name is %{public}s", path.c_str()); - map bigInfo; + struct ReportFileInfo info = bigInfos.find(path)->second; + string file = GetReportFileName(string(INDEX_FILE_INCREMENTAL_BACKUP).append(item.first)); + HILOGI("IncrementalBigFileReady write name is %{public}s", path.c_str()); + HILOGI("IncrementalBigFileReady: file: %{public}s", file.c_str()); + map bigInfo; bigInfo.try_emplace(path, info); WriteFile(file, bigInfo); @@ -1329,8 +1290,7 @@ static ErrCode IncrementalBigFileReady(const TarMap &pkgInfo, const map &infos, TarMap &tar, sptr proxy) +static void IncrementalPacket(const map &infos, TarMap &tar, sptr proxy) { - HILOGE("IncrementalPacket begin"); + HILOGI("IncrementalPacket begin"); string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP); int64_t totalSize = 0; uint32_t fileCount = 0; vector packFiles; - map tarInfos; + map tarInfos; for (auto small : infos) { totalSize += small.second.size; fileCount += 1; @@ -1419,7 +1379,7 @@ static void IncrementalPacket(const map &infos, TarMap } } -static ErrCode IncrementalAllFileReady(const TarMap &pkgInfo, const map &srcFiles, +static ErrCode IncrementalAllFileReady(const TarMap &pkgInfo, const map &srcFiles, sptr proxy) { BJsonCachedEntity cachedEntity( diff --git a/utils/include/b_json/b_report_entity.h b/utils/include/b_json/b_report_entity.h index 83fad2433..c493276d1 100644 --- a/utils/include/b_json/b_report_entity.h +++ b/utils/include/b_json/b_report_entity.h @@ -17,17 +17,31 @@ #define OHOS_FILEMGMT_BACKUP_B_REPORT_ENTITY_H #include +#include #include +#include +#include + +#include "b_error/b_error.h" +#include "filemgmt_libhilog.h" +#include "unique_fd.h" namespace OHOS::FileManagement::Backup { +using namespace std; struct ReportFileInfo { string filePath {""}; - mode_t mode {0}; + string mode {""}; bool isDir {false}; off_t size {0}; off_t mtime {0}; string hash {""}; + bool isIncremental {false}; }; + +namespace { +const int64_t HASH_BUFFER_SIZE = 4096; // 每次读取的siz +} // namespace + enum ReportFileInfoAttr {FILE_PATH, MODE, IS_DIR, SIZE, MTIME, HASH}; class BReportEntity { public: @@ -41,7 +55,7 @@ public: info.filePath = attrs[FILE_PATH]; if (!attrs[MODE].empty()) { - info.mode = static_cast(atoi(attrs[MODE].c_str())); + info.mode = attrs[MODE]; } if (attrs[IS_DIR].empty()) { @@ -163,6 +177,99 @@ public: return infos; } + ErrCode ParseReportInfo(struct ReportFileInfo &fileStat, const std::vector &splits, const std::unordered_map &keys) + { + // 根据数据拼接结构体 + int len = keys.size(); + int splitsLen = (int)splits.size(); + // 处理path路径 + std::string path; + std::vector residue; + for (int i = 0; i < splitsLen; i++) { + if (i <= splitsLen - len) { + path += splits[i] + ";"; + } else { + residue.emplace_back(splits[i]); + } + } + + try { + fileStat.filePath = path.substr(0, path.length() - 1); + fileStat.mode = residue[keys.find("mode")->second]; + fileStat.isDir = atoi(residue[keys.find("dir")->second].c_str()) == 1 ? true : false; + fileStat.size = static_cast(atol(residue[keys.find("size")->second].c_str())); + fileStat.mtime = static_cast(atol(residue[keys.find("mtime")->second].c_str())); + fileStat.hash = residue[keys.find("hash")->second]; + if (keys.find("isIncremental") != keys.end()) { + fileStat.isIncremental = atoi(residue[keys.find("isIncremental")->second].c_str()) == 1 ? true : false; + } + return ERR_OK; + } catch (const exception &e) { + HILOGE("Failed to ParseReportInfo %{public}s", e.what()); + return EPERM; + } + } + /** + * @brief 获取Report信息 + * + * @return std::map + */ + std::map GetReportInfos() + { + std::map infos {}; + + char buffer[HASH_BUFFER_SIZE]; + ssize_t bytesRead; + std::string currentLine; + std::unordered_map keys; + std::vector splits; + int num = 0; + struct ReportFileInfo fileState; + while ((bytesRead = read(srcFile_, buffer, sizeof(buffer))) > 0) { + for (ssize_t i = 0; i < bytesRead; ++i) { + if (buffer[i] == lineSep_) { + splits.clear(); + splits = SplitStringByChar(currentLine, attrSep_); + if (num < 2) { + if (num == 1) { + for (int j = 0; j < (int)splits.size(); j++) { + keys.emplace(splits[j], j - 1); + } + } + num++; + currentLine.clear(); + continue; + } + + auto code = ParseReportInfo(fileState, splits, keys); + if (code != ERR_OK) { + HILOGE("ParseReportInfo err:%{public}d, %{public}s", code, currentLine.c_str()); + continue; + } + infos.try_emplace(fileState.filePath, fileState); + currentLine.clear(); + } else { + currentLine += buffer[i]; + } + } + } + + // 处理文件中的最后一行 + if (!currentLine.empty()) { + splits.clear(); + splits = SplitStringByChar(currentLine, attrSep_); + + auto code = ParseReportInfo(fileState, splits, keys); + if (code == ERR_OK) { + infos.try_emplace(fileState.filePath, fileState); + } else { + HILOGE("ParseReportInfo err:%{public}d, %{public}s", code, currentLine.c_str()); + } + } + + return infos; + } + public: /** * @brief 构造方法 -- Gitee From 3a6e743c08ce9dfca0ac7b3f28d92f52fe1652d8 Mon Sep 17 00:00:00 2001 From: yang-jingbo1985 Date: Sat, 30 Dec 2023 10:53:02 +0800 Subject: [PATCH 06/35] =?UTF-8?q?service=E4=BE=A7=E8=B0=83=E7=94=A8?= =?UTF-8?q?=E8=A1=A5=E5=85=85=20Signed-off-by:=20yangjingbo10=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/module_external/bms_adapter.cpp | 4 +- .../src/module_ipc/service_incremental.cpp | 38 ++++++++++++++++++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/services/backup_sa/src/module_external/bms_adapter.cpp b/services/backup_sa/src/module_external/bms_adapter.cpp index 9ed603326..6cc2117c8 100644 --- a/services/backup_sa/src/module_external/bms_adapter.cpp +++ b/services/backup_sa/src/module_external/bms_adapter.cpp @@ -189,7 +189,7 @@ static tuple, vector> GetBa } static bool CreateIPCInteractionFiles(int32_t userId, const string &bundleName, int64_t lastIncrementalTime, - const vector includes, const vector excludes) + const vector &includes, const vector &excludes) { // backup_sa bundle path string backupSaBundleDir = BConstants::BACKUP_PATH_PREFIX + to_string(userId) + BConstants::BACKUP_PATH_SURFFIX + @@ -217,7 +217,7 @@ static bool CreateIPCInteractionFiles(int32_t userId, const string &bundleName, return true; } -std::vector GetBundleInfosForIncremental( +std::vector BundleMgrAdapter::GetBundleInfosForIncremental( const std::vector &incrementalDataList, int32_t userId) { std::vector bundleNames; diff --git a/services/backup_sa/src/module_ipc/service_incremental.cpp b/services/backup_sa/src/module_ipc/service_incremental.cpp index f8ede49c4..03a3bf03c 100644 --- a/services/backup_sa/src/module_ipc/service_incremental.cpp +++ b/services/backup_sa/src/module_ipc/service_incremental.cpp @@ -86,8 +86,42 @@ ErrCode Service::Release() UniqueFd Service::GetLocalCapabilitiesIncremental(const std::vector &bundleNames) { - HILOGI("Begin"); - return UniqueFd(-1); + try { + HILOGI("Begin"); + /* + Only called by restore app before InitBackupSession, + so there must be set init userId. + */ + session_->IncreaseSessionCnt(); + session_->SetSessionUserId(GetUserIdDefault()); + VerifyCaller(); + string path = BConstants::GetSaBundleBackupRootDir(session_->GetSessionUserId()); + BExcepUltils::VerifyPath(path, false); + BJsonCachedEntity cachedEntity( + UniqueFd(open(path.data(), O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR))); + + auto cache = cachedEntity.Structuralize(); + + cache.SetSystemFullName(GetOSFullName()); + cache.SetDeviceType(GetDeviceType()); + auto bundleInfos = BundleMgrAdapter::GetBundleInfosForIncremental(bundleNames, session_->GetSessionUserId()); + cache.SetBundleInfos(bundleInfos); + cachedEntity.Persist(); + session_->DecreaseSessionCnt(); + return move(cachedEntity.GetFd()); + } catch (const BError &e) { + session_->DecreaseSessionCnt(); + HILOGE("GetLocalCapabilitiesIncremental failed, errCode = %{public}d", e.GetCode()); + return UniqueFd(-e.GetCode()); + } catch (const exception &e) { + session_->DecreaseSessionCnt(); + HILOGI("Catched an unexpected low-level exception %{public}s", e.what()); + return UniqueFd(-EPERM); + } catch (...) { + session_->DecreaseSessionCnt(); + HILOGI("Unexpected exception"); + return UniqueFd(-EPERM); + } } ErrCode Service::InitIncrementalBackupSession(sptr remote) -- Gitee From 2b4623b0d4abc6ffbc6fb4a908c592caa0aa41a7 Mon Sep 17 00:00:00 2001 From: yang-jingbo1985 Date: Sat, 30 Dec 2023 14:45:57 +0800 Subject: [PATCH 07/35] =?UTF-8?q?=E7=94=9F=E6=88=90includeexclude=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D=20Signed-off-by:?= =?UTF-8?q?=20yangjingbo10=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../include/module_external/bms_adapter.h | 4 ++-- .../src/module_external/bms_adapter.cpp | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/services/backup_sa/include/module_external/bms_adapter.h b/services/backup_sa/include/module_external/bms_adapter.h index 7297a5fe6..6a33d678a 100644 --- a/services/backup_sa/include/module_external/bms_adapter.h +++ b/services/backup_sa/include/module_external/bms_adapter.h @@ -59,8 +59,8 @@ public: * @param userId User ID * @return std::vector */ - static std::vector GetBundleInfosForIncremental(const std::vector &incrementalDataList, - int32_t userId); + 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/src/module_external/bms_adapter.cpp b/services/backup_sa/src/module_external/bms_adapter.cpp index 6cc2117c8..01f396490 100644 --- a/services/backup_sa/src/module_external/bms_adapter.cpp +++ b/services/backup_sa/src/module_external/bms_adapter.cpp @@ -193,10 +193,13 @@ static bool CreateIPCInteractionFiles(int32_t userId, const string &bundleName, { // 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; + bundleName + BConstants::FILE_SEPARATOR_CHAR; + if (access(backupSaBundleDir.data(), F_OK) != 0) { + int err = mkdir(backupSaBundleDir.data(), S_IRWXU | S_IRWXG); + if (err != 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); @@ -251,7 +254,11 @@ std::vector BundleMgrAdapter::GetBundleInfosForIncr std::vector pkgFileSizes; std::vector pkgStatPaths; - StorageMgrAdapter::GetBundleStatsForIncrease(userId, bundleNames , incrementalBackTimes, pkgFileSizes, pkgStatPaths); + int32_t err = StorageMgrAdapter::GetBundleStatsForIncrease(userId, bundleNames , incrementalBackTimes, pkgFileSizes, pkgStatPaths); + if (err != 0) { + HILOGE("Failed to get bundleStats result"); + return {}; + } std::vector newBundleInfos; for (size_t i = 0; bundleInfos.size(); i++) { -- Gitee From eee4e9a475976e8ef5e0c507c2b86018f1748837 Mon Sep 17 00:00:00 2001 From: zhuruigan Date: Sat, 30 Dec 2023 14:59:30 +0800 Subject: [PATCH 08/35] =?UTF-8?q?=E8=A7=A3=E5=91=8A=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhuruigan --- .../native/backup_ext/include/ext_extension.h | 2 +- .../native/backup_ext/src/ext_extension.cpp | 23 ++++---- utils/include/b_filesystem/b_file.h | 2 +- utils/include/b_json/b_report_entity.h | 54 +++++++++-------- utils/src/b_filesystem/b_file.cpp | 59 ++++++++++--------- utils/src/b_filesystem/b_file_hash.cpp | 14 ----- 6 files changed, 73 insertions(+), 81 deletions(-) diff --git a/frameworks/native/backup_ext/include/ext_extension.h b/frameworks/native/backup_ext/include/ext_extension.h index fdc74ecec..6d8a52ece 100644 --- a/frameworks/native/backup_ext/include/ext_extension.h +++ b/frameworks/native/backup_ext/include/ext_extension.h @@ -115,7 +115,7 @@ private: /** * @brief IncrementalBackup - * + * * @param incrementalFd storage fd * @param manifestFd 云空间 fd */ diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index 36d3178fa..cb19ae7aa 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -1127,8 +1127,9 @@ ErrCode BackupExtExtension::HandleRestore() return 0; } -static tuple, map, map, - map> CompareFiles(const UniqueFd &cloudFd, const UniqueFd &storageFd) +static tuple, map, + map, map> + CompareFiles(const UniqueFd &cloudFd, const UniqueFd &storageFd) { BReportEntity cloudRp(UniqueFd(cloudFd.Get())); map cloudFiles = cloudRp.GetReportInfos(); @@ -1142,7 +1143,7 @@ static tuple, map, mapsecond.hash != item.second.hash)) { // 在云空间简报里不存在或者hash不一致 // 区分大小文件 @@ -1181,7 +1182,7 @@ static tuple, map &srcFiles) { fstream f; - f.open(filename.data(), ios::out); + f.open(filename.data(), ios::out); // 前面2行先填充进去 f << "version=1.0&attrNum=6" << endl; f << "path;mode;dir;size;mtime;hash" << endl; @@ -1198,7 +1199,7 @@ static void WriteFile(const string &filename, const map &files) +static TarMap GetIncrmentBigInfos(const map &files) { auto getStringHash = [](const TarMap &m, const string &str) -> string { ostringstream strHex; @@ -1260,7 +1261,7 @@ static ErrCode IncrementalTarFileReady(const TarMap &bigFileInfo, const map &bigInfos, - sptr proxy) + sptr proxy) { ErrCode ret {ERR_OK}; for (auto &item : pkgInfo) { @@ -1272,7 +1273,7 @@ static ErrCode IncrementalBigFileReady(const TarMap &pkgInfo, const mapAppIncrementalFileReady(item.first, std::move(fd), UniqueFd(open(file.data(), O_RDONLY))); if (SUCCEEDED(ret)) { - HILOGI("IncrementalBigFileReady : The application is packaged successfully, package name is %{public}s", - item.first.c_str()); + HILOGI("IncrementalBigFileReady:The application is packaged successfully, package name is %{public}s", + item.first.c_str()); RemoveFile(file); } else { HILOGE("IncrementalBigFileReady interface fails to be invoked: %{public}d", ret); @@ -1380,7 +1381,7 @@ static void IncrementalPacket(const map &infos, T } static ErrCode IncrementalAllFileReady(const TarMap &pkgInfo, const map &srcFiles, - sptr proxy) + sptr proxy) { BJsonCachedEntity cachedEntity( UniqueFd(open(INDEX_FILE_BACKUP.data(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR))); diff --git a/utils/include/b_filesystem/b_file.h b/utils/include/b_filesystem/b_file.h index f9a0055ff..a2f958fb7 100644 --- a/utils/include/b_filesystem/b_file.h +++ b/utils/include/b_filesystem/b_file.h @@ -63,7 +63,7 @@ public: /** * @brief read incremental file info - * + * * @param fd UniqueFd */ static vector> ReadIncrementalFile(const UniqueFd &fd); diff --git a/utils/include/b_json/b_report_entity.h b/utils/include/b_json/b_report_entity.h index c493276d1..7456bae21 100644 --- a/utils/include/b_json/b_report_entity.h +++ b/utils/include/b_json/b_report_entity.h @@ -40,6 +40,7 @@ struct ReportFileInfo { namespace { const int64_t HASH_BUFFER_SIZE = 4096; // 每次读取的siz +const int FILTER_LINE = 2; // 过滤前2行 } // namespace enum ReportFileInfoAttr {FILE_PATH, MODE, IS_DIR, SIZE, MTIME, HASH}; @@ -177,7 +178,8 @@ public: return infos; } - ErrCode ParseReportInfo(struct ReportFileInfo &fileStat, const std::vector &splits, const std::unordered_map &keys) + ErrCode ParseReportInfo(struct ReportFileInfo &fileStat, const std::vector &splits, + const std::unordered_map &keys) { // 根据数据拼接结构体 int len = keys.size(); @@ -209,6 +211,29 @@ public: return EPERM; } } + + void DealLine(std::unordered_map &keys, int &num, const std::string ¤tLine, + std::map &infos) + { + std::vector splits = SplitStringByChar(currentLine, attrSep_); + if (num < FILTER_LINE) { + if (num == 1) { + for (int j = 0; j < (int)splits.size(); j++) { + keys.emplace(splits[j], j - 1); + } + } + num++; + } else { + struct ReportFileInfo fileState; + auto code = ParseReportInfo(fileState, splits, keys); + if (code != ERR_OK) { + HILOGE("ParseReportInfo err:%{public}d, %{public}s", code, currentLine.c_str()); + } else { + infos.try_emplace(fileState.filePath, fileState); + } + } + } + /** * @brief 获取Report信息 * @@ -222,31 +247,11 @@ public: ssize_t bytesRead; std::string currentLine; std::unordered_map keys; - std::vector splits; int num = 0; - struct ReportFileInfo fileState; while ((bytesRead = read(srcFile_, buffer, sizeof(buffer))) > 0) { for (ssize_t i = 0; i < bytesRead; ++i) { if (buffer[i] == lineSep_) { - splits.clear(); - splits = SplitStringByChar(currentLine, attrSep_); - if (num < 2) { - if (num == 1) { - for (int j = 0; j < (int)splits.size(); j++) { - keys.emplace(splits[j], j - 1); - } - } - num++; - currentLine.clear(); - continue; - } - - auto code = ParseReportInfo(fileState, splits, keys); - if (code != ERR_OK) { - HILOGE("ParseReportInfo err:%{public}d, %{public}s", code, currentLine.c_str()); - continue; - } - infos.try_emplace(fileState.filePath, fileState); + DealLine(keys, num, currentLine, infos); currentLine.clear(); } else { currentLine += buffer[i]; @@ -256,9 +261,8 @@ public: // 处理文件中的最后一行 if (!currentLine.empty()) { - splits.clear(); - splits = SplitStringByChar(currentLine, attrSep_); - + std::vector splits = SplitStringByChar(currentLine, attrSep_); + struct ReportFileInfo fileState; auto code = ParseReportInfo(fileState, splits, keys); if (code == ERR_OK) { infos.try_emplace(fileState.filePath, fileState); diff --git a/utils/src/b_filesystem/b_file.cpp b/utils/src/b_filesystem/b_file.cpp index d85b30ae9..eb6804dd3 100644 --- a/utils/src/b_filesystem/b_file.cpp +++ b/utils/src/b_filesystem/b_file.cpp @@ -163,36 +163,37 @@ vector> BFile::ReadIncrementalFile(const UniqueFd &fd) vector> infos; vector lines = SplitString(content, '\n'); - if (lines.begin() != lines.end()) { - // 对第2行的数据做切分 - vector keys = SplitString(lines[1], ';'); - int num = (int)keys.size() - 1; - - for (int i = 2; i < (int)lines.size(); i++) { - map info; - // 如果结尾有;,就删除后再切分 - string newLine = lines[i]; - if (newLine[newLine.length() - 1] == ';') { - newLine = newLine.substr(0, newLine.length() - 1); - } - - vector words = SplitString(newLine, ';'); - if (words.begin() != words.end()) { - string filePath = ""; - int len = words.size(); - for (int j = 1; j < (int)keys.size(); j++) { - int index = len - num - 1 + j; - info.try_emplace(keys[j], words[index]); - } - for (int j = 0; j < len - num; j++) { - filePath += words[j] + ";"; - } - filePath = filePath.substr(0, filePath.length() - 1); - info.try_emplace(keys[0], filePath); - - } - infos.emplace_back(info); + if (lines.begin() == lines.end()) { + return infos; + } + // 对第2行的数据做切分 + vector keys = SplitString(lines[1], ';'); + int num = (int)keys.size() - 1; + + for (int i = 2; i < (int)lines.size(); i++) { + map info; + // 如果结尾有;,就删除后再切分 + string newLine = lines[i]; + if (newLine[newLine.length() - 1] == ';') { + newLine = newLine.substr(0, newLine.length() - 1); + } + + vector words = SplitString(newLine, ';'); + if (words.begin() == words.end()) { + continue; + } + string filePath = ""; + int len = words.size(); + for (int j = 1; j < (int)keys.size(); j++) { + int index = len - num - 1 + j; + info.try_emplace(keys[j], words[index]); + } + for (int j = 0; j < len - num; j++) { + filePath += words[j] + ";"; } + filePath = filePath.substr(0, filePath.length() - 1); + info.try_emplace(keys[0], filePath); + infos.emplace_back(info); } return infos; } diff --git a/utils/src/b_filesystem/b_file_hash.cpp b/utils/src/b_filesystem/b_file_hash.cpp index c3e162786..1b84790b8 100644 --- a/utils/src/b_filesystem/b_file_hash.cpp +++ b/utils/src/b_filesystem/b_file_hash.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -63,19 +62,6 @@ static int ForEachFileSegment(const string &fpath, function BFileHash::HashWithMD5(const string &fpath) -{ - auto res = make_unique(MD5_DIGEST_LENGTH); - MD5_CTX ctx; - MD5_Init(&ctx); - auto md5Update = [ctx = &ctx](char *buf, size_t len) { - MD5_Update(ctx, buf, len); - }; - int err = ForEachFileSegment(fpath, md5Update); - MD5_Final(res.get(), &ctx); - return HashFinal(err, res, MD5_DIGEST_LENGTH); -} - tuple BFileHash::HashWithSHA1(const string &fpath) { auto res = make_unique(SHA_DIGEST_LENGTH); -- Gitee From 5c3abd5b3ec2e8348604ce50ffb1e6a86cdd8074 Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Sat, 30 Dec 2023 15:36:27 +0800 Subject: [PATCH 09/35] =?UTF-8?q?=E4=BC=98=E5=8C=96IncrementalBackup?= =?UTF-8?q?=E6=89=93=E9=80=9A=E5=A4=87=E4=BB=BD=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- .../include/module_ipc/svc_session_manager.h | 8 ++++++++ .../src/module_ipc/service_incremental.cpp | 19 ++++++++++--------- .../src/module_ipc/svc_session_manager.cpp | 10 ++++++++++ .../module_ipc/svc_session_manager_mock.cpp | 5 +++++ 4 files changed, 33 insertions(+), 9 deletions(-) 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 9473b48b5..60b786c38 100644 --- a/services/backup_sa/include/module_ipc/svc_session_manager.h +++ b/services/backup_sa/include/module_ipc/svc_session_manager.h @@ -406,6 +406,14 @@ public: */ int32_t GetIncrementalManifestFd(const std::string &bundleName); + /** + * @brief Get the Last Incremental Time object + * + * @param bundleName + * @return int64_t + */ + int64_t GetLastIncrementalTime(const std::string &bundleName); + private: /** * @brief 获取backup extension ability diff --git a/services/backup_sa/src/module_ipc/service_incremental.cpp b/services/backup_sa/src/module_ipc/service_incremental.cpp index 03a3bf03c..465be7a19 100644 --- a/services/backup_sa/src/module_ipc/service_incremental.cpp +++ b/services/backup_sa/src/module_ipc/service_incremental.cpp @@ -25,8 +25,6 @@ #include #include #include -#include -#include #include #include @@ -34,27 +32,23 @@ #include #include +#include -#include "ability_manager_client.h" #include "accesstoken_kit.h" #include "b_error/b_error.h" #include "b_error/b_excep_utils.h" -#include "b_file_info.h" #include "b_json/b_json_cached_entity.h" #include "b_json/b_json_entity_caps.h" #include "b_ohos/startup/backup_para.h" #include "b_process/b_multiuser.h" #include "b_resources/b_constants.h" -#include "bundle_mgr_client.h" #include "filemgmt_libhilog.h" #include "ipc_skeleton.h" -#include "module_app_gallery/app_gallery_dispose_proxy.h" #include "module_external/bms_adapter.h" #include "module_ipc/svc_backup_connection.h" #include "module_ipc/svc_restore_deps_manager.h" #include "parameter.h" #include "system_ability_definition.h" -#include "unique_fd.h" namespace OHOS::FileManagement::Backup { using namespace std; @@ -86,7 +80,7 @@ ErrCode Service::Release() UniqueFd Service::GetLocalCapabilitiesIncremental(const std::vector &bundleNames) { - try { + try { HILOGI("Begin"); /* Only called by restore app before InitBackupSession, @@ -330,7 +324,14 @@ bool Service::IncrementalBackup(const string &bundleName) throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty"); } if (scenario == IServiceReverse::Scenario::BACKUP && session_->GetIsIncrementalBackup()) { - UniqueFd fd; + // 本地全量数据 + string path = BConstants::GetSaBundleBackupRootDir(session_->GetSessionUserId()) + .append(bundleName) + .append(BConstants::BACKUP_STAT_SYMBOL) + .append(to_string(session_->GetLastIncrementalTime(bundleName))); + HILOGI("path = %{public}s", path.c_str()); + UniqueFd fd(open(path.data(), O_RDWR, S_IRGRP | S_IWGRP | S_IRGRP | S_IWGRP)); + // 云上存在的数据 UniqueFd manifestFd(session_->GetIncrementalManifestFd(bundleName)); auto ret = proxy->HandleIncrementalBackup(move(fd), move(manifestFd)); session_->GetServiceReverseProxy()->IncrementalBackupOnBundleStarted(ret, bundleName); 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 b154d51e7..626c2d225 100644 --- a/services/backup_sa/src/module_ipc/svc_session_manager.cpp +++ b/services/backup_sa/src/module_ipc/svc_session_manager.cpp @@ -665,4 +665,14 @@ int32_t SvcSessionManager::GetIncrementalManifestFd(const string &bundleName) auto it = GetBackupExtNameMap(bundleName); return it->second.manifestFd; } + +int64_t SvcSessionManager::GetLastIncrementalTime(const string &bundleName) +{ + 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.lastIncrementalTime; +} } // namespace OHOS::FileManagement::Backup diff --git a/tests/mock/module_ipc/svc_session_manager_mock.cpp b/tests/mock/module_ipc/svc_session_manager_mock.cpp index e5b8d488b..7c81bf84c 100644 --- a/tests/mock/module_ipc/svc_session_manager_mock.cpp +++ b/tests/mock/module_ipc/svc_session_manager_mock.cpp @@ -326,4 +326,9 @@ int32_t SvcSessionManager::GetIncrementalManifestFd(const string &bundleName) { return 0; } + +int64_t SvcSessionManager::GetLastIncrementalTime(const string &bundleName) +{ + return 0; +} } // namespace OHOS::FileManagement::Backup -- Gitee From 57ff4d58eb6bd3526d1dbdc4e5a1c6f5c51ff28e Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Sat, 30 Dec 2023 15:36:27 +0800 Subject: [PATCH 10/35] =?UTF-8?q?=E4=BC=98=E5=8C=96IncrementalBackup?= =?UTF-8?q?=E6=89=93=E9=80=9A=E5=A4=87=E4=BB=BD=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- .../include/module_ipc/svc_session_manager.h | 8 ++++++++ .../src/module_ipc/service_incremental.cpp | 20 ++++++++++--------- .../src/module_ipc/svc_session_manager.cpp | 10 ++++++++++ .../module_ipc/svc_session_manager_mock.cpp | 5 +++++ 4 files changed, 34 insertions(+), 9 deletions(-) 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 9473b48b5..60b786c38 100644 --- a/services/backup_sa/include/module_ipc/svc_session_manager.h +++ b/services/backup_sa/include/module_ipc/svc_session_manager.h @@ -406,6 +406,14 @@ public: */ int32_t GetIncrementalManifestFd(const std::string &bundleName); + /** + * @brief Get the Last Incremental Time object + * + * @param bundleName + * @return int64_t + */ + int64_t GetLastIncrementalTime(const std::string &bundleName); + private: /** * @brief 获取backup extension ability diff --git a/services/backup_sa/src/module_ipc/service_incremental.cpp b/services/backup_sa/src/module_ipc/service_incremental.cpp index 03a3bf03c..adeab2c7b 100644 --- a/services/backup_sa/src/module_ipc/service_incremental.cpp +++ b/services/backup_sa/src/module_ipc/service_incremental.cpp @@ -25,8 +25,6 @@ #include #include #include -#include -#include #include #include @@ -34,27 +32,23 @@ #include #include +#include -#include "ability_manager_client.h" #include "accesstoken_kit.h" #include "b_error/b_error.h" #include "b_error/b_excep_utils.h" -#include "b_file_info.h" #include "b_json/b_json_cached_entity.h" #include "b_json/b_json_entity_caps.h" #include "b_ohos/startup/backup_para.h" #include "b_process/b_multiuser.h" #include "b_resources/b_constants.h" -#include "bundle_mgr_client.h" #include "filemgmt_libhilog.h" #include "ipc_skeleton.h" -#include "module_app_gallery/app_gallery_dispose_proxy.h" #include "module_external/bms_adapter.h" #include "module_ipc/svc_backup_connection.h" #include "module_ipc/svc_restore_deps_manager.h" #include "parameter.h" #include "system_ability_definition.h" -#include "unique_fd.h" namespace OHOS::FileManagement::Backup { using namespace std; @@ -86,7 +80,7 @@ ErrCode Service::Release() UniqueFd Service::GetLocalCapabilitiesIncremental(const std::vector &bundleNames) { - try { + try { HILOGI("Begin"); /* Only called by restore app before InitBackupSession, @@ -330,7 +324,15 @@ bool Service::IncrementalBackup(const string &bundleName) throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty"); } if (scenario == IServiceReverse::Scenario::BACKUP && session_->GetIsIncrementalBackup()) { - UniqueFd fd; + // 本地全量数据 + string path = BConstants::GetSaBundleBackupRootDir(session_->GetSessionUserId()) + .append(bundleName) + .append("/") + .append(BConstants::BACKUP_STAT_SYMBOL) + .append(to_string(session_->GetLastIncrementalTime(bundleName))); + HILOGI("path = %{public}s", path.c_str()); + UniqueFd fd(open(path.data(), O_RDWR, S_IRGRP | S_IWGRP | S_IRGRP | S_IWGRP)); + // 云上存在的数据 UniqueFd manifestFd(session_->GetIncrementalManifestFd(bundleName)); auto ret = proxy->HandleIncrementalBackup(move(fd), move(manifestFd)); session_->GetServiceReverseProxy()->IncrementalBackupOnBundleStarted(ret, bundleName); 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 b154d51e7..626c2d225 100644 --- a/services/backup_sa/src/module_ipc/svc_session_manager.cpp +++ b/services/backup_sa/src/module_ipc/svc_session_manager.cpp @@ -665,4 +665,14 @@ int32_t SvcSessionManager::GetIncrementalManifestFd(const string &bundleName) auto it = GetBackupExtNameMap(bundleName); return it->second.manifestFd; } + +int64_t SvcSessionManager::GetLastIncrementalTime(const string &bundleName) +{ + 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.lastIncrementalTime; +} } // namespace OHOS::FileManagement::Backup diff --git a/tests/mock/module_ipc/svc_session_manager_mock.cpp b/tests/mock/module_ipc/svc_session_manager_mock.cpp index e5b8d488b..7c81bf84c 100644 --- a/tests/mock/module_ipc/svc_session_manager_mock.cpp +++ b/tests/mock/module_ipc/svc_session_manager_mock.cpp @@ -326,4 +326,9 @@ int32_t SvcSessionManager::GetIncrementalManifestFd(const string &bundleName) { return 0; } + +int64_t SvcSessionManager::GetLastIncrementalTime(const string &bundleName) +{ + return 0; +} } // namespace OHOS::FileManagement::Backup -- Gitee From e8dd4ddc261dd8e6ee1aeaa5a1dba23afa4ed6eb Mon Sep 17 00:00:00 2001 From: zhuruigan Date: Sat, 30 Dec 2023 17:22:41 +0800 Subject: [PATCH 11/35] =?UTF-8?q?=E5=A2=9E=E9=87=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhuruigan --- frameworks/native/backup_ext/src/ext_extension.cpp | 13 ++++++++----- .../src/module_ipc/service_incremental.cpp | 3 --- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index cb19ae7aa..39a3785ca 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -1418,17 +1418,20 @@ int BackupExtExtension::DoIncrementalBackup(UniqueFd incrementalFd, UniqueFd man throw BError(errno); } + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno)); + } // 获取增量文件和全量数据 auto [allFiles, smallFiles, bigFiles, bigInfos] = CompareFiles(manifestFd, incrementalFd); if (smallFiles.size() == 0 && bigFiles.size() == 0) { // 没有增量,则不需要上传 + TarMap tMap; + IncrementalAllFileReady(tMap, allFiles, proxy); + HILOGI("Do increment backup, IncrementalAllFileReady end, file empty"); return ERR_OK; } - - auto proxy = ServiceProxy::GetInstance(); - if (proxy == nullptr) { - throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno)); - } + // tar包数据 TarMap tarMap; IncrementalPacket(smallFiles, tarMap, proxy); diff --git a/services/backup_sa/src/module_ipc/service_incremental.cpp b/services/backup_sa/src/module_ipc/service_incremental.cpp index 21ce961d6..adeab2c7b 100644 --- a/services/backup_sa/src/module_ipc/service_incremental.cpp +++ b/services/backup_sa/src/module_ipc/service_incremental.cpp @@ -327,10 +327,7 @@ bool Service::IncrementalBackup(const string &bundleName) // 本地全量数据 string path = BConstants::GetSaBundleBackupRootDir(session_->GetSessionUserId()) .append(bundleName) -<<<<<<< HEAD -======= .append("/") ->>>>>>> upstream/master .append(BConstants::BACKUP_STAT_SYMBOL) .append(to_string(session_->GetLastIncrementalTime(bundleName))); HILOGI("path = %{public}s", path.c_str()); -- Gitee From 9b93587566eb438ab2eca99fe312b30de1a51a8b Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Sat, 30 Dec 2023 18:00:35 +0800 Subject: [PATCH 12/35] =?UTF-8?q?=E6=89=93=E9=80=9Abackup=5Ftool=E5=A2=9E?= =?UTF-8?q?=E9=87=8F=E6=81=A2=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- .../backup_sa/src/module_ipc/service_incremental.cpp | 8 ++++---- .../backup_tool/src/tools_op_incremental_restore.cpp | 11 +++++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/services/backup_sa/src/module_ipc/service_incremental.cpp b/services/backup_sa/src/module_ipc/service_incremental.cpp index adeab2c7b..f5526598e 100644 --- a/services/backup_sa/src/module_ipc/service_incremental.cpp +++ b/services/backup_sa/src/module_ipc/service_incremental.cpp @@ -206,16 +206,16 @@ ErrCode Service::AppIncrementalFileReady(const std::string &fileName, UniqueFd f try { HILOGI("Begin"); string callerName = VerifyCallerAndGetCallerName(); - if (fileName == BConstants::EXT_BACKUP_MANAGE) { - fd = session_->OnBunleExtManageInfo(callerName, move(fd)); - } - if (session_->GetScenario() == IServiceReverse::Scenario::RESTORE) { session_->GetServiceReverseProxy()->IncrementalRestoreOnFileReady(callerName, fileName, move(fd), move(manifestFd)); return BError(BError::Codes::OK); } + if (fileName == BConstants::EXT_BACKUP_MANAGE) { + fd = session_->OnBunleExtManageInfo(callerName, move(fd)); + } + session_->GetServiceReverseProxy()->IncrementalBackupOnFileReady(callerName, fileName, move(fd), move(manifestFd)); if (session_->OnBunleFileReady(callerName, fileName)) { diff --git a/tools/backup_tool/src/tools_op_incremental_restore.cpp b/tools/backup_tool/src/tools_op_incremental_restore.cpp index 1970e9d5a..ec070184a 100644 --- a/tools/backup_tool/src/tools_op_incremental_restore.cpp +++ b/tools/backup_tool/src/tools_op_incremental_restore.cpp @@ -129,8 +129,9 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq throw BError(BError::Codes::TOOL_INVAL_ARG, "Filename is not valid"); } // 待恢复文件 路径拼接方式: /data/backup/incrementalreceived/bundleName/时间戳/incremental/文件名 - string tmpPath = string(BConstants::BACKUP_TOOL_RECEIVE_DIR) + fileInfo.owner + "/" + ctx->lastIncrementalTime + - string(BConstants::BACKUP_TOOL_INCREMENTAL) + "/" + fileInfo.fileName; + string tmpPath = string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + fileInfo.owner + "/" + + ctx->lastIncrementalTime + string(BConstants::BACKUP_TOOL_INCREMENTAL) + "/" + fileInfo.fileName; + printf("tmpPath = %s\n", tmpPath.data()); if (access(tmpPath.data(), F_OK) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } @@ -140,8 +141,9 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq } BFile::SendFile(fd, fdLocal); // manifest文件 路径拼接方式: /data/backup/incrementalreceived/bundleName/时间戳/manifest/文件名.rp - tmpPath = string(BConstants::BACKUP_TOOL_RECEIVE_DIR) + fileInfo.owner + "/" + ctx->lastIncrementalTime + - string(BConstants::BACKUP_TOOL_MANIFEST) + "/" + fileInfo.fileName + ".rp"; + tmpPath = string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + fileInfo.owner + "/" + + ctx->lastIncrementalTime + string(BConstants::BACKUP_TOOL_MANIFEST) + "/" + fileInfo.fileName + ".rp"; + printf("tmpPath = %s\n", tmpPath.data()); if (access(tmpPath.data(), F_OK) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } @@ -221,6 +223,7 @@ static void RestoreApp(shared_ptr restore, vector &bundleNa for (auto &filePath : filePaths) { string fileName = filePath.substr(filePath.rfind("/") + 1); restore->session_->GetFileHandle(bundleName, fileName); + printf("GetFileHandle bundleName = %s, fileName = %s\n", bundleName.c_str(), fileName.c_str()); restore->UpdateBundleSendFiles(bundleName, fileName); } } -- Gitee From 47e2a5232e1f84b91b1fd372019f47f23fbf6acd Mon Sep 17 00:00:00 2001 From: nieben Date: Sat, 30 Dec 2023 18:08:34 +0800 Subject: [PATCH 13/35] DoClear change to ext Signed-off-by: nieben --- frameworks/native/backup_ext/include/ext_extension.h | 1 + frameworks/native/backup_ext/src/ext_backup.cpp | 6 ++++++ frameworks/native/backup_ext/src/ext_extension.cpp | 6 ++++++ services/backup_sa/src/module_ipc/service.cpp | 5 ----- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/frameworks/native/backup_ext/include/ext_extension.h b/frameworks/native/backup_ext/include/ext_extension.h index 6d8a52ece..296c609a4 100644 --- a/frameworks/native/backup_ext/include/ext_extension.h +++ b/frameworks/native/backup_ext/include/ext_extension.h @@ -41,6 +41,7 @@ public: void AsyncTaskRestoreForUpgrade(void); void AsyncTaskIncrementalRestoreForUpgrade(void); + void ExtClear(void); public: explicit BackupExtExtension(const std::shared_ptr &extension) : extension_(extension) diff --git a/frameworks/native/backup_ext/src/ext_backup.cpp b/frameworks/native/backup_ext/src/ext_backup.cpp index b08d04cec..298df3f9c 100644 --- a/frameworks/native/backup_ext/src/ext_backup.cpp +++ b/frameworks/native/backup_ext/src/ext_backup.cpp @@ -184,6 +184,12 @@ sptr ExtBackup::OnConnect(const AAFwk::Want &want) auto remoteObject = sptr(new BackupExtExtension(std::static_pointer_cast(shared_from_this()))); + + // 排除特殊场景 + if (!WasFromSpeicalVersion()) { + remoteObject->ExtClear(); + } + return remoteObject->AsObject(); } catch (const BError &e) { return nullptr; diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index 39a3785ca..7192149d5 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -1028,6 +1028,12 @@ void BackupExtExtension::AsyncTaskIncrementalRestoreForUpgrade() }); } +void BackupExtExtension::ExtClear() +{ + HILOGI("ext begin clear"); + DoClear(); +} + void BackupExtExtension::DoClear() { try { diff --git a/services/backup_sa/src/module_ipc/service.cpp b/services/backup_sa/src/module_ipc/service.cpp index d5afa327a..9e8807978 100644 --- a/services/backup_sa/src/module_ipc/service.cpp +++ b/services/backup_sa/src/module_ipc/service.cpp @@ -601,11 +601,6 @@ void Service::ExtStart(const string &bundleName) if (!proxy) { throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty"); } - if (session_->GetBundleVersionCode(bundleName) != BConstants::DEFAULT_VERSION_CODE && - session_->GetBundleVersionName(bundleName) != BConstants::DEFAULT_VERSION_NAME && - session_->GetBundleRestoreType(bundleName) != RestoreTypeEnum::RESTORE_DATA_READDY) { - proxy->HandleClear(); - } if (scenario == IServiceReverse::Scenario::BACKUP) { auto ret = proxy->HandleBackup(); session_->GetServiceReverseProxy()->BackupOnBundleStarted(ret, bundleName); -- Gitee From d1ac49145444638002e5285fe517aa34b6bbb8bb Mon Sep 17 00:00:00 2001 From: nieben Date: Sat, 30 Dec 2023 18:38:31 +0800 Subject: [PATCH 14/35] debug Signed-off-by: nieben --- .../native/backup_ext/src/ext_extension.cpp | 22 +--- utils/include/b_json/b_report_entity.h | 120 ------------------ 2 files changed, 3 insertions(+), 139 deletions(-) diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index 7192149d5..b4cd4f1e7 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -139,25 +139,9 @@ UniqueFd BackupExtExtension::GetFileHandle(const string &fileName) } } -static string ChangeFileExtension(const string &fileName, const string &fileExt) -{ - auto n = fileName.rfind("."); - if (n == string::npos) { - throw BError(BError::Codes::EXT_INVAL_ARG, "filename has no extension"); - } - - return string(fileName).replace(n, fileName.length()-n, "." + fileExt); -} - static string GetReportFileName(const string &fileName) { - string reportName; - if (fileName.rfind(".") != string::npos) { - reportName = ChangeFileExtension(fileName, string(BConstants::REPORT_FILE_EXT)); - } else { - reportName = fileName + "." + string(BConstants::REPORT_FILE_EXT); - } - + string reportName = fileName + "." + string(BConstants::REPORT_FILE_EXT); return reportName; } @@ -560,9 +544,9 @@ static unordered_map GetTarIncludes(const string &tarName) // 获取简报内容 BReportEntity rp(UniqueFd(open(reportName.data(), O_RDONLY))); - vector infos = rp.GetReportFileInfos(); + auto infos = rp.GetReportInfos(); for (auto iter : infos) { - includes.emplace(iter.filePath, true); + includes.emplace(iter.first, true); } return includes; diff --git a/utils/include/b_json/b_report_entity.h b/utils/include/b_json/b_report_entity.h index 7456bae21..15d573b48 100644 --- a/utils/include/b_json/b_report_entity.h +++ b/utils/include/b_json/b_report_entity.h @@ -43,45 +43,8 @@ const int64_t HASH_BUFFER_SIZE = 4096; // 每次读取的siz const int FILTER_LINE = 2; // 过滤前2行 } // namespace -enum ReportFileInfoAttr {FILE_PATH, MODE, IS_DIR, SIZE, MTIME, HASH}; class BReportEntity { public: - ErrCode ParseReportFileInfo(ReportFileInfo &info, const std::vector &attrs) - { - try { - if (attrs[FILE_PATH].empty()) { - HILOGE("Invalid filePath:%{public}s", attrs[FILE_PATH].c_str()); - return EPERM; - } - info.filePath = attrs[FILE_PATH]; - - if (!attrs[MODE].empty()) { - info.mode = attrs[MODE]; - } - - if (attrs[IS_DIR].empty()) { - HILOGE("Invalid isDir:%{public}s", attrs[IS_DIR].c_str()); - return EPERM; - } - info.isDir = atoi(attrs[IS_DIR].c_str()) == 1 ? true : false; - - if (!attrs[SIZE].empty()) { - info.size = static_cast(atol(attrs[SIZE].c_str())); - } - - if (!attrs[MTIME].empty()) { - info.mtime = static_cast(atol(attrs[MTIME].c_str())); - } - - info.hash = attrs[HASH]; - - return ERR_OK; - } catch (...) { - HILOGE("Failed to ParseReportFileInfo"); - return EPERM; - } - } - std::vector SplitStringByChar(const std::string &str, const char &sep) { std::vector eles = {}; @@ -95,89 +58,6 @@ public: return eles; } - ErrCode ParseInfoLine(const std::string &line) - { - try { - std::stringstream lineStream = std::stringstream(line); - std::stringstream infoStream; - std::string info = {}; - std::string key = {}; - std::vector keys = {}; - while (!lineStream.eof()) { - getline(lineStream, info, infoSep_); - keys.clear(); - keys = SplitStringByChar(info, infoAlign_); - if (keys.size() != INFO_ALIGN_NUM_) { - HILOGE("Failed to Parse info:%{public}s", info.c_str()); - continue; - } - if (keys[0] == VERSION_TAG_) { - version = keys[1]; - } else if (keys[0] == ATTR_NUM_TAG_) { - attrNum = atoi(keys[1].c_str()); - } else { - HILOGE("invalid info:%{public}s", info.c_str()); - } - } - - return ERR_OK; - } catch (...) { - HILOGE("Failed to ParseInfoLine"); - return EPERM; - } - } - - /** - * @brief 获取Report信息 - * - * @return std::vector - */ - std::vector GetReportFileInfos() - { - std::vector infos {}; - - std::unique_ptr rawBuf = BFile::ReadFile(srcFile_); - std::stringstream fileStream(rawBuf.get()); - std::string line; - std::stringstream lineStream; - std::string attr = {}; - std::vector attrs; - bool infoLine = false; - bool attrLine = false; - while (!fileStream.eof()) { - getline(fileStream, line, lineSep_); - - if (!line.empty()) { - if (!infoLine) { - infoLine = true; - ParseInfoLine(line); - continue; - } - if (!attrLine) { - attrLine = true; - continue; - } - - attrs.clear(); - attrs = SplitStringByChar(line, attrSep_); - if (attrs.size() != attrNum) { - HILOGE("Invalid line:%{public}s", line.c_str()); - continue; - } - ReportFileInfo info = {}; - auto code = ParseReportFileInfo(info, attrs); - if (code != ERR_OK) { - HILOGE("ParseReportFileInfo err:%{public}d %{public}s", code, line.c_str()); - continue; - } else { - infos.emplace_back(info); - } - } - } - - return infos; - } - ErrCode ParseReportInfo(struct ReportFileInfo &fileStat, const std::vector &splits, const std::unordered_map &keys) { -- Gitee From ab262684ef4f62a23d927c34e680d6210dc51f7d Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Sat, 30 Dec 2023 19:50:37 +0800 Subject: [PATCH 15/35] =?UTF-8?q?bug=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- interfaces/kits/js/BUILD.gn | 2 +- .../unittests/backup_utils/b_filesystem/b_file_test.cpp | 2 +- tools/backup_tool/src/tools_op_incremental_backup.cpp | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index 3b1649759..5feaca179 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -149,8 +149,8 @@ ohos_shared_library("backup") { "${path_backup_js}/backup/module.cpp", "${path_backup_js}/backup/prop_n_exporter.cpp", "${path_backup_js}/backup/session_backup_n_exporter.cpp", - "${path_backup_js}/backup/session_restore_n_exporter.cpp", "${path_backup_js}/backup/session_incremental_backup_n_exporter.cpp", + "${path_backup_js}/backup/session_restore_n_exporter.cpp", ] deps = [ diff --git a/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp b/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp index e253747f9..cf3cc122b 100644 --- a/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp +++ b/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp @@ -198,7 +198,7 @@ HWTEST_F(BFileTest, b_file_ReadIncrementalFile_0100, testing::ext::TestSize.Leve BFile::Write(UniqueFd(open(filePath.data(), O_RDWR)), fileInPath); vector> infos = BFile::ReadIncrementalFile(UniqueFd(open(fileInPath.c_str(), O_RDONLY))); string incrInfo = ""; - for (auto item : infos) { + for (auto info : infos) { string filePath = info.find("path") != info.end() ? info.find("path")->second : ""; string mode = info.find("mode") != info.end() ? info.find("mode")->second : ""; string dir = info.find("dir") != info.end() ? info.find("dir")->second : "0"; diff --git a/tools/backup_tool/src/tools_op_incremental_backup.cpp b/tools/backup_tool/src/tools_op_incremental_backup.cpp index 6721bfa7d..aa5cd4730 100644 --- a/tools/backup_tool/src/tools_op_incremental_backup.cpp +++ b/tools/backup_tool/src/tools_op_incremental_backup.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -129,8 +130,8 @@ static string GenHelpMsg() static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, UniqueFd fd, UniqueFd manifestFd) { - printf("FileReady owner = %s, fileName = %s, sn = %u, fd = %d, manifestFd = %d\n", fileInfo.owner.c_str(), - fileInfo.fileName.c_str(), fileInfo.sn, fd.Get(), manifestFd.Get()); + printf("FileReady owner = %s, fileName = %s, fd = %d, manifestFd = %d\n", fileInfo.owner.c_str(), + fileInfo.fileName.c_str(), fd.Get(), manifestFd.Get()); string tmpPath = string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + fileInfo.owner; if (access(tmpPath.data(), F_OK) != 0 && mkdir(tmpPath.data(), S_IRWXU) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); @@ -152,7 +153,7 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq // 简报文件保存 路径拼接方式: /data/backup/incrementalreceived/bundleName/时间戳/manifest/文件名.rp string tmpmanifestPath = tmpPath + string(BConstants::BACKUP_TOOL_MANIFEST); - if (access(tmpDataPath.data(), F_OK) != 0 && mkdir(tmpDataPath.data(), S_IRWXU) != 0) { + if (access(tmpmanifestPath.data(), F_OK) != 0 && mkdir(tmpmanifestPath.data(), S_IRWXU) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } UniqueFd fdManifest( @@ -160,7 +161,7 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq if (fdManifest < 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } - BFile::SendFile(fdManifest, fd); + BFile::SendFile(fdManifest, manifestFd); if (fileInfo.fileName == BConstants::EXT_BACKUP_MANAGE) { UniqueFd fullDatFd(open((string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + fileInfo.owner + string(BConstants::BACKUP_TOOL_MANIFEST).append(".rp")) -- Gitee From 38918630679328a1dca64a475fc5418c983b4811 Mon Sep 17 00:00:00 2001 From: yang-jingbo1985 Date: Tue, 2 Jan 2024 10:32:17 +0800 Subject: [PATCH 16/35] =?UTF-8?q?GetLoccapabilities=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20Signed-off-by:=20yangjingbo10=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/module_external/bms_adapter.cpp | 23 +++++++++++++------ .../src/module_ipc/service_incremental.cpp | 1 + 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/services/backup_sa/src/module_external/bms_adapter.cpp b/services/backup_sa/src/module_external/bms_adapter.cpp index 01f396490..88f2ebc25 100644 --- a/services/backup_sa/src/module_external/bms_adapter.cpp +++ b/services/backup_sa/src/module_external/bms_adapter.cpp @@ -220,6 +220,7 @@ static bool CreateIPCInteractionFiles(int32_t userId, const string &bundleName, return true; } + std::vector BundleMgrAdapter::GetBundleInfosForIncremental( const std::vector &incrementalDataList, int32_t userId) { @@ -252,20 +253,28 @@ std::vector BundleMgrAdapter::GetBundleInfosForIncr incrementalBackTimes.emplace_back(bundleNameTime.lastIncrementalTime); } - std::vector pkgFileSizes; - std::vector pkgStatPaths; - int32_t err = StorageMgrAdapter::GetBundleStatsForIncrease(userId, bundleNames , incrementalBackTimes, pkgFileSizes, pkgStatPaths); + std::vector pkgFileSizes {}; + std::vector pkgStatPaths {}; + int32_t err = StorageMgrAdapter::GetBundleStatsForIncrease(userId, bundleNames, incrementalBackTimes, pkgFileSizes, pkgStatPaths); if (err != 0) { HILOGE("Failed to get bundleStats result"); return {}; } - std::vector newBundleInfos; - for (size_t i = 0; bundleInfos.size(); i++) { - BJsonEntityCaps::BundleInfo newBundleInfo = bundleInfos[i]; - newBundleInfo.spaceOccupied = pkgFileSizes[i]; + vector newBundleInfos {}; + for (size_t i = 0; i < bundleInfos.size(); i++) { + HILOGI("BundleMgrAdapter name for %{public}s", bundleInfos[i].name.c_str()); + BJsonEntityCaps::BundleInfo newBundleInfo = {.name = bundleInfos[i].name, + .versionCode = bundleInfos[i].versionCode, + .versionName = bundleInfos[i].versionName, + .spaceOccupied = pkgFileSizes[i], + .allToBackup = bundleInfos[i].allToBackup, + .extensionName = bundleInfos[i].extensionName, + .restoreDeps = bundleInfos[i].restoreDeps, + .supportScene = bundleInfos[i].supportScene}; newBundleInfos.emplace_back(newBundleInfo); } + HILOGI("BundleMgrAdapter GetBundleInfosForIncremental end "); return newBundleInfos; } } // namespace OHOS::FileManagement::Backup diff --git a/services/backup_sa/src/module_ipc/service_incremental.cpp b/services/backup_sa/src/module_ipc/service_incremental.cpp index f5526598e..8d24f2d60 100644 --- a/services/backup_sa/src/module_ipc/service_incremental.cpp +++ b/services/backup_sa/src/module_ipc/service_incremental.cpp @@ -101,6 +101,7 @@ UniqueFd Service::GetLocalCapabilitiesIncremental(const std::vectorGetSessionUserId()); cache.SetBundleInfos(bundleInfos); cachedEntity.Persist(); + HILOGI("Service GetLocalCapabilitiesIncremental persist"); session_->DecreaseSessionCnt(); return move(cachedEntity.GetFd()); } catch (const BError &e) { -- Gitee From 78371dfd65a522881c04b8a2159b9c932e318347 Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Tue, 2 Jan 2024 11:11:23 +0800 Subject: [PATCH 17/35] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=A2=9E=E9=87=8F?= =?UTF-8?q?=E5=A4=87=E4=BB=BDbackup=5Ftool=E5=B7=A5=E5=85=B7fd=E6=8A=A5?= =?UTF-8?q?=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- tools/backup_tool/src/tools_op_incremental_backup.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/backup_tool/src/tools_op_incremental_backup.cpp b/tools/backup_tool/src/tools_op_incremental_backup.cpp index aa5cd4730..ca0cf1a1d 100644 --- a/tools/backup_tool/src/tools_op_incremental_backup.cpp +++ b/tools/backup_tool/src/tools_op_incremental_backup.cpp @@ -157,7 +157,7 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } UniqueFd fdManifest( - open((tmpmanifestPath + "/" + fileInfo.fileName + ".rp").data(), O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU)); + open((tmpmanifestPath + "/" + fileInfo.fileName + ".rp").data(), O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)); if (fdManifest < 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } @@ -166,7 +166,7 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq UniqueFd fullDatFd(open((string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + fileInfo.owner + string(BConstants::BACKUP_TOOL_MANIFEST).append(".rp")) .data(), - O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU)); + O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)); BFile::SendFile(fullDatFd, fdManifest); ctx->SetIndexFiles(fileInfo.owner, move(fd)); } else { -- Gitee From d3665bb491b9d31e4989883a871ffe5e7a43ca57 Mon Sep 17 00:00:00 2001 From: zhuruigan Date: Tue, 2 Jan 2024 11:12:05 +0800 Subject: [PATCH 18/35] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhuruigan --- tests/mock/b_filesystem/b_file_mock.cpp | 6 -- .../backup_utils/b_filesystem/b_file_test.cpp | 37 ------------- utils/include/b_filesystem/b_file.h | 7 --- utils/src/b_filesystem/b_file.cpp | 55 ------------------- 4 files changed, 105 deletions(-) diff --git a/tests/mock/b_filesystem/b_file_mock.cpp b/tests/mock/b_filesystem/b_file_mock.cpp index 1e80a11dd..d3561215a 100644 --- a/tests/mock/b_filesystem/b_file_mock.cpp +++ b/tests/mock/b_filesystem/b_file_mock.cpp @@ -83,10 +83,4 @@ bool BFile::CopyFile(const string &from, const string &to) { return true; } - -vector> BFile::ReadIncrementalFile(const UniqueFd &fd) -{ - vector> infos; - return infos; -} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp b/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp index cf3cc122b..1aaa78956 100644 --- a/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp +++ b/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp @@ -177,41 +177,4 @@ static tuple GetTestIncrementalFile(const TestManager &tm) } return {filePath, info}; } - -/** - * @tc.number: SUB_backup_b_file_ReadIncrementalFile_0100 - * @tc.name: b_file_ReadIncrementalFile_0100 - * @tc.desc: 测试ReadIncrementalFile接口 - * @tc.size: MEDIUM - * @tc.type: FUNC - * @tc.level Level 1 - * @tc.require: I6F3GV - */ -HWTEST_F(BFileTest, b_file_ReadIncrementalFile_0100, testing::ext::TestSize.Level1) -{ - GTEST_LOG_(INFO) << "BFileTest-begin b_file_ReadIncrementalFile_0100"; - try { - TestManager tm(__func__); - const auto [filePath, content] = GetTestFile(tm); - TestManager tmInFile("b_file_ReadIncrementalFile_0100"); - string fileInPath = tmInFile.GetRootDirCurTest().append("1.txt"); - BFile::Write(UniqueFd(open(filePath.data(), O_RDWR)), fileInPath); - vector> infos = BFile::ReadIncrementalFile(UniqueFd(open(fileInPath.c_str(), O_RDONLY))); - string incrInfo = ""; - for (auto info : infos) { - string filePath = info.find("path") != info.end() ? info.find("path")->second : ""; - string mode = info.find("mode") != info.end() ? info.find("mode")->second : ""; - string dir = info.find("dir") != info.end() ? info.find("dir")->second : "0"; - string size = info.find("size") != info.end() ? stoll(info.find("size")->second) : "0"; - string mtime = info.find("mtime") != info.end() ? info.find("mtime")->second : "0"; - string hash = info.find("hash") != info.end() ? info.find("hash")->second : ""; - incrInfo += filePath + ";" + mode + ";" + dir + ";" + size + ";" + mtime + ";" + hash + ";"; - } - EXPECT_EQ(incrInfo, content); - } catch (const exception &e) { - GTEST_LOG_(INFO) << "BFileTest-an exception occurred by Write."; - e.what(); - } - GTEST_LOG_(INFO) << "BFileTest-end b_file_ReadIncrementalFile_0100"; -} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/utils/include/b_filesystem/b_file.h b/utils/include/b_filesystem/b_file.h index a2f958fb7..863f4ad4b 100644 --- a/utils/include/b_filesystem/b_file.h +++ b/utils/include/b_filesystem/b_file.h @@ -61,13 +61,6 @@ public: */ static bool CopyFile(const string &from, const string &to); - /** - * @brief read incremental file info - * - * @param fd UniqueFd - */ - static vector> ReadIncrementalFile(const UniqueFd &fd); - private: }; } // namespace OHOS::FileManagement::Backup diff --git a/utils/src/b_filesystem/b_file.cpp b/utils/src/b_filesystem/b_file.cpp index eb6804dd3..db1a4de00 100644 --- a/utils/src/b_filesystem/b_file.cpp +++ b/utils/src/b_filesystem/b_file.cpp @@ -142,59 +142,4 @@ bool BFile::CopyFile(const string &from, const string &to) } return false; } - -static vector SplitString(string str, char sep) -{ - stringstream ss(str); - string line; - vector splitArr; - while (!ss.eof()) { - getline(ss, line, sep); - if (!line.empty() || sep == ';') { - splitArr.push_back(line); - } - } - return splitArr; -} - -vector> BFile::ReadIncrementalFile(const UniqueFd &fd) -{ - string content = ReadFile(fd).get(); - vector> infos; - - vector lines = SplitString(content, '\n'); - if (lines.begin() == lines.end()) { - return infos; - } - // 对第2行的数据做切分 - vector keys = SplitString(lines[1], ';'); - int num = (int)keys.size() - 1; - - for (int i = 2; i < (int)lines.size(); i++) { - map info; - // 如果结尾有;,就删除后再切分 - string newLine = lines[i]; - if (newLine[newLine.length() - 1] == ';') { - newLine = newLine.substr(0, newLine.length() - 1); - } - - vector words = SplitString(newLine, ';'); - if (words.begin() == words.end()) { - continue; - } - string filePath = ""; - int len = words.size(); - for (int j = 1; j < (int)keys.size(); j++) { - int index = len - num - 1 + j; - info.try_emplace(keys[j], words[index]); - } - for (int j = 0; j < len - num; j++) { - filePath += words[j] + ";"; - } - filePath = filePath.substr(0, filePath.length() - 1); - info.try_emplace(keys[0], filePath); - infos.emplace_back(info); - } - return infos; -} } // namespace OHOS::FileManagement::Backup \ No newline at end of file -- Gitee From 54f7de1b5d836daaaeacff217b738749a7de4847 Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Tue, 2 Jan 2024 17:53:28 +0800 Subject: [PATCH 19/35] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=A2=9E=E9=87=8F?= =?UTF-8?q?=E5=A4=87=E4=BB=BD=E6=81=A2=E5=A4=8Dbackup=5Ftool=20=E5=A4=9A?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- .../src/tools_op_incremental_backup.cpp | 55 +++++++------- .../src/tools_op_incremental_restore.cpp | 74 +++++++++++-------- 2 files changed, 74 insertions(+), 55 deletions(-) diff --git a/tools/backup_tool/src/tools_op_incremental_backup.cpp b/tools/backup_tool/src/tools_op_incremental_backup.cpp index ca0cf1a1d..53cf4f6c6 100644 --- a/tools/backup_tool/src/tools_op_incremental_backup.cpp +++ b/tools/backup_tool/src/tools_op_incremental_backup.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2024 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 @@ -117,7 +117,7 @@ private: public: std::atomic isAllBundelsFinished {false}; - string lastIncrementalTime; + vector lastIncrementalData {}; }; static string GenHelpMsg() @@ -136,7 +136,12 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq if (access(tmpPath.data(), F_OK) != 0 && mkdir(tmpPath.data(), S_IRWXU) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } - tmpPath = tmpPath + "/" + ctx->lastIncrementalTime; + auto iter = find_if(ctx->lastIncrementalData.begin(), ctx->lastIncrementalData.end(), + [bundleName {fileInfo.owner}](const auto &data) { return bundleName == data.bundleName; }); + if (iter == ctx->lastIncrementalData.end()) { + throw BError(BError::Codes::TOOL_INVAL_ARG); + } + tmpPath = tmpPath + "/" + to_string(iter->lastIncrementalTime); if (access(tmpPath.data(), F_OK) != 0 && mkdir(tmpPath.data(), S_IRWXU) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } @@ -246,10 +251,15 @@ static void BackupToolDirSoftlinkToBackupDir() } } -static int GetLocalCapabilitiesIncremental(const string &pathCapFile, +static int GetLocalCapabilitiesIncremental(shared_ptr ctx, + const string &pathCapFile, const vector &bundleNames, - const string &time) + const vector ×) { + if (bundleNames.size() != times.size()) { + fprintf(stderr, "Inconsistent amounts of bundles and incrementalTime!\n"); + return -EPERM; + } UniqueFd fdLocal(open(pathCapFile.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)); if (fdLocal < 0) { fprintf(stderr, "Failed to open file. error: %d %s\n", errno, strerror(errno)); @@ -260,14 +270,15 @@ static int GetLocalCapabilitiesIncremental(const string &pathCapFile, fprintf(stderr, "Get an empty backup sa proxy\n"); return -EPERM; } - vector bundlesToBackup; + int num = 0; for (auto &bundleName : bundleNames) { BIncrementalData data; data.bundleName = bundleName; - data.lastIncrementalTime = atoi(time.c_str()); - bundlesToBackup.push_back(data); + data.lastIncrementalTime = atoi(times[num].c_str()); + ctx->lastIncrementalData.push_back(data); + num++; } - int fd = proxy->GetLocalCapabilitiesIncremental(bundlesToBackup); + UniqueFd fd = proxy->GetLocalCapabilitiesIncremental(ctx->lastIncrementalData); if (fd < 0) { fprintf(stderr, "error GetLocalCapabilitiesIncremental"); } else { @@ -276,16 +287,12 @@ static int GetLocalCapabilitiesIncremental(const string &pathCapFile, return 0; } -static int32_t Init(const string &pathCapFile, vector bundleNames, const string &time) +static int32_t Init(const string &pathCapFile, vector bundleNames, vector times) { StartTrace(HITRACE_TAG_FILEMANAGEMENT, "InitPathCapFile"); // SELinux backup_tool工具/data/文件夹下创建文件夹 SA服务因root用户的自定义标签无写入权限 此处调整为软链接形式 BackupToolDirSoftlinkToBackupDir(); - if (int ret = GetLocalCapabilitiesIncremental(pathCapFile, bundleNames, time); ret != 0) { - return ret; - } - auto ctx = make_shared(); ctx->session_ = BIncrementalBackupSession::Init(BIncrementalBackupSession::Callbacks { .onFileReady = bind(OnFileReady, ctx, placeholders::_1, placeholders::_2, placeholders::_3), @@ -298,21 +305,20 @@ static int32_t Init(const string &pathCapFile, vector bundleNames, const FinishTrace(HITRACE_TAG_FILEMANAGEMENT); return -EPERM; } - ctx->lastIncrementalTime = time; + + if (int ret = GetLocalCapabilitiesIncremental(ctx, pathCapFile, bundleNames, times); ret != 0) { + return ret; + } vector bundlesToBackup; - for (auto &bundleName : bundleNames) { - BIncrementalData data; - data.bundleName = bundleName; - data.lastIncrementalTime = atoi(time.c_str()); - string tmpPath = string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + bundleName; + for (auto &data : ctx->lastIncrementalData) { + string tmpPath = string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + data.bundleName; if (access(tmpPath.data(), F_OK) != 0 && mkdir(tmpPath.data(), S_IRWXU) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } tmpPath = tmpPath + string(BConstants::BACKUP_TOOL_MANIFEST).append(".rp"); data.manifestFd = open(tmpPath.data(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - bundlesToBackup.push_back(data); } - int ret = ctx->session_->AppendBundles(bundlesToBackup); + int ret = ctx->session_->AppendBundles(ctx->lastIncrementalData); if (ret != 0) { printf("backup append bundles error: %d\n", ret); throw BError(BError::Codes::TOOL_INVAL_ARG, "backup append bundles error"); @@ -331,8 +337,7 @@ static int Exec(map> &mapArgToVal) mapArgToVal.find("incrementalTime") == mapArgToVal.end()) { return -EPERM; } - return Init(*(mapArgToVal["pathCapFile"].begin()), mapArgToVal["bundles"], - *(mapArgToVal["incrementalTime"].begin())); + return Init(*(mapArgToVal["pathCapFile"].begin()), mapArgToVal["bundles"], mapArgToVal["incrementalTime"]); } bool IncrementalBackUpRegister() @@ -349,7 +354,7 @@ bool IncrementalBackUpRegister() }, { .paramName = "incrementalTime", - .repeatable = false, + .repeatable = true, }}, .funcGenHelpMsg = GenHelpMsg, .funcExec = Exec, diff --git a/tools/backup_tool/src/tools_op_incremental_restore.cpp b/tools/backup_tool/src/tools_op_incremental_restore.cpp index ec070184a..d90646ffb 100644 --- a/tools/backup_tool/src/tools_op_incremental_restore.cpp +++ b/tools/backup_tool/src/tools_op_incremental_restore.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2024 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 @@ -111,7 +111,7 @@ private: public: std::atomic isAllBundelsFinished {false}; - string lastIncrementalTime; + vector lastIncrementalData {}; }; static string GenHelpMsg() @@ -128,9 +128,15 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq if (fileInfo.fileName.find('/') != string::npos) { throw BError(BError::Codes::TOOL_INVAL_ARG, "Filename is not valid"); } + auto iter = find_if(ctx->lastIncrementalData.begin(), ctx->lastIncrementalData.end(), + [bundleName {fileInfo.owner}](const auto &data) { return bundleName == data.bundleName; }); + if (iter == ctx->lastIncrementalData.end()) { + throw BError(BError::Codes::TOOL_INVAL_ARG); + } // 待恢复文件 路径拼接方式: /data/backup/incrementalreceived/bundleName/时间戳/incremental/文件名 string tmpPath = string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + fileInfo.owner + "/" + - ctx->lastIncrementalTime + string(BConstants::BACKUP_TOOL_INCREMENTAL) + "/" + fileInfo.fileName; + to_string(iter->lastIncrementalTime) + string(BConstants::BACKUP_TOOL_INCREMENTAL) + "/" + + fileInfo.fileName; printf("tmpPath = %s\n", tmpPath.data()); if (access(tmpPath.data(), F_OK) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); @@ -142,16 +148,16 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq BFile::SendFile(fd, fdLocal); // manifest文件 路径拼接方式: /data/backup/incrementalreceived/bundleName/时间戳/manifest/文件名.rp tmpPath = string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + fileInfo.owner + "/" + - ctx->lastIncrementalTime + string(BConstants::BACKUP_TOOL_MANIFEST) + "/" + fileInfo.fileName + ".rp"; + to_string(iter->lastIncrementalTime) + string(BConstants::BACKUP_TOOL_MANIFEST) + "/" + + fileInfo.fileName + ".rp"; printf("tmpPath = %s\n", tmpPath.data()); - if (access(tmpPath.data(), F_OK) != 0) { - throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); - } - UniqueFd fdManifest(open(tmpPath.data(), O_RDONLY)); - if (fdManifest < 0) { - throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + if (access(tmpPath.data(), F_OK) == 0) { + UniqueFd fdManifest(open(tmpPath.data(), O_RDONLY)); + if (fdManifest < 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + } + BFile::SendFile(manifestFd, fdManifest); } - BFile::SendFile(manifestFd, fdManifest); // 文件准备完成 int ret = ctx->session_->PublishFile(fileInfo); if (ret != 0) { @@ -201,18 +207,15 @@ static void OnBackupServiceDied(shared_ptr ctx) ctx->TryNotify(true); } -static void RestoreApp(shared_ptr restore, vector &bundleNames) +static void RestoreApp(shared_ptr restore) { StartTrace(HITRACE_TAG_FILEMANAGEMENT, "RestoreApp"); if (!restore || !restore->session_) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } - for (auto &bundleName : bundleNames) { - if (bundleName.find('/') != string::npos) { - throw BError(BError::Codes::TOOL_INVAL_ARG, "Filename is not valid"); - } - string path = string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + bundleName + "/" + - restore->lastIncrementalTime + string(BConstants::BACKUP_TOOL_INCREMENTAL); + for (auto &data : restore->lastIncrementalData) { + string path = string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + data.bundleName + "/" + + to_string(data.lastIncrementalTime) + string(BConstants::BACKUP_TOOL_INCREMENTAL); if (access(path.data(), F_OK) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } @@ -222,9 +225,9 @@ static void RestoreApp(shared_ptr restore, vector &bundleNa } for (auto &filePath : filePaths) { string fileName = filePath.substr(filePath.rfind("/") + 1); - restore->session_->GetFileHandle(bundleName, fileName); - printf("GetFileHandle bundleName = %s, fileName = %s\n", bundleName.c_str(), fileName.c_str()); - restore->UpdateBundleSendFiles(bundleName, fileName); + restore->session_->GetFileHandle(data.bundleName, fileName); + printf("GetFileHandle bundleName = %s, fileName = %s\n", data.bundleName.c_str(), fileName.c_str()); + restore->UpdateBundleSendFiles(data.bundleName, fileName); } } FinishTrace(HITRACE_TAG_FILEMANAGEMENT); @@ -245,10 +248,14 @@ static bool GetRealPath(string &path) return true; } -static int32_t InitRestoreSession(shared_ptr ctx) +static int32_t InitRestoreSession(shared_ptr ctx, vector &bundleNames, vector ×) { + if (bundleNames.size() != times.size()) { + fprintf(stderr, "Inconsistent amounts of bundles and incrementalTime!\n"); + return -EPERM; + } if (!ctx) { - throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); + return -EPERM; } ctx->session_ = BIncrementalRestoreSession::Init(BIncrementalRestoreSession::Callbacks { .onFileReady = bind(OnFileReady, ctx, placeholders::_1, placeholders::_2, placeholders::_3), @@ -261,10 +268,19 @@ static int32_t InitRestoreSession(shared_ptr ctx) FinishTrace(HITRACE_TAG_FILEMANAGEMENT); return -EPERM; } + + int num = 0; + for (auto &bundleName : bundleNames) { + BIncrementalData data; + data.bundleName = bundleName; + data.lastIncrementalTime = atoi(times[num].c_str()); + ctx->lastIncrementalData.push_back(data); + num++; + } return 0; } -static int32_t Init(const string &pathCapFile, vector bundleNames, bool depMode, const string &time) +static int32_t Init(const string &pathCapFile, vector bundleNames, bool depMode, vector times) { StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Init"); string realPath = pathCapFile; @@ -275,7 +291,7 @@ static int32_t Init(const string &pathCapFile, vector bundleNames, bool UniqueFd fd(open(realPath.data(), O_RDWR, S_IRWXU)); auto ctx = make_shared(); - int32_t ret = InitRestoreSession(ctx); + int32_t ret = InitRestoreSession(ctx, bundleNames, times); if (ret != 0) { printf("Failed to init restore session error:%d\n", ret); return ret; @@ -302,9 +318,8 @@ static int32_t Init(const string &pathCapFile, vector bundleNames, bool return -ret; } } - ctx->lastIncrementalTime = time; ctx->SetBundleFinishedCount(bundleNames.size()); - RestoreApp(ctx, bundleNames); + RestoreApp(ctx); ctx->Wait(); ctx->session_->Release(); return 0; @@ -322,8 +337,7 @@ static int Exec(map> &mapArgToVal) mapArgToVal.find("incrementalTime") == mapArgToVal.end()) { return -EPERM; } - return Init(*(mapArgToVal["pathCapFile"].begin()), mapArgToVal["bundles"], depMode, - *(mapArgToVal["incrementalTime"].begin())); + return Init(*(mapArgToVal["pathCapFile"].begin()), mapArgToVal["bundles"], depMode, mapArgToVal["incrementalTime"]); } bool IncrementalRestoreRegister() @@ -344,7 +358,7 @@ bool IncrementalRestoreRegister() }, { .paramName = "incrementalTime", - .repeatable = false, + .repeatable = true, }}, .funcGenHelpMsg = GenHelpMsg, .funcExec = Exec, -- Gitee From 8d4e32f63713bfcc466658ee7b43124f693c8fac Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Tue, 2 Jan 2024 18:05:07 +0800 Subject: [PATCH 20/35] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=A2=9E=E9=87=8F?= =?UTF-8?q?=E5=A4=87=E4=BB=BD=E6=96=87=E4=BB=B6=E6=B8=85=E5=8D=95=E4=BC=A0?= =?UTF-8?q?=E9=80=92=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- .../native/backup_ext/include/ext_extension.h | 1 + .../backup_ext/include/ext_extension_stub.h | 1 + .../native/backup_ext/src/ext_extension.cpp | 5 + .../backup_ext/src/ext_extension_stub.cpp | 15 +++ .../backup_kit_inner/impl/i_extension.h | 1 + .../impl/i_extension_ipc_interface_code.h | 1 + services/backup_sa/BUILD.gn | 1 + .../include/module_ipc/svc_extension_proxy.h | 1 + .../src/module_ipc/service_incremental.cpp | 9 +- .../svc_extension_incremental_proxy.cpp | 121 ++++++++++++++++++ .../src/module_ipc/svc_extension_proxy.cpp | 73 ----------- .../module_ipc/svc_extension_proxy_mock.cpp | 5 + .../backup_impl/include/ext_extension_mock.h | 5 + 13 files changed, 163 insertions(+), 76 deletions(-) create mode 100644 services/backup_sa/src/module_ipc/svc_extension_incremental_proxy.cpp diff --git a/frameworks/native/backup_ext/include/ext_extension.h b/frameworks/native/backup_ext/include/ext_extension.h index 296c609a4..cc17b1d38 100644 --- a/frameworks/native/backup_ext/include/ext_extension.h +++ b/frameworks/native/backup_ext/include/ext_extension.h @@ -38,6 +38,7 @@ public: ErrCode GetIncrementalFileHandle(const std::string &fileName) override; ErrCode PublishIncrementalFile(const std::string &fileName) override; ErrCode HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) override; + std::tuple GetIncrementalBackupFileHandle() override; void AsyncTaskRestoreForUpgrade(void); void AsyncTaskIncrementalRestoreForUpgrade(void); diff --git a/frameworks/native/backup_ext/include/ext_extension_stub.h b/frameworks/native/backup_ext/include/ext_extension_stub.h index 08ccc2a88..97dabc07c 100644 --- a/frameworks/native/backup_ext/include/ext_extension_stub.h +++ b/frameworks/native/backup_ext/include/ext_extension_stub.h @@ -39,6 +39,7 @@ private: ErrCode CmdGetIncrementalFileHandle(MessageParcel &data, MessageParcel &reply); ErrCode CmdPublishIncrementalFile(MessageParcel &data, MessageParcel &reply); ErrCode CmdHandleIncrementalBackup(MessageParcel &data, MessageParcel &reply); + ErrCode CmdGetIncrementalBackupFileHandle(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 b4cd4f1e7..b2cd4e37a 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -1301,6 +1301,11 @@ ErrCode BackupExtExtension::HandleIncrementalBackup(UniqueFd incrementalFd, Uniq return 0; } +tuple BackupExtExtension::GetIncrementalBackupFileHandle() +{ + return {UniqueFd(-1), UniqueFd(-1)}; +} + void BackupExtExtension::AsyncTaskOnIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) { auto task = [obj {wptr(this)}, ifd(incrementalFd.Get()), mfd(manifestFd.Get())]() { diff --git a/frameworks/native/backup_ext/src/ext_extension_stub.cpp b/frameworks/native/backup_ext/src/ext_extension_stub.cpp index 373caeefa..e01c1ef0e 100644 --- a/frameworks/native/backup_ext/src/ext_extension_stub.cpp +++ b/frameworks/native/backup_ext/src/ext_extension_stub.cpp @@ -43,6 +43,8 @@ ExtExtensionStub::ExtExtensionStub() &ExtExtensionStub::CmdPublishIncrementalFile; opToInterfaceMap_[static_cast(IExtensionInterfaceCode::CMD_HANDLE_INCREMENTAL_BACKUP)] = &ExtExtensionStub::CmdHandleIncrementalBackup; + opToInterfaceMap_[static_cast(IExtensionInterfaceCode::CMD_GET_INCREMENTAL_BACKUP_FILE_HANDLE)] = + &ExtExtensionStub::CmdGetIncrementalBackupFileHandle; } int32_t ExtExtensionStub::OnRemoteRequest(uint32_t code, @@ -180,4 +182,17 @@ ErrCode ExtExtensionStub::CmdHandleIncrementalBackup(MessageParcel &data, Messag } return BError(BError::Codes::OK); } + +ErrCode ExtExtensionStub::CmdGetIncrementalBackupFileHandle(MessageParcel &data, MessageParcel &reply) +{ + HILOGI("Begin"); + auto [incrementalFd, manifestFd] = GetIncrementalBackupFileHandle(); + if (!reply.WriteFileDescriptor(incrementalFd)) { + return BError(BError::Codes::EXT_BROKEN_IPC, "Failed to send out the file").GetCode(); + } + if (!reply.WriteFileDescriptor(manifestFd)) { + return BError(BError::Codes::EXT_BROKEN_IPC, "Failed to send out the file").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 c21393e67..b2604948c 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 @@ -35,6 +35,7 @@ public: virtual ErrCode GetIncrementalFileHandle(const std::string &fileName) = 0; virtual ErrCode PublishIncrementalFile(const std::string &fileName) = 0; virtual ErrCode HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) = 0; + virtual std::tuple GetIncrementalBackupFileHandle() = 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 091f87107..e9e63c21e 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 @@ -27,6 +27,7 @@ enum class IExtensionInterfaceCode { CMD_GET_INCREMENTAL_FILE_HANDLE, CMD_PUBLISH_INCREMENTAL_FILE, CMD_HANDLE_INCREMENTAL_BACKUP, + CMD_GET_INCREMENTAL_BACKUP_FILE_HANDLE, }; } // namespace OHOS::FileManagement::Backup diff --git a/services/backup_sa/BUILD.gn b/services/backup_sa/BUILD.gn index 6a42bd130..119eb3a22 100644 --- a/services/backup_sa/BUILD.gn +++ b/services/backup_sa/BUILD.gn @@ -35,6 +35,7 @@ ohos_shared_library("backup_sa") { "src/module_ipc/service_reverse_proxy.cpp", "src/module_ipc/service_stub.cpp", "src/module_ipc/svc_backup_connection.cpp", + "src/module_ipc/svc_extension_incremental_proxy.cpp", "src/module_ipc/svc_extension_proxy.cpp", "src/module_ipc/svc_restore_deps_manager.cpp", "src/module_ipc/svc_session_manager.cpp", 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 ac48221f0..bfbf52c23 100644 --- a/services/backup_sa/include/module_ipc/svc_extension_proxy.h +++ b/services/backup_sa/include/module_ipc/svc_extension_proxy.h @@ -31,6 +31,7 @@ public: ErrCode GetIncrementalFileHandle(const std::string &fileName) override; ErrCode PublishIncrementalFile(const std::string &fileName) override; ErrCode HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) override; + std::tuple GetIncrementalBackupFileHandle() override; public: explicit SvcExtensionProxy(const sptr &remote) : IRemoteProxy(remote) {} diff --git a/services/backup_sa/src/module_ipc/service_incremental.cpp b/services/backup_sa/src/module_ipc/service_incremental.cpp index 8d24f2d60..dce49baa4 100644 --- a/services/backup_sa/src/module_ipc/service_incremental.cpp +++ b/services/backup_sa/src/module_ipc/service_incremental.cpp @@ -325,6 +325,7 @@ bool Service::IncrementalBackup(const string &bundleName) throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty"); } if (scenario == IServiceReverse::Scenario::BACKUP && session_->GetIsIncrementalBackup()) { + auto [incrementalFd, manifestFd] = proxy->GetIncrementalBackupFileHandle(); // 本地全量数据 string path = BConstants::GetSaBundleBackupRootDir(session_->GetSessionUserId()) .append(bundleName) @@ -332,10 +333,12 @@ bool Service::IncrementalBackup(const string &bundleName) .append(BConstants::BACKUP_STAT_SYMBOL) .append(to_string(session_->GetLastIncrementalTime(bundleName))); HILOGI("path = %{public}s", path.c_str()); - UniqueFd fd(open(path.data(), O_RDWR, S_IRGRP | S_IWGRP | S_IRGRP | S_IWGRP)); + UniqueFd fdLocal(open(path.data(), O_RDWR, S_IRGRP | S_IWGRP | S_IRGRP | S_IWGRP)); + BFile::SendFile(incrementalFd, fdLocal); // 云上存在的数据 - UniqueFd manifestFd(session_->GetIncrementalManifestFd(bundleName)); - auto ret = proxy->HandleIncrementalBackup(move(fd), move(manifestFd)); + UniqueFd lastManifestFd(session_->GetIncrementalManifestFd(bundleName)); + BFile::SendFile(manifestFd, lastManifestFd); + auto ret = proxy->HandleIncrementalBackup(UniqueFd(-1), UniqueFd(-1)); session_->GetServiceReverseProxy()->IncrementalBackupOnBundleStarted(ret, bundleName); if (ret) { ClearSessionAndSchedInfo(bundleName); 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 new file mode 100644 index 000000000..8833cda5b --- /dev/null +++ b/services/backup_sa/src/module_ipc/svc_extension_incremental_proxy.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "module_ipc/svc_extension_proxy.h" + +#include "b_error/b_error.h" +#include "b_error/b_excep_utils.h" +#include "filemgmt_libhilog.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; + +ErrCode SvcExtensionProxy::GetIncrementalFileHandle(const string &fileName) +{ + HILOGI("Start"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + data.WriteInterfaceToken(GetDescriptor()); + + if (!data.WriteString(fileName)) { + BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the fileName"); + return ErrCode(EPERM); + } + + MessageParcel reply; + MessageOption option; + int32_t ret = Remote()->SendRequest(static_cast(IExtensionInterfaceCode::CMD_GET_INCREMENTAL_FILE_HANDLE), + data, reply, option); + if (ret != NO_ERROR) { + HILOGE("Received error %{public}d when doing IPC", ret); + return ErrCode(ret); + } + + HILOGI("Successful"); + return reply.ReadInt32(); +} + +ErrCode SvcExtensionProxy::PublishIncrementalFile(const string &fileName) +{ + HILOGI("Start"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + data.WriteInterfaceToken(GetDescriptor()); + + if (!data.WriteString(fileName)) { + BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the fileName"); + return ErrCode(EPERM); + } + + MessageParcel reply; + MessageOption option; + int32_t ret = Remote()->SendRequest(static_cast(IExtensionInterfaceCode::CMD_PUBLISH_INCREMENTAL_FILE), + data, reply, option); + if (ret != NO_ERROR) { + HILOGE("Received error %{public}d when doing IPC", ret); + return ErrCode(ret); + } + + HILOGI("Successful"); + return reply.ReadInt32(); +} + +ErrCode SvcExtensionProxy::HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) +{ + HILOGI("Start"); + BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); + MessageParcel data; + data.WriteInterfaceToken(GetDescriptor()); + + data.WriteFileDescriptor(incrementalFd); + data.WriteFileDescriptor(manifestFd); + + MessageParcel reply; + MessageOption option; + int32_t ret = Remote()->SendRequest(static_cast(IExtensionInterfaceCode::CMD_HANDLE_INCREMENTAL_BACKUP), + data, reply, option); + if (ret != NO_ERROR) { + HILOGE("Received error %{public}d when doing IPC", ret); + return ErrCode(ret); + } + + HILOGI("Successful"); + return reply.ReadInt32(); +} + +tuple SvcExtensionProxy::GetIncrementalBackupFileHandle() +{ + HILOGI("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_GET_INCREMENTAL_BACKUP_FILE_HANDLE), data, reply, option); + if (ret != NO_ERROR) { + HILOGE("Received error %{public}d when doing IPC", ret); + return {UniqueFd(-1), UniqueFd(-1)}; + } + + HILOGI("Successful"); + UniqueFd incrementalFd(reply.ReadFileDescriptor()); + UniqueFd manifestFd(reply.ReadFileDescriptor()); + return {move(incrementalFd), move(manifestFd)}; +} +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/services/backup_sa/src/module_ipc/svc_extension_proxy.cpp b/services/backup_sa/src/module_ipc/svc_extension_proxy.cpp index 0eec93ecb..8d1c9276c 100644 --- a/services/backup_sa/src/module_ipc/svc_extension_proxy.cpp +++ b/services/backup_sa/src/module_ipc/svc_extension_proxy.cpp @@ -134,77 +134,4 @@ ErrCode SvcExtensionProxy::HandleRestore() HILOGI("Successful"); return reply.ReadInt32(); } - -ErrCode SvcExtensionProxy::GetIncrementalFileHandle(const string &fileName) -{ - HILOGI("Start"); - BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); - MessageParcel data; - data.WriteInterfaceToken(GetDescriptor()); - - if (!data.WriteString(fileName)) { - BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the fileName"); - return ErrCode(EPERM); - } - - MessageParcel reply; - MessageOption option; - int32_t ret = Remote()->SendRequest(static_cast(IExtensionInterfaceCode::CMD_GET_INCREMENTAL_FILE_HANDLE), - data, reply, option); - if (ret != NO_ERROR) { - HILOGE("Received error %{public}d when doing IPC", ret); - return ErrCode(ret); - } - - HILOGI("Successful"); - return reply.ReadInt32(); -} - -ErrCode SvcExtensionProxy::PublishIncrementalFile(const string &fileName) -{ - HILOGI("Start"); - BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); - MessageParcel data; - data.WriteInterfaceToken(GetDescriptor()); - - if (!data.WriteString(fileName)) { - BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the fileName"); - return ErrCode(EPERM); - } - - MessageParcel reply; - MessageOption option; - int32_t ret = Remote()->SendRequest(static_cast(IExtensionInterfaceCode::CMD_PUBLISH_INCREMENTAL_FILE), - data, reply, option); - if (ret != NO_ERROR) { - HILOGE("Received error %{public}d when doing IPC", ret); - return ErrCode(ret); - } - - HILOGI("Successful"); - return reply.ReadInt32(); -} - -ErrCode SvcExtensionProxy::HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) -{ - HILOGI("Start"); - BExcepUltils::BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); - MessageParcel data; - data.WriteInterfaceToken(GetDescriptor()); - - data.WriteFileDescriptor(incrementalFd); - data.WriteFileDescriptor(manifestFd); - - MessageParcel reply; - MessageOption option; - int32_t ret = Remote()->SendRequest(static_cast(IExtensionInterfaceCode::CMD_HANDLE_INCREMENTAL_BACKUP), - data, reply, option); - if (ret != NO_ERROR) { - HILOGE("Received error %{public}d when doing IPC", ret); - return ErrCode(ret); - } - - HILOGI("Successful"); - return reply.ReadInt32(); -} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/mock/module_ipc/svc_extension_proxy_mock.cpp b/tests/mock/module_ipc/svc_extension_proxy_mock.cpp index 6c1fbe7e3..cc3f57902 100644 --- a/tests/mock/module_ipc/svc_extension_proxy_mock.cpp +++ b/tests/mock/module_ipc/svc_extension_proxy_mock.cpp @@ -57,4 +57,9 @@ ErrCode SvcExtensionProxy::HandleIncrementalBackup(UniqueFd incrementalFd, Uniqu { return 0; } + +tuple SvcExtensionProxy::GetIncrementalBackupFileHandle() +{ + return {UniqueFd(-1), UniqueFd(-1)}; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file 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 d6fe04fba..07cf8be79 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 @@ -112,6 +112,11 @@ public: return BError(BError::Codes::OK); }; + std::tuple GetIncrementalBackupFileHandle() override + { + return {UniqueFd(-1), UniqueFd(-1)}; + }; + private: int32_t nHandleBackupNum_ = 0; }; -- Gitee From 66df3695df84cb1fbbf63df759dd5547dc7e6b82 Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Tue, 2 Jan 2024 23:14:49 +0800 Subject: [PATCH 21/35] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=A2=9E=E9=87=8F=E5=A4=87=E4=BB=BD=E6=97=B6=E4=BC=A0=E9=80=92?= =?UTF-8?q?=E7=9A=84fd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- .../backup_sa/src/module_ipc/service_incremental.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/backup_sa/src/module_ipc/service_incremental.cpp b/services/backup_sa/src/module_ipc/service_incremental.cpp index dce49baa4..121533383 100644 --- a/services/backup_sa/src/module_ipc/service_incremental.cpp +++ b/services/backup_sa/src/module_ipc/service_incremental.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2024 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 @@ -325,7 +325,7 @@ bool Service::IncrementalBackup(const string &bundleName) throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty"); } if (scenario == IServiceReverse::Scenario::BACKUP && session_->GetIsIncrementalBackup()) { - auto [incrementalFd, manifestFd] = proxy->GetIncrementalBackupFileHandle(); + //auto [incrementalFd, manifestFd] = proxy->GetIncrementalBackupFileHandle(); // 本地全量数据 string path = BConstants::GetSaBundleBackupRootDir(session_->GetSessionUserId()) .append(bundleName) @@ -334,11 +334,11 @@ bool Service::IncrementalBackup(const string &bundleName) .append(to_string(session_->GetLastIncrementalTime(bundleName))); HILOGI("path = %{public}s", path.c_str()); UniqueFd fdLocal(open(path.data(), O_RDWR, S_IRGRP | S_IWGRP | S_IRGRP | S_IWGRP)); - BFile::SendFile(incrementalFd, fdLocal); + //BFile::SendFile(incrementalFd, fdLocal); // 云上存在的数据 UniqueFd lastManifestFd(session_->GetIncrementalManifestFd(bundleName)); - BFile::SendFile(manifestFd, lastManifestFd); - auto ret = proxy->HandleIncrementalBackup(UniqueFd(-1), UniqueFd(-1)); + //BFile::SendFile(manifestFd, lastManifestFd); + auto ret = proxy->HandleIncrementalBackup(move(fdLocal), move(lastManifestFd)); session_->GetServiceReverseProxy()->IncrementalBackupOnBundleStarted(ret, bundleName); if (ret) { ClearSessionAndSchedInfo(bundleName); -- Gitee From 0e686b4db97bc11f3be1b642e1dede5635535b8b Mon Sep 17 00:00:00 2001 From: zhuruigan Date: Tue, 2 Jan 2024 23:19:34 +0800 Subject: [PATCH 22/35] =?UTF-8?q?=E5=A4=87=E4=BB=BD=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhuruigan --- .../native/backup_ext/include/ext_extension.h | 26 ++++--- .../native/backup_ext/src/ext_extension.cpp | 23 ++++--- .../backup_utils/b_filesystem/b_file_test.cpp | 17 ----- utils/include/b_json/b_report_entity.h | 67 +++++++++++-------- utils/src/b_filesystem/b_file.cpp | 2 - 5 files changed, 65 insertions(+), 70 deletions(-) diff --git a/frameworks/native/backup_ext/include/ext_extension.h b/frameworks/native/backup_ext/include/ext_extension.h index cc17b1d38..eab04ed2a 100644 --- a/frameworks/native/backup_ext/include/ext_extension.h +++ b/frameworks/native/backup_ext/include/ext_extension.h @@ -19,8 +19,12 @@ #include #include #include +#include + +#include #include "b_json/b_json_entity_extension_config.h" +#include "b_json/b_report_entity.h" #include "b_resources/b_constants.h" #include "ext_backup_js.h" #include "ext_extension_stub.h" @@ -115,21 +119,15 @@ private: void AsyncTaskOnBackup(); - /** - * @brief IncrementalBackup - * - * @param incrementalFd storage fd - * @param manifestFd 云空间 fd - */ - int DoIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd); + int DoIncrementalBackup(const std::map &allFiles, + const std::map &smallFiles, + const std::map &bigFiles, + const std::map &bigInfos); - /** - * @brief AsyncTaskOnIncrementalBackup - * - * @param incrementalFd storage fd - * @param manifestFd 云空间 fd - */ - void AsyncTaskOnIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd); + void AsyncTaskOnIncrementalBackup(const std::map &allFiles, + const std::map &smallFiles, + const std::map &bigFiles, + const std::map &bigInfos); /** * @brief extension incremental backup restore is done diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index b2cd4e37a..d1fe20c15 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -1123,7 +1123,6 @@ static tuple, map cloudFiles = cloudRp.GetReportInfos(); - BReportEntity storageRp(UniqueFd(storageFd.Get())); map storageFiles = storageRp.GetReportInfos(); map allFiles = {}; @@ -1234,7 +1233,7 @@ static ErrCode IncrementalTarFileReady(const TarMap &bigFileInfo, const mapAppIncrementalFileReady(tarName, UniqueFd(open(tarName.data(), O_RDONLY)), + proxy->AppIncrementalFileReady(tarFile, UniqueFd(open(tarName.data(), O_RDONLY)), UniqueFd(open(file.data(), O_RDONLY))); if (SUCCEEDED(ret)) { HILOGI("IncrementalTarFileReady: The application is packaged successfully"); @@ -1297,7 +1296,9 @@ ErrCode BackupExtExtension::HandleIncrementalBackup(UniqueFd incrementalFd, Uniq return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore") .GetCode(); } - AsyncTaskOnIncrementalBackup(move(incrementalFd), move(manifestFd)); + + auto [allFiles, smallFiles, bigFiles, bigInfos] = CompareFiles(move(manifestFd), move(incrementalFd)); + AsyncTaskOnIncrementalBackup(allFiles, smallFiles, bigFiles, bigInfos); return 0; } @@ -1306,9 +1307,12 @@ tuple BackupExtExtension::GetIncrementalBackupFileHandle() return {UniqueFd(-1), UniqueFd(-1)}; } -void BackupExtExtension::AsyncTaskOnIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd) + +void BackupExtExtension::AsyncTaskOnIncrementalBackup(const map &allFiles, + const map &smallFiles, const map &bigFiles, + const map &bigInfos) { - auto task = [obj {wptr(this)}, ifd(incrementalFd.Get()), mfd(manifestFd.Get())]() { + auto task = [obj {wptr(this)}, allFiles, smallFiles, bigFiles, bigInfos]() { auto ptr = obj.promote(); try { BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, @@ -1316,7 +1320,7 @@ void BackupExtExtension::AsyncTaskOnIncrementalBackup(UniqueFd incrementalFd, Un BExcepUltils::BAssert(ptr->extension_, BError::Codes::EXT_INVAL_ARG, "extension handle have been already released"); - auto ret = ptr->DoIncrementalBackup(UniqueFd(ifd), UniqueFd(mfd)); + auto ret = ptr->DoIncrementalBackup(allFiles, smallFiles, bigFiles, bigInfos); ptr->AppIncrementalDone(ret); HILOGE("Incremental backup app done %{public}d", ret); } catch (const BError &e) { @@ -1385,7 +1389,7 @@ static ErrCode IncrementalAllFileReady(const TarMap &pkgInfo, const map &allFiles, + const map &smallFiles, const map &bigFiles, + const map &bigInfos) { HILOGI("Do increment backup"); if (extension_->GetExtensionAction() != BConstants::ExtensionAction::BACKUP) { @@ -1418,7 +1424,6 @@ int BackupExtExtension::DoIncrementalBackup(UniqueFd incrementalFd, UniqueFd man throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno)); } // 获取增量文件和全量数据 - auto [allFiles, smallFiles, bigFiles, bigInfos] = CompareFiles(manifestFd, incrementalFd); if (smallFiles.size() == 0 && bigFiles.size() == 0) { // 没有增量,则不需要上传 TarMap tMap; diff --git a/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp b/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp index 1aaa78956..5708ff760 100644 --- a/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp +++ b/tests/unittests/backup_utils/b_filesystem/b_file_test.cpp @@ -160,21 +160,4 @@ HWTEST_F(BFileTest, b_file_Write_0100, testing::ext::TestSize.Level1) } GTEST_LOG_(INFO) << "BFileTest-end b_file_Write_0100"; } - -/** - * @brief 创建增量测试文件 - * - * @return tuple 文件路径、对比内容 - */ -static tuple GetTestIncrementalFile(const TestManager &tm) -{ - string path = tm.GetRootDirCurTest(); - string filePath = path + "incremental.txt"; - string content = "version=1.0&attrNum=6\npath;mode;dir;size;mtime;hash\n"; - string info = "a.txt;0660;0;10;123456;asd1asdasd;"; - if (bool contentCreate = SaveStringToFile(filePath, content + info, true); !contentCreate) { - throw system_error(errno, system_category()); - } - return {filePath, info}; -} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/utils/include/b_json/b_report_entity.h b/utils/include/b_json/b_report_entity.h index 15d573b48..f20cd1e19 100644 --- a/utils/include/b_json/b_report_entity.h +++ b/utils/include/b_json/b_report_entity.h @@ -17,6 +17,7 @@ #define OHOS_FILEMGMT_BACKUP_B_REPORT_ENTITY_H #include +#include #include #include #include @@ -38,11 +39,6 @@ struct ReportFileInfo { bool isIncremental {false}; }; -namespace { -const int64_t HASH_BUFFER_SIZE = 4096; // 每次读取的siz -const int FILTER_LINE = 2; // 过滤前2行 -} // namespace - class BReportEntity { public: std::vector SplitStringByChar(const std::string &str, const char &sep) @@ -67,15 +63,16 @@ public: // 处理path路径 std::string path; std::vector residue; - for (int i = 0; i < splitsLen; i++) { - if (i <= splitsLen - len) { - path += splits[i] + ";"; - } else { - residue.emplace_back(splits[i]); - } - } - + HILOGE("ParseReportInfo start splitsLen=%{public}d, len=%{public}d", splitsLen, len); try { + for (int i = 0; i < splitsLen; i++) { + if (i <= splitsLen - len) { + path += splits[i] + ";"; + } else { + HILOGE("ParseReportInfo split %{public}s", splits[i].data()); + residue.emplace_back(splits[i]); + } + } fileStat.filePath = path.substr(0, path.length() - 1); fileStat.mode = residue[keys.find("mode")->second]; fileStat.isDir = atoi(residue[keys.find("dir")->second].c_str()) == 1 ? true : false; @@ -85,32 +82,46 @@ public: if (keys.find("isIncremental") != keys.end()) { fileStat.isIncremental = atoi(residue[keys.find("isIncremental")->second].c_str()) == 1 ? true : false; } + HILOGE("ParseReportInfo end"); return ERR_OK; - } catch (const exception &e) { - HILOGE("Failed to ParseReportInfo %{public}s", e.what()); + } catch (...) { + HILOGE("Failed to ParseReportInfo"); return EPERM; } } - void DealLine(std::unordered_map &keys, int &num, const std::string ¤tLine, + void DealLine(std::unordered_map &keys, int &num, const std::string &line, std::map &infos) { + std::string currentLine = line; + if (currentLine[currentLine.length()-1] == '\r') { + currentLine = currentLine.substr(0, currentLine.length()-1); + } + + HILOGE("DealLine begin:%{public}s", currentLine.c_str()); std::vector splits = SplitStringByChar(currentLine, attrSep_); - if (num < FILTER_LINE) { + HILOGE("DealLine end"); + if (num < INFO_ALIGN_NUM_) { if (num == 1) { for (int j = 0; j < (int)splits.size(); j++) { + HILOGE("keys %{public}s, j=%{public}d", splits[j].data(), j); keys.emplace(splits[j], j - 1); } } num++; } else { + HILOGE("ParseReportInfo begin:%{public}s", currentLine.c_str()); struct ReportFileInfo fileState; + for (int j = 0; j < (int)splits.size(); j++) { + HILOGE("splits %{public}s, j=%{public}d", splits[j].data(), j); + } auto code = ParseReportInfo(fileState, splits, keys); if (code != ERR_OK) { HILOGE("ParseReportInfo err:%{public}d, %{public}s", code, currentLine.c_str()); } else { infos.try_emplace(fileState.filePath, fileState); } + HILOGE("ParseReportInfo end"); } } @@ -123,15 +134,19 @@ public: { std::map infos {}; - char buffer[HASH_BUFFER_SIZE]; + char buffer[HASH_BUFFER_SIZE_]; ssize_t bytesRead; std::string currentLine; std::unordered_map keys; + int num = 0; while ((bytesRead = read(srcFile_, buffer, sizeof(buffer))) > 0) { - for (ssize_t i = 0; i < bytesRead; ++i) { + HILOGI("GetReportInfos line:%{public}s", buffer); + for (ssize_t i = 0; i < bytesRead; i++) { if (buffer[i] == lineSep_) { + HILOGI("GetReportInfos line:%{public}s", currentLine.c_str()); DealLine(keys, num, currentLine, infos); + HILOGI("GetReportInfos end"); currentLine.clear(); } else { currentLine += buffer[i]; @@ -141,14 +156,9 @@ public: // 处理文件中的最后一行 if (!currentLine.empty()) { - std::vector splits = SplitStringByChar(currentLine, attrSep_); - struct ReportFileInfo fileState; - auto code = ParseReportInfo(fileState, splits, keys); - if (code == ERR_OK) { - infos.try_emplace(fileState.filePath, fileState); - } else { - HILOGE("ParseReportInfo err:%{public}d, %{public}s", code, currentLine.c_str()); - } + HILOGI("GetReportInfos2 line:%{public}s", currentLine.c_str()); + DealLine(keys, num, currentLine, infos); + HILOGI("GetReportInfos2 end"); } return infos; @@ -175,9 +185,10 @@ protected: const char attrSep_ = ';'; const char infoSep_ = '&'; const char infoAlign_ = '='; - const unsigned int INFO_ALIGN_NUM_ = 2; + const int INFO_ALIGN_NUM_ = 2; const string VERSION_TAG_ = "version"; const string ATTR_NUM_TAG_ = "attrNum"; + const int64_t HASH_BUFFER_SIZE_ = 4096; // 每次读取的siz }; } // namespace OHOS::FileManagement::Backup diff --git a/utils/src/b_filesystem/b_file.cpp b/utils/src/b_filesystem/b_file.cpp index db1a4de00..aa8c36370 100644 --- a/utils/src/b_filesystem/b_file.cpp +++ b/utils/src/b_filesystem/b_file.cpp @@ -23,8 +23,6 @@ #include #include #include -#include -#include #include "b_error/b_error.h" #include "filemgmt_libhilog.h" -- Gitee From 7b9e5aafae1865e53e21b0b9d93b90d1b0f98f6e Mon Sep 17 00:00:00 2001 From: zhuruigan Date: Wed, 3 Jan 2024 16:29:40 +0800 Subject: [PATCH 23/35] =?UTF-8?q?=E5=A2=9E=E9=87=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhuruigan --- .../native/backup_ext/src/ext_extension.cpp | 32 ++++++++++++------- utils/include/b_json/b_report_entity.h | 30 ++++++++--------- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index d1fe20c15..02a19a279 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -16,6 +16,7 @@ #include "ext_extension.h" #include +#include #include #include #include @@ -1132,8 +1133,10 @@ static tuple, map, mapsecond.hash != item.second.hash)) { + if (cloudFiles.find(path) == cloudFiles.end() || (item.second.isDir == false && + item.second.isIncremental == true && cloudFiles.find(path)->second.hash != item.second.hash)) { // 在云空间简报里不存在或者hash不一致 - // 区分大小文件 struct stat sta = {}; if (stat(path.c_str(), &sta) == -1) { continue; } if (sta.st_size < BConstants::BIG_FILE_BOUNDARY) { - HILOGI("compareFiles Find small file"); item.second.size = sta.st_size; smallFiles.try_emplace(path, item.second); } else { - HILOGI("compareFiles Find big file"); bigFiles.try_emplace(path, sta); bigInfos.try_emplace(path, item.second); } @@ -1296,7 +1296,6 @@ ErrCode BackupExtExtension::HandleIncrementalBackup(UniqueFd incrementalFd, Uniq return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore") .GetCode(); } - auto [allFiles, smallFiles, bigFiles, bigInfos] = CompareFiles(move(manifestFd), move(incrementalFd)); AsyncTaskOnIncrementalBackup(allFiles, smallFiles, bigFiles, bigInfos); return 0; @@ -1343,6 +1342,15 @@ void BackupExtExtension::AsyncTaskOnIncrementalBackup(const map(duration); + + return to_string(milliseconds.count()) + "_part"; +} + static void IncrementalPacket(const map &infos, TarMap &tar, sptr proxy) { HILOGI("IncrementalPacket begin"); @@ -1351,6 +1359,8 @@ static void IncrementalPacket(const map &infos, T uint32_t fileCount = 0; vector packFiles; map tarInfos; + + string partName = GetIncrmentPartName(); for (auto small : infos) { totalSize += small.second.size; fileCount += 1; @@ -1358,7 +1368,7 @@ static void IncrementalPacket(const map &infos, T tarInfos.try_emplace(small.first, small.second); if (totalSize >= DEFAULT_SLICE_SIZE || fileCount >= MAX_FILE_COUNT) { TarMap tarMap {}; - TarFile::GetInstance().Packet(packFiles, "part", path, tarMap); + TarFile::GetInstance().Packet(packFiles, partName, path, tarMap); tar.insert(tarMap.begin(), tarMap.end()); // 执行tar包回传功能 IncrementalTarFileReady(tarMap, tarInfos, proxy); @@ -1371,7 +1381,7 @@ static void IncrementalPacket(const map &infos, T if (fileCount > 0) { // 打包回传 TarMap tarMap {}; - TarFile::GetInstance().Packet(packFiles, "part", path, tarMap); + TarFile::GetInstance().Packet(packFiles, partName, path, tarMap); IncrementalTarFileReady(tarMap, tarInfos, proxy); tar.insert(tarMap.begin(), tarMap.end()); packFiles.clear(); diff --git a/utils/include/b_json/b_report_entity.h b/utils/include/b_json/b_report_entity.h index f20cd1e19..9934c3d48 100644 --- a/utils/include/b_json/b_report_entity.h +++ b/utils/include/b_json/b_report_entity.h @@ -63,26 +63,33 @@ public: // 处理path路径 std::string path; std::vector residue; - HILOGE("ParseReportInfo start splitsLen=%{public}d, len=%{public}d", splitsLen, len); try { for (int i = 0; i < splitsLen; i++) { if (i <= splitsLen - len) { path += splits[i] + ";"; } else { - HILOGE("ParseReportInfo split %{public}s", splits[i].data()); residue.emplace_back(splits[i]); } } fileStat.filePath = path.substr(0, path.length() - 1); - fileStat.mode = residue[keys.find("mode")->second]; - fileStat.isDir = atoi(residue[keys.find("dir")->second].c_str()) == 1 ? true : false; - fileStat.size = static_cast(atol(residue[keys.find("size")->second].c_str())); - fileStat.mtime = static_cast(atol(residue[keys.find("mtime")->second].c_str())); - fileStat.hash = residue[keys.find("hash")->second]; + if (keys.find("mode") != keys.end()) { + fileStat.mode = residue[keys.find("mode")->second]; + } + if (keys.find("dir") != keys.end()) { + fileStat.isDir = atoi(residue[keys.find("dir")->second].c_str()) == 1 ? true : false; + } + if (keys.find("size") != keys.end()) { + fileStat.size = static_cast(atol(residue[keys.find("size")->second].c_str())); + } + if (keys.find("mtime") != keys.end()) { + fileStat.mtime = static_cast(atol(residue[keys.find("mtime")->second].c_str())); + } + if (keys.find("hash") != keys.end()) { + fileStat.hash = residue[keys.find("hash")->second]; + } if (keys.find("isIncremental") != keys.end()) { fileStat.isIncremental = atoi(residue[keys.find("isIncremental")->second].c_str()) == 1 ? true : false; } - HILOGE("ParseReportInfo end"); return ERR_OK; } catch (...) { HILOGE("Failed to ParseReportInfo"); @@ -98,30 +105,23 @@ public: currentLine = currentLine.substr(0, currentLine.length()-1); } - HILOGE("DealLine begin:%{public}s", currentLine.c_str()); std::vector splits = SplitStringByChar(currentLine, attrSep_); HILOGE("DealLine end"); if (num < INFO_ALIGN_NUM_) { if (num == 1) { for (int j = 0; j < (int)splits.size(); j++) { - HILOGE("keys %{public}s, j=%{public}d", splits[j].data(), j); keys.emplace(splits[j], j - 1); } } num++; } else { - HILOGE("ParseReportInfo begin:%{public}s", currentLine.c_str()); struct ReportFileInfo fileState; - for (int j = 0; j < (int)splits.size(); j++) { - HILOGE("splits %{public}s, j=%{public}d", splits[j].data(), j); - } auto code = ParseReportInfo(fileState, splits, keys); if (code != ERR_OK) { HILOGE("ParseReportInfo err:%{public}d, %{public}s", code, currentLine.c_str()); } else { infos.try_emplace(fileState.filePath, fileState); } - HILOGE("ParseReportInfo end"); } } -- Gitee From 70617b85c092e15a5ceb4d3934c3b7acb8c7d5cd Mon Sep 17 00:00:00 2001 From: yang-jingbo1985 Date: Wed, 3 Jan 2024 16:46:31 +0800 Subject: [PATCH 24/35] =?UTF-8?q?stat=E6=96=87=E4=BB=B6=E9=9C=80=E8=A6=81b?= =?UTF-8?q?ackupUID=E5=92=8CGID=20Signed-off-by:=20yangjingbo10=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backup_sa/src/module_external/bms_adapter.cpp | 14 +++++++++++++- 1 file changed, 13 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 88f2ebc25..fb4dbcc07 100644 --- a/services/backup_sa/src/module_external/bms_adapter.cpp +++ b/services/backup_sa/src/module_external/bms_adapter.cpp @@ -206,7 +206,7 @@ static bool CreateIPCInteractionFiles(int32_t userId, const string &bundleName, std::ofstream incExcFile; incExcFile.open(incExFilePath.data(), std::ios::out | std::ios::trunc); if (!incExcFile.is_open()) { - HILOGE("Cannot create file"); + HILOGE("Cannot create incexc file"); return false; } incExcFile << BConstants::BACKUP_INCLUDE << std::endl; @@ -217,6 +217,18 @@ static bool CreateIPCInteractionFiles(int32_t userId, const string &bundleName, for (auto &exclude : excludes) { incExcFile << exclude << std::endl; } + incExcFile.close(); + + // backup_sa stat + std::string statFilePath = backupSaBundleDir + BConstants::BACKUP_STAT_SYMBOL + to_string(lastIncrementalTime); + std::ofstream statFile; + statFile.open(statFilePath.data(), std::ios::out | std::ios::trunc); + if (!statFile.is_open()) { + HILOGE("Cannot create stat file"); + return false; + } + statFile.close(); + return true; } -- Gitee From f17873ecd5641b31532d35f944ead148585a3e0a Mon Sep 17 00:00:00 2001 From: yang-jingbo1985 Date: Wed, 3 Jan 2024 21:55:28 +0800 Subject: [PATCH 25/35] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=89=A9=E7=90=86?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E6=B2=99=E7=AE=B1=E8=B7=AF=E5=BE=84=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E6=8E=A5=E5=8F=A3=20Signed-off-by:=20yangjingbo10=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.diff | 165 +++++++++++++++++++++ interfaces/common/include/sandbox_helper.h | 4 + interfaces/common/src/sandbox_helper.cpp | 83 +++++++++++ interfaces/innerkits/native/BUILD.gn | 12 +- 4 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 app.diff diff --git a/app.diff b/app.diff new file mode 100644 index 000000000..80f7b28dc --- /dev/null +++ b/app.diff @@ -0,0 +1,165 @@ +diff --git a/interfaces/common/include/sandbox_helper.h b/interfaces/common/include/sandbox_helper.h +index d4ed5db..c491182 100644 +--- a/interfaces/common/include/sandbox_helper.h ++++ b/interfaces/common/include/sandbox_helper.h +@@ -26,13 +26,17 @@ class SandboxHelper { + private: + static std::mutex mapMutex_; + static std::unordered_map sandboxPathMap_; ++ static std::unordered_map backupSandboxPathMap_; + static bool GetSandboxPathMap(); ++ static bool GetBackupSandboxPathMap(); + public: + static std::string Encode(const std::string &uri); + static std::string Decode(const std::string &uri); + static bool CheckValidPath(const std::string &filePath); + static int32_t GetPhysicalPath(const std::string &fileUri, const std::string &userId, + std::string &physicalPath); ++ static int32_t GetBackupPhysicalPath(const std::string &fileUri, const std::string &userId, ++ std::string &physicalPath); + static bool IsValidPath(const std::string &path); + }; + } // namespace AppFileService +diff --git a/interfaces/common/src/sandbox_helper.cpp b/interfaces/common/src/sandbox_helper.cpp +index 140fb61..7d18b67 100644 +--- a/interfaces/common/src/sandbox_helper.cpp ++++ b/interfaces/common/src/sandbox_helper.cpp +@@ -35,6 +35,7 @@ namespace { + const string SANDBOX_PATH_KEY = "sandbox-path"; + const string MOUNT_PATH_MAP_KEY = "mount-path-map"; + const string SANDBOX_JSON_FILE_PATH = "/etc/app_file_service/file_share_sandbox.json"; ++ const string BACKUP_SANDBOX_JSON_FILE_PATH = "/etc/app_file_service/backup_sandbox.json"; + const std::string SHAER_PATH_HEAD = "/mnt/hmdfs/"; + const std::string SHAER_PATH_MID = "/account/cloud_merge_view/files/"; + const string FILE_MANAGER_URI_HEAD = "/storage/"; +@@ -57,6 +58,7 @@ struct MediaUriInfo { + }; + + std::unordered_map SandboxHelper::sandboxPathMap_; ++std::unordered_map SandboxHelper::backupSandboxPathMap_; + std::mutex SandboxHelper::mapMutex_; + + string SandboxHelper::Encode(const string &uri) +@@ -159,6 +161,39 @@ bool SandboxHelper::GetSandboxPathMap() + return true; + } + ++bool SandboxHelper::GetBackupSandboxPathMap() ++{ ++ lock_guard lock(mapMutex_); ++ if (backupSandboxPathMap_.size() > 0) { ++ return true; ++ } ++ ++ nlohmann::json jsonObj; ++ int ret = JsonUtils::GetJsonObjFromPath(jsonObj, BACKUP_SANDBOX_JSON_FILE_PATH); ++ if (ret != 0) { ++ LOGE("Get json object failed with %{public}d", ret); ++ return false; ++ } ++ ++ if (jsonObj.find(MOUNT_PATH_MAP_KEY) == jsonObj.end()) { ++ LOGE("Json object find mount path map failed"); ++ return false; ++ } ++ ++ nlohmann::json mountPathMap = jsonObj[MOUNT_PATH_MAP_KEY]; ++ for (size_t i = 0; i < mountPathMap.size(); i++) { ++ string srcPath = mountPathMap[i][PHYSICAL_PATH_KEY]; ++ string sandboxPath = mountPathMap[i][SANDBOX_PATH_KEY]; ++ backupSandboxPathMap_[sandboxPath] = srcPath; ++ } ++ ++ if (backupSandboxPathMap_.size() == 0) { ++ return false; ++ } ++ ++ return true; ++} ++ + static int32_t GetPathSuffix(const std::string &path, string &pathSuffix) + { + size_t pos = path.rfind('.'); +@@ -323,6 +358,54 @@ int32_t SandboxHelper::GetPhysicalPath(const std::string &fileUri, const std::st + return 0; + } + ++int32_t SandboxHelper::GetBackupPhysicalPath(const std::string &fileUri, const std::string &userId, ++ std::string &physicalPath) ++{ ++ Uri uri(fileUri); ++ string bundleName = uri.GetAuthority(); ++ if (bundleName == MEDIA) { ++ return GetMediaPhysicalPath(uri.GetPath(), userId, physicalPath); ++ } ++ ++ string sandboxPath = SandboxHelper::Decode(uri.GetPath()); ++ if ((sandboxPath.find(FILE_MANAGER_URI_HEAD) == 0 && bundleName != FILE_MANAGER_AUTHORITY) || ++ (sandboxPath.find(FUSE_URI_HEAD) == 0 && bundleName != DLP_MANAGER_BUNDLE_NAME)) { ++ return -EINVAL; ++ } ++ ++ if (!GetBackupSandboxPathMap()) { ++ LOGE("GetBackupSandboxPathMap failed"); ++ return -EINVAL; ++ } ++ ++ string lowerPathTail = ""; ++ string lowerPathHead = ""; ++ string::size_type curPrefixMatchLen = 0; ++ for (auto it = backupSandboxPathMap_.begin(); it != backupSandboxPathMap_.end(); it++) { ++ string sandboxPathPrefix = it->first; ++ string::size_type prefixMatchLen = sandboxPathPrefix.length(); ++ if (sandboxPath.length() >= prefixMatchLen) { ++ string sandboxPathTemp = sandboxPath.substr(0, prefixMatchLen); ++ if (sandboxPathTemp == sandboxPathPrefix && curPrefixMatchLen <= prefixMatchLen) { ++ curPrefixMatchLen = prefixMatchLen; ++ lowerPathHead = it->second; ++ lowerPathTail = sandboxPath.substr(prefixMatchLen); ++ } ++ } ++ } ++ ++ if (lowerPathHead == "") { ++ LOGE("lowerPathHead is invalid"); ++ return -EINVAL; ++ } ++ ++ string networkId = LOCAL; ++ GetNetworkIdFromUri(fileUri, networkId); ++ ++ physicalPath = GetLowerPath(lowerPathHead, lowerPathTail, userId, bundleName, networkId); ++ return 0; ++} ++ + bool SandboxHelper::IsValidPath(const std::string &path) + { + if (path.find("/./") != std::string::npos || +diff --git a/interfaces/innerkits/native/BUILD.gn b/interfaces/innerkits/native/BUILD.gn +index 7fa9ffa..069d1cd 100644 +--- a/interfaces/innerkits/native/BUILD.gn ++++ b/interfaces/innerkits/native/BUILD.gn +@@ -96,6 +96,13 @@ ohos_prebuilt_etc("file_share_sandbox.json") { + module_install_dir = "etc/app_file_service" + } + ++ohos_prebuilt_etc("backup_sandbox.json") { ++ source = "../../common/backup_sandbox.json" ++ part_name = "app_file_service" ++ subsystem_name = "filemanagement" ++ module_install_dir = "etc/app_file_service" ++} ++ + config("remote_file_share_config") { + visibility = [ ":*" ] + include_dirs = [ +@@ -176,5 +183,8 @@ group("app_file_service_native") { + } + + group("etc_files") { +- deps = [ ":file_share_sandbox.json" ] ++ deps = [ ++ ":backup_sandbox.json", ++ ":file_share_sandbox.json", ++ ] + } diff --git a/interfaces/common/include/sandbox_helper.h b/interfaces/common/include/sandbox_helper.h index d4ed5dbd3..c49118204 100644 --- a/interfaces/common/include/sandbox_helper.h +++ b/interfaces/common/include/sandbox_helper.h @@ -26,13 +26,17 @@ class SandboxHelper { private: static std::mutex mapMutex_; static std::unordered_map sandboxPathMap_; + static std::unordered_map backupSandboxPathMap_; static bool GetSandboxPathMap(); + static bool GetBackupSandboxPathMap(); public: static std::string Encode(const std::string &uri); static std::string Decode(const std::string &uri); static bool CheckValidPath(const std::string &filePath); static int32_t GetPhysicalPath(const std::string &fileUri, const std::string &userId, std::string &physicalPath); + static int32_t GetBackupPhysicalPath(const std::string &fileUri, const std::string &userId, + std::string &physicalPath); static bool IsValidPath(const std::string &path); }; } // namespace AppFileService diff --git a/interfaces/common/src/sandbox_helper.cpp b/interfaces/common/src/sandbox_helper.cpp index 140fb61e9..7d18b6796 100644 --- a/interfaces/common/src/sandbox_helper.cpp +++ b/interfaces/common/src/sandbox_helper.cpp @@ -35,6 +35,7 @@ namespace { const string SANDBOX_PATH_KEY = "sandbox-path"; const string MOUNT_PATH_MAP_KEY = "mount-path-map"; const string SANDBOX_JSON_FILE_PATH = "/etc/app_file_service/file_share_sandbox.json"; + const string BACKUP_SANDBOX_JSON_FILE_PATH = "/etc/app_file_service/backup_sandbox.json"; const std::string SHAER_PATH_HEAD = "/mnt/hmdfs/"; const std::string SHAER_PATH_MID = "/account/cloud_merge_view/files/"; const string FILE_MANAGER_URI_HEAD = "/storage/"; @@ -57,6 +58,7 @@ struct MediaUriInfo { }; std::unordered_map SandboxHelper::sandboxPathMap_; +std::unordered_map SandboxHelper::backupSandboxPathMap_; std::mutex SandboxHelper::mapMutex_; string SandboxHelper::Encode(const string &uri) @@ -159,6 +161,39 @@ bool SandboxHelper::GetSandboxPathMap() return true; } +bool SandboxHelper::GetBackupSandboxPathMap() +{ + lock_guard lock(mapMutex_); + if (backupSandboxPathMap_.size() > 0) { + return true; + } + + nlohmann::json jsonObj; + int ret = JsonUtils::GetJsonObjFromPath(jsonObj, BACKUP_SANDBOX_JSON_FILE_PATH); + if (ret != 0) { + LOGE("Get json object failed with %{public}d", ret); + return false; + } + + if (jsonObj.find(MOUNT_PATH_MAP_KEY) == jsonObj.end()) { + LOGE("Json object find mount path map failed"); + return false; + } + + nlohmann::json mountPathMap = jsonObj[MOUNT_PATH_MAP_KEY]; + for (size_t i = 0; i < mountPathMap.size(); i++) { + string srcPath = mountPathMap[i][PHYSICAL_PATH_KEY]; + string sandboxPath = mountPathMap[i][SANDBOX_PATH_KEY]; + backupSandboxPathMap_[sandboxPath] = srcPath; + } + + if (backupSandboxPathMap_.size() == 0) { + return false; + } + + return true; +} + static int32_t GetPathSuffix(const std::string &path, string &pathSuffix) { size_t pos = path.rfind('.'); @@ -323,6 +358,54 @@ int32_t SandboxHelper::GetPhysicalPath(const std::string &fileUri, const std::st return 0; } +int32_t SandboxHelper::GetBackupPhysicalPath(const std::string &fileUri, const std::string &userId, + std::string &physicalPath) +{ + Uri uri(fileUri); + string bundleName = uri.GetAuthority(); + if (bundleName == MEDIA) { + return GetMediaPhysicalPath(uri.GetPath(), userId, physicalPath); + } + + string sandboxPath = SandboxHelper::Decode(uri.GetPath()); + if ((sandboxPath.find(FILE_MANAGER_URI_HEAD) == 0 && bundleName != FILE_MANAGER_AUTHORITY) || + (sandboxPath.find(FUSE_URI_HEAD) == 0 && bundleName != DLP_MANAGER_BUNDLE_NAME)) { + return -EINVAL; + } + + if (!GetBackupSandboxPathMap()) { + LOGE("GetBackupSandboxPathMap failed"); + return -EINVAL; + } + + string lowerPathTail = ""; + string lowerPathHead = ""; + string::size_type curPrefixMatchLen = 0; + for (auto it = backupSandboxPathMap_.begin(); it != backupSandboxPathMap_.end(); it++) { + string sandboxPathPrefix = it->first; + string::size_type prefixMatchLen = sandboxPathPrefix.length(); + if (sandboxPath.length() >= prefixMatchLen) { + string sandboxPathTemp = sandboxPath.substr(0, prefixMatchLen); + if (sandboxPathTemp == sandboxPathPrefix && curPrefixMatchLen <= prefixMatchLen) { + curPrefixMatchLen = prefixMatchLen; + lowerPathHead = it->second; + lowerPathTail = sandboxPath.substr(prefixMatchLen); + } + } + } + + if (lowerPathHead == "") { + LOGE("lowerPathHead is invalid"); + return -EINVAL; + } + + string networkId = LOCAL; + GetNetworkIdFromUri(fileUri, networkId); + + physicalPath = GetLowerPath(lowerPathHead, lowerPathTail, userId, bundleName, networkId); + return 0; +} + bool SandboxHelper::IsValidPath(const std::string &path) { if (path.find("/./") != std::string::npos || diff --git a/interfaces/innerkits/native/BUILD.gn b/interfaces/innerkits/native/BUILD.gn index 7fa9ffad3..069d1cda0 100644 --- a/interfaces/innerkits/native/BUILD.gn +++ b/interfaces/innerkits/native/BUILD.gn @@ -96,6 +96,13 @@ ohos_prebuilt_etc("file_share_sandbox.json") { module_install_dir = "etc/app_file_service" } +ohos_prebuilt_etc("backup_sandbox.json") { + source = "../../common/backup_sandbox.json" + part_name = "app_file_service" + subsystem_name = "filemanagement" + module_install_dir = "etc/app_file_service" +} + config("remote_file_share_config") { visibility = [ ":*" ] include_dirs = [ @@ -176,5 +183,8 @@ group("app_file_service_native") { } group("etc_files") { - deps = [ ":file_share_sandbox.json" ] + deps = [ + ":backup_sandbox.json", + ":file_share_sandbox.json", + ] } -- Gitee From 73aebbc16c4c1bd7dc7b8a6536bd81ba7a6344ad Mon Sep 17 00:00:00 2001 From: yang-jingbo1985 Date: Wed, 3 Jan 2024 21:55:28 +0800 Subject: [PATCH 26/35] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=89=A9=E7=90=86?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E6=B2=99=E7=AE=B1=E8=B7=AF=E5=BE=84=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E6=8E=A5=E5=8F=A3=20Signed-off-by:=20yangjingbo10=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- interfaces/common/include/sandbox_helper.h | 4 ++ interfaces/common/src/sandbox_helper.cpp | 83 ++++++++++++++++++++++ interfaces/innerkits/native/BUILD.gn | 12 +++- 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/interfaces/common/include/sandbox_helper.h b/interfaces/common/include/sandbox_helper.h index d4ed5dbd3..c49118204 100644 --- a/interfaces/common/include/sandbox_helper.h +++ b/interfaces/common/include/sandbox_helper.h @@ -26,13 +26,17 @@ class SandboxHelper { private: static std::mutex mapMutex_; static std::unordered_map sandboxPathMap_; + static std::unordered_map backupSandboxPathMap_; static bool GetSandboxPathMap(); + static bool GetBackupSandboxPathMap(); public: static std::string Encode(const std::string &uri); static std::string Decode(const std::string &uri); static bool CheckValidPath(const std::string &filePath); static int32_t GetPhysicalPath(const std::string &fileUri, const std::string &userId, std::string &physicalPath); + static int32_t GetBackupPhysicalPath(const std::string &fileUri, const std::string &userId, + std::string &physicalPath); static bool IsValidPath(const std::string &path); }; } // namespace AppFileService diff --git a/interfaces/common/src/sandbox_helper.cpp b/interfaces/common/src/sandbox_helper.cpp index 140fb61e9..7d18b6796 100644 --- a/interfaces/common/src/sandbox_helper.cpp +++ b/interfaces/common/src/sandbox_helper.cpp @@ -35,6 +35,7 @@ namespace { const string SANDBOX_PATH_KEY = "sandbox-path"; const string MOUNT_PATH_MAP_KEY = "mount-path-map"; const string SANDBOX_JSON_FILE_PATH = "/etc/app_file_service/file_share_sandbox.json"; + const string BACKUP_SANDBOX_JSON_FILE_PATH = "/etc/app_file_service/backup_sandbox.json"; const std::string SHAER_PATH_HEAD = "/mnt/hmdfs/"; const std::string SHAER_PATH_MID = "/account/cloud_merge_view/files/"; const string FILE_MANAGER_URI_HEAD = "/storage/"; @@ -57,6 +58,7 @@ struct MediaUriInfo { }; std::unordered_map SandboxHelper::sandboxPathMap_; +std::unordered_map SandboxHelper::backupSandboxPathMap_; std::mutex SandboxHelper::mapMutex_; string SandboxHelper::Encode(const string &uri) @@ -159,6 +161,39 @@ bool SandboxHelper::GetSandboxPathMap() return true; } +bool SandboxHelper::GetBackupSandboxPathMap() +{ + lock_guard lock(mapMutex_); + if (backupSandboxPathMap_.size() > 0) { + return true; + } + + nlohmann::json jsonObj; + int ret = JsonUtils::GetJsonObjFromPath(jsonObj, BACKUP_SANDBOX_JSON_FILE_PATH); + if (ret != 0) { + LOGE("Get json object failed with %{public}d", ret); + return false; + } + + if (jsonObj.find(MOUNT_PATH_MAP_KEY) == jsonObj.end()) { + LOGE("Json object find mount path map failed"); + return false; + } + + nlohmann::json mountPathMap = jsonObj[MOUNT_PATH_MAP_KEY]; + for (size_t i = 0; i < mountPathMap.size(); i++) { + string srcPath = mountPathMap[i][PHYSICAL_PATH_KEY]; + string sandboxPath = mountPathMap[i][SANDBOX_PATH_KEY]; + backupSandboxPathMap_[sandboxPath] = srcPath; + } + + if (backupSandboxPathMap_.size() == 0) { + return false; + } + + return true; +} + static int32_t GetPathSuffix(const std::string &path, string &pathSuffix) { size_t pos = path.rfind('.'); @@ -323,6 +358,54 @@ int32_t SandboxHelper::GetPhysicalPath(const std::string &fileUri, const std::st return 0; } +int32_t SandboxHelper::GetBackupPhysicalPath(const std::string &fileUri, const std::string &userId, + std::string &physicalPath) +{ + Uri uri(fileUri); + string bundleName = uri.GetAuthority(); + if (bundleName == MEDIA) { + return GetMediaPhysicalPath(uri.GetPath(), userId, physicalPath); + } + + string sandboxPath = SandboxHelper::Decode(uri.GetPath()); + if ((sandboxPath.find(FILE_MANAGER_URI_HEAD) == 0 && bundleName != FILE_MANAGER_AUTHORITY) || + (sandboxPath.find(FUSE_URI_HEAD) == 0 && bundleName != DLP_MANAGER_BUNDLE_NAME)) { + return -EINVAL; + } + + if (!GetBackupSandboxPathMap()) { + LOGE("GetBackupSandboxPathMap failed"); + return -EINVAL; + } + + string lowerPathTail = ""; + string lowerPathHead = ""; + string::size_type curPrefixMatchLen = 0; + for (auto it = backupSandboxPathMap_.begin(); it != backupSandboxPathMap_.end(); it++) { + string sandboxPathPrefix = it->first; + string::size_type prefixMatchLen = sandboxPathPrefix.length(); + if (sandboxPath.length() >= prefixMatchLen) { + string sandboxPathTemp = sandboxPath.substr(0, prefixMatchLen); + if (sandboxPathTemp == sandboxPathPrefix && curPrefixMatchLen <= prefixMatchLen) { + curPrefixMatchLen = prefixMatchLen; + lowerPathHead = it->second; + lowerPathTail = sandboxPath.substr(prefixMatchLen); + } + } + } + + if (lowerPathHead == "") { + LOGE("lowerPathHead is invalid"); + return -EINVAL; + } + + string networkId = LOCAL; + GetNetworkIdFromUri(fileUri, networkId); + + physicalPath = GetLowerPath(lowerPathHead, lowerPathTail, userId, bundleName, networkId); + return 0; +} + bool SandboxHelper::IsValidPath(const std::string &path) { if (path.find("/./") != std::string::npos || diff --git a/interfaces/innerkits/native/BUILD.gn b/interfaces/innerkits/native/BUILD.gn index 7fa9ffad3..069d1cda0 100644 --- a/interfaces/innerkits/native/BUILD.gn +++ b/interfaces/innerkits/native/BUILD.gn @@ -96,6 +96,13 @@ ohos_prebuilt_etc("file_share_sandbox.json") { module_install_dir = "etc/app_file_service" } +ohos_prebuilt_etc("backup_sandbox.json") { + source = "../../common/backup_sandbox.json" + part_name = "app_file_service" + subsystem_name = "filemanagement" + module_install_dir = "etc/app_file_service" +} + config("remote_file_share_config") { visibility = [ ":*" ] include_dirs = [ @@ -176,5 +183,8 @@ group("app_file_service_native") { } group("etc_files") { - deps = [ ":file_share_sandbox.json" ] + deps = [ + ":backup_sandbox.json", + ":file_share_sandbox.json", + ] } -- Gitee From a831b9dbcc063367744e3c32645aa23340171493 Mon Sep 17 00:00:00 2001 From: yang-jingbo1985 Date: Thu, 4 Jan 2024 15:04:48 +0800 Subject: [PATCH 27/35] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99diff?= =?UTF-8?q?=20Signed-off-by:=20yangjingbo10=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.diff | 165 ------------------------------------------------------- 1 file changed, 165 deletions(-) delete mode 100644 app.diff diff --git a/app.diff b/app.diff deleted file mode 100644 index 80f7b28dc..000000000 --- a/app.diff +++ /dev/null @@ -1,165 +0,0 @@ -diff --git a/interfaces/common/include/sandbox_helper.h b/interfaces/common/include/sandbox_helper.h -index d4ed5db..c491182 100644 ---- a/interfaces/common/include/sandbox_helper.h -+++ b/interfaces/common/include/sandbox_helper.h -@@ -26,13 +26,17 @@ class SandboxHelper { - private: - static std::mutex mapMutex_; - static std::unordered_map sandboxPathMap_; -+ static std::unordered_map backupSandboxPathMap_; - static bool GetSandboxPathMap(); -+ static bool GetBackupSandboxPathMap(); - public: - static std::string Encode(const std::string &uri); - static std::string Decode(const std::string &uri); - static bool CheckValidPath(const std::string &filePath); - static int32_t GetPhysicalPath(const std::string &fileUri, const std::string &userId, - std::string &physicalPath); -+ static int32_t GetBackupPhysicalPath(const std::string &fileUri, const std::string &userId, -+ std::string &physicalPath); - static bool IsValidPath(const std::string &path); - }; - } // namespace AppFileService -diff --git a/interfaces/common/src/sandbox_helper.cpp b/interfaces/common/src/sandbox_helper.cpp -index 140fb61..7d18b67 100644 ---- a/interfaces/common/src/sandbox_helper.cpp -+++ b/interfaces/common/src/sandbox_helper.cpp -@@ -35,6 +35,7 @@ namespace { - const string SANDBOX_PATH_KEY = "sandbox-path"; - const string MOUNT_PATH_MAP_KEY = "mount-path-map"; - const string SANDBOX_JSON_FILE_PATH = "/etc/app_file_service/file_share_sandbox.json"; -+ const string BACKUP_SANDBOX_JSON_FILE_PATH = "/etc/app_file_service/backup_sandbox.json"; - const std::string SHAER_PATH_HEAD = "/mnt/hmdfs/"; - const std::string SHAER_PATH_MID = "/account/cloud_merge_view/files/"; - const string FILE_MANAGER_URI_HEAD = "/storage/"; -@@ -57,6 +58,7 @@ struct MediaUriInfo { - }; - - std::unordered_map SandboxHelper::sandboxPathMap_; -+std::unordered_map SandboxHelper::backupSandboxPathMap_; - std::mutex SandboxHelper::mapMutex_; - - string SandboxHelper::Encode(const string &uri) -@@ -159,6 +161,39 @@ bool SandboxHelper::GetSandboxPathMap() - return true; - } - -+bool SandboxHelper::GetBackupSandboxPathMap() -+{ -+ lock_guard lock(mapMutex_); -+ if (backupSandboxPathMap_.size() > 0) { -+ return true; -+ } -+ -+ nlohmann::json jsonObj; -+ int ret = JsonUtils::GetJsonObjFromPath(jsonObj, BACKUP_SANDBOX_JSON_FILE_PATH); -+ if (ret != 0) { -+ LOGE("Get json object failed with %{public}d", ret); -+ return false; -+ } -+ -+ if (jsonObj.find(MOUNT_PATH_MAP_KEY) == jsonObj.end()) { -+ LOGE("Json object find mount path map failed"); -+ return false; -+ } -+ -+ nlohmann::json mountPathMap = jsonObj[MOUNT_PATH_MAP_KEY]; -+ for (size_t i = 0; i < mountPathMap.size(); i++) { -+ string srcPath = mountPathMap[i][PHYSICAL_PATH_KEY]; -+ string sandboxPath = mountPathMap[i][SANDBOX_PATH_KEY]; -+ backupSandboxPathMap_[sandboxPath] = srcPath; -+ } -+ -+ if (backupSandboxPathMap_.size() == 0) { -+ return false; -+ } -+ -+ return true; -+} -+ - static int32_t GetPathSuffix(const std::string &path, string &pathSuffix) - { - size_t pos = path.rfind('.'); -@@ -323,6 +358,54 @@ int32_t SandboxHelper::GetPhysicalPath(const std::string &fileUri, const std::st - return 0; - } - -+int32_t SandboxHelper::GetBackupPhysicalPath(const std::string &fileUri, const std::string &userId, -+ std::string &physicalPath) -+{ -+ Uri uri(fileUri); -+ string bundleName = uri.GetAuthority(); -+ if (bundleName == MEDIA) { -+ return GetMediaPhysicalPath(uri.GetPath(), userId, physicalPath); -+ } -+ -+ string sandboxPath = SandboxHelper::Decode(uri.GetPath()); -+ if ((sandboxPath.find(FILE_MANAGER_URI_HEAD) == 0 && bundleName != FILE_MANAGER_AUTHORITY) || -+ (sandboxPath.find(FUSE_URI_HEAD) == 0 && bundleName != DLP_MANAGER_BUNDLE_NAME)) { -+ return -EINVAL; -+ } -+ -+ if (!GetBackupSandboxPathMap()) { -+ LOGE("GetBackupSandboxPathMap failed"); -+ return -EINVAL; -+ } -+ -+ string lowerPathTail = ""; -+ string lowerPathHead = ""; -+ string::size_type curPrefixMatchLen = 0; -+ for (auto it = backupSandboxPathMap_.begin(); it != backupSandboxPathMap_.end(); it++) { -+ string sandboxPathPrefix = it->first; -+ string::size_type prefixMatchLen = sandboxPathPrefix.length(); -+ if (sandboxPath.length() >= prefixMatchLen) { -+ string sandboxPathTemp = sandboxPath.substr(0, prefixMatchLen); -+ if (sandboxPathTemp == sandboxPathPrefix && curPrefixMatchLen <= prefixMatchLen) { -+ curPrefixMatchLen = prefixMatchLen; -+ lowerPathHead = it->second; -+ lowerPathTail = sandboxPath.substr(prefixMatchLen); -+ } -+ } -+ } -+ -+ if (lowerPathHead == "") { -+ LOGE("lowerPathHead is invalid"); -+ return -EINVAL; -+ } -+ -+ string networkId = LOCAL; -+ GetNetworkIdFromUri(fileUri, networkId); -+ -+ physicalPath = GetLowerPath(lowerPathHead, lowerPathTail, userId, bundleName, networkId); -+ return 0; -+} -+ - bool SandboxHelper::IsValidPath(const std::string &path) - { - if (path.find("/./") != std::string::npos || -diff --git a/interfaces/innerkits/native/BUILD.gn b/interfaces/innerkits/native/BUILD.gn -index 7fa9ffa..069d1cd 100644 ---- a/interfaces/innerkits/native/BUILD.gn -+++ b/interfaces/innerkits/native/BUILD.gn -@@ -96,6 +96,13 @@ ohos_prebuilt_etc("file_share_sandbox.json") { - module_install_dir = "etc/app_file_service" - } - -+ohos_prebuilt_etc("backup_sandbox.json") { -+ source = "../../common/backup_sandbox.json" -+ part_name = "app_file_service" -+ subsystem_name = "filemanagement" -+ module_install_dir = "etc/app_file_service" -+} -+ - config("remote_file_share_config") { - visibility = [ ":*" ] - include_dirs = [ -@@ -176,5 +183,8 @@ group("app_file_service_native") { - } - - group("etc_files") { -- deps = [ ":file_share_sandbox.json" ] -+ deps = [ -+ ":backup_sandbox.json", -+ ":file_share_sandbox.json", -+ ] - } -- Gitee From 33def1f182af90808ec467e3a550e42e1caebdf0 Mon Sep 17 00:00:00 2001 From: yang-jingbo1985 Date: Thu, 4 Jan 2024 19:29:40 +0800 Subject: [PATCH 28/35] =?UTF-8?q?=E8=A1=A5=E5=85=85=E9=81=97=E6=BC=8F?= =?UTF-8?q?=E7=9A=84sanboxJSON=E6=96=87=E4=BB=B6=20Signed-off-by:=20yangji?= =?UTF-8?q?ngbo10=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- interfaces/common/backup_sandbox.json | 34 +++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 interfaces/common/backup_sandbox.json diff --git a/interfaces/common/backup_sandbox.json b/interfaces/common/backup_sandbox.json new file mode 100644 index 000000000..d4429ab4d --- /dev/null +++ b/interfaces/common/backup_sandbox.json @@ -0,0 +1,34 @@ +{ + "mount-path-map" : [{ + "sandbox-path" : "/data/storage/el2/base/", + "src-path" : "/data/app/el2//base//" + }, { + "sandbox-path" : "/data/storage/el1/base/", + "src-path" : "/data/app/el1//base//" + }, { + "sandbox-path" : "/data/storage/el1/database/", + "src-path" : "/data/app/el1//database//" + }, { + "sandbox-path" : "/data/storage/el2/database/", + "src-path" : "/data/app/el2//database//" + }, { + "sandbox-path" : "/data/storage/el2/distributedfiles/", + "src-path" : "/mnt/hmdfs//account/device_view//data//" + }, { + "sandbox-path" : "/mnt/data/fuse/", + "src-path" : "/mnt/data//fuse/" + }, { + "sandbox-path" : "/storage/Users/currentUser/", + "src-path" : "/mnt/hmdfs//account/device_view//files/Docs/" + }, { + "sandbox-path" : "/storage/External/", + "src-path" : "/mnt/data/external/" + }, { + "sandbox-path" : "/storage/Share/", + "src-path" : "/data/service/el1/public/storage_daemon/share/public/" + }, { + "sandbox-path" : "/data/storage/el2/cloud/", + "src-path" : "/mnt/hmdfs//cloud/data//" + } + ] +} -- Gitee From ebb331ba809c72548c99cd30e4157d635419f5df Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Thu, 4 Jan 2024 19:34:57 +0800 Subject: [PATCH 29/35] =?UTF-8?q?=E5=A2=9E=E9=87=8F=E5=A4=87=E4=BB=BDnapi?= =?UTF-8?q?=20bug=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- interfaces/kits/js/backup/local_capabilities.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interfaces/kits/js/backup/local_capabilities.cpp b/interfaces/kits/js/backup/local_capabilities.cpp index 0678dbcd8..2e8ad8025 100644 --- a/interfaces/kits/js/backup/local_capabilities.cpp +++ b/interfaces/kits/js/backup/local_capabilities.cpp @@ -96,7 +96,7 @@ static napi_value AsyncDataList(napi_env env, const NFuncArg& funcArg) HILOGI("called LocalCapabilities::AsyncDataList cbExec, failed to get proxy"); return NError(errno); } - *fd = proxy->GetLocalCapabilities(/*backupData*/); + *fd = proxy->GetLocalCapabilitiesIncremental(backupData) return NError(ERRNO_NOERR); }; auto cbCompl = [fd](napi_env env, NError err) -> NVal { -- Gitee From b3f6bbd2e0c7cee296a6464afcf363eee615e130 Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Thu, 4 Jan 2024 19:59:14 +0800 Subject: [PATCH 30/35] =?UTF-8?q?=E9=94=99=E8=AF=AF=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- interfaces/kits/js/backup/local_capabilities.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interfaces/kits/js/backup/local_capabilities.cpp b/interfaces/kits/js/backup/local_capabilities.cpp index 2e8ad8025..85a2dc329 100644 --- a/interfaces/kits/js/backup/local_capabilities.cpp +++ b/interfaces/kits/js/backup/local_capabilities.cpp @@ -96,7 +96,7 @@ static napi_value AsyncDataList(napi_env env, const NFuncArg& funcArg) HILOGI("called LocalCapabilities::AsyncDataList cbExec, failed to get proxy"); return NError(errno); } - *fd = proxy->GetLocalCapabilitiesIncremental(backupData) + *fd = proxy->GetLocalCapabilitiesIncremental(backupData); return NError(ERRNO_NOERR); }; auto cbCompl = [fd](napi_env env, NError err) -> NVal { -- Gitee From fd9172c4491fba2332d508a9159d38e829ba126d Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Thu, 4 Jan 2024 20:40:54 +0800 Subject: [PATCH 31/35] =?UTF-8?q?napi=E9=80=BB=E8=BE=91=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- interfaces/kits/js/backup/local_capabilities.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/interfaces/kits/js/backup/local_capabilities.cpp b/interfaces/kits/js/backup/local_capabilities.cpp index 85a2dc329..1ab71842c 100644 --- a/interfaces/kits/js/backup/local_capabilities.cpp +++ b/interfaces/kits/js/backup/local_capabilities.cpp @@ -18,6 +18,7 @@ #include "filemgmt_libn.h" #include "service_proxy.h" +#include "b_incremental_data.h" #include "incremental_backup_data.h" namespace OHOS::FileManagement::Backup { @@ -60,7 +61,7 @@ static napi_value AsyncCallback(napi_env env, const NFuncArg& funcArg) } } -static std::vector ParseDataList(napi_env env, const napi_value& value) +static std::vector ParseDataList(napi_env env, const napi_value& value) { uint32_t size = 0; napi_status status = napi_get_array_length(env, value, &size); @@ -70,13 +71,18 @@ static std::vector ParseDataList(napi_env env, const napi } napi_value result; - std::vector backupData; + std::vector backupData; for (uint32_t i = 0; i < size; i++) { status = napi_get_element(env, value, i, &result); if (status != napi_ok) { HILOGE("Get element failed! index is :%{public}u", i); } else { - backupData.emplace_back(NVal(env, result)); + IncrementalBackupData data(NVal(env, result)); + backupData.emplace_back(data.bundleName, + data.lastIncrementalTime, + data.manifestFd, + data.parameters, + data.priority); } } return backupData; @@ -86,7 +92,7 @@ static napi_value AsyncDataList(napi_env env, const NFuncArg& funcArg) { HILOGI("called LocalCapabilities::AsyncDataList begin"); - std::vector backupData = ParseDataList(env, funcArg[NARG_POS::FIRST]); + std::vector backupData = ParseDataList(env, funcArg[NARG_POS::FIRST]); auto fd = make_shared(); auto cbExec = [fd, backupData { move(backupData) }]() -> NError { HILOGI("called LocalCapabilities::AsyncDataList cbExec"); -- Gitee From 46bb213bb47259e73bd0f0329b26915e32e8d833 Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Thu, 4 Jan 2024 22:53:29 +0800 Subject: [PATCH 32/35] =?UTF-8?q?backup=5Ftool=20=E5=A4=9A=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E5=A2=9E=E9=87=8F=E5=A4=87=E4=BB=BD=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- .../src/tools_op_incremental_backup.cpp | 21 ++++++++--------- .../src/tools_op_incremental_restore.cpp | 23 ++++++++----------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/tools/backup_tool/src/tools_op_incremental_backup.cpp b/tools/backup_tool/src/tools_op_incremental_backup.cpp index 53cf4f6c6..07144dcea 100644 --- a/tools/backup_tool/src/tools_op_incremental_backup.cpp +++ b/tools/backup_tool/src/tools_op_incremental_backup.cpp @@ -40,16 +40,14 @@ #include "b_resources/b_constants.h" #include "backup_kit_inner.h" #include "base/hiviewdfx/hitrace/interfaces/native/innerkits/include/hitrace_meter/hitrace_meter.h" -#include "out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/include/fcntl.h" -#include "out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/include/stdio.h" #include "service_proxy.h" #include "tools_op.h" -#include "tools_op_backup.h" +#include "tools_op_incremental_backup.h" namespace OHOS::FileManagement::Backup { using namespace std; -class Session { +class SessionBckup { public: void UpdateBundleReceivedFiles(const BundleName &bundleName, const string &fileName) { @@ -64,6 +62,7 @@ public: auto cache = cachedEntity.Structuralize(); lock_guard lk(lock_); bundleStatusMap_[bundleName].indexFile = cache.GetExtManage(); + TryClearBundleOfMap(bundleName); } void TryNotify(bool flag = false) @@ -128,7 +127,7 @@ static string GenHelpMsg() "\t\t--bundle\t\t This parameter is bundleName."; } -static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, UniqueFd fd, UniqueFd manifestFd) +static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, UniqueFd fd, UniqueFd manifestFd) { printf("FileReady owner = %s, fileName = %s, fd = %d, manifestFd = %d\n", fileInfo.owner.c_str(), fileInfo.fileName.c_str(), fd.Get(), manifestFd.Get()); @@ -180,7 +179,7 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq ctx->TryNotify(); } -static void OnBundleStarted(shared_ptr ctx, ErrCode err, const BundleName name) +static void OnBundleStarted(shared_ptr ctx, ErrCode err, const BundleName name) { printf("BundleStarted errCode = %d, BundleName = %s\n", err, name.c_str()); if (err != 0) { @@ -190,14 +189,14 @@ static void OnBundleStarted(shared_ptr ctx, ErrCode err, const BundleNa } } -static void OnBundleFinished(shared_ptr ctx, ErrCode err, const BundleName name) +static void OnBundleFinished(shared_ptr ctx, ErrCode err, const BundleName name) { printf("BundleFinished errCode = %d, BundleName = %s\n", err, name.c_str()); ctx->UpdateBundleFinishedCount(); ctx->TryNotify(); } -static void OnAllBundlesFinished(shared_ptr ctx, ErrCode err) +static void OnAllBundlesFinished(shared_ptr ctx, ErrCode err) { ctx->isAllBundelsFinished.store(true); if (err == 0) { @@ -210,7 +209,7 @@ static void OnAllBundlesFinished(shared_ptr ctx, ErrCode err) ctx->TryNotify(); } -static void OnBackupServiceDied(shared_ptr ctx) +static void OnBackupServiceDied(shared_ptr ctx) { printf("backupServiceDied\n"); ctx->TryNotify(true); @@ -251,7 +250,7 @@ static void BackupToolDirSoftlinkToBackupDir() } } -static int GetLocalCapabilitiesIncremental(shared_ptr ctx, +static int GetLocalCapabilitiesIncremental(shared_ptr ctx, const string &pathCapFile, const vector &bundleNames, const vector ×) @@ -293,7 +292,7 @@ static int32_t Init(const string &pathCapFile, vector bundleNames, vecto // SELinux backup_tool工具/data/文件夹下创建文件夹 SA服务因root用户的自定义标签无写入权限 此处调整为软链接形式 BackupToolDirSoftlinkToBackupDir(); - auto ctx = make_shared(); + auto ctx = make_shared(); ctx->session_ = BIncrementalBackupSession::Init(BIncrementalBackupSession::Callbacks { .onFileReady = bind(OnFileReady, ctx, placeholders::_1, placeholders::_2, placeholders::_3), .onBundleStarted = bind(OnBundleStarted, ctx, placeholders::_1, placeholders::_2), diff --git a/tools/backup_tool/src/tools_op_incremental_restore.cpp b/tools/backup_tool/src/tools_op_incremental_restore.cpp index d90646ffb..bcbd9212f 100644 --- a/tools/backup_tool/src/tools_op_incremental_restore.cpp +++ b/tools/backup_tool/src/tools_op_incremental_restore.cpp @@ -41,12 +41,12 @@ #include "errors.h" #include "service_proxy.h" #include "tools_op.h" -#include "tools_op_restore.h" +#include "tools_op_incremental_restore.h" namespace OHOS::FileManagement::Backup { using namespace std; -class Session { +class SessionRestore { public: void UpdateBundleSendFiles(const BundleName &bundleName, const string &fileName) { @@ -121,7 +121,7 @@ static string GenHelpMsg() "\t\t--bundle\t\t This parameter is bundleName."; } -static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, UniqueFd fd, UniqueFd manifestFd) +static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, UniqueFd fd, UniqueFd manifestFd) { printf("FileReady owner = %s, fileName = %s, sn = %u, fd = %d\n", fileInfo.owner.c_str(), fileInfo.fileName.c_str(), fileInfo.sn, fd.Get()); @@ -137,7 +137,6 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq string tmpPath = string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + fileInfo.owner + "/" + to_string(iter->lastIncrementalTime) + string(BConstants::BACKUP_TOOL_INCREMENTAL) + "/" + fileInfo.fileName; - printf("tmpPath = %s\n", tmpPath.data()); if (access(tmpPath.data(), F_OK) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } @@ -150,7 +149,6 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq tmpPath = string(BConstants::BACKUP_TOOL_INCREMENTAL_RECEIVE_DIR) + fileInfo.owner + "/" + to_string(iter->lastIncrementalTime) + string(BConstants::BACKUP_TOOL_MANIFEST) + "/" + fileInfo.fileName + ".rp"; - printf("tmpPath = %s\n", tmpPath.data()); if (access(tmpPath.data(), F_OK) == 0) { UniqueFd fdManifest(open(tmpPath.data(), O_RDONLY)); if (fdManifest < 0) { @@ -166,7 +164,7 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq ctx->TryNotify(); } -static void OnBundleStarted(shared_ptr ctx, ErrCode err, const BundleName name) +static void OnBundleStarted(shared_ptr ctx, ErrCode err, const BundleName name) { printf("BundleStarted errCode = %d, BundleName = %s\n", err, name.c_str()); if (err != 0) { @@ -177,7 +175,7 @@ static void OnBundleStarted(shared_ptr ctx, ErrCode err, const BundleNa } } -static void OnBundleFinished(shared_ptr ctx, ErrCode err, const BundleName name) +static void OnBundleFinished(shared_ptr ctx, ErrCode err, const BundleName name) { printf("BundleFinished errCode = %d, BundleName = %s\n", err, name.c_str()); ctx->UpdateBundleFinishedCount(); @@ -188,7 +186,7 @@ static void OnBundleFinished(shared_ptr ctx, ErrCode err, const BundleN ctx->TryNotify(); } -static void OnAllBundlesFinished(shared_ptr ctx, ErrCode err) +static void OnAllBundlesFinished(shared_ptr ctx, ErrCode err) { ctx->isAllBundelsFinished.store(true); if (err == 0) { @@ -201,13 +199,13 @@ static void OnAllBundlesFinished(shared_ptr ctx, ErrCode err) ctx->TryNotify(); } -static void OnBackupServiceDied(shared_ptr ctx) +static void OnBackupServiceDied(shared_ptr ctx) { printf("backupServiceDied\n"); ctx->TryNotify(true); } -static void RestoreApp(shared_ptr restore) +static void RestoreApp(shared_ptr restore) { StartTrace(HITRACE_TAG_FILEMANAGEMENT, "RestoreApp"); if (!restore || !restore->session_) { @@ -226,7 +224,6 @@ static void RestoreApp(shared_ptr restore) for (auto &filePath : filePaths) { string fileName = filePath.substr(filePath.rfind("/") + 1); restore->session_->GetFileHandle(data.bundleName, fileName); - printf("GetFileHandle bundleName = %s, fileName = %s\n", data.bundleName.c_str(), fileName.c_str()); restore->UpdateBundleSendFiles(data.bundleName, fileName); } } @@ -248,7 +245,7 @@ static bool GetRealPath(string &path) return true; } -static int32_t InitRestoreSession(shared_ptr ctx, vector &bundleNames, vector ×) +static int32_t InitRestoreSession(shared_ptr ctx, vector &bundleNames, vector ×) { if (bundleNames.size() != times.size()) { fprintf(stderr, "Inconsistent amounts of bundles and incrementalTime!\n"); @@ -290,7 +287,7 @@ static int32_t Init(const string &pathCapFile, vector bundleNames, bool } UniqueFd fd(open(realPath.data(), O_RDWR, S_IRWXU)); - auto ctx = make_shared(); + auto ctx = make_shared(); int32_t ret = InitRestoreSession(ctx, bundleNames, times); if (ret != 0) { printf("Failed to init restore session error:%d\n", ret); -- Gitee From 47b3c85e8ea53ed2015ce924e9351e8b8ab8d8d8 Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Fri, 5 Jan 2024 17:30:03 +0800 Subject: [PATCH 33/35] =?UTF-8?q?napi=E4=BB=A3=E7=A0=81=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- .../kits/js/backup/session_incremental_backup_n_exporter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interfaces/kits/js/backup/session_incremental_backup_n_exporter.h b/interfaces/kits/js/backup/session_incremental_backup_n_exporter.h index 3baa8d73f..475465689 100644 --- a/interfaces/kits/js/backup/session_incremental_backup_n_exporter.h +++ b/interfaces/kits/js/backup/session_incremental_backup_n_exporter.h @@ -20,7 +20,7 @@ namespace OHOS::FileManagement::Backup { class SessionIncrementalBackupNExporter final : public LibN::NExporter { public: - inline static const std::string className = "SessionIncrementalBackup"; + inline static const std::string className = "IncrementalBackupSession"; bool Export() override; std::string GetClassName() override; -- Gitee From 3ffa20c65e276019cae04ccf09e798631dce4906 Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Tue, 9 Jan 2024 17:44:56 +0800 Subject: [PATCH 34/35] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=A2=9E=E9=87=8F?= =?UTF-8?q?=E5=A4=87=E4=BB=BDnapi=E5=B1=82manifestFd=E4=BC=A0=E9=80=92?= =?UTF-8?q?=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- .../kits/js/backup/session_incremental_backup_n_exporter.cpp | 2 +- interfaces/kits/js/backup/session_restore_n_exporter.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interfaces/kits/js/backup/session_incremental_backup_n_exporter.cpp b/interfaces/kits/js/backup/session_incremental_backup_n_exporter.cpp index cf0e0e742..1ef3f451a 100644 --- a/interfaces/kits/js/backup/session_incremental_backup_n_exporter.cpp +++ b/interfaces/kits/js/backup/session_incremental_backup_n_exporter.cpp @@ -56,7 +56,7 @@ static void OnFileReady(weak_ptr pCallbacks, const BFileInfo & auto cbCompl = [bundleName {fileInfo.owner}, fileName {fileInfo.fileName}, fd {make_shared(fd.Release())}, - manifestFd {make_shared(fd.Release())}](napi_env env, NError err) -> NVal { + manifestFd {make_shared(manifestFd.Release())}](napi_env env, NError err) -> NVal { if (err) { return {env, err.GetNapiErr(env)}; } diff --git a/interfaces/kits/js/backup/session_restore_n_exporter.cpp b/interfaces/kits/js/backup/session_restore_n_exporter.cpp index 1703d1e22..51e64b894 100644 --- a/interfaces/kits/js/backup/session_restore_n_exporter.cpp +++ b/interfaces/kits/js/backup/session_restore_n_exporter.cpp @@ -93,7 +93,7 @@ static void OnFileReadySheet(weak_ptr pCallbacks, auto cbCompl = [bundleName {fileInfo.owner}, fileName {fileInfo.fileName}, fd {make_shared(fd.Release())}, - manifestFd {make_shared(fd.Release())}](napi_env env, NError err) -> NVal { + manifestFd {make_shared(manifestFd.Release())}](napi_env env, NError err) -> NVal { if (err) { return {env, err.GetNapiErr(env)}; } -- Gitee From 5fbdc8dc46125af160bfea1e5dcbb5d9d4010bed Mon Sep 17 00:00:00 2001 From: huaqingsimeng Date: Mon, 22 Jan 2024 14:24:33 +0800 Subject: [PATCH 35/35] =?UTF-8?q?backup=5Ftool=20=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huaqingsimeng --- .../src/tools_op_incremental_backup.cpp | 9 ++++---- .../src/tools_op_incremental_restore.cpp | 22 +++++++++---------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/tools/backup_tool/src/tools_op_incremental_backup.cpp b/tools/backup_tool/src/tools_op_incremental_backup.cpp index 07144dcea..f16db9906 100644 --- a/tools/backup_tool/src/tools_op_incremental_backup.cpp +++ b/tools/backup_tool/src/tools_op_incremental_backup.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include "tools_op_incremental_backup.h" + #include #include #include @@ -42,7 +44,6 @@ #include "base/hiviewdfx/hitrace/interfaces/native/innerkits/include/hitrace_meter/hitrace_meter.h" #include "service_proxy.h" #include "tools_op.h" -#include "tools_op_incremental_backup.h" namespace OHOS::FileManagement::Backup { using namespace std; @@ -288,7 +289,7 @@ static int GetLocalCapabilitiesIncremental(shared_ptr ctx, static int32_t Init(const string &pathCapFile, vector bundleNames, vector times) { - StartTrace(HITRACE_TAG_FILEMANAGEMENT, "InitPathCapFile"); + StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Init"); // SELinux backup_tool工具/data/文件夹下创建文件夹 SA服务因root用户的自定义标签无写入权限 此处调整为软链接形式 BackupToolDirSoftlinkToBackupDir(); @@ -330,7 +331,7 @@ static int32_t Init(const string &pathCapFile, vector bundleNames, vecto return 0; } -static int Exec(map> &mapArgToVal) +static int g_exec(map> &mapArgToVal) { if (mapArgToVal.find("pathCapFile") == mapArgToVal.end() || mapArgToVal.find("bundles") == mapArgToVal.end() || mapArgToVal.find("incrementalTime") == mapArgToVal.end()) { @@ -356,7 +357,7 @@ bool IncrementalBackUpRegister() .repeatable = true, }}, .funcGenHelpMsg = GenHelpMsg, - .funcExec = Exec, + .funcExec = g_exec, }}); } } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tools/backup_tool/src/tools_op_incremental_restore.cpp b/tools/backup_tool/src/tools_op_incremental_restore.cpp index bcbd9212f..ffab7d1e5 100644 --- a/tools/backup_tool/src/tools_op_incremental_restore.cpp +++ b/tools/backup_tool/src/tools_op_incremental_restore.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include "tools_op_incremental_restore.h" + #include #include #include @@ -31,6 +33,7 @@ #include #include "b_error/b_error.h" +#include "b_error/b_excep_utils.h" #include "b_filesystem/b_dir.h" #include "b_filesystem/b_file.h" #include "b_json/b_json_entity_caps.h" @@ -41,7 +44,6 @@ #include "errors.h" #include "service_proxy.h" #include "tools_op.h" -#include "tools_op_incremental_restore.h" namespace OHOS::FileManagement::Backup { using namespace std; @@ -232,20 +234,16 @@ static void RestoreApp(shared_ptr restore) static bool GetRealPath(string &path) { - unique_ptr absPath = make_unique(PATH_MAX + 1); - if (realpath(path.c_str(), absPath.get()) == nullptr) { + string absPath = BExcepUltils::Canonicalize(path); + if (access(absPath.data(), F_OK) != 0) { return false; } - - path = absPath.get(); - if (access(path.data(), F_OK) != 0) { - return false; - } - return true; } -static int32_t InitRestoreSession(shared_ptr ctx, vector &bundleNames, vector ×) +static int32_t InitRestoreSession(shared_ptr ctx, + vector &bundleNames, + vector ×) { if (bundleNames.size() != times.size()) { fprintf(stderr, "Inconsistent amounts of bundles and incrementalTime!\n"); @@ -322,7 +320,7 @@ static int32_t Init(const string &pathCapFile, vector bundleNames, bool return 0; } -static int Exec(map> &mapArgToVal) +static int g_exec(map> &mapArgToVal) { bool depMode = false; if (mapArgToVal.find("depMode") != mapArgToVal.end()) { @@ -358,7 +356,7 @@ bool IncrementalRestoreRegister() .repeatable = true, }}, .funcGenHelpMsg = GenHelpMsg, - .funcExec = Exec, + .funcExec = g_exec, }}); } } // namespace OHOS::FileManagement::Backup \ No newline at end of file -- Gitee