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