xref: /aosp_15_r20/external/vboot_reference/cgpt/cmd_find.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2012 The ChromiumOS Authors
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 #include <getopt.h>
7 #include <string.h>
8 
9 #include "cgpt.h"
10 #include "vboot_host.h"
11 
12 extern const char* progname;
13 
Usage(void)14 static void Usage(void)
15 {
16   printf("\nUsage: %s find [OPTIONS] [DRIVE]\n\n"
17          "Find a partition by its UUID or label. With no specified DRIVE\n"
18          "it scans all physical drives.\n\n"
19          "Options:\n"
20          "  -D NUM       Size (in bytes) of the disk where partitions reside;\n"
21          "                 default 0, meaning partitions and GPT structs are\n"
22          "                 both on DRIVE\n"
23          "  -t GUID      Search for Partition Type GUID\n"
24          "  -u GUID      Search for Partition Unique ID\n"
25          "  -l LABEL     Search for Label\n"
26          "  -v           Be verbose in displaying matches (repeatable)\n"
27          "  -n           Numeric output only\n"
28          "  -1           Fail if more than one match is found\n"
29          "  -M FILE"
30          "      Matching partition data must also contain FILE content\n"
31          "  -O NUM"
32          "       Byte offset into partition to match content (default 0)\n"
33          "\n", progname);
34   PrintTypes();
35 }
36 
37 // read a file into a buffer, return buffer and update size
ReadFile(const char * filename,uint64_t * size)38 static uint8_t *ReadFile(const char *filename, uint64_t *size) {
39   FILE *f;
40   uint8_t *buf;
41   long pos;
42 
43   f = fopen(filename, "rb");
44   if (!f) {
45     return NULL;
46   }
47 
48   fseek(f, 0, SEEK_END);
49   pos = ftell(f);
50   if (pos < 0) {
51     fclose(f);
52     return NULL;
53   }
54   *size = pos;
55   rewind(f);
56 
57   buf = malloc(*size);
58   if (!buf) {
59     fclose(f);
60     return NULL;
61   }
62 
63   if (1 != fread(buf, *size, 1, f)) {
64     fclose(f);
65     free(buf);
66     return NULL;
67   }
68 
69   fclose(f);
70   return buf;
71 }
72 
cmd_find(int argc,char * argv[])73 int cmd_find(int argc, char *argv[]) {
74 
75   CgptFindParams params;
76   memset(&params, 0, sizeof(params));
77 
78   int i;
79   int errorcnt = 0;
80   char *e = 0;
81   int c;
82 
83   opterr = 0;                     // quiet, you
84   while ((c=getopt(argc, argv, ":hv1nt:u:l:M:O:D:")) != -1)
85   {
86     switch (c)
87     {
88     case 'D':
89       params.drive_size = strtoull(optarg, &e, 0);
90       errorcnt += check_int_parse(c, e);
91       break;
92     case 'v':
93       params.verbose++;
94       break;
95     case 'n':
96       params.numeric = 1;
97       break;
98     case '1':
99       params.oneonly = 1;
100       break;
101     case 'l':
102       params.set_label = 1;
103       params.label = optarg;
104       break;
105     case 't':
106       params.set_type = 1;
107       if (CGPT_OK != SupportedType(optarg, &params.type_guid) &&
108           CGPT_OK != StrToGuid(optarg, &params.type_guid)) {
109         Error("invalid argument to -%c: %s\n", c, optarg);
110         errorcnt++;
111       }
112       break;
113     case 'u':
114       params.set_unique = 1;
115       if (CGPT_OK != StrToGuid(optarg, &params.unique_guid)) {
116         Error("invalid argument to -%c: %s\n", c, optarg);
117         errorcnt++;
118       }
119       break;
120     case 'M':
121       params.matchbuf = ReadFile(optarg, &params.matchlen);
122       if (!params.matchbuf || !params.matchlen) {
123         Error("Unable to read from %s\n", optarg);
124         errorcnt++;
125       }
126       // Go ahead and allocate space for the comparison too
127       params.comparebuf = (uint8_t *)malloc(params.matchlen);
128       if (!params.comparebuf) {
129         Error("Unable to allocate %" PRIu64 "bytes for comparison buffer\n",
130               params.matchlen);
131         errorcnt++;
132       }
133       break;
134     case 'O':
135       params.matchoffset = strtoull(optarg, &e, 0);
136       errorcnt += check_int_parse(c, e);
137       break;
138 
139     case 'h':
140       Usage();
141       return CGPT_OK;
142     case '?':
143       Error("unrecognized option: -%c\n", optopt);
144       errorcnt++;
145       break;
146     case ':':
147       Error("missing argument to -%c\n", optopt);
148       errorcnt++;
149       break;
150     default:
151       errorcnt++;
152       break;
153     }
154   }
155   if (!params.set_unique && !params.set_type && !params.set_label) {
156     Error("You must specify at least one of -t, -u, or -l\n");
157     errorcnt++;
158   }
159   if (errorcnt)
160   {
161     Usage();
162     return CGPT_FAILED;
163   }
164 
165   if (optind < argc) {
166     for (i=optind; i<argc; i++) {
167       params.drive_name = argv[i];
168       CgptFind(&params);
169       }
170   } else {
171       CgptFind(&params);
172   }
173 
174   if (params.oneonly && params.hits != 1) {
175     return CGPT_FAILED;
176   }
177 
178   if (params.match_partnum) {
179     return CGPT_OK;
180   }
181 
182   return CGPT_FAILED;
183 }
184