• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 <sys/mount.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21 #include "ipc/istorage_daemon.h"
22 #include "parameter.h"
23 #include "storage_service_errno.h"
24 #include "storage_service_log.h"
25 #include "utils/file_utils.h"
26 #include "utils/mount_argument_utils.h"
27 #include "utils/string_utils.h"
28 
29 
30 namespace OHOS {
31 namespace StorageDaemon {
32 using namespace std;
33 constexpr int32_t UMOUNT_RETRY_TIMES = 3;
34 std::shared_ptr<MountManager> MountManager::instance_ = nullptr;
35 
36 const std::string HMDFS_SYS_CAP = "const.distributed_file_property.enabled";
37 const int32_t HMDFS_VAL_LEN = 6;
38 const int32_t HMDFS_TRUE_LEN = 5;
MountManager()39 MountManager::MountManager()
40     : hmdfsDirVec_{{"/data/service/el2/%d/share", 0711, OID_SYSTEM, OID_SYSTEM},
41                    {"/data/service/el2/%d/hmdfs", 0711, OID_SYSTEM, OID_SYSTEM},
42                    {"/data/service/el2/%d/hmdfs/account", 0711, OID_SYSTEM, OID_SYSTEM},
43                    {"/data/service/el2/%d/hmdfs/account/files", 02771, OID_USER_DATA_RW, OID_USER_DATA_RW},
44                    {"/data/service/el2/%d/hmdfs/account/data", 0711, OID_SYSTEM, OID_SYSTEM},
45                    {"/data/service/el2/%d/hmdfs/non_account", 0711, OID_SYSTEM, OID_SYSTEM},
46                    {"/data/service/el2/%d/hmdfs/non_account/files", 0711, OID_USER_DATA_RW, OID_USER_DATA_RW},
47                    {"/data/service/el2/%d/hmdfs/non_account/data", 0711, OID_SYSTEM, OID_SYSTEM},
48                    {"/data/service/el2/%d/hmdfs/cache", 0711, OID_DFS, OID_DFS},
49                    {"/data/service/el2/%d/hmdfs/cache/account_cache", 0711, OID_DFS, OID_DFS},
50                    {"/data/service/el2/%d/hmdfs/cache/non_account_cache", 0711, OID_DFS, OID_DFS},
51                    {"/data/service/el2/%d/hmdfs/account/services", 0771, OID_DFS_SHARE, OID_DFS_SHARE}},
52       virtualDir_{{"/storage/media/%d", 0711, OID_USER_DATA_RW, OID_USER_DATA_RW},
53                   {"/storage/media/%d/local", 0711, OID_USER_DATA_RW, OID_USER_DATA_RW},
54                   {"/mnt/share/", 0711, OID_ROOT, OID_ROOT},
55                   {"/mnt/share/%d/", 0711, OID_ROOT, OID_ROOT},
56                   {"/mnt/hmdfs/", 0711, OID_ROOT, OID_ROOT},
57                   {"/mnt/hmdfs/%d/", 0711, OID_ROOT, OID_ROOT},
58                   {"/mnt/hmdfs/%d/account", 0711, OID_ROOT, OID_ROOT},
59                   {"/mnt/hmdfs/%d/non_account", 0711, OID_ROOT, OID_ROOT}}
60 {
61 }
62 
GetInstance()63 std::shared_ptr<MountManager> MountManager::GetInstance()
64 {
65     static std::once_flag onceFlag;
66     std::call_once(onceFlag, [&]() { instance_ = std::make_shared<MountManager>(); });
67 
68     return instance_;
69 }
70 
HmdfsTwiceMount(int32_t userId,std::string relativePath)71 int32_t MountManager::HmdfsTwiceMount(int32_t userId, std::string relativePath)
72 {
73     int32_t ret = HmdfsMount(userId, relativePath);
74 
75     // bind mount
76     Utils::MountArgument hmdfsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
77     ret += Mount(hmdfsMntArgs.GetFullDst() + "/device_view/", hmdfsMntArgs.GetCommFullPath(),
78                  nullptr, MS_BIND, nullptr);
79     if (ret != 0 && errno != EEXIST && errno != EBUSY) {
80         LOGE("failed to bind mount, err %{public}d", errno);
81         return E_MOUNT;
82     }
83     return E_OK;
84 }
85 
SharefsMount(int32_t userId)86 int32_t MountManager::SharefsMount(int32_t userId)
87 {
88     Utils::MountArgument sharefsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, ""));
89     int ret = Mount(sharefsMntArgs.GetShareSrc(), sharefsMntArgs.GetShareDst(), "sharefs",
90                     sharefsMntArgs.GetFlags(), sharefsMntArgs.GetUserIdPara().c_str());
91     if (ret != 0 && errno != EEXIST && errno != EBUSY) {
92         LOGE("failed to mount sharefs, err %{public}d", errno);
93         return E_MOUNT;
94     }
95     return E_OK;
96 }
97 
SharefsUMount(int32_t userId)98 int32_t MountManager::SharefsUMount(int32_t userId)
99 {
100     Utils::MountArgument sharefsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, ""));
101     int32_t ret = UMount2(sharefsMntArgs.GetShareDst().c_str(), MNT_DETACH);
102     if (ret != E_OK) {
103         LOGE("umount sharefs, errno %{public}d, sharefs dst %{public}s", errno,
104              sharefsMntArgs.GetShareDst().c_str());
105         return E_UMOUNT;
106     }
107     return E_OK;
108 }
109 
HmdfsMount(int32_t userId,std::string relativePath)110 int32_t MountManager::HmdfsMount(int32_t userId, std::string relativePath)
111 {
112     Utils::MountArgument hmdfsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
113     int ret = Mount(hmdfsMntArgs.GetFullSrc(), hmdfsMntArgs.GetFullDst(), "hmdfs",
114                     hmdfsMntArgs.GetFlags(), hmdfsMntArgs.OptionsToString().c_str());
115     if (ret != 0 && errno != EEXIST && errno != EBUSY) {
116         LOGE("failed to mount hmdfs, err %{public}d", errno);
117         return E_MOUNT;
118     }
119 
120     ret = chown(hmdfsMntArgs.GetCtrlPath().c_str(), OID_DFS, OID_SYSTEM);
121     if (ret != 0) {
122         LOGE("failed to chown hmdfs sysfs node, err %{public}d", errno);
123     }
124 
125     return E_OK;
126 }
127 
HmdfsMount(int32_t userId)128 int32_t MountManager::HmdfsMount(int32_t userId)
129 {
130     int32_t ret = HmdfsTwiceMount(userId, "account");
131 
132     ret += HmdfsMount(userId, "non_account");
133     if (ret != E_OK) {
134         return E_MOUNT;
135     }
136 
137     return E_OK;
138 }
139 
HmdfsTwiceUMount(int32_t userId,std::string relativePath)140 int32_t MountManager::HmdfsTwiceUMount(int32_t userId, std::string relativePath)
141 {
142     int32_t err = E_OK;
143     // un bind mount
144     Utils::MountArgument hmdfsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
145     err = UMount(hmdfsMntArgs.GetCommFullPath());
146     if (err != E_OK) {
147         LOGE("failed to un bind mount, errno %{public}d, ComDataDir_ dst %{public}s", errno,
148              hmdfsMntArgs.GetCommFullPath().c_str());
149     }
150 
151     err = UMount2(hmdfsMntArgs.GetFullDst().c_str(), MNT_DETACH);
152     if (err != E_OK) {
153         LOGE("identical account hmdfs umount failed, errno %{public}d, hmdfs dst %{public}s", errno,
154              hmdfsMntArgs.GetFullDst().c_str());
155         return E_UMOUNT;
156     }
157     return E_OK;
158 }
159 
HmdfsUMount(int32_t userId,std::string relativePath)160 int32_t MountManager::HmdfsUMount(int32_t userId, std::string relativePath)
161 {
162     Utils::MountArgument hmdfsAuthMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
163     int32_t ret = UMount2(hmdfsAuthMntArgs.GetFullDst().c_str(), MNT_DETACH);
164     if (ret != E_OK) {
165         LOGE("umount auth hmdfs, errno %{public}d, auth hmdfs dst %{public}s", errno,
166              hmdfsAuthMntArgs.GetFullDst().c_str());
167         return E_UMOUNT;
168     }
169     return E_OK;
170 }
171 
HmdfsUMount(int32_t userId)172 int32_t MountManager::HmdfsUMount(int32_t userId)
173 {
174     int32_t ret = HmdfsTwiceUMount(userId, "account");
175     ret += HmdfsUMount(userId, "non_account");
176     if (ret != E_OK) {
177         return E_UMOUNT;
178     }
179     return E_OK;
180 }
181 
SupportHmdfs()182 bool MountManager::SupportHmdfs()
183 {
184     char hmdfsEnable[HMDFS_VAL_LEN + 1] = {"false"};
185     int ret = GetParameter(HMDFS_SYS_CAP.c_str(), "", hmdfsEnable, HMDFS_VAL_LEN);
186     LOGI("GetParameter hmdfsEnable %{public}s, ret %{public}d", hmdfsEnable, ret);
187     if (strncmp(hmdfsEnable, "true", HMDFS_TRUE_LEN) == 0) {
188         return true;
189     }
190     return false;
191 }
192 
LocalMount(int32_t userId)193 int32_t MountManager::LocalMount(int32_t userId)
194 {
195     Utils::MountArgument LocalMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, "account"));
196     if (Mount(LocalMntArgs.GetFullSrc(), LocalMntArgs.GetCommFullPath() + "local/",
197               nullptr, MS_BIND, nullptr)) {
198         LOGE("failed to bind mount, err %{public}d", errno);
199         return E_MOUNT;
200     }
201     return E_OK;
202 }
203 
MountByUser(int32_t userId)204 int32_t MountManager::MountByUser(int32_t userId)
205 {
206     int ret = E_OK;
207     if (CreateVirtualDirs(userId) != E_OK) {
208         LOGE("create hmdfs virtual dir error");
209         return E_PREPARE_DIR;
210     }
211 
212     if (!SupportHmdfs()) {
213         ret = LocalMount(userId);
214     } else {
215         ret = HmdfsMount(userId);
216     }
217 
218     if (ret != E_OK) {
219         LOGE("hmdfs mount error");
220         return ret;
221     }
222 
223     ret = SharefsMount(userId);
224     if (ret != E_OK) {
225         LOGE("sharefs mount error");
226         return ret;
227     }
228     return E_OK;
229 }
230 
LocalUMount(int32_t userId)231 int32_t MountManager::LocalUMount(int32_t userId)
232 {
233     Utils::MountArgument LocalMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, "account"));
234     return UMount(LocalMntArgs.GetCommFullPath() + "local/");
235 }
236 
UmountByUser(int32_t userId)237 int32_t MountManager::UmountByUser(int32_t userId)
238 {
239     int32_t count = 0;
240     while (count < UMOUNT_RETRY_TIMES) {
241         int32_t err = E_OK;
242         err = SharefsUMount(userId);
243         if (err != E_OK) {
244             LOGE("failed to umount sharefs, errno %{public}d", errno);
245         }
246         if (!SupportHmdfs()) {
247             err = LocalUMount(userId);
248         } else {
249             err = HmdfsUMount(userId);
250         }
251         if (err == E_OK) {
252             break;
253         } else if (errno == EBUSY) {
254             count++;
255             continue;
256         }
257         LOGE("failed to umount hmdfs, errno %{public}d", errno);
258         return E_UMOUNT;
259     }
260     return E_OK;
261 }
262 
PrepareHmdfsDirs(int32_t userId)263 int32_t MountManager::PrepareHmdfsDirs(int32_t userId)
264 {
265     for (const DirInfo &dir : hmdfsDirVec_) {
266         if (!PrepareDir(StringPrintf(dir.path.c_str(), userId), dir.mode, dir.uid, dir.gid)) {
267             return E_PREPARE_DIR;
268         }
269     }
270 
271     return E_OK;
272 }
273 
CreateVirtualDirs(int32_t userId)274 int32_t MountManager::CreateVirtualDirs(int32_t userId)
275 {
276     for (const DirInfo &dir : virtualDir_) {
277         if (!PrepareDir(StringPrintf(dir.path.c_str(), userId), dir.mode, dir.uid, dir.gid)) {
278             return E_PREPARE_DIR;
279         }
280     }
281 
282     return E_OK;
283 }
284 
DestroyHmdfsDirs(int32_t userId)285 int32_t MountManager::DestroyHmdfsDirs(int32_t userId)
286 {
287     bool err = true;
288 
289     for (const DirInfo &dir : hmdfsDirVec_) {
290         if (IsEndWith(dir.path.c_str(), "%d")) {
291             err = RmDirRecurse(StringPrintf(dir.path.c_str(), userId));
292         }
293     }
294 
295     return err ? E_OK : E_DESTROY_DIR;
296 }
297 } // namespace StorageDaemon
298 } // namespace OHOS
299