• 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 #include "fs_manager/partitions.h"
16 #include <cstdlib>
17 #include <string>
18 #include <sys/stat.h>
19 #include <sys/sysmacros.h>
20 #include <unistd.h>
21 #include "log/log.h"
22 #include "partition_const.h"
23 #include "securec.h"
24 
25 namespace Updater {
26 static struct Disk *g_disks;
DeviceStat(const BlockDevice & dev,struct stat & devStat)27 static int DeviceStat(const BlockDevice &dev, struct stat &devStat)
28 {
29     int ret = 0;
30     if (!stat (dev.devPath.c_str(), &devStat)) {
31         ret = 1;
32     }
33     if (stat (dev.devPath.c_str(), &devStat) != EOK) {
34         LOG(ERROR) << "stat error: " << errno << std::endl;
35         ret = 0;
36     }
37     return ret;
38 }
39 
DeviceProbeType(BlockDevice & dev)40 static int DeviceProbeType(BlockDevice &dev)
41 {
42     struct stat devStat {};
43     int devMajor;
44     int devMinor;
45     BlockSpecific *specific = BLOCK_SPECIFIC(&dev);
46     if (DeviceStat(dev, devStat) == 0) {
47         return 0;
48     }
49 
50     devMajor = static_cast<int>(major (devStat.st_rdev));
51     specific->major = devMajor;
52     devMinor = static_cast<int>(minor (devStat.st_rdev));
53     specific->minor = devMinor;
54     bool a1 = SCSI_BLK_MAJOR(devMajor) && (devMinor % 0x10 == 0);
55     bool a2 = devMajor == SDMMC_MAJOR && (devMinor % 0x08 == 0);
56     if (a1) {
57         dev.type = DEVICE_SCSI;
58     }
59     if (a2) {
60         dev.type = DEVICE_EMMC;
61     }
62     if (!a1 && !a2) {
63         dev.type = DEVICE_UNKNOWN;
64     }
65     return 1;
66 }
67 
LastComponent(const std::string & path)68 static std::string LastComponent(const std::string &path)
69 {
70     std::string tmp = "";
71     if (path == MMC_PATH) {
72         tmp = MMC_DEV;
73     }
74     if (path == SDA_PATH) {
75         tmp = SDA_DEV;
76     }
77     if (path == SDB_PATH) {
78         tmp = SDB_DEV;
79     }
80     return tmp;
81 }
82 
ReadDeviceSysfsFile(BlockDevice & dev,const std::string & file,std::string & strl)83 static bool ReadDeviceSysfsFile(BlockDevice &dev, const std::string &file, std::string &strl)
84 {
85     FILE *f = nullptr;
86     char nameBuf[DEVPATH_SIZE];
87     char buf[BUFFER_SIZE];
88 
89     if (snprintf_s(nameBuf, DEVPATH_SIZE, DEVPATH_SIZE - 1, "/sys/block/%s/device/%s",
90         LastComponent(dev.devPath).c_str(), file.c_str()) == -1) {
91         return false;
92     }
93     char *realPath = realpath(nameBuf, NULL);
94     if (realPath == nullptr) {
95         return false;
96     }
97     if ((f = fopen(realPath, "r")) == nullptr) {
98         free(realPath);
99         return false;
100     }
101 
102     if (fgets(buf, BUFFER_SIZE, f) == nullptr) {
103         fclose(f);
104         free(realPath);
105         return false;
106     }
107     strl = buf;
108     fclose(f);
109     free(realPath);
110     return true;
111 }
112 
SdmmcGetProductInfo(BlockDevice & dev,std::string & type,std::string & name)113 static bool SdmmcGetProductInfo(BlockDevice &dev, std::string &type, std::string &name)
114 {
115     std::string typeStr = "type";
116     std::string nameStr = "name";
117 
118     bool ret = ReadDeviceSysfsFile(dev, typeStr, type);
119     bool red = ReadDeviceSysfsFile(dev, nameStr, name);
120     return (ret || red);
121 }
122 
SetBlockDeviceMode(BlockDevice & dev)123 bool SetBlockDeviceMode(BlockDevice &dev)
124 {
125     BlockSpecific *specific = BLOCK_SPECIFIC(&dev);
126 
127     specific->fd = open(dev.devPath.c_str(), RW_MODE);
128     if (specific->fd == -1) {
129         LOG(WARNING) << "Open " << dev.devPath << " with read-write failed, try read-only mode";
130         specific->fd = open(dev.devPath.c_str(), RD_MODE);
131         bool a1 = dev.readOnly;
132         dev.readOnly = 1;
133         if (specific->fd == -1) {
134             LOG(ERROR) << "Open " << dev.devPath << " with read-only mode failed: " << errno;
135             dev.readOnly = a1;
136             return false;
137         }
138     } else {
139         dev.readOnly = 0;
140     }
141     return true;
142 }
143 
BlockDeviceClose(const BlockDevice & dev)144 static int BlockDeviceClose(const BlockDevice &dev)
145 {
146     BlockSpecific* specific = BLOCK_SPECIFIC(&dev);
147     if (fsync(specific->fd) < 0 || close(specific->fd) < 0) {
148         return 0;
149     }
150     return 1;
151 }
ReadPartitionFromSys(const std::string & devname,const std::string & partn,const std::string & type,const std::string & table)152 static std::string ReadPartitionFromSys(const std::string &devname, const std::string &partn,
153     const std::string &type, const std::string &table)
154 {
155     FILE *f = nullptr;
156     char nameBuf[DEVPATH_SIZE] = {0};
157     char buf[BUFFER_SIZE] = {0};
158     char *str = nullptr;
159     std::string partString = "";
160     char *partInf = (char *)calloc(BUFFER_SIZE, sizeof(char));
161     UPDATER_ERROR_CHECK(partInf, "Allocate memory for partInf failed.", return partString);
162     if (partn.empty()) {
163         UPDATER_CHECK_ONLY_RETURN(snprintf_s(nameBuf, DEVPATH_SIZE, DEVPATH_SIZE - 1, "/sys/block/%s/%s",
164             devname.c_str(), type.c_str()) != -1, free(partInf); return partString);
165     } else {
166         UPDATER_CHECK_ONLY_RETURN(snprintf_s(nameBuf, DEVPATH_SIZE, DEVPATH_SIZE - 1, "/sys/block/%s/%s/%s",
167             devname.c_str(), partn.c_str(), type.c_str()) != -1, free(partInf); return partString);
168     }
169     if ((f = fopen(nameBuf, "r")) == nullptr) {
170         free(partInf);
171         return partString;
172     }
173     while (!feof(f)) {
174         UPDATER_CHECK_ONLY_RETURN(fgets(buf, BUFFER_SIZE, f) != nullptr, fclose(f); free(partInf); return partString);
175         if (type == "uevent") {
176             str = strstr(buf, table.c_str());
177             if (str != nullptr) {
178                 UPDATER_CHECK_ONLY_RETURN(memcpy_s(partInf, BUFFER_SIZE, buf + table.size(),
179                 sizeof(buf) - table.size()) == 0, fclose(f); free(partInf); return partString);
180                 partInf[strlen(partInf) - 1] = '\0';
181                 partString = partInf;
182                 goto end;
183             }
184         } else if (type == "start") {
185             UPDATER_CHECK_ONLY_RETURN(memcpy_s(partInf, BUFFER_SIZE, buf, sizeof(buf) - 1) == 0,
186                                       fclose(f); free(partInf); return partString);
187             LOG(INFO) << "start partInf: " << partInf;
188             partString = partInf;
189             goto end;
190         } else if (type == "size") {
191             UPDATER_CHECK_ONLY_RETURN(memcpy_s(partInf, BUFFER_SIZE, buf, sizeof(buf) - 1) == 0,
192             fclose(f); free(partInf); return partString);
193             LOG(INFO) << "size partInf: " << partInf;
194             partString = partInf;
195             goto end;
196         }
197         UPDATER_CHECK_ONLY_RETURN(memset_s(buf, sizeof(buf), 0, sizeof(buf)) == 0, fclose(f);
198             free(partInf); return partString);
199     }
200     end:
201     free(partInf);
202     fclose(f);
203     return partString;
204 }
205 
InitGeneric(BlockDevice & dev,const std::string modelName)206 static int InitGeneric(BlockDevice &dev, const std::string modelName)
207 {
208     struct stat devStat {};
209     if (DeviceStat(dev, devStat) == 0) {
210         LOG(ERROR) << "device stat error ";
211         return 0;
212     }
213     if (!SetBlockDeviceMode(dev)) {
214         LOG(ERROR) << "device authority error ";
215         return 0;
216     }
217 
218     const std::string devName = LastComponent(dev.devPath);
219     std::string partSize = ReadPartitionFromSys(devName, "", "size", "");
220     if (partSize.empty()) {
221         return 0;
222     }
223     int devSize = atoi(partSize.c_str());
224     dev.length = devSize;
225     dev.sectorSize = SECTOR_SIZE_DEFAULT;
226     dev.physSectorSize = SECTOR_SIZE_DEFAULT;
227     dev.model = modelName;
228     BlockDeviceClose (dev);
229     dev.fd = -1;
230     return 1;
231 }
232 
InitSdmmc(BlockDevice & dev)233 static int InitSdmmc(BlockDevice &dev)
234 {
235     std::string type = "";
236     std::string name = "";
237     std::string id = "";
238     bool a1 = SdmmcGetProductInfo(dev, type, name);
239     if (a1) {
240         id = type + name;
241     }
242     if (!a1) {
243         id = "Generic SD/MMC Storage Card";
244         return 0;
245     }
246     return InitGeneric(dev, id);
247 }
248 
NewBlockDevice(const std::string & path)249 static BlockDevice* NewBlockDevice(const std::string &path)
250 {
251     BlockDevice *dev = nullptr;
252     BlockSpecific *specific = nullptr;
253 
254     dev = static_cast<BlockDevice*>(calloc(1, sizeof (BlockDevice)));
255     if (dev == nullptr) {
256         LOG(ERROR) << "calloc errno " << errno;
257         return nullptr;
258     }
259 
260     dev->devPath = path;
261     dev->specific = static_cast<BlockSpecific*>(calloc(1, sizeof (BlockSpecific)));
262     if (!dev->specific) {
263         LOG(ERROR) << "calloc errno " << errno;
264         free(dev);
265         return nullptr;
266     }
267 
268     specific = BLOCK_SPECIFIC(dev);
269     dev->readOnly = 0;
270     dev->sectorSize = 0;
271     dev->physSectorSize = 0;
272 
273     int ret = 0;
274     bool a1 = DeviceProbeType(*dev);
275     if (a1) {
276         if (dev->type == DEVICE_EMMC)  {
277             ret = InitSdmmc(*dev);
278             if (ret == 0) {
279                 LOG(ERROR) << "Init sdmmc error";
280             }
281         }
282         if (dev->type != DEVICE_EMMC) {
283             LOG(WARNING) << "Unsupported device type";
284         }
285     }
286     if (!a1) {
287         LOG(ERROR) << "Device probe error";
288     }
289 
290     if (ret == 0) {
291         free(dev->specific);
292         free(dev);
293         dev = nullptr;
294     }
295     return dev;
296 }
297 
NewBlockDisk(const BlockDevice & dev,const DiskType diskType)298 static Disk* NewBlockDisk(const BlockDevice &dev, const DiskType diskType)
299 {
300     Disk *disk = nullptr;
301 
302     disk = static_cast<Disk*>(calloc (1, sizeof (Disk)));
303     if (disk == nullptr) {
304         LOG(ERROR) << "Allocate memory for disk failed: " << errno;
305         return nullptr;
306     }
307 
308     disk->dev = (BlockDevice*)&dev;
309     disk->type = diskType;
310     disk->partsum = 0;
311     disk->partList.clear();
312     return disk;
313 }
314 
DiskAlloc(const std::string & path)315 int DiskAlloc(const std::string &path)
316 {
317     struct Disk *disk = nullptr;
318     struct BlockDevice *dev = nullptr;
319     dev = NewBlockDevice(path);
320     if (dev == nullptr) {
321         LOG(ERROR) << "NewBlockDevice nullptr ";
322         return 0;
323     }
324 
325     disk = NewBlockDisk(*dev, GPT);
326     if (disk == nullptr) {
327         LOG(ERROR) << "NewBlockDevice nullptr ";
328         return 0;
329     }
330     g_disks = disk;
331     return 1;
332 }
333 
NewPartition(const BlockDevice & dev,int partn)334 static struct Partition* NewPartition(const BlockDevice &dev, int partn)
335 {
336     Partition* part = (Partition*) calloc (1, sizeof (Partition));
337     if (part == nullptr) {
338         LOG(ERROR) << "Allocate memory for partition failed.";
339         return nullptr;
340     }
341     const std::string devName = LastComponent(dev.devPath);
342     char partName[64] = {0};
343     if (devName == MMC_DEV) {
344         if (snprintf_s(partName, sizeof(partName), sizeof(partName) - 1, "%sp%d", devName.c_str(), partn) == -1) {
345             free(part);
346             return nullptr;
347         }
348     }
349     if (devName != MMC_DEV && ((devName == SDA_DEV) || (devName == SDB_DEV)) &&
350         snprintf_s(partName, sizeof(partName), sizeof(partName) - 1, "%s%d", devName.c_str(), partn) == -1) {
351         free(part);
352         return nullptr;
353     }
354 
355     std::string strstart = ReadPartitionFromSys(devName, partName, "start", "");
356     if (strstart.empty()) {
357         free(part);
358         return nullptr;
359     }
360     part->start = static_cast<size_t>(atoi(strstart.c_str()));
361 
362     std::string strsize = ReadPartitionFromSys(devName, partName, "size", "");
363     if (strsize.empty()) {
364         free(part);
365         return nullptr;
366     }
367     part->length = static_cast<size_t>(atoi(strsize.c_str()));
368 
369     std::string strdevname = ReadPartitionFromSys(devName, partName, "uevent", "DEVNAME=");
370     part->devName = partName;
371     if (!strdevname.empty()) {
372         part->devName = strdevname;
373     }
374     std::string strpartname = ReadPartitionFromSys(devName, partName, "uevent", "PARTNAME=");
375     part->partName = partName;
376     if (!strpartname.empty()) {
377         part->partName = strpartname;
378     }
379 
380     part->partNum = partn;
381     part->type = NORMAL;
382     part->fsType = "";
383     part->changeType = NORMAL_CHANGE;
384     return part;
385 }
386 
GetPartition(const Disk & disk,int partn)387 struct Partition* GetPartition(const Disk &disk, int partn)
388 {
389     struct Partition *part = nullptr;
390     if (partn == 0) {
391         return nullptr;
392     }
393     if (disk.partList.empty()) {
394         return nullptr;
395     }
396     for (auto& p : disk.partList) {
397         if (p->partNum == partn) {
398             part = p;
399             break;
400         }
401     }
402     return part;
403 }
404 
ProbeAllPartitions()405 int ProbeAllPartitions()
406 {
407     int i = 0;
408     struct Disk* disk = nullptr;
409     disk = g_disks;
410     if (disk == nullptr) {
411         return 0;
412     }
413     int partSum = DEFAULT_PARTSUM;
414     struct Partition* part = nullptr;
415     for (i = 1; i < partSum; i++) {
416         part = NewPartition(*(disk->dev), i);
417         if (!part) {
418             LOG(ERROR) << "Create new partition failed.";
419             break;
420         }
421         disk->partList.push_back(part);
422         disk->partsum++;
423     }
424     return disk->partsum;
425 }
426 
GetRegisterBlockDisk(const std::string & path)427 Disk* GetRegisterBlockDisk(const std::string &path)
428 {
429     if (g_disks == nullptr) {
430         return nullptr;
431     }
432     Disk *p = nullptr;
433     if (g_disks->dev->devPath == path) {
434         p = g_disks;
435     }
436     return p;
437 }
438 
GetPartitionNumByPartName(const std::string & partname,const PartitonList & plist)439 int GetPartitionNumByPartName(const std::string &partname, const PartitonList &plist)
440 {
441     int ret = 0;
442     for (const auto &p : plist) {
443         if (p->partName == partname) {
444             ret = p->partNum;
445             break;
446         }
447     }
448     return ret;
449 }
450 } // namespace Updater
451