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 "disk/disk_info.h"
17
18 #include <sys/sysmacros.h>
19
20 #include "disk/disk_manager.h"
21 #include "ipc/storage_manager_client.h"
22 #include "storage_service_errno.h"
23 #include "storage_service_log.h"
24 #include "utils/disk_utils.h"
25 #include "utils/file_utils.h"
26 #include "utils/string_utils.h"
27 #include "volume/volume_manager.h"
28
29 namespace OHOS {
30 namespace StorageDaemon {
31 const std::string SGDISK_PATH = "/system/bin/sgdisk";
32 const std::string SGDISK_DUMP_CMD = "--ohos-dump";
33 const std::string SGDISK_ZAP_CMD = "--zap-all";
34 const std::string SGDISK_PART_CMD = "--new=0:0:-0 --typeconde=0:0c00 --gpttombr=1";
35
DiskInfo(std::string sysPath,std::string devPath,dev_t device,int flag)36 DiskInfo::DiskInfo(std::string sysPath, std::string devPath, dev_t device, int flag)
37 {
38 id_ = StringPrintf("disk-%d-%d", major(device), minor(device));
39 sysPath_ = sysPath;
40 eventPath_ = devPath;
41 devPath_ = StringPrintf("/dev/block/%s", id_.c_str());
42 device_ = device;
43 flags_ = static_cast<unsigned int>(flag);
44 status = sInital;
45 }
46
GetDevice() const47 dev_t DiskInfo::GetDevice() const
48 {
49 return device_;
50 }
51
GetId() const52 std::string DiskInfo::GetId() const
53 {
54 return id_;
55 }
56
GetDevPath() const57 std::string DiskInfo::GetDevPath() const
58 {
59 return devPath_;
60 }
61
GetDevDSize() const62 uint64_t DiskInfo::GetDevDSize() const
63 {
64 return size_;
65 }
66
GetSysPath() const67 std::string DiskInfo::GetSysPath() const
68 {
69 return sysPath_;
70 }
71
GetDevVendor() const72 std::string DiskInfo::GetDevVendor() const
73 {
74 return vendor_;
75 }
76
GetDevFlag() const77 int DiskInfo::GetDevFlag() const
78 {
79 return flags_;
80 }
81
~DiskInfo()82 DiskInfo::~DiskInfo()
83 {
84 DestroyDiskNode(devPath_);
85 }
86
Create()87 int DiskInfo::Create()
88 {
89 int ret;
90
91 CreateDiskNode(devPath_, device_);
92 status = sCreate;
93 ReadMetadata();
94
95 StorageManagerClient client;
96 ret = client.NotifyDiskCreated(*this);
97 if (ret != E_OK) {
98 LOGE("Notify Disk Created failed");
99 return ret;
100 }
101
102 ret = ReadPartition();
103 if (ret != E_OK) {
104 LOGE("Create disk failed");
105 return ret;
106 }
107
108 return E_OK;
109 }
110
Destroy()111 int DiskInfo::Destroy()
112 {
113 int ret;
114 auto volume = VolumeManager::Instance();
115
116 for (auto volumeId : volumeId_) {
117 ret = volume->DestroyVolume(volumeId);
118 if (ret != E_OK) {
119 LOGE("Destroy volume %{public}s failed", volumeId.c_str());
120 return E_ERR;
121 }
122 }
123 status = sDestroy;
124 volumeId_.clear();
125 return E_OK;
126 }
127
ReadMetadata()128 void DiskInfo::ReadMetadata()
129 {
130 size_ = -1;
131 vendor_.clear();
132 if (GetDevSize(devPath_, &size_) != E_OK) {
133 size_ = -1;
134 }
135
136 unsigned int majorId = major(device_);
137 if (majorId == DISK_MMC_MAJOR) {
138 std::string path(sysPath_ + "/device/manfid");
139 std::string str;
140 if (!ReadFile(path, &str)) {
141 LOGE("open file %{public}s failed", path.c_str());
142 return;
143 }
144 int manfid = std::stoi(str);
145 switch (manfid) {
146 case 0x000003: {
147 vendor_ = "SanDisk";
148 break;
149 }
150 case 0x00001b: {
151 vendor_ = "SamSung";
152 break;
153 }
154 case 0x000028: {
155 vendor_ = "Lexar";
156 break;
157 }
158 case 0x000074: {
159 vendor_ = "Transcend";
160 break;
161 }
162 default : {
163 vendor_ = "Unknown";
164 LOGI("Unknown vendor information: %{public}d", manfid);
165 break;
166 }
167 }
168 } else {
169 std::string path(sysPath_ + "/device/vendor");
170 std::string str;
171 if (!ReadFile(path, &str)) {
172 LOGE("open file %{public}s failed", path.c_str());
173 return;
174 }
175 vendor_ = str;
176 LOGI("Read metadata %{public}s", path.c_str());
177 }
178 }
179
ReadPartition()180 int DiskInfo::ReadPartition()
181 {
182 int maxVolumes = GetMaxVolume(device_);
183 if (maxVolumes < 0) {
184 LOGE("Invaild maxVolumes");
185 return E_ERR;
186 }
187
188 std::vector<std::string> cmd;
189 std::vector<std::string> output;
190 std::vector<std::string> lines;
191 int res;
192
193 cmd.push_back(SGDISK_PATH);
194 cmd.push_back(SGDISK_DUMP_CMD);
195 cmd.push_back(devPath_);
196 res = ForkExec(cmd, &output);
197 if (res != E_OK) {
198 LOGE("get %{private}s partition failed", devPath_.c_str());
199 return res;
200 }
201 std::string bufToken = "\n";
202 for (auto &buf : output) {
203 auto split = SplitLine(buf, bufToken);
204 for (auto &tmp : split)
205 lines.push_back(tmp);
206 }
207
208 std::string lineToken = " ";
209 status = sScan;
210 for (auto &line : lines) {
211 auto split = SplitLine(line, lineToken);
212 auto it = split.begin();
213 if (it == split.end()) {
214 continue;
215 }
216 if (*it == "DISK") {
217 continue;
218 } else if (*it == "PART") {
219 if (++it == split.end()) {
220 continue;
221 }
222 int32_t index = std::stoi(*it);
223 if (index > maxVolumes || index < 1) {
224 LOGE("Invalid partition %{public}d", index);
225 continue;
226 }
227 dev_t partitionDev = makedev(major(device_), minor(device_) + static_cast<uint32_t>(index));
228 res = CreateVolume(partitionDev);
229 if (res != E_OK) {
230 return res;
231 }
232 }
233 }
234 return E_OK;
235 }
236
CreateVolume(dev_t dev)237 int DiskInfo::CreateVolume(dev_t dev)
238 {
239 auto volume = VolumeManager::Instance();
240
241 LOGI("disk read volume metadata");
242 std::string volumeId = volume->CreateVolume(GetId(), dev);
243 if (volumeId == "") {
244 LOGE("Create volume failed");
245 return E_ERR;
246 }
247
248 volumeId_.push_back(volumeId);
249 return E_OK;
250 }
251
Partition()252 int DiskInfo::Partition()
253 {
254 std::vector<std::string> cmd;
255 int res;
256
257 res = Destroy();
258 if (res != E_OK) {
259 LOGE("Destroy failed in Partition()");
260 }
261
262 cmd.push_back(SGDISK_PATH);
263 cmd.push_back(SGDISK_ZAP_CMD);
264 cmd.push_back(devPath_);
265 res = ForkExec(cmd);
266 if (res != E_OK) {
267 LOGE("sgdisk: zap fail");
268 return res;
269 }
270
271 cmd.clear();
272 cmd.push_back(SGDISK_PATH);
273 cmd.push_back(SGDISK_PART_CMD);
274 cmd.push_back(devPath_);
275 res = ForkExec(cmd);
276 if (res != E_OK) {
277 LOGE("sgdisk: partition fail");
278 return res;
279 }
280
281 return E_OK;
282 }
283 } // namespace STORAGE_DAEMON
284 } // namespace OHOS
285