1cb7eb8c9Sopenharmony_ci/* 2cb7eb8c9Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3cb7eb8c9Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4cb7eb8c9Sopenharmony_ci * you may not use this file except in compliance with the License. 5cb7eb8c9Sopenharmony_ci * You may obtain a copy of the License at 6cb7eb8c9Sopenharmony_ci * 7cb7eb8c9Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8cb7eb8c9Sopenharmony_ci * 9cb7eb8c9Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10cb7eb8c9Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11cb7eb8c9Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cb7eb8c9Sopenharmony_ci * See the License for the specific language governing permissions and 13cb7eb8c9Sopenharmony_ci * limitations under the License. 14cb7eb8c9Sopenharmony_ci */ 15cb7eb8c9Sopenharmony_ci 16cb7eb8c9Sopenharmony_ci#include "ipc/cloud_daemon.h" 17cb7eb8c9Sopenharmony_ci 18cb7eb8c9Sopenharmony_ci#include <exception> 19cb7eb8c9Sopenharmony_ci#include <stdexcept> 20cb7eb8c9Sopenharmony_ci#include <thread> 21cb7eb8c9Sopenharmony_ci#include <malloc.h> 22cb7eb8c9Sopenharmony_ci#include <sys/stat.h> 23cb7eb8c9Sopenharmony_ci#include <sys/utsname.h> 24cb7eb8c9Sopenharmony_ci 25cb7eb8c9Sopenharmony_ci#include "iremote_object.h" 26cb7eb8c9Sopenharmony_ci#include "system_ability_definition.h" 27cb7eb8c9Sopenharmony_ci#include "parameters.h" 28cb7eb8c9Sopenharmony_ci#include "plugin_loader.h" 29cb7eb8c9Sopenharmony_ci#include "dfs_error.h" 30cb7eb8c9Sopenharmony_ci#include "fuse_manager/fuse_manager.h" 31cb7eb8c9Sopenharmony_ci#include "utils_directory.h" 32cb7eb8c9Sopenharmony_ci#include "utils_log.h" 33cb7eb8c9Sopenharmony_ci 34cb7eb8c9Sopenharmony_cinamespace OHOS { 35cb7eb8c9Sopenharmony_cinamespace FileManagement { 36cb7eb8c9Sopenharmony_cinamespace CloudFile { 37cb7eb8c9Sopenharmony_ciusing namespace std; 38cb7eb8c9Sopenharmony_ciusing namespace CloudDisk; 39cb7eb8c9Sopenharmony_ci 40cb7eb8c9Sopenharmony_cinamespace { 41cb7eb8c9Sopenharmony_ci static const string LOCAL_PATH_DATA_SERVICE_EL2 = "/data/service/el2/"; 42cb7eb8c9Sopenharmony_ci static const string LOCAL_PATH_HMDFS_DENTRY_CACHE = "/hmdfs/cache/account_cache/dentry_cache/"; 43cb7eb8c9Sopenharmony_ci static const string LOCAL_PATH_HMDFS_CACHE_CLOUD = "/hmdfs/cache/account_cache/dentry_cache/cloud"; 44cb7eb8c9Sopenharmony_ci static const int32_t STAT_MODE_DIR = 0771; 45cb7eb8c9Sopenharmony_ci static const int32_t STAT_MODE_DIR_DENTRY_CACHE = 02771; 46cb7eb8c9Sopenharmony_ci static const int32_t OID_DFS = 1009; 47cb7eb8c9Sopenharmony_ci} 48cb7eb8c9Sopenharmony_ciREGISTER_SYSTEM_ABILITY_BY_ID(CloudDaemon, FILEMANAGEMENT_CLOUD_DAEMON_SERVICE_SA_ID, true); 49cb7eb8c9Sopenharmony_ci 50cb7eb8c9Sopenharmony_ciCloudDaemon::CloudDaemon(int32_t saID, bool runOnCreate) : SystemAbility(saID, runOnCreate) 51cb7eb8c9Sopenharmony_ci{ 52cb7eb8c9Sopenharmony_ci accountStatusListener_ = make_shared<AccountStatusListener>(); 53cb7eb8c9Sopenharmony_ci} 54cb7eb8c9Sopenharmony_ci 55cb7eb8c9Sopenharmony_civoid CloudDaemon::PublishSA() 56cb7eb8c9Sopenharmony_ci{ 57cb7eb8c9Sopenharmony_ci LOGI("Begin to init"); 58cb7eb8c9Sopenharmony_ci if (!registerToService_) { 59cb7eb8c9Sopenharmony_ci bool ret = SystemAbility::Publish(this); 60cb7eb8c9Sopenharmony_ci if (!ret) { 61cb7eb8c9Sopenharmony_ci throw runtime_error("Failed to publish the daemon"); 62cb7eb8c9Sopenharmony_ci } 63cb7eb8c9Sopenharmony_ci registerToService_ = true; 64cb7eb8c9Sopenharmony_ci } 65cb7eb8c9Sopenharmony_ci LOGI("Init finished successfully"); 66cb7eb8c9Sopenharmony_ci} 67cb7eb8c9Sopenharmony_ci 68cb7eb8c9Sopenharmony_cistatic bool CheckDeviceInLinux() 69cb7eb8c9Sopenharmony_ci{ 70cb7eb8c9Sopenharmony_ci struct utsname uts; 71cb7eb8c9Sopenharmony_ci if (uname(&uts) == -1) { 72cb7eb8c9Sopenharmony_ci LOGE("uname get failed."); 73cb7eb8c9Sopenharmony_ci return false; 74cb7eb8c9Sopenharmony_ci } 75cb7eb8c9Sopenharmony_ci if (strcmp(uts.sysname, "Linux") == 0) { 76cb7eb8c9Sopenharmony_ci LOGI("uname system is linux."); 77cb7eb8c9Sopenharmony_ci return true; 78cb7eb8c9Sopenharmony_ci } 79cb7eb8c9Sopenharmony_ci return false; 80cb7eb8c9Sopenharmony_ci} 81cb7eb8c9Sopenharmony_ci 82cb7eb8c9Sopenharmony_cistatic void ModSysParam() 83cb7eb8c9Sopenharmony_ci{ 84cb7eb8c9Sopenharmony_ci if (CheckDeviceInLinux()) { 85cb7eb8c9Sopenharmony_ci const string photos = "persist.kernel.bundle_name.photos"; 86cb7eb8c9Sopenharmony_ci const string clouddrive = "persist.kernel.bundle_name.clouddrive"; 87cb7eb8c9Sopenharmony_ci system::SetParameter(photos, ""); 88cb7eb8c9Sopenharmony_ci system::SetParameter(clouddrive, ""); 89cb7eb8c9Sopenharmony_ci } 90cb7eb8c9Sopenharmony_ci} 91cb7eb8c9Sopenharmony_ci 92cb7eb8c9Sopenharmony_civoid CloudDaemon::OnStart() 93cb7eb8c9Sopenharmony_ci{ 94cb7eb8c9Sopenharmony_ci LOGI("Begin to start service"); 95cb7eb8c9Sopenharmony_ci if (state_ == ServiceRunningState::STATE_RUNNING) { 96cb7eb8c9Sopenharmony_ci LOGI("Daemon has already started"); 97cb7eb8c9Sopenharmony_ci return; 98cb7eb8c9Sopenharmony_ci } 99cb7eb8c9Sopenharmony_ci 100cb7eb8c9Sopenharmony_ci try { 101cb7eb8c9Sopenharmony_ci PublishSA(); 102cb7eb8c9Sopenharmony_ci AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID); 103cb7eb8c9Sopenharmony_ci mode_t mode = 002; 104cb7eb8c9Sopenharmony_ci umask(mode); 105cb7eb8c9Sopenharmony_ci ModSysParam(); 106cb7eb8c9Sopenharmony_ci } catch (const exception &e) { 107cb7eb8c9Sopenharmony_ci LOGE("%{public}s", e.what()); 108cb7eb8c9Sopenharmony_ci } 109cb7eb8c9Sopenharmony_ci 110cb7eb8c9Sopenharmony_ci state_ = ServiceRunningState::STATE_RUNNING; 111cb7eb8c9Sopenharmony_ci /* load cloud file ext plugin */ 112cb7eb8c9Sopenharmony_ci CloudFile::PluginLoader::GetInstance().LoadCloudKitPlugin(); 113cb7eb8c9Sopenharmony_ci LOGI("Start service successfully"); 114cb7eb8c9Sopenharmony_ci} 115cb7eb8c9Sopenharmony_ci 116cb7eb8c9Sopenharmony_civoid HandleStartMove(int32_t userId) 117cb7eb8c9Sopenharmony_ci{ 118cb7eb8c9Sopenharmony_ci const std::string filemanagerKey = "persist.kernel.bundle_name.filemanager"; 119cb7eb8c9Sopenharmony_ci string subList[] = {"com.ohos.photos", system::GetParameter(filemanagerKey, "")}; 120cb7eb8c9Sopenharmony_ci string srcBase = "/data/service/el1/public/cloudfile/" + to_string(userId); 121cb7eb8c9Sopenharmony_ci string dstBase = "/data/service/el2/" + to_string(userId) + "/hmdfs/cloudfile_manager"; 122cb7eb8c9Sopenharmony_ci const auto copyOptions = filesystem::copy_options::overwrite_existing | filesystem::copy_options::recursive; 123cb7eb8c9Sopenharmony_ci for (auto sub : subList) { 124cb7eb8c9Sopenharmony_ci string srcPath = srcBase + '/' + sub; 125cb7eb8c9Sopenharmony_ci string dstPath = dstBase + '/' + sub; 126cb7eb8c9Sopenharmony_ci if (access(srcPath.c_str(), F_OK) != 0) { 127cb7eb8c9Sopenharmony_ci LOGI("srcPath %{public}s not found", GetAnonyString(srcPath).c_str()); 128cb7eb8c9Sopenharmony_ci continue; 129cb7eb8c9Sopenharmony_ci } 130cb7eb8c9Sopenharmony_ci LOGI("Begin to move path: %{public}s", GetAnonyString(srcPath).c_str()); 131cb7eb8c9Sopenharmony_ci error_code errCode; 132cb7eb8c9Sopenharmony_ci filesystem::copy(srcPath, dstPath, copyOptions, errCode); 133cb7eb8c9Sopenharmony_ci if (errCode.value() != 0) { 134cb7eb8c9Sopenharmony_ci LOGE("copy failed path: %{public}s, errCode: %{public}d", 135cb7eb8c9Sopenharmony_ci GetAnonyString(srcPath).c_str(), errCode.value()); 136cb7eb8c9Sopenharmony_ci } 137cb7eb8c9Sopenharmony_ci LOGI("End move path: %{public}s", GetAnonyString(srcPath).c_str()); 138cb7eb8c9Sopenharmony_ci bool ret = Storage::DistributedFile::Utils::ForceRemoveDirectoryDeepFirst(srcPath); 139cb7eb8c9Sopenharmony_ci if (!ret) { 140cb7eb8c9Sopenharmony_ci LOGE("remove failed path: %{public}s", GetAnonyString(srcPath).c_str()); 141cb7eb8c9Sopenharmony_ci } 142cb7eb8c9Sopenharmony_ci } 143cb7eb8c9Sopenharmony_ci const string moveFile = "persist.kernel.move.finish"; 144cb7eb8c9Sopenharmony_ci system::SetParameter(moveFile, "true"); 145cb7eb8c9Sopenharmony_ci} 146cb7eb8c9Sopenharmony_ci 147cb7eb8c9Sopenharmony_civoid CloudDaemon::OnStop() 148cb7eb8c9Sopenharmony_ci{ 149cb7eb8c9Sopenharmony_ci LOGI("Begin to stop"); 150cb7eb8c9Sopenharmony_ci state_ = ServiceRunningState::STATE_NOT_START; 151cb7eb8c9Sopenharmony_ci registerToService_ = false; 152cb7eb8c9Sopenharmony_ci LOGI("Stop finished successfully"); 153cb7eb8c9Sopenharmony_ci} 154cb7eb8c9Sopenharmony_ci 155cb7eb8c9Sopenharmony_civoid CloudDaemon::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) 156cb7eb8c9Sopenharmony_ci{ 157cb7eb8c9Sopenharmony_ci LOGI("OnAddSystemAbility systemAbilityId:%{public}d added!", systemAbilityId); 158cb7eb8c9Sopenharmony_ci accountStatusListener_->Start(); 159cb7eb8c9Sopenharmony_ci} 160cb7eb8c9Sopenharmony_ci 161cb7eb8c9Sopenharmony_ciint32_t CloudDaemon::StartFuse(int32_t userId, int32_t devFd, const string &path) 162cb7eb8c9Sopenharmony_ci{ 163cb7eb8c9Sopenharmony_ci LOGI("Start Fuse"); 164cb7eb8c9Sopenharmony_ci std::thread([=]() { 165cb7eb8c9Sopenharmony_ci int32_t ret = FuseManager::GetInstance().StartFuse(userId, devFd, path); 166cb7eb8c9Sopenharmony_ci LOGI("start fuse result %d", ret); 167cb7eb8c9Sopenharmony_ci }).detach(); 168cb7eb8c9Sopenharmony_ci 169cb7eb8c9Sopenharmony_ci string dentryPath = LOCAL_PATH_DATA_SERVICE_EL2 + to_string(userId) + LOCAL_PATH_HMDFS_CACHE_CLOUD; 170cb7eb8c9Sopenharmony_ci if (access(dentryPath.c_str(), F_OK) != 0) { 171cb7eb8c9Sopenharmony_ci string cachePath = LOCAL_PATH_DATA_SERVICE_EL2 + to_string(userId) + LOCAL_PATH_HMDFS_DENTRY_CACHE; 172cb7eb8c9Sopenharmony_ci if (mkdir(cachePath.c_str(), STAT_MODE_DIR) != 0 && errno != EEXIST) { 173cb7eb8c9Sopenharmony_ci LOGE("create accout_cache path error %{public}d", errno); 174cb7eb8c9Sopenharmony_ci return E_PATH; 175cb7eb8c9Sopenharmony_ci } 176cb7eb8c9Sopenharmony_ci if (chmod(cachePath.c_str(), STAT_MODE_DIR_DENTRY_CACHE) != 0) { 177cb7eb8c9Sopenharmony_ci LOGE("chmod cachepath error %{public}d", errno); 178cb7eb8c9Sopenharmony_ci } 179cb7eb8c9Sopenharmony_ci if (chown(cachePath.c_str(), OID_DFS, OID_DFS) != 0) { 180cb7eb8c9Sopenharmony_ci LOGE("chown cachepath error %{public}d", errno); 181cb7eb8c9Sopenharmony_ci } 182cb7eb8c9Sopenharmony_ci if (mkdir(dentryPath.c_str(), STAT_MODE_DIR) != 0 && errno != EEXIST) { 183cb7eb8c9Sopenharmony_ci LOGE("create dentrypath %{public}d", errno); 184cb7eb8c9Sopenharmony_ci return E_PATH; 185cb7eb8c9Sopenharmony_ci } 186cb7eb8c9Sopenharmony_ci if (chown(dentryPath.c_str(), OID_DFS, OID_DFS) != 0) { 187cb7eb8c9Sopenharmony_ci LOGE("chown cachepath error %{public}d", errno); 188cb7eb8c9Sopenharmony_ci } 189cb7eb8c9Sopenharmony_ci } 190cb7eb8c9Sopenharmony_ci if (path.find("cloud_fuse") != string::npos) { 191cb7eb8c9Sopenharmony_ci std::thread([userId]() { 192cb7eb8c9Sopenharmony_ci HandleStartMove(userId); 193cb7eb8c9Sopenharmony_ci }).detach(); 194cb7eb8c9Sopenharmony_ci } 195cb7eb8c9Sopenharmony_ci return E_OK; 196cb7eb8c9Sopenharmony_ci} 197cb7eb8c9Sopenharmony_ci} // namespace CloudFile 198cb7eb8c9Sopenharmony_ci} // namespace FileManagement 199cb7eb8c9Sopenharmony_ci} // namespace OHOS 200