Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1011)

Side by Side Diff: cgpt/cmd_find.c

Issue 3122023: Enhance 'cgpt find' command to match keyblocks if desired. (Closed) Base URL: http://src.chromium.org/git/vboot_reference.git
Patch Set: Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | firmware/version.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cgpt.h" 5 #include "cgpt.h"
6 6
7 #include <getopt.h> 7 #include <getopt.h>
8 #include <stdio.h> 8 #include <stdio.h>
9 #include <stdlib.h> 9 #include <stdlib.h>
10 #include <string.h> 10 #include <string.h>
(...skipping 10 matching lines...) Expand all
21 printf("\nUsage: %s find [OPTIONS] [DRIVE]\n\n" 21 printf("\nUsage: %s find [OPTIONS] [DRIVE]\n\n"
22 "Find a partition by its UUID or label. With no specified DRIVE\n" 22 "Find a partition by its UUID or label. With no specified DRIVE\n"
23 "it scans all physical drives.\n\n" 23 "it scans all physical drives.\n\n"
24 "Options:\n" 24 "Options:\n"
25 " -t GUID Search for Partition Type GUID\n" 25 " -t GUID Search for Partition Type GUID\n"
26 " -u GUID Search for Partition Unique ID\n" 26 " -u GUID Search for Partition Unique ID\n"
27 " -l LABEL Search for Label\n" 27 " -l LABEL Search for Label\n"
28 " -v Be verbose in displaying matches (repeatable)\n" 28 " -v Be verbose in displaying matches (repeatable)\n"
29 " -n Numeric output only\n" 29 " -n Numeric output only\n"
30 " -1 Fail if more than one match is found\n" 30 " -1 Fail if more than one match is found\n"
31 " -M FILE"
32 " Matching partition data must also contain FILE content\n"
33 " -O NUM"
34 " Byte offset into partition to match content (default 0)\n"
31 "\n", progname); 35 "\n", progname);
32 PrintTypes(); 36 PrintTypes();
33 } 37 }
34 38
35 39
36 // globals 40 // globals
37 static int verbose = 0; 41 static int verbose = 0;
38 static int set_unique = 0; 42 static int set_unique = 0;
39 static int set_type = 0; 43 static int set_type = 0;
40 static int set_label = 0; 44 static int set_label = 0;
41 static int oneonly = 0; 45 static int oneonly = 0;
42 static int numeric = 0; 46 static int numeric = 0;
47 static uint8_t *matchbuf = NULL;
48 static uint64_t matchlen = 0;
49 static uint64_t matchoffset = 0;
50 static uint8_t *comparebuf = NULL;
43 51
44 static Guid unique_guid; 52 static Guid unique_guid;
45 static Guid type_guid; 53 static Guid type_guid;
46 static char *label; 54 static char *label;
47 static int hits = 0; 55 static int hits = 0;
48 56
49 #define BUFSIZE 1024 57 #define BUFSIZE 1024
58 // FIXME: currently we only support 512-byte sectors.
59 #define LBA_SIZE 512
50 60
51 61
52 // remember one of the possibly many hits 62 // remember one of the possibly many hits
53 static int match_partnum = 0; // 0 for no match, 1-N for match 63 static int match_partnum = 0; // 0 for no match, 1-N for match
54 static char match_filename[BUFSIZE]; // matching filename 64 static char match_filename[BUFSIZE]; // matching filename
55 65
56 66
67 // read a file into a buffer, return buffer and update size
68 static uint8_t *ReadFile(const char *filename, uint64_t *size) {
69 FILE *f;
70 uint8_t *buf;
71
72 f = fopen(filename, "rb");
73 if (!f) {
74 return NULL;
75 }
76
77 fseek(f, 0, SEEK_END);
78 *size = ftell(f);
79 rewind(f);
80
81 buf = malloc(*size);
82 if (!buf) {
83 fclose(f);
84 return NULL;
85 }
86
87 if(1 != fread(buf, *size, 1, f)) {
88 fclose(f);
89 free(buf);
90 return NULL;
91 }
92
93 fclose(f);
94 return buf;
95 }
96
97 // fill comparebuf with the data to be examined, returning true on success.
98 static int FillBuffer(int fd, uint64_t pos, uint64_t count) {
99 uint8_t *bufptr = comparebuf;
100
101 if (-1 == lseek(fd, pos, SEEK_SET))
102 return 0;
103
104 // keep reading until done or error
105 while (count) {
106 ssize_t bytes_read = read(fd, bufptr, count);
107 // negative means error, 0 means (unexpected) EOF
108 if (bytes_read <= 0)
109 return 0;
110 count -= bytes_read;
111 bufptr += bytes_read;
112 }
113
114 return 1;
115 }
116
117 // check partition data content. return true for match, 0 for no match or error
118 static int match_content(struct drive *drive, GptEntry *entry) {
119 uint64_t part_size;
120
121 if (!matchlen)
122 return 1;
123
124 // Ensure that the region we want to match against is inside the partition.
125 part_size = LBA_SIZE * (entry->ending_lba - entry->starting_lba + 1);
126 if (matchoffset + matchlen > part_size) {
127 return 0;
128 }
129
130 // Read the partition data.
131 if (!FillBuffer(drive->fd,
132 (LBA_SIZE * entry->starting_lba) + matchoffset,
133 matchlen)) {
134 Error("unable to read partition data\n");
135 return 0;
136 }
137
138 // Compare it
139 if (0 == memcmp(matchbuf, comparebuf, matchlen)) {
140 return 1;
141 }
142
143 // Nope.
144 return 0;
145 }
146
57 // FIXME: This needs to handle /dev/mmcblk0 -> /dev/mmcblk0p3 147 // FIXME: This needs to handle /dev/mmcblk0 -> /dev/mmcblk0p3
58 static void showmatch(char *filename, int partnum, GptEntry *entry) { 148 static void showmatch(char *filename, int partnum, GptEntry *entry) {
59 printf("%s%d\n", filename, partnum); 149 printf("%s%d\n", filename, partnum);
60 if (verbose > 0) 150 if (verbose > 0)
61 EntryDetails(entry, partnum - 1, numeric); 151 EntryDetails(entry, partnum - 1, numeric);
62 } 152 }
63 153
64 // This returns true if a GPT partition matches the search criteria. If a match 154 // This returns true if a GPT partition matches the search criteria. If a match
65 // isn't found (or if the file doesn't contain a GPT), it returns false. The 155 // isn't found (or if the file doesn't contain a GPT), it returns false. The
66 // filename and partition number that matched is left in a global, since we 156 // filename and partition number that matched is left in a global, since we
(...skipping 22 matching lines...) Expand all
89 int found = 0; 179 int found = 0;
90 if ((set_unique && !memcmp(&unique_guid, &entry->unique, sizeof(Guid))) || 180 if ((set_unique && !memcmp(&unique_guid, &entry->unique, sizeof(Guid))) ||
91 (set_type && !memcmp(&type_guid, &entry->type, sizeof(Guid)))) { 181 (set_type && !memcmp(&type_guid, &entry->type, sizeof(Guid)))) {
92 found = 1; 182 found = 1;
93 } else if (set_label) { 183 } else if (set_label) {
94 UTF16ToUTF8(entry->name, (uint8_t *)partlabel); 184 UTF16ToUTF8(entry->name, (uint8_t *)partlabel);
95 if (!strncmp(label, partlabel, sizeof(partlabel))) { 185 if (!strncmp(label, partlabel, sizeof(partlabel))) {
96 found = 1; 186 found = 1;
97 } 187 }
98 } 188 }
99 if (found) { 189 if (found && match_content(&drive, entry)) {
100 hits++; 190 hits++;
101 retval++; 191 retval++;
102 showmatch(filename, i+1, entry); 192 showmatch(filename, i+1, entry);
103 if (!match_partnum) { 193 if (!match_partnum) {
104 match_partnum = i+1; 194 match_partnum = i+1;
105 strcpy(match_filename, filename); 195 strcpy(match_filename, filename);
106 } 196 }
107 } 197 }
108 } 198 }
109 199
110 (void) DriveClose(&drive, 0); 200 (void) DriveClose(&drive, 0);
111 201
112 return retval; 202 return retval;
113 } 203 }
114 204
115 205
116 #define PROC_PARTITIONS "/proc/partitions" 206 #define PROC_PARTITIONS "/proc/partitions"
117 #define DEV_DIR "/dev" 207 #define DEV_DIR "/dev"
118 #define SYS_BLOCK_DIR "/sys/block" 208 #define SYS_BLOCK_DIR "/sys/block"
119 209
120 static const char *devdirs[] = { "/dev", "/devices", "/devfs", 0 }; 210 static const char *devdirs[] = { "/dev", "/devices", "/devfs", 0 };
121 211
122 // Given basename "foo", see if we can find a whole, real device by that name. 212 // Given basename "foo", see if we can find a whole, real device by that name.
123 // This is copied from the logic in the linux utility 'findfs', although that 213 // This is copied from the logic in the linux utility 'findfs', although that
124 // does more exhaustive searching. 214 // does more exhaustive searching.
125 static char *is_wholedev(const char *basename) { 215 static char *is_wholedev(const char *basename) {
126 int i; 216 int i;
127 struct stat statbuf; 217 struct stat statbuf;
128 static char pathname[BUFSIZE]; // we'll return this. 218 static char pathname[BUFSIZE]; // we'll return this.
129 char tmpname[BUFSIZE]; 219 char tmpname[BUFSIZE];
130 220
131 // printf("basename is %s\n", basename); 221 // It should be a block device under /dev/,
132
133 // It should be a block device under /dev/,
134 for (i = 0; devdirs[i]; i++) { 222 for (i = 0; devdirs[i]; i++) {
135 sprintf(pathname, "%s/%s", devdirs[i], basename); 223 sprintf(pathname, "%s/%s", devdirs[i], basename);
136 // printf(" look at %s\n", pathname);
137 224
138 if (0 != stat(pathname, &statbuf)) 225 if (0 != stat(pathname, &statbuf))
139 continue; 226 continue;
140 227
141 if (!S_ISBLK(statbuf.st_mode)) 228 if (!S_ISBLK(statbuf.st_mode))
142 continue; 229 continue;
143 230
144 // It should have a symlink called /sys/block/*/device 231 // It should have a symlink called /sys/block/*/device
145 sprintf(tmpname, "%s/%s/device", SYS_BLOCK_DIR, basename); 232 sprintf(tmpname, "%s/%s/device", SYS_BLOCK_DIR, basename);
146 // printf(" look at %s\n", tmpname);
147 233
148 if (0 != lstat(tmpname, &statbuf)) 234 if (0 != lstat(tmpname, &statbuf))
149 continue; 235 continue;
150 236
151 if (!S_ISLNK(statbuf.st_mode)) 237 if (!S_ISLNK(statbuf.st_mode))
152 continue; 238 continue;
153 239
154 // found it 240 // found it
155 return pathname; 241 return pathname;
156 } 242 }
(...skipping 13 matching lines...) Expand all
170 256
171 fp = fopen(PROC_PARTITIONS, "r"); 257 fp = fopen(PROC_PARTITIONS, "r");
172 if (!fp) { 258 if (!fp) {
173 perror("can't read " PROC_PARTITIONS); 259 perror("can't read " PROC_PARTITIONS);
174 return found; 260 return found;
175 } 261 }
176 262
177 while (fgets(line, sizeof(line), fp)) { 263 while (fgets(line, sizeof(line), fp)) {
178 int ma, mi; 264 int ma, mi;
179 long long unsigned int sz; 265 long long unsigned int sz;
180 266
181 if (sscanf(line, " %d %d %llu %128[^\n ]", &ma, &mi, &sz, partname) != 4) 267 if (sscanf(line, " %d %d %llu %128[^\n ]", &ma, &mi, &sz, partname) != 4)
182 continue; 268 continue;
183 269
184 if ((pathname = is_wholedev(partname))) { 270 if ((pathname = is_wholedev(partname))) {
185 if (do_search(pathname)) { 271 if (do_search(pathname)) {
186 found++; 272 found++;
187 } 273 }
188 } 274 }
189 } 275 }
190 276
191 fclose(fp); 277 fclose(fp);
192 return found; 278 return found;
193 } 279 }
194 280
195 281
196 int cmd_find(int argc, char *argv[]) { 282 int cmd_find(int argc, char *argv[]) {
197 int i; 283 int i;
198
199 int errorcnt = 0; 284 int errorcnt = 0;
285 char *e = 0;
200 int c; 286 int c;
201 287
202 opterr = 0; // quiet, you 288 opterr = 0; // quiet, you
203 while ((c=getopt(argc, argv, ":hv1nt:u:l:")) != -1) 289 while ((c=getopt(argc, argv, ":hv1nt:u:l:M:O:")) != -1)
204 { 290 {
205 switch (c) 291 switch (c)
206 { 292 {
207 case 'v': 293 case 'v':
208 verbose++; 294 verbose++;
209 break; 295 break;
210 case 'n': 296 case 'n':
211 numeric = 1; 297 numeric = 1;
212 break; 298 break;
213 case '1': 299 case '1':
(...skipping 11 matching lines...) Expand all
225 errorcnt++; 311 errorcnt++;
226 } 312 }
227 break; 313 break;
228 case 'u': 314 case 'u':
229 set_unique = 1; 315 set_unique = 1;
230 if (CGPT_OK != StrToGuid(optarg, &unique_guid)) { 316 if (CGPT_OK != StrToGuid(optarg, &unique_guid)) {
231 Error("invalid argument to -%c: %s\n", c, optarg); 317 Error("invalid argument to -%c: %s\n", c, optarg);
232 errorcnt++; 318 errorcnt++;
233 } 319 }
234 break; 320 break;
321 case 'M':
322 matchbuf = ReadFile(optarg, &matchlen);
323 if (!matchbuf || !matchlen) {
324 Error("Unable to read from %s\n", optarg);
325 errorcnt++;
326 }
327 // Go ahead and allocate space for the comparison too
328 comparebuf = (uint8_t *)malloc(matchlen);
329 if (!comparebuf) {
330 Error("Unable to allocate %" PRIu64 "bytes for comparison buffer\n",
331 matchlen);
332 errorcnt++;
333 }
334 break;
335 case 'O':
336 matchoffset = strtoull(optarg, &e, 0);
337 if (!*optarg || (e && *e)) {
338 Error("invalid argument to -%c: \"%s\"\n", c, optarg);
339 errorcnt++;
340 }
341 break;
235 342
236 case 'h': 343 case 'h':
237 Usage(); 344 Usage();
238 return CGPT_OK; 345 return CGPT_OK;
239 case '?': 346 case '?':
240 Error("unrecognized option: -%c\n", optopt); 347 Error("unrecognized option: -%c\n", optopt);
241 errorcnt++; 348 errorcnt++;
242 break; 349 break;
243 case ':': 350 case ':':
244 Error("missing argument to -%c\n", optopt); 351 Error("missing argument to -%c\n", optopt);
245 errorcnt++; 352 errorcnt++;
246 break; 353 break;
247 default: 354 default:
248 errorcnt++; 355 errorcnt++;
249 break; 356 break;
250 } 357 }
251 } 358 }
359 if (!set_unique && !set_type && !set_label) {
360 Error("You must specify at least one of -t, -u, or -l\n");
361 errorcnt++;
362 }
252 if (errorcnt) 363 if (errorcnt)
253 { 364 {
254 Usage(); 365 Usage();
255 return CGPT_FAILED; 366 return CGPT_FAILED;
256 } 367 }
257 368
258
259 if (optind < argc) { 369 if (optind < argc) {
260 for (i=optind; i<argc; i++) 370 for (i=optind; i<argc; i++)
261 do_search(argv[i]); 371 do_search(argv[i]);
262 } else { 372 } else {
263 scan_real_devs(); 373 scan_real_devs();
264 } 374 }
265 375
266 if (oneonly && hits != 1) { 376 if (oneonly && hits != 1) {
267 return CGPT_FAILED; 377 return CGPT_FAILED;
268 } 378 }
269 379
270 if (match_partnum) { 380 if (match_partnum) {
271 return CGPT_OK; 381 return CGPT_OK;
272 } 382 }
273 383
274 return CGPT_FAILED; 384 return CGPT_FAILED;
275 } 385 }
OLDNEW
« no previous file with comments | « no previous file | firmware/version.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698