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