diff --git a/services/clouddiskservice/BUILD.gn b/services/clouddiskservice/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..7526603976ca50a9a932398b2a3c67a1976b2ec1 --- /dev/null +++ b/services/clouddiskservice/BUILD.gn @@ -0,0 +1,129 @@ +# Copyright (C) 2025 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. + +import("//build/config/components/idl_tool/idl.gni") +import("//build/ohos.gni") +import("//foundation/filemanagement/dfs_service/distributedfile.gni") + +config("optimize-size") { + cflags = [ + "-fdata-sections", + "-ffunction-sections", + "-Oz", + ] + cflags_cc = [ + "-fvisibility-inlines-hidden", + "-Oz", + ] +} + +config("cloud_disk_service_public_config") { + include_dirs = [ "${target_gen_dir}" ] +} + +idl_gen_interface("cloud_disk_service") { + sources = [ "ICloudDiskService.idl" ] + sources_cpp = [ + "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.cpp", + "${distributedfile_path}/utils/log/src/utils_log.cpp", + ] + sub_include = [ + "${distributedfile_path}/utils/log/include", + "${innerkits_native_path}/clouddiskservice_kit_inner", + ] + configs = [] + + sequenceable_ext_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] + + innerapi_tags = [ "platformsdk" ] + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + log_domainid = "0xD003900" + log_tag = "CloudDiskService" + subsystem_name = "filemanagement" + part_name = "dfs_service" +} + +ohos_shared_library("clouddiskservice_sa") { + branch_protector_ret = "pac_ret" + configs = [ ":optimize-size" ] + public_configs = [ ":cloud_disk_service_public_config" ] + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + include_dirs = [ + "ipc/include", + ] + + sources = [ + "ipc/src/cloud_disk_service.cpp", + "ipc/src/cloud_disk_service_callback_manager.cpp", + "ipc/src/cloud_disk_service_callback_proxy.cpp", + "ipc/src/cloud_disk_sync_folder.cpp", + "ipc/src/account_status_listener.cpp", + "${distributedfile_path}/frameworks/native/clouddiskservice_kit_inner/src/cloud_disk_common.cpp", + "${distributedfile_path}/utils/log/src/utils_log.cpp", + ] + + output_values = get_target_outputs(":cloud_disk_service") + sources += filter_include(output_values, [ "*_stub.cpp" ]) + + defines = [ + "LOG_DOMAIN=0xD004308", + "LOG_TAG=\"CLOUDDISKSERVICE_SA\"", + ] + + if (dfs_service_feature_enable_cloud_disk) { + defines += [ "SUPPORT_CLOUD_DISK_SERVICE "] + } + + deps = [ + ":cloud_disk_service", + ":libcloud_disk_service_proxy", + "${innerkits_native_path}/clouddiskservice_kit_inner:clouddiskservice_kit_inner", + "${utils_path}:libdistributedfiledentry", + "${utils_path}:libdistributedfileutils", + ] + + external_deps = [ + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "ffrt:libffrt", + "e2fsprogs:libext2_uuid", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_single", + "samgr:samgr_proxy", + "safwk:system_ability_fwk", + "user_file_service:cloud_disk_manager_kit" + ] + + use_exceptions = true + part_name = "dfs_service" + subsystem_name = "filemanagement" +} diff --git a/services/clouddiskservice/ICloudDiskService.idl b/services/clouddiskservice/ICloudDiskService.idl new file mode 100644 index 0000000000000000000000000000000000000000..057ced6387f1c48375680e0583a81bb47297c268 --- /dev/null +++ b/services/clouddiskservice/ICloudDiskService.idl @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 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. + */ +sequenceable OHOS.IRemoteObject; +sequenceable cloud_disk_common..OHOS.FileManagement.CloudDiskService.ChangesResult; +sequenceable cloud_disk_common..OHOS.FileManagement.CloudDiskService.FileSyncState; +sequenceable cloud_disk_common..OHOS.FileManagement.CloudDiskService.FailedList; +sequenceable cloud_disk_common..OHOS.FileManagement.CloudDiskService.ResultList; + +interface OHOS.FileManagement.CloudDiskService.ICloudDiskService +{ + void RegisterSyncFolderChangesInner([in] String syncFolder, [in] IRemoteObject remoteobject); + void UnregisterSyncFolderChangesInner([in] String syncFolder); + ChangesResult GetSyncFolderChangesInner([in] String syncFolder, [in] unsigned long count, [in] unsigned long startUSN); + List SetFileSyncStatesInner([in] String syncFolder, [in] List fileSyncStates); + List GetFileSyncStatesInner([in] String syncFolder, [in] List pathArray); + void RegisterSyncFolderInner([in] int userId, [in] String bundleName, [in] String path); + void UnregisterSyncFolderInner([in] int userId, [in] String bundleName, [in] String path); + void UnregisterForSaInner([in] String path); +} diff --git a/services/clouddiskservice/ipc/include/account_status_listener.h b/services/clouddiskservice/ipc/include/account_status_listener.h new file mode 100644 index 0000000000000000000000000000000000000000..1b132540a45e7fd647aaf335fd1d04e28c4614ce --- /dev/null +++ b/services/clouddiskservice/ipc/include/account_status_listener.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 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 CLOUD_DISK_SERVICE_ACCOUNT_STATUS_LISTENER_H +#define CLOUD_DISK_SERVICE_ACCOUNT_STATUS_LISTENER_H + +#include "cloud_file_utils.h" +#include "common_event_subscriber.h" +#include "dfsu_access_token_helper.h" +#include "disk_monitor.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { +class AccountStatusListener { +public: + explicit AccountStatusListener() = default; + ~AccountStatusListener(); + void Start(); + void Stop(); + +private: + std::shared_ptr commonEventSubscriber_ = nullptr; +}; + +class AccountStatusSubscriber : public EventFwk::CommonEventSubscriber { +public: + AccountStatusSubscriber(const EventFwk::CommonEventSubscribeInfo &subscribeInfo); + ~AccountStatusSubscriber() override {} + void OnReceiveEvent(const EventFwk::CommonEventData &eventData) override; +}; +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS +#endif // CLOUD_DISK_SERVICE_ACCOUNT_STATUS_LISTENER_H \ No newline at end of file diff --git a/services/clouddiskservice/ipc/include/cloud_disk_service.h b/services/clouddiskservice/ipc/include/cloud_disk_service.h new file mode 100644 index 0000000000000000000000000000000000000000..8008233f188357572bfafb681464ca6beff04bea --- /dev/null +++ b/services/clouddiskservice/ipc/include/cloud_disk_service.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025 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 CLOUD_DISK_SERVICE_H +#define CLOUD_DISK_SERVICE_H + +#include +#include +#include + +#include "account_status_listener.h" +#include "cloud_disk_service_stub.h" +#include "i_cloud_disk_service_callback.h" +#include "icloud_disk_service.h" +#include "iremote_stub.h" +#include "nocopyable.h" +#include "refbase.h" +#include "system_ability.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { +enum class ServiceRunningState { STATE_NOT_START, STATE_RUNNING }; + +class CloudDiskService final : public SystemAbility, public CloudDiskServiceStub, protected NoCopyable { + DECLARE_SYSTEM_ABILITY(CloudDiskService); + +public: + explicit CloudDiskService(int32_t saID, bool runOnCreate = true); + virtual ~CloudDiskService() = default; + + void OnStart() override; + void OnStop() override; + ErrCode RegisterSyncFolderChangesInner(const std::string &syncFolder, + const sptr &remoteObject) override; + ErrCode UnregisterSyncFolderChangesInner(const std::string &syncFolder) override; + ErrCode GetSyncFolderChangesInner(const std::string &syncFolder, + uint64_t count, + uint64_t startUsn, + ChangesResult &changesResult) override; + ErrCode SetFileSyncStatesInner(const std::string &syncFolder, + const std::vector &fileSyncStates, + std::vector &failedList) override; + ErrCode GetFileSyncStatesInner(const std::string &syncFolder, + const std::vector &pathArray, + std::vector &resultList) override; + ErrCode RegisterSyncFolderInner(int32_t userId, const std::string &bundleName, const std::string &path) override; + ErrCode UnregisterSyncFolderInner(int32_t userId, const std::string &bundleName, const std::string &path) override; + + int32_t UnregisterForSaInner(const std::string &path) override; + +private: + CloudDiskService(); + ServiceRunningState state_{ServiceRunningState::STATE_NOT_START}; + static sptr instance_; + bool registerToService_{false}; + void PublishSA(); + void OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) override; + std::shared_ptr accountStatusListener_ = nullptr; +}; +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS +#endif // CLOUD_DISK_SERVICE_H diff --git a/services/clouddiskservice/ipc/include/cloud_disk_service_callback_manager.h b/services/clouddiskservice/ipc/include/cloud_disk_service_callback_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..891090546c2c640e82ffbd1a1228b807a202e343 --- /dev/null +++ b/services/clouddiskservice/ipc/include/cloud_disk_service_callback_manager.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025 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_CLOUD_DISK_SERVICE_CALLBACK_MANAGER_H +#define OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_MANAGER_H + +#include "nocopyable.h" + +#include "i_cloud_disk_service_callback.h" +#include "svc_death_recipient.h" + +namespace OHOS::FileManagement::CloudDiskService { +class CloudDiskServiceCallbackManager final : public NoCopyable { +public: + using TaskId = uint64_t; + static CloudDiskServiceCallbackManager &GetInstance(); + bool RigisterSyncFolderMap(std::string &bundleName, + uint32_t syncFolderIndex, + const sptr &callback); + void UnregisterSyncFolderMap(const std::string &bundleName, uint32_t syncFolderIndex); + bool UnregisterSyncFolderForChangesMap(std::string &bundleName, uint32_t syncFolderIndex); + void AddCallback(const std::string &bundleName, const sptr &callback); + void OnChangeData(const uint32_t syncFolderIndex, const std::vector &changeData); + + struct CallbackValue { + sptr callback; + std::vector syncFolderIndexs; + }; + +private: + std::map callbackAppMap_; + std::map> callbackIndexMap_; + std::mutex callbackMutex_; +}; +} // namespace OHOS::FileManagement::CloudDiskService + +#endif // OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_MANAGER_H \ No newline at end of file diff --git a/services/clouddiskservice/ipc/include/cloud_disk_service_callback_proxy.h b/services/clouddiskservice/ipc/include/cloud_disk_service_callback_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..6c15360452f844ce1d4a2d234e0d3cdc8cfbfc9f --- /dev/null +++ b/services/clouddiskservice/ipc/include/cloud_disk_service_callback_proxy.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 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_CLOUD_DISK_SERVICE_CALLBACK_PROXY_H +#define OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_PROXY_H + +#include "iremote_proxy.h" + +#include "i_cloud_disk_service_callback.h" + +namespace OHOS::FileManagement::CloudDiskService { +class CloudDiskServiceCallbackProxy : public IRemoteProxy { +public: + explicit CloudDiskServiceCallbackProxy(const sptr &impl) + : IRemoteProxy(impl) + { + } + ~CloudDiskServiceCallbackProxy() override {} + + void OnChangeData(const std::string &sandboxPath, const std::vector &changeData) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace OHOS::FileManagement::CloudDiskService + +#endif // OHOS_FILEMGMT_CLOUD_DISK_SERVICE_CALLBACK_PROXY_H \ No newline at end of file diff --git a/services/clouddiskservice/ipc/include/cloud_disk_sync_folder.h b/services/clouddiskservice/ipc/include/cloud_disk_sync_folder.h new file mode 100644 index 0000000000000000000000000000000000000000..f6ba1b7a2ee5a1721d26fef4ee34cd7ea985e208 --- /dev/null +++ b/services/clouddiskservice/ipc/include/cloud_disk_sync_folder.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025 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 CLOUD_DISK_SYNC_FOLDER_H +#define CLOUD_DISK_SYNC_FOLDER_H + +#include +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { + +struct SyncFolderValue { + std::string bundleName; + std::string path; +}; +class CloudDiskSyncFolder { +public: + static CloudDiskSyncFolder &GetInstance(); + void AddSyncFolder(const uint32_t &syncFolderIndex, const SyncFolderValue &syncFolderValue); + void DeleteSyncFolder(const uint32_t &syncFolderIndex); + int32_t GetSyncFolderSize(); + bool CheckSyncFolder(const uint32_t &syncFolderIndex); + bool GetSyncFolderByIndex(const uint32_t syncFolderIndex, std::string &path); + bool GetSyncFolderValueByIndex(const uint32_t syncFolderIndex, SyncFolderValue &syncFolderValue); + bool GetIndexBySyncFolder(uint32_t &syncFolderIndex, const std::string &path); + void RemoveXattr(std::string &path, const std::string &attrName); + bool PathToPhysicalPath(const std::string &path, const std::string &userId, std::string &physicalPath); + bool PathToMntPathBySandboxPath(const std::string &path, const std::string &userId, std::string &realpath); + bool PathToMntPathByPhysicalPath(const std::string &path, const std::string &userId, std::string &realpath); + bool PathToSandboxPathByPhysicalPath(const std::string &path, const std::string &userId, std::string &realpath); + std::unordered_map GetSyncFolderMap(); + +private: + std::unordered_map syncFolderMap; + std::mutex mutex_; +}; +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS +#endif // CLOUD_DISK_SYNC_FOLDER_H diff --git a/services/clouddiskservice/ipc/src/account_status_listener.cpp b/services/clouddiskservice/ipc/src/account_status_listener.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2a472b82aabe4eba24cbe773aa66f51cd89d6ea --- /dev/null +++ b/services/clouddiskservice/ipc/src/account_status_listener.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2025 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 "account_status_listener.h" + +#include + +#include "cloud_disk_comm.h" +#include "cloud_disk_sync_folder.h" +#include "cloud_disk_sync_folder_manager.h" +#include "common_event_manager.h" +#include "common_event_support.h" + +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { + +AccountStatusSubscriber::AccountStatusSubscriber(const EventFwk::CommonEventSubscribeInfo &subscribeInfo) + : EventFwk::CommonEventSubscriber(subscribeInfo) +{ +} + +void AccountStatusSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &eventData) +{ + auto action = eventData.GetWant().GetAction(); + if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USER_STARTED) { + LOGI("OnStartUser!"); + + std::vector syncFolders; + OHOS::FileManagement::CloudDiskSyncFolderManager::GetInstance().GetAllSyncFoldersForSa(syncFolders); + int32_t userId = DfsuAccessTokenHelper::GetUserId(); + if (userId == 0) { + DfsuAccessTokenHelper::GetAccountId(userId); + } + for (auto item : syncFolders) { + std::string path; + if (!CloudDiskSyncFolder::GetInstance().PathToPhysicalPath(item.path_, std::to_string(userId), path)) { + LOGE("Get path failed"); + continue; + } + SyncFolderValue syncFolderValue; + syncFolderValue.bundleName = item.bundleName_; + syncFolderValue.path = path; + uint32_t syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(path); + CloudDiskSyncFolder::GetInstance().AddSyncFolder(syncFolderIndex, syncFolderValue); + } + if (CloudDiskSyncFolder::GetInstance().GetSyncFolderSize() > 0) { + DiskMonitor::GetInstance().StartMonitor(eventData.GetCode()); + } + } +} + +AccountStatusListener::~AccountStatusListener() +{ + Stop(); +} + +void AccountStatusListener::Start() +{ + /* subscribe Account login, logout, Package remove and Datashare ready */ + EventFwk::MatchingSkills matchingSkills; + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_STARTED); + EventFwk::CommonEventSubscribeInfo info(matchingSkills); + commonEventSubscriber_ = std::make_shared(info); + auto subRet = EventFwk::CommonEventManager::SubscribeCommonEvent(commonEventSubscriber_); + LOGI("Subscriber end, SubscribeResult = %{public}d", subRet); +} + +void AccountStatusListener::Stop() +{ + if (commonEventSubscriber_ != nullptr) { + EventFwk::CommonEventManager::UnSubscribeCommonEvent(commonEventSubscriber_); + commonEventSubscriber_ = nullptr; + } +} + +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/services/clouddiskservice/ipc/src/cloud_disk_service.cpp b/services/clouddiskservice/ipc/src/cloud_disk_service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b4da305791b20ee371015114fb11dbd6b7c0458d --- /dev/null +++ b/services/clouddiskservice/ipc/src/cloud_disk_service.cpp @@ -0,0 +1,582 @@ +/* + * Copyright (c) 2025 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 "cloud_disk_service.h" + +#include +#include +#include +#include +#include +#include + +#include "cloud_disk_service_callback_manager.h" +#include "cloud_disk_service_error.h" +#include "cloud_disk_service_syncfolder.h" +#include "cloud_disk_service_task_manager.h" +#include "cloud_disk_sync_folder_manager.h" +#include "cloud_disk_sync_folder.h" +#include "iremote_object.h" +#include "system_ability_definition.h" +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { +using namespace std; + +const int32_t GET_FILE_SYNC_MAX = 100; +constexpr const char *FILE_SYNC_STATE = "user.clouddisk.filesyncstate"; + +namespace { +} +REGISTER_SYSTEM_ABILITY_BY_ID(CloudDiskService, FILEMANAGEMENT_CLOUD_DISK_SERVICE_SA_ID, true); + +CloudDiskService::CloudDiskService(int32_t saID, bool runOnCreate) : SystemAbility(saID, runOnCreate) +{ + accountStatusListener_ = make_shared(); +} + +CloudDiskService::CloudDiskService() {} + +void CloudDiskService::PublishSA() +{ + LOGI("Begin to init"); + if (!registerToService_) { + bool ret = SystemAbility::Publish(this); + if (!ret) { + throw runtime_error("Failed to publish the clouddiskservice"); + } + registerToService_ = true; + } + LOGI("Init finished successfully"); +} + +void CloudDiskService::OnStart() +{ + LOGI("Begin to start service"); + if (state_ == ServiceRunningState::STATE_RUNNING) { + LOGI("CloudDiskService has already started"); + return; + } + + try { + PublishSA(); + AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID); + } catch (const exception &e) { + LOGE("%{public}s", e.what()); + } + + std::vector syncFolders; + OHOS::FileManagement::CloudDiskSyncFolderManager::GetInstance().GetAllSyncFoldersForSa(syncFolders); + int32_t userId = DfsuAccessTokenHelper::GetUserId(); + if (userId == 0) { + DfsuAccessTokenHelper::GetAccountId(userId); + } + for (const auto &item : syncFolders) { + std::string path; + if (!CloudDiskSyncFolder::GetInstance().PathToPhysicalPath(item.path_, std::to_string(userId), path)) { + LOGE("Get path failed"); + continue; + } + SyncFolderValue syncFolderValue; + syncFolderValue.bundleName = item.bundleName_; + syncFolderValue.path = path; + uint32_t syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(path); + CloudDiskSyncFolder::GetInstance().AddSyncFolder(syncFolderIndex, syncFolderValue); + } + + if (CloudDiskSyncFolder::GetInstance().GetSyncFolderSize() > 0) { + DiskMonitor::GetInstance().StartMonitor(userId); + } + state_ = ServiceRunningState::STATE_RUNNING; + + LOGI("Start service successfully"); +} + +void CloudDiskService::OnStop() +{ + LOGI("Begin to stop"); + state_ = ServiceRunningState::STATE_NOT_START; + registerToService_ = false; + LOGI("Stop finished successfully"); +} + +static int32_t CheckPermissions(const string &permission, bool isSystemApp) +{ + if (!permission.empty() && !DfsuAccessTokenHelper::CheckCallerPermission(permission)) { + LOGE("permission denied"); + return E_PERMISSION_DENIED; + } + return E_OK; +} + +int32_t CloudDiskService::RegisterSyncFolderChangesInner(const std::string &syncFolder, + const sptr &remoteObject) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + LOGI("Begin RegisterSyncFolderChangesInner"); + + if (remoteObject == nullptr) { + LOGE("remoteObject is nullptr"); + return E_INVALID_ARG; + } + + int32_t userId = DfsuAccessTokenHelper::GetUserId(); + std::string path; + if (!CloudDiskSyncFolder::GetInstance().PathToPhysicalPath(syncFolder, std::to_string(userId), path)) { + LOGE("Get path failed"); + return E_INVALID_ARG; + } + + std::string bundleName = ""; + int32_t ret = DfsuAccessTokenHelper::GetCallerBundleName(bundleName); + if (ret != E_OK) { + LOGE("Get bundleName failed, ret:%{public}d", ret); + return E_INTERNAL_ERROR; + } + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(path); + if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + LOGE("SyncFolder is not exist"); + return E_SYNC_FOLDER_PATH_NOT_EXIST; + } + + TaskKey taskKey; + taskKey.bundleName = bundleName; + taskKey.syncChronousRootPath = path; + CloudDiskServiceTaskManager::GetInstance().StartTask(taskKey, TaskType::REGISTER_TASK); + + auto callback = iface_cast(remoteObject); + + if (!CloudDiskServiceCallbackManager::GetInstance().RigisterSyncFolderMap(bundleName, syncFolderIndex, callback)) { + return E_LISTENER_ALREADY_REGISTERED; + } + + CloudDiskServiceSyncFolder::RegisterSyncFolderChanges(userId, syncFolderIndex); + CloudDiskServiceCallbackManager::GetInstance().AddCallback(bundleName, callback); + + LOGI("End RegisterSyncFolderChangesInner"); + return E_OK; +#else + return E_NOT_SUPPORTED; +#endif +} + +int32_t CloudDiskService::UnregisterSyncFolderChangesInner(const std::string &syncFolder) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + LOGI("Begin UnregisterSyncFolderChangesInner"); + + int32_t userId = DfsuAccessTokenHelper::GetUserId(); + std::string path; + if (!CloudDiskSyncFolder::GetInstance().PathToPhysicalPath(syncFolder, std::to_string(userId), path)) { + LOGE("Get path failed"); + return E_INVALID_ARG; + } + + std::string bundleName = ""; + int32_t ret = DfsuAccessTokenHelper::GetCallerBundleName(bundleName); + if (ret != E_OK) { + LOGE("Get bundleName failed, ret:%{public}d", ret); + return E_INTERNAL_ERROR; + } + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(path); + if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + LOGE("SyncFolder is not exist"); + return E_SYNC_FOLDER_PATH_NOT_EXIST; + } + + if (!CloudDiskServiceCallbackManager::GetInstance().UnregisterSyncFolderForChangesMap( + bundleName, syncFolderIndex)) { + return E_LISTENER_NOT_REGISTERED; + } + + CloudDiskServiceSyncFolder::UnRegisterSyncFolderChanges(userId, syncFolderIndex); + + TaskKey taskKey; + taskKey.bundleName = bundleName; + taskKey.syncChronousRootPath = path; + CloudDiskServiceTaskManager::GetInstance().CompleteTask(taskKey, TaskType::REGISTER_TASK); + LOGI("End UnregisterSyncFolderChangesInner"); + return E_OK; +#else + return E_NOT_SUPPORTED; +#endif +} + +int32_t CloudDiskService::GetSyncFolderChangesInner(const std::string &syncFolder, + uint64_t count, + uint64_t startUsn, + ChangesResult &changesResult) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + LOGI("Begin GetSyncFolderChangesInner"); + + int32_t userId = DfsuAccessTokenHelper::GetUserId(); + std::string path; + if (!CloudDiskSyncFolder::GetInstance().PathToPhysicalPath(syncFolder, std::to_string(userId), path)) { + LOGE("Get path failed"); + return E_INVALID_ARG; + } + + std::string bundleName = ""; + int32_t ret = DfsuAccessTokenHelper::GetCallerBundleName(bundleName); + if (ret != E_OK) { + LOGE("Get bundleName failed, ret:%{public}d", ret); + return E_INTERNAL_ERROR; + } + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(path); + if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + LOGE("SyncFolder is not exist"); + return E_SYNC_FOLDER_PATH_NOT_EXIST; + } + + ret = CloudDiskServiceSyncFolder::GetSyncFolderChanges(userId, syncFolderIndex, startUsn, count, changesResult); + if (ret != E_OK) { + LOGE("GetSyncFolderChanges failed"); + return ret; + } + LOGI("End GetSyncFolderChangesInner"); + return E_OK; +#else + return E_NOT_SUPPORTED; +#endif +} + +static int32_t GetErrorNum(int32_t error) +{ + int32_t errNum; + switch (error) { + case EDQUOT: + errNum = static_cast(ErrorReason::NO_SPACE_LEFT); + break; + case ERANGE: + errNum = static_cast(ErrorReason::OUT_OF_RANGE); + break; + case ENOENT: + errNum = static_cast(ErrorReason::NO_SUCH_FILE); + break; + default: + errNum = static_cast(ErrorReason::NO_SYNC_STATE); + } + return errNum; +} + +static bool SetFileSyncStates(const FileSyncState &fileSyncStates, int32_t &userId, FailedList &failed) +{ + std::string setXattrPath; + if (!CloudDiskSyncFolder::GetInstance().PathToMntPathBySandboxPath(fileSyncStates.path, std::to_string(userId), + setXattrPath)) { + LOGE("Get path failed"); + failed.path = fileSyncStates.path; + failed.error = ErrorReason::NO_SUCH_FILE; + return false; + } + uint8_t state = static_cast(fileSyncStates.state); + if (state > static_cast(SyncState::SYNC_CONFLICTED)) { + LOGE("Invalid state"); + failed.path = fileSyncStates.path; + failed.error = ErrorReason::OUT_OF_RANGE; + return false; + } + if (setxattr(setXattrPath.c_str(), FILE_SYNC_STATE, &state, sizeof(state), 0) != 0) { + int32_t error = errno; + LOGE("Failed to set xattr, err: %{public}d", error); + failed.path = fileSyncStates.path; + failed.error = static_cast(GetErrorNum(error)); + return false; + } + return true; +} + +int32_t CloudDiskService::SetFileSyncStatesInner(const std::string &syncFolder, + const std::vector &fileSyncStates, + std::vector &failedList) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + LOGI("Begin SetXattrInner"); + + if (fileSyncStates.empty() || fileSyncStates.size() > GET_FILE_SYNC_MAX) { + LOGE("Invalid parameter"); + return E_INVALID_ARG; + } + + int32_t userId = DfsuAccessTokenHelper::GetUserId(); + + std::string path; + if (!CloudDiskSyncFolder::GetInstance().PathToPhysicalPath(syncFolder, std::to_string(userId), path)) { + LOGE("Get path failed"); + return E_INVALID_ARG; + } + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(path); + if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + LOGE("SyncFolder is not exist"); + return E_SYNC_FOLDER_PATH_NOT_EXIST; + } + + FailedList failed; + for (auto &item : fileSyncStates) { + if (!SetFileSyncStates(item, userId, failed)) { + failedList.push_back(failed); + } + } + + LOGI("End SetXattrInner"); + return E_OK; +#else + return E_NOT_SUPPORTED; +#endif +} + +static ResultList GetFileSyncState(const std::string &path, int32_t &userId) +{ + ResultList getResult; + getResult.isSuccess = false; + getResult.path = path; + std::string getXattrPath; + + if (!CloudDiskSyncFolder::GetInstance().PathToMntPathBySandboxPath(path, std::to_string(userId), getXattrPath)) { + LOGE("Get path failed"); + getResult.error = ErrorReason::NO_SUCH_FILE; + return getResult; + } + + auto xattrValueSize = getxattr(getXattrPath.c_str(), FILE_SYNC_STATE, nullptr, 0); + if (xattrValueSize < 0) { + int32_t error = errno; + LOGE("getxattr failed, errno : %{public}d", error); + getResult.error = static_cast(GetErrorNum(error)); + return getResult; + } + + std::unique_ptr xattrValue = std::make_unique((long)xattrValueSize); + if (xattrValue == nullptr) { + LOGE("Failed to allocate memory for xattrValue, errno : %{public}d", errno); + getResult.error = ErrorReason::NO_SPACE_LEFT; + return getResult; + } + + xattrValueSize = getxattr(getXattrPath.c_str(), FILE_SYNC_STATE, xattrValue.get(), xattrValueSize); + if (xattrValueSize <= 0) { + int32_t error = errno; + LOGE("getxattr failed, errno : %{public}d", error); + getResult.error = static_cast(GetErrorNum(error)); + return getResult; + } + + uint8_t rawState = static_cast(xattrValue[0]); + if (rawState > static_cast(SyncState::SYNC_CONFLICTED)) { + LOGE("get invalid number"); + getResult.error = ErrorReason::INVALID_ARGUMENT; + return getResult; + } + + getResult.isSuccess = true; + getResult.state = static_cast(rawState); + return getResult; +} + +int32_t CloudDiskService::GetFileSyncStatesInner(const std::string &syncFolder, + const std::vector &pathArray, + std::vector &resultList) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + LOGI("Begin GetXattrInner"); + + if (pathArray.empty() || pathArray.size() > GET_FILE_SYNC_MAX) { + LOGE("Invalid parameter"); + return E_INVALID_ARG; + } + + int32_t userId = DfsuAccessTokenHelper::GetUserId(); + std::string path; + + if (!CloudDiskSyncFolder::GetInstance().PathToPhysicalPath(syncFolder, std::to_string(userId), path)) { + LOGE("Get path failed"); + return E_INVALID_ARG; + } + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(path); + if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + LOGE("SyncFolder is not exist"); + return E_SYNC_FOLDER_PATH_NOT_EXIST; + } + + ResultList getResult; + for (auto &item : pathArray) { + getResult = GetFileSyncState(item, userId); + resultList.push_back(getResult); + } + + LOGI("End GetXattrInner"); + return E_OK; +#else + return E_NOT_SUPPORTED; +#endif +} + +int32_t CloudDiskService::RegisterSyncFolderInner(int32_t userId, const std::string &bundleName, + const std::string &path) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + LOGI("Begin RegisterSyncFolderInner"); + RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + + std::string registerSyncFolder; + if (!CloudDiskSyncFolder::GetInstance().PathToPhysicalPath(path, std::to_string(userId), registerSyncFolder)) { + LOGE("Get registerSyncFolder failed"); + return E_INVALID_ARG; + } + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(registerSyncFolder); + if (CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + LOGE("Syncfolder is exist"); + return E_SYNC_FOLDER_PATH_NOT_EXIST; + } + + TaskKey taskKey; + taskKey.bundleName = bundleName; + taskKey.syncChronousRootPath = registerSyncFolder; + CloudDiskServiceTaskManager::GetInstance().StartTask(taskKey, TaskType::REGISTER_TASK); + + int32_t ret = CloudDiskServiceSyncFolder::RegisterSyncFolder(userId, syncFolderIndex, registerSyncFolder); + if (ret != E_OK) { + LOGE("RegisterSyncFolder failed"); + return ret; + } + + if (CloudDiskSyncFolder::GetInstance().GetSyncFolderSize() == 0) { + DiskMonitor::GetInstance().StartMonitor(userId); + } + + SyncFolderValue syncFolderValue; + syncFolderValue.bundleName = bundleName; + syncFolderValue.path = registerSyncFolder; + + CloudDiskSyncFolder::GetInstance().AddSyncFolder(syncFolderIndex, syncFolderValue); + + CloudDiskServiceTaskManager::GetInstance().CompleteTask(taskKey, TaskType::REGISTER_TASK); + LOGI("End RegisterSyncFolderInner"); + return E_OK; +#else + return E_NOT_SUPPORTED; +#endif +} + +int32_t CloudDiskService::UnregisterSyncFolderInner(int32_t userId, + const std::string &bundleName, const std::string &path) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + LOGI("Begin UnregisterSyncFolderInner"); + RETURN_ON_ERR(CheckPermissions(PERM_CLOUD_DISK_SERVICE, true)); + + std::string unregisterSyncFolder; + if (!CloudDiskSyncFolder::GetInstance().PathToPhysicalPath(path, std::to_string(userId), unregisterSyncFolder)) { + LOGE("Get unregisterSyncFolder failed"); + return E_INVALID_ARG; + } + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(unregisterSyncFolder); + if (!CloudDiskSyncFolder::GetInstance().CheckSyncFolder(syncFolderIndex)) { + LOGE("Syncfolder is not exist"); + return E_SYNC_FOLDER_PATH_NOT_EXIST; + } + + TaskKey taskKey; + taskKey.bundleName = bundleName; + taskKey.syncChronousRootPath = unregisterSyncFolder; + CloudDiskServiceTaskManager::GetInstance().StartTask(taskKey, TaskType::REGISTER_TASK); + + int32_t ret = CloudDiskServiceSyncFolder::UnRegisterSyncFolder(userId, syncFolderIndex); + if (ret != E_OK) { + LOGE("UnRegisterSyncFolder failed"); + return ret; + } + + CloudDiskSyncFolder::GetInstance().DeleteSyncFolder(syncFolderIndex); + CloudDiskServiceCallbackManager::GetInstance().UnregisterSyncFolderMap(bundleName, syncFolderIndex); + + if (CloudDiskSyncFolder::GetInstance().GetSyncFolderSize() == 0) { + DiskMonitor::GetInstance().StopMonitor(); + } + if (!CloudDiskSyncFolder::GetInstance().PathToMntPathBySandboxPath(path, std::to_string(userId), + unregisterSyncFolder)) { + LOGE("Get unregisterSyncFolder failed"); + return E_INVALID_ARG; + } + + CloudDiskSyncFolder::GetInstance().RemoveXattr(unregisterSyncFolder, FILE_SYNC_STATE); + + CloudDiskServiceTaskManager::GetInstance().CompleteTask(taskKey, TaskType::REGISTER_TASK); + LOGI("End UnregisterSyncFolderInner"); + return E_OK; +#else + return E_NOT_SUPPORTED; +#endif +} + +int32_t CloudDiskService::UnregisterForSaInner(const std::string &path) +{ +#ifdef SUPPORT_CLOUD_DISK_SERVICE + std::string pathRemove; + int32_t userId = DfsuAccessTokenHelper::GetUserId(); + if (userId == 0) { + DfsuAccessTokenHelper::GetAccountId(userId); + } + + if (!CloudDiskSyncFolder::GetInstance().PathToSandboxPathByPhysicalPath(path, + std::to_string(userId), pathRemove)) { + LOGE("Get path failed"); + return E_INVALID_ARG; + } + int32_t ret = OHOS::FileManagement::CloudDiskSyncFolderManager::GetInstance().UnregisterForSa(pathRemove); + if (ret != E_OK) { + LOGE("UnregisterForSa failed, ret:%{public}d", ret); + return ret; + } + + if (!CloudDiskSyncFolder::GetInstance().PathToMntPathByPhysicalPath(path, std::to_string(userId), pathRemove)) { + LOGE("Get path failed"); + return E_INVALID_ARG; + } + CloudDiskSyncFolder::GetInstance().RemoveXattr(pathRemove, FILE_SYNC_STATE); + + auto syncFolderIndex = CloudDisk::CloudFileUtils::DentryHash(path); + SyncFolderValue syncFolderValue; + if (!CloudDiskSyncFolder::GetInstance().GetSyncFolderValueByIndex(syncFolderIndex, syncFolderValue)) { + LOGE("No such index"); + return E_INTERNAL_ERROR; + } + + CloudDiskSyncFolder::GetInstance().DeleteSyncFolder(syncFolderIndex); + CloudDiskServiceCallbackManager::GetInstance().UnregisterSyncFolderMap(syncFolderValue.bundleName, syncFolderIndex); + return ret; +#else + return E_NOT_SUPPORTED; +#endif +} + +void CloudDiskService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) +{ + LOGI("OnAddSystemAbility systemAbilityId:%{public}d added!", systemAbilityId); + accountStatusListener_->Start(); +} +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS diff --git a/services/clouddiskservice/ipc/src/cloud_disk_service_callback_manager.cpp b/services/clouddiskservice/ipc/src/cloud_disk_service_callback_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b799e642f19b138ca6c9f87e9bd24bad1a35494f --- /dev/null +++ b/services/clouddiskservice/ipc/src/cloud_disk_service_callback_manager.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2025 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 "cloud_disk_service_callback_manager.h" + +#include + +#include "cloud_disk_sync_folder.h" +#include "dfsu_access_token_helper.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; + +constexpr const char *FILE_SYNC_STATE = "user.clouddisk.filesyncstate"; + +CloudDiskServiceCallbackManager &CloudDiskServiceCallbackManager::GetInstance() +{ + static CloudDiskServiceCallbackManager instance; + return instance; +} + +void CloudDiskServiceCallbackManager::AddCallback( + const std::string &bundleName, const sptr &callback) +{ + unique_lock lock(callbackMutex_); + if (callbackAppMap_[bundleName].callback != nullptr) { + return; + } + if (callback == nullptr) { + LOGE("callback is nullptr"); + return; + } + callbackAppMap_[bundleName].callback = callback; + auto remoteObject = callback->AsObject(); + auto deathCb = [this, bundleName](const wptr &obj) { + LOGE("client died"); + std::vector syncFolderIndex; + auto it = callbackAppMap_.find(bundleName); + if (it != callbackAppMap_.end()) { + syncFolderIndex = it->second.syncFolderIndexs; + callbackAppMap_.erase(it); + } + int32_t userId = DfsuAccessTokenHelper::GetUserId(); + if (userId == 0) { + DfsuAccessTokenHelper::GetAccountId(userId); + } + for (auto item : syncFolderIndex) { + callbackIndexMap_.erase(item); + std::string syncFolderSync = ""; + if (!CloudDiskSyncFolder::GetInstance().GetSyncFolderByIndex(item, syncFolderSync)) { + LOGE("Get syncFolder failed"); + return; + } + std::string toRemovePath; + if (!CloudDiskSyncFolder::GetInstance().PathToMntPathByPhysicalPath( + syncFolderSync, std::to_string(userId), toRemovePath)) { + LOGE("Get physicalPath failed"); + return; + } + CloudDiskSyncFolder::GetInstance().RemoveXattr(toRemovePath, FILE_SYNC_STATE); + } + }; + auto death = sptr(new SvcDeathRecipient(deathCb)); + remoteObject->AddDeathRecipient(death); +} + +void CloudDiskServiceCallbackManager::OnChangeData( + const uint32_t syncFolderIndex, const std::vector &changeData) +{ + unique_lock lock(callbackMutex_); + auto item = callbackIndexMap_.find(syncFolderIndex); + if (item == callbackIndexMap_.end() || !item->second) { + LOGE("callback is nullptr"); + return; + } + std::string syncFolderSync; + if (!CloudDiskSyncFolder::GetInstance().GetSyncFolderByIndex(item->first, syncFolderSync)) { + LOGE("Get syncFolder failed"); + return; + } + int32_t userId = DfsuAccessTokenHelper::GetUserId(); + if (userId == 0) { + DfsuAccessTokenHelper::GetAccountId(userId); + } + std::string sandboxPath; + if (!CloudDiskSyncFolder::GetInstance().PathToSandboxPathByPhysicalPath( + syncFolderSync, std::to_string(userId), sandboxPath)) { + LOGE("Get path failed"); + return; + } + item->second->OnChangeData(sandboxPath, changeData); +} + +bool CloudDiskServiceCallbackManager::RigisterSyncFolderMap( + std::string &bundleName, uint32_t syncFolderIndex, const sptr &callback) +{ + unique_lock lock(callbackMutex_); + auto item = callbackIndexMap_.find(syncFolderIndex); + if (item != callbackIndexMap_.end()) { + LOGE("Register for this syncFolder is exist"); + return false; + } + callbackIndexMap_[syncFolderIndex] = callback; + + auto it = callbackAppMap_.find(bundleName); + if (it == callbackAppMap_.end()) { + CallbackValue callbackValue; + callbackValue.syncFolderIndexs.push_back(syncFolderIndex); + callbackAppMap_[bundleName] = callbackValue; + } else { + it->second.syncFolderIndexs.push_back(syncFolderIndex); + } + return true; +} + +void CloudDiskServiceCallbackManager::UnregisterSyncFolderMap(const std::string &bundleName, uint32_t syncFolderIndex) +{ + unique_lock lock(callbackMutex_); + auto it = callbackIndexMap_.find(syncFolderIndex); + if (it != callbackIndexMap_.end()) { + callbackIndexMap_.erase(it); + } + + auto item = callbackAppMap_.find(bundleName); + if (item != callbackAppMap_.end()) { + auto &vec = item->second.syncFolderIndexs; + auto pos = std::find(vec.begin(), vec.end(), syncFolderIndex); + if (pos != vec.end()) { + vec.erase(pos); + } + } +} + +bool CloudDiskServiceCallbackManager::UnregisterSyncFolderForChangesMap( + std::string &bundleName, uint32_t syncFolderIndex) +{ + unique_lock lock(callbackMutex_); + auto it = callbackIndexMap_.find(syncFolderIndex); + if (it == callbackIndexMap_.end()) { + LOGE("No register for this syncFolder"); + return false; + } + callbackIndexMap_.erase(it); + + auto item = callbackAppMap_.find(bundleName); + if (item == callbackAppMap_.end()) { + LOGE("No such app in callback"); + return false; + } + auto &vec = item->second.syncFolderIndexs; + auto pos = std::find(vec.begin(), vec.end(), syncFolderIndex); + if (pos != vec.end()) { + vec.erase(pos); + } + return true; +} + +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/services/clouddiskservice/ipc/src/cloud_disk_service_callback_proxy.cpp b/services/clouddiskservice/ipc/src/cloud_disk_service_callback_proxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3800e0cd9d4aded5ee5870bd804cfeb56d7ffc0 --- /dev/null +++ b/services/clouddiskservice/ipc/src/cloud_disk_service_callback_proxy.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025 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 "cloud_disk_service_callback_proxy.h" + +#include "cloud_file_error.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; + +void CloudDiskServiceCallbackProxy::OnChangeData(const std::string &sandboxPath, + const std::vector &changeData) +{ + LOGI("Start"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + LOGE("Failed to write interface token"); + return; + } + + if (changeData.size() > static_cast(VECTOR_MAX_SIZE)) { + return; + } + + data.WriteString(sandboxPath); + data.WriteInt32(changeData.size()); + for (auto item = changeData.begin(); item != changeData.end(); ++item) { + if (!data.WriteParcelable(&(*item))) { + return; + } + } + auto remote = Remote(); + if (!remote) { + LOGE("remote is nullptr"); + return; + } + int32_t ret = remote->SendRequest(ICloudDiskServiceCallback::SERVICE_CMD_ON_CHANGE_DATA, data, reply, option); + if (ret != E_OK) { + LOGE("Failed to send out the requeset, ret:%{public}d", ret); + return; + } + LOGI("End"); + return; +} +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/services/clouddiskservice/ipc/src/cloud_disk_sync_folder.cpp b/services/clouddiskservice/ipc/src/cloud_disk_sync_folder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..60c7108639aeb5da54414ad41b4b564851c64085 --- /dev/null +++ b/services/clouddiskservice/ipc/src/cloud_disk_sync_folder.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2025 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 "cloud_disk_sync_folder.h" + +#include +#include +#include + +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { +using namespace std; + +CloudDiskSyncFolder &CloudDiskSyncFolder::GetInstance() +{ + static CloudDiskSyncFolder instance; + return instance; +} + +void CloudDiskSyncFolder::AddSyncFolder(const uint32_t &syncFolderIndex, const SyncFolderValue &syncFolderValue) +{ + unique_lock lock(mutex_); + auto item = syncFolderMap.find(syncFolderIndex); + if (item == syncFolderMap.end()) { + syncFolderMap[syncFolderIndex] = syncFolderValue; + } +} + +void CloudDiskSyncFolder::DeleteSyncFolder(const uint32_t &syncFolderIndex) +{ + unique_lock lock(mutex_); + auto item = syncFolderMap.find(syncFolderIndex); + if (item != syncFolderMap.end()) { + syncFolderMap.erase(syncFolderIndex); + } +} + +int32_t CloudDiskSyncFolder::GetSyncFolderSize() +{ + unique_lock lock(mutex_); + return syncFolderMap.size(); +} + +bool CloudDiskSyncFolder::CheckSyncFolder(const uint32_t &syncFolderIndex) +{ + unique_lock lock(mutex_); + auto it = syncFolderMap.find(syncFolderIndex); + if (it == syncFolderMap.end()) { + return false; + } + return true; +} + +bool CloudDiskSyncFolder::GetSyncFolderByIndex(const uint32_t syncFolderIndex, std::string &path) +{ + unique_lock lock(mutex_); + auto item = syncFolderMap.find(syncFolderIndex); + if (item == syncFolderMap.end()) { + return false; + } + path = item->second.path; + return true; +} + +bool CloudDiskSyncFolder::GetSyncFolderValueByIndex(const uint32_t syncFolderIndex, SyncFolderValue &syncFolderValue) +{ + unique_lock lock(mutex_); + auto item = syncFolderMap.find(syncFolderIndex); + if (item == syncFolderMap.end()) { + return false; + } + syncFolderValue = item->second; + return true; +} + +bool CloudDiskSyncFolder::GetIndexBySyncFolder(uint32_t &syncFolderIndex, const std::string &path) +{ + unique_lock lock(mutex_); + for (const auto &item : syncFolderMap) { + if (item.second.path == path) { + syncFolderIndex = item.first; + return true; + } + } + return false; +} + +std::unordered_map CloudDiskSyncFolder::GetSyncFolderMap() +{ + unique_lock lock(mutex_); + return syncFolderMap; +} + +void CloudDiskSyncFolder::RemoveXattr(std::string &path, const std::string &attrName) +{ + DIR *dir = opendir(path.c_str()); + if (!dir) { + LOGE("Open failed, err:%{public}d", errno); + return; + } + struct dirent *entry; + while ((entry = readdir(dir)) != nullptr) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + char realPath[PATH_MAX] = {'\0'}; + std::string pathToRemove = path + "/" + entry->d_name; + if (realpath(pathToRemove.c_str(), realPath) == nullptr) { + LOGE("get realPath failed, errno: %{public}d", errno); + continue; + } + + struct stat st; + if (lstat(realPath, &st) == -1) { + LOGE("lstat failed"); + continue; + } + if (S_ISDIR(st.st_mode)) { + RemoveXattr(pathToRemove, attrName); + } + if (S_ISREG(st.st_mode)) { + removexattr(realPath, attrName.c_str()); + } + } + closedir(dir); +} + +bool CloudDiskSyncFolder::PathToPhysicalPath(const std::string &path, const std::string &userId, std::string &realpath) +{ + std::string sandboxPath = "/storage/Users/currentUser"; + std::string replacementPath = "/data/service/el2/" + userId + "/hmdfs/account/files/Docs"; + + if (path.substr(0, sandboxPath.length()) != sandboxPath) { + LOGE("replace path failed"); + return false; + } + realpath = replacementPath + path.substr(sandboxPath.length()); + return true; +} + +bool CloudDiskSyncFolder::PathToMntPathBySandboxPath(const std::string &path, + const std::string &userId, + std::string &realpath) +{ + std::string sandboxPath = "/storage/Users/currentUser"; + std::string replacementPath = "/mnt/hmdfs/" + userId + "/account/device_view/local/files/Docs"; + + if (path.substr(0, sandboxPath.length()) != sandboxPath) { + LOGE("replace path failed"); + return false; + } + realpath = replacementPath + path.substr(sandboxPath.length()); + return true; +} + +bool CloudDiskSyncFolder::PathToMntPathByPhysicalPath(const std::string &path, + const std::string &userId, + std::string &realpath) +{ + std::string sandboxPath = "/data/service/el2/" + userId + "/hmdfs/account/files/Docs"; + std::string replacementPath = "/mnt/hmdfs/" + userId + "/account/device_view/local/files/Docs"; + + if (path.substr(0, sandboxPath.length()) != sandboxPath) { + LOGE("replace path failed"); + return false; + } + realpath = replacementPath + path.substr(sandboxPath.length()); + return true; +} + +bool CloudDiskSyncFolder::PathToSandboxPathByPhysicalPath(const std::string &path, + const std::string &userId, + std::string &realpath) +{ + std::string physicalPath = "/data/service/el2/" + userId + "/hmdfs/account/files/Docs"; + std::string replacementPath = "/storage/Users/currentUser"; + + if (path.substr(0, physicalPath.length()) != physicalPath) { + LOGE("replace path failed"); + return false; + } + realpath = replacementPath + path.substr(physicalPath.length()); + return true; +} +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file