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