• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 
18 #include <unistd.h>
19 
20 #include "parameter.h"
21 #include "utils/mount_argument_utils.h"
22 #include "utils/storage_radar.h"
23 #include "storage_service_constant.h"
24 #include "storage_service_errno.h"
25 #include "storage_service_log.h"
26 
27 namespace OHOS {
28 namespace StorageDaemon {
29 using namespace std;
30 using namespace OHOS::StorageService;
31 const string PROC_MOUNTS = "/proc/mounts";
32 static constexpr int SHARE_FILE_0771 = 0771;
33 constexpr int32_t PATH_MAX_FOR_LINK = 4096;
34 
CheckSymlinkForMulti(const std::string & fdPath,const std::string & path,std::set<std::string> & occupyFiles)35 void MountManager::CheckSymlinkForMulti(const std::string &fdPath, const std::string &path,
36     std::set<std::string> &occupyFiles)
37 {
38     char realPath[PATH_MAX_FOR_LINK];
39     int res = readlink(fdPath.c_str(), realPath, sizeof(realPath) - 1);
40     if (res < 0) {
41         LOGE("readlink failed for multi, errno is %{public}d.", errno);
42         return;
43     }
44     realPath[res] = '\0';
45     std::string realPathStr(realPath);
46     if (realPathStr.find(UN_REACHABLE) == 0) {
47         realPathStr = realPathStr.substr(UN_REACHABLE.size()) + FILE_SEPARATOR_CHAR;
48     }
49     if (realPathStr.find(path) == 0) {
50         LOGE("find a fd from link, %{public}s", realPathStr.c_str());
51         realPathStr = realPathStr.substr(path.size());
52         if (realPathStr.empty()) {
53             return;
54         }
55         if (path == FILE_MGR_ROOT_PATH) {
56             occupyFiles.insert(realPathStr);
57             return;
58         }
59         std::string::size_type point = realPathStr.find(FILE_SEPARATOR_CHAR);
60         if (point != std::string::npos) {
61             realPathStr = realPathStr.substr(0, point);
62         }
63         occupyFiles.insert(realPathStr);
64     }
65 }
66 
MountDisShareFile(int32_t userId,const std::map<std::string,std::string> & shareFiles)67 int32_t MountManager::MountDisShareFile(int32_t userId, const std::map<std::string, std::string> &shareFiles)
68 {
69     LOGI("mount share file start.");
70     std::map<std::string, std::string> notMountPaths = shareFiles;
71     FilterNotMountedPath(notMountPaths);
72     for (const auto &item: notMountPaths) {
73         std::string dstPath = item.first;
74         std::string srcPath = item.second;
75         if (!IsDir(srcPath)) {
76             LOGE("mount share file, src path invalid, errno is %{public}d", errno);
77             return E_NON_EXIST;
78         }
79         if (!IsDir(dstPath) && !MkDirRecurse(dstPath, SHARE_FILE_0771)) {
80             LOGE("mount share file, dst path mkdir failed, errno is %{public}d", errno);
81             return E_NON_EXIST;
82         }
83         int32_t ret = Mount(srcPath, dstPath, nullptr, MS_BIND, nullptr);
84         if (ret != 0) {
85             LOGE("mount share file failed, errno is %{public}d", errno);
86             std::string extraData = "src=" + srcPath + ",dst=" + dstPath + ",kernelCode=" + to_string(errno);
87             StorageRadar::ReportUserManager("MountDisShareFile", userId, E_MOUNT_SHARE_FILE, extraData);
88             return E_MOUNT_SHARE_FILE;
89         }
90     }
91     LOGI("mount share file success.");
92     return E_OK;
93 }
94 
UMountDisShareFile(int32_t userId,const std::string & networkId)95 int32_t MountManager::UMountDisShareFile(int32_t userId, const std::string &networkId)
96 {
97     LOGI("umount share file, userId is %{public}d, networkId is %{private}s.", userId, networkId.c_str());
98     std::list<std::string> mounts;
99     FindMountsByNetworkId(networkId, mounts);
100     for (const std::string &item: mounts) {
101         int32_t ret = UMount2(item, MNT_DETACH);
102         if (ret != E_OK && errno != ENOENT && errno != EINVAL) {
103             LOGE("umount share file failed, errno is %{public}d.", errno);
104             std::string extraData = "networkId=" + networkId + ",kernelCode=" + to_string(errno);
105             StorageRadar::ReportUserManager("UMountDisShareFile", userId, E_UMOUNT_SHARE_FILE, extraData);
106         }
107         std::string path = item.substr(0, item.find(networkId) + networkId.size());
108         RmDirRecurse(path);
109     }
110     LOGI("umount share file end.");
111     return E_OK;
112 }
113 
FindMountsByNetworkId(const std::string & networkId,std::list<std::string> & mounts)114 int32_t MountManager::FindMountsByNetworkId(const std::string &networkId, std::list<std::string> &mounts)
115 {
116     std::ifstream inputStream(PROC_MOUNTS.c_str(), std::ios::in);
117     if (!inputStream.is_open()) {
118         LOGE("unable to open /proc/mounts, errno is %{public}d", errno);
119         return E_UMOUNT_PROC_MOUNTS_OPEN;
120     }
121     std::string tmpLine;
122     while (std::getline(inputStream, tmpLine)) {
123         if (tmpLine.empty()) {
124             continue;
125         }
126         std::stringstream ss(tmpLine);
127         std::string dst;
128         if ((ss >> dst >> dst) && dst.find(networkId) != std::string::npos) {
129             mounts.push_front(dst);
130         }
131     }
132     return E_OK;
133 }
134 
FilterNotMountedPath(std::map<std::string,std::string> & notMountPaths)135 int32_t MountManager::FilterNotMountedPath(std::map<std::string, std::string> &notMountPaths)
136 {
137     std::ifstream inputStream(PROC_MOUNTS.c_str(), std::ios::in);
138     if (!inputStream.is_open()) {
139         LOGE("unable to open /proc/mounts, errno is %{public}d", errno);
140         return E_UMOUNT_PROC_MOUNTS_OPEN;
141     }
142     std::string tmpLine;
143     while (std::getline(inputStream, tmpLine)) {
144         if (tmpLine.empty()) {
145             continue;
146         }
147         std::stringstream ss(tmpLine);
148         std::string dst;
149         if ((ss >> dst >> dst) && notMountPaths.find(dst) != notMountPaths.end()) {
150             notMountPaths.erase(dst);
151         }
152     }
153     return E_OK;
154 }
155 } // namespace StorageDaemon
156 } // namespace OHOS