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