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