• 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 "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 
36 enum class Table {
37     UNKNOWN,
38     MBR,
39     GPT,
40 };
41 
DiskInfo(std::string sysPath,std::string devPath,dev_t device,int flag)42 DiskInfo::DiskInfo(std::string sysPath, std::string devPath, dev_t device, int flag)
43 {
44     id_ = StringPrintf("disk-%d-%d", major(device), minor(device));
45     sysPath_ = sysPath;
46     eventPath_ = devPath;
47     devPath_ = StringPrintf("/dev/block/%s", id_.c_str());
48     device_ = device;
49     flags_ = static_cast<unsigned int>(flag);
50     status = sInital;
51 }
52 
GetDevice() const53 dev_t DiskInfo::GetDevice() const
54 {
55     return device_;
56 }
57 
GetId() const58 std::string DiskInfo::GetId() const
59 {
60     return id_;
61 }
62 
GetDevPath() const63 std::string DiskInfo::GetDevPath() const
64 {
65     return devPath_;
66 }
67 
GetDevDSize() const68 uint64_t DiskInfo::GetDevDSize() const
69 {
70     return size_;
71 }
72 
GetSysPath() const73 std::string DiskInfo::GetSysPath() const
74 {
75     return sysPath_;
76 }
77 
GetDevVendor() const78 std::string DiskInfo::GetDevVendor() const
79 {
80     return vendor_;
81 }
82 
GetDevFlag() const83 int DiskInfo::GetDevFlag() const
84 {
85     return flags_;
86 }
87 
~DiskInfo()88 DiskInfo::~DiskInfo()
89 {
90     DestroyDiskNode(devPath_);
91 }
92 
Create()93 int DiskInfo::Create()
94 {
95     int ret;
96 
97     CreateDiskNode(devPath_, device_);
98     status = sCreate;
99     ReadMetadata();
100 
101     StorageManagerClient client;
102     ret = client.NotifyDiskCreated(*this);
103     if (ret != E_OK) {
104         LOGE("Notify Disk Created failed");
105         return ret;
106     }
107 
108     ret = ReadPartition();
109     if (ret != E_OK) {
110         LOGE("Create disk failed");
111         return ret;
112     }
113 
114     return E_OK;
115 }
116 
Destroy()117 int DiskInfo::Destroy()
118 {
119     int ret;
120     auto volume = VolumeManager::Instance();
121 
122     for (auto volumeId : volumeId_) {
123         ret = volume->DestroyVolume(volumeId);
124         if (ret != E_OK) {
125             LOGE("Destroy volume %{public}s failed", volumeId.c_str());
126             return E_ERR;
127         }
128     }
129     status = sDestroy;
130     volumeId_.clear();
131     return E_OK;
132 }
133 
ReadMetadata()134 void DiskInfo::ReadMetadata()
135 {
136     size_ = -1;
137     vendor_.clear();
138     if (GetDevSize(devPath_, &size_) != E_OK) {
139         size_ = -1;
140     }
141 
142     unsigned int majorId = major(device_);
143     if (majorId == DISK_MMC_MAJOR) {
144         std::string path(sysPath_ + "/device/manfid");
145         std::string str;
146         if (!ReadFile(path, &str)) {
147             LOGE("open file %{public}s failed", path.c_str());
148             return;
149         }
150         int manfid = std::stoi(str);
151         switch (manfid) {
152             case 0x000003: {
153                 vendor_ = "SanDisk";
154                 break;
155             }
156             case 0x00001b: {
157                 vendor_ = "SamSung";
158                 break;
159             }
160             case 0x000028: {
161                 vendor_ = "Lexar";
162                 break;
163             }
164             case 0x000074: {
165                 vendor_ = "Transcend";
166                 break;
167             }
168             default : {
169                 vendor_ = "Unknown";
170                 LOGI("Unknown vendor information: %{public}d", manfid);
171                 break;
172             }
173         }
174     } else {
175         std::string path(sysPath_ + "/device/vendor");
176         std::string str;
177         if (!ReadFile(path, &str)) {
178             LOGE("open file %{public}s failed", path.c_str());
179             return;
180         }
181         vendor_ = str;
182     LOGI("Read metadata %{public}s", path.c_str());
183     }
184 }
185 
ReadPartition()186 int DiskInfo::ReadPartition()
187 {
188     int maxVolumes = GetMaxVolume(device_);
189     if (maxVolumes < 0) {
190         LOGE("Invaild maxVolumes");
191         return E_ERR;
192     }
193 
194     std::vector<std::string> cmd;
195     std::vector<std::string> output;
196     std::vector<std::string> lines;
197     int res;
198 
199     cmd.push_back(SGDISK_PATH);
200     cmd.push_back(SGDISK_DUMP_CMD);
201     cmd.push_back(devPath_);
202     res = ForkExec(cmd, &output);
203     if (res != E_OK) {
204         LOGE("get %{private}s partition failed", devPath_.c_str());
205         return res;
206     }
207     std::string bufToken = "\n";
208     for (auto &buf : output) {
209         auto split = SplitLine(buf, bufToken);
210         for (auto &tmp : split)
211             lines.push_back(tmp);
212     }
213 
214     std::string lineToken = " ";
215     status = sScan;
216     bool foundPart = false;
217     Table table = Table::UNKNOWN;
218     for (auto &line : lines) {
219         auto split = SplitLine(line, lineToken);
220         auto it = split.begin();
221         if (it == split.end()) {
222             continue;
223         }
224         if (*it == "DISK") {
225             if (++it == split.end()) {
226                 continue;
227             }
228             if (*it == "mbr") {
229                 table = Table::MBR;
230             } else if (*it == "gpt") {
231                 table = Table::GPT;
232             } else {
233                 LOGI("Unknown partition table %{public}s", (*it).c_str());
234                 continue;
235             }
236         } else if (*it == "PART") {
237             if (++it == split.end()) {
238                 continue;
239             }
240             int32_t index = std::stoi(*it);
241             if (index > maxVolumes || index < 1) {
242                 LOGE("Invalid partition %{public}d", index);
243                 continue;
244             }
245             dev_t partitionDev = makedev(major(device_), minor(device_) + static_cast<uint32_t>(index));
246             res = CreateVolume(partitionDev);
247             if (res == E_OK) {
248                 foundPart = true;
249             }
250         }
251     }
252     if (table == Table::UNKNOWN || !foundPart) {
253         LOGI("%{public}s has unknown table", id_.c_str());
254         std::string fsType;
255         std::string uuid;
256         std::string label;
257         if (OHOS::StorageDaemon::ReadMetadata(devPath_, fsType, uuid, label) == E_OK) {
258             CreateVolume(device_);
259         } else {
260             LOGE("failed to identify the disk device");
261             return E_NON_EXIST;
262         }
263     }
264     return E_OK;
265 }
266 
CreateVolume(dev_t dev)267 int DiskInfo::CreateVolume(dev_t dev)
268 {
269     auto volume = VolumeManager::Instance();
270 
271     LOGI("disk read volume metadata");
272     std::string volumeId = volume->CreateVolume(GetId(), dev);
273     if (volumeId == "") {
274         LOGE("Create volume failed");
275         return E_ERR;
276     }
277 
278     volumeId_.push_back(volumeId);
279     return E_OK;
280 }
281 
Partition()282 int DiskInfo::Partition()
283 {
284     std::vector<std::string> cmd;
285     int res;
286 
287     res = Destroy();
288     if (res != E_OK) {
289         LOGE("Destroy failed in Partition()");
290     }
291 
292     cmd.push_back(SGDISK_PATH);
293     cmd.push_back(SGDISK_ZAP_CMD);
294     cmd.push_back(devPath_);
295     res = ForkExec(cmd);
296     if (res != E_OK) {
297         LOGE("sgdisk: zap fail");
298         return res;
299     }
300 
301     cmd.clear();
302     cmd.push_back(SGDISK_PATH);
303     cmd.push_back(SGDISK_PART_CMD);
304     cmd.push_back(devPath_);
305     res = ForkExec(cmd);
306     if (res != E_OK) {
307         LOGE("sgdisk: partition fail");
308         return res;
309     }
310 
311     return E_OK;
312 }
313 } // namespace STORAGE_DAEMON
314 } // namespace OHOS
315