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

Side by Side Diff: cgpt/cmd_find.c

Issue 2849040: Add 'find' command to cgpt, to search for partitions by UUID. (Closed) Base URL: ssh://git@gitrw.chromium.org//vboot_reference.git
Patch Set: Created 10 years, 5 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 | « cgpt/cgpt.c ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "cgpt.h"
6
7 #include <getopt.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/stat.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14 #include <uuid/uuid.h>
15
16 #include "cgptlib_internal.h"
17
18
19 static void Usage(void)
20 {
21 printf("\nUsage: %s find [OPTIONS] [DRIVE]\n\n"
22 "Find a partition by its UUID or label. With no specified DRIVE\n"
23 "it scans all physical drives.\n\n"
24 "Options:\n"
25 " -t GUID Search for Partition Type GUID\n"
26 " -u GUID Search for Partition Unique ID\n"
27 " -l LABEL Search for Label\n"
28 " -v Be verbose in displaying matches (repeatable)\n"
29 " -n Numeric output only\n"
30 " -1 Fail if more than one match is found\n"
31 "\n", progname);
32 PrintTypes();
33 }
34
35
36 // globals
37 static int verbose = 0;
38 static int set_unique = 0;
39 static int set_type = 0;
40 static int set_label = 0;
41 static int oneonly = 0;
42 static int numeric = 0;
43
44 static Guid unique_guid;
45 static Guid type_guid;
46 static char *label;
47 static int hits = 0;
48
49 #define BUFSIZE 1024
50
51
52 // remember one of the possibly many hits
53 static int match_partnum = 0; // 0 for no match, 1-N for match
54 static char match_filename[BUFSIZE]; // matching filename
55
56
57 // FIXME: This needs to handle /dev/mmcblk0 -> /dev/mmcblk0p3
58 static void showmatch(char *filename, int partnum, GptEntry *entry) {
59 printf("%s%d\n", filename, partnum);
60 if (verbose > 0)
61 EntryDetails(entry, partnum - 1, numeric);
62 }
63
64 // 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
66 // filename and partition number that matched is left in a global, since we
67 // could have multiple hits.
68 static int do_search(char *filename) {
69 int retval = 0;
70 int i;
71 struct drive drive;
72 GptEntry *entry;
73 char partlabel[sizeof(entry->name) * 3 / 2];
74
75 if (CGPT_OK != DriveOpen(filename, &drive))
76 return 0;
77
78 if (GPT_SUCCESS != GptSanityCheck(&drive.gpt)) {
79 (void) DriveClose(&drive, 0);
80 return 0;
81 }
82
83 for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) {
84 entry = GetEntry(&drive.gpt, PRIMARY, i);
85
86 if (IsZero(&entry->type))
87 continue;
88
89 int found = 0;
90 if ((set_unique && !memcmp(&unique_guid, &entry->unique, sizeof(Guid))) ||
91 (set_type && !memcmp(&type_guid, &entry->type, sizeof(Guid)))) {
92 found = 1;
93 } else if (set_label) {
94 UTF16ToUTF8(entry->name, (uint8_t *)partlabel);
95 if (!strncmp(label, partlabel, sizeof(partlabel))) {
96 found = 1;
97 }
98 }
99 if (found) {
100 hits++;
101 retval++;
102 showmatch(filename, i+1, entry);
103 if (!match_partnum) {
104 match_partnum = i+1;
105 strcpy(match_filename, filename);
106 }
107 }
108 }
109
110 (void) DriveClose(&drive, 0);
111
112 return retval;
113 }
114
115
116 #define PROC_PARTITIONS "/proc/partitions"
117 #define DEV_DIR "/dev"
118 #define SYS_BLOCK_DIR "/sys/block"
119
120 static const char *devdirs[] = { "/dev", "/devices", "/devfs", 0 };
121
122 // 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
124 // does more exhaustive searching.
125 static char *is_wholedev(const char *basename) {
126 int i;
127 struct stat statbuf;
128 static char pathname[BUFSIZE]; // we'll return this.
129 char tmpname[BUFSIZE];
130
131 // printf("basename is %s\n", basename);
132
133 // It should be a block device under /dev/,
134 for (i = 0; devdirs[i]; i++) {
135 sprintf(pathname, "%s/%s", devdirs[i], basename);
136 // printf(" look at %s\n", pathname);
137
138 if (0 != stat(pathname, &statbuf))
139 continue;
140
141 if (!S_ISBLK(statbuf.st_mode))
142 continue;
143
144 // It should have a symlink called /sys/block/*/device
145 sprintf(tmpname, "%s/%s/device", SYS_BLOCK_DIR, basename);
146 // printf(" look at %s\n", tmpname);
147
148 if (0 != lstat(tmpname, &statbuf))
149 continue;
150
151 if (!S_ISLNK(statbuf.st_mode))
152 continue;
153
154 // found it
155 return pathname;
156 }
157
158 return 0;
159 }
160
161
162 // This scans all the physical devices it can find, looking for a match. It
163 // returns true if any matches were found, false otherwise.
164 static int scan_real_devs(void) {
165 int found = 0;
166 char line[BUFSIZE];
167 char partname[128];
168 FILE *fp;
169 char *pathname;
170
171 fp = fopen(PROC_PARTITIONS, "r");
172 if (!fp) {
173 perror("can't read " PROC_PARTITIONS);
174 return found;
175 }
176
177 while (fgets(line, sizeof(line), fp)) {
178 int ma, mi;
179 long long unsigned int sz;
180
181 if (sscanf(line, " %d %d %llu %128[^\n ]", &ma, &mi, &sz, partname) != 4)
182 continue;
183
184 if ((pathname = is_wholedev(partname))) {
185 if (do_search(pathname)) {
186 found++;
187 }
188 }
189 }
190
191 fclose(fp);
192 return found;
193 }
194
195
196 int cmd_find(int argc, char *argv[]) {
197 int i;
198
199 int errorcnt = 0;
200 int c;
201
202 opterr = 0; // quiet, you
203 while ((c=getopt(argc, argv, ":hv1nt:u:l:")) != -1)
204 {
205 switch (c)
206 {
207 case 'v':
208 verbose++;
209 break;
210 case 'n':
211 numeric = 1;
212 break;
213 case '1':
214 oneonly = 1;
215 break;
216 case 'l':
217 set_label = 1;
218 label = optarg;
219 break;
220 case 't':
221 set_type = 1;
222 if (CGPT_OK != SupportedType(optarg, &type_guid) &&
223 CGPT_OK != StrToGuid(optarg, &type_guid)) {
224 Error("invalid argument to -%c: %s\n", c, optarg);
225 errorcnt++;
226 }
227 break;
228 case 'u':
229 set_unique = 1;
230 if (CGPT_OK != StrToGuid(optarg, &unique_guid)) {
231 Error("invalid argument to -%c: %s\n", c, optarg);
232 errorcnt++;
233 }
234 break;
235
236 case 'h':
237 Usage();
238 return CGPT_OK;
239 case '?':
240 Error("unrecognized option: -%c\n", optopt);
241 errorcnt++;
242 break;
243 case ':':
244 Error("missing argument to -%c\n", optopt);
245 errorcnt++;
246 break;
247 default:
248 errorcnt++;
249 break;
250 }
251 }
252 if (errorcnt)
253 {
254 Usage();
255 return CGPT_FAILED;
256 }
257
258
259 if (optind < argc) {
260 for (i=optind; i<argc; i++)
261 do_search(argv[i]);
262 } else {
263 scan_real_devs();
264 }
265
266 if (oneonly && hits != 1) {
267 return CGPT_FAILED;
268 }
269
270 if (match_partnum) {
271 return CGPT_OK;
272 }
273
274 return CGPT_FAILED;
275 }
OLDNEW
« no previous file with comments | « cgpt/cgpt.c ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698