xref: /aosp_15_r20/external/vboot_reference/cgpt/cgpt_find.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2012 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker  * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker  */
5*8617a60dSAndroid Build Coastguard Worker 
6*8617a60dSAndroid Build Coastguard Worker #include <ctype.h>
7*8617a60dSAndroid Build Coastguard Worker #include <string.h>
8*8617a60dSAndroid Build Coastguard Worker #include <sys/stat.h>
9*8617a60dSAndroid Build Coastguard Worker #include <sys/types.h>
10*8617a60dSAndroid Build Coastguard Worker #include <unistd.h>
11*8617a60dSAndroid Build Coastguard Worker 
12*8617a60dSAndroid Build Coastguard Worker #include "cgpt.h"
13*8617a60dSAndroid Build Coastguard Worker #include "cgptlib_internal.h"
14*8617a60dSAndroid Build Coastguard Worker #include "cgpt_nor.h"
15*8617a60dSAndroid Build Coastguard Worker #include "vboot_host.h"
16*8617a60dSAndroid Build Coastguard Worker 
17*8617a60dSAndroid Build Coastguard Worker #define BUFSIZE 1024
18*8617a60dSAndroid Build Coastguard Worker 
19*8617a60dSAndroid Build Coastguard Worker // fill comparebuf with the data to be examined, returning true on success.
FillBuffer(CgptFindParams * params,int fd,uint64_t pos,uint64_t count)20*8617a60dSAndroid Build Coastguard Worker static int FillBuffer(CgptFindParams *params, int fd, uint64_t pos,
21*8617a60dSAndroid Build Coastguard Worker                        uint64_t count) {
22*8617a60dSAndroid Build Coastguard Worker   uint8_t *bufptr = params->comparebuf;
23*8617a60dSAndroid Build Coastguard Worker 
24*8617a60dSAndroid Build Coastguard Worker   if (-1 == lseek(fd, pos, SEEK_SET))
25*8617a60dSAndroid Build Coastguard Worker     return 0;
26*8617a60dSAndroid Build Coastguard Worker 
27*8617a60dSAndroid Build Coastguard Worker   // keep reading until done or error
28*8617a60dSAndroid Build Coastguard Worker   while (count) {
29*8617a60dSAndroid Build Coastguard Worker     ssize_t bytes_read = read(fd, bufptr, count);
30*8617a60dSAndroid Build Coastguard Worker     // negative means error, 0 means (unexpected) EOF
31*8617a60dSAndroid Build Coastguard Worker     if (bytes_read <= 0)
32*8617a60dSAndroid Build Coastguard Worker       return 0;
33*8617a60dSAndroid Build Coastguard Worker     count -= bytes_read;
34*8617a60dSAndroid Build Coastguard Worker     bufptr += bytes_read;
35*8617a60dSAndroid Build Coastguard Worker   }
36*8617a60dSAndroid Build Coastguard Worker 
37*8617a60dSAndroid Build Coastguard Worker   return 1;
38*8617a60dSAndroid Build Coastguard Worker }
39*8617a60dSAndroid Build Coastguard Worker 
40*8617a60dSAndroid Build Coastguard Worker // check partition data content. return true for match, 0 for no match or error
match_content(CgptFindParams * params,struct drive * drive,GptEntry * entry)41*8617a60dSAndroid Build Coastguard Worker static int match_content(CgptFindParams *params, struct drive *drive,
42*8617a60dSAndroid Build Coastguard Worker                              GptEntry *entry) {
43*8617a60dSAndroid Build Coastguard Worker   uint64_t part_size;
44*8617a60dSAndroid Build Coastguard Worker 
45*8617a60dSAndroid Build Coastguard Worker   if (!params->matchlen)
46*8617a60dSAndroid Build Coastguard Worker     return 1;
47*8617a60dSAndroid Build Coastguard Worker 
48*8617a60dSAndroid Build Coastguard Worker   // Ensure that the region we want to match against is inside the partition.
49*8617a60dSAndroid Build Coastguard Worker   part_size = drive->gpt.sector_bytes *
50*8617a60dSAndroid Build Coastguard Worker     (entry->ending_lba - entry->starting_lba + 1);
51*8617a60dSAndroid Build Coastguard Worker   if (params->matchoffset + params->matchlen > part_size) {
52*8617a60dSAndroid Build Coastguard Worker     return 0;
53*8617a60dSAndroid Build Coastguard Worker   }
54*8617a60dSAndroid Build Coastguard Worker 
55*8617a60dSAndroid Build Coastguard Worker   // Read the partition data.
56*8617a60dSAndroid Build Coastguard Worker   if (!FillBuffer(params, drive->fd,
57*8617a60dSAndroid Build Coastguard Worker     (drive->gpt.sector_bytes * entry->starting_lba) + params->matchoffset,
58*8617a60dSAndroid Build Coastguard Worker                   params->matchlen)) {
59*8617a60dSAndroid Build Coastguard Worker     Error("unable to read partition data\n");
60*8617a60dSAndroid Build Coastguard Worker     return 0;
61*8617a60dSAndroid Build Coastguard Worker   }
62*8617a60dSAndroid Build Coastguard Worker 
63*8617a60dSAndroid Build Coastguard Worker   // Compare it
64*8617a60dSAndroid Build Coastguard Worker   if (0 == memcmp(params->matchbuf, params->comparebuf, params->matchlen)) {
65*8617a60dSAndroid Build Coastguard Worker     return 1;
66*8617a60dSAndroid Build Coastguard Worker   }
67*8617a60dSAndroid Build Coastguard Worker 
68*8617a60dSAndroid Build Coastguard Worker   // Nope.
69*8617a60dSAndroid Build Coastguard Worker   return 0;
70*8617a60dSAndroid Build Coastguard Worker }
71*8617a60dSAndroid Build Coastguard Worker 
72*8617a60dSAndroid Build Coastguard Worker // This needs to handle /dev/mmcblk0 -> /dev/mmcblk0p3, /dev/sda -> /dev/sda3
showmatch(CgptFindParams * params,const char * filename,int partnum,GptEntry * entry)73*8617a60dSAndroid Build Coastguard Worker static void showmatch(CgptFindParams *params, const char *filename,
74*8617a60dSAndroid Build Coastguard Worker                       int partnum, GptEntry *entry) {
75*8617a60dSAndroid Build Coastguard Worker   const char * format = "%s%d\n";
76*8617a60dSAndroid Build Coastguard Worker 
77*8617a60dSAndroid Build Coastguard Worker   /*
78*8617a60dSAndroid Build Coastguard Worker    * Follow convention from disk_name() in kernel block/partition-generic.c
79*8617a60dSAndroid Build Coastguard Worker    * code:
80*8617a60dSAndroid Build Coastguard Worker    * If the last digit of the device name is a number, add a 'p' between the
81*8617a60dSAndroid Build Coastguard Worker    * device name and the partition number.
82*8617a60dSAndroid Build Coastguard Worker    */
83*8617a60dSAndroid Build Coastguard Worker   if (isdigit(filename[strlen(filename) - 1]))
84*8617a60dSAndroid Build Coastguard Worker     format = "%sp%d\n";
85*8617a60dSAndroid Build Coastguard Worker 
86*8617a60dSAndroid Build Coastguard Worker   if (params->numeric) {
87*8617a60dSAndroid Build Coastguard Worker     printf("%d\n", partnum);
88*8617a60dSAndroid Build Coastguard Worker   } else {
89*8617a60dSAndroid Build Coastguard Worker     if (params->show_fn) {
90*8617a60dSAndroid Build Coastguard Worker       params->show_fn(params, filename, partnum, entry);
91*8617a60dSAndroid Build Coastguard Worker     } else {
92*8617a60dSAndroid Build Coastguard Worker       printf(format, filename, partnum);
93*8617a60dSAndroid Build Coastguard Worker     }
94*8617a60dSAndroid Build Coastguard Worker   }
95*8617a60dSAndroid Build Coastguard Worker   if (params->verbose > 0)
96*8617a60dSAndroid Build Coastguard Worker     EntryDetails(entry, partnum - 1, params->numeric);
97*8617a60dSAndroid Build Coastguard Worker }
98*8617a60dSAndroid Build Coastguard Worker 
99*8617a60dSAndroid Build Coastguard Worker // This returns true if a GPT partition matches the search criteria. If a match
100*8617a60dSAndroid Build Coastguard Worker // isn't found (or if the file doesn't contain a GPT), it returns false. The
101*8617a60dSAndroid Build Coastguard Worker // filename and partition number that matched is left in a global, since we
102*8617a60dSAndroid Build Coastguard Worker // could have multiple hits.
gpt_search(CgptFindParams * params,struct drive * drive,const char * filename)103*8617a60dSAndroid Build Coastguard Worker static int gpt_search(CgptFindParams *params, struct drive *drive,
104*8617a60dSAndroid Build Coastguard Worker                       const char *filename) {
105*8617a60dSAndroid Build Coastguard Worker   int i;
106*8617a60dSAndroid Build Coastguard Worker   GptEntry *entry;
107*8617a60dSAndroid Build Coastguard Worker   int retval = 0;
108*8617a60dSAndroid Build Coastguard Worker   char partlabel[GPT_PARTNAME_LEN];
109*8617a60dSAndroid Build Coastguard Worker 
110*8617a60dSAndroid Build Coastguard Worker   if (GPT_SUCCESS != GptValidityCheck(&drive->gpt)) {
111*8617a60dSAndroid Build Coastguard Worker     return 0;
112*8617a60dSAndroid Build Coastguard Worker   }
113*8617a60dSAndroid Build Coastguard Worker 
114*8617a60dSAndroid Build Coastguard Worker   for (i = 0; i < GetNumberOfEntries(drive); ++i) {
115*8617a60dSAndroid Build Coastguard Worker     entry = GetEntry(&drive->gpt, ANY_VALID, i);
116*8617a60dSAndroid Build Coastguard Worker 
117*8617a60dSAndroid Build Coastguard Worker     if (GuidIsZero(&entry->type))
118*8617a60dSAndroid Build Coastguard Worker       continue;
119*8617a60dSAndroid Build Coastguard Worker 
120*8617a60dSAndroid Build Coastguard Worker     int found = 0;
121*8617a60dSAndroid Build Coastguard Worker     if ((params->set_unique && GuidEqual(&params->unique_guid, &entry->unique))
122*8617a60dSAndroid Build Coastguard Worker         || (params->set_type && GuidEqual(&params->type_guid, &entry->type))) {
123*8617a60dSAndroid Build Coastguard Worker       found = 1;
124*8617a60dSAndroid Build Coastguard Worker     } else if (params->set_label) {
125*8617a60dSAndroid Build Coastguard Worker       if (CGPT_OK != UTF16ToUTF8(entry->name,
126*8617a60dSAndroid Build Coastguard Worker                                  sizeof(entry->name) / sizeof(entry->name[0]),
127*8617a60dSAndroid Build Coastguard Worker                                  (uint8_t *)partlabel, sizeof(partlabel))) {
128*8617a60dSAndroid Build Coastguard Worker         Error("The label cannot be converted from UTF16, so abort.\n");
129*8617a60dSAndroid Build Coastguard Worker         return 0;
130*8617a60dSAndroid Build Coastguard Worker       }
131*8617a60dSAndroid Build Coastguard Worker       if (!strncmp(params->label, partlabel, sizeof(partlabel)))
132*8617a60dSAndroid Build Coastguard Worker         found = 1;
133*8617a60dSAndroid Build Coastguard Worker     }
134*8617a60dSAndroid Build Coastguard Worker     if (found && match_content(params, drive, entry)) {
135*8617a60dSAndroid Build Coastguard Worker       params->hits++;
136*8617a60dSAndroid Build Coastguard Worker       retval++;
137*8617a60dSAndroid Build Coastguard Worker       showmatch(params, filename, i+1, entry);
138*8617a60dSAndroid Build Coastguard Worker       if (!params->match_partnum)
139*8617a60dSAndroid Build Coastguard Worker         params->match_partnum = i+1;
140*8617a60dSAndroid Build Coastguard Worker     }
141*8617a60dSAndroid Build Coastguard Worker   }
142*8617a60dSAndroid Build Coastguard Worker 
143*8617a60dSAndroid Build Coastguard Worker   return retval;
144*8617a60dSAndroid Build Coastguard Worker }
145*8617a60dSAndroid Build Coastguard Worker 
do_search(CgptFindParams * params,const char * fileName)146*8617a60dSAndroid Build Coastguard Worker static int do_search(CgptFindParams *params, const char *fileName) {
147*8617a60dSAndroid Build Coastguard Worker   int retval;
148*8617a60dSAndroid Build Coastguard Worker   struct drive drive;
149*8617a60dSAndroid Build Coastguard Worker 
150*8617a60dSAndroid Build Coastguard Worker   if (CGPT_OK != DriveOpen(fileName, &drive, O_RDONLY, params->drive_size))
151*8617a60dSAndroid Build Coastguard Worker     return 0;
152*8617a60dSAndroid Build Coastguard Worker 
153*8617a60dSAndroid Build Coastguard Worker   retval = gpt_search(params, &drive, fileName);
154*8617a60dSAndroid Build Coastguard Worker 
155*8617a60dSAndroid Build Coastguard Worker   (void) DriveClose(&drive, 0);
156*8617a60dSAndroid Build Coastguard Worker 
157*8617a60dSAndroid Build Coastguard Worker   return retval;
158*8617a60dSAndroid Build Coastguard Worker }
159*8617a60dSAndroid Build Coastguard Worker 
160*8617a60dSAndroid Build Coastguard Worker 
161*8617a60dSAndroid Build Coastguard Worker #define PROC_MTD "/proc/mtd"
162*8617a60dSAndroid Build Coastguard Worker #define PROC_PARTITIONS "/proc/partitions"
163*8617a60dSAndroid Build Coastguard Worker #define DEV_DIR "/dev"
164*8617a60dSAndroid Build Coastguard Worker #define SYS_BLOCK_DIR "/sys/block"
165*8617a60dSAndroid Build Coastguard Worker #define MAX_PARTITION_NAME_LEN 128
166*8617a60dSAndroid Build Coastguard Worker 
167*8617a60dSAndroid Build Coastguard Worker static const char *devdirs[] = { "/dev", "/devices", "/devfs", 0 };
168*8617a60dSAndroid Build Coastguard Worker 
169*8617a60dSAndroid Build Coastguard Worker // Given basename "foo", see if we can find a whole, real device by that name.
170*8617a60dSAndroid Build Coastguard Worker // This is copied from the logic in the linux utility 'findfs', although that
171*8617a60dSAndroid Build Coastguard Worker // does more exhaustive searching.
is_wholedev(const char * basename)172*8617a60dSAndroid Build Coastguard Worker static char *is_wholedev(const char *basename) {
173*8617a60dSAndroid Build Coastguard Worker   int i;
174*8617a60dSAndroid Build Coastguard Worker   struct stat statbuf;
175*8617a60dSAndroid Build Coastguard Worker   static char pathname[BUFSIZE];        // we'll return this.
176*8617a60dSAndroid Build Coastguard Worker   char tmpname[BUFSIZE];
177*8617a60dSAndroid Build Coastguard Worker 
178*8617a60dSAndroid Build Coastguard Worker   // It should be a block device under /dev/,
179*8617a60dSAndroid Build Coastguard Worker   for (i = 0; devdirs[i]; i++) {
180*8617a60dSAndroid Build Coastguard Worker     sprintf(pathname, "%s/%s", devdirs[i], basename);
181*8617a60dSAndroid Build Coastguard Worker 
182*8617a60dSAndroid Build Coastguard Worker     if (0 != stat(pathname, &statbuf))
183*8617a60dSAndroid Build Coastguard Worker       continue;
184*8617a60dSAndroid Build Coastguard Worker 
185*8617a60dSAndroid Build Coastguard Worker     if (!S_ISBLK(statbuf.st_mode))
186*8617a60dSAndroid Build Coastguard Worker       continue;
187*8617a60dSAndroid Build Coastguard Worker 
188*8617a60dSAndroid Build Coastguard Worker     // It should have a symlink called /sys/block/*/device
189*8617a60dSAndroid Build Coastguard Worker     sprintf(tmpname, "%s/%s/device", SYS_BLOCK_DIR, basename);
190*8617a60dSAndroid Build Coastguard Worker 
191*8617a60dSAndroid Build Coastguard Worker     if (0 != lstat(tmpname, &statbuf))
192*8617a60dSAndroid Build Coastguard Worker       continue;
193*8617a60dSAndroid Build Coastguard Worker 
194*8617a60dSAndroid Build Coastguard Worker     if (!S_ISLNK(statbuf.st_mode))
195*8617a60dSAndroid Build Coastguard Worker       continue;
196*8617a60dSAndroid Build Coastguard Worker 
197*8617a60dSAndroid Build Coastguard Worker     // found it
198*8617a60dSAndroid Build Coastguard Worker     return pathname;
199*8617a60dSAndroid Build Coastguard Worker   }
200*8617a60dSAndroid Build Coastguard Worker 
201*8617a60dSAndroid Build Coastguard Worker   return 0;
202*8617a60dSAndroid Build Coastguard Worker }
203*8617a60dSAndroid Build Coastguard Worker 
204*8617a60dSAndroid Build Coastguard Worker #ifdef GPT_SPI_NOR
205*8617a60dSAndroid Build Coastguard Worker // This handles the MTD devices. ChromeOS uses /dev/mtdX for kernel partitions,
206*8617a60dSAndroid Build Coastguard Worker // /dev/ubiblockX_0 for root partitions, and /dev/ubiX for stateful partition.
chromeos_mtd_show(CgptFindParams * params,const char * filename,int partnum,GptEntry * entry)207*8617a60dSAndroid Build Coastguard Worker static void chromeos_mtd_show(CgptFindParams *params, const char *filename,
208*8617a60dSAndroid Build Coastguard Worker                               int partnum, GptEntry *entry) {
209*8617a60dSAndroid Build Coastguard Worker   if (GuidEqual(&guid_chromeos_kernel, &entry->type)) {
210*8617a60dSAndroid Build Coastguard Worker     printf("/dev/mtd%d\n", partnum);
211*8617a60dSAndroid Build Coastguard Worker   } else if (GuidEqual(&guid_chromeos_rootfs, &entry->type)) {
212*8617a60dSAndroid Build Coastguard Worker     printf("/dev/ubiblock%d_0\n", partnum);
213*8617a60dSAndroid Build Coastguard Worker   } else {
214*8617a60dSAndroid Build Coastguard Worker     printf("/dev/ubi%d_0\n", partnum);
215*8617a60dSAndroid Build Coastguard Worker   }
216*8617a60dSAndroid Build Coastguard Worker }
217*8617a60dSAndroid Build Coastguard Worker 
scan_spi_gpt(CgptFindParams * params)218*8617a60dSAndroid Build Coastguard Worker static int scan_spi_gpt(CgptFindParams *params) {
219*8617a60dSAndroid Build Coastguard Worker   int found = 0;
220*8617a60dSAndroid Build Coastguard Worker   char partname[MAX_PARTITION_NAME_LEN];
221*8617a60dSAndroid Build Coastguard Worker   FILE *fp;
222*8617a60dSAndroid Build Coastguard Worker   size_t line_length = 0;
223*8617a60dSAndroid Build Coastguard Worker   char *line = NULL;
224*8617a60dSAndroid Build Coastguard Worker 
225*8617a60dSAndroid Build Coastguard Worker   fp = fopen(PROC_MTD, "re");
226*8617a60dSAndroid Build Coastguard Worker   if (!fp) {
227*8617a60dSAndroid Build Coastguard Worker     return found;
228*8617a60dSAndroid Build Coastguard Worker   }
229*8617a60dSAndroid Build Coastguard Worker 
230*8617a60dSAndroid Build Coastguard Worker   while (getline(&line, &line_length, fp) != -1) {
231*8617a60dSAndroid Build Coastguard Worker     uint64_t sz;
232*8617a60dSAndroid Build Coastguard Worker     uint32_t erasesz;
233*8617a60dSAndroid Build Coastguard Worker     char name[128];
234*8617a60dSAndroid Build Coastguard Worker     // dev:  size  erasesize  name
235*8617a60dSAndroid Build Coastguard Worker     if (sscanf(line, "%64[^:]: %" PRIx64 " %x \"%127[^\"]\"",
236*8617a60dSAndroid Build Coastguard Worker                partname, &sz, &erasesz, name) != 4)
237*8617a60dSAndroid Build Coastguard Worker       continue;
238*8617a60dSAndroid Build Coastguard Worker     if (strcmp(partname, "mtd0") == 0) {
239*8617a60dSAndroid Build Coastguard Worker       char temp_dir[] = VBOOT_TMP_DIR "/cgpt_find.XXXXXX";
240*8617a60dSAndroid Build Coastguard Worker       if (params->drive_size == 0) {
241*8617a60dSAndroid Build Coastguard Worker         if (GetMtdSize("/dev/mtd0", &params->drive_size) != 0) {
242*8617a60dSAndroid Build Coastguard Worker           perror("GetMtdSize");
243*8617a60dSAndroid Build Coastguard Worker           goto cleanup;
244*8617a60dSAndroid Build Coastguard Worker         }
245*8617a60dSAndroid Build Coastguard Worker       }
246*8617a60dSAndroid Build Coastguard Worker       // Create a temp dir to work in.
247*8617a60dSAndroid Build Coastguard Worker       if (mkdtemp(temp_dir) == NULL) {
248*8617a60dSAndroid Build Coastguard Worker         perror("Cannot create a temporary directory.\n");
249*8617a60dSAndroid Build Coastguard Worker         goto cleanup;
250*8617a60dSAndroid Build Coastguard Worker       }
251*8617a60dSAndroid Build Coastguard Worker       if (ReadNorFlash(temp_dir) != 0) {
252*8617a60dSAndroid Build Coastguard Worker         perror("ReadNorFlash");
253*8617a60dSAndroid Build Coastguard Worker         RemoveDir(temp_dir);
254*8617a60dSAndroid Build Coastguard Worker         goto cleanup;
255*8617a60dSAndroid Build Coastguard Worker       }
256*8617a60dSAndroid Build Coastguard Worker       char nor_file[64];
257*8617a60dSAndroid Build Coastguard Worker       if (snprintf(nor_file, sizeof(nor_file), "%s/rw_gpt", temp_dir) > 0) {
258*8617a60dSAndroid Build Coastguard Worker         params->show_fn = chromeos_mtd_show;
259*8617a60dSAndroid Build Coastguard Worker         if (do_search(params, nor_file)) {
260*8617a60dSAndroid Build Coastguard Worker           found++;
261*8617a60dSAndroid Build Coastguard Worker         }
262*8617a60dSAndroid Build Coastguard Worker         params->show_fn = NULL;
263*8617a60dSAndroid Build Coastguard Worker       }
264*8617a60dSAndroid Build Coastguard Worker       RemoveDir(temp_dir);
265*8617a60dSAndroid Build Coastguard Worker       break;
266*8617a60dSAndroid Build Coastguard Worker     }
267*8617a60dSAndroid Build Coastguard Worker   }
268*8617a60dSAndroid Build Coastguard Worker cleanup:
269*8617a60dSAndroid Build Coastguard Worker   fclose(fp);
270*8617a60dSAndroid Build Coastguard Worker   free(line);
271*8617a60dSAndroid Build Coastguard Worker   return found;
272*8617a60dSAndroid Build Coastguard Worker }
273*8617a60dSAndroid Build Coastguard Worker #else
274*8617a60dSAndroid Build Coastguard Worker // Stub
scan_spi_gpt(CgptFindParams * params)275*8617a60dSAndroid Build Coastguard Worker static int scan_spi_gpt(CgptFindParams *params) {
276*8617a60dSAndroid Build Coastguard Worker   return 0;
277*8617a60dSAndroid Build Coastguard Worker }
278*8617a60dSAndroid Build Coastguard Worker #endif
279*8617a60dSAndroid Build Coastguard Worker 
280*8617a60dSAndroid Build Coastguard Worker // This scans all the physical devices it can find, looking for a match. It
281*8617a60dSAndroid Build Coastguard Worker // returns true if any matches were found, false otherwise.
scan_real_devs(CgptFindParams * params)282*8617a60dSAndroid Build Coastguard Worker static int scan_real_devs(CgptFindParams *params) {
283*8617a60dSAndroid Build Coastguard Worker   int found = 0;
284*8617a60dSAndroid Build Coastguard Worker   char partname[MAX_PARTITION_NAME_LEN];
285*8617a60dSAndroid Build Coastguard Worker   char partname_prev[MAX_PARTITION_NAME_LEN];
286*8617a60dSAndroid Build Coastguard Worker   FILE *fp;
287*8617a60dSAndroid Build Coastguard Worker   char *pathname;
288*8617a60dSAndroid Build Coastguard Worker 
289*8617a60dSAndroid Build Coastguard Worker   fp = fopen(PROC_PARTITIONS, "re");
290*8617a60dSAndroid Build Coastguard Worker   if (!fp) {
291*8617a60dSAndroid Build Coastguard Worker     perror("can't read " PROC_PARTITIONS);
292*8617a60dSAndroid Build Coastguard Worker     return found;
293*8617a60dSAndroid Build Coastguard Worker   }
294*8617a60dSAndroid Build Coastguard Worker 
295*8617a60dSAndroid Build Coastguard Worker   size_t line_length = 0;
296*8617a60dSAndroid Build Coastguard Worker   char *line = NULL;
297*8617a60dSAndroid Build Coastguard Worker   partname_prev[0] = '\0';
298*8617a60dSAndroid Build Coastguard Worker   while (getline(&line, &line_length, fp) != -1) {
299*8617a60dSAndroid Build Coastguard Worker     int ma, mi;
300*8617a60dSAndroid Build Coastguard Worker     long long unsigned int sz;
301*8617a60dSAndroid Build Coastguard Worker 
302*8617a60dSAndroid Build Coastguard Worker     if (sscanf(line, " %d %d %llu %127[^\n ]", &ma, &mi, &sz, partname) != 4)
303*8617a60dSAndroid Build Coastguard Worker       continue;
304*8617a60dSAndroid Build Coastguard Worker 
305*8617a60dSAndroid Build Coastguard Worker     /* Only check devices that have partitions under them.
306*8617a60dSAndroid Build Coastguard Worker      * We can tell by checking that an entry like "sda" is immediately
307*8617a60dSAndroid Build Coastguard Worker      * followed by one like "sda0". */
308*8617a60dSAndroid Build Coastguard Worker     if (!strncmp(partname_prev, partname, strlen(partname_prev)) &&
309*8617a60dSAndroid Build Coastguard Worker         strlen(partname_prev)) {
310*8617a60dSAndroid Build Coastguard Worker       if ((pathname = is_wholedev(partname_prev))) {
311*8617a60dSAndroid Build Coastguard Worker         if (do_search(params, pathname)) {
312*8617a60dSAndroid Build Coastguard Worker           found++;
313*8617a60dSAndroid Build Coastguard Worker         }
314*8617a60dSAndroid Build Coastguard Worker       }
315*8617a60dSAndroid Build Coastguard Worker     }
316*8617a60dSAndroid Build Coastguard Worker 
317*8617a60dSAndroid Build Coastguard Worker     strcpy(partname_prev, partname);
318*8617a60dSAndroid Build Coastguard Worker   }
319*8617a60dSAndroid Build Coastguard Worker 
320*8617a60dSAndroid Build Coastguard Worker   fclose(fp);
321*8617a60dSAndroid Build Coastguard Worker   free(line);
322*8617a60dSAndroid Build Coastguard Worker 
323*8617a60dSAndroid Build Coastguard Worker   found += scan_spi_gpt(params);
324*8617a60dSAndroid Build Coastguard Worker 
325*8617a60dSAndroid Build Coastguard Worker   return found;
326*8617a60dSAndroid Build Coastguard Worker }
327*8617a60dSAndroid Build Coastguard Worker 
328*8617a60dSAndroid Build Coastguard Worker 
CgptFind(CgptFindParams * params)329*8617a60dSAndroid Build Coastguard Worker void CgptFind(CgptFindParams *params) {
330*8617a60dSAndroid Build Coastguard Worker   if (params == NULL)
331*8617a60dSAndroid Build Coastguard Worker     return;
332*8617a60dSAndroid Build Coastguard Worker 
333*8617a60dSAndroid Build Coastguard Worker   if (params->drive_name != NULL)
334*8617a60dSAndroid Build Coastguard Worker     do_search(params, params->drive_name);
335*8617a60dSAndroid Build Coastguard Worker   else
336*8617a60dSAndroid Build Coastguard Worker     scan_real_devs(params);
337*8617a60dSAndroid Build Coastguard Worker }
338