Home | History | Annotate | Download | only in other
      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 <getopt.h>
     33 #include <inttypes.h>
     34 #include <stdio.h>
     35 #include <stdlib.h>
     36 #include <unistd.h>
     37 
     38 #include <cutils/klog.h>
     39 
     40 #include "commands/partitions.h"
     41 #include "debug.h"
     42 
     43 unsigned int debug_level = DEBUG;
     44 //TODO: add tool to generate config file
     45 
     46 void usage() {
     47     fprintf(stderr,
     48             "usage: test_gpt [ <option> ] <file>\n"
     49             "\n"
     50             "options:\n"
     51             "  -p                                       print partitions\n"
     52             "  -c                                       print config file\n"
     53             "  -a                                       adds new partition\n"
     54             "  -d                                       deletes partition (-o needed)\n"
     55             "\n"
     56             "  -n name@startlba,endlba                  new partition detail\n"
     57             "  -o                                       old partition name\n"
     58             "  -t                                       type guid\n"
     59             "  -g                                       partition guid\n"
     60             "  -l gpt_location                          specyfies gpt secto\n"
     61     );
     62 
     63 }
     64 
     65 void printGPT(struct GPT_entry_table *table);
     66 void addGPT(struct GPT_entry_table *table, const char *arg, const char *guid, const char *tguid);
     67 void deleteGPT(struct GPT_entry_table *table, const char *name);
     68 void configPrintGPT(struct GPT_entry_table *table);
     69 
     70 int main(int argc, char *argv[]) {
     71     int print_cmd = 0;
     72     int config_cmd = 0;
     73     int add_cmd = 0;
     74     int del_cmd = 0;
     75     int sync_cmd = 0;
     76     int c;
     77     const char *new_partition = NULL;
     78     const char *old_partition = NULL;
     79     const char *type_guid = NULL;
     80     const char *partition_guid = NULL;
     81     unsigned gpt_location = 1;
     82 
     83     klog_init();
     84     klog_set_level(6);
     85 
     86     const struct option longopts[] = {
     87         {"print", no_argument, 0, 'p'},
     88         {"config-print", no_argument, 0, 'c'},
     89         {"add", no_argument, 0, 'a'},
     90         {"del", no_argument, 0, 'd'},
     91         {"new", required_argument, 0, 'n'},
     92         {"old", required_argument, 0, 'o'},
     93         {"type", required_argument, 0, 't'},
     94         {"sync", required_argument, 0, 's'},
     95         {"guid", required_argument, 0, 'g'},
     96         {"location", required_argument, 0, 'l'},
     97         {0, 0, 0, 0}
     98     };
     99 
    100     while (1) {
    101         c = getopt_long(argc, argv, "pcadt:g:n:o:sl:", longopts, NULL);
    102         /* Alphabetical cases */
    103         if (c < 0)
    104             break;
    105         switch (c) {
    106         case 'p':
    107             print_cmd = 1;
    108             break;
    109         case 'c':
    110             config_cmd = 1;
    111             break;
    112         case 'a':
    113             add_cmd = 1;
    114             break;
    115         case 'd':
    116             del_cmd = 1;
    117             break;
    118         case 'n':
    119             new_partition = optarg;
    120             break;
    121         case 'o':
    122             old_partition = optarg;
    123             break;
    124         case 't':
    125             type_guid = optarg;
    126         case 'g':
    127             partition_guid = optarg;
    128             break;
    129         case 's':
    130             sync_cmd = 1;
    131             break;
    132         case 'l':
    133             gpt_location = strtoul(optarg, NULL, 10);
    134             fprintf(stderr, "Got offset as %d", gpt_location);
    135             break;
    136         case '?':
    137             return 1;
    138         default:
    139             abort();
    140         }
    141     }
    142 
    143     argc -= optind;
    144     argv += optind;
    145 
    146     if (argc < 1) {
    147         usage();
    148         return 1;
    149     }
    150 
    151     const char *path = argv[0];
    152     struct GPT_entry_table *table = GPT_get_device(path, gpt_location);
    153     if (table == NULL) {
    154         fprintf(stderr, "unable to get GPT table from %s\n", path);
    155         return 1;
    156     }
    157 
    158     if (add_cmd)
    159         addGPT(table, new_partition, partition_guid, type_guid);
    160     if (del_cmd)
    161         deleteGPT(table, old_partition);
    162     if (print_cmd)
    163         printGPT(table);
    164     if (config_cmd)
    165         configPrintGPT(table);
    166     if (sync_cmd)
    167         GPT_sync(table);
    168 
    169     GPT_release_device(table);
    170 
    171     return 0;
    172 }
    173 
    174 void printGPT(struct GPT_entry_table *table) {
    175     struct GPT_entry_raw *entry = table->entries;
    176     unsigned n, m;
    177     char name[GPT_NAMELEN + 1];
    178 
    179     printf("ptn  start block   end block     name\n");
    180     printf("---- ------------- -------------\n");
    181 
    182     for (n = 0; n < table->header->entries_count; n++, entry++) {
    183         if (entry->type_guid[0] == 0)
    184             continue;
    185         for (m = 0; m < GPT_NAMELEN; m++) {
    186             name[m] = entry->name[m] & 127;
    187         }
    188         name[m] = 0;
    189         printf("#%03d %13"PRId64" %13"PRId64" %s\n",
    190             n + 1, entry->first_lba, entry->last_lba, name);
    191     }
    192 }
    193 
    194 void configPrintGPT(struct GPT_entry_table *table) {
    195     struct GPT_entry_raw *entry = table->entries;
    196     unsigned n, m;
    197     char name[GPT_NAMELEN + 1];
    198     char temp_guid[17];
    199     temp_guid[16] = 0;
    200 
    201     printf("header_lba %"PRId64"\n", table->header->current_lba);
    202     printf("backup_lba %"PRId64"\n", table->header->backup_lba);
    203     printf("first_lba %"PRId64"\n", table->header->first_usable_lba);
    204     printf("last_lba %"PRId64"\n", table->header->last_usable_lba);
    205     printf("entries_lba %"PRId64"\n", table->header->entries_lba);
    206     snprintf(temp_guid, 17, "%s", table->header->disk_guid);
    207     printf("guid \"%s\"", temp_guid);
    208 
    209     printf("\npartitions {\n");
    210 
    211     for (n = 0; n < table->header->entries_count; n++, entry++) {
    212         uint64_t size = entry->last_lba - entry->first_lba + 1;
    213 
    214         if (entry->type_guid[0] == 0)
    215             continue;
    216         for (m = 0; m < GPT_NAMELEN; m++) {
    217             name[m] = entry->name[m] & 127;
    218         }
    219         name[m] = 0;
    220 
    221         printf("    %s {\n", name);
    222         snprintf(temp_guid, 17, "%s", entry->partition_guid);
    223         printf("        guid \"%s\"\n", temp_guid);
    224         printf("        first_lba %"PRId64"\n", entry->first_lba);
    225         printf("        partition_size %"PRId64"\n", size);
    226         if (entry->flags & GPT_FLAG_SYSTEM)
    227             printf("        system\n");
    228         if (entry->flags & GPT_FLAG_BOOTABLE)
    229             printf("        bootable\n");
    230         if (entry->flags & GPT_FLAG_READONLY)
    231             printf("        readonly\n");
    232         if (entry->flags & GPT_FLAG_DOAUTOMOUNT)
    233             printf("        automount\n");
    234         printf("    }\n\n");
    235     }
    236     printf("}\n");
    237 }
    238 
    239 void addGPT(struct GPT_entry_table *table, const char *str  , const char *guid, const char *tguid) {
    240     char *c, *c2;
    241     char *arg = malloc(strlen(str));
    242     char *name = arg;
    243     unsigned start, end;
    244     strcpy(arg, str);
    245     if (guid == NULL || tguid == NULL) {
    246         fprintf(stderr, "Type guid and partion guid needed");
    247         free(arg);
    248         return;
    249     }
    250 
    251     c = strchr(arg, '@');
    252 
    253     if (c == NULL) {
    254         fprintf(stderr, "Wrong entry format");
    255         free(arg);
    256         return;
    257     }
    258 
    259     *c++ = '\0';
    260 
    261     c2 = strchr(c, ',');
    262 
    263     if (c2 == NULL) {
    264         fprintf(stderr, "Wrong entry format");
    265         free(arg);
    266         return;
    267     }
    268 
    269     start = strtoul(c, NULL, 10);
    270     *c2++ = '\0';
    271     end = strtoul(c2, NULL, 10);
    272 
    273     struct GPT_entry_raw data;
    274     strncpy((char *)data.partition_guid, guid, 15);
    275     data.partition_guid[15] = '\0';
    276     strncpy((char *)data.type_guid, tguid, 15);
    277     data.type_guid[15] = '\0';
    278     GPT_to_UTF16(data.name, name, GPT_NAMELEN);
    279     data.first_lba = start;
    280     data.last_lba = end;
    281 
    282     fprintf(stderr, "Adding (%d,%d) %s as, [%s, %s]", start, end, name, (char *) data.type_guid, (char *) data.partition_guid);
    283     GPT_add_entry(table, &data);
    284     free(arg);
    285 }
    286 
    287 void deleteGPT(struct GPT_entry_table *table, const char *name) {
    288     struct GPT_entry_raw *entry;
    289 
    290     if (name == NULL) {
    291         fprintf(stderr, "Need partition name");
    292         return;
    293     }
    294 
    295     entry = GPT_get_pointer_by_name(table, name);
    296 
    297     if (!entry) {
    298         fprintf(stderr, "Unable to find partition: %s", name);
    299         return;
    300     }
    301     GPT_delete_entry(table, entry);
    302 }
    303 
    304