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