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