/*
 * gpt.c:
 *
 * Copyright (c) 2007 James McKenzie <james@fishsoup.dhs.org>,
 * All rights reserved.
 *
 */

static char rcsid[] = "$Id: gpt.c,v 1.21 2012/03/11 11:30:50 james Exp $";

/*
 * $Log: gpt.c,v $
 * Revision 1.21  2012/03/11 11:30:50  james
 * *** empty log message ***
 *
 * Revision 1.20  2012/03/11 11:15:50  james
 * *** empty log message ***
 *
 * Revision 1.19  2012/03/11 10:54:21  james
 * *** empty log message ***
 *
 * Revision 1.18  2012/03/11 10:52:06  james
 * *** empty log message ***
 *
 * Revision 1.17  2011/08/07 11:33:43  james
 * add support for repairing half a table
 *
 * Revision 1.16  2009/05/06 01:35:00  james
 * *** empty log message ***
 *
 * Revision 1.15  2009/05/06 01:12:55  james
 * *** empty log message ***
 *
 * Revision 1.14  2008/01/25 03:01:06  james
 * *** empty log message ***
 *
 * Revision 1.13  2007/11/13 15:18:30  james
 * *** empty log message ***
 *
 * Revision 1.12  2007/11/12 13:28:04  james
 * *** empty log message ***
 *
 * Revision 1.11  2007/10/17 09:51:42  james
 * *** empty log message ***
 *
 * Revision 1.10  2007/10/16 10:37:15  james
 * *** empty log message ***
 *
 * Revision 1.9  2007/10/16 10:36:11  james
 * *** empty log message ***
 *
 * Revision 1.8  2007/10/16 10:20:57  james
 * *** empty log message ***
 *
 * Revision 1.7  2007/10/16 10:07:49  james
 * *** empty log message ***
 *
 * Revision 1.6  2007/09/10 11:23:08  root
 * *** empty log message ***
 *
 * Revision 1.4  2007/09/09 22:30:05  root
 * *** empty log message ***
 *
 * Revision 1.3  2007/09/09 22:29:50  root
 * *** empty log message ***
 *
 * Revision 1.2  2007/09/08 18:21:23  root
 * *** empty log message ***
 *
 * Revision 1.1  2007/09/08 16:49:37  root
 * *** empty log message ***
 *
 */



#include "project.h"

void
usage (void)
{
  fprintf (stderr, "gpt %s\n", get_version ());
  fprintf (stderr,
           "Usage:\n"
           "gpt -h                            show help\n"
           "gpt -d disk-device -l             list partitions\n"
           "gpt -d disk-device -s             print the address of frist usable sector\n"
           "                                  on the disk\n"
           "                                  the last usable sector on the disk\n"
#if 0
           "gpt -d disk-device -e             print the address of the sector after the\n"
           "                                  the last addressable sector on the disk\n"
#endif
           "gpt -d disk-device -e             print the address of the last sector\n"
           "                                  usable as a partition\n"
           "gpt -d disk-device -f n           print the lba of the last sector in\n"
           "                                  parition n\n"
           "gpt -d disk-device -g n           print the partition type of partition n\n"
           "gpt -d disk-device -n             write a new blank parition table to the disk\n"
           "                                  the end of parition n\n"
           "gpt -d disk-device -a n name type start end [partition-guid]\n"
           "                                  set partiton n, type can either be a named\n"
           "                                  type or a hexadecimal GUID\n"
           "gpt -d disk-device -c             fill the PMBR with entries taken from\n"
           "                                  the first few GPT entries, using dark\n"
           "                                  voodoo\n");
  exit (1);
}


int
main (int argc, char *argv[])
{
  DISK *d = NULL;
  GPT_headers h;
  GPT_entry e;
  int c;
  int n;
  int aflag = 0;
  uint64_t start_lba, end_lba;
  extern char *optarg;
  extern int optind;
  uint32_t crc;

  fprintf (stderr, "sizeof(off_t)=%d\n", sizeof (off_t));

  while ((c = getopt (argc, argv, "Cqd:hlsef:g:unac")) != EOF)
    {
      switch (c)
        {

        case 'C':
          n = 0;

          if (d)
            {
              h = headers_get (d);
              n = header_check_crc (d, &h.header);
              if (n)
                n = header_check_crc (d, &h.header);
            }

          return n ? 0 : -1;
        case 'd':
          d = disk_open (optarg);
          if (!d)
            {
              fprintf (stderr, "failed to open disk %s\n", optarg);
              perror ("open");
              return -1;
            }
          break;
        case 'e':
          if (!d)
            usage ();
          h = headers_get (d);
          printf ("%lld\n", (long long) h.header.last_usable_lba);
          return 0;
        case 's':
          if (!d)
            usage ();
          h = headers_get (d);
          printf ("%lld\n", (long long) h.header.first_usable_lba);
          return 0;
        case 'u':
          if (!d)
            usage ();
          h = headers_get (d);
          printf ("%lld\n", (long long) h.header.last_usable_lba);
          return 0;
        case 'f':
          h = headers_get (d);
          n = atoi (optarg);
          e = entry_read (d, &h.header, n);
          printf ("%lld\n", e.end);
          return 0;
        case 'g':
          h = headers_get (d);
          n = atoi (optarg);
          e = entry_read (d, &h.header, n);
          printf ("%s\n", guid_to_a (e.type));
          return 0;
        case 'q':
          if (!d)
            usage ();
          fixup (d);
          disk_reread_kernel_table (d);
          return 0;
        case 'n':
          if (!d)
            usage ();
          new (d);
          disk_reread_kernel_table (d);
          return 0;
        case 'a':
          aflag++;
          break;
        case 'l':
          if (!d)
            usage ();
          show (d);
          return 0;
        case 'c':
          if (!d)
            usage ();
          sync_tables (d);
          show (d);
          disk_reread_kernel_table (d);
          return 0;
        default:
          usage ();
        }
    }

  if (!aflag)
    usage ();
  if (!d)
    usage ();

  if (((argc - optind) != 5) && ((argc - optind) != 6))
    usage ();

  start_lba = strtoll (argv[optind + 3], NULL, 0);
  end_lba = strtoll (argv[optind + 4], NULL, 0);
//printf("%lld %lld\n",(long long)start_lba,(long long) end_lba);

  n = atoi (argv[optind]);

  modify (d, n, argv[optind + 1], argv[optind + 2], start_lba, end_lba,
          ((argc - optind) == 6) ? argv[optind + 5] : NULL);

  show (d);
  disk_reread_kernel_table (d);
  return 0;
}