blob: 07d01cb97ecea980d5ab6586c8aae3392bc10928 [file] [log] [blame]
Szymon Starzyckie160f812013-07-24 17:08:04 -07001/*
2 * Copyright (c) 2009-2013, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google, Inc. nor the names of its contributors
15 * may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <getopt.h>
35#include <unistd.h>
36
37#include <cutils/klog.h>
38
39#include "commands/partitions.h"
40#include "debug.h"
41
42unsigned int debug_level = DEBUG;
43//TODO: add tool to generate config file
44
45void usage() {
46 fprintf(stderr,
47 "usage: test_gpt [ <option> ] <file>\n"
48 "\n"
49 "options:\n"
50 " -p print partitions\n"
51 " -c print config file\n"
52 " -a adds new partition\n"
53 " -d deletes partition (-o needed)\n"
54 "\n"
55 " -n name@startlba,endlba new partition detail\n"
56 " -o old partition name\n"
57 " -t type guid\n"
58 " -g partition guid\n"
59 " -l gpt_location specyfies gpt secto\n"
60 );
61
62}
63
64void printGPT(struct GPT_entry_table *table);
65void addGPT(struct GPT_entry_table *table, const char *arg, const char *guid, const char *tguid);
66void deleteGPT(struct GPT_entry_table *table, const char *name);
67void configPrintGPT(struct GPT_entry_table *table);
68
69int main(int argc, char *argv[]) {
70 int print_cmd = 0;
71 int config_cmd = 0;
72 int add_cmd = 0;
73 int del_cmd = 0;
74 int sync_cmd = 0;
75 int c;
76 const char *new_partition = NULL;
77 const char *old_partition = NULL;
78 const char *type_guid = NULL;
79 const char *partition_guid = NULL;
80 unsigned gpt_location = 1;
81
82 klog_init();
83 klog_set_level(6);
84
85 const struct option longopts[] = {
86 {"print", no_argument, 0, 'p'},
87 {"config-print", no_argument, 0, 'c'},
88 {"add", no_argument, 0, 'a'},
89 {"del", no_argument, 0, 'd'},
90 {"new", required_argument, 0, 'n'},
91 {"old", required_argument, 0, 'o'},
92 {"type", required_argument, 0, 't'},
93 {"sync", required_argument, 0, 's'},
94 {"guid", required_argument, 0, 'g'},
95 {"location", required_argument, 0, 'l'},
96 {0, 0, 0, 0}
97 };
98
99 while (1) {
100 c = getopt_long(argc, argv, "pcadt:g:n:o:sl:", longopts, NULL);
101 /* Alphabetical cases */
102 if (c < 0)
103 break;
104 switch (c) {
105 case 'p':
106 print_cmd = 1;
107 break;
108 case 'c':
109 config_cmd = 1;
110 break;
111 case 'a':
112 add_cmd = 1;
113 break;
114 case 'd':
115 del_cmd = 1;
116 break;
117 case 'n':
118 new_partition = optarg;
119 break;
120 case 'o':
121 old_partition = optarg;
122 break;
123 case 't':
124 type_guid = optarg;
125 case 'g':
126 partition_guid = optarg;
127 break;
128 case 's':
129 sync_cmd = 1;
130 break;
131 case 'l':
132 gpt_location = strtoul(optarg, NULL, 10);
133 fprintf(stderr, "Got offset as %d", gpt_location);
134 break;
135 case '?':
136 return 1;
137 default:
138 abort();
139 }
140 }
141
142 argc -= optind;
143 argv += optind;
144
145 if (argc < 1) {
146 usage();
147 return 1;
148 }
149
150 const char *path = argv[0];
151 struct GPT_entry_table *table = GPT_get_device(path, gpt_location);
152 if (table == NULL) {
153 fprintf(stderr, "unable to get GPT table from %s\n", path);
154 return 1;
155 }
156
157 fprintf(stderr, "entries %d, name %s\n", table->header->entries_count, (char *) table->header->signature);
158
159
160 if (add_cmd)
161 addGPT(table, new_partition, partition_guid, type_guid);
162 if (del_cmd)
163 deleteGPT(table, old_partition);
164 if (print_cmd)
165 printGPT(table);
166 if (config_cmd)
167 configPrintGPT(table);
168 if (sync_cmd)
169 GPT_sync(table);
170
171 GPT_release_device(table);
172
173 return 0;
174}
175
176void printGPT(struct GPT_entry_table *table) {
177 struct GPT_entry_raw *entry = table->entries;
178 unsigned n, m;
179 char name[GPT_NAMELEN + 1];
180
181 printf("ptn start block end block name\n");
182 printf("---- ------------- -------------\n");
183
184 for (n = 0; n < table->header->entries_count; n++, entry++) {
185 if (entry->type_guid[0] == 0)
186 continue;
187 for (m = 0; m < GPT_NAMELEN; m++) {
188 name[m] = entry->name[m] & 127;
189 }
190 name[m] = 0;
191 printf("#%03d %13lld %13lld %s\n",
192 n + 1, entry->first_lba, entry->last_lba, name);
193 }
194}
195
196void configPrintGPT(struct GPT_entry_table *table) {
197 struct GPT_entry_raw *entry = table->entries;
198 unsigned n, m;
199 char name[GPT_NAMELEN + 1];
200
201 printf("header_lba %lld\n", table->header->current_lba);
202 printf("backup_lba %lld\n", table->header->backup_lba);
203 printf("first_lba %lld\n", table->header->first_usable_lba);
204 printf("last_lba %lld\n", table->header->last_usable_lba);
205 printf("entries_lba %lld\n", table->header->entries_lba);
206
207 printf("\npartitions {\n");
208
209 for (n = 0; n < table->header->entries_count; n++, entry++) {
210 uint64_t size = entry->last_lba - entry->first_lba + 1;
211
212 if (entry->type_guid[0] == 0)
213 continue;
214 for (m = 0; m < GPT_NAMELEN; m++) {
215 name[m] = entry->name[m] & 127;
216 }
217 name[m] = 0;
218
219 printf(" %s {\n", name);
220 printf(" first_lba %lld\n", entry->first_lba);
221 printf(" partition_size %lld\n", size);
222 if (entry->flags != 0)
223 printf(" flags %lld\n", entry->flags);
224 printf(" }\n\n");
225 }
226 printf("}\n");
227}
228
229void addGPT(struct GPT_entry_table *table, const char *str , const char *guid, const char *tguid) {
230 char *c, *c2;
231 char *arg = malloc(strlen(str));
232 char *name = arg;
233 unsigned start, end;
234 strcpy(arg, str);
235 if (guid == NULL || tguid == NULL) {
236 fprintf(stderr, "Type guid and partion guid needed");
237 free(arg);
238 return;
239 }
240
241 c = strchr(arg, '@');
242
243 if (c == NULL) {
244 fprintf(stderr, "Wrong entry format");
245 free(arg);
246 return;
247 }
248
249 *c++ = '\0';
250
251 c2 = strchr(c, ',');
252
253 if (c2 == NULL) {
254 fprintf(stderr, "Wrong entry format");
255 free(arg);
256 return;
257 }
258
259 start = strtoul(c, NULL, 10);
260 *c2++ = '\0';
261 end = strtoul(c2, NULL, 10);
262
263 struct GPT_entry_raw data;
264 strncpy((char *)data.partition_guid, guid, 15);
265 data.partition_guid[15] = '\0';
266 strncpy((char *)data.type_guid, tguid, 15);
267 data.type_guid[15] = '\0';
268 GPT_to_UTF16(data.name, name, GPT_NAMELEN);
269 data.first_lba = start;
270 data.last_lba = end;
271
272 fprintf(stderr, "Adding (%d,%d) %s as, [%s, %s]", start, end, name, (char *) data.type_guid, (char *) data.partition_guid);
273 GPT_add_entry(table, &data);
274 free(arg);
275}
276
277void deleteGPT(struct GPT_entry_table *table, const char *name) {
278 struct GPT_entry_raw *entry;
279
280 if (name == NULL) {
281 fprintf(stderr, "Need partition name");
282 return;
283 }
284
285 entry = GPT_get_pointer_by_name(table, name);
286
287 if (!entry) {
288 fprintf(stderr, "Unable to find partition: %s", name);
289 return;
290 }
291 GPT_delete_entry(table, entry);
292}
293