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