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/external_volume_info.h"
17
18 #include <algorithm>
19 #include <cerrno>
20 #include <csignal>
21 #include <cstdlib>
22 #include <cstring>
23 #include <sys/mount.h>
24 #include <sys/stat.h>
25 #include <sys/wait.h>
26 #include <unistd.h>
27
28 #include "storage_service_errno.h"
29 #include "storage_service_log.h"
30 #include "utils/disk_utils.h"
31 #include "utils/file_utils.h"
32 #include "utils/string_utils.h"
33 #include "volume/process.h"
34
35 using namespace std;
36 namespace OHOS {
37 namespace StorageDaemon {
ReadMetadata()38 int32_t ExternalVolumeInfo::ReadMetadata()
39 {
40 int32_t ret = OHOS::StorageDaemon::ReadMetadata(devPath_, fsUuid_, fsType_, fsLabel_);
41 if (fsType_ == "ntfs") {
42 std::vector<std::string> cmd;
43 cmd = {
44 "ntfslabel",
45 devPath_
46 };
47 fsLabel_ = GetBlkidDataByCmd(cmd);
48 }
49 return ret;
50 }
51
GetFsType()52 int32_t ExternalVolumeInfo::GetFsType()
53 {
54 for (uint32_t i = 0; i < supportMountType_.size(); i++) {
55 if (supportMountType_[i].compare(fsType_) == 0) {
56 return i;
57 }
58 }
59 return -1;
60 }
61
GetFsUuid()62 std::string ExternalVolumeInfo::GetFsUuid()
63 {
64 return fsUuid_;
65 }
66
GetFsLabel()67 std::string ExternalVolumeInfo::GetFsLabel()
68 {
69 return fsLabel_;
70 }
71
GetMountPath()72 std::string ExternalVolumeInfo::GetMountPath()
73 {
74 return mountPath_;
75 }
76
DoCreate(dev_t dev)77 int32_t ExternalVolumeInfo::DoCreate(dev_t dev)
78 {
79 int32_t ret = 0;
80 string id = VolumeInfo::GetVolumeId();
81
82 device_ = dev;
83 devPath_ = StringPrintf(devPathDir_.c_str(), (id).c_str());
84
85 ret = mknod(devPath_.c_str(), S_IFBLK, dev);
86 if (ret) {
87 LOGE("External volume DoCreate error.");
88 return E_ERR;
89 }
90
91 return E_OK;
92 }
93
DoDestroy()94 int32_t ExternalVolumeInfo::DoDestroy()
95 {
96 int err = remove(devPath_.c_str());
97 if (err) {
98 LOGE("External volume DoDestroy error.");
99 return E_ERR;
100 }
101 return E_OK;
102 }
103
DoMount(uint32_t mountFlags)104 int32_t ExternalVolumeInfo::DoMount(uint32_t mountFlags)
105 {
106 int32_t ret = 0;
107 mode_t mode = 0777;
108 struct stat statbuf;
109
110 if (GetFsType() == -1) {
111 return E_NOT_SUPPORT;
112 }
113
114 ret = ReadMetadata();
115 if (ret) {
116 LOGE("External volume ReadMetadata failed.");
117 return E_ERR;
118 }
119 mountPath_ = StringPrintf(mountPathDir_.c_str(), fsUuid_.c_str());
120
121 // check if dir exists
122 ret = lstat(mountPath_.c_str(), &statbuf);
123 if (!ret) {
124 LOGE("volume mount path %{public}s exists, please remove first", GetMountPath().c_str());
125 return E_MOUNT;
126 }
127
128 ret = mkdir(mountPath_.c_str(), S_IRWXU | S_IRWXG | S_IXOTH);
129 if (ret) {
130 LOGE("the volume %{public}s create mount file %{public}s failed",
131 GetVolumeId().c_str(), GetMountPath().c_str());
132 return E_MOUNT;
133 }
134
135 auto mountData = StringPrintf("uid=%d,gid=%d,dmask=0007,fmask=0007", UID_FILE_MANAGER, UID_FILE_MANAGER);
136 if (fsType_ == "ext2" || fsType_ == "ext3" || fsType_ == "ext4") {
137 ret = mount(devPath_.c_str(), mountPath_.c_str(), fsType_.c_str(), mountFlags, "");
138 if (!ret) {
139 TravelChmod(mountPath_, mode);
140 }
141 } else if (fsType_ == "ntfs") {
142 if (mountFlags & MS_RDONLY) {
143 mountData = StringPrintf("ro,uid=%d,gid=%d,dmask=0007,fmask=0007", UID_FILE_MANAGER, UID_FILE_MANAGER);
144 } else {
145 mountData = StringPrintf("rw,uid=%d,gid=%d,dmask=0007,fmask=0007", UID_FILE_MANAGER, UID_FILE_MANAGER);
146 }
147 std::vector<std::string> cmd = {
148 "mount.ntfs",
149 devPath_,
150 mountPath_,
151 "-o",
152 mountData.c_str()
153 };
154 ret = ForkExec(cmd);
155 } else {
156 mountFlags |= MS_MGC_VAL;
157 ret = mount(devPath_.c_str(), mountPath_.c_str(), fsType_.c_str(), mountFlags, mountData.c_str());
158 }
159
160 if (ret) {
161 LOGE("External volume DoMount error.");
162 remove(mountPath_.c_str());
163 return E_MOUNT;
164 }
165
166 return E_OK;
167 }
168
DoUMount(bool force)169 int32_t ExternalVolumeInfo::DoUMount(bool force)
170 {
171 if (force) {
172 LOGI("External volume start force to unmount.");
173 Process ps(mountPath_);
174 ps.UpdatePidByPath();
175 ps.KillProcess(SIGKILL);
176 umount2(mountPath_.c_str(), MNT_DETACH);
177 remove(mountPath_.c_str());
178 return E_OK;
179 }
180
181 int ret = umount(mountPath_.c_str());
182 int err = remove(mountPath_.c_str());
183 if (err && ret) {
184 LOGE("External volume DoUmount error.");
185 return E_UMOUNT;
186 }
187
188 if (err) {
189 LOGE("failed to call remove(%{public}s) error, errno = %{public}d", mountPath_.c_str(), errno);
190 return E_SYS_CALL;
191 }
192 return E_OK;
193 }
194
DoCheck()195 int32_t ExternalVolumeInfo::DoCheck()
196 {
197 int32_t ret = ExternalVolumeInfo::ReadMetadata();
198 if (ret) {
199 LOGE("External volume uuid=%{public}s DoCheck failed.", GetFsUuid().c_str());
200 return E_ERR;
201 }
202
203 // check fstype
204 if (GetFsType() == -1) {
205 LOGE("External Volume type not support.");
206 return E_NOT_SUPPORT;
207 }
208 return E_OK;
209 }
210
DoFormat(std::string type)211 int32_t ExternalVolumeInfo::DoFormat(std::string type)
212 {
213 int32_t err = 0;
214 std::map<std::string, std::string>::iterator iter = supportFormatType_.find(type);
215 if (iter == supportFormatType_.end()) {
216 LOGE("External volume format not support.");
217 return E_NOT_SUPPORT;
218 }
219
220 if (type == "vfat") {
221 std::vector<std::string> cmd = {
222 iter->second,
223 "-A",
224 devPath_
225 };
226 err = ForkExec(cmd);
227 } else {
228 std::vector<std::string> cmd = {
229 iter->second,
230 devPath_
231 };
232 err = ForkExec(cmd);
233 }
234
235 if (err == E_NO_CHILD) {
236 err = E_OK;
237 }
238
239 ReadMetadata();
240 return err;
241 }
242
DoSetVolDesc(std::string description)243 int32_t ExternalVolumeInfo::DoSetVolDesc(std::string description)
244 {
245 int32_t err = 0;
246 if (fsType_ == "ntfs") {
247 std::vector<std::string> cmd = {
248 "ntfslabel",
249 devPath_,
250 description
251 };
252 err = ForkExec(cmd);
253 } else if (fsType_ == "exfat") {
254 std::vector<std::string> cmd = {
255 "exfatlabel",
256 devPath_,
257 description
258 };
259 err = ForkExec(cmd);
260 } else if (fsType_ == "vfat") {
261 std::vector<std::string> cmd = {
262 "newfs_msdos",
263 "-L",
264 description,
265 devPath_
266 };
267 err = ForkExec(cmd);
268 } else {
269 LOGE("SetVolumeDescription fsType not support.");
270 return E_NOT_SUPPORT;
271 }
272
273 ReadMetadata();
274 return err;
275 }
276 } // StorageDaemon
277 } // OHOS
278