1 /*
2 * Copyright (c) 2021-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 "volume/external_volume_info.h"
17
18 #include <fcntl.h>
19 #include <future>
20 #include <sys/stat.h>
21 #include <sys/wait.h>
22 #include <unistd.h>
23 #include <filesystem>
24
25 #include "storage_service_errno.h"
26 #include "storage_service_log.h"
27 #include "utils/disk_utils.h"
28 #include "utils/file_utils.h"
29 #include "utils/storage_radar.h"
30 #include "utils/string_utils.h"
31 #include "volume/process.h"
32
33 #define STORAGE_MANAGER_IOC_CHK_BUSY _IOR(0xAC, 77, int)
34 constexpr uid_t FILE_MANAGER_UID = 1006;
35 constexpr gid_t FILE_MANAGER_GID = 1006;
36 using namespace std;
37 using namespace OHOS::StorageService;
38 namespace OHOS {
39 namespace StorageDaemon {
40 constexpr int32_t WAIT_THREAD_TIMEOUT_S = 15;
41 constexpr int32_t FILE_NOT_EXIST = 2;
42 constexpr int UID_FILE_MANAGER = 1006;
ReadMetadata()43 int32_t ExternalVolumeInfo::ReadMetadata()
44 {
45 int32_t ret = OHOS::StorageDaemon::ReadMetadata(devPath_, fsUuid_, fsType_, fsLabel_);
46 if (fsType_ == "ntfs" && (fsLabel_.find('?') != std::string::npos || fsLabel_ == "")) {
47 std::vector<std::string> cmd;
48 cmd = {
49 "ntfslabel",
50 devPath_
51 };
52 fsLabel_ = GetBlkidDataByCmd(cmd);
53 }
54 return ret;
55 }
56
GetFsType()57 std::string ExternalVolumeInfo::GetFsType()
58 {
59 return fsType_;
60 }
61
GetFsUuid()62 std::string ExternalVolumeInfo::GetFsUuid()
63 {
64 return fsUuid_;
65 }
66
GetFsLabel()67 std::string ExternalVolumeInfo::GetFsLabel()
68 {
69 return fsLabel_;
70 }
71
GetMountPath()72 std::string ExternalVolumeInfo::GetMountPath()
73 {
74 return mountPath_;
75 }
76
DoCreate(dev_t dev)77 int32_t ExternalVolumeInfo::DoCreate(dev_t dev)
78 {
79 int32_t ret = 0;
80 string id = VolumeInfo::GetVolumeId();
81
82 device_ = dev;
83 devPath_ = StringPrintf(devPathDir_.c_str(), (id).c_str());
84
85 ret = mknod(devPath_.c_str(), S_IFBLK, dev);
86 if (ret) {
87 LOGE("External volume DoCreate error.");
88 return E_ERR;
89 }
90 return E_OK;
91 }
92
DoDestroy()93 int32_t ExternalVolumeInfo::DoDestroy()
94 {
95 int err = remove(devPath_.c_str());
96 if (err) {
97 LOGE("External volume DoDestroy error.");
98 return E_ERR;
99 }
100 return E_OK;
101 }
102
DoMount4Ext(uint32_t mountFlags)103 int32_t ExternalVolumeInfo::DoMount4Ext(uint32_t mountFlags)
104 {
105 mode_t mode = 0777;
106 int32_t ret = mount(devPath_.c_str(), mountPath_.c_str(), fsType_.c_str(), mountFlags, "");
107 if (ret) {
108 return E_EXT_MOUNT;
109 }
110 TravelChmod(mountPath_, mode);
111 return ret;
112 }
113
DoMount4Hmfs(uint32_t mountFlags)114 int32_t ExternalVolumeInfo::DoMount4Hmfs(uint32_t mountFlags)
115 {
116 mode_t mode = 0777;
117 const char *fsType = "hmfs";
118 auto mountData = StringPrintf("context=u:object_r:mnt_external_file:s0");
119 int32_t ret = mount(devPath_.c_str(), mountPath_.c_str(), fsType, mountFlags, mountData.c_str());
120 if (!ret) {
121 TravelChmod(mountPath_, mode);
122 StorageRadar::ReportVolumeOperation("ExternalVolumeInfo::DoMount4Hmfs", ret);
123 }
124 return ret;
125 }
126
DoMount4Ntfs(uint32_t mountFlags)127 int32_t ExternalVolumeInfo::DoMount4Ntfs(uint32_t mountFlags)
128 {
129 #ifdef EXTERNAL_STORAGE_QOS_TRANS
130 auto mountData = StringPrintf("rw,big_writes,uid=%d,gid=%d,dmask=0007,fmask=0007",
131 UID_FILE_MANAGER, UID_FILE_MANAGER);
132 #else
133 auto mountData = StringPrintf("rw,uid=%d,gid=%d,dmask=0007,fmask=0007", UID_FILE_MANAGER, UID_FILE_MANAGER);
134 #endif
135 if (mountFlags & MS_RDONLY) {
136 mountData = StringPrintf("ro,uid=%d,gid=%d,dmask=0007,fmask=0007", UID_FILE_MANAGER, UID_FILE_MANAGER);
137 }
138
139 std::vector<std::string> cmd = {
140 "mount.ntfs",
141 devPath_,
142 mountPath_,
143 "-o",
144 mountData.c_str()
145 };
146 std::vector<std::string> output;
147 #ifdef EXTERNAL_STORAGE_QOS_TRANS
148 if (ExtStorageMountForkExec(cmd) != E_OK) {
149 LOGE("ext exec mount for ntfs failed, errno is %{public}d.", errno);
150 return E_NTFS_MOUNT;
151 }
152 return E_OK;
153 #else
154 if (ForkExec(cmd, &output) != E_OK) {
155 LOGE("exec mount for ntfs failed, errno is %{public}d.", errno);
156 return E_NTFS_MOUNT;
157 }
158 return E_OK;
159 #endif
160 }
161
DoMount4Exfat(uint32_t mountFlags)162 int32_t ExternalVolumeInfo::DoMount4Exfat(uint32_t mountFlags)
163 {
164 auto mountData = StringPrintf("rw,uid=%d,gid=%d,dmask=0007,fmask=0007", UID_FILE_MANAGER, UID_FILE_MANAGER);
165 if (mountFlags & MS_RDONLY) {
166 mountData = StringPrintf("ro,uid=%d,gid=%d,dmask=0007,fmask=0007", UID_FILE_MANAGER, UID_FILE_MANAGER);
167 }
168
169 std::vector<std::string> cmd = {
170 "mount.exfat",
171 "-o",
172 mountData.c_str(),
173 devPath_,
174 mountPath_,
175 };
176 std::vector<std::string> output;
177 #ifdef EXTERNAL_STORAGE_QOS_TRANS
178 if (ExtStorageMountForkExec(cmd) != E_OK) {
179 LOGE("ext exec mount for exfat failed, errno is %{public}d.", errno);
180 return E_EXFAT_MOUNT;
181 }
182 return E_OK;
183 #else
184 if (ForkExec(cmd, &output) != E_OK) {
185 LOGE("exec mount for exfat failed, errno is %{public}d.", errno);
186 return E_EXFAT_MOUNT;
187 }
188 return E_OK;
189 #endif
190 }
191
DoCheck4Exfat()192 int32_t ExternalVolumeInfo::DoCheck4Exfat()
193 {
194 std::vector<std::string> cmd = {
195 "fsck.exfat",
196 "-n",
197 devPath_,
198 };
199 int execRet = ForkExecWithExit(cmd);
200 LOGI("execRet: %{public}d", execRet);
201 if (execRet != E_OK) {
202 return E_VOL_NEED_FIX;
203 }
204 return E_OK;
205 }
206
DoCheck4Ntfs()207 int32_t ExternalVolumeInfo::DoCheck4Ntfs()
208 {
209 std::vector<std::string> cmd = {
210 "fsck.ntfs",
211 devPath_,
212 };
213 int execRet = ForkExecWithExit(cmd);
214 LOGI("execRet: %{public}d", execRet);
215 if (execRet != E_OK) {
216 return E_VOL_NEED_FIX;
217 }
218 return E_OK;
219 }
220
DoFix4Ntfs()221 int32_t ExternalVolumeInfo::DoFix4Ntfs()
222 {
223 LOGE("DoFix4Ntfs");
224 std::vector<std::string> cmd = {
225 "ntfsfix",
226 "-d",
227 devPath_
228 };
229 std::vector<std::string> output;
230 #ifdef EXTERNAL_STORAGE_QOS_TRANS
231 if (ExtStorageMountForkExec(cmd) != E_OK) {
232 LOGE("ext exec fix for ntfs failed, errno is %{public}d.", errno);
233 return E_VOL_FIX_FAILED;
234 }
235 return E_OK;
236 #else
237 if (ForkExec(cmd, &output) != E_OK) {
238 LOGE("exec fix for ntfs failed, errno is %{public}d.", errno);
239 return E_VOL_FIX_FAILED;
240 }
241 return E_OK;
242 #endif
243 }
244
DoFix4Exfat()245 int32_t ExternalVolumeInfo::DoFix4Exfat()
246 {
247 LOGE("DoFix4Exfat");
248 std::vector<std::string> cmd = {
249 "fsck.exfat",
250 "-p",
251 devPath_,
252 };
253 std::vector<std::string> output;
254 #ifdef EXTERNAL_STORAGE_QOS_TRANS
255 if (ExtStorageMountForkExec(cmd) != E_OK) {
256 LOGE("ext exec fix for exfat failed, errno is %{public}d.", errno);
257 return E_VOL_FIX_FAILED;
258 }
259 return E_OK;
260 #else
261 if (ForkExec(cmd, &output) != E_OK) {
262 LOGE("exec fix for exfat failed, errno is %{public}d.", errno);
263 return E_VOL_FIX_FAILED;
264 }
265 return E_OK;
266 #endif
267 }
268
DoMount4OtherType(uint32_t mountFlags)269 int32_t ExternalVolumeInfo::DoMount4OtherType(uint32_t mountFlags)
270 {
271 mountFlags |= MS_MGC_VAL;
272 auto mountData = StringPrintf("uid=%d,gid=%d,dmask=0007,fmask=0007", UID_FILE_MANAGER, UID_FILE_MANAGER);
273 int32_t ret = mount(devPath_.c_str(), mountPath_.c_str(), fsType_.c_str(), mountFlags, mountData.c_str());
274 if (ret) {
275 return E_OTHER_MOUNT;
276 }
277 return ret;
278 }
279
DoMount4Vfat(uint32_t mountFlags)280 int32_t ExternalVolumeInfo::DoMount4Vfat(uint32_t mountFlags)
281 {
282 mountFlags |= MS_MGC_VAL;
283 auto mountData = StringPrintf("uid=%d,gid=%d,dmask=0007,fmask=0007,utf8", UID_FILE_MANAGER, UID_FILE_MANAGER);
284 int32_t ret = mount(devPath_.c_str(), mountPath_.c_str(), fsType_.c_str(), mountFlags, mountData.c_str());
285 if (ret) {
286 return E_FAT_MOUNT;
287 }
288 return ret;
289 }
290
DoMount(uint32_t mountFlags)291 int32_t ExternalVolumeInfo::DoMount(uint32_t mountFlags)
292 {
293 int32_t ret = DoCheck();
294 if (ret != E_OK) {
295 LOGE("External volume uuid=%{public}s check failed.", GetAnonyString(GetFsUuid()).c_str());
296 return E_DOCHECK_MOUNT;
297 }
298 if (IsUsbFuse()) {
299 ret = CreateFuseMountPath();
300 } else {
301 ret = CreateMountPath();
302 }
303 if (ret != E_OK) {
304 return ret;
305 }
306 if ((fsType_ == "hmfs" || fsType_ == "f2fs") && GetIsUserdata()) {
307 ret = DoMount4Hmfs(mountFlags);
308 }
309 if (ret) {
310 LOGE("External volume DoMount error, errno = %{public}d", errno);
311 remove(mountPath_.c_str());
312 return E_HMFS_MOUNT;
313 }
314 std::promise<int32_t> promise;
315 std::future<int32_t> future = promise.get_future();
316 std::thread mountThread ([this, mountFlags, p = std::move(promise)]() mutable {
317 LOGI("Ready to mount: volume fstype is %{public}s, mountflag is %{public}d", fsType_.c_str(), mountFlags);
318 int retValue = E_OK;
319 if (fsType_ == "ntfs") retValue = DoMount4Ntfs(mountFlags);
320 else if (fsType_ == "exfat") retValue = DoMount4Exfat(mountFlags);
321 else if (fsType_ == "vfat" || fsType_ == "fat32") retValue = DoMount4Vfat(mountFlags);
322 else if ((fsType_ == "hmfs" || fsType_ == "f2fs") && GetIsUserdata()) retValue = E_OK;
323 else retValue = E_OTHER_MOUNT;
324 p.set_value(retValue);
325 });
326 if (future.wait_for(std::chrono::seconds(WAIT_THREAD_TIMEOUT_S)) == std::future_status::timeout) {
327 LOGE("Mount timed out");
328 remove(mountPath_.c_str());
329 mountThread.detach();
330 return E_TIMEOUT_MOUNT;
331 }
332 ret = future.get();
333 mountThread.join();
334 if (ret) {
335 LOGE("External volume DoMount error, errno = %{public}d", errno);
336 remove(mountPath_.c_str());
337 return ret;
338 }
339 mountPath_ = mountBackupPath_;
340 return E_OK;
341 }
342
IsUsbInUse(int fd)343 int32_t ExternalVolumeInfo::IsUsbInUse(int fd)
344 {
345 int32_t inUse = -1;
346 if (ioctl(fd, STORAGE_MANAGER_IOC_CHK_BUSY, &inUse) < 0) {
347 LOGE("ioctl check in use failed errno %{public}d", errno);
348 return E_IOCTL_FAILED;
349 }
350 if (inUse) {
351 LOGI("usb inuse number is %{public}d", inUse);
352 return E_USB_IN_USE;
353 }
354 LOGI("usb not inUse");
355 return E_OK;
356 }
357
DoUMount(bool force)358 int32_t ExternalVolumeInfo::DoUMount(bool force)
359 {
360 if (force && !IsUsbFuse()) {
361 LOGI("External volume start force to unmount.");
362 Process ps(mountPath_);
363 ps.UpdatePidByPath();
364 ps.KillProcess(SIGKILL);
365 umount2(mountPath_.c_str(), MNT_DETACH);
366 remove(mountPath_.c_str());
367 LOGI("External volume force to unmount success.");
368 return E_OK;
369 }
370 if (IsUsbFuse()) {
371 mountPath_ = mountUsbFusePath_;
372 }
373 int fd = open(mountPath_.c_str(), O_RDONLY);
374 if (fd < 0) {
375 LOGE("open file fail mountPath %{public}s, errno %{public}d", GetAnonyString(mountPath_).c_str(), errno);
376 }
377 if (fd >= 0) {
378 IsUsbInUse(fd);
379 }
380
381 LOGI("External volume start to unmount mountPath: %{public}s.", GetAnonyString(mountPath_).c_str());
382 int ret = umount2(mountPath_.c_str(), MNT_DETACH);
383 if (ret != E_OK) {
384 LOGE("umount2 failed errno %{public}d", errno);
385 }
386 if (fd >= 0) {
387 IsUsbInUse(fd);
388 close(fd);
389 }
390
391 int err = remove(mountPath_.c_str());
392 if (err && ret) {
393 LOGE("External volume DoUmount error.");
394 return E_VOL_UMOUNT_ERR;
395 }
396 if (err && errno != FILE_NOT_EXIST) {
397 LOGE("failed to call remove(%{public}s) error, errno = %{public}d", GetAnonyString(mountPath_).c_str(), errno);
398 return E_RMDIR_MOUNT;
399 }
400 mountPath_ = mountBackupPath_;
401
402 LOGI("External volume unmount success.");
403 return E_OK;
404 }
405
DoUMountUsbFuse()406 int32_t ExternalVolumeInfo::DoUMountUsbFuse()
407 {
408 LOGI("DoUMountUsbFuse in.");
409 int ret = umount2(mountPath_.c_str(), MNT_DETACH);
410 if (ret != E_OK) {
411 LOGE("umount2 mountUsbFusePath failed errno %{public}d", errno);
412 }
413
414 int err = rmdir(mountPath_.c_str());
415 if (err) {
416 LOGE("External volume DoUMountUsbFuse error: rmdir failed, errno %{public}d", errno);
417 return E_RMDIR_MOUNT;
418 }
419 LOGI("DoUMountUsbFuse success.");
420 return E_OK;
421 }
422
DoTryToCheck()423 int32_t ExternalVolumeInfo::DoTryToCheck()
424 {
425 int32_t ret = DoCheck();
426 if (ret != E_OK) {
427 LOGE("External volume uuid=%{public}s check failed.", GetAnonyString(GetFsUuid()).c_str());
428 return E_DOCHECK_MOUNT;
429 }
430
431 if (fsType_ != "ntfs" && fsType_ != "exfat") {
432 LOGE("Volume type %{public}s, is not support fix", fsType_.c_str());
433 return E_OK;
434 }
435
436 std::promise<int32_t> promise;
437 std::future<int32_t> future = promise.get_future();
438 std::thread mountThread ([this, p = std::move(promise)]() mutable {
439 LOGI("Ready to DoTryToCheck: volume fstype is %{public}s", fsType_.c_str());
440 int retValue = E_OK;
441 if (fsType_ == "ntfs") retValue = DoCheck4Ntfs();
442 else if (fsType_ == "exfat") retValue = DoCheck4Exfat();
443 else retValue = E_VOL_FIX_NOT_SUPPORT;
444 LOGI("DoTryToCheck cmdRet:%{public}d", retValue);
445 p.set_value(retValue);
446 });
447 if (future.wait_for(std::chrono::seconds(WAIT_THREAD_TIMEOUT_S)) == std::future_status::timeout) {
448 LOGE("DoTryToCheck timed out");
449 mountThread.detach();
450 return E_TIMEOUT_MOUNT;
451 }
452
453 ret = future.get();
454 mountThread.join();
455 if (ret != E_OK) {
456 LOGE("External volume DoTryToCheck error, maybe need fix, errno = %{public}d", ret);
457 return E_VOL_NEED_FIX;
458 }
459 return E_OK;
460 }
461
DoTryToFix()462 int32_t ExternalVolumeInfo::DoTryToFix()
463 {
464 int32_t ret = DoCheck();
465 if (ret != E_OK) {
466 LOGE("External volume uuid=%{public}s check failed.", GetAnonyString(GetFsUuid()).c_str());
467 return E_DOCHECK_MOUNT;
468 }
469
470 if (fsType_ != "ntfs" && fsType_ != "exfat") {
471 LOGE("Volume type %{public}s, is not support fix", fsType_.c_str());
472 return E_VOL_FIX_NOT_SUPPORT;
473 }
474 std::promise<int32_t> promise;
475 std::future<int32_t> future = promise.get_future();
476 std::thread mountThread ([this, p = std::move(promise)]() mutable {
477 LOGI("Ready to mount: volume fstype is %{public}s", fsType_.c_str());
478 int retValue = E_OK;
479 if (fsType_ == "ntfs") retValue = DoFix4Ntfs();
480 else if (fsType_ == "exfat") retValue = DoFix4Exfat();
481 p.set_value(retValue);
482 });
483 if (future.wait_for(std::chrono::seconds(WAIT_THREAD_TIMEOUT_S)) == std::future_status::timeout) {
484 LOGE("Fix timed out");
485 mountThread.detach();
486 return E_TIMEOUT_MOUNT;
487 }
488
489 ret = future.get();
490 mountThread.join();
491 LOGI("DoTryToFix: volume fstype is %{public}s, ret: %{public}d, errno: %{public}d", fsType_.c_str(), ret, errno);
492 return ret;
493 }
494
DoCheck()495 int32_t ExternalVolumeInfo::DoCheck()
496 {
497 int32_t ret = ExternalVolumeInfo::ReadMetadata();
498 if (ret) {
499 LOGE("External volume uuid=%{public}s DoCheck failed.", GetAnonyString(GetFsUuid()).c_str());
500 return E_CHECK;
501 }
502
503 // check fstype
504 for (std::string item : supportMountType_) {
505 if (item == fsType_) {
506 return E_OK;
507 }
508 }
509 LOGE("External Volume type not support.");
510 return E_NOT_SUPPORT;
511 }
512
DoFormat(std::string type)513 int32_t ExternalVolumeInfo::DoFormat(std::string type)
514 {
515 int32_t err = 0;
516 if (IsUsbFuse() && IsPathMounted(mountPath_)) {
517 err = DoUMountUsbFuse();
518 }
519 if (err != E_OK) {
520 return err;
521 }
522
523 std::map<std::string, std::string>::iterator iter = supportFormatType_.find(type);
524 if (iter == supportFormatType_.end()) {
525 LOGE("External volume format not support.");
526 return E_NOT_SUPPORT;
527 }
528 std::vector<std::string> output;
529 if (type == "vfat") {
530 std::vector<std::string> cmd = {
531 iter->second,
532 "-A",
533 devPath_
534 };
535 err = ForkExec(cmd, &output);
536 } else {
537 std::vector<std::string> cmd = {
538 iter->second,
539 devPath_
540 };
541 err = ForkExec(cmd, &output);
542 }
543
544 if (err == E_NO_CHILD) {
545 err = E_OK;
546 }
547 ReadMetadata();
548 LOGI("do format end, err is %{public}d.", err);
549 return err;
550 }
551
DoSetVolDesc(std::string description)552 int32_t ExternalVolumeInfo::DoSetVolDesc(std::string description)
553 {
554 int32_t err = 0;
555 std::vector<std::string> output;
556 if (fsType_ == "ntfs") {
557 std::vector<std::string> fixCmd = {
558 "ntfsfix",
559 "-d",
560 devPath_
561 };
562 err = ForkExec(fixCmd, &output);
563 std::vector<std::string> labelCmd = {
564 "ntfslabel",
565 devPath_,
566 description
567 };
568 output.clear();
569 err = ForkExec(labelCmd, &output);
570 } else if (fsType_ == "exfat") {
571 std::vector<std::string> cmd = {
572 "exfatlabel",
573 devPath_,
574 description
575 };
576 err = ForkExec(cmd, &output);
577 } else if (fsType_ == "hmfs") {
578 std::vector<std::string> cmd = {
579 "hmfslabel",
580 devPath_,
581 description
582 };
583 err = ForkExec(cmd, &output);
584 } else {
585 LOGE("SetVolumeDescription fsType not support.");
586 return E_NOT_SUPPORT;
587 }
588 ReadMetadata();
589 LOGI("do set vol desc end, err is %{public}d.", err);
590 return err;
591 }
592
CreateFuseMountPath()593 int32_t ExternalVolumeInfo::CreateFuseMountPath()
594 {
595 struct stat statbuf;
596 mountBackupPath_ = StringPrintf(mountPathDir_.c_str(), fsUuid_.c_str());
597 mountUsbFusePath_ = StringPrintf(mountFusePathDir_.c_str(), fsUuid_.c_str());
598 std::string mountFusePath = "/mnt/data/external_fuse";
599 bool ret = true;
600 if (lstat(mountFusePath.c_str(), &statbuf)) {
601 ret = PrepareDir("/mnt/data/external_fuse", S_IRWXU | S_IRWXG | S_IXOTH, FILE_MANAGER_UID, FILE_MANAGER_GID);
602 if (!ret) {
603 LOGE("create path %{public}s failed", mountFusePath.c_str());
604 return E_MKDIR_MOUNT;
605 }
606 }
607
608 if (!lstat(mountUsbFusePath_.c_str(), &statbuf)) {
609 LOGE("volume mount path %{public}s exists, please remove first", GetAnonyString(mountUsbFusePath_).c_str());
610 remove(mountUsbFusePath_.c_str());
611 return E_SYS_KERNEL_ERR;
612 }
613 ret = PrepareDir(mountUsbFusePath_, S_IRWXU | S_IRWXG | S_IXOTH, FILE_MANAGER_UID, FILE_MANAGER_GID);
614 if (!ret) {
615 LOGE("the volume %{public}s create path %{public}s failed",
616 GetVolumeId().c_str(), GetAnonyString(mountUsbFusePath_).c_str());
617 return E_MKDIR_MOUNT;
618 }
619 mountPath_ = mountUsbFusePath_;
620 return E_OK;
621 }
622
CreateMountPath()623 int32_t ExternalVolumeInfo::CreateMountPath()
624 {
625 struct stat statbuf;
626 mountBackupPath_ = StringPrintf(mountPathDir_.c_str(), fsUuid_.c_str());
627 if (!lstat(mountBackupPath_.c_str(), &statbuf)) {
628 LOGE("volume mount path %{public}s exists, please remove first", mountBackupPath_.c_str());
629 remove(mountBackupPath_.c_str());
630 return E_SYS_KERNEL_ERR;
631 }
632 if (mkdir(mountBackupPath_.c_str(), S_IRWXU | S_IRWXG | S_IXOTH)) {
633 LOGE("the volume %{public}s create path %{public}s failed", GetVolumeId().c_str(), mountBackupPath_.c_str());
634 return E_MKDIR_MOUNT;
635 }
636 mountPath_ = mountBackupPath_;
637 return E_OK;
638 }
639 } // StorageDaemon
640 } // OHOS
641