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(¶ms, 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, ¶ms.type_guid) &&
108 CGPT_OK != StrToGuid(optarg, ¶ms.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, ¶ms.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, ¶ms.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(¶ms);
169 }
170 } else {
171 CgptFind(¶ms);
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