gptedit.c revision b88fa3292d70f3a1e1512628f12cce87731ce160
1/* 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 char temp_guid[17]; 201 temp_guid[16] = 0; 202 203 printf("header_lba %lld\n", table->header->current_lba); 204 printf("backup_lba %lld\n", table->header->backup_lba); 205 printf("first_lba %lld\n", table->header->first_usable_lba); 206 printf("last_lba %lld\n", table->header->last_usable_lba); 207 printf("entries_lba %lld\n", table->header->entries_lba); 208 snprintf(temp_guid, 17, "%s", table->header->disk_guid); 209 printf("guid \"%s\"", temp_guid); 210 211 printf("\npartitions {\n"); 212 213 for (n = 0; n < table->header->entries_count; n++, entry++) { 214 uint64_t size = entry->last_lba - entry->first_lba + 1; 215 216 if (entry->type_guid[0] == 0) 217 continue; 218 for (m = 0; m < GPT_NAMELEN; m++) { 219 name[m] = entry->name[m] & 127; 220 } 221 name[m] = 0; 222 223 printf(" %s {\n", name); 224 snprintf(temp_guid, 17, "%s", entry->partition_guid); 225 printf(" guid \"%s\"\n", temp_guid); 226 printf(" first_lba %lld\n", entry->first_lba); 227 printf(" partition_size %lld\n", size); 228 if (entry->flags & GPT_FLAG_SYSTEM) 229 printf(" system\n"); 230 if (entry->flags & GPT_FLAG_BOOTABLE) 231 printf(" bootable\n"); 232 if (entry->flags & GPT_FLAG_READONLY) 233 printf(" readonly\n"); 234 if (entry->flags & GPT_FLAG_DOAUTOMOUNT) 235 printf(" automount\n"); 236 printf(" }\n\n"); 237 } 238 printf("}\n"); 239} 240 241void addGPT(struct GPT_entry_table *table, const char *str , const char *guid, const char *tguid) { 242 char *c, *c2; 243 char *arg = malloc(strlen(str)); 244 char *name = arg; 245 unsigned start, end; 246 strcpy(arg, str); 247 if (guid == NULL || tguid == NULL) { 248 fprintf(stderr, "Type guid and partion guid needed"); 249 free(arg); 250 return; 251 } 252 253 c = strchr(arg, '@'); 254 255 if (c == NULL) { 256 fprintf(stderr, "Wrong entry format"); 257 free(arg); 258 return; 259 } 260 261 *c++ = '\0'; 262 263 c2 = strchr(c, ','); 264 265 if (c2 == NULL) { 266 fprintf(stderr, "Wrong entry format"); 267 free(arg); 268 return; 269 } 270 271 start = strtoul(c, NULL, 10); 272 *c2++ = '\0'; 273 end = strtoul(c2, NULL, 10); 274 275 struct GPT_entry_raw data; 276 strncpy((char *)data.partition_guid, guid, 15); 277 data.partition_guid[15] = '\0'; 278 strncpy((char *)data.type_guid, tguid, 15); 279 data.type_guid[15] = '\0'; 280 GPT_to_UTF16(data.name, name, GPT_NAMELEN); 281 data.first_lba = start; 282 data.last_lba = end; 283 284 fprintf(stderr, "Adding (%d,%d) %s as, [%s, %s]", start, end, name, (char *) data.type_guid, (char *) data.partition_guid); 285 GPT_add_entry(table, &data); 286 free(arg); 287} 288 289void deleteGPT(struct GPT_entry_table *table, const char *name) { 290 struct GPT_entry_raw *entry; 291 292 if (name == NULL) { 293 fprintf(stderr, "Need partition name"); 294 return; 295 } 296 297 entry = GPT_get_pointer_by_name(table, name); 298 299 if (!entry) { 300 fprintf(stderr, "Unable to find partition: %s", name); 301 return; 302 } 303 GPT_delete_entry(table, entry); 304} 305 306