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