/* * 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 "ipc/cloud_daemon.h" #include #include #include #include #include #include #include "iremote_object.h" #include "system_ability_definition.h" #include "parameters.h" #include "plugin_loader.h" #include "dfs_error.h" #include "fuse_manager/fuse_manager.h" #include "utils_directory.h" #include "utils_log.h" namespace OHOS { namespace FileManagement { namespace CloudFile { using namespace std; using namespace CloudDisk; namespace { static const string LOCAL_PATH_DATA_SERVICE_EL2 = "/data/service/el2/"; static const string LOCAL_PATH_HMDFS_DENTRY_CACHE = "/hmdfs/cache/account_cache/dentry_cache/"; static const string LOCAL_PATH_HMDFS_CACHE_CLOUD = "/hmdfs/cache/account_cache/dentry_cache/cloud"; static const int32_t STAT_MODE_DIR = 0771; static const int32_t STAT_MODE_DIR_DENTRY_CACHE = 02771; static const int32_t OID_DFS = 1009; } REGISTER_SYSTEM_ABILITY_BY_ID(CloudDaemon, FILEMANAGEMENT_CLOUD_DAEMON_SERVICE_SA_ID, true); CloudDaemon::CloudDaemon(int32_t saID, bool runOnCreate) : SystemAbility(saID, runOnCreate) { accountStatusListener_ = make_shared(); } void CloudDaemon::PublishSA() { LOGI("Begin to init"); if (!registerToService_) { bool ret = SystemAbility::Publish(this); if (!ret) { throw runtime_error("Failed to publish the daemon"); } registerToService_ = true; } LOGI("Init finished successfully"); } static bool CheckDeviceInLinux() { struct utsname uts; if (uname(&uts) == -1) { LOGE("uname get failed."); return false; } if (strcmp(uts.sysname, "Linux") == 0) { LOGI("uname system is linux."); return true; } return false; } static void ModSysParam() { if (CheckDeviceInLinux()) { const string photos = "persist.kernel.bundle_name.photos"; const string clouddrive = "persist.kernel.bundle_name.clouddrive"; system::SetParameter(photos, ""); system::SetParameter(clouddrive, ""); } } void CloudDaemon::OnStart() { LOGI("Begin to start service"); if (state_ == ServiceRunningState::STATE_RUNNING) { LOGI("Daemon has already started"); return; } try { PublishSA(); AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID); mode_t mode = 002; umask(mode); ModSysParam(); } catch (const exception &e) { LOGE("%{public}s", e.what()); } state_ = ServiceRunningState::STATE_RUNNING; /* load cloud file ext plugin */ CloudFile::PluginLoader::GetInstance().LoadCloudKitPlugin(); LOGI("Start service successfully"); } void HandleStartMove(int32_t userId) { const string moveFile = "persist.kernel.move.finish"; system::SetParameter(moveFile, "false"); const std::string filemanagerKey = "persist.kernel.bundle_name.filemanager"; string subList[] = {"com.ohos.photos", system::GetParameter(filemanagerKey, "")}; string srcBase = "/data/service/el1/public/cloudfile/" + to_string(userId); string dstBase = "/data/service/el2/" + to_string(userId) + "/hmdfs/cloudfile_manager"; const auto copyOptions = filesystem::copy_options::overwrite_existing | filesystem::copy_options::recursive; for (auto sub : subList) { string srcPath = srcBase + '/' + sub; string dstPath = dstBase + '/' + sub; if (access(srcPath.c_str(), F_OK) != 0) { LOGI("srcPath %{public}s not found", GetAnonyString(srcPath).c_str()); continue; } LOGI("Begin to move path: %{public}s", GetAnonyString(srcPath).c_str()); error_code errCode; filesystem::copy(srcPath, dstPath, copyOptions, errCode); if (errCode.value() != 0) { LOGE("copy failed path: %{public}s, errCode: %{public}d", GetAnonyString(srcPath).c_str(), errCode.value()); } LOGI("End move path: %{public}s", GetAnonyString(srcPath).c_str()); bool ret = Storage::DistributedFile::Utils::ForceRemoveDirectoryDeepFirst(srcPath); if (!ret) { LOGE("remove failed path: %{public}s", GetAnonyString(srcPath).c_str()); } } system::SetParameter(moveFile, "true"); } void CloudDaemon::OnStop() { LOGI("Begin to stop"); state_ = ServiceRunningState::STATE_NOT_START; registerToService_ = false; LOGI("Stop finished successfully"); } void CloudDaemon::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) { LOGI("OnAddSystemAbility systemAbilityId:%{public}d added!", systemAbilityId); accountStatusListener_->Start(); } int32_t CloudDaemon::StartFuse(int32_t userId, int32_t devFd, const string &path) { LOGI("Start Fuse"); std::thread([=]() { int32_t ret = FuseManager::GetInstance().StartFuse(userId, devFd, path); LOGI("start fuse result %d", ret); }).detach(); string dentryPath = LOCAL_PATH_DATA_SERVICE_EL2 + to_string(userId) + LOCAL_PATH_HMDFS_CACHE_CLOUD; if (access(dentryPath.c_str(), F_OK) != 0) { string cachePath = LOCAL_PATH_DATA_SERVICE_EL2 + to_string(userId) + LOCAL_PATH_HMDFS_DENTRY_CACHE; if (mkdir(cachePath.c_str(), STAT_MODE_DIR) != 0 && errno != EEXIST) { LOGE("create accout_cache path error %{public}d", errno); return E_PATH; } if (chmod(cachePath.c_str(), STAT_MODE_DIR_DENTRY_CACHE) != 0) { LOGE("chmod cachepath error %{public}d", errno); } if (chown(cachePath.c_str(), OID_DFS, OID_DFS) != 0) { LOGE("chown cachepath error %{public}d", errno); } if (mkdir(dentryPath.c_str(), STAT_MODE_DIR) != 0 && errno != EEXIST) { LOGE("create dentrypath %{public}d", errno); return E_PATH; } if (chown(dentryPath.c_str(), OID_DFS, OID_DFS) != 0) { LOGE("chown cachepath error %{public}d", errno); } } if (path.find("cloud_fuse") != string::npos) { std::thread([userId]() { HandleStartMove(userId); }).detach(); } return E_OK; } } // namespace CloudFile } // namespace FileManagement } // namespace OHOS