• 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 "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