• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 "user/mount_manager.h"
17 #include <cstdlib>
18 #include <csignal>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <set>
22 #include <sys/mount.h>
23 #include <sys/types.h>
24 #include <thread>
25 #include <unistd.h>
26 #include <regex>
27 #include <filesystem>
28 #include "hisysevent.h"
29 #include "utils/storage_radar.h"
30 #include "ipc/istorage_daemon.h"
31 #include "parameter.h"
32 #include "quota/quota_manager.h"
33 #include "storage_service_constant.h"
34 #include "storage_service_errno.h"
35 #include "storage_service_log.h"
36 #include "utils/file_utils.h"
37 #include "utils/mount_argument_utils.h"
38 #include "utils/string_utils.h"
39 #include "system_ability_definition.h"
40 #ifdef DFS_SERVICE
41 #include "cloud_daemon_manager.h"
42 #endif
43 #ifdef USE_LIBRESTORECON
44 #include "policycoreutils.h"
45 #endif
46 
47 namespace OHOS {
48 namespace StorageDaemon {
49 using namespace std;
50 #ifdef DFS_SERVICE
51 using namespace OHOS::FileManagement::CloudFile;
52 #endif
53 using namespace OHOS::StorageService;
54 constexpr int32_t UMOUNT_RETRY_TIMES = 3;
55 constexpr int32_t ONE_KB = 1024;
56 std::shared_ptr<MountManager> MountManager::instance_ = nullptr;
57 
58 const string SANDBOX_ROOT_PATH = "/mnt/sandbox/";
59 const string CURRENT_USER_ID_FLAG = "<currentUserId>";
60 const string PACKAGE_NAME_FLAG = "<bundleName>";
61 const string SCENE_BOARD_BUNDLE_NAME = "com.ohos.sceneboard";
62 const string PUBLIC_DIR_SANDBOX_PATH = "/storage/Users/currentUser";
63 const string PUBLIC_DIR_SRC_PATH = "/storage/media/<currentUserId>/local/files/Docs";
64 const string MOUNT_POINT_INFO = "/proc/mounts";
65 const string MOUNT_POINT_TYPE_HMDFS = "hmdfs";
66 const string MOUNT_POINT_TYPE_HMFS = "hmfs";
67 const string MOUNT_POINT_TYPE_SHAREFS = "sharefs";
68 const string EL2_BASE = "/data/storage/el2/base/";
69 const string MOUNT_SUFFIX = "_locked";
70 const set<string> SANDBOX_EXCLUDE_PATH = {
71     "chipset",
72     "system",
73     "com.ohos.render"
74 };
75 const vector<string> CRYPTO_SANDBOX_PATH = {
76     "/data/storage/el2/base/",
77     "/data/storage/el2/database/",
78     "/data/storage/el2/share/",
79     "/data/storage/el2/log/",
80     "/data/storage/el2/distributedfiles/",
81     "/data/storage/el2/cloud/",
82     "/data/storage/el3/base/",
83     "/data/storage/el3/database/",
84     "/data/storage/el4/base/",
85     "/data/storage/el4/database/",
86     "/data/storage/el5/base/",
87     "/data/storage/el5/database/"
88 };
89 const vector<string> CRYPTO_SRC_PATH = {
90     "/data/app/el2/<currentUserId>/base/<bundleName>/",
91     "/data/app/el2/<currentUserId>/database/<bundleName>/",
92     "/mnt/share/<currentUserId>/<bundleName>/",
93     "/data/app/el2/<currentUserId>/log/<bundleName>/",
94     "/mnt/hmdfs/<currentUserId>/account/merge_view/data/<bundleName>/",
95     "/mnt/hmdfs/<currentUserId>/cloud/data/<bundleName>/",
96     "/data/app/el3/<currentUserId>/base/<bundleName>/",
97     "/data/app/el3/<currentUserId>/database/<bundleName>/",
98     "/data/app/el4/<currentUserId>/base/<bundleName>/",
99     "/data/app/el4/<currentUserId>/database/<bundleName>/",
100     "/data/app/el5/<currentUserId>/base/<bundleName>/",
101     "/data/app/el5/<currentUserId>/database/<bundleName>/"
102 };
103 const std::string HMDFS_SYS_CAP = "const.distributed_file_property.enabled";
104 const int32_t HMDFS_VAL_LEN = 6;
105 const int32_t HMDFS_TRUE_LEN = 5;
106 const string SHARE_PATH = "/data/service/el1/public/storage_daemon/share/public";
107 static constexpr int MODE_0711 = 0711;
108 static constexpr int MODE_0771 = 0771;
109 static constexpr int MODE_02771 = 02771;
MountManager()110 MountManager::MountManager()
111     : hmdfsDirVec_{{"/data/service/el2/%d/share", MODE_0711, OID_SYSTEM, OID_SYSTEM},
112                    {"/data/service/el2/%d/hmdfs", MODE_0711, OID_DFS, OID_DFS},
113                    {"/data/service/el2/%d/hmdfs/account", MODE_0711, OID_SYSTEM, OID_SYSTEM},
114                    {"/data/service/el2/%d/hmdfs/account/files", MODE_02771, OID_USER_DATA_RW, OID_USER_DATA_RW},
115                    {"/data/service/el2/%d/hmdfs/account/data", MODE_0711, OID_SYSTEM, OID_SYSTEM},
116                    {"/data/service/el2/%d/hmdfs/non_account", MODE_0711, OID_SYSTEM, OID_SYSTEM},
117                    {"/data/service/el2/%d/hmdfs/non_account/files", MODE_0711, OID_USER_DATA_RW, OID_USER_DATA_RW},
118                    {"/data/service/el2/%d/hmdfs/non_account/data", MODE_0711, OID_SYSTEM, OID_SYSTEM},
119                    {"/data/service/el2/%d/hmdfs/cloud", MODE_0711, OID_DFS, OID_DFS},
120                    {"/data/service/el2/%d/hmdfs/cloud/data", MODE_0711, OID_DFS, OID_DFS},
121                    {"/data/service/el2/%d/hmdfs/cache", MODE_0711, OID_DFS, OID_DFS},
122                    {"/data/service/el2/%d/hmdfs/cloudfile_manager", MODE_0711, OID_DFS, OID_DFS},
123                    {"/data/service/el2/%d/hmdfs/cache/account_cache", MODE_0711, OID_DFS, OID_DFS},
124                    {"/data/service/el2/%d/hmdfs/cache/non_account_cache", MODE_0711, OID_DFS, OID_DFS},
125                    {"/data/service/el2/%d/hmdfs/cache/cloud_cache", MODE_0711, OID_DFS, OID_DFS},
126                    {"/data/service/el2/%d/hmdfs/account/services", MODE_0771, OID_DFS_SHARE, OID_DFS_SHARE}},
127       virtualDir_{{"/storage/media/%d", MODE_0711, OID_USER_DATA_RW, OID_USER_DATA_RW},
128                   {"/storage/media/%d/local", MODE_0711, OID_USER_DATA_RW, OID_USER_DATA_RW},
129                   {"/storage/cloud", MODE_0711, OID_ROOT, OID_ROOT},
130                   {"/storage/cloud/%d", MODE_0711, OID_USER_DATA_RW, OID_USER_DATA_RW},
131                   {"/mnt/share/", MODE_0711, OID_ROOT, OID_ROOT},
132                   {"/mnt/share/%d/", MODE_0711, OID_ROOT, OID_ROOT},
133                   {"/mnt/data/%d/", MODE_0711, OID_ROOT, OID_ROOT},
134                   {"/mnt/data/%d/cloud", MODE_0711, OID_ROOT, OID_ROOT},
135                   {"/mnt/data/%d/cloud_fuse", MODE_0711, OID_DFS, OID_DFS},
136                   {"/mnt/data/%d/hmdfs", MODE_0711, OID_FILE_MANAGER, OID_FILE_MANAGER},
137                   {"/mnt/hmdfs/", MODE_0711, OID_ROOT, OID_ROOT},
138                   {"/mnt/hmdfs/%d/", MODE_0711, OID_ROOT, OID_ROOT},
139                   {"/mnt/hmdfs/%d/cloud", MODE_0711, OID_ROOT, OID_ROOT},
140                   {"/mnt/hmdfs/%d/account", MODE_0711, OID_ROOT, OID_ROOT},
141                   {"/mnt/hmdfs/%d/non_account", MODE_0711, OID_ROOT, OID_ROOT}},
142       systemServiceDir_{{"/data/service/el2/%d/tee", MODE_0711, OID_TEE, OID_TEE},
143                   {"/data/service/el2/%d/deviceauth", MODE_0711, OID_DEVICE_AUTH, OID_DEVICE_AUTH},
144                   {"/data/service/el2/%d/hwid_service", MODE_0711, OID_HWID, OID_HWID},
145                   {"/data/service/el2/%d/huks_service", MODE_0711, OID_HUKS, OID_HUKS},
146                   {"/data/service/el4/%d/huks_service", MODE_0711, OID_HUKS, OID_HUKS},
147                   {"/data/service/el2/%d/asset_service", MODE_0711, OID_ASSET, OID_ASSET},
148                   {"/data/service/el2/%d/account", MODE_0711, OID_ACCOUNT, OID_ACCOUNT},
149                   {"/data/service/el2/%d/parentcontrol", MODE_0711, OID_PARENT_CONTROL, OID_PARENT_CONTROL},
150                   {"/data/service/el2/%d/dlp_credential_service", MODE_0711, OID_DLP_CREDENTIAL, OID_DLP_CREDENTIAL},
151                   {"/data/service/el2/%d/xpower", MODE_0711, OID_HIVIEW, OID_HIVIEW},
152                   {"/data/service/el2/%d/av_session", MODE_0711, OID_AV_SESSION, OID_AV_SESSION}},
153       fileManagerDir_{{"/data/service/el2/%d/hmdfs/account/files/Docs", MODE_02771, OID_FILE_MANAGER, OID_FILE_MANAGER},
154                    {"/data/service/el2/%d/hmdfs/account/files/Docs/Documents",
155                    MODE_02771, OID_FILE_MANAGER, OID_FILE_MANAGER},
156                    {"/data/service/el2/%d/hmdfs/account/files/Docs/Download",
157                    MODE_02771, OID_FILE_MANAGER, OID_FILE_MANAGER},
158                    {"/data/service/el2/%d/hmdfs/account/files/Docs/Desktop",
159                    MODE_02771, OID_FILE_MANAGER, OID_FILE_MANAGER},
160                    {"/data/service/el2/%d/hmdfs/account/files/Docs/.Trash",
161                    MODE_02771, OID_FILE_MANAGER, OID_FILE_MANAGER},
162                    {"/data/service/el2/%d/hmdfs/account/files/.Recent", MODE_02771, OID_FILE_MANAGER, OID_FILE_MANAGER}}
163 {
164 }
165 
GetInstance()166 std::shared_ptr<MountManager> MountManager::GetInstance()
167 {
168     static std::once_flag onceFlag;
169     std::call_once(onceFlag, [&]() { instance_ = std::make_shared<MountManager>(); });
170 
171     return instance_;
172 }
173 
HmdfsTwiceMount(int32_t userId,std::string relativePath)174 int32_t MountManager::HmdfsTwiceMount(int32_t userId, std::string relativePath)
175 {
176     int32_t ret = HmdfsMount(userId, relativePath);
177 
178     // bind mount
179     Utils::MountArgument hmdfsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
180     ret += Mount(hmdfsMntArgs.GetFullDst() + "/device_view/", hmdfsMntArgs.GetCommFullPath(),
181                  nullptr, MS_BIND, nullptr);
182     if (ret != 0 && errno != EEXIST && errno != EBUSY) {
183         LOGE("failed to bind mount device_view, err %{public}d", errno);
184         return E_MOUNT;
185     }
186     ret += Mount(hmdfsMntArgs.GetFullDst() + "/cloud_merge_view/", hmdfsMntArgs.GetCloudFullPath(),
187                  nullptr, MS_BIND, nullptr);
188     if (ret != 0 && errno != EEXIST && errno != EBUSY) {
189         LOGE("failed to bind mount cloud_merge_view, err %{public}d", errno);
190         return E_MOUNT;
191     }
192 
193     if (Mount(hmdfsMntArgs.GetLocalDocsPath(), hmdfsMntArgs.GetCloudDocsPath(),
194               nullptr, MS_BIND, nullptr)) {
195         LOGE("failed to bind mount docs, err %{public}d", errno);
196     }
197     return E_OK;
198 }
199 
SharefsMount(int32_t userId)200 int32_t MountManager::SharefsMount(int32_t userId)
201 {
202     Utils::MountArgument sharefsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, ""));
203     int ret = Mount(sharefsMntArgs.GetShareSrc(), sharefsMntArgs.GetShareDst(), "sharefs",
204                     sharefsMntArgs.GetFlags(), sharefsMntArgs.GetUserIdPara().c_str());
205     if (ret != 0 && errno != EEXIST && errno != EBUSY) {
206         LOGE("failed to mount sharefs, err %{public}d", errno);
207         return E_MOUNT;
208     }
209     return E_OK;
210 }
211 
HmdfsMount(int32_t userId,std::string relativePath,bool mountCloudDisk)212 int32_t MountManager::HmdfsMount(int32_t userId, std::string relativePath, bool mountCloudDisk)
213 {
214     Utils::MountArgument hmdfsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
215     std::string mountSrcPath = hmdfsMntArgs.GetFullSrc();
216     if (mountCloudDisk) {
217         hmdfsMntArgs.enableCloudDisk_ = true;
218         hmdfsMntArgs.useCloudDir_ = false;
219         hmdfsMntArgs.enableMergeView_ = false;
220         mountSrcPath = hmdfsMntArgs.GetFullCloud();
221     }
222 
223     int ret = Mount(mountSrcPath, hmdfsMntArgs.GetFullDst(), "hmdfs",
224                     hmdfsMntArgs.GetFlags(), hmdfsMntArgs.OptionsToString().c_str());
225     if (ret != 0 && errno != EEXIST && errno != EBUSY) {
226         LOGE("failed to mount hmdfs, err %{public}d", errno);
227         return E_MOUNT;
228     }
229 
230     ret = chown(hmdfsMntArgs.GetCtrlPath().c_str(), OID_DFS, OID_SYSTEM);
231     if (ret != 0) {
232         LOGE("failed to chown hmdfs sysfs node, err %{public}d", errno);
233     }
234 
235     return E_OK;
236 }
237 
FindAndKillProcess(int32_t userId,std::list<std::string> & mountFailList)238 int32_t MountManager::FindAndKillProcess(int32_t userId, std::list<std::string> &mountFailList)
239 {
240     if (userId <= 0) {
241         return E_OK;
242     }
243     LOGI("FindAndKillProcess start, userId is %{public}d", userId);
244     auto procDir = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/proc"), closedir);
245     if (!procDir) {
246         LOGE("failed to open dir proc, err %{public}d", errno);
247         return -errno;
248     }
249     std::vector<ProcessInfo> processInfos;
250     struct dirent *entry;
251     while ((entry = readdir(procDir.get())) != nullptr) {
252         if (entry->d_type != DT_DIR) {
253             continue;
254         }
255         std::string name = entry->d_name;
256         if (!StringIsNumber(name)) {
257             continue;
258         }
259         ProcessInfo info;
260         std::string filename = "/proc/" + name + "/stat";
261         if (!GetProcessInfo(filename, info)) {
262             LOGE("failed to get process info, pid is %{public}s.", name.c_str());
263             continue;
264         }
265         if (info.name == "(storage_daemon)") {
266             continue;
267         }
268         Utils::MountArgument argument(Utils::MountArgumentDescriptors::Alpha(userId, ""));
269         const string &prefix = argument.GetMountPointPrefix();
270         std::string pidPath = "/proc/" + name;
271         if (PidUsingFlag(pidPath, prefix, mountFailList)) {
272             LOGE("find a link pid is %{public}d, processName is %{public}s.", info.pid, info.name.c_str());
273             processInfos.push_back(info);
274         }
275     }
276     LOGI("FindAndKillProcess end, total find %{public}d", static_cast<int>(processInfos.size()));
277     KillProcess(processInfos);
278     UmountFailRadar(processInfos);
279     return E_OK;
280 }
281 
UmountFailRadar(std::vector<ProcessInfo> & processInfos)282 void MountManager::UmountFailRadar(std::vector<ProcessInfo> &processInfos)
283 {
284     if (processInfos.empty()) {
285         return;
286     }
287     std::string ss;
288     int32_t ret = E_UMOUNT;
289     for (const auto &item:processInfos) {
290         ss += item.name + ",";
291     }
292     if (StorageService::StorageRadar::GetInstance().RecordKillProcessResult(ss, ret)) {
293         LOGI("StorageRadar record FindAndKillProcess result success, ret = %{public}d, process is %{public}s",
294              ret, ss.c_str());
295     }
296 }
297 
PidUsingFlag(std::string & pidPath,const std::string & prefix,std::list<std::string> & mountFailList)298 bool MountManager::PidUsingFlag(std::string &pidPath, const std::string &prefix, std::list<std::string> &mountFailList)
299 {
300     bool found = false;
301     found |= CheckMaps(pidPath + "/maps", prefix, mountFailList);
302     found |= CheckSymlink(pidPath + "/cwd", prefix, mountFailList);
303     found |= CheckSymlink(pidPath + "/root", prefix, mountFailList);
304     found |= CheckSymlink(pidPath + "/exe", prefix, mountFailList);
305 
306     std::string fdPath = pidPath + "/fd";
307     auto fdDir = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(fdPath.c_str()), closedir);
308     if (!fdDir) {
309         LOGE("unable to open %{public}s, err %{public}d", fdPath.c_str(), errno);
310     } else {
311         struct dirent* fdDirent;
312         while ((fdDirent = readdir(fdDir.get())) != nullptr) {
313             if (fdDirent->d_type != DT_LNK) {
314                 continue;
315             }
316             found |= CheckSymlink(fdPath + "/" +fdDirent->d_name, prefix, mountFailList);
317         }
318     }
319     return found;
320 }
321 
KillProcess(std::vector<ProcessInfo> & processInfo)322 void MountManager::KillProcess(std::vector<ProcessInfo> &processInfo)
323 {
324     if (processInfo.empty()) {
325         return;
326     }
327     for (const auto &item: processInfo) {
328         LOGI("KILL PID %{public}d", item.pid);
329         kill(item.pid, SIGKILL);
330     }
331 }
332 
GetProcessInfo(const std::string & filename,ProcessInfo & info)333 bool MountManager::GetProcessInfo(const std::string &filename, ProcessInfo &info)
334 {
335     if (filename.empty()) {
336         return false;
337     }
338     LOGE("GetProcessInfo path is %{public}s", filename.c_str());
339     std::ifstream inputStream(filename.c_str(), std::ios::in);
340     if (!inputStream.is_open()) {
341         LOGE("unable to open %{public}s, err %{public}d", filename.c_str(), errno);
342         return false;
343     }
344     std::string line;
345     std::getline(inputStream, line);
346     if (line.empty()) {
347         LOGE("line is empty");
348         inputStream.close();
349         return false;
350     }
351     std::stringstream ss(line);
352     std::string pid;
353     ss >> pid;
354     std::string processName;
355     ss >> processName;
356     info.pid = std::stoi(pid);
357     info.name = processName;
358     LOGE("GetProcessInfo pid is %{public}s and name is %{public}s", pid.c_str(), processName.c_str());
359     inputStream.close();
360     return true;
361 }
362 
CheckMaps(const std::string & path,const std::string & prefix,std::list<std::string> & mountFailList)363 bool MountManager::CheckMaps(const std::string &path, const std::string &prefix, std::list<std::string> &mountFailList)
364 {
365     if (path.empty()) {
366         return false;
367     }
368     std::ifstream inputStream(path.c_str(), std::ios::in);
369     if (!inputStream.is_open()) {
370         LOGE("unable to open %{public}s, err %{public}d", path.c_str(), errno);
371         return false;
372     }
373     LOGE("CheckMaps path is %{public}s", path.c_str());
374     std::string tmpLine;
375     while (std::getline(inputStream, tmpLine)) {
376         std::string::size_type pos = tmpLine.find("/");
377         if (pos == std::string::npos) {
378             continue;
379         }
380         tmpLine = tmpLine.substr(pos);
381         if (tmpLine.find(prefix) == 0) {
382             LOGE("find a fd %{public}s", tmpLine.c_str());
383             inputStream.close();
384             return true;
385         }
386         for (const auto &item: mountFailList) {
387             if (tmpLine.find(item) == 0) {
388                 LOGE("find a fd %{public}s", tmpLine.c_str());
389                 inputStream.close();
390                 return true;
391             }
392         }
393     }
394     inputStream.close();
395     return false;
396 }
397 
CheckSymlink(const std::string & path,const std::string & prefix,std::list<std::string> & mountFailList)398 bool MountManager::CheckSymlink(const std::string &path,
399                                 const std::string &prefix, std::list<std::string> &mountFailList)
400 {
401     if (path.empty()) {
402         return false;
403     }
404     char realPath[ONE_KB];
405     int res = readlink(path.c_str(), realPath, sizeof(realPath) - 1);
406     if (res < 0 || res >= ONE_KB) {
407         return false;
408     }
409     realPath[res] = '\0';
410     std::string realPathStr(realPath);
411     if (realPathStr.find(prefix) == 0) {
412         LOGE("find a fd %{public}s", realPathStr.c_str());
413         return true;
414     }
415     for (const auto &item: mountFailList) {
416         if (realPathStr.find(item) == 0) {
417             LOGE("find a fd %{public}s", realPathStr.c_str());
418             return true;
419         }
420     }
421     return false;
422 }
423 
CloudMount(int32_t userId,const string & path)424 int32_t MountManager::CloudMount(int32_t userId, const string& path)
425 {
426     LOGI("cloud mount start");
427 #ifdef DFS_SERVICE
428     int fd = -1;
429     string opt;
430     int ret;
431     if (!cloudReady_) {
432         LOGI("Cloud Service has not started");
433         return E_MOUNT;
434     }
435 
436     fd = open("/dev/fuse", O_RDWR);
437     if (fd < 0) {
438         LOGE("open /dev/fuse fail");
439         return E_MOUNT;
440     }
441     LOGI("open fuse end");
442     opt = StringPrintf("fd=%i,"
443         "rootmode=40000,"
444         "default_permissions,"
445         "allow_other,"
446         "user_id=0,group_id=0,"
447         "context=\"u:object_r:hmdfs:s0\","
448         "fscontext=u:object_r:hmdfs:s0",
449         fd);
450     LOGI("start to mount fuse");
451     ret = Mount("/dev/fuse", path.c_str(), "fuse", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opt.c_str());
452     if (ret) {
453         LOGE("failed to mount fuse, err %{public}d %{public}d %{public}s", errno, ret, path.c_str());
454         close(fd);
455         return ret;
456     }
457     LOGI("start cloud daemon fuse");
458     ret = CloudDaemonManager::GetInstance().StartFuse(userId, fd, path);
459     if (ret) {
460         LOGE("failed to connect fuse, err %{public}d %{public}d %{public}s", errno, ret, path.c_str());
461         UMount(path.c_str());
462     }
463     LOGI("mount %{public}s success", path.c_str());
464     close(fd);
465     return ret;
466 #else
467     return E_OK;
468 #endif
469 }
470 
CloudTwiceMount(int32_t userId)471 int32_t MountManager::CloudTwiceMount(int32_t userId)
472 {
473     LOGI("mount cloud twice start");
474 #ifdef DFS_SERVICE
475     Utils::MountArgument cloudMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, ""));
476     const string cloudPath = cloudMntArgs.GetFullCloud();
477     const string cloudMediaPath = cloudMntArgs.GetFullMediaCloud();
478     return (CloudMount(userId, cloudPath) | CloudMount(userId, cloudMediaPath));
479 #else
480     return E_OK;
481 #endif
482 }
483 
HmdfsMount(int32_t userId)484 int32_t MountManager::HmdfsMount(int32_t userId)
485 {
486     int32_t err = PrepareHmdfsDirs(userId);
487     if (err != E_OK) {
488         LOGE("Prepare fileManager dir error");
489     }
490 
491     int32_t ret = HmdfsTwiceMount(userId, "account");
492 
493     ret += HmdfsMount(userId, "non_account");
494     if (ret != E_OK) {
495         return E_MOUNT;
496     }
497 
498     LOGI("ready to mount cloud");
499     mountMutex_.lock();
500     ret = CloudTwiceMount(userId);
501     if (ret == E_OK) {
502         fuseMountedUsers_.push_back(userId);
503     } else {
504         fuseToMountUsers_.push_back(userId);
505     }
506     mountMutex_.unlock();
507 
508     ret = HmdfsMount(userId, "cloud", true);
509     if (ret != E_OK) {
510         LOGE("mount cloud to hmdfs failed!");
511     }
512 
513     return E_OK;
514 }
515 
ParseSandboxPath(string & path,const string & userId,const string & bundleName)516 static void ParseSandboxPath(string &path, const string &userId, const string &bundleName)
517 {
518     size_t pos = path.find(CURRENT_USER_ID_FLAG);
519     if (pos != string::npos) {
520         path = path.replace(pos, CURRENT_USER_ID_FLAG.length(), userId);
521     }
522 
523     pos = path.find(PACKAGE_NAME_FLAG);
524     if (pos != string::npos) {
525         path = path.replace(pos, PACKAGE_NAME_FLAG.length(), bundleName);
526     }
527 }
528 
CheckPathValid(const std::string & bundleNameStr,uint32_t userId)529 bool MountManager::CheckPathValid(const std::string &bundleNameStr, uint32_t userId)
530 {
531     string completePath =
532         SANDBOX_ROOT_PATH + to_string(userId) + "/" + bundleNameStr + EL2_BASE;
533     if (!IsDir(completePath)) {
534         LOGE("Invalid directory path: %{public}s", completePath.c_str());
535         return false;
536     }
537 
538     if (!std::filesystem::is_empty(completePath)) {
539         LOGE("The directory has been mounted, path is %{public}s", completePath.c_str());
540         return false;
541     }
542     return true;
543 }
544 
MountCryptoPathAgain(uint32_t userId)545 int32_t MountManager::MountCryptoPathAgain(uint32_t userId)
546 {
547     filesystem::path rootDir(SANDBOX_ROOT_PATH + to_string(userId));
548     std::error_code errCode;
549     if (!exists(rootDir, errCode)) {
550         LOGE("root path not exists, rootDir is %{public}s", SANDBOX_ROOT_PATH.c_str());
551         return -ENOENT;
552     }
553 
554     int32_t ret = 0;
555     filesystem::directory_iterator bundleNameList(rootDir);
556     for (const auto &bundleName : bundleNameList) {
557         if (SANDBOX_EXCLUDE_PATH.find(bundleName.path().filename()) != SANDBOX_EXCLUDE_PATH.end()) {
558             continue;
559         }
560         std::string bundleNameStr = bundleName.path().filename().generic_string();
561         std::string::size_type point = bundleNameStr.find(MOUNT_SUFFIX);
562         if (point == std::string::npos) {
563             LOGI("bundleName do not need to mount: %{public}s", bundleNameStr.c_str());
564             continue;
565         }
566         bundleNameStr = bundleNameStr.substr(0, point);
567         if (!CheckPathValid(bundleNameStr, userId)) {
568             continue;
569         }
570         vector<string> dstPaths = CRYPTO_SANDBOX_PATH;
571         vector<string> srcPaths = CRYPTO_SRC_PATH;
572         if (bundleNameStr == SCENE_BOARD_BUNDLE_NAME) {
573             dstPaths.push_back(PUBLIC_DIR_SANDBOX_PATH);
574             srcPaths.push_back(PUBLIC_DIR_SRC_PATH);
575         }
576         MountSandboxPath(srcPaths, dstPaths, bundleNameStr, to_string(userId));
577     }
578     LOGI("mount crypto path success, userId is %{public}d", userId);
579     return ret;
580 }
581 
MountSandboxPath(const std::vector<std::string> & srcPaths,const std::vector<std::string> & dstPaths,const std::string & bundleName,const std::string & userId)582 void MountManager::MountSandboxPath(const std::vector<std::string> &srcPaths, const std::vector<std::string> &dstPaths,
583     const std::string &bundleName, const std::string &userId)
584 {
585     int srcCnt = static_cast<int>(srcPaths.size());
586     int dstCnt = static_cast<int>(dstPaths.size());
587     if (srcCnt == 0 || dstCnt == 0 || srcCnt != dstCnt) {
588         LOGE("invalid params, srcPaths total %{public}d, dstPaths total %{public}d", srcCnt, dstCnt);
589         return;
590     }
591     for (int i = 0; i < dstCnt; i++) {
592         std::string dstPath = SANDBOX_ROOT_PATH;
593         dstPath = dstPath.append(userId).append("/").append(bundleName).append(dstPaths[i]);
594         string srcPath = srcPaths[i];
595         ParseSandboxPath(srcPath, userId, bundleName);
596         if (!IsDir(dstPath)) {
597             LOGE("dstPath is not a dir: %{public}s", dstPath.c_str());
598             continue;
599         }
600         if (!IsDir(srcPath)) {
601             LOGE("srcPath is not a dir: %{public}s", srcPath.c_str());
602             continue;
603         }
604         LOGD("mount crypto path, srcPath is %{public}s, dstPath is %{public}s", srcPath.c_str(), dstPath.c_str());
605         int32_t ret = mount(srcPath.c_str(), dstPath.c_str(), nullptr, MS_BIND | MS_REC, nullptr);
606         if (ret != E_OK && errno == EBUSY) {
607             ret = mount(srcPath.c_str(), dstPath.c_str(), nullptr, MS_BIND | MS_REC, nullptr);
608             LOGI("mount again dstPath is %{public}s, ret is %{public}d.", dstPath.c_str(), ret);
609         }
610         if (ret != 0) {
611             LOGE("mount bind failed, srcPath is %{public}s dstPath is %{public}s errno is %{public}d",
612                  srcPath.c_str(), dstPath.c_str(), errno);
613             continue;
614         }
615         LOGI("bind mount path, srcPath is %{public}s, dstPath is %{public}s", srcPath.c_str(), dstPath.c_str());
616         ret = mount(nullptr, dstPath.c_str(), nullptr, MS_SHARED, nullptr);
617         if (ret != 0) {
618             LOGE("mount to share failed, srcPath is %{public}s dstPath is %{public}s errno is %{public}d",
619                  srcPath.c_str(), dstPath.c_str(), errno);
620             continue;
621         }
622         LOGI("shared mount success, dstPath is %{public}s", dstPath.c_str());
623     }
624 }
625 
MountPointToList(std::list<std::string> & hmdfsList,std::list<std::string> & hmfsList,std::list<std::string> & sharefsList,std::string & line,int32_t userId)626 void MountManager::MountPointToList(std::list<std::string> &hmdfsList, std::list<std::string> &hmfsList,
627     std::list<std::string> &sharefsList, std::string &line, int32_t userId)
628 {
629     if (line.empty()) {
630         return;
631     }
632     Utils::MountArgument hmdfsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, ""));
633     const string &hmdfsPrefix = hmdfsMntArgs.GetMountPointPrefix();
634     const string &hmfsPrefix = hmdfsMntArgs.GetSandboxPath();
635     const string &sharefsPrefix = hmdfsMntArgs.GetShareSrc();
636     const string &cloudPrefix = hmdfsMntArgs.GetFullCloud();
637     std::stringstream ss(line);
638     std::string src;
639     ss >> src;
640     std::string dst;
641     ss >> dst;
642     std::string type;
643     ss >> type;
644     if (type == MOUNT_POINT_TYPE_HMDFS) {
645         if (src.length() >= hmdfsPrefix.length() && src.substr(0, hmdfsPrefix.length()) == hmdfsPrefix) {
646             hmdfsList.push_front(dst);
647         }
648         if (src.length() >= cloudPrefix.length() && src.substr(0, cloudPrefix.length()) == cloudPrefix) {
649             hmdfsList.push_front(dst);
650         }
651         return;
652     }
653     if (type == MOUNT_POINT_TYPE_HMFS) {
654         if (dst.length() >= hmfsPrefix.length() && dst.substr(0, hmfsPrefix.length()) == hmfsPrefix) {
655             hmfsList.push_front(dst);
656         }
657         return;
658     }
659     if (type == MOUNT_POINT_TYPE_SHAREFS) {
660         if (src.length() >= sharefsPrefix.length() &&
661             src.substr(0, sharefsPrefix.length()) == sharefsPrefix) {
662             sharefsList.push_front(dst);
663         }
664         return;
665     }
666 }
667 
FindMountPointsToMap(std::map<std::string,std::list<std::string>> & mountMap,int32_t userId)668 int32_t MountManager::FindMountPointsToMap(std::map<std::string, std::list<std::string>> &mountMap, int32_t userId)
669 {
670     std::ifstream inputStream(MOUNT_POINT_INFO.c_str(), std::ios::in);
671     if (!inputStream.is_open()) {
672         LOGE("unable to open /proc/mounts, errno is %{public}d", errno);
673         return -errno;
674     }
675     std::list<std::string> hmdfsList;
676     std::list<std::string> hmfsList;
677     std::list<std::string> sharefsList;
678     std::string tmpLine;
679     while (std::getline(inputStream, tmpLine)) {
680         MountPointToList(hmdfsList, hmfsList, sharefsList, tmpLine, userId);
681     }
682     inputStream.close();
683     mountMap[MOUNT_POINT_TYPE_HMDFS] = hmdfsList;
684     mountMap[MOUNT_POINT_TYPE_HMFS] = hmfsList;
685     mountMap[MOUNT_POINT_TYPE_SHAREFS] = sharefsList;
686     hmdfsList.clear();
687     hmfsList.clear();
688     sharefsList.clear();
689     return E_OK;
690 }
691 
UMountAllPath(int32_t userId,std::list<std::string> & mountFailList)692 int32_t MountManager::UMountAllPath(int32_t userId, std::list<std::string> &mountFailList)
693 {
694     std::map<std::string, std::list<std::string>> mountMap;
695     int32_t res = FindMountPointsToMap(mountMap, userId);
696     if (res != E_OK) {
697         return res;
698     }
699     int32_t result = 0;
700     std::list<std::string> list = mountMap[MOUNT_POINT_TYPE_SHAREFS];
701     int total = static_cast<int>(list.size());
702     LOGI("unmount sharefs path start, total %{public}d.", total);
703     res = UMountByList(list, mountFailList);
704     if (res != E_OK) {
705         result = res;
706     }
707 
708     list = mountMap[MOUNT_POINT_TYPE_HMDFS];
709     total = static_cast<int>(list.size());
710     LOGI("unmount hmdfs path start, total %{public}d.", total);
711     res = UMountByList(list, mountFailList);
712     if (res != E_OK) {
713         result = res;
714     }
715     LOGI("result is %{public}d.", result);
716     list = mountMap[MOUNT_POINT_TYPE_HMFS];
717     total = static_cast<int>(list.size());
718     LOGI("unmount hmfs path start, total %{public}d.", total);
719     res = UMountByList(list, mountFailList);
720     if (res != E_OK) {
721         result = res;
722     }
723     if (result != E_OK) {
724         for (const auto &item: mountFailList) {
725             res = UMount2(item.c_str(), MNT_DETACH);
726             if (res != E_OK) {
727                 LOGE("failed to unmount with detach, path %{public}s, errno %{public}d.", item.c_str(), errno);
728             }
729         }
730         return result;
731     }
732     LOGI("UMountAllPath success");
733     return E_OK;
734 }
735 
UMountByList(std::list<std::string> & list,std::list<std::string> & mountFailList)736 int32_t MountManager::UMountByList(std::list<std::string> &list, std::list<std::string> &mountFailList)
737 {
738     if (list.empty()) {
739         return E_OK;
740     }
741     int32_t result = E_OK;
742     for (const std::string &path: list) {
743         LOGD("umount path %{public}s.", path.c_str());
744         int32_t res = UMount(path);
745         if (res != E_OK) {
746             LOGE("failed to unmount path %{public}s, errno %{public}d.", path.c_str(), errno);
747             result = errno;
748             mountFailList.push_back(path);
749         }
750     }
751     LOGI("UMountByList result is %{public}d.", result);
752     return result;
753 }
754 
MountCloudForUsers(void)755 void MountManager::MountCloudForUsers(void)
756 {
757     for (auto it = fuseToMountUsers_.begin(); it != fuseToMountUsers_.end();) {
758         int32_t res = CloudTwiceMount(*it);
759         if (res == E_OK) {
760             fuseMountedUsers_.push_back(*it);
761             it = fuseToMountUsers_.erase(it);
762         } else {
763             it++;
764         }
765     }
766 }
767 
UMountCloudForUsers(void)768 void MountManager::UMountCloudForUsers(void)
769 {
770     for (auto it = fuseMountedUsers_.begin(); it != fuseMountedUsers_.end();) {
771         int32_t res = CloudUMount(*it);
772         if (res == E_OK) {
773             fuseToMountUsers_.push_back(*it);
774             it = fuseMountedUsers_.erase(it);
775         } else {
776             it++;
777         }
778     }
779 }
780 
SetCloudState(bool active)781 void MountManager::SetCloudState(bool active)
782 {
783     LOGI("set cloud state start, active is %{public}d", active);
784     mountMutex_.lock();
785     cloudReady_ = active;
786     if (cloudReady_) {
787         MountCloudForUsers();
788     } else {
789         UMountCloudForUsers();
790     }
791     mountMutex_.unlock();
792     LOGI("set cloud state end");
793 }
794 
HmdfsUMount(int32_t userId,std::string relativePath)795 int32_t MountManager::HmdfsUMount(int32_t userId, std::string relativePath)
796 {
797     Utils::MountArgument hmdfsAuthMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
798     int32_t ret = UMount2(hmdfsAuthMntArgs.GetFullDst().c_str(), MNT_DETACH);
799     if (ret != E_OK) {
800         LOGE("umount auth hmdfs, errno %{public}d, auth hmdfs dst %{public}s", errno,
801              hmdfsAuthMntArgs.GetFullDst().c_str());
802         return E_UMOUNT;
803     }
804     return E_OK;
805 }
806 
CloudUMount(int32_t userId)807 int32_t MountManager::CloudUMount(int32_t userId)
808 {
809 #ifdef DFS_SERVICE
810     int32_t err = E_OK;
811     Utils::MountArgument cloudMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, ""));
812     const string path = cloudMntArgs.GetFullCloud();
813     const string mediaCloudPath = cloudMntArgs.GetFullMediaCloud();
814 
815     HmdfsUMount(userId, "cloud");
816 
817     err = UMount2(path, MNT_DETACH);
818     if (err != E_OK) {
819         LOGE("fuse umount2 failed, errno %{public}d, fuse dst %{public}s", errno, path.c_str());
820         return E_UMOUNT;
821     }
822 
823     err = UMount2(mediaCloudPath, MNT_DETACH);
824     if (err != E_OK) {
825         LOGE("fuse umount2 failed, errno %{public}d, fuse dst %{public}s", errno, mediaCloudPath.c_str());
826         return E_UMOUNT;
827     }
828     LOGI("umount2 media cloud path:%{public}s  cloud path:%{public}s success", mediaCloudPath.c_str(), path.c_str());
829     return E_OK;
830 #else
831     return E_OK;
832 #endif
833 }
834 
SupportHmdfs()835 bool MountManager::SupportHmdfs()
836 {
837     char hmdfsEnable[HMDFS_VAL_LEN + 1] = {"false"};
838     int ret = GetParameter(HMDFS_SYS_CAP.c_str(), "", hmdfsEnable, HMDFS_VAL_LEN);
839     LOGI("GetParameter hmdfsEnable %{public}s, ret %{public}d", hmdfsEnable, ret);
840     if (strncmp(hmdfsEnable, "true", HMDFS_TRUE_LEN) == 0) {
841         return true;
842     }
843     return false;
844 }
845 
LocalMount(int32_t userId)846 int32_t MountManager::LocalMount(int32_t userId)
847 {
848     Utils::MountArgument LocalMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, "account"));
849     if (Mount(LocalMntArgs.GetFullSrc(), LocalMntArgs.GetCommFullPath() + "local/",
850               nullptr, MS_BIND, nullptr)) {
851         LOGE("failed to bind mount, err %{public}d", errno);
852         return E_MOUNT;
853     }
854     if (Mount(LocalMntArgs.GetFullSrc(), LocalMntArgs.GetCloudFullPath(),
855               nullptr, MS_BIND, nullptr)) {
856         LOGE("failed to bind mount, err %{public}d", errno);
857         return E_MOUNT;
858     }
859     return E_OK;
860 }
861 
RmExistDir(const std::string & dirPath)862 static void RmExistDir(const std::string &dirPath)
863 {
864     if (access(dirPath.c_str(), 0) == 0) {
865         if (!RmDirRecurse(dirPath)) {
866             LOGE("Failed to remove dir %{public}s", dirPath.c_str());
867         }
868     }
869 }
870 
ClearRedundantResources(int32_t userId)871 static void ClearRedundantResources(int32_t userId)
872 {
873     std::string sharePath = StringPrintf("/data/service/el2/%d/share", userId);
874     filesystem::path rootDir(sharePath);
875     std::error_code errCode;
876     if (!exists(rootDir, errCode)) {
877         LOGE("Bundles share path not exists, rootDir is %{public}s", sharePath.c_str());
878         return;
879     }
880 
881     filesystem::directory_iterator bundleNameList(rootDir);
882     for (const auto &bundleName : bundleNameList) {
883         RmExistDir(bundleName.path().generic_string() + "/r");
884         RmExistDir(bundleName.path().generic_string() + "/rw");
885     }
886 }
887 
MountByUser(int32_t userId)888 int32_t MountManager::MountByUser(int32_t userId)
889 {
890     int ret = E_OK;
891     // The Documnets and Download directories are managed by the File access framework,
892     // and the UID GID is changed to filemanager
893     std::thread thread([userId]() { ClearRedundantResources(userId); });
894     thread.detach();
895     PrepareFileManagerDir(userId);
896     if (CreateVirtualDirs(userId) != E_OK) {
897         LOGE("create hmdfs virtual dir error");
898         return E_PREPARE_DIR;
899     }
900 
901     if (!SupportHmdfs()) {
902         ret = LocalMount(userId);
903     } else {
904         ret = HmdfsMount(userId);
905     }
906 
907     if (ret != E_OK) {
908         LOGE("hmdfs mount error");
909         return ret;
910     }
911 
912     ret = SharefsMount(userId);
913     if (ret != E_OK) {
914         LOGE("sharefs mount error");
915     }
916     SetFafQuotaProId(userId);
917 
918     if (CreateSystemServiceDirs(userId) != E_OK) {
919         LOGE("create system service dir error");
920         return E_PREPARE_DIR;
921     }
922     return E_OK;
923 }
924 
GetFileManagerUid(uid_t uid,int32_t userId)925 static uid_t GetFileManagerUid(uid_t uid, int32_t userId)
926 {
927     return USER_ID_BASE * userId + uid;
928 }
929 
PrepareFileManagerDir(int32_t userId)930 void MountManager::PrepareFileManagerDir(int32_t userId)
931 {
932     std::string filesPath = StringPrintf("/data/service/el2/%d/hmdfs/account/files/", userId);
933     // move file manager dir
934     MoveFileManagerData(filesPath);
935     for (const DirInfo &dir : fileManagerDir_) {
936         uid_t dirUid = GetFileManagerUid(dir.uid, userId);
937         std::string path = StringPrintf(dir.path.c_str(), userId);
938         int ret = IsSameGidUid(path, dirUid, dir.gid);
939         LOGD("prepareDir %{public}s ret %{public}d, dirUid: %{public}d", path.c_str(), ret, dirUid);
940         // Dir exist and same uid, gid
941         if (ret == E_OK) {
942             continue;
943         }
944         // system error
945         if (ret == E_SYS_ERR) {
946             LOGE("system err %{public}s ", path.c_str());
947             continue;
948         }
949         // Dir exist and different uid, gid
950         if (ret == E_DIFF_UID_GID) {
951             ChownRecursion(path, dirUid, OID_FILE_MANAGER);
952             continue;
953         }
954         // Dir not exist
955         if (ret == E_NON_EXIST && !PrepareDir(path, dir.mode, dirUid, dir.gid)) {
956             LOGE("failed to prepareDir %{public}s ", path.c_str());
957         }
958     }
959 }
960 
LocalUMount(int32_t userId)961 int32_t MountManager::LocalUMount(int32_t userId)
962 {
963     Utils::MountArgument LocalMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, "account"));
964     int err = UMount(LocalMntArgs.GetCommFullPath() + "local/");
965     if (err != E_OK) {
966         LOGE("failed to un bind mount, errno %{public}d, ComDataDir dst %{public}s", errno,
967              LocalMntArgs.GetCommFullPath().c_str());
968     }
969     err = UMount(LocalMntArgs.GetCloudFullPath());
970     if (err != E_OK) {
971         LOGE("failed to un bind mount, errno %{public}d, CloudDataDir dst %{public}s", errno,
972              LocalMntArgs.GetCloudFullPath().c_str());
973     }
974     return err;
975 }
976 
UmountByUser(int32_t userId)977 int32_t MountManager::UmountByUser(int32_t userId)
978 {
979     LOGI("umount hmdfs mount point start.");
980     int32_t err = E_OK;
981     if (!SupportHmdfs()) {
982         err = LocalUMount(userId);
983     } else {
984         std::list<std::string> mountFailList;
985         err = UMountAllPath(userId, mountFailList);
986         if (err != E_OK) {
987             LOGE("failed to umount hmdfs mount point, err is %{public}d", err);
988             FindAndKillProcess(userId, mountFailList);
989         }
990     }
991 
992     LOGI("umount cloud mount point start.");
993     int32_t count = 0;
994     while (count < UMOUNT_RETRY_TIMES) {
995         err = CloudUMount(userId);
996         if (err == E_OK) {
997             break;
998         } else if (errno == EBUSY) {
999             count++;
1000             continue;
1001         }
1002         LOGE("failed to umount cloud mount point, err %{public}d", err);
1003         return E_UMOUNT;
1004     }
1005     return E_OK;
1006 }
1007 
PrepareHmdfsDirs(int32_t userId)1008 int32_t MountManager::PrepareHmdfsDirs(int32_t userId)
1009 {
1010     for (const DirInfo &dir : hmdfsDirVec_) {
1011         if (!PrepareDir(StringPrintf(dir.path.c_str(), userId), dir.mode, dir.uid, dir.gid)) {
1012             return E_PREPARE_DIR;
1013         }
1014     }
1015 
1016     return E_OK;
1017 }
1018 
PrepareFileManagerDirs(int32_t userId)1019 int32_t MountManager::PrepareFileManagerDirs(int32_t userId)
1020 {
1021     for (const DirInfo &dir : fileManagerDir_) {
1022         uid_t dirUid = GetFileManagerUid(dir.uid, userId);
1023         if (!PrepareDir(StringPrintf(dir.path.c_str(), userId), dir.mode, dirUid, dir.gid)) {
1024             return E_PREPARE_DIR;
1025         }
1026     }
1027 
1028     return E_OK;
1029 }
1030 
CreateVirtualDirs(int32_t userId)1031 int32_t MountManager::CreateVirtualDirs(int32_t userId)
1032 {
1033     for (const DirInfo &dir : virtualDir_) {
1034         if (!PrepareDir(StringPrintf(dir.path.c_str(), userId), dir.mode, dir.uid, dir.gid)) {
1035             return E_PREPARE_DIR;
1036         }
1037     }
1038 
1039     return E_OK;
1040 }
1041 
MountDfsDocs(int32_t userId,const std::string & relativePath,const std::string & networkId,const std::string & deviceId)1042 int32_t MountManager::MountDfsDocs(int32_t userId, const std::string &relativePath,
1043     const std::string &networkId, const std::string &deviceId)
1044 {
1045     LOGI("MountManager::MountDfsDocs start.");
1046     std::string dstPath = StringPrintf("/mnt/data/%d/hmdfs/%s/", userId, deviceId.c_str());
1047     if (!PrepareDir(dstPath, MODE_0711, OID_FILE_MANAGER, OID_FILE_MANAGER)) {
1048         return E_PREPARE_DIR;
1049     }
1050 
1051     std::regex pathRegex("^[a-zA-Z0-9_/]+$");
1052     if (relativePath.empty() || relativePath.length() > PATH_MAX || !std::regex_match(relativePath, pathRegex)) {
1053         LOGE("[MountDfsDocs]invalid relativePath");
1054         return E_MOUNT;
1055     }
1056 
1057     Utils::MountArgument hmdfsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
1058     std::string srcPath = hmdfsMntArgs.GetFullDst() + "/device_view/" + networkId + "/files/Docs/";
1059     int32_t ret = Mount(srcPath, dstPath, nullptr, MS_BIND, nullptr);
1060     if (ret != 0 && errno != EEXIST && errno != EBUSY) {
1061         LOGE("MountDfsDocs mount bind failed, srcPath is %{public}s dstPath is %{public}s errno is %{public}d",
1062             srcPath.c_str(), dstPath.c_str(), errno);
1063         return E_MOUNT;
1064     }
1065     return E_OK;
1066 }
1067 
UMountDfsDocs(int32_t userId,const std::string & relativePath,const std::string & networkId,const std::string & deviceId)1068 int32_t MountManager::UMountDfsDocs(int32_t userId, const std::string &relativePath,
1069     const std::string &networkId, const std::string &deviceId)
1070 {
1071     LOGI("MountManager::UMountDfsDocs start.");
1072 
1073     std::regex pathRegex("^[a-zA-Z0-9_/]+$");
1074     if (relativePath.empty() || relativePath.length() > PATH_MAX || !std::regex_match(relativePath, pathRegex)) {
1075         LOGE("[UMountDfsDocs]invalid relativePath");
1076         return E_UMOUNT;
1077     }
1078 
1079     std::string dstPath = StringPrintf("/mnt/data/%d/hmdfs/%s", userId, deviceId.c_str());
1080     sync();
1081     int32_t ret = UMount2(dstPath, MNT_FORCE);
1082     if (ret != E_OK) {
1083         LOGE("UMountDfsDocs unmount bind failed, srcPath is %{public}s errno is %{public}d",
1084              dstPath.c_str(), errno);
1085         return E_UMOUNT;
1086     }
1087     LOGI("MountManager::UMountDfsDocs end.");
1088     if (!filesystem::is_empty(dstPath)) {
1089         LOGE("[UMountDfsDocs] Failed to umount");
1090         return E_UMOUNT;
1091     }
1092     if (!RmDirRecurse(dstPath)) {
1093         LOGE("Failed to remove dir %{public}s", dstPath.c_str());
1094     }
1095     return E_OK;
1096 }
1097 
RestoreconSystemServiceDirs(int32_t userId)1098 int32_t MountManager::RestoreconSystemServiceDirs(int32_t userId)
1099 {
1100     int32_t err = E_OK;
1101 #ifdef USE_LIBRESTORECON
1102     for (const DirInfo &dir : systemServiceDir_) {
1103         std::string path = StringPrintf(dir.path.c_str(), userId);
1104         RestoreconRecurse(path.c_str());
1105         LOGD("systemServiceDir_ RestoreconRecurse path is %{public}s ", path.c_str());
1106     }
1107 #endif
1108     return err;
1109 }
1110 
CreateSystemServiceDirs(int32_t userId)1111 int32_t MountManager::CreateSystemServiceDirs(int32_t userId)
1112 {
1113     int32_t err = E_OK;
1114     for (const DirInfo &dir : systemServiceDir_) {
1115         std::string path = StringPrintf(dir.path.c_str(), userId);
1116         if (!PrepareDir(path, dir.mode, dir.uid, dir.gid)) {
1117             LOGE("failed to prepareDir %{public}s ", path.c_str());
1118             err = E_PREPARE_DIR;
1119         }
1120     }
1121     return err;
1122 }
1123 
DestroySystemServiceDirs(int32_t userId)1124 int32_t MountManager::DestroySystemServiceDirs(int32_t userId)
1125 {
1126     bool err = true;
1127     for (const DirInfo &dir : systemServiceDir_) {
1128         std::string path = StringPrintf(dir.path.c_str(), userId);
1129         err = err && RmDirRecurse(path);
1130     }
1131     return err ? E_OK : E_DESTROY_DIR;
1132 }
1133 
DestroyHmdfsDirs(int32_t userId)1134 int32_t MountManager::DestroyHmdfsDirs(int32_t userId)
1135 {
1136     bool err = true;
1137 
1138     for (const DirInfo &dir : hmdfsDirVec_) {
1139         if (IsEndWith(dir.path.c_str(), "%d")) {
1140             err = err && RmDirRecurse(StringPrintf(dir.path.c_str(), userId));
1141         }
1142     }
1143 
1144     return err ? E_OK : E_DESTROY_DIR;
1145 }
1146 
1147 
DestroyFileManagerDirs(int32_t userId)1148 int32_t MountManager::DestroyFileManagerDirs(int32_t userId)
1149 {
1150     bool err = true;
1151 
1152     for (const DirInfo &dir : fileManagerDir_) {
1153         if (IsEndWith(dir.path.c_str(), "%d")) {
1154             err = err && RmDirRecurse(StringPrintf(dir.path.c_str(), userId));
1155         }
1156     }
1157 
1158     return err ? E_OK : E_DESTROY_DIR;
1159 }
1160 
SetFafQuotaProId(int32_t userId)1161 int32_t MountManager::SetFafQuotaProId(int32_t userId)
1162 {
1163     int32_t prjId = 0;
1164     for (const DirInfo &dir: fileManagerDir_) {
1165         QuotaManager::GetInstance()->SetQuotaPrjId(StringPrintf(dir.path.c_str(), userId), prjId, true);
1166     }
1167     QuotaManager::GetInstance()->SetQuotaPrjId(StringPrintf(SHARE_PATH.c_str(), userId), prjId, true);
1168     return E_OK;
1169 }
1170 
CheckMountFileByUser(int32_t userId)1171 bool MountManager::CheckMountFileByUser(int32_t userId)
1172 {
1173     for (const DirInfo &dir : virtualDir_) {
1174         std::string path = StringPrintf(dir.path.c_str(), userId);
1175         if (CloudDirFlag(path)) {
1176             continue;
1177         }
1178         if (access(path.c_str(), 0) != 0) {
1179             LOGI("VirtualDir : %{public}s is not exists", path.c_str());
1180             return false;
1181         }
1182     }
1183     LOGI("MountFile is exists");
1184     return true;
1185 }
1186 
CloudDirFlag(const std::string & path)1187 bool MountManager::CloudDirFlag(const std::string &path)
1188 {
1189     if (path.empty()) {
1190         return true;
1191     }
1192     std::regex cloudPattern("\\/mnt\\/data.*cloud");
1193     if (std::regex_match(path.c_str(), cloudPattern)) {
1194         return true;
1195     }
1196     std::regex cloudFusePattern("\\/mnt\\/data.*cloud_fuse");
1197     if (std::regex_match(path.c_str(), cloudFusePattern)) {
1198         return true;
1199     }
1200     return false;
1201 }
1202 } // namespace StorageDaemon
1203 } // namespace OHOS
1204