| /* |
| * Copyright (c) 2009-2013, Google Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google, Inc. nor the names of its contributors |
| * may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
| * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
| * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| */ |
| |
| #include <getopt.h> |
| #include <inttypes.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| |
| #include <cutils/klog.h> |
| |
| #include "commands/partitions.h" |
| #include "debug.h" |
| |
| unsigned int debug_level = DEBUG; |
| //TODO: add tool to generate config file |
| |
| void usage() { |
| fprintf(stderr, |
| "usage: test_gpt [ <option> ] <file>\n" |
| "\n" |
| "options:\n" |
| " -p print partitions\n" |
| " -c print config file\n" |
| " -a adds new partition\n" |
| " -d deletes partition (-o needed)\n" |
| "\n" |
| " -n name@startlba,endlba new partition detail\n" |
| " -o old partition name\n" |
| " -t type guid\n" |
| " -g partition guid\n" |
| " -l gpt_location specyfies gpt secto\n" |
| ); |
| |
| } |
| |
| void printGPT(struct GPT_entry_table *table); |
| void addGPT(struct GPT_entry_table *table, const char *arg, const char *guid, const char *tguid); |
| void deleteGPT(struct GPT_entry_table *table, const char *name); |
| void configPrintGPT(struct GPT_entry_table *table); |
| |
| int main(int argc, char *argv[]) { |
| int print_cmd = 0; |
| int config_cmd = 0; |
| int add_cmd = 0; |
| int del_cmd = 0; |
| int sync_cmd = 0; |
| int c; |
| const char *new_partition = NULL; |
| const char *old_partition = NULL; |
| const char *type_guid = NULL; |
| const char *partition_guid = NULL; |
| unsigned gpt_location = 1; |
| |
| klog_init(); |
| klog_set_level(6); |
| |
| const struct option longopts[] = { |
| {"print", no_argument, 0, 'p'}, |
| {"config-print", no_argument, 0, 'c'}, |
| {"add", no_argument, 0, 'a'}, |
| {"del", no_argument, 0, 'd'}, |
| {"new", required_argument, 0, 'n'}, |
| {"old", required_argument, 0, 'o'}, |
| {"type", required_argument, 0, 't'}, |
| {"sync", required_argument, 0, 's'}, |
| {"guid", required_argument, 0, 'g'}, |
| {"location", required_argument, 0, 'l'}, |
| {0, 0, 0, 0} |
| }; |
| |
| while (1) { |
| c = getopt_long(argc, argv, "pcadt:g:n:o:sl:", longopts, NULL); |
| /* Alphabetical cases */ |
| if (c < 0) |
| break; |
| switch (c) { |
| case 'p': |
| print_cmd = 1; |
| break; |
| case 'c': |
| config_cmd = 1; |
| break; |
| case 'a': |
| add_cmd = 1; |
| break; |
| case 'd': |
| del_cmd = 1; |
| break; |
| case 'n': |
| new_partition = optarg; |
| break; |
| case 'o': |
| old_partition = optarg; |
| break; |
| case 't': |
| type_guid = optarg; |
| case 'g': |
| partition_guid = optarg; |
| break; |
| case 's': |
| sync_cmd = 1; |
| break; |
| case 'l': |
| gpt_location = strtoul(optarg, NULL, 10); |
| fprintf(stderr, "Got offset as %d", gpt_location); |
| break; |
| case '?': |
| return 1; |
| default: |
| abort(); |
| } |
| } |
| |
| argc -= optind; |
| argv += optind; |
| |
| if (argc < 1) { |
| usage(); |
| return 1; |
| } |
| |
| const char *path = argv[0]; |
| struct GPT_entry_table *table = GPT_get_device(path, gpt_location); |
| if (table == NULL) { |
| fprintf(stderr, "unable to get GPT table from %s\n", path); |
| return 1; |
| } |
| |
| if (add_cmd) |
| addGPT(table, new_partition, partition_guid, type_guid); |
| if (del_cmd) |
| deleteGPT(table, old_partition); |
| if (print_cmd) |
| printGPT(table); |
| if (config_cmd) |
| configPrintGPT(table); |
| if (sync_cmd) |
| GPT_sync(table); |
| |
| GPT_release_device(table); |
| |
| return 0; |
| } |
| |
| void printGPT(struct GPT_entry_table *table) { |
| struct GPT_entry_raw *entry = table->entries; |
| unsigned n, m; |
| char name[GPT_NAMELEN + 1]; |
| |
| printf("ptn start block end block name\n"); |
| printf("---- ------------- -------------\n"); |
| |
| for (n = 0; n < table->header->entries_count; n++, entry++) { |
| if (entry->type_guid[0] == 0) |
| continue; |
| for (m = 0; m < GPT_NAMELEN; m++) { |
| name[m] = entry->name[m] & 127; |
| } |
| name[m] = 0; |
| printf("#%03d %13"PRId64" %13"PRId64" %s\n", |
| n + 1, entry->first_lba, entry->last_lba, name); |
| } |
| } |
| |
| void configPrintGPT(struct GPT_entry_table *table) { |
| struct GPT_entry_raw *entry = table->entries; |
| unsigned n, m; |
| char name[GPT_NAMELEN + 1]; |
| char temp_guid[17]; |
| temp_guid[16] = 0; |
| |
| printf("header_lba %"PRId64"\n", table->header->current_lba); |
| printf("backup_lba %"PRId64"\n", table->header->backup_lba); |
| printf("first_lba %"PRId64"\n", table->header->first_usable_lba); |
| printf("last_lba %"PRId64"\n", table->header->last_usable_lba); |
| printf("entries_lba %"PRId64"\n", table->header->entries_lba); |
| snprintf(temp_guid, 17, "%s", table->header->disk_guid); |
| printf("guid \"%s\"", temp_guid); |
| |
| printf("\npartitions {\n"); |
| |
| for (n = 0; n < table->header->entries_count; n++, entry++) { |
| uint64_t size = entry->last_lba - entry->first_lba + 1; |
| |
| if (entry->type_guid[0] == 0) |
| continue; |
| for (m = 0; m < GPT_NAMELEN; m++) { |
| name[m] = entry->name[m] & 127; |
| } |
| name[m] = 0; |
| |
| printf(" %s {\n", name); |
| snprintf(temp_guid, 17, "%s", entry->partition_guid); |
| printf(" guid \"%s\"\n", temp_guid); |
| printf(" first_lba %"PRId64"\n", entry->first_lba); |
| printf(" partition_size %"PRId64"\n", size); |
| if (entry->flags & GPT_FLAG_SYSTEM) |
| printf(" system\n"); |
| if (entry->flags & GPT_FLAG_BOOTABLE) |
| printf(" bootable\n"); |
| if (entry->flags & GPT_FLAG_READONLY) |
| printf(" readonly\n"); |
| if (entry->flags & GPT_FLAG_DOAUTOMOUNT) |
| printf(" automount\n"); |
| printf(" }\n\n"); |
| } |
| printf("}\n"); |
| } |
| |
| void addGPT(struct GPT_entry_table *table, const char *str , const char *guid, const char *tguid) { |
| char *c, *c2; |
| char *arg = malloc(strlen(str)); |
| char *name = arg; |
| unsigned start, end; |
| strcpy(arg, str); |
| if (guid == NULL || tguid == NULL) { |
| fprintf(stderr, "Type guid and partion guid needed"); |
| free(arg); |
| return; |
| } |
| |
| c = strchr(arg, '@'); |
| |
| if (c == NULL) { |
| fprintf(stderr, "Wrong entry format"); |
| free(arg); |
| return; |
| } |
| |
| *c++ = '\0'; |
| |
| c2 = strchr(c, ','); |
| |
| if (c2 == NULL) { |
| fprintf(stderr, "Wrong entry format"); |
| free(arg); |
| return; |
| } |
| |
| start = strtoul(c, NULL, 10); |
| *c2++ = '\0'; |
| end = strtoul(c2, NULL, 10); |
| |
| struct GPT_entry_raw data; |
| strncpy((char *)data.partition_guid, guid, 15); |
| data.partition_guid[15] = '\0'; |
| strncpy((char *)data.type_guid, tguid, 15); |
| data.type_guid[15] = '\0'; |
| GPT_to_UTF16(data.name, name, GPT_NAMELEN); |
| data.first_lba = start; |
| data.last_lba = end; |
| |
| fprintf(stderr, "Adding (%d,%d) %s as, [%s, %s]", start, end, name, (char *) data.type_guid, (char *) data.partition_guid); |
| GPT_add_entry(table, &data); |
| free(arg); |
| } |
| |
| void deleteGPT(struct GPT_entry_table *table, const char *name) { |
| struct GPT_entry_raw *entry; |
| |
| if (name == NULL) { |
| fprintf(stderr, "Need partition name"); |
| return; |
| } |
| |
| entry = GPT_get_pointer_by_name(table, name); |
| |
| if (!entry) { |
| fprintf(stderr, "Unable to find partition: %s", name); |
| return; |
| } |
| GPT_delete_entry(table, entry); |
| } |
| |