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 "mtp/mtp_device_manager.h"
17 #include "ipc/storage_manager_client.h"
18 #include "storage_service_errno.h"
19 #include "storage_service_log.h"
20 #include "utils/file_utils.h"
21
22 #include <config.h>
23 #include <dirent.h>
24 #include <iostream>
25 #include <cstdio>
26 #include <string>
27 #include <sys/mount.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <sys/wait.h>
31 #include <unistd.h>
32 #include "ipc/storage_manager_client.h"
33 #include "storage_service_errno.h"
34 #include "storage_service_log.h"
35 #include "utils/file_utils.h"
36
37 namespace OHOS {
38 namespace StorageDaemon {
39 constexpr int32_t DEFAULT_DEV_INDEX = 1;
40 constexpr uid_t FILE_MANAGER_UID = 1006;
41 constexpr gid_t FILE_MANAGER_GID = 1006;
42 constexpr mode_t PUBLIC_DIR_MODE = 02770;
MtpDeviceManager()43 MtpDeviceManager::MtpDeviceManager() {}
44
~MtpDeviceManager()45 MtpDeviceManager::~MtpDeviceManager()
46 {
47 LOGI("MtpDeviceManager Destructor.");
48 }
49
PrepareMtpMountPath(const std::string & path)50 int32_t MtpDeviceManager::PrepareMtpMountPath(const std::string &path)
51 {
52 if (!IsDir(path)) {
53 LOGI("PrepareMtpMountPath: mtp device mount path directory does not exist, creating it.");
54 bool ret = PrepareDir(path, PUBLIC_DIR_MODE, FILE_MANAGER_UID, FILE_MANAGER_GID);
55 if (!ret) {
56 LOGE("Prepare directory for mtp device path = %{public}s failed.", path.c_str());
57 return E_MTP_PREPARE_DIR_ERR;
58 }
59 }
60 return E_OK;
61 }
62
MountDevice(const MtpDeviceInfo & device)63 int32_t MtpDeviceManager::MountDevice(const MtpDeviceInfo &device)
64 {
65 LOGI("MountDevice: start mount mtp device, path=%{public}s", device.path.c_str());
66 if (isMounting) {
67 LOGI("MountDevice: mtp device is mounting, try again later.");
68 return E_MTP_IS_MOUNTING;
69 }
70 isMounting = true;
71 int32_t ret = PrepareMtpMountPath(device.path);
72 if (ret != E_OK) {
73 isMounting = false;
74 return ret;
75 }
76 std::vector<std::string> cmdVec = {
77 "mtpfs",
78 "-o",
79 "uid=" + std::to_string(FILE_MANAGER_UID),
80 "-o",
81 "gid=" + std::to_string(FILE_MANAGER_GID),
82 "-o",
83 "allow_other",
84 "-o",
85 "enable-move",
86 "-o",
87 "max_idle_threads=10",
88 "-o",
89 "max_threads=20",
90 "-o",
91 "context=u:object_r:mnt_external_file:s0",
92 "--device",
93 std::to_string(DEFAULT_DEV_INDEX),
94 device.path,
95 };
96 std::vector<std::string> result;
97 int32_t err = ForkExec(cmdVec, &result);
98 for (auto str : result) {
99 LOGI("MountDevice result: %{public}s", str.c_str());
100 }
101 if ((err != 0) || (result.size() != 0)) {
102 LOGE("Run mtpfs cmd to mount mtp device failed.");
103 UmountDevice(device, false, false);
104 isMounting = false;
105 return E_MTP_MOUNT_FAILED;
106 }
107
108 LOGI("Run mtpfs cmd to mount mtp device success.");
109 isMounting = false;
110 StorageManagerClient client;
111 client.NotifyMtpMounted(device.id, device.path, device.vendor, device.uuid);
112 return E_OK;
113 }
114
UmountDevice(const MtpDeviceInfo & device,bool needNotify,bool isBadRemove)115 int32_t MtpDeviceManager::UmountDevice(const MtpDeviceInfo &device, bool needNotify, bool isBadRemove)
116 {
117 LOGI("MountDevice: start umount mtp device, path=%{public}s", device.path.c_str());
118 if (isBadRemove) {
119 LOGI("force to umount mtp device");
120 umount2(device.path.c_str(), MNT_DETACH);
121 remove(device.path.c_str());
122 LOGI("Mtp device force to unmount success");
123 if (needNotify) {
124 StorageManagerClient client;
125 client.NotifyMtpUnmounted(device.id, device.path, isBadRemove);
126 }
127 DelFolder(device.path);
128 return E_OK;
129 }
130 int ret = umount(device.path.c_str());
131 int err = remove(device.path.c_str());
132 if (err && ret) {
133 LOGE("umount mtp device error.");
134 return E_MTP_UMOUNT_FAILED;
135 }
136 if (err) {
137 LOGE("failed to call remove(%{public}s) error, errno=%{public}d", device.path.c_str(), errno);
138 return E_SYS_KERNEL_ERR;
139 }
140 LOGI("Mtp device unmount success.");
141 if (needNotify) {
142 StorageManagerClient client;
143 client.NotifyMtpUnmounted(device.id, device.path, isBadRemove);
144 }
145 DelFolder(device.path);
146 return E_OK;
147 }
148 } // namespace StorageDaemon
149 } // namespace OHOS
150