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 "volume/volume_manager_service.h"
17 #include "volume/volume_manager_service_ext.h"
18
19 #include "disk.h"
20 #include "disk/disk_manager_service.h"
21 #include "safe_map.h"
22 #include "securec.h"
23 #include "storage_daemon_communication/storage_daemon_communication.h"
24 #include "storage_service_errno.h"
25 #include "storage_service_log.h"
26 #include <sys/xattr.h>
27 #include "utils/storage_radar.h"
28 #include "utils/storage_utils.h"
29 #include "utils/file_utils.h"
30 #include "utils/string_utils.h"
31 #include "volume/notification.h"
32
33 using namespace std;
34 using namespace OHOS::StorageService;
35 const int32_t MTP_DEVICE_NAME_LEN = 512;
36 namespace OHOS {
37 namespace StorageManager {
VolumeManagerService()38 VolumeManagerService::VolumeManagerService() {}
~VolumeManagerService()39 VolumeManagerService::~VolumeManagerService() {}
40
VolumeStateNotify(VolumeState state,std::shared_ptr<VolumeExternal> volume)41 void VolumeManagerService::VolumeStateNotify(VolumeState state, std::shared_ptr<VolumeExternal> volume)
42 {
43 Notification::GetInstance().NotifyVolumeChange(state, volume);
44 }
45
OnVolumeCreated(VolumeCore vc)46 void VolumeManagerService::OnVolumeCreated(VolumeCore vc)
47 {
48 auto volumePtr = make_shared<VolumeExternal>(vc);
49 volumeMap_.Insert(volumePtr->GetId(), volumePtr);
50 Mount(volumePtr->GetId());
51 }
52
OnVolumeStateChanged(string volumeId,VolumeState state)53 void VolumeManagerService::OnVolumeStateChanged(string volumeId, VolumeState state)
54 {
55 if (state == VolumeState::FUSE_REMOVED) {
56 int32_t result = VolumeManagerServiceExt::GetInstance().NotifyUsbFuseUmount(volumeId);
57 if (result != E_OK) {
58 LOGE("VolumeManagerServiceExt NotifyUsbFuseUmount failed, error = %{public}d", result);
59 }
60 return;
61 }
62 if (!volumeMap_.Contains(volumeId)) {
63 LOGE("VolumeManagerService::OnVolumeDestroyed volumeId %{public}s not exists", volumeId.c_str());
64 return;
65 }
66 std::shared_ptr<VolumeExternal> volumePtr = volumeMap_.ReadVal(volumeId);
67 VolumeStateNotify(state, volumePtr);
68 if (state == VolumeState::REMOVED || state == VolumeState::BAD_REMOVAL) {
69 volumeMap_.Erase(volumeId);
70 }
71 }
72
OnVolumeMounted(const std::string & volumeId,const std::string & fsTypeStr,const std::string & fsUuid,const std::string & path,const std::string & description)73 void VolumeManagerService::OnVolumeMounted(const std::string &volumeId, const std::string &fsTypeStr,
74 const std::string &fsUuid, const std::string &path,
75 const std::string &description)
76 {
77 if (!volumeMap_.Contains(volumeId)) {
78 LOGE("VolumeManagerService::OnVolumeMounted volumeId %{public}s not exists", volumeId.c_str());
79 return;
80 }
81 std::shared_ptr<VolumeExternal> volumePtr = volumeMap_.ReadVal(volumeId);
82 if (volumePtr == nullptr) {
83 LOGE("volumePtr is nullptr for volumeId");
84 return;
85 }
86 volumePtr->SetFsType(volumePtr->GetFsTypeByStr(fsTypeStr));
87 volumePtr->SetFsUuid(fsUuid);
88 volumePtr->SetPath(path);
89 std::string des = description;
90 auto disk = DiskManagerService::GetInstance().GetDiskById(volumePtr->GetDiskId());
91 if (disk != nullptr) {
92 if (des == "") {
93 if (disk->GetFlag() == SD_FLAG) {
94 des = "MySDCard";
95 } else if (disk->GetFlag() == USB_FLAG) {
96 des = "MyUSB";
97 } else {
98 des = "Default";
99 }
100 }
101 volumePtr->SetFlags(disk->GetFlag());
102 }
103 volumePtr->SetDescription(des);
104 volumePtr->SetState(VolumeState::MOUNTED);
105 VolumeStateNotify(VolumeState::MOUNTED, volumePtr);
106 }
107
OnVolumeDamaged(const std::string & volumeId,const std::string & fsTypeStr,const std::string & fsUuid,const std::string & path,const std::string & description)108 void VolumeManagerService::OnVolumeDamaged(const std::string &volumeId, const std::string &fsTypeStr,
109 const std::string &fsUuid, const std::string &path,
110 const std::string &description)
111 {
112 if (!volumeMap_.Contains(volumeId)) {
113 LOGE("VolumeManagerService::OnVolumeDamaged volumeId %{public}s not exists", volumeId.c_str());
114 return;
115 }
116 std::shared_ptr<VolumeExternal> volumePtr = volumeMap_.ReadVal(volumeId);
117 if (volumePtr == nullptr) {
118 LOGE("volumePtr is nullptr for volumeId");
119 return;
120 }
121 volumePtr->SetFsType(volumePtr->GetFsTypeByStr(fsTypeStr));
122 volumePtr->SetFsUuid(fsUuid);
123 volumePtr->SetPath(path);
124 std::string des = description;
125 auto disk = DiskManagerService::GetInstance().GetDiskById(volumePtr->GetDiskId());
126 if (disk != nullptr) {
127 if (des == "") {
128 if (disk->GetFlag() == SD_FLAG) {
129 des = "MySDCard";
130 } else if (disk->GetFlag() == USB_FLAG) {
131 des = "MyUSB";
132 } else {
133 des = "Default";
134 }
135 }
136 volumePtr->SetFlags(disk->GetFlag());
137 }
138 volumePtr->SetDescription(des);
139 VolumeStateNotify(VolumeState::DAMAGED, volumePtr);
140 }
141
Mount(std::string volumeId)142 int32_t VolumeManagerService::Mount(std::string volumeId)
143 {
144 if (!volumeMap_.Contains(volumeId)) {
145 LOGE("VolumeManagerService::Mount volumeId %{public}s not exists", volumeId.c_str());
146 return E_NON_EXIST;
147 }
148 std::shared_ptr<VolumeExternal> volumePtr = volumeMap_.ReadVal(volumeId);
149 if (volumePtr == nullptr) {
150 LOGE("volumePtr is nullptr for volumeId");
151 return E_VOLUMEEX_IS_NULLPTR;
152 }
153 if (volumePtr->GetState() != VolumeState::UNMOUNTED) {
154 LOGE("VolumeManagerService::The type of volume(Id %{public}s) is not unmounted", volumeId.c_str());
155 return E_VOL_MOUNT_ERR;
156 }
157 std::shared_ptr<StorageDaemonCommunication> sdCommunication;
158 sdCommunication = DelayedSingleton<StorageDaemonCommunication>::GetInstance();
159 int32_t result = Check(volumePtr->GetId());
160 if (result != E_OK || sdCommunication == nullptr) {
161 volumePtr->SetState(VolumeState::UNMOUNTED);
162 StorageRadar::ReportVolumeOperation("VolumeManagerService::Check", result);
163 return result;
164 }
165 std::string mountUsbFusePath = StorageDaemon::StringPrintf("/mnt/data/external/%s", volumePtr->GetUuid().c_str());
166 if (StorageDaemon::IsUsbFuse() && !StorageDaemon::IsPathMounted(mountUsbFusePath)) {
167 result = MountUsbFuse(volumeId);
168 if (result != E_OK) {
169 volumePtr->SetState(VolumeState::UNMOUNTED);
170 return result;
171 }
172 }
173
174 result = sdCommunication->Mount(volumeId, 0);
175 if (result != E_OK) {
176 volumePtr->SetState(VolumeState::UNMOUNTED);
177 }
178 return result;
179 }
180
MountUsbFuse(const std::string & volumeId)181 int32_t VolumeManagerService::MountUsbFuse(const std::string &volumeId)
182 {
183 LOGI("VolumeManagerService::MountUsbFuse in");
184 std::shared_ptr<StorageDaemonCommunication> sdCommunication;
185 sdCommunication = DelayedSingleton<StorageDaemonCommunication>::GetInstance();
186 if (sdCommunication == nullptr) {
187 LOGE("sdCommunication is nullptr");
188 return E_PARAMS_NULLPTR_ERR;
189 }
190
191 std::string fsUuid;
192 int32_t fuseFd;
193 int32_t result = sdCommunication->MountUsbFuse(volumeId, fsUuid, fuseFd);
194 if (result == E_OK) {
195 result = VolumeManagerServiceExt::GetInstance().NotifyUsbFuseMount(fuseFd, volumeId, fsUuid);
196 }
197 LOGI("VolumeManagerService::MountUsbFuse out");
198 return result;
199 }
200
Unmount(std::string volumeId)201 int32_t VolumeManagerService::Unmount(std::string volumeId)
202 {
203 if (!volumeMap_.Contains(volumeId)) {
204 LOGE("VolumeManagerService::Unmount volumeId %{public}s not exists", volumeId.c_str());
205 return E_NON_EXIST;
206 }
207 std::shared_ptr<VolumeExternal> volumePtr = volumeMap_.ReadVal(volumeId);
208 if (volumePtr == nullptr) {
209 LOGE("volumePtr is nullptr for volumeId");
210 return E_VOLUMEEX_IS_NULLPTR;
211 }
212 if (volumePtr->GetState() != VolumeState::MOUNTED) {
213 LOGE("VolumeManagerService::The type of volume(Id %{public}s) is not mounted", volumeId.c_str());
214 return E_VOL_UMOUNT_ERR;
215 }
216 std::shared_ptr<StorageDaemonCommunication> sdCommunication;
217 sdCommunication = DelayedSingleton<StorageDaemonCommunication>::GetInstance();
218 if (sdCommunication == nullptr) {
219 LOGE("sdCommunication is nullptr");
220 return E_PARAMS_NULLPTR_ERR;
221 }
222 volumePtr->SetState(VolumeState::EJECTING);
223 int32_t result = sdCommunication->Unmount(volumeId);
224 if (result == E_OK) {
225 volumePtr->SetState(VolumeState::UNMOUNTED);
226 volumePtr->Reset();
227 } else {
228 volumePtr->SetState(VolumeState::MOUNTED);
229 }
230 return result;
231 }
232
TryToFix(std::string volumeId)233 int32_t VolumeManagerService::TryToFix(std::string volumeId)
234 {
235 if (!volumeMap_.Contains(volumeId)) {
236 LOGE("VolumeManagerService::TryToFix volumeId %{public}s not exists", volumeId.c_str());
237 return E_NON_EXIST;
238 }
239 std::shared_ptr<VolumeExternal> volumePtr = volumeMap_.ReadVal(volumeId);
240 if (volumePtr == nullptr) {
241 LOGE("volumePtr is nullptr for volumeId");
242 return E_VOLUMEEX_IS_NULLPTR;
243 }
244 std::shared_ptr<StorageDaemonCommunication> sdCommunication;
245 sdCommunication = DelayedSingleton<StorageDaemonCommunication>::GetInstance();
246 int32_t result = Check(volumePtr->GetId());
247 if (result == E_OK && sdCommunication != nullptr) {
248 result = sdCommunication->TryToFix(volumeId, 0);
249 } else {
250 volumePtr->Reset();
251 StorageRadar::ReportVolumeOperation("VolumeManagerService::DAMAGED", result);
252 }
253 return result;
254 }
255
Check(std::string volumeId)256 int32_t VolumeManagerService::Check(std::string volumeId)
257 {
258 std::shared_ptr<VolumeExternal> volumePtr = volumeMap_.ReadVal(volumeId);
259 if (volumePtr == nullptr) {
260 LOGE("volumePtr is nullptr for volumeId");
261 return E_VOLUMEEX_IS_NULLPTR;
262 }
263 volumePtr->SetState(VolumeState::CHECKING);
264 if (volumePtr->GetFsType() == FsType::MTP) {
265 return E_OK;
266 }
267 std::shared_ptr<StorageDaemonCommunication> sdCommunication;
268 sdCommunication = DelayedSingleton<StorageDaemonCommunication>::GetInstance();
269 if (sdCommunication == nullptr) {
270 LOGE("sdCommunication is nullptr");
271 return E_PARAMS_NULLPTR_ERR;
272 }
273 int32_t result = sdCommunication->Check(volumeId);
274 return result;
275 }
276
GetAllVolumes()277 vector<VolumeExternal> VolumeManagerService::GetAllVolumes()
278 {
279 vector<VolumeExternal> result;
280 for (auto it = volumeMap_.Begin(); it != volumeMap_.End(); ++it) {
281 VolumeExternal vc = *(it->second);
282 result.push_back(vc);
283 }
284 return result;
285 }
286
GetVolumeByUuid(std::string volumeUuid)287 std::shared_ptr<VolumeExternal> VolumeManagerService::GetVolumeByUuid(std::string volumeUuid)
288 {
289 for (auto it = volumeMap_.Begin(); it != volumeMap_.End(); ++it) {
290 auto vc = it->second;
291 if (vc->GetUuid() == volumeUuid) {
292 LOGE("VolumeManagerService::GetVolumeByUuid volumeUuid %{public}s exists",
293 GetAnonyString(volumeUuid).c_str());
294 return vc;
295 }
296 }
297 return nullptr;
298 }
299
GetVolumeByUuid(std::string fsUuid,VolumeExternal & vc)300 int32_t VolumeManagerService::GetVolumeByUuid(std::string fsUuid, VolumeExternal &vc)
301 {
302 for (auto it = volumeMap_.Begin(); it != volumeMap_.End(); ++it) {
303 auto volume = it->second;
304 if (volume->GetUuid() == fsUuid) {
305 LOGI("VolumeManagerService::GetVolumeByUuid volumeUuid %{public}s exists",
306 GetAnonyString(fsUuid).c_str());
307 vc = *volume;
308 return E_OK;
309 }
310 }
311 return E_NON_EXIST;
312 }
313
GetVolumeById(std::string volumeId,VolumeExternal & vc)314 int32_t VolumeManagerService::GetVolumeById(std::string volumeId, VolumeExternal &vc)
315 {
316 if (volumeMap_.Contains(volumeId)) {
317 vc = *volumeMap_.ReadVal(volumeId);
318 return E_OK;
319 }
320 return E_NON_EXIST;
321 }
322
SetVolumeDescription(std::string fsUuid,std::string description)323 int32_t VolumeManagerService::SetVolumeDescription(std::string fsUuid, std::string description)
324 {
325 for (auto it = volumeMap_.Begin(); it != volumeMap_.End(); ++it) {
326 auto volume = it->second;
327 if (volume->GetUuid() == fsUuid) {
328 LOGI("VolumeManagerService::SetVolumeDescription volumeUuid %{public}s exists",
329 GetAnonyString(fsUuid).c_str());
330 if (volume->GetState() != VolumeState::UNMOUNTED) {
331 LOGE("VolumeManagerService::SetVolumeDescription volume state is not unmounted!");
332 return E_VOL_STATE;
333 }
334 std::shared_ptr<StorageDaemonCommunication> sdCommunication;
335 sdCommunication = DelayedSingleton<StorageDaemonCommunication>::GetInstance();
336 if (sdCommunication == nullptr) {
337 LOGE("sdCommunication is nullptr");
338 return E_PARAMS_NULLPTR_ERR;
339 }
340 return sdCommunication->SetVolumeDescription(volume->GetId(), description);
341 }
342 }
343 return E_NON_EXIST;
344 }
345
Format(std::string volumeId,std::string fsType)346 int32_t VolumeManagerService::Format(std::string volumeId, std::string fsType)
347 {
348 if (volumeMap_.Find(volumeId) == volumeMap_.End()) {
349 return E_NON_EXIST;
350 }
351 std::shared_ptr<VolumeExternal> volumePtr = volumeMap_.ReadVal(volumeId);
352 if ((volumePtr != nullptr) && (volumePtr->GetFsType() == FsType::MTP)) {
353 LOGE("MTP device not support to format.");
354 return E_NOT_SUPPORT;
355 }
356 if (volumeMap_.ReadVal(volumeId)->GetState() != VolumeState::UNMOUNTED) {
357 LOGE("VolumeManagerService::SetVolumeDescription volume state is not unmounted!");
358 return E_VOL_STATE;
359 }
360 // check fstype!!!!
361 std::shared_ptr<StorageDaemonCommunication> sdCommunication;
362 sdCommunication = DelayedSingleton<StorageDaemonCommunication>::GetInstance();
363 if (sdCommunication == nullptr) {
364 LOGE("sdCommunication is nullptr");
365 return E_PARAMS_NULLPTR_ERR;
366 }
367 int32_t result = sdCommunication->Format(volumeId, fsType);
368 if (result != E_OK) {
369 return result;
370 }
371
372 if (StorageDaemon::IsUsbFuse()) {
373 result = VolumeManagerServiceExt::GetInstance().NotifyUsbFuseUmount(volumeId);
374 }
375 return result;
376 }
377
NotifyMtpMounted(const std::string & id,const std::string & path,const std::string & desc,const std::string & uuid)378 void VolumeManagerService::NotifyMtpMounted(const std::string &id, const std::string &path, const std::string &desc,
379 const std::string &uuid)
380 {
381 LOGI("VolumeManagerService NotifyMtpMounted");
382 std::string key = "user.getfriendlyname";
383 char *value = (char *)malloc(sizeof(char) * MTP_DEVICE_NAME_LEN);
384 int32_t len = 0;
385 if (value != nullptr) {
386 len = getxattr(path.c_str(), key.c_str(), value, MTP_DEVICE_NAME_LEN);
387 if (len >= 0 && len < MTP_DEVICE_NAME_LEN) {
388 value[len] = '\0';
389 LOGI("MTP get namelen=%{public}d, name=%{public}s", len, value);
390 }
391 }
392
393 VolumeCore core(id, 0, "");
394 auto volumePtr = make_shared<VolumeExternal>(core);
395 volumePtr->SetPath(path);
396 volumePtr->SetFsType(volumePtr->GetFsTypeByStr("mtp"));
397 volumePtr->SetDescription(desc);
398 if (len > 0) {
399 LOGI("set MTP device name:%{public}s", value);
400 volumePtr->SetDescription(std::string(value));
401 }
402 if (value != nullptr) {
403 free(value);
404 value = nullptr;
405 }
406 volumePtr->SetState(MOUNTED);
407 volumePtr->SetFsUuid(uuid);
408 volumeMap_.Insert(volumePtr->GetId(), volumePtr);
409 VolumeStateNotify(VolumeState::MOUNTED, volumePtr);
410 }
411
NotifyMtpUnmounted(const std::string & id,const std::string & path,const bool isBadRemove)412 void VolumeManagerService::NotifyMtpUnmounted(const std::string &id, const std::string &path, const bool isBadRemove)
413 {
414 LOGI("VolumeManagerService NotifyMtpUnmounted");
415 if (!volumeMap_.Contains(id)) {
416 LOGE("VolumeManagerService::Unmount id %{public}s not exists", id.c_str());
417 return;
418 }
419 std::shared_ptr<VolumeExternal> volumePtr = volumeMap_.ReadVal(id);
420 if (volumePtr == nullptr) {
421 LOGE("volumePtr is nullptr for id");
422 return;
423 }
424 if (!isBadRemove) {
425 VolumeStateNotify(VolumeState::UNMOUNTED, volumePtr);
426 } else {
427 VolumeStateNotify(VolumeState::BAD_REMOVAL, volumePtr);
428 }
429
430 volumeMap_.Erase(id);
431 }
432 } // StorageManager
433 } // OHOS
434