fdisk: initial stab at GPT partition support

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index b6417a3..3f2e0d3 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -107,12 +107,30 @@
 	unsigned char size4[4];         /* nr of sectors in partition */
 } PACKED;
 
+/*
+ * per partition table entry data
+ *
+ * The four primary partitions have the same sectorbuffer (MBRbuffer)
+ * and have NULL ext_pointer.
+ * Each logical partition table entry has two pointers, one for the
+ * partition and one link to the next one.
+ */
+struct pte {
+	struct partition *part_table;   /* points into sectorbuffer */
+	struct partition *ext_pointer;  /* points into sectorbuffer */
+	sector_t offset_from_dev_start; /* disk sector number */
+	char *sectorbuffer;             /* disk sector contents */
+#if ENABLE_FEATURE_FDISK_WRITABLE
+	char changed;                   /* boolean */
+#endif
+};
+
 #define unable_to_open "can't open '%s'"
 #define unable_to_read "can't read from %s"
 #define unable_to_seek "can't seek on %s"
 
 enum label_type {
-	LABEL_DOS, LABEL_SUN, LABEL_SGI, LABEL_AIX, LABEL_OSF
+	LABEL_DOS, LABEL_SUN, LABEL_SGI, LABEL_AIX, LABEL_OSF, LABEL_GPT
 };
 
 #define LABEL_IS_DOS	(LABEL_DOS == current_label_type)
@@ -149,6 +167,14 @@
 #define STATIC_OSF extern
 #endif
 
+#if ENABLE_FEATURE_GPT_LABEL
+#define LABEL_IS_GPT	(LABEL_GPT == current_label_type)
+#define STATIC_GPT static
+#else
+#define LABEL_IS_GPT	0
+#define STATIC_GPT extern
+#endif
+
 enum action { OPEN_MAIN, TRY_ONLY, CREATE_EMPTY_DOS, CREATE_EMPTY_SUN };
 
 static void update_units(void);
@@ -162,6 +188,7 @@
 #endif
 static const char *partition_type(unsigned char type);
 static void get_geometry(void);
+static void read_pte(struct pte *pe, sector_t offset);
 #if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
 static int get_boot(enum action what);
 #else
@@ -174,24 +201,6 @@
 static sector_t get_start_sect(const struct partition *p);
 static sector_t get_nr_sects(const struct partition *p);
 
-/*
- * per partition table entry data
- *
- * The four primary partitions have the same sectorbuffer (MBRbuffer)
- * and have NULL ext_pointer.
- * Each logical partition table entry has two pointers, one for the
- * partition and one link to the next one.
- */
-struct pte {
-	struct partition *part_table;   /* points into sectorbuffer */
-	struct partition *ext_pointer;  /* points into sectorbuffer */
-	sector_t offset_from_dev_start; /* disk sector number */
-	char *sectorbuffer;             /* disk sector contents */
-#if ENABLE_FEATURE_FDISK_WRITABLE
-	char changed;                   /* boolean */
-#endif
-};
-
 /* DOS partition types */
 
 static const char *const i386_sys_types[] = {
@@ -653,6 +662,8 @@
 STATIC_OSF void xbsd_print_disklabel(int);
 #include "fdisk_osf.c"
 
+#include "fdisk_gpt.c"
+
 #if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
 static uint16_t
 fdisk_swap16(uint16_t x)
@@ -833,6 +844,11 @@
 		puts("o\tcreate a new empty DOS partition table");
 		puts("q\tquit without saving changes");
 		puts("s\tcreate a new empty Sun disklabel");  /* sun */
+	} else if (LABEL_IS_GPT) {
+		puts("o\tcreate a new empty DOS partition table");
+		puts("p\tprint the partition table");
+		puts("q\tquit without saving changes");
+		puts("s\tcreate a new empty Sun disklabel");  /* sun */
 	} else {
 		puts("a\ttoggle a bootable flag");
 		puts("b\tedit bsd disklabel");
@@ -1308,7 +1324,18 @@
 
 /*
  * Opens disk_device and optionally reads MBR.
- *    FIXME: document what each 'what' value will do!
+ *    If what == OPEN_MAIN:
+ *      Open device, read MBR.  Abort program on short read.  Create empty
+ *      disklabel if the on-disk structure is invalid (WRITABLE mode).
+ *    If what == TRY_ONLY:
+ *      Open device, read MBR.  Return an error if anything is out of place.
+ *      Do not create an empty disklabel.  This is used for the "list"
+ *      operations: "fdisk -l /dev/sda" and "fdisk -l" (all devices).
+ *    If what == CREATE_EMPTY_*:
+ *      This means that get_boot() was called recursively from create_*label().
+ *      Do not re-open the device; just set up the ptes array and print
+ *      geometry warnings.
+ *
  * Returns:
  *   -1: no 0xaa55 flag present (possibly entire disk BSD)
  *    0: found or created label
@@ -1390,6 +1417,10 @@
 	if (check_aix_label())
 		return 0;
 #endif
+#if ENABLE_FEATURE_GPT_LABEL
+	if (check_gpt_label())
+		return 0;
+#endif
 #if ENABLE_FEATURE_OSF_LABEL
 	if (check_osf_label()) {
 		possibly_osf_label = 1;
@@ -1409,7 +1440,7 @@
 	if (!valid_part_table_flag(MBRbuffer)) {
 		if (what == OPEN_MAIN) {
 			printf("Device contains neither a valid DOS "
-				  "partition table, nor Sun, SGI or OSF "
+				  "partition table, nor Sun, SGI, OSF or GPT "
 				  "disklabel\n");
 #ifdef __sparc__
 			IF_FEATURE_SUN_LABEL(create_sunlabel();)
@@ -2056,10 +2087,14 @@
 		sun_list_table(xtra);
 		return;
 	}
-	if (LABEL_IS_SUN) {
+	if (LABEL_IS_SGI) {
 		sgi_list_table(xtra);
 		return;
 	}
+	if (LABEL_IS_GPT) {
+		gpt_list_table(xtra);
+		return;
+	}
 
 	list_disk_geometry();