Nearly complete rewrite of cgpt tool.

This fixes a number of bugs, adds a bunch of commands, and essentially makes
cgpt ready to use as a replacement for gpt. Still to do is to add commands
and options that will let it generated intentionally bad partitions, for use
in testing.

Review URL: http://codereview.chromium.org/2719008
diff --git a/tests/Makefile b/tests/Makefile
index d52b282..5ad4b74 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -126,6 +126,8 @@
 	./kernel_rollback_tests
 	# Helper Library Tests
 	./cgptlib_test
+	# Tool tests
+	./run_cgpt_tests.sh
 
 clean:
 	rm -f $(TEST_BINS)
diff --git a/tests/cgptlib_test.c b/tests/cgptlib_test.c
index 1ab5342..f016b21 100644
--- a/tests/cgptlib_test.c
+++ b/tests/cgptlib_test.c
@@ -136,8 +136,8 @@
   Memcpy(header->signature, GPT_HEADER_SIGNATURE,
          sizeof(GPT_HEADER_SIGNATURE));
   header->revision = GPT_HEADER_REVISION;
-  header->size = sizeof(GptHeader) - sizeof(header->padding);
-  header->reserved = 0;
+  header->size = sizeof(GptHeader);
+  header->reserved_zero = 0;
   header->my_lba = 1;
   header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
   header->first_usable_lba = 34;
@@ -157,7 +157,6 @@
   Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
   entries[3].starting_lba = 334;
   entries[3].ending_lba = 430;
-  Memset(header->padding, 0, sizeof(header->padding));
 
   /* build secondary */
   header2 = (GptHeader*)gpt->secondary_header;
@@ -355,8 +354,8 @@
   GptHeader* h2 = (GptHeader*)gpt->secondary_header;
 
   BuildTestGptData(gpt);
-  h1->reserved ^= 0x12345678;  /* whatever random */
-  h2->reserved ^= 0x12345678;  /* whatever random */
+  h1->reserved_zero ^= 0x12345678;  /* whatever random */
+  h2->reserved_zero ^= 0x12345678;  /* whatever random */
   RefreshCrc32(gpt);
   EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
   EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
diff --git a/tests/common.sh b/tests/common.sh
index 421f629..6afcd77 100755
--- a/tests/common.sh
+++ b/tests/common.sh
@@ -30,10 +30,21 @@
 hash_algos=( sha1 sha256 sha512 )
 key_lengths=( 1024 2048 4096 8192 ) 
 
-function check_test_keys {
-  if [ ! -d ${TESTKEY_DIR} ]
-  then
-    echo "You must run gen_test_keys.sh to generate test keys first."
-    exit 1
-  fi
+function happy {
+  echo -e "${COL_GREEN}$*${COL_STOP}" 1>&2
 }
+
+function warning {
+  echo -e "${COL_YELLOW}WARNING: $*${COL_STOP}" 1>&2
+}
+
+function error {
+  echo -e "${COL_RED}ERROR: $*${COL_STOP}" 1>&2
+  exit 1
+}
+
+function check_test_keys {
+  [ -d ${TESTKEY_DIR} ] || \
+    error "You must run gen_test_keys.sh to generate test keys first."
+}
+
diff --git a/tests/run_cgpt_tests.sh b/tests/run_cgpt_tests.sh
new file mode 100755
index 0000000..2dcca99
--- /dev/null
+++ b/tests/run_cgpt_tests.sh
@@ -0,0 +1,114 @@
+#!/bin/bash -eu
+
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Run tests for RSA Signature verification.
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+GPT=${1:-../cgpt/cgpt}
+[ -x "$GPT" ] || error "Can't execute $GPT"
+warning "testing $GPT"
+
+echo "Create an empty file to use as the device..."
+NUM_SECTORS=1000
+DEV=$(mktemp)
+BOOTFILE=$(mktemp)
+dd if=/dev/zero of=${DEV} conv=notrunc bs=512 count=${NUM_SECTORS} 2>/dev/null
+trap "rm -f ${DEV}" EXIT
+
+
+echo "Create a bunch of partitions, using the real GUID types..."
+DATA_START=100
+DATA_SIZE=20
+DATA_LABEL="data stuff"
+DATA_GUID='ebd0a0a2-b9e5-4433-87c0-68b6b72699c7'
+DATA_NUM=1
+
+KERN_START=200
+KERN_SIZE=30
+KERN_LABEL="kernel stuff"
+KERN_GUID='fe3a2a5d-4f32-41a7-b725-accc3285a309'
+KERN_NUM=2
+
+ROOTFS_START=300
+ROOTFS_SIZE=40
+ROOTFS_LABEL="rootfs stuff"
+ROOTFS_GUID='3cb8e202-3b7e-47dd-8a3c-7ff2a13cfcec'
+ROOTFS_NUM=3
+
+ESP_START=400
+ESP_SIZE=50
+ESP_LABEL="ESP stuff"
+ESP_GUID='c12a7328-f81f-11d2-ba4b-00a0c93ec93b'
+ESP_NUM=4
+
+FUTURE_START=500
+FUTURE_SIZE=60
+FUTURE_LABEL="future stuff"
+FUTURE_GUID='2e0a753d-9e48-43b0-8337-b15192cb1b5e'
+FUTURE_NUM=5
+
+RANDOM_START=600
+RANDOM_SIZE=70
+RANDOM_LABEL="random stuff"
+RANDOM_GUID='2364a860-bf63-42fb-a83d-9ad3e057fcf5'
+RANDOM_NUM=6
+
+$GPT create ${DEV}
+
+$GPT add -b ${DATA_START} -s ${DATA_SIZE} -t ${DATA_GUID} \
+  -l "${DATA_LABEL}" ${DEV}
+$GPT add -b ${KERN_START} -s ${KERN_SIZE} -t ${KERN_GUID} \
+  -l "${KERN_LABEL}" ${DEV}
+$GPT add -b ${ROOTFS_START} -s ${ROOTFS_SIZE} -t ${ROOTFS_GUID} \
+  -l "${ROOTFS_LABEL}" ${DEV}
+$GPT add -b ${ESP_START} -s ${ESP_SIZE} -t ${ESP_GUID} \
+  -l "${ESP_LABEL}" ${DEV}
+$GPT add -b ${FUTURE_START} -s ${FUTURE_SIZE} -t ${FUTURE_GUID} \
+  -l "${FUTURE_LABEL}" ${DEV}
+$GPT add -b ${RANDOM_START} -s ${RANDOM_SIZE} -t ${RANDOM_GUID} \
+  -l "${RANDOM_LABEL}" ${DEV}
+
+
+echo "Extract the start and size of given partitions..."
+
+X=$($GPT show -b -i $DATA_NUM ${DEV})
+Y=$($GPT show -s -i $DATA_NUM ${DEV})
+[ "$X $Y" = "$DATA_START $DATA_SIZE" ] || error "fail at line $LINENO"
+
+X=$($GPT show -b -i $KERN_NUM ${DEV})
+Y=$($GPT show -s -i $KERN_NUM ${DEV})
+[ "$X $Y" = "$KERN_START $KERN_SIZE" ] || error "fail at line $LINENO"
+
+X=$($GPT show -b -i $ROOTFS_NUM ${DEV})
+Y=$($GPT show -s -i $ROOTFS_NUM ${DEV})
+[ "$X $Y" = "$ROOTFS_START $ROOTFS_SIZE" ] || error "fail at line $LINENO"
+
+X=$($GPT show -b -i $ESP_NUM ${DEV})
+Y=$($GPT show -s -i $ESP_NUM ${DEV})
+[ "$X $Y" = "$ESP_START $ESP_SIZE" ] || error "fail at line $LINENO"
+
+X=$($GPT show -b -i $FUTURE_NUM ${DEV})
+Y=$($GPT show -s -i $FUTURE_NUM ${DEV})
+[ "$X $Y" = "$FUTURE_START $FUTURE_SIZE" ] || error "fail at line $LINENO"
+
+X=$($GPT show -b -i $RANDOM_NUM ${DEV})
+Y=$($GPT show -s -i $RANDOM_NUM ${DEV})
+[ "$X $Y" = "$RANDOM_START $RANDOM_SIZE" ] || error "fail at line $LINENO"
+
+
+echo "Set the boot partition.."
+$GPT boot -i ${KERN_NUM} ${DEV} >/dev/null
+
+echo "Check the PMBR's idea of the boot partition..."
+X=$($GPT boot ${DEV})
+Y=$($GPT show -u -i $KERN_NUM $DEV)
+[ "$X" = "$Y" ] || error "fail at line $LINENO"
+
+echo "Done."
+
+happy "All tests passed."