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