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_info.h"
17
18 #include <sys/mount.h>
19
20 #include "ipc/storage_manager_client.h"
21 #include "storage_service_errno.h"
22 #include "storage_service_log.h"
23 #include "utils/storage_radar.h"
24 #include "parameter.h"
25
26 using namespace std;
27 using namespace OHOS::StorageService;
28 namespace OHOS {
29 namespace StorageDaemon {
30 constexpr int32_t TRUE_LEN = 5;
Create(const std::string volId,const std::string diskId,dev_t device)31 int32_t VolumeInfo::Create(const std::string volId, const std::string diskId, dev_t device)
32 {
33 id_ = volId;
34 diskId_ = diskId;
35 type_ = EXTERNAL;
36 mountState_ = UNMOUNTED;
37 mountFlags_ = 0;
38 userIdOwner_ = 0;
39
40 int32_t err = DoCreate(device);
41 if (err) {
42 return err;
43 }
44 return E_OK;
45 }
46
GetVolumeId()47 std::string VolumeInfo::GetVolumeId()
48 {
49 return id_;
50 }
51
GetVolumeType()52 int32_t VolumeInfo::GetVolumeType()
53 {
54 return type_;
55 }
56
GetDiskId()57 std::string VolumeInfo::GetDiskId()
58 {
59 return diskId_;
60 }
61
GetState()62 int32_t VolumeInfo::GetState()
63 {
64 return mountState_;
65 }
66
Destroy()67 int32_t VolumeInfo::Destroy()
68 {
69 VolumeState state = REMOVED;
70 if (mountState_ == REMOVED || mountState_ == BADREMOVABLE) {
71 return E_OK;
72 }
73 StorageManagerClient client;
74 if (mountState_ != UNMOUNTED) {
75 // force umount
76 UMount(true);
77 state = BADREMOVABLE;
78 if (client.NotifyVolumeStateChanged(id_, StorageManager::VolumeState::BAD_REMOVAL) != E_OK) {
79 LOGE("Volume Notify Bad Removal failed");
80 }
81 } else {
82 if (client.NotifyVolumeStateChanged(id_, StorageManager::VolumeState::REMOVED) != E_OK) {
83 LOGE("Volume Notify Removed failed");
84 }
85 }
86
87 int32_t err = DoDestroy();
88 if (err) {
89 return err;
90 }
91 mountState_ = state;
92 return E_OK;
93 }
94
Mount(uint32_t flags)95 int32_t VolumeInfo::Mount(uint32_t flags)
96 {
97 int32_t err = 0;
98
99 if (mountState_ == MOUNTED) {
100 return E_OK;
101 }
102 if (mountState_ != CHECKING) {
103 LOGE("please check volume %{public}s first", GetVolumeId().c_str());
104 return E_VOL_STATE;
105 }
106
107 std::string key = "persist.filemanagement.usb.readonly";
108 int handle = static_cast<int>(FindParameter(key.c_str()));
109 if (handle != -1) {
110 char rdOnlyEnable[255] = {"false"};
111 auto res = GetParameterValue(handle, rdOnlyEnable, 255);
112 if (res >= 0 && strncmp(rdOnlyEnable, "true", TRUE_LEN) == 0) {
113 mountFlags_ |= MS_RDONLY;
114 } else {
115 mountFlags_ &= ~MS_RDONLY;
116 }
117 }
118
119 mountFlags_ |= flags;
120 LOGI("external volume mount start");
121 err = DoMount(mountFlags_);
122 if (err) {
123 mountState_ = UNMOUNTED;
124 StorageRadar::ReportVolumeOperation("VolumeInfo::DoMount", err);
125 return err;
126 }
127 LOGI("external volume mount success");
128 mountState_ = MOUNTED;
129 return E_OK;
130 }
131
UMount(bool force)132 int32_t VolumeInfo::UMount(bool force)
133 {
134 int32_t err = 0;
135
136 if (mountState_ == REMOVED || mountState_ == BADREMOVABLE) {
137 LOGE("the volume %{public}s is in REMOVED state", GetVolumeId().c_str());
138 return E_VOL_STATE;
139 }
140
141 if (mountState_ == UNMOUNTED) {
142 return E_OK;
143 }
144
145 if (mountState_ == CHECKING) {
146 mountState_ = UNMOUNTED;
147 return E_OK;
148 }
149
150 if (mountState_ == EJECTING && !force) {
151 return E_UMOUNT_BUSY;
152 }
153
154 mountState_ = EJECTING;
155 StorageManagerClient client;
156 if (client.NotifyVolumeStateChanged(id_, StorageManager::VolumeState::EJECTING) != E_OK) {
157 LOGE("Volume Notify Ejecting failed");
158 }
159
160 err = DoUMount(force);
161 if (!force && err) {
162 mountState_ = MOUNTED;
163 return err;
164 }
165
166 mountState_ = UNMOUNTED;
167 if (client.NotifyVolumeStateChanged(id_, StorageManager::VolumeState::UNMOUNTED) != E_OK) {
168 LOGE("Volume Notify Unmounted failed");
169 }
170 return E_OK;
171 }
172
Check()173 int32_t VolumeInfo::Check()
174 {
175 if (mountState_ != UNMOUNTED) {
176 LOGE("the volume %{public}s is not in UNMOUNT state", GetVolumeId().c_str());
177 return E_VOL_STATE;
178 }
179
180 if (mountState_ == CHECKING) {
181 mountState_ = UNMOUNTED;
182 }
183
184 int32_t err = DoCheck();
185 if (err) {
186 return err;
187 }
188 mountState_ = CHECKING;
189 return E_OK;
190 }
191
Format(std::string type)192 int32_t VolumeInfo::Format(std::string type)
193 {
194 if (mountState_ != UNMOUNTED) {
195 LOGE("Please unmount the volume %{public}s first", GetVolumeId().c_str());
196 return E_VOL_STATE;
197 }
198
199 int32_t err = DoFormat(type);
200 if (err != E_OK) {
201 StorageRadar::ReportVolumeOperation("VolumeInfo::DoFormat", err);
202 }
203 return err;
204 }
205
SetVolumeDescription(const std::string description)206 int32_t VolumeInfo::SetVolumeDescription(const std::string description)
207 {
208 if (mountState_ != UNMOUNTED) {
209 LOGE("Please unmount the volume %{public}s first", GetVolumeId().c_str());
210 return E_VOL_STATE;
211 }
212
213 int32_t err = DoSetVolDesc(description);
214 if (err != E_OK) {
215 StorageRadar::ReportVolumeOperation("VolumeInfo::DoSetVolDesc", err);
216 }
217 return err;
218 }
219 } // StorageDaemon
220 } // OHOS
221