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