From f05a23653cbd392aa4ed159491678bced77d8005 Mon Sep 17 00:00:00 2001 From: huaqingsimeng <1004904143@qq.com> Date: Wed, 29 Mar 2023 08:55:31 +0000 Subject: [PATCH] =?UTF-8?q?=20=E5=A4=87=E4=BB=BD=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E6=8F=90=E4=BE=9Bjs=E6=8E=A5=E5=8F=A3=E8=83=BD=E5=8A=9B-?= =?UTF-8?q?=E5=A4=87=E4=BB=BD=E6=81=A2=E5=A4=8D=E8=83=BD=E5=8A=9B=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=BB=93=E6=9E=84=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 --- backup.gni | 2 +- bundle.json | 3 +- .../backup_kit_inner/src/b_session_backup.cpp | 6 +- .../src/b_session_restore.cpp | 18 +- .../backup_kit_inner/src/service_proxy.cpp | 21 +- .../backup_kit_inner/impl/b_session_backup.h | 7 +- .../backup_kit_inner/impl/b_session_restore.h | 14 +- .../native/backup_kit_inner/impl/i_service.h | 10 +- .../backup_kit_inner/impl/service_proxy.h | 8 +- interfaces/kits/js/backup/general_callbacks.h | 42 +++ interfaces/kits/js/backup/module.cpp | 47 +++ interfaces/kits/js/backup/prop_n_exporter.cpp | 38 +++ interfaces/kits/js/backup/prop_n_exporter.h | 34 +++ .../js/backup/session_backup_n_exporter.cpp | 279 ++++++++++++++++++ .../js/backup/session_backup_n_exporter.h | 35 +++ services/backup.cfg | 3 +- services/backup_sa/BUILD.gn | 4 + .../include/module_external/bms_adapter.h | 54 ++++ .../module_external/inner_receiver_impl.h | 48 +++ .../include/module_external/sms_adapter.h | 34 +++ .../backup_sa/include/module_ipc/service.h | 21 +- .../include/module_ipc/service_stub.h | 2 +- .../include/module_ipc/svc_session_manager.h | 82 ++++- .../include/module_sched/sched_scheduler.h | 11 + .../src/module_external/bms_adapter.cpp | 137 +++++++++ .../module_external/inner_receiver_impl.cpp | 44 +++ .../src/module_external/sms_adapter.cpp | 52 ++++ services/backup_sa/src/module_ipc/service.cpp | 125 ++++---- .../backup_sa/src/module_ipc/service_stub.cpp | 45 +-- .../src/module_ipc/svc_session_manager.cpp | 239 +++++++++------ .../src/module_sched/sched_scheduler.cpp | 54 +++- tests/unittests/backup_utils/BUILD.gn | 5 +- tools/backup_tool/src/tools_op_backup.cpp | 42 +-- tools/backup_tool/src/tools_op_restore.cpp | 108 ++++--- utils/BUILD.gn | 4 + utils/include/b_error/b_error.h | 45 ++- utils/include/b_json/b_json_entity_caps.h | 78 +++-- utils/include/b_resources/b_constants.h | 12 +- utils/src/b_error/b_error.cpp | 15 + utils/src/b_filesystem/b_file.cpp | 4 + utils/src/b_json/b_json_entity_ext_manage.cpp | 8 + 41 files changed, 1487 insertions(+), 353 deletions(-) create mode 100644 interfaces/kits/js/backup/general_callbacks.h create mode 100644 interfaces/kits/js/backup/module.cpp create mode 100644 interfaces/kits/js/backup/prop_n_exporter.cpp create mode 100644 interfaces/kits/js/backup/prop_n_exporter.h create mode 100644 interfaces/kits/js/backup/session_backup_n_exporter.cpp create mode 100644 interfaces/kits/js/backup/session_backup_n_exporter.h create mode 100644 services/backup_sa/include/module_external/bms_adapter.h create mode 100644 services/backup_sa/include/module_external/inner_receiver_impl.h create mode 100644 services/backup_sa/include/module_external/sms_adapter.h create mode 100644 services/backup_sa/src/module_external/bms_adapter.cpp create mode 100644 services/backup_sa/src/module_external/inner_receiver_impl.cpp create mode 100644 services/backup_sa/src/module_external/sms_adapter.cpp diff --git a/backup.gni b/backup.gni index 7dc5c0e87..18af02ca6 100644 --- a/backup.gni +++ b/backup.gni @@ -25,7 +25,7 @@ path_jsoncpp = "//third_party/jsoncpp" path_napi = "//foundation/arkui/napi" path_samgr = "//foundation/systemabilitymgr/samgr" path_init = "//base/startup/init" - +path_filemgmt_libn = "//foundation/filemanagement/file_api/utils/filemgmt_libn" path_backup_mock = "//foundation/filemanagement/app_file_service/tests/mock" backup_mock_parcel_include_dirs = [ "$path_backup_mock/parcel/include" ] diff --git a/bundle.json b/bundle.json index fc02fdb76..92a968337 100644 --- a/bundle.json +++ b/bundle.json @@ -74,8 +74,7 @@ ], "test": [ "//foundation/filemanagement/app_file_service/test/fuzztest:fuzztest", - "//foundation/filemanagement/app_file_service/test/unittest:unittest", - "//foundation/filemanagement/app_file_service:tgt_backup_tests" + "//foundation/filemanagement/app_file_service/test/unittest:unittest" ] } } 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 976336618..a798cd391 100644 --- a/frameworks/native/backup_kit_inner/src/b_session_backup.cpp +++ b/frameworks/native/backup_kit_inner/src/b_session_backup.cpp @@ -40,9 +40,7 @@ BSessionBackup::~BSessionBackup() deathRecipient_ = nullptr; } -unique_ptr BSessionBackup::Init(UniqueFd remoteCap, - vector bundlesToBackup, - Callbacks callbacks) +unique_ptr BSessionBackup::Init(Callbacks callbacks) { try { auto backup = make_unique(); @@ -52,7 +50,7 @@ unique_ptr BSessionBackup::Init(UniqueFd remoteCap, return nullptr; } - int32_t res = proxy->InitBackupSession(sptr(new ServiceReverse(callbacks)), move(remoteCap), bundlesToBackup); + int32_t res = proxy->InitBackupSession(sptr(new ServiceReverse(callbacks))); if (res != 0) { HILOGE("Failed to Backup because of %{public}d", res); return nullptr; 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 6fc1db385..f640d7abf 100644 --- a/frameworks/native/backup_kit_inner/src/b_session_restore.cpp +++ b/frameworks/native/backup_kit_inner/src/b_session_restore.cpp @@ -40,7 +40,7 @@ BSessionRestore::~BSessionRestore() deathRecipient_ = nullptr; } -unique_ptr BSessionRestore::Init(std::vector bundlesToRestore, Callbacks callbacks) +unique_ptr BSessionRestore::Init(Callbacks callbacks) { try { auto restore = make_unique(); @@ -49,7 +49,7 @@ unique_ptr BSessionRestore::Init(std::vector bundle HILOGI("Failed to get backup service"); return nullptr; } - int32_t res = proxy->InitRestoreSession(new ServiceReverse(callbacks), bundlesToRestore); + int32_t res = proxy->InitRestoreSession(new ServiceReverse(callbacks)); if (res != 0) { HILOGE("Failed to Restore because of %{public}d", res); return nullptr; @@ -63,16 +63,6 @@ unique_ptr BSessionRestore::Init(std::vector bundle return nullptr; } -UniqueFd BSessionRestore::GetLocalCapabilities() -{ - auto proxy = ServiceProxy::GetInstance(); - if (proxy == nullptr) { - HILOGI("Failed to get backup service"); - return UniqueFd(-1); - } - return UniqueFd(proxy->GetLocalCapabilities()); -} - ErrCode BSessionRestore::PublishFile(BFileInfo fileInfo) { auto proxy = ServiceProxy::GetInstance(); @@ -92,14 +82,14 @@ ErrCode BSessionRestore::Start() return proxy->Start(); } -ErrCode BSessionRestore::GetExtFileName(string &bundleName, string &fileName) +ErrCode BSessionRestore::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->GetExtFileName(bundleName, fileName); + return proxy->GetFileHandle(bundleName, fileName); } ErrCode BSessionRestore::AppendBundles(UniqueFd remoteCap, vector bundlesToRestore) diff --git a/frameworks/native/backup_kit_inner/src/service_proxy.cpp b/frameworks/native/backup_kit_inner/src/service_proxy.cpp index e35abfd43..e6b2dc95c 100644 --- a/frameworks/native/backup_kit_inner/src/service_proxy.cpp +++ b/frameworks/native/backup_kit_inner/src/service_proxy.cpp @@ -26,7 +26,7 @@ namespace OHOS::FileManagement::Backup { using namespace std; using namespace BExcepUltils; -int32_t ServiceProxy::InitRestoreSession(sptr remote, const std::vector &bundleNames) +ErrCode ServiceProxy::InitRestoreSession(sptr remote) { HILOGI("Begin"); BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); @@ -44,10 +44,6 @@ int32_t ServiceProxy::InitRestoreSession(sptr remote, const std return BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the reverse stub").GetCode(); } - if (!data.WriteStringVector(bundleNames)) { - return BError(BError::Codes::SDK_INVAL_ARG, "Failed to send bundleNames").GetCode(); - } - int32_t ret = Remote()->SendRequest(IService::SERVICE_CMD_INIT_RESTORE_SESSION, data, reply, option); if (ret != NO_ERROR) { string str = "Failed to send out the request because of " + to_string(ret); @@ -56,9 +52,7 @@ int32_t ServiceProxy::InitRestoreSession(sptr remote, const std return reply.ReadInt32(); } -int32_t ServiceProxy::InitBackupSession(sptr remote, - UniqueFd fd, - const std::vector &bundleNames) +ErrCode ServiceProxy::InitBackupSession(sptr remote) { HILOGI("Begin"); BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); @@ -76,13 +70,6 @@ int32_t ServiceProxy::InitBackupSession(sptr remote, return BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the reverse stub").GetCode(); } - if (!data.WriteFileDescriptor(fd)) { - return BError(BError::Codes::SDK_INVAL_ARG, "Failed to send the fd").GetCode(); - } - if (!data.WriteStringVector(bundleNames)) { - return BError(BError::Codes::SDK_INVAL_ARG, "Failed to send bundleNames").GetCode(); - } - int32_t ret = Remote()->SendRequest(IService::SERVICE_CMD_INIT_BACKUP_SESSION, data, reply, option); if (ret != NO_ERROR) { string str = "Failed to send out the request because of " + to_string(ret); @@ -204,7 +191,7 @@ ErrCode ServiceProxy::AppDone(ErrCode errCode) return reply.ReadInt32(); } -ErrCode ServiceProxy::GetExtFileName(string &bundleName, string &fileName) +ErrCode ServiceProxy::GetFileHandle(const string &bundleName, const string &fileName) { HILOGI("Begin"); BAssert(Remote(), BError::Codes::SDK_INVAL_ARG, "Remote is nullptr"); @@ -223,7 +210,7 @@ ErrCode ServiceProxy::GetExtFileName(string &bundleName, string &fileName) MessageParcel reply; MessageOption option; option.SetFlags(MessageOption::TF_ASYNC); - int32_t ret = Remote()->SendRequest(IService::SERVICE_CMD_GET_EXT_FILE_NAME, data, reply, option); + int32_t ret = Remote()->SendRequest(IService::SERVICE_CMD_GET_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(); 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 7ab3e2519..059e3b798 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 @@ -40,13 +40,10 @@ public: /** * @brief 获取一个用于控制备份流程的会话 * - * @param remoteCap 已打开的保存远端设备能力的Json文件。可使用BRestoreSession的GetLocalCapabilities方法获取 - * @param bundlesToBackup 待备份应用清单 + * @param callbacks 注册回调 * @return std::unique_ptr 指向会话的智能指针。失败时为空指针 */ - static std::unique_ptr Init(UniqueFd remoteCap, - std::vector bundlesToBackup, - Callbacks callbacks); + static std::unique_ptr Init(Callbacks callbacks); /** * @brief 用于追加应用,现阶段仅支持在Start之前调用 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 308084eae..4654a7bc5 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 @@ -40,25 +40,17 @@ public: /** * @brief 获取一个用于控制恢复流程的会话 * - * @param bundlesToRestore 待恢复应用清单 * @param callbacks 注册的回调函数 * @return std::unique_ptr 指向BRestoreSession的智能指针。失败时为空指针 */ - static std::unique_ptr Init(std::vector bundlesToRestore, Callbacks callbacks); - - /** - * @brief 获取用于描述本端能力的Json文件 - * - * @return UniqueFd 文件描述符 - */ - UniqueFd GetLocalCapabilities(); + static std::unique_ptr Init(Callbacks callbacks); /** * @brief 通知备份服务文件内容已就绪 * * @param fileInfo 文件描述信息 * @return ErrCode 规范错误码 - * @see GetExtFileName + * @see GetFileHandle */ ErrCode PublishFile(BFileInfo fileInfo); @@ -68,7 +60,7 @@ public: * @param bundleName 应用名称 * @param fileName 文件名称 */ - ErrCode GetExtFileName(std::string &bundleName, std::string &fileName); + ErrCode GetFileHandle(const std::string &bundleName, const std::string &fileName); /** * @brief 用于追加应用,现阶段仅支持在Start之前调用 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 3dbe01b78..3e8af262c 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 @@ -36,22 +36,20 @@ public: SERVICE_CMD_APP_FILE_READY, SERVICE_CMD_APP_DONE, SERVICE_CMD_START, - SERVICE_CMD_GET_EXT_FILE_NAME, + SERVICE_CMD_GET_FILE_NAME, SERVICE_CMD_APPEND_BUNDLES_RESTORE_SESSION, SERVICE_CMD_APPEND_BUNDLES_BACKUP_SESSION, SERVICE_CMD_FINISH, }; - virtual ErrCode InitRestoreSession(sptr remote, const std::vector &bundleNames) = 0; - virtual ErrCode InitBackupSession(sptr remote, - UniqueFd fd, - const std::vector &bundleNames) = 0; + virtual ErrCode InitRestoreSession(sptr remote) = 0; + virtual ErrCode InitBackupSession(sptr remote) = 0; virtual ErrCode Start() = 0; virtual UniqueFd GetLocalCapabilities() = 0; virtual ErrCode PublishFile(const BFileInfo &fileInfo) = 0; virtual ErrCode AppFileReady(const std::string &fileName, UniqueFd fd) = 0; virtual ErrCode AppDone(ErrCode errCode) = 0; - virtual ErrCode GetExtFileName(std::string &bundleName, std::string &fileName) = 0; + virtual ErrCode GetFileHandle(const std::string &bundleName, const std::string &fileName) = 0; virtual ErrCode AppendBundlesRestoreSession(UniqueFd fd, const std::vector &bundleNames) = 0; virtual ErrCode AppendBundlesBackupSession(const std::vector &bundleNames) = 0; virtual ErrCode Finish() = 0; 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 18ef4a0f3..8033b7f10 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 @@ -28,16 +28,14 @@ namespace OHOS::FileManagement::Backup { class ServiceProxy : public IRemoteProxy { public: - ErrCode InitRestoreSession(sptr remote, const std::vector &bundleNames) override; - ErrCode InitBackupSession(sptr remote, - UniqueFd fd, - const std::vector &bundleNames) override; + ErrCode InitRestoreSession(sptr remote) override; + ErrCode InitBackupSession(sptr remote) override; ErrCode Start() override; UniqueFd GetLocalCapabilities() override; ErrCode PublishFile(const BFileInfo &fileInfo) override; ErrCode AppFileReady(const std::string &fileName, UniqueFd fd) override; ErrCode AppDone(ErrCode errCode) override; - ErrCode GetExtFileName(std::string &bundleName, std::string &fileName) override; + ErrCode GetFileHandle(const std::string &bundleName, const std::string &fileName) override; ErrCode AppendBundlesRestoreSession(UniqueFd fd, const std::vector &bundleNames) override; ErrCode AppendBundlesBackupSession(const std::vector &bundleNames) override; ErrCode Finish() override; diff --git a/interfaces/kits/js/backup/general_callbacks.h b/interfaces/kits/js/backup/general_callbacks.h new file mode 100644 index 000000000..6bde169b8 --- /dev/null +++ b/interfaces/kits/js/backup/general_callbacks.h @@ -0,0 +1,42 @@ +/* + * 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_GENERAL_CALLBACKS_H +#define INTERFACES_KITS_JS_SRC_MOD_BACKUP_PROPERTIES_GENERAL_CALLBACKS_H + +#include +#include +#include + +#include "filemgmt_libn.h" + +namespace OHOS::FileManagement::Backup { +class GeneralCallbacks { +public: + GeneralCallbacks(const napi_env &env, const LibN::NVal &thisPtr, const LibN::NVal &jsCallbacks) + : onFileReady(env, thisPtr, jsCallbacks.GetProp("onFileReady")), + onBundleBegin(env, thisPtr, jsCallbacks.GetProp("onBundleBegin")), + onBundleEnd(env, thisPtr, jsCallbacks.GetProp("onBundleEnd")), + onAllBundlesEnd(env, thisPtr, jsCallbacks.GetProp("onAllBundlesEnd")), + onBackupServiceDied(env, thisPtr, jsCallbacks.GetProp("onBackupServiceDied")) {}; + +public: + LibN::NAsyncWorkCallback onFileReady; + LibN::NAsyncWorkCallback onBundleBegin; + LibN::NAsyncWorkCallback onBundleEnd; + LibN::NAsyncWorkCallback onAllBundlesEnd; + LibN::NAsyncWorkCallback onBackupServiceDied; +}; +} // namespace OHOS::FileManagement::Backup +#endif // INTERFACES_KITS_JS_SRC_MOD_BACKUP_PROPERTIES_GENERAL_CALLBACKS_H \ No newline at end of file diff --git a/interfaces/kits/js/backup/module.cpp b/interfaces/kits/js/backup/module.cpp new file mode 100644 index 000000000..6a0cc1ec1 --- /dev/null +++ b/interfaces/kits/js/backup/module.cpp @@ -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. + */ + +#include +#include + +#include "filemgmt_libhilog.h" +#include "filemgmt_libn.h" +#include "prop_n_exporter.h" +#include "session_backup_n_exporter.h" +#include "session_restore_n_exporter.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; +using namespace LibN; + +static napi_value Export(napi_env env, napi_value exports) +{ + std::vector> products; + 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 backup", product->GetClassName().c_str()); + return nullptr; + } else { + HILOGI("Class %{public}s for module fileio has been exported", product->GetClassName().c_str()); + } + } + return exports; +} + +NAPI_MODULE(backup, Export) +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/interfaces/kits/js/backup/prop_n_exporter.cpp b/interfaces/kits/js/backup/prop_n_exporter.cpp new file mode 100644 index 000000000..572a46db4 --- /dev/null +++ b/interfaces/kits/js/backup/prop_n_exporter.cpp @@ -0,0 +1,38 @@ +/* + * 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 "prop_n_exporter.h" + +#include "local_capabilities.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; +using namespace LibN; + +bool PropNExporter::Export() +{ + return exports_.AddProp({ + NVal::DeclareNapiFunction("getLocalCapabilities", LocalCapabilities::Async), + }); +} + +string PropNExporter::GetClassName() +{ + return PropNExporter::className; +} + +PropNExporter::PropNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {} + +PropNExporter::~PropNExporter() {} +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/interfaces/kits/js/backup/prop_n_exporter.h b/interfaces/kits/js/backup/prop_n_exporter.h new file mode 100644 index 000000000..defb4c78a --- /dev/null +++ b/interfaces/kits/js/backup/prop_n_exporter.h @@ -0,0 +1,34 @@ +/* + * 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_PROP_N_EXPORTER_H +#define INTERFACES_KITS_JS_SRC_MOD_BACKUP_PROPERTIES_PROP_N_EXPORTER_H + +#include + +#include "filemgmt_libn.h" + +namespace OHOS::FileManagement::Backup { +class PropNExporter final : public LibN::NExporter { +public: + inline static const std::string className = "LocalCapabilities"; + + bool Export() override; + std::string GetClassName() override; + + PropNExporter(napi_env env, napi_value exports); + ~PropNExporter() override; +}; +} // namespace OHOS::FileManagement::Backup +#endif // INTERFACES_KITS_JS_SRC_MOD_BACKUP_PROPERTIES_PROP_N_EXPORTER_H \ No newline at end of file diff --git a/interfaces/kits/js/backup/session_backup_n_exporter.cpp b/interfaces/kits/js/backup/session_backup_n_exporter.cpp new file mode 100644 index 000000000..e3a5a1303 --- /dev/null +++ b/interfaces/kits/js/backup/session_backup_n_exporter.cpp @@ -0,0 +1,279 @@ +/* + * 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_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_session_backup.h" +#include "backup_kit_inner.h" +#include "directory_ex.h" +#include "filemgmt_libhilog.h" +#include "general_callbacks.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) +{ + 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())}](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_)}); + + 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}](napi_env env, NError err) -> NVal { + return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUTF8String(env, name); + }; + + 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}](napi_env env, NError err) -> NVal { + return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUTF8String(env, name); + }; + + 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 = [](napi_env env, NError err) -> NVal { + return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env); + }; + + 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 SessionBackupNExporter::Constructor(napi_env env, napi_callback_info cbinfo) +{ + HILOGI("called SessionBackup::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 = BSessionBackup::Init(BSessionBackup::Callbacks { + .onFileReady = bind(OnFileReady, backupEntity->callbacks, placeholders::_1, placeholders::_2), + .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 SessionBackup::Constructor end"); + return funcArg.GetThisVar(); +} + +napi_value SessionBackupNExporter::AppendBundles(napi_env env, napi_callback_info cbinfo) +{ + HILOGI("called SessionBackup::AppendBundles begin"); + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + NVal jsBundles(env, funcArg[NARG_POS::FIRST]); + auto [succ, bundles, ignore] = jsBundles.ToStringArray(); + if (!succ) { + HILOGE("First argument is not bundles array."); + 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()}, bundles {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 SessionBackup::AppendBundles end."); + + NVal thisVar(env, funcArg.GetThisVar()); + if (funcArg.GetArgc() == NARG_CNT::ONE) { + return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_; + } else { + NVal cb(env, funcArg[NARG_POS::SECOND]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(className, cbExec, cbCompl).val_; + } +} + +bool SessionBackupNExporter::Export() +{ + HILOGI("called SessionBackupNExporter::Export begin"); + vector props = {NVal::DeclareNapiFunction("appendBundles", AppendBundles)}; + + 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 SessionBackupNExporter::Export end"); + return exports_.AddProp(className, classValue); +} + +string SessionBackupNExporter::GetClassName() +{ + return SessionBackupNExporter::className; +} + +SessionBackupNExporter::SessionBackupNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {} + +SessionBackupNExporter::~SessionBackupNExporter() {} +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/interfaces/kits/js/backup/session_backup_n_exporter.h b/interfaces/kits/js/backup/session_backup_n_exporter.h new file mode 100644 index 000000000..afa3c96b2 --- /dev/null +++ b/interfaces/kits/js/backup/session_backup_n_exporter.h @@ -0,0 +1,35 @@ +/* + * 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_BACKUP_N_EXPORTER_H +#define INTERFACES_KITS_JS_SRC_MOD_BACKUP_PROPERTIES_SESSION_BACKUP_N_EXPORTER_H + +#include "n_exporter.h" + +namespace OHOS::FileManagement::Backup { +class SessionBackupNExporter final : public LibN::NExporter { +public: + inline static const std::string className = "SessionBackup"; + + 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); + + SessionBackupNExporter(napi_env env, napi_value exports); + ~SessionBackupNExporter() override; +}; +} // namespace OHOS::FileManagement::Backup +#endif // INTERFACES_KITS_JS_SRC_MOD_BACKUP_PROPERTIES_SESSION_BACKUP_N_EXPORTER_H \ No newline at end of file diff --git a/services/backup.cfg b/services/backup.cfg index 84d391ce6..40c460399 100644 --- a/services/backup.cfg +++ b/services/backup.cfg @@ -5,7 +5,8 @@ "ondemand" : true, "uid" : "backup", "gid" : ["backup"], - "secon" : "u:r:backup_sa:s0" + "secon" : "u:r:backup_sa:s0", + "permission": ["ohos.permission.STORAGE_MANAGER"] } ] } \ No newline at end of file diff --git a/services/backup_sa/BUILD.gn b/services/backup_sa/BUILD.gn index d71e26ba0..d065d2e5b 100644 --- a/services/backup_sa/BUILD.gn +++ b/services/backup_sa/BUILD.gn @@ -16,6 +16,9 @@ import("//foundation/filemanagement/app_file_service/backup.gni") ohos_shared_library("backup_sa") { sources = [ + "src/module_external/bms_adapter.cpp", + "src/module_external/inner_receiver_impl.cpp", + "src/module_external/sms_adapter.cpp", "src/module_ipc/service.cpp", "src/module_ipc/service_reverse_proxy.cpp", "src/module_ipc/service_stub.cpp", @@ -45,6 +48,7 @@ ohos_shared_library("backup_sa") { "ipc:ipc_core", "safwk:system_ability_fwk", "samgr:samgr_proxy", + "storage_service:storage_manager_sa_proxy", ] use_exceptions = true diff --git a/services/backup_sa/include/module_external/bms_adapter.h b/services/backup_sa/include/module_external/bms_adapter.h new file mode 100644 index 000000000..3671396d9 --- /dev/null +++ b/services/backup_sa/include/module_external/bms_adapter.h @@ -0,0 +1,54 @@ +/* + * 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_BUNDLE_MGR_ADAPTER_H +#define OHOS_FILEMGMT_BACKUP_BUNDLE_MGR_ADAPTER_H + +#include +#include + +#include "b_json/b_json_entity_caps.h" +#include "bundlemgr/bundle_mgr_interface.h" + +namespace OHOS::FileManagement::Backup { +class InnerReceiverImpl; + +class BundleMgrAdapter { +public: + /** + * @brief Get the Bundle Infos object + * + * @return std::vector + */ + static std::vector GetBundleInfos(); + + /** + * @brief Get the bundle infos object + * + * @param bundleNames bundle names + * @return std::vector + */ + static std::vector GetBundleInfos(const std::vector &bundleNames); + + /** + * @brief Install bundle + * + * @param bundleName bundle name + * @param bundleFilePath bundle file path + */ + static ErrCode Install(wptr statusReceiver, const std::string &bundleFilePath); +}; +} // namespace OHOS::FileManagement::Backup +#endif // OHOS_FILEMGMT_BACKUP_BUNDLE_MGR_ADAPTER_H \ No newline at end of file diff --git a/services/backup_sa/include/module_external/inner_receiver_impl.h b/services/backup_sa/include/module_external/inner_receiver_impl.h new file mode 100644 index 000000000..3819f6be2 --- /dev/null +++ b/services/backup_sa/include/module_external/inner_receiver_impl.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_FILEMGMT_BACKUP_INNERRECEIVER_H +#define OHOS_FILEMGMT_BACKUP_INNERRECEIVER_H + +#include + +#include + +#include "status_receiver_host.h" + +namespace OHOS::FileManagement::Backup { +class SchedScheduler; + +class InnerReceiverImpl : public AppExecFwk::StatusReceiverHost { +public: + virtual void OnStatusNotify(const int progress) override; + virtual void OnFinished(const int32_t resultCode, const std::string &resultMsg) override; + + std::string GetBundleName(); + +public: + explicit InnerReceiverImpl(std::string bundleName, wptr sched) + : bundleName_(bundleName), sched_(sched) {}; + ~InnerReceiverImpl() override + { + sched_ = nullptr; + } + +private: + std::string bundleName_; + wptr sched_; +}; +} // namespace OHOS::FileManagement::Backup +#endif // OHOS_FILEMGMT_BACKUP_INNERRECEIVER_H \ No newline at end of file diff --git a/services/backup_sa/include/module_external/sms_adapter.h b/services/backup_sa/include/module_external/sms_adapter.h new file mode 100644 index 000000000..ff59b8164 --- /dev/null +++ b/services/backup_sa/include/module_external/sms_adapter.h @@ -0,0 +1,34 @@ +/* + * 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_STORAGE_MGR_ADAPTER_H +#define OHOS_FILEMGMT_BACKUP_STORAGE_MGR_ADAPTER_H + +#include + +#include "istorage_manager.h" + +namespace OHOS::FileManagement::Backup { +class StorageMgrAdapter { +public: + /** + * @brief Get the bundle stats object + * + * @param bundleName bundle name + */ + static StorageManager::BundleStats GetBundleStats(const std::string &bundleName); +}; +} // namespace OHOS::FileManagement::Backup +#endif // OHOS_FILEMGMT_BACKUP_STORAGE_MGR_ADAPTER_H \ No newline at end of file diff --git a/services/backup_sa/include/module_ipc/service.h b/services/backup_sa/include/module_ipc/service.h index 5b771775c..7bb1dd330 100644 --- a/services/backup_sa/include/module_ipc/service.h +++ b/services/backup_sa/include/module_ipc/service.h @@ -32,16 +32,14 @@ class Service : public SystemAbility, public ServiceStub, protected NoCopyable { // 以下都是IPC接口 public: - ErrCode InitRestoreSession(sptr remote, const std::vector &bundleNames) override; - ErrCode InitBackupSession(sptr remote, - UniqueFd fd, - const std::vector &bundleNames) override; + ErrCode InitRestoreSession(sptr remote) override; + ErrCode InitBackupSession(sptr remote) override; ErrCode Start() override; UniqueFd GetLocalCapabilities() override; ErrCode PublishFile(const BFileInfo &fileInfo) override; ErrCode AppFileReady(const std::string &fileName, UniqueFd fd) override; ErrCode AppDone(ErrCode errCode) override; - ErrCode GetExtFileName(std::string &bundleName, std::string &fileName) override; + ErrCode GetFileHandle(const std::string &bundleName, const std::string &fileName) override; ErrCode AppendBundlesRestoreSession(UniqueFd fd, const std::vector &bundleNames) override; ErrCode AppendBundlesBackupSession(const std::vector &bundleNames) override; ErrCode Finish() override; @@ -124,6 +122,19 @@ private: */ void ClearSessionAndSchedInfo(const std::string &bundleName); + /** + * @brief 整个备份恢复流程结束 + * + * @param errCode 错误码 + */ + void OnAllBundlesFinished(ErrCode errCode); + + /** + * @brief 执行调度器 + * + */ + void OnStartSched(); + private: static sptr instance_; static std::mutex instanceLock_; diff --git a/services/backup_sa/include/module_ipc/service_stub.h b/services/backup_sa/include/module_ipc/service_stub.h index fb0fc4eb8..1049e1574 100644 --- a/services/backup_sa/include/module_ipc/service_stub.h +++ b/services/backup_sa/include/module_ipc/service_stub.h @@ -41,7 +41,7 @@ private: int32_t CmdPublishFile(MessageParcel &data, MessageParcel &reply); int32_t CmdAppFileReady(MessageParcel &data, MessageParcel &reply); int32_t CmdAppDone(MessageParcel &data, MessageParcel &reply); - int32_t CmdGetExtFileName(MessageParcel &data, MessageParcel &reply); + int32_t CmdGetFileHandle(MessageParcel &data, MessageParcel &reply); int32_t CmdAppendBundlesRestoreSession(MessageParcel &data, MessageParcel &reply); int32_t CmdAppendBundlesBackupSession(MessageParcel &data, MessageParcel &reply); int32_t CmdFinish(MessageParcel &data, MessageParcel &reply); 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 0ec0f863c..6fa59256c 100644 --- a/services/backup_sa/include/module_ipc/svc_session_manager.h +++ b/services/backup_sa/include/module_ipc/svc_session_manager.h @@ -31,19 +31,22 @@ #include "b_file_info.h" #include "b_resources/b_constants.h" -#include "bundlemgr/bundle_mgr_interface.h" #include "i_service_reverse.h" #include "module_ipc/svc_backup_connection.h" #include "svc_death_recipient.h" +#include "unique_fd.h" namespace OHOS::FileManagement::Backup { struct BackupExtInfo { bool receExtManageJson {false}; bool receExtAppDone {false}; + bool isBundleFinished {false}; std::string backupExtName; sptr backUpConnection; std::set fileNameInfo; BConstants::ServiceSchedAction schedAction {BConstants::ServiceSchedAction::WAIT}; + bool bNeedToInstall {false}; + std::string installState; }; class Service; @@ -54,6 +57,7 @@ public: IServiceReverse::Scenario scenario {IServiceReverse::Scenario::UNDEFINED}; std::map backupExtNameMap; sptr clientProxy; + bool isBackupStart {false}; bool isAppendFinish {false}; }; @@ -199,6 +203,20 @@ public: */ std::string GetBackupExtName(const std::string &bundleName); + /** + * @brief 追加应用 + * + * @param bundleNames 应用名称 + */ + void AppendBundles(const std::vector &bundleNames); + + /** + * @brief 开始备份 + * + * @return ErrCode + */ + void Start(); + /** * @brief 结束追加应用 * @@ -206,29 +224,69 @@ public: */ void Finish(); -private: /** - * @brief 校验BundleName和ability type 并补全Impl.backupExtNameMap信息 + * @brief 整个备份恢复流程是否结束 + * + * @return true 备份恢复流程结束 + * @return false 备份恢复流程未结束 + */ + bool IsOnAllBundlesFinished(); + + /** + * @brief 是否启动调度器 + * + * @return true 启动调度器 + * @return false 不启动调度器 + */ + bool IsOnOnStartSched(); + + /** + * @brief Set the Install State object + * + * @param bundleName + * @param state + */ + void SetInstallState(const std::string &bundleName, const std::string &state); + + /** + * @brief Get the Install State object * - * @param backupExtNameMap 客户端信息 - * @throw BError::Codes::SA_INVAL_ARG 客户端信息异常 - * @throw BError::Codes::SA_BROKEN_IPC + * @param bundleName + * @return std::string */ - virtual void GetBundleExtNames(std::map &backupExtNameMap); + std::string GetInstallState(const std::string &bundleName); /** - * @brief 初始化 extension backUpConnection + * @brief Set the Need To Install object * - * @param backupExtNameMap + * @param bundleName + * @param needToInstall */ - virtual void InitExtConn(std::map &backupExtNameMap); + void SetNeedToInstall(const std::string &bundleName, bool needToInstall); + + /** + * @brief Get the Need To Install object + * + * @param bundleName + * @return true + * @return false + */ + bool GetNeedToInstall(const std::string &bundleName); + +private: + /** + * @brief 获取backup extension ability + * + * @param bundleName 应用名称 + */ + sptr GetBackupExtAbility(const std::string &bundleName); /** * @brief 初始化 clientProxy * * @param newImpl */ - virtual void InitClient(Impl &newImpl); + void InitClient(Impl &newImpl); /** * @brief 获取BackupExtNameMap iterator @@ -248,8 +306,6 @@ public: ~SvcSessionManager() override = default; private: - sptr GetBundleManager(); - mutable std::shared_mutex lock_; wptr reversePtr_; sptr deathRecipient_; diff --git a/services/backup_sa/include/module_sched/sched_scheduler.h b/services/backup_sa/include/module_sched/sched_scheduler.h index b84f4c134..736c3b985 100644 --- a/services/backup_sa/include/module_sched/sched_scheduler.h +++ b/services/backup_sa/include/module_sched/sched_scheduler.h @@ -16,6 +16,7 @@ #ifndef OHOS_FILEMGMT_BACKUP_SCHED_SCHEDULER_H #define OHOS_FILEMGMT_BACKUP_SCHED_SCHEDULER_H +#include #include #include #include @@ -53,6 +54,8 @@ public: */ void RemoveExtConn(const std::string &bundleName); + void InstallSuccess(const std::string &bundleName, const int32_t resultCode); + void StartTimer() { extTime_.Setup(); @@ -73,6 +76,14 @@ public: bundleTimeVec_.clear(); } +private: + /** + * @brief install state + * + * @param bundleName + */ + void InstallingState(const std::string &bundleName); + private: mutable std::shared_mutex lock_; OHOS::ThreadPool threadPool_; diff --git a/services/backup_sa/src/module_external/bms_adapter.cpp b/services/backup_sa/src/module_external/bms_adapter.cpp new file mode 100644 index 000000000..2f57d4141 --- /dev/null +++ b/services/backup_sa/src/module_external/bms_adapter.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "module_external/bms_adapter.h" + +#include + +#include "b_error/b_error.h" +#include "b_file_info.h" +#include "b_json/b_json_entity_extension_config.h" +#include "b_resources/b_constants.h" +#include "bundle_mgr_client.h" +#include "filemgmt_libhilog.h" +#include "install_param.h" +#include "iservice_registry.h" +#include "module_external/inner_receiver_impl.h" +#include "module_external/sms_adapter.h" +#include "module_ipc/service.h" +#include "module_ipc/svc_session_manager.h" +#include "module_sched/sched_scheduler.h" +#include "status_receiver_host.h" +#include "system_ability_definition.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; + +static sptr GetBundleManager() +{ + auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saMgr == nullptr) { + throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get system ability manager"); + } + + auto bundleObj = saMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (bundleObj == nullptr) { + throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get bundle manager service"); + } + + return iface_cast(bundleObj); +} + +static tuple GetAllowAndExtName(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}; + } + return {false, ""}; +} + +vector BundleMgrAdapter::GetBundleInfos() +{ + vector bundleInfos; + vector installedBundles; + auto bms = GetBundleManager(); + if (!bms->GetBundleInfos(AppExecFwk::GET_BUNDLE_WITH_EXTENSION_INFO, installedBundles, + AppExecFwk::Constants::START_USERID)) { + throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get bundle infos"); + } + for (auto const &installedBundle : installedBundles) { + auto [allToBackup, extName] = GetAllowAndExtName(installedBundle.extensionInfos); + auto bundleStats = StorageMgrAdapter::GetBundleStats(installedBundle.name); + bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {installedBundle.name, installedBundle.versionCode, + installedBundle.versionName, bundleStats.dataSize_, + allToBackup, extName}); + } + return bundleInfos; +} + +vector BundleMgrAdapter::GetBundleInfos(const vector &bundleNames) +{ + vector bundleInfos; + auto bms = GetBundleManager(); + for (auto const &bundleName : bundleNames) { + AppExecFwk::BundleInfo installedBundle; + if (!bms->GetBundleInfo(bundleName, AppExecFwk::GET_BUNDLE_WITH_EXTENSION_INFO, installedBundle, + AppExecFwk::Constants::START_USERID)) { + throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get bundle info"); + } + auto [allToBackup, extName] = GetAllowAndExtName(installedBundle.extensionInfos); + auto bundleStats = StorageMgrAdapter::GetBundleStats(installedBundle.name); + bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {installedBundle.name, installedBundle.versionCode, + installedBundle.versionName, bundleStats.dataSize_, + allToBackup, extName}); + } + return bundleInfos; +} + +ErrCode BundleMgrAdapter::Install(wptr statusReceiver, const string &bundleFilePath) +{ + HILOGI("Begin"); + auto bms = GetBundleManager(); + AppExecFwk::BundleInfo bundleInfo; + if (!bms->GetBundleArchiveInfo(bundleFilePath, AppExecFwk::BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo)) { + return BError(BError::Codes::SA_BROKEN_IPC, "Failed to get bundle archive info").GetCode(); + } + auto receiver = statusReceiver.promote(); + if (receiver == nullptr) { + return BError(BError::Codes::SA_BROKEN_IPC, "Failed to get receiver").GetCode(); + } + // check bundle name + if (bundleInfo.name != receiver->GetBundleName()) { + return BError(BError::Codes::SA_INVAL_ARG, "Bundle name is not match").GetCode(); + } + + auto install = bms->GetBundleInstaller(); + if (!install) { + return BError(BError::Codes::SA_BROKEN_IPC, "Failed to get bundle installer").GetCode(); + } + + AppExecFwk::InstallParam installParam; + installParam.installFlag = AppExecFwk::InstallFlag::REPLACE_EXISTING; + installParam.userId = AppExecFwk::Constants::START_USERID; + return install->StreamInstall({bundleFilePath}, installParam, receiver); +} +} // namespace OHOS::FileManagement::Backup diff --git a/services/backup_sa/src/module_external/inner_receiver_impl.cpp b/services/backup_sa/src/module_external/inner_receiver_impl.cpp new file mode 100644 index 000000000..039159798 --- /dev/null +++ b/services/backup_sa/src/module_external/inner_receiver_impl.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "module_external/inner_receiver_impl.h" + +#include "b_error/b_error.h" +#include "filemgmt_libhilog.h" +#include "module_ipc/svc_session_manager.h" +#include "module_sched/sched_scheduler.h" +#include "module_ipc/service.h" + +namespace OHOS::FileManagement::Backup { +void InnerReceiverImpl::OnStatusNotify(const int progress) +{ + HILOGI("OnStatusNotify %{public}d", progress); +} +void InnerReceiverImpl::OnFinished(const int32_t resultCode, const std::string &resultMsg) +{ + HILOGI("Finished to install %{public}s, resultCode = %{public}d resultMsg = %{public}s", bundleName_.c_str(), + resultCode, resultMsg.c_str()); + + auto sched = sched_.promote(); + if (sched == nullptr) { + throw BError(BError::Codes::SA_INVAL_ARG, std::string("Failed to promote bundleContext")); + } + sched->InstallSuccess(bundleName_, resultCode); +} +std::string InnerReceiverImpl::GetBundleName() +{ + return bundleName_; +} +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/services/backup_sa/src/module_external/sms_adapter.cpp b/services/backup_sa/src/module_external/sms_adapter.cpp new file mode 100644 index 000000000..ce378162b --- /dev/null +++ b/services/backup_sa/src/module_external/sms_adapter.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "module_external/sms_adapter.h" + +#include + +#include "b_error/b_error.h" +#include "filemgmt_libhilog.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; + +static sptr GetStorageManager() +{ + auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saMgr == nullptr) { + throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get system ability manager"); + } + + auto storageObj = saMgr->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); + if (storageObj == nullptr) { + throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get storage manager service"); + } + + return iface_cast(storageObj); +} + +StorageManager::BundleStats StorageMgrAdapter::GetBundleStats(const string &bundleName) +{ + StorageManager::BundleStats bundleStats; + auto storageMgr = GetStorageManager(); + if (storageMgr->GetBundleStats(bundleName, bundleStats)) { + throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get bundle stats"); + } + return bundleStats; +} +} // namespace OHOS::FileManagement::Backup diff --git a/services/backup_sa/src/module_ipc/service.cpp b/services/backup_sa/src/module_ipc/service.cpp index 9ebc17913..fb8da800c 100644 --- a/services/backup_sa/src/module_ipc/service.cpp +++ b/services/backup_sa/src/module_ipc/service.cpp @@ -42,11 +42,11 @@ #include "b_json/b_json_cached_entity.h" #include "b_json/b_json_entity_caps.h" #include "b_process/b_multiuser.h" -#include "b_process/b_process.h" #include "b_resources/b_constants.h" #include "bundle_mgr_client.h" #include "filemgmt_libhilog.h" #include "ipc_skeleton.h" +#include "module_external/bms_adapter.h" #include "module_ipc/svc_backup_connection.h" #include "parameter.h" #include "system_ability_definition.h" @@ -74,18 +74,16 @@ void Service::OnStop() UniqueFd Service::GetLocalCapabilities() { try { + HILOGI("Begin"); VerifyCaller(); - struct statfs fsInfo = {}; - if (statfs(BConstants::SA_BUNDLE_BACKUP_ROOT_DIR.data(), &fsInfo) == -1) { - throw BError(errno); - } - BJsonCachedEntity cachedEntity( UniqueFd(open(BConstants::SA_BUNDLE_BACKUP_ROOT_DIR.data(), O_TMPFILE | O_RDWR, 0600))); auto cache = cachedEntity.Structuralize(); - cache.SetFreeDiskSpace(fsInfo.f_bfree); - cache.SetOSFullName(GetOSFullName()); + + cache.SetSystemFullName(GetOSFullName()); cache.SetDeviceType(GetDeviceType()); + auto bundleInfos = BundleMgrAdapter::GetBundleInfos(); + cache.SetBundleInfos(bundleInfos); cachedEntity.Persist(); return move(cachedEntity.GetFd()); @@ -134,7 +132,7 @@ void Service::VerifyCaller() switch (tokenType) { case Security::AccessToken::ATokenTypeEnum::TOKEN_HAP: { auto multiuser = BMultiuser::ParseUid(IPCSkeleton::GetCallingUid()); - if (multiuser.userId != BConstants::DEFAULT_USER_ID) { + if ((multiuser.userId != BConstants::DEFAULT_USER_ID) && (multiuser.userId != BConstants::XTS_UID)) { throw BError(BError::Codes::SA_INVAL_ARG, string("Calling user is ") .append(to_string(multiuser.userId)) .append(", which is currently not supported")); @@ -164,21 +162,13 @@ void Service::VerifyCaller(IServiceReverse::Scenario scenario) VerifyCaller(); } -ErrCode Service::InitRestoreSession(sptr remote, const vector &bundleNames) +ErrCode Service::InitRestoreSession(sptr remote) { try { VerifyCaller(); - map backupExtNameMap; - auto setBackupExtNameMap = [](const BundleName &bundleName) { - BackupExtInfo info {}; - return make_pair(bundleName, info); - }; - transform(bundleNames.begin(), bundleNames.end(), inserter(backupExtNameMap, backupExtNameMap.end()), - setBackupExtNameMap); session_->Active({ .clientToken = IPCSkeleton::GetCallingTokenID(), .scenario = IServiceReverse::Scenario::RESTORE, - .backupExtNameMap = move(backupExtNameMap), .clientProxy = remote, }); return BError(BError::Codes::OK); @@ -194,30 +184,15 @@ ErrCode Service::InitRestoreSession(sptr remote, const vector remote, UniqueFd fd, const vector &bundleNames) +ErrCode Service::InitBackupSession(sptr remote) { try { VerifyCaller(); - map backupExtNameMap; - auto setBackupExtNameMap = [](const BundleName &bundleName) { - BackupExtInfo info {}; - return make_pair(bundleName, info); - }; - transform(bundleNames.begin(), bundleNames.end(), inserter(backupExtNameMap, backupExtNameMap.end()), - setBackupExtNameMap); session_->Active({ .clientToken = IPCSkeleton::GetCallingTokenID(), .scenario = IServiceReverse::Scenario::BACKUP, - .backupExtNameMap = move(backupExtNameMap), .clientProxy = remote, }); - - BJsonCachedEntity cachedEntity(move(fd)); - auto cache = cachedEntity.Structuralize(); - uint64_t size = cache.GetFreeDiskSpace(); - if (size == 0) { - throw BError(BError::Codes::SA_INVAL_ARG, "Invalid field FreeDiskSpace or unsufficient space"); - } return BError(BError::Codes::OK); } catch (const BError &e) { StopAll(nullptr, true); @@ -227,22 +202,11 @@ ErrCode Service::InitBackupSession(sptr remote, UniqueFd fd, co ErrCode Service::Start() { - try { - HILOGI("Begin"); - VerifyCaller(session_->GetScenario()); - for (int num = 0; num < BConstants::EXT_CONNECT_MAX_COUNT; num++) { - sched_->Sched(); - } - 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; - } + HILOGI("Begin"); + VerifyCaller(session_->GetScenario()); + session_->Start(); + OnStartSched(); + return BError(BError::Codes::OK); } ErrCode Service::AppendBundlesRestoreSession(UniqueFd fd, const vector &bundleNames) @@ -251,10 +215,22 @@ ErrCode Service::AppendBundlesRestoreSession(UniqueFd fd, const vectorGetScenario()); BJsonCachedEntity cachedEntity(move(fd)); auto cache = cachedEntity.Structuralize(); - uint64_t size = cache.GetFreeDiskSpace(); - if (size == 0) { - throw BError(BError::Codes::SA_INVAL_ARG, "Invalid field FreeDiskSpace or unsufficient space"); + auto bundleInfos = cache.GetBundleInfos(); + if (!bundleInfos.size()) { + throw BError(BError::Codes::SA_INVAL_ARG, "Json entity caps is empty"); + } + session_->AppendBundles(bundleNames); + for (auto bundleName : bundleNames) { + for (auto &&bundleInfo : bundleInfos) { + if (bundleInfo.name != bundleName) { + continue; + } + session_->SetNeedToInstall(bundleInfo.name, bundleInfo.needToInstall); + } } + Start(); + Finish(); + OnStartSched(); return BError(BError::Codes::OK); } @@ -262,6 +238,10 @@ ErrCode Service::AppendBundlesBackupSession(const vector &bundleName { HILOGI("Begin"); VerifyCaller(session_->GetScenario()); + session_->AppendBundles(bundleNames); + Start(); + Finish(); + OnStartSched(); return BError(BError::Codes::OK); } @@ -270,6 +250,7 @@ ErrCode Service::Finish() HILOGI("Begin"); VerifyCaller(session_->GetScenario()); session_->Finish(); + OnAllBundlesFinished(BError(BError::Codes::OK)); return BError(BError::Codes::OK); } @@ -279,6 +260,11 @@ ErrCode Service::PublishFile(const BFileInfo &fileInfo) HILOGI("Begin"); VerifyCaller(IServiceReverse::Scenario::RESTORE); + if (fileInfo.fileName == BConstants::RESTORE_INSTALL_PATH) { + session_->SetInstallState(fileInfo.owner, "OK"); + sched_->Sched(fileInfo.owner); + return BError(BError::Codes::OK); + } if (!regex_match(fileInfo.fileName, regex("^[0-9a-zA-Z_.]+$"))) { throw BError(BError::Codes::SA_INVAL_ARG, "Filename is not alphanumeric"); } @@ -294,7 +280,7 @@ ErrCode Service::PublishFile(const BFileInfo &fileInfo) HILOGE("Failed to publish file for backup extension"); } - return BError(BError::Codes::OK); + return res; } catch (const BError &e) { return e.GetCode(); } catch (const exception &e) { @@ -334,6 +320,7 @@ ErrCode Service::AppFileReady(const string &fileName, UniqueFd fd) backUpConnection->DisconnectBackupExtAbility(); ClearSessionAndSchedInfo(callerName); } + OnAllBundlesFinished(BError(BError::Codes::OK)); return BError(BError::Codes::OK); } catch (const BError &e) { return e.GetCode(); // 任意异常产生,终止监听该任务 @@ -367,6 +354,7 @@ ErrCode Service::AppDone(ErrCode errCode) backUpConnection->DisconnectBackupExtAbility(); ClearSessionAndSchedInfo(callerName); } + OnAllBundlesFinished(BError(BError::Codes::OK)); return BError(BError::Codes::OK); } catch (const BError &e) { return e.GetCode(); // 任意异常产生,终止监听该任务 @@ -412,11 +400,15 @@ ErrCode Service::LaunchBackupExtension(const BundleName &bundleName) } } -ErrCode Service::GetExtFileName(string &bundleName, string &fileName) +ErrCode Service::GetFileHandle(const string &bundleName, const string &fileName) { try { - HILOGE("begin"); + HILOGI("Begin"); VerifyCaller(IServiceReverse::Scenario::RESTORE); + if (fileName == BConstants::RESTORE_INSTALL_PATH && regex_match(bundleName, regex("^[0-9a-zA-Z_.]+$"))) { + session_->SetInstallState(bundleName, string(BConstants::RESTORE_INSTALL_PATH)); + return BError(BError::Codes::OK); + } if (!regex_match(fileName, regex("^[0-9a-zA-Z_.]+$"))) { throw BError(BError::Codes::SA_INVAL_ARG, "Filename is not alphanumeric"); } @@ -572,4 +564,25 @@ void Service::ClearSessionAndSchedInfo(const string &bundleName) return; } } + +void Service::OnAllBundlesFinished(ErrCode errCode) +{ + if (session_->IsOnAllBundlesFinished()) { + IServiceReverse::Scenario scenario = session_->GetScenario(); + if (scenario == IServiceReverse::Scenario::BACKUP) { + session_->GetServiceReverseProxy()->BackupOnAllBundlesFinished(errCode); + } else if (scenario == IServiceReverse::Scenario::RESTORE) { + session_->GetServiceReverseProxy()->RestoreOnAllBundlesFinished(errCode); + } + } +} + +void Service::OnStartSched() +{ + if (session_->IsOnOnStartSched()) { + for (int num = 0; num < BConstants::EXT_CONNECT_MAX_COUNT; num++) { + sched_->Sched(); + } + } +} } // namespace OHOS::FileManagement::Backup diff --git a/services/backup_sa/src/module_ipc/service_stub.cpp b/services/backup_sa/src/module_ipc/service_stub.cpp index 4c7b48bf3..51e1576ac 100644 --- a/services/backup_sa/src/module_ipc/service_stub.cpp +++ b/services/backup_sa/src/module_ipc/service_stub.cpp @@ -24,13 +24,11 @@ #include #include "b_error/b_error.h" -#include "b_error/b_excep_utils.h" #include "filemgmt_libhilog.h" #include "module_ipc/service_reverse_proxy.h" namespace OHOS::FileManagement::Backup { using namespace std; -using namespace BExcepUltils; ServiceStub::ServiceStub() { @@ -41,7 +39,7 @@ ServiceStub::ServiceStub() opToInterfaceMap_[SERVICE_CMD_APP_FILE_READY] = &ServiceStub::CmdAppFileReady; opToInterfaceMap_[SERVICE_CMD_APP_DONE] = &ServiceStub::CmdAppDone; opToInterfaceMap_[SERVICE_CMD_START] = &ServiceStub::CmdStart; - opToInterfaceMap_[SERVICE_CMD_GET_EXT_FILE_NAME] = &ServiceStub::CmdGetExtFileName; + opToInterfaceMap_[SERVICE_CMD_GET_FILE_NAME] = &ServiceStub::CmdGetFileHandle; opToInterfaceMap_[SERVICE_CMD_APPEND_BUNDLES_RESTORE_SESSION] = &ServiceStub::CmdAppendBundlesRestoreSession; opToInterfaceMap_[SERVICE_CMD_APPEND_BUNDLES_BACKUP_SESSION] = &ServiceStub::CmdAppendBundlesBackupSession; opToInterfaceMap_[SERVICE_CMD_FINISH] = &ServiceStub::CmdFinish; @@ -49,20 +47,21 @@ ServiceStub::ServiceStub() int32_t ServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { + HILOGI("Begin to call procedure indexed %{public}u", code); + auto interfaceIndex = opToInterfaceMap_.find(code); + if (interfaceIndex == opToInterfaceMap_.end() || !interfaceIndex->second) { + stringstream ss; + ss << "Cannot response request " << code << ": unknown procedure"; + return BError(BError::Codes::SA_INVAL_ARG, ss.str()); + } + const std::u16string descriptor = ServiceStub::GetDescriptor(); const std::u16string remoteDescriptor = data.ReadInterfaceToken(); if (descriptor != remoteDescriptor) { return BError(BError::Codes::SA_INVAL_ARG, "Invalid remote descriptor"); } - HILOGI("Begin to call procedure indexed %{public}u", code); - auto interfaceIndex = opToInterfaceMap_.find(code); - if (interfaceIndex == opToInterfaceMap_.end() || !interfaceIndex->second) { - HILOGE("Cannot response request %{public}d : unknown procedure", code); - return IPCObjectStub::OnRemoteRequest(code, data, reply, option); - } - - return ExceptionCatcherLocked([&]() { return ErrCode((this->*(interfaceIndex->second))(data, reply)); }); + return BError::ExceptionCatcherLocked([&]() { return ErrCode((this->*(interfaceIndex->second))(data, reply)); }); } int32_t ServiceStub::CmdInitRestoreSession(MessageParcel &data, MessageParcel &reply) @@ -77,12 +76,7 @@ int32_t ServiceStub::CmdInitRestoreSession(MessageParcel &data, MessageParcel &r return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive the reverse stub"); } - std::vector bundleNames; - if (!data.ReadStringVector(&bundleNames)) { - return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive bundleNames"); - } - - int32_t res = InitRestoreSession(iremote, bundleNames); + int32_t res = InitRestoreSession(iremote); if (!reply.WriteInt32(res)) { stringstream ss; ss << "Failed to send the result " << res; @@ -103,17 +97,7 @@ int32_t ServiceStub::CmdInitBackupSession(MessageParcel &data, MessageParcel &re return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive the reverse stub"); } - UniqueFd fd(data.ReadFileDescriptor()); - if (fd < 0) { - return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive fd"); - } - - std::vector bundleNames; - if (!data.ReadStringVector(&bundleNames)) { - return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive bundleNames"); - } - - int res = InitBackupSession(iremote, move(fd), bundleNames); + int res = InitBackupSession(iremote); if (!reply.WriteInt32(res)) { stringstream ss; ss << "Failed to send the result " << res; @@ -124,6 +108,7 @@ int32_t ServiceStub::CmdInitBackupSession(MessageParcel &data, MessageParcel &re int32_t ServiceStub::CmdStart(MessageParcel &data, MessageParcel &reply) { + HILOGI("Begin"); int res = Start(); if (!reply.WriteInt32(res)) { stringstream ss; @@ -196,7 +181,7 @@ int32_t ServiceStub::CmdAppDone(MessageParcel &data, MessageParcel &reply) return BError(BError::Codes::OK); } -int32_t ServiceStub::CmdGetExtFileName(MessageParcel &data, MessageParcel &reply) +int32_t ServiceStub::CmdGetFileHandle(MessageParcel &data, MessageParcel &reply) { HILOGI("Begin"); string bundleName; @@ -208,7 +193,7 @@ int32_t ServiceStub::CmdGetExtFileName(MessageParcel &data, MessageParcel &reply return BError(BError::Codes::SA_INVAL_ARG, "Failed to receive fileName").GetCode(); } - return GetExtFileName(bundleName, fileName); + return GetFileHandle(bundleName, fileName); } int32_t ServiceStub::CmdAppendBundlesRestoreSession(MessageParcel &data, MessageParcel &reply) 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 db963091f..fad864859 100644 --- a/services/backup_sa/src/module_ipc/svc_session_manager.cpp +++ b/services/backup_sa/src/module_ipc/svc_session_manager.cpp @@ -18,18 +18,18 @@ #include #include #include +#include #include #include #include "b_error/b_error.h" +#include "b_file_info.h" +#include "b_json/b_json_entity_caps.h" #include "b_json/b_json_entity_ext_manage.h" -#include "b_json/b_json_entity_extension_config.h" #include "b_resources/b_constants.h" -#include "bundle_mgr_client.h" #include "filemgmt_libhilog.h" -#include "iservice_registry.h" +#include "module_external/bms_adapter.h" #include "module_ipc/service.h" -#include "system_ability_definition.h" namespace OHOS::FileManagement::Backup { using namespace std; @@ -61,10 +61,6 @@ void SvcSessionManager::Active(Impl newImpl) throw BError(BError::Codes::SA_INVAL_ARG, "No scenario was specified"); } - GetBundleExtNames(newImpl.backupExtNameMap); - - InitExtConn(newImpl.backupExtNameMap); - InitClient(newImpl); impl_ = newImpl; } @@ -123,46 +119,6 @@ IServiceReverse::Scenario SvcSessionManager::GetScenario() return impl_.scenario; } -void SvcSessionManager::GetBundleExtNames(map &backupExtNameMap) -{ - if (backupExtNameMap.empty()) { - throw BError(BError::Codes::SA_INVAL_ARG, "No app was selected"); - } - - auto bms = GetBundleManager(); - if (!bms) { - throw BError(BError::Codes::SA_BROKEN_IPC, "Bms is invalid"); - } - - for (auto &&it : backupExtNameMap) { - AppExecFwk::BundleInfo installedBundle; - if (!bms->GetBundleInfo(it.first, AppExecFwk::GET_BUNDLE_WITH_EXTENSION_INFO, installedBundle, - AppExecFwk::Constants::START_USERID)) { - throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get the info of bundle " + it.first); - } - for (auto &&ext : installedBundle.extensionInfos) { - if (ext.type == AppExecFwk::ExtensionAbilityType::BACKUP) { - if (ext.name.empty()) { - throw BError(BError::Codes::SA_INVAL_ARG, "Failed to get ext name of bundle " + it.first); - } - 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 " + it.first); - } - BJsonCachedEntity cachedEntity(out[0], it.first); - auto cache = cachedEntity.Structuralize(); - if (cache.GetAllowToBackupRestore()) { - it.second.backupExtName = ext.name; - } else { - throw BError(BError::Codes::SA_INVAL_ARG, - "Permission denied to get allowToBackupRestore of bundle " + it.first); - } - } - } - } -} - bool SvcSessionManager::OnBunleFileReady(const string &bundleName, const string &fileName) { unique_lock lock(lock_); @@ -179,6 +135,7 @@ bool SvcSessionManager::OnBunleFileReady(const string &bundleName, const string // 判断是否结束 通知EXTENTION清理资源 TOOL应用完成备份 if (impl_.scenario == IServiceReverse::Scenario::RESTORE) { + it->second.isBundleFinished = true; return true; } else if (impl_.scenario == IServiceReverse::Scenario::BACKUP) { if (!fileName.empty() && fileName != BConstants::EXT_BACKUP_MANAGE) { @@ -190,6 +147,7 @@ bool SvcSessionManager::OnBunleFileReady(const string &bundleName, const string it->second.receExtAppDone = true; } if (it->second.receExtManageJson && it->second.fileNameInfo.empty() && it->second.receExtAppDone) { + it->second.isBundleFinished = true; return true; } } @@ -248,37 +206,30 @@ wptr SvcSessionManager::GetExtConnection(const BundleName & return wptr(it->second.backUpConnection); } -void SvcSessionManager::InitExtConn(std::map &backupExtNameMap) +sptr SvcSessionManager::GetBackupExtAbility(const string &bundleName) { HILOGI("Begin"); - if (backupExtNameMap.empty()) { - throw BError(BError::Codes::SA_INVAL_ARG, "No app was selected"); - } + auto callDied = [revPtr {reversePtr_}](const string &&bundleName) { + auto revPtrStrong = revPtr.promote(); + if (!revPtrStrong) { + // 服务先于客户端死亡是一种异常场景,但该场景对本流程来说也没什么影响,所以只是简单记录一下 + HILOGW("It's curious that the backup sa dies before the backup client"); + return; + } + revPtrStrong->OnBackupExtensionDied(move(bundleName), ESRCH); + }; - for (auto &&it : backupExtNameMap) { - auto callDied = [revPtr {reversePtr_}](const string &&bundleName) { - auto revPtrStrong = revPtr.promote(); - if (!revPtrStrong) { - // 服务先于客户端死亡是一种异常场景,但该场景对本流程来说也没什么影响,所以只是简单记录一下 - HILOGW("It's curious that the backup sa dies before the backup client"); - return; - } - revPtrStrong->OnBackupExtensionDied(move(bundleName), ESRCH); - }; - - auto callConnDone = [revPtr {reversePtr_}](const string &&bundleName) { - auto revPtrStrong = revPtr.promote(); - if (!revPtrStrong) { - // 服务先于客户端死亡是一种异常场景,但该场景对本流程来说也没什么影响,所以只是简单记录一下 - HILOGW("It's curious that the backup sa dies before the backup client"); - return; - } - revPtrStrong->ExtConnectDone(move(bundleName)); - }; + auto callConnDone = [revPtr {reversePtr_}](const string &&bundleName) { + auto revPtrStrong = revPtr.promote(); + if (!revPtrStrong) { + // 服务先于客户端死亡是一种异常场景,但该场景对本流程来说也没什么影响,所以只是简单记录一下 + HILOGW("It's curious that the backup sa dies before the backup client"); + return; + } + revPtrStrong->ExtConnectDone(move(bundleName)); + }; - auto backUpConnection = sptr(new SvcBackupConnection(callDied, callConnDone)); - it.second.backUpConnection = backUpConnection; - } + return sptr(new SvcBackupConnection(callDied, callConnDone)); } void SvcSessionManager::DumpInfo(const int fd, const std::vector &args) @@ -328,7 +279,7 @@ void SvcSessionManager::SetExtFileNameRequest(const string &bundleName, const st std::set SvcSessionManager::GetExtFileNameRequest(const std::string &bundleName) { HILOGI("Begin"); - shared_lock lock(lock_); + unique_lock lock(lock_); if (!impl_.clientToken) { throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); } @@ -337,7 +288,9 @@ std::set SvcSessionManager::GetExtFileNameRequest(const std::string throw BError(BError::Codes::SA_INVAL_ARG, "Invalid Scenario"); } auto it = GetBackupExtNameMap(bundleName); - return it->second.fileNameInfo; + set fileNameInfo = it->second.fileNameInfo; + it->second.fileNameInfo.clear(); + return fileNameInfo; } map::iterator SvcSessionManager::GetBackupExtNameMap(const string &bundleName) @@ -389,7 +342,7 @@ void SvcSessionManager::SetServiceSchedAction(const string &bundleName, BConstan auto it = GetBackupExtNameMap(bundleName); it->second.schedAction = action; - if (it->second.schedAction == BConstants::ServiceSchedAction::START) { + if (it->second.schedAction == BConstants::ServiceSchedAction::INSTALLING) { extConnectNum_++; } } @@ -401,25 +354,56 @@ string SvcSessionManager::GetBackupExtName(const string &bundleName) if (!impl_.clientToken) { throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); } - auto it = GetBackupExtNameMap(bundleName); - return it->second.backupExtName; + string name = bundleName; + VerifyBundleName(name); + auto bundleInfos = BundleMgrAdapter::GetBundleInfos({bundleName}); + for (auto &&bundleInfo : bundleInfos) { + if (!bundleInfo.allToBackup || bundleInfo.extensionName.empty()) { + throw BError(BError::Codes::SA_INVAL_ARG, + string(bundleInfo.name).append(" is not allow to backup or extension name is empty")); + } + if (bundleInfo.name == bundleName) { + return bundleInfo.extensionName; + } + } + throw BError(BError::Codes::SA_INVAL_ARG, "Could not find the extension name"); } -sptr SvcSessionManager::GetBundleManager() +void SvcSessionManager::AppendBundles(const vector &bundleNames) { - auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); - if (saMgr == nullptr) { - HILOGI("SystemAbilityManager is nullptr."); - return nullptr; + HILOGI("Begin"); + unique_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); } - auto bundleObj = saMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); - if (bundleObj == nullptr) { - HILOGI("Failed to get bundle manager service."); - return nullptr; + // auto bundleInfos = BundleMgrAdapter::GetBundleInfos(bundleNames); + // for (auto &&bundleInfo : bundleInfos) { + // if (!bundleInfo.allToBackup || bundleInfo.extensionName.empty()) { + // throw BError(BError::Codes::SA_INVAL_ARG, + // string(bundleInfo.name).append(" is not allow to backup or extension name is empty")); + // } + // BackupExtInfo info {}; + // info.backupExtName = bundleInfo.extensionName; + // info.backUpConnection = GetBackupExtAbility(bundleInfo.name); + + // impl_.backupExtNameMap.insert(make_pair(bundleInfo.name, info)); + // } + for (auto &&bundleName : bundleNames) { + BackupExtInfo info {}; + info.backUpConnection = GetBackupExtAbility(bundleName); + impl_.backupExtNameMap.insert(make_pair(bundleName, info)); } +} - return iface_cast(bundleObj); +void SvcSessionManager::Start() +{ + HILOGI("Begin"); + unique_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + impl_.isBackupStart = true; } void SvcSessionManager::Finish() @@ -431,4 +415,79 @@ void SvcSessionManager::Finish() } impl_.isAppendFinish = true; } + +bool SvcSessionManager::IsOnAllBundlesFinished() +{ + shared_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + auto iter = find_if(impl_.backupExtNameMap.begin(), impl_.backupExtNameMap.end(), + [](auto &it) { return it.second.isBundleFinished == false; }); + if (iter == impl_.backupExtNameMap.end() && impl_.isAppendFinish) { + return true; + } + return false; +} + +bool SvcSessionManager::IsOnOnStartSched() +{ + shared_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + if (impl_.isBackupStart && impl_.backupExtNameMap.size()) { + return true; + } + + return false; +} + +void SvcSessionManager::SetInstallState(const string &bundleName, const string &state) +{ + HILOGI("Begin"); + unique_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + + auto it = GetBackupExtNameMap(bundleName); + it->second.installState = state; +} + +string SvcSessionManager::GetInstallState(const string &bundleName) +{ + HILOGI("Begin"); + unique_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + + auto it = GetBackupExtNameMap(bundleName); + return it->second.installState; +} + +void SvcSessionManager::SetNeedToInstall(const std::string &bundleName, bool needToInstall) +{ + HILOGI("Begin"); + unique_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + + auto it = GetBackupExtNameMap(bundleName); + it->second.bNeedToInstall = needToInstall; +} + +bool SvcSessionManager::GetNeedToInstall(const std::string &bundleName) +{ + HILOGI("Begin"); + unique_lock lock(lock_); + if (!impl_.clientToken) { + throw BError(BError::Codes::SA_INVAL_ARG, "No caller token was specified"); + } + + auto it = GetBackupExtNameMap(bundleName); + return it->second.bNeedToInstall; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/services/backup_sa/src/module_sched/sched_scheduler.cpp b/services/backup_sa/src/module_sched/sched_scheduler.cpp index 9257b89f6..c07c7e102 100644 --- a/services/backup_sa/src/module_sched/sched_scheduler.cpp +++ b/services/backup_sa/src/module_sched/sched_scheduler.cpp @@ -20,8 +20,15 @@ #include #include +#include + +#include +#include + #include "b_error/b_error.h" #include "filemgmt_libhilog.h" +#include "module_external/bms_adapter.h" +#include "module_external/inner_receiver_impl.h" #include "module_ipc/service.h" #include "module_ipc/svc_session_manager.h" @@ -36,7 +43,7 @@ void SchedScheduler::Sched(string bundleName) } BConstants::ServiceSchedAction action = sessionPtr_->GetServiceSchedAction(bundleName); if (action == BConstants::ServiceSchedAction::WAIT) { - sessionPtr_->SetServiceSchedAction(bundleName, BConstants::ServiceSchedAction::START); + sessionPtr_->SetServiceSchedAction(bundleName, BConstants::ServiceSchedAction::INSTALLING); } } HILOGE("Sched bundleName %{public}s", bundleName.data()); @@ -58,6 +65,7 @@ void SchedScheduler::Sched(string bundleName) void SchedScheduler::ExecutingQueueTasks(const string &bundleName) { HILOGE("start"); + InstallingState(bundleName); BConstants::ServiceSchedAction action = sessionPtr_->GetServiceSchedAction(bundleName); if (action == BConstants::ServiceSchedAction::START) { // 注册启动定时器 @@ -106,4 +114,48 @@ void SchedScheduler::RemoveExtConn(const string &bundleName) bundleTimeVec_.erase(iter); } } + +void SchedScheduler::InstallingState(const string &bundleName) +{ + BConstants::ServiceSchedAction action = sessionPtr_->GetServiceSchedAction(bundleName); + if (action == BConstants::ServiceSchedAction::INSTALLING) { + IServiceReverse::Scenario scenario = sessionPtr_->GetScenario(); + if (scenario == IServiceReverse::Scenario::BACKUP || !sessionPtr_->GetNeedToInstall(bundleName)) { + sessionPtr_->SetServiceSchedAction(bundleName, BConstants::ServiceSchedAction::START); + return; + } + string state = sessionPtr_->GetInstallState(bundleName); + string path = string(BConstants::SA_BUNDLE_BACKUP_ROOT_DIR).append(bundleName); + string filePath = path + "/bundle.hap"; + if (state == BConstants::RESTORE_INSTALL_PATH) { + HILOGI("CreateDirectory , path = %{public}s", path.data()); + if (!ForceCreateDirectory(path)) { + throw BError(BError::Codes::SA_INVAL_ARG, string("Failed to create directory")); + } + sessionPtr_->GetServiceReverseProxy()->RestoreOnFileReady( + bundleName, state, + UniqueFd(open(filePath.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IROTH))); + } else if (state == "OK") { + if (access(filePath.data(), F_OK) != 0) { + throw BError(BError::Codes::SA_INVAL_ARG, string("File already exists")); + } + sptr statusReceiver = sptr(new InnerReceiverImpl(bundleName, wptr(this))); + ErrCode err = BundleMgrAdapter::Install(statusReceiver, filePath); + if (err != ERR_OK) { + InstallSuccess(bundleName, err); + } + } + } +} + +void SchedScheduler::InstallSuccess(const std::string &bundleName, const int32_t resultCode) +{ + if (!resultCode) { + sessionPtr_->SetServiceSchedAction(bundleName, BConstants::ServiceSchedAction::START); + Sched(bundleName); + } else { + sessionPtr_->GetServiceReverseProxy()->RestoreOnBundleStarted(resultCode, bundleName); + sessionPtr_->RemoveExtInfo(bundleName); + } +} }; // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/unittests/backup_utils/BUILD.gn b/tests/unittests/backup_utils/BUILD.gn index 9da04ca4c..3e7a4d4bc 100644 --- a/tests/unittests/backup_utils/BUILD.gn +++ b/tests/unittests/backup_utils/BUILD.gn @@ -79,7 +79,10 @@ ohos_unittest("b_tarball_cmdline_test") { "${path_backup}/utils/include", ] - deps = [ "${path_backup}/tests/utils:backup_test_utils" ] + deps = [ + "${path_backup}/tests/utils:backup_test_utils", + "${path_backup}/utils/:backup_utils", + ] external_deps = [ "c_utils:utils" ] use_exceptions = true diff --git a/tools/backup_tool/src/tools_op_backup.cpp b/tools/backup_tool/src/tools_op_backup.cpp index 72f281865..2d8de8e23 100644 --- a/tools/backup_tool/src/tools_op_backup.cpp +++ b/tools/backup_tool/src/tools_op_backup.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include #include #include #include @@ -66,7 +67,7 @@ public: if (flag == true) { ready_ = true; cv_.notify_all(); - } else if (bundleStatusMap_.size() == 0 && cnt_ == 0) { + } else if (bundleStatusMap_.size() == 0 && cnt_ == 0 && isAllBundelsFinished.load()) { ready_ = true; cv_.notify_all(); } @@ -109,6 +110,9 @@ private: mutex lock_; bool ready_ = false; uint32_t cnt_ {0}; + +public: + std::atomic isAllBundelsFinished {false}; }; static string GenHelpMsg() @@ -147,6 +151,7 @@ static void OnBundleStarted(shared_ptr ctx, ErrCode err, const BundleNa { printf("BundleStarted errCode = %d, BundleName = %s\n", err, name.c_str()); if (err != 0) { + ctx->isAllBundelsFinished.store(true); ctx->UpdateBundleFinishedCount(); ctx->TryNotify(); } @@ -161,6 +166,7 @@ static void OnBundleFinished(shared_ptr ctx, ErrCode err, const BundleN static void OnAllBundlesFinished(shared_ptr ctx, ErrCode err) { + ctx->isAllBundelsFinished.store(true); if (err == 0) { printf("backup successful\n"); } else { @@ -206,34 +212,18 @@ static void BackupToolDirSoftlinkToBackupDir() } } -static int32_t InitPathCapFile(const string &isLocal, const string &pathCapFile, vector bundleNames) +static int32_t InitPathCapFile(vector bundleNames) { StartTrace(HITRACE_TAG_FILEMANAGEMENT, "InitPathCapFile"); // SELinux backup_tool工具/data/文件夹下创建文件夹 SA服务因root用户的自定义标签无写入权限 此处调整为软链接形式 BackupToolDirSoftlinkToBackupDir(); - UniqueFd fd(open(pathCapFile.data(), O_RDWR | O_CREAT, S_IRWXU)); - if (fd < 0) { - fprintf(stderr, "Failed to open file error: %d %s\n", errno, strerror(errno)); - FinishTrace(HITRACE_TAG_FILEMANAGEMENT); - return -errno; - } - if (isLocal == "true") { - auto proxy = ServiceProxy::GetInstance(); - if (!proxy) { - fprintf(stderr, "Get an empty backup sa proxy\n"); - return -EFAULT; - } - BFile::SendFile(fd, proxy->GetLocalCapabilities()); - } - if (access((BConstants::BACKUP_TOOL_RECEIVE_DIR).data(), F_OK) != 0 && mkdir((BConstants::BACKUP_TOOL_RECEIVE_DIR).data(), S_IRWXU) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } auto ctx = make_shared(); ctx->session_ = BSessionBackup::Init( - move(fd), bundleNames, BSessionBackup::Callbacks {.onFileReady = bind(OnFileReady, ctx, placeholders::_1, placeholders::_2), .onBundleStarted = bind(OnBundleStarted, ctx, placeholders::_1, placeholders::_2), .onBundleFinished = bind(OnBundleFinished, ctx, placeholders::_1, placeholders::_2), @@ -244,11 +234,22 @@ static int32_t InitPathCapFile(const string &isLocal, const string &pathCapFile, FinishTrace(HITRACE_TAG_FILEMANAGEMENT); return -EPERM; } + int ret = ctx->session_->AppendBundles(bundleNames); + if (ret != 0) { + printf("backup append bundles error: %d", ret); + throw BError(BError::Codes::TOOL_INVAL_ARG, "backup append bundles error"); + } + ctx->SetBundleFinishedCount(bundleNames.size()); - int ret = ctx->session_->Start(); + ret = ctx->session_->Start(); if (ret != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, "backup start error"); } + + ret = ctx->session_->Finish(); + if (ret != 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, "backup finish error"); + } ctx->Wait(); FinishTrace(HITRACE_TAG_FILEMANAGEMENT); return 0; @@ -260,8 +261,7 @@ static int Exec(map> &mapArgToVal) mapArgToVal.find("isLocal") == mapArgToVal.end()) { return -EPERM; } - return InitPathCapFile(*(mapArgToVal["isLocal"].begin()), *(mapArgToVal["pathCapFile"].begin()), - mapArgToVal["bundles"]); + return InitPathCapFile(mapArgToVal["bundles"]); } /** diff --git a/tools/backup_tool/src/tools_op_restore.cpp b/tools/backup_tool/src/tools_op_restore.cpp index 95ba8b840..d4ccb5945 100644 --- a/tools/backup_tool/src/tools_op_restore.cpp +++ b/tools/backup_tool/src/tools_op_restore.cpp @@ -33,6 +33,7 @@ #include "b_error/b_error.h" #include "b_filesystem/b_dir.h" #include "b_filesystem/b_file.h" +#include "b_json/b_json_entity_caps.h" #include "b_json/b_json_entity_ext_manage.h" #include "b_resources/b_constants.h" #include "backup_kit_inner.h" @@ -70,7 +71,7 @@ public: if (flag == true) { ready_ = true; cv_.notify_all(); - } else if (bundleStatusMap_.size() == 0 && cnt_ == 0) { + } else if (bundleStatusMap_.size() == 0 && cnt_ == 0 && isAllBundelsFinished.load()) { ready_ = true; cv_.notify_all(); } @@ -113,6 +114,9 @@ private: mutex lock_; bool ready_ = false; uint32_t cnt_ {0}; + +public: + std::atomic isAllBundelsFinished {false}; }; static string GenHelpMsg() @@ -126,10 +130,17 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq { printf("FileReady owner = %s, fileName = %s, sn = %u, fd = %d\n", fileInfo.owner.c_str(), fileInfo.fileName.c_str(), fileInfo.sn, fd.Get()); - if (!regex_match(fileInfo.fileName, regex("^[0-9a-zA-Z_.]+$"))) { + if (!regex_match(fileInfo.fileName, regex("^[0-9a-zA-Z_.]+$")) && + fileInfo.fileName != BConstants::RESTORE_INSTALL_PATH) { throw BError(BError::Codes::TOOL_INVAL_ARG, "Filename is not alphanumeric"); } - string tmpPath = string(BConstants::BACKUP_TOOL_RECEIVE_DIR) + fileInfo.owner + "/" + fileInfo.fileName; + string tmpPath; + if (fileInfo.fileName == BConstants::RESTORE_INSTALL_PATH) { + printf("OnFileReady bundle hap\n"); + tmpPath = string(BConstants::BACKUP_TOOL_INSTALL_DIR) + fileInfo.owner + ".hap"; + } else { + tmpPath = string(BConstants::BACKUP_TOOL_RECEIVE_DIR) + fileInfo.owner + "/" + fileInfo.fileName; + } if (access(tmpPath.data(), F_OK) != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, generic_category().message(errno)); } @@ -142,7 +153,9 @@ static void OnFileReady(shared_ptr ctx, const BFileInfo &fileInfo, Uniq if (ret != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, "PublishFile error"); } - ctx->UpdateBundleSentFiles(fileInfo.owner, fileInfo.fileName); + if (fileInfo.fileName != BConstants::RESTORE_INSTALL_PATH) { + ctx->UpdateBundleSentFiles(fileInfo.owner, fileInfo.fileName); + } ctx->TryNotify(); } @@ -161,18 +174,23 @@ static void OnBundleFinished(shared_ptr ctx, ErrCode err, const BundleN 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(ErrCode err) +static void OnAllBundlesFinished(shared_ptr ctx, ErrCode err) { + ctx->isAllBundelsFinished.store(true); if (err == 0) { printf("Restore successful\n"); } else { printf("Failed to Unplanned Abort error: %d\n", err); + ctx->TryNotify(true); + return; } + ctx->TryNotify(); } static void OnBackupServiceDied(shared_ptr ctx) @@ -199,63 +217,81 @@ static void RestoreApp(shared_ptr restore, vector &bundleNa if (err != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, "error path"); } + // install bundle.hap + string installPath = string(BConstants::BACKUP_TOOL_INSTALL_DIR) + bundleName + ".hap"; + if (access(installPath.data(), F_OK) == 0) { + printf("install bundle hap %s\n", installPath.c_str()); + restore->session_->GetFileHandle(bundleName, string(BConstants::RESTORE_INSTALL_PATH)); + } for (auto &filePath : filePaths) { string fileName = filePath.substr(filePath.rfind("/") + 1); - restore->session_->GetExtFileName(bundleName, fileName); + restore->session_->GetFileHandle(bundleName, fileName); restore->UpdateBundleSendFiles(bundleName, fileName); } } FinishTrace(HITRACE_TAG_FILEMANAGEMENT); } -static int32_t Init(const string &pathCapFile, vector bundleNames) +static int32_t InitPathCapFile(const string &pathCapFile, vector bundleNames) { StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Init"); + + UniqueFd fd(open(pathCapFile.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)); + if (fd < 0) { + fprintf(stderr, "Failed to open file error: %d %s\n", errno, strerror(errno)); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return -errno; + } + // auto proxy = ServiceProxy::GetInstance(); + // if (!proxy) { + // fprintf(stderr, "Get an empty backup sa proxy\n"); + // return -EFAULT; + // } + // BFile::SendFile(fd, proxy->GetLocalCapabilities()); + + BJsonCachedEntity cachedEntity(move(fd)); + auto cache = cachedEntity.Structuralize(); + vector bundleInfos; + for (auto name : bundleNames) { + string installPath = string(BConstants::BACKUP_TOOL_INSTALL_DIR) + name + ".hap"; + bool needToInstall = false; + if (access(installPath.data(), F_OK) == 0) { + needToInstall = true; + } + bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {.name = name, .needToInstall = needToInstall}); + } + cache.SetBundleInfos(bundleInfos); + cachedEntity.Persist(); + auto ctx = make_shared(); ctx->session_ = BSessionRestore::Init( - bundleNames, BSessionRestore::Callbacks {.onFileReady = bind(OnFileReady, ctx, placeholders::_1, placeholders::_2), .onBundleStarted = bind(OnBundleStarted, ctx, placeholders::_1, placeholders::_2), .onBundleFinished = bind(OnBundleFinished, ctx, placeholders::_1, placeholders::_2), - .onAllBundlesFinished = OnAllBundlesFinished, + .onAllBundlesFinished = bind(OnAllBundlesFinished, ctx, placeholders::_1), .onBackupServiceDied = bind(OnBackupServiceDied, ctx)}); if (ctx->session_ == nullptr) { printf("Failed to init restore"); FinishTrace(HITRACE_TAG_FILEMANAGEMENT); return -EPERM; } - UniqueFd fdRemote(ctx->session_->GetLocalCapabilities()); - if (fdRemote < 0) { - printf("Failed to receive fd"); - FinishTrace(HITRACE_TAG_FILEMANAGEMENT); - return fdRemote; - } - if (lseek(fdRemote, 0, SEEK_SET) == -1) { - FinishTrace(HITRACE_TAG_FILEMANAGEMENT); - return -errno; - } - struct stat stat = {}; - if (fstat(fdRemote, &stat) == -1) { - FinishTrace(HITRACE_TAG_FILEMANAGEMENT); - return -errno; - } - UniqueFd fdLocal(open(pathCapFile.data(), O_WRONLY | O_CREAT, S_IRWXU)); - if (fdLocal < 0) { - fprintf(stderr, "Failed to open file. error: %d %s\n", errno, strerror(errno)); - FinishTrace(HITRACE_TAG_FILEMANAGEMENT); - return -errno; - } - if (sendfile(fdLocal, fdRemote, nullptr, stat.st_size) == -1) { - fprintf(stderr, "Failed to Copy file. error: %d %s\n", errno, strerror(errno)); - FinishTrace(HITRACE_TAG_FILEMANAGEMENT); - return -errno; + int ret = ctx->session_->AppendBundles(move(cachedEntity.GetFd()), bundleNames); + if (ret != 0) { + printf("restore append bundles error: %d", ret); + throw BError(BError::Codes::TOOL_INVAL_ARG, "restore append bundles error"); } ctx->SetBundleFinishedCount(bundleNames.size()); RestoreApp(ctx, bundleNames); - int ret = ctx->session_->Start(); + + ret = ctx->session_->Start(); if (ret != 0) { throw BError(BError::Codes::TOOL_INVAL_ARG, "restore start error"); } + + ret = ctx->session_->Finish(); + if (ret != 0) { + throw BError(BError::Codes::TOOL_INVAL_ARG, "backup finish error"); + } ctx->Wait(); return 0; } @@ -265,7 +301,7 @@ static int Exec(map> &mapArgToVal) if (mapArgToVal.find("pathCapFile") == mapArgToVal.end() || mapArgToVal.find("bundles") == mapArgToVal.end()) { return -EPERM; } - return Init(*(mapArgToVal["pathCapFile"].begin()), mapArgToVal["bundles"]); + return InitPathCapFile(*(mapArgToVal["pathCapFile"].begin()), mapArgToVal["bundles"]); } /** diff --git a/utils/BUILD.gn b/utils/BUILD.gn index e05117dfb..2bc20ad1b 100644 --- a/utils/BUILD.gn +++ b/utils/BUILD.gn @@ -25,6 +25,10 @@ config("utils_public_config") { include_dirs = [ "include", "${path_base}/include", + "${path_filemgmt_libn}/include", + "${path_napi}/interfaces/inner_api", + "${path_napi}/interfaces/kits", + "//third_party/node/src", ] } diff --git a/utils/include/b_error/b_error.h b/utils/include/b_error/b_error.h index 058361d2b..dd58e794c 100644 --- a/utils/include/b_error/b_error.h +++ b/utils/include/b_error/b_error.h @@ -30,6 +30,8 @@ #include #include +#include "n_error.h" + #if __has_builtin(__builtin_FILE) && __has_builtin(__builtin_LINE) && __has_builtin(__builtin_FUNCTION) #define DEFINE_SOURCE_LOCATION \ int lineNo = __builtin_LINE(), const char *fileName = __builtin_FILE(), \ @@ -39,6 +41,8 @@ #endif namespace OHOS::FileManagement::Backup { +using ErrCode = int; + class BError : public std::exception { public: /** @@ -85,14 +89,7 @@ public: * * @return int 标注错误码 */ - int GetCode() const - { - if (code_ == Codes::OK) { - return 0; - } else { - return -1 * (static_cast(code_) | ErrCodeOffset(SUBSYS_FILEMANAGEMENT, codeSubsystem_)); - } - } + int GetCode() const; /** * @brief 返回原始错误码 @@ -200,8 +197,38 @@ private: {Codes::EXT_BROKEN_IPC, "Extension failed to do IPC"}, }; + static inline const std::map errCodeTable_ { + {static_cast(Codes::OK), static_cast(Codes::OK)}, + {static_cast(Codes::UTILS_INVAL_JSON_ENTITY), + LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfFileIO::E_INVAL}, + {static_cast(Codes::UTILS_INVAL_FILE_HANDLE), + LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfFileIO::E_INVAL}, + {static_cast(Codes::UTILS_INVAL_TARBALL_ARG), + LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfFileIO::E_UKERR}, + {static_cast(Codes::UTILS_INVAL_PROCESS_ARG), + LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfFileIO::E_UKERR}, + {static_cast(Codes::UTILS_INTERRUPTED_PROCESS), + LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfFileIO::E_UKERR}, + {static_cast(Codes::TOOL_INVAL_ARG), LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfFileIO::E_UKERR}, + {static_cast(Codes::SA_INVAL_ARG), LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfFileIO::E_INVAL}, + {static_cast(Codes::SA_BROKEN_IPC), + LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfStorageService::E_IPCSS}, + {static_cast(Codes::SA_REFUSED_ACT), LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfFileIO::E_PERM}, + {static_cast(Codes::SA_BROKEN_ROOT_DIR), LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfFileIO::E_UKERR}, + {static_cast(Codes::SDK_INVAL_ARG), LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfFileIO::E_INVAL}, + {static_cast(Codes::SDK_BROKEN_IPC), + LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfStorageService::E_IPCSS}, + {static_cast(Codes::SDK_MIXED_SCENARIO), LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfFileIO::E_INVAL}, + {static_cast(Codes::EXT_INVAL_ARG), LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfFileIO::E_INVAL}, + {static_cast(Codes::EXT_BROKEN_FRAMEWORK), + LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfFileIO::E_UKERR}, + {static_cast(Codes::EXT_BROKEN_BACKUP_SA), + LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfStorageService::E_IPCSS}, + {static_cast(Codes::EXT_BROKEN_IPC), + LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfStorageService::E_IPCSS}, + }; + private: - const int codeSubsystem_ {1}; Codes code_ {Codes::OK}; std::string msg_; diff --git a/utils/include/b_json/b_json_entity_caps.h b/utils/include/b_json/b_json_entity_caps.h index 7c1c7625a..9ab7bc212 100644 --- a/utils/include/b_json/b_json_entity_caps.h +++ b/utils/include/b_json/b_json_entity_caps.h @@ -22,51 +22,87 @@ namespace OHOS::FileManagement::Backup { class BJsonEntityCaps : public BJsonEntity { public: - uint64_t GetFreeDiskSpace() - { - if (!obj_ || !obj_.isMember("freeDiskSpace") || !obj_["freeDiskSpace"].isUInt64()) { - HILOGE("Failed to init field FreeDiskSpace"); - return 0; - } - - return obj_["freeDiskSpace"].asUInt64(); - } + struct BundleInfo { + std::string name; + uint32_t versionCode; + std::string versionName; + int64_t spaceOccupied; + bool allToBackup; + std::string extensionName; + bool needToInstall {false}; + }; - void SetFreeDiskSpace(uint64_t freeDiskSpace) +public: + void SetSystemFullName(std::string systemFullName) { - obj_["freeDiskSpace"] = freeDiskSpace; + obj_["systemFullName"] = systemFullName; } - void SetOSFullName(std::string osFullName) + void SetDeviceType(std::string deviceType) { - obj_["OSFullName"] = osFullName; + obj_["deviceType"] = deviceType; } - void SetDeviceType(std::string deviceType) + void SetBundleInfos(std::vector bundleInfos) { - obj_["deviceType"] = deviceType; + if (obj_.isMember("bundleInfos")) { + obj_["bundleInfos"].clear(); + } + for (const auto &item : bundleInfos) { + Json::Value arrObj; + arrObj["name"] = item.name; + arrObj["versionCode"] = item.versionCode; + arrObj["versionName"] = item.versionName; + arrObj["spaceOccupied"] = item.spaceOccupied; + arrObj["allToBackup"] = item.allToBackup; + arrObj["extensionName"] = item.extensionName; + arrObj["needToInstall"] = item.needToInstall; + obj_["bundleInfos"].append(arrObj); + } } - std::string GetOSFullName() + std::string GetSystemFullName() { - if (!obj_ || !obj_.isMember("OSFullName") || !obj_["OSFullName"].isString()) { - HILOGE("Failed to get field OSFullName"); + if (!obj_ || !obj_.isMember("systemFullName") || !obj_["systemFullName"].isString()) { + HILOGI("Failed to get field systemFullName"); return ""; } - return obj_["OSFullName"].asString(); + return obj_["systemFullName"].asString(); } std::string GetDeviceType() { if (!obj_ || !obj_.isMember("deviceType") || !obj_["deviceType"].isString()) { - HILOGE("Failed to get field deviceType"); + HILOGI("Failed to get field deviceType"); return ""; } return obj_["deviceType"].asString(); } + std::vector GetBundleInfos() + { + if (!obj_ || !obj_.isMember("bundleInfos") || !obj_["bundleInfos"].isArray()) { + HILOGI("Failed to get field get bundleInfos"); + return {}; + } + std::vector bundleInfos; + for (const auto &item : obj_["bundleInfos"]) { + if (!item || !item["name"].isString() || !item["versionCode"].isUInt() || !item["versionName"].isString() || + !item["spaceOccupied"].isInt64() || !item["allToBackup"].isBool() || + !item["extensionName"].isString() || !item["needToInstall"].isBool()) { + HILOGI("Failed to get field bundleInfos, type error"); + return {}; + } + bundleInfos.emplace_back(BundleInfo {item["name"].asString(), item["versionCode"].asUInt(), + item["versionName"].asString(), item["spaceOccupied"].asInt64(), + item["allToBackup"].asBool(), item["extensionName"].asString(), + item["needToInstall"].asBool()}); + } + return bundleInfos; + } + public: /** * @brief 构造方法,具备T(Json::Value&, std::any)能力的构造函数 @@ -76,7 +112,7 @@ public: */ explicit BJsonEntityCaps(Json::Value &obj, std::any option = std::any()) : BJsonEntity(obj, option) { - SetFreeDiskSpace(GetFreeDiskSpace()); + SetBundleInfos(GetBundleInfos()); } BJsonEntityCaps() = delete; diff --git a/utils/include/b_resources/b_constants.h b/utils/include/b_resources/b_constants.h index d46740f55..9a61caa0a 100644 --- a/utils/include/b_resources/b_constants.h +++ b/utils/include/b_resources/b_constants.h @@ -32,9 +32,10 @@ enum class ExtensionAction { enum ServiceSchedAction { WAIT = 0, - START = 1, - RUNNING = 2, - FINISH = 3, + INSTALLING = 1, + START, + RUNNING, + FINISH, }; enum EntryKey { @@ -45,6 +46,7 @@ enum EntryKey { constexpr int SPAN_USERID_UID = 20000000; constexpr int SYSTEM_UID = 0; +constexpr int XTS_UID = 1; constexpr int DEFAULT_USER_ID = 100; constexpr int BACKUP_UID = 1089; constexpr int EXTENSION_THREAD_POOL_COUNT = 1; @@ -110,6 +112,7 @@ static inline std::string_view BACKUP_TOOL_RECEIVE_DIR = "/data/backup/received/ static inline std::string_view PATH_BUNDLE_BACKUP_HOME = "/data/storage/el2/backup"; static inline std::string_view SA_BUNDLE_BACKUP_TOOL_DIR = "/data/service/el2/100/backup/backup_tool/"; static inline std::string_view BACKUP_TOOL_LINK_DIR = "/data/backup"; +static inline std::string_view BACKUP_TOOL_INSTALL_DIR = "/data/backup/install/"; // 备份恢复配置文件暂存路径 static inline std::string_view BACKUP_CONFIG_EXTENSION_PATH = "/data/storage/el2/base/temp/"; @@ -120,6 +123,9 @@ static inline std::string_view EXT_BACKUP_MANAGE = "manage.json"; // 包管理元数据配置文件 static inline std::string_view BACKUP_CONFIG_JSON = "backup_config.json"; +// 恢复应用安装包路径 +static inline std::string_view RESTORE_INSTALL_PATH = "/data/storage/el2/restore/bundle.hap"; + // 应用默认备份的目录,其均为相对根路径的路径。为避免模糊匹配,务必以斜线为结尾。 static inline std::array PATHES_TO_BACKUP = { "data/storage/el2/database/", diff --git a/utils/src/b_error/b_error.cpp b/utils/src/b_error/b_error.cpp index e6e108153..74987d5be 100644 --- a/utils/src/b_error/b_error.cpp +++ b/utils/src/b_error/b_error.cpp @@ -15,6 +15,7 @@ #include "b_error/b_error.h" +#include #include #include @@ -49,4 +50,18 @@ string BError::WrapMessageWithExtraInfos(const char *fileName, HiviewDFX::HiLog::Error(FILEMGMT_LOG_LABEL, "%{public}s", res.c_str()); return res; } + +int BError::GetCode() const +{ + int code = static_cast(GetRawCode()); + if (LibN::errCodeTable.find(code) != LibN::errCodeTable.end()) { + auto [err, msg] = LibN::errCodeTable.at(code); + return err; + } + if (errCodeTable_.find(code) != errCodeTable_.end()) { + return errCodeTable_.at(code); + } + HILOGE("Unknown code : %{public}d", code); + return LibN::FILEIO_SYS_CAP_TAG + LibN::ErrCodeSuffixOfFileIO::E_UKERR; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/utils/src/b_filesystem/b_file.cpp b/utils/src/b_filesystem/b_file.cpp index e653b32bc..aa8c36370 100644 --- a/utils/src/b_filesystem/b_file.cpp +++ b/utils/src/b_filesystem/b_file.cpp @@ -73,6 +73,10 @@ void BFile::SendFile(int outFd, int inFd) if (ret == -1) { throw BError(errno); } + ret = ftruncate(outFd, offset); + if (ret == -1) { + throw BError(errno); + } } void BFile::Write(const UniqueFd &fd, const string &str) diff --git a/utils/src/b_json/b_json_entity_ext_manage.cpp b/utils/src/b_json/b_json_entity_ext_manage.cpp index 79fef1a72..9d5ccca90 100644 --- a/utils/src/b_json/b_json_entity_ext_manage.cpp +++ b/utils/src/b_json/b_json_entity_ext_manage.cpp @@ -18,7 +18,9 @@ #include #include +#include "b_error/b_error.h" #include "b_json/b_json_entity_ext_manage.h" +#include "b_resources/b_constants.h" #include "filemgmt_libhilog.h" #include "json/value.h" @@ -91,6 +93,9 @@ void BJsonEntityExtManage::SetExtManage(const mapfirst; + if (item->second.first == BConstants::RESTORE_INSTALL_PATH) { + throw BError(BError::Codes::UTILS_INVAL_JSON_ENTITY, "Failed to set ext manage, invalid path"); + } value["information"]["path"] = item->second.first; value["information"]["stat"] = Stat2JsonValue(item->second.second); set lks = FindLinks(item, index); @@ -142,6 +147,9 @@ map> BJsonEntityExtManage::GetExtManageInfo() struct stat sta = {}; string path = item["information"].isMember("path") ? item["information"]["path"].asString() : ""; + if (path == BConstants::RESTORE_INSTALL_PATH) { + throw BError(BError::Codes::UTILS_INVAL_JSON_ENTITY, "Failed to get ext manage info, invalid path"); + } if (item["information"].isMember("stat")) { sta = JsonValue2Stat(item["information"]["stat"]); } -- Gitee