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(&params, 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, &params.type_guid) &&
105           CGPT_OK != StrToGuid(optarg, &params.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, &params.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, &params.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(&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