Misc. updates and bug fixes
diff --git a/CHANGELOG b/CHANGELOG
index c09020a..a5a7c84 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,10 @@
 0.6.2 (?/??/2010):
 ------------------
 
+- Fixed bug that caused new protective MBR to not be created when the
+  MBR was invalid and the GPT was damaged and the user opts to try to
+  use the GPT data.
+
 - Enabled default partition type code of 0700 when creating partitions
   or changing their type codes. (Type 0700, Linux/Windows data, is set if
   the user hits the Enter key alone.)
diff --git a/attributes.cc b/attributes.cc
index 73560d6..9bdd428 100644
--- a/attributes.cc
+++ b/attributes.cc
@@ -11,6 +11,7 @@
 #include <string.h>
 #include <stdint.h>
 #include <stdio.h>
+#include <iostream>
 #include "attributes.h"
 
 using namespace std;
@@ -25,14 +26,14 @@
    // appropriate name
    for (i = 1; i < NUM_ATR; i++) {
       sprintf(temp, "Undefined bit #%d", i);
-      strcpy(atNames[i], temp);
+      atNames[i] = temp;
    } // for
 
    // Now reset those names that are defined....
-   strcpy(atNames[0], "system partition");
-   strcpy(atNames[60], "read-only");
-   strcpy(atNames[62], "hidden");
-   strcpy(atNames[63], "do not automount");
+   atNames[0] = "system partition";
+   atNames[60] = "read-only";
+   atNames[62] = "hidden";
+   atNames[63] = "do not automount";
 } // Attributes constructor
 
 // Destructor.
@@ -43,16 +44,18 @@
 void Attributes::DisplayAttributes(void) {
    int i;
 
-   printf("Attribute value is %llX. Set fields are:\n",
-          (unsigned long long) attributes);
+   cout << "Attribute value is ";
+   cout.setf(ios::uppercase);
+   cout.fill('0');
+   cout.width(16);
+   cout << hex << attributes << dec << ". Set fields are:\n";
    for (i = 0; i < NUM_ATR; i++) {
       if (((attributes >> i) % 2) == 1) { // bit is set
-/*         if (strncmp("Undefined", atNames[i], 9) != 0)
-            printf("%s\n", atNames[i]); */
-         if (strncmp("Undefined", atNames[NUM_ATR - i - 1], 9) != 0)
-            printf("%s\n", atNames[NUM_ATR - i - 1]);
+         if (atNames[NUM_ATR - i - 1].substr(0, 9) != "Undefined")
+            cout << atNames[NUM_ATR - i - 1] << "\n";
       } // if
    } // for
+   cout.fill(' ');
 } // Attributes::DisplayAttributes()
 
 // Prompt user for attribute changes
@@ -60,23 +63,22 @@
    int response, i;
    uint64_t bitValue;
 
-   printf("Known attributes are:\n");
+   cout << "Known attributes are:\n";
    for (i = 0; i < NUM_ATR; i++) {
-      if (strncmp("Undefined", atNames[i], 9) != 0)
-         printf("%d - %s\n", i, atNames[i]);
+      if (atNames[i].substr(0, 9) != "Undefined")
+         cout << i << " - " << atNames[i] << "\n";
    } // for
 
    do {
-      response = GetNumber(0, 64, -1, "Toggle which attribute field (0-63, 64 to exit): ");
+      response = GetNumber(0, 64, -1, (string) "Toggle which attribute field (0-63, 64 to exit): ");
       if (response != 64) {
          bitValue = PowerOf2(NUM_ATR - response - 1); // Find the integer value of the bit
-//         bitValue = PowerOf2(response); // Find the integer value of the bit
          if ((bitValue & attributes) == bitValue) { // bit is set
             attributes -= bitValue; // so unset it
-	    printf("Have disabled the '%s' attribute.\n", atNames[response]);
+	    cout << "Have disabled the '" << atNames[response] << "' attribute.\n";
          } else { // bit is not set
             attributes += bitValue; // so set it
-	    printf("Have enabled the '%s' attribute.\n", atNames[response]);
+            cout << "Have enabled the '" << atNames[response] << "' attribute.\n";
          } // if/else
       } // if
    } while (response != 64);
diff --git a/attributes.h b/attributes.h
index 38313d7..647c205 100644
--- a/attributes.h
+++ b/attributes.h
@@ -18,7 +18,7 @@
 class Attributes {
 protected:
    uint64_t attributes;
-   char atNames[NUM_ATR][ATR_NAME_SIZE];
+   string atNames[NUM_ATR];
 public:
    Attributes(void);
    ~Attributes(void);
diff --git a/bsd.cc b/bsd.cc
index 7052001..1db68ea 100644
--- a/bsd.cc
+++ b/bsd.cc
@@ -14,9 +14,10 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <fcntl.h>
-#include <string.h>
 #include <sys/stat.h>
 #include <errno.h>
+#include <iostream>
+#include <string>
 #include "support.h"
 #include "bsd.h"
 
@@ -41,39 +42,30 @@
 
 // Read BSD disklabel data from the specified device filename. This function
 // just opens the device file and then calls an overloaded function to do
-// the bulk of the work.
-int BSDData::ReadBSDData(char* device, uint64_t startSector, uint64_t endSector) {
-   int allOK = 1, tempMyDisk = 0;
+// the bulk of the work. Returns 1 on success, 0 on failure.
+int BSDData::ReadBSDData(string *device, uint64_t startSector, uint64_t endSector) {
+   int allOK = 1;
+   DiskIO myDisk;
 
-   if (device != NULL) {
-      if (myDisk == NULL) {
-         myDisk = new DiskIO;
-         tempMyDisk = 1;
-      } // if
-      if (myDisk->OpenForRead(device)) {
-         ReadBSDData(myDisk, startSector, endSector);
+   if (*device != "") {
+      if (myDisk.OpenForRead(*device)) {
+         allOK = ReadBSDData(&myDisk, startSector, endSector);
       } else {
          allOK = 0;
       } // if/else
 
-      myDisk->Close();
+      myDisk.Close();
    } else {
       allOK = 0;
    } // if/else
-
-   if (tempMyDisk) {
-      delete myDisk;
-      myDisk = NULL;
-   } // if
-
    return allOK;
 } // BSDData::ReadBSDData() (device filename version)
 
 // Load the BSD disklabel data from an already-opened disk
 // file, starting with the specified sector number.
-void BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSector) {
+int BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSector) {
    uint8_t buffer[4096]; // I/O buffer
-   int i, err, foundSig = 0, bigEnd = 0;
+   int i, err, foundSig = 0, bigEnd = 0, allOK = 1;
    int relative = 0; // assume absolute partition sector numbering
    uint32_t realSig;
    uint32_t* temp32;
@@ -81,54 +73,59 @@
    BSDRecord* tempRecords;
    int offset[NUM_OFFSETS] = { LABEL_OFFSET1, LABEL_OFFSET2 };
 
-   myDisk = theDisk;
+//   myDisk = theDisk;
    labelFirstLBA = startSector;
    labelLastLBA = endSector;
-   offset[1] = myDisk->GetBlockSize();
+   offset[1] = theDisk->GetBlockSize();
 
    // Read 4096 bytes (eight 512-byte sectors or equivalent)
    // into memory; we'll extract data from this buffer.
    // (Done to work around FreeBSD limitation on size of reads
    // from block devices.)
-   myDisk->Seek(startSector /* * myDisk->GetBlockSize() */);
-   myDisk->Read(buffer, 4096);
+   allOK = theDisk->Seek(startSector);
+   if (allOK) allOK = theDisk->Read(buffer, 4096);
 
    // Do some strangeness to support big-endian architectures...
    bigEnd = (IsLittleEndian() == 0);
    realSig = BSD_SIGNATURE;
-   if (bigEnd)
+   if (bigEnd && allOK)
       ReverseBytes(&realSig, 4);
 
    // Look for the signature at any of two locations.
    // Note that the signature is repeated at both the original
    // offset and 132 bytes later, so we need two checks....
-   i = 0;
-   do {
-      temp32 = (uint32_t*) &buffer[offset[i]];
-      signature = *temp32;
-      if (signature == realSig) { // found first, look for second
-         temp32 = (uint32_t*) &buffer[offset[i] + 132];
-         signature2 = *temp32;
-         if (signature2 == realSig) {
-            foundSig = 1;
-            labelStart = offset[i];
-         } // if found signature
-      } // if/else
-      i++;
-   } while ((!foundSig) && (i < NUM_OFFSETS));
+   if (allOK) {
+      i = 0;
+      do {
+         temp32 = (uint32_t*) &buffer[offset[i]];
+         signature = *temp32;
+         if (signature == realSig) { // found first, look for second
+            temp32 = (uint32_t*) &buffer[offset[i] + 132];
+            signature2 = *temp32;
+            if (signature2 == realSig) {
+               foundSig = 1;
+               labelStart = offset[i];
+            } // if found signature
+         } // if/else
+         i++;
+      } while ((!foundSig) && (i < NUM_OFFSETS));
+      allOK = foundSig;
+   } // if
 
    // Load partition metadata from the buffer....
-   temp32 = (uint32_t*) &buffer[labelStart + 40];
-   sectorSize = *temp32;
-   temp16 = (uint16_t*) &buffer[labelStart + 138];
-   numParts = *temp16;
+   if (allOK) {
+      temp32 = (uint32_t*) &buffer[labelStart + 40];
+      sectorSize = *temp32;
+      temp16 = (uint16_t*) &buffer[labelStart + 138];
+      numParts = *temp16;
+   } // if
 
    // Make it big-endian-aware....
-   if (IsLittleEndian() == 0)
+   if ((IsLittleEndian() == 0) && allOK)
       ReverseMetaBytes();
 
    // Check validity of the data and flag it appropriately....
-   if (foundSig && (numParts <= MAX_BSD_PARTS)) {
+   if (foundSig && (numParts <= MAX_BSD_PARTS) && allOK) {
       state = bsd;
    } else {
       state = bsd_invalid;
@@ -167,7 +164,8 @@
       } // if
    } // if signatures OK
 //   DisplayBSDData();
-} // BSDData::ReadBSDData(int fd, uint64_t startSector)
+   return allOK;
+} // BSDData::ReadBSDData(DiskIO* theDisk, uint64_t startSector)
 
 // Reverse metadata's byte order; called only on big-endian systems
 void BSDData::ReverseMetaBytes(void) {
@@ -182,12 +180,19 @@
    int i;
 
    if (state == bsd) {
-      printf("BSD partitions:\n");
-      printf("Number\t Start (sector)\t Length (sectors)\tType\n");
+      cout << "BSD partitions:\n";
       for (i = 0; i < numParts; i++) {
-         printf("%4d\t%13lu\t%15lu \t0x%02X\n", i + 1,
-                (unsigned long) partitions[i].firstLBA,
-                (unsigned long) partitions[i].lengthLBA, partitions[i].fsType);
+         cout.width(4);
+         cout << i + 1 << "\t";
+         cout.width(13);
+         cout << partitions[i].firstLBA << "\t";
+         cout.width(15);
+         cout << partitions[i].lengthLBA << " \t0x";
+         cout.width(2);
+         cout.fill('0');
+         cout.setf(ios::uppercase);
+         cout << hex << (int) partitions[i].fsType << "\n" << dec;
+         cout.fill(' ');
       } // for
    } // if
 } // BSDData::DisplayBSDData()
@@ -199,14 +204,14 @@
 
    switch (state) {
       case bsd_invalid:
-         printf("  BSD: not present\n");
+         cout << "  BSD: not present\n";
          break;
       case bsd:
-         printf("  BSD: present\n");
+         cout << "  BSD: present\n";
          retval = 1;
          break;
       default:
-         printf("\a  BSD: unknown -- bug!\n");
+         cout << "\a  BSD: unknown -- bug!\n";
          break;
    } // switch
    return retval;
@@ -318,7 +323,7 @@
             guid.SetType(0x0700); break;
       } // switch
       // Set the partition name to the name of the type code....
-      guid.SetName((unsigned char*) guid.GetNameType().c_str());
+      guid.SetName(guid.GetNameType());
    } // if
    return guid;
 } // BSDData::AsGPT()
diff --git a/bsd.h b/bsd.h
index 77d3d3c..54f5899 100644
--- a/bsd.h
+++ b/bsd.h
@@ -69,12 +69,11 @@
       uint64_t labelLastLBA;     // final sector of BSD disklabel
       uint64_t labelStart;       // BSD disklabel start point in bytes from labelFirstLBA
       BSDValidity state;
-      DiskIO *myDisk;
    public:
       BSDData(void);
       ~BSDData(void);
-      int ReadBSDData(char* deviceFilename, uint64_t startSector, uint64_t endSector);
-      void ReadBSDData(DiskIO *myDisk, uint64_t startSector, uint64_t endSector);
+      int ReadBSDData(string *deviceFilename, uint64_t startSector, uint64_t endSector);
+      int ReadBSDData(DiskIO *myDisk, uint64_t startSector, uint64_t endSector);
       void ReverseMetaBytes(void);
       void DisplayBSDData(void);
       int ShowState(void); // returns 1 if BSD disklabel detected
diff --git a/diskio-unix.cc b/diskio-unix.cc
index 573af56..a72c7ce 100644
--- a/diskio-unix.cc
+++ b/diskio-unix.cc
@@ -16,7 +16,7 @@
 #define __STDC_CONSTANT_MACROS
 
 #include <sys/ioctl.h>
-#include <stdio.h>
+#include <string.h>
 #include <string>
 #include <stdint.h>
 #include <errno.h>
@@ -24,7 +24,6 @@
 #include <sys/stat.h>
 #include <iostream>
 
-#include "support.h"
 #include "diskio.h"
 
 using namespace std;
@@ -50,10 +49,9 @@
    if (shouldOpen) {
       fd = open(realFilename.c_str(), O_RDONLY);
       if (fd == -1) {
-         fprintf(stderr, "Problem opening %s for reading! Error is %d\n",
-                 realFilename.c_str(), errno);
+         cerr << "Problem opening " << realFilename << " for reading! Error is " << errno << "\n";
          if (errno == EACCES) { // User is probably not running as root
-            fprintf(stderr, "You must run this program as root or use sudo!\n");
+            cerr << "You must run this program as root or use sudo!\n";
          } // if
          realFilename = "";
          userFilename = "";
@@ -82,7 +80,7 @@
 #ifdef __APPLE__
    // MacOS X requires a shared lock under some circumstances....
    if (fd < 0) {
-      fd = open(realFilename.c_str(), O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH | O_SHLOCK);
+      fd = open(realFilename.c_str(), O_WRONLY | O_SHLOCK);
    } // if
 #endif
    if (fd >= 0) {
@@ -133,8 +131,8 @@
          // 32-bit code returns EINVAL, I don't know why. I know I'm treading on
          // thin ice here, but it should be OK in all but very weird cases....
          if ((errno != ENOTTY) && (errno != EINVAL)) {
-            printf("\aError %d when determining sector size! Setting sector size to %d\n",
-                  errno, SECTOR_SIZE);
+            cerr << "\aError " << errno << " when determining sector size! Setting sector size to "
+                 << SECTOR_SIZE << "\n";
          } // if
       } // if (err == -1)
    } // if (isOpen)
@@ -155,8 +153,8 @@
    if (isOpen) {
       sync();
 #ifdef __APPLE__
-      printf("Warning: The kernel may continue to use old or deleted partitions.\n"
-            "You should reboot or remove the drive.\n");
+      cout << "Warning: The kernel may continue to use old or deleted partitions.\n"
+           << "You should reboot or remove the drive.\n";
                /* don't know if this helps
                * it definitely will get things on disk though:
                * http://topiks.org/mac-os-x/0321278542/ch12lev1sec8.html */
@@ -166,22 +164,22 @@
 #ifdef __FreeBSD__
       sleep(2);
       i = ioctl(fd, DIOCGFLUSH);
-      printf("Warning: The kernel may continue to use old or deleted partitions.\n"
-            "You should reboot or remove the drive.\n");
+      cout << "Warning: The kernel may continue to use old or deleted partitions.\n"
+           << "You should reboot or remove the drive.\n";
       platformFound++;
 #endif
 #ifdef __linux__
       sleep(2);
       i = ioctl(fd, BLKRRPART);
       if (i)
-         printf("Warning: The kernel is still using the old partition table.\n"
-               "The new table will be used at the next reboot.\n");
+         cout << "Warning: The kernel is still using the old partition table.\n"
+              << "The new table will be used at the next reboot.\n";
       platformFound++;
 #endif
       if (platformFound == 0)
-         fprintf(stderr, "Warning: Platform not recognized!\n");
+         cerr << "Warning: Platform not recognized!\n";
       if (platformFound > 1)
-         fprintf(stderr, "\nWarning: We seem to be running on multiple platforms!\n");
+         cerr << "\nWarning: We seem to be running on multiple platforms!\n";
    } // if (isOpen)
 } // DiskIO::DiskSync()
 
@@ -233,9 +231,6 @@
       // Read the data into temporary space, then copy it to buffer
       retval = read(fd, tempSpace, numBlocks * blockSize);
       memcpy(buffer, tempSpace, numBytes);
-/*      for (i = 0; i < numBytes; i++) {
-         ((char*) buffer)[i] = tempSpace[i];
-      } // for */
 
       // Adjust the return value, if necessary....
       if (((numBlocks * blockSize) != numBytes) && (retval > 0))
@@ -347,7 +342,7 @@
       platformFound++;
 #endif
       if (platformFound != 1)
-         fprintf(stderr, "Warning! We seem to be running on no known platform!\n");
+         cerr << "Warning! We seem to be running on no known platform!\n";
 
       // The above methods have failed, so let's assume it's a regular
       // file (a QEMU image, dd backup, or what have you) and see what
@@ -356,8 +351,8 @@
          if (fstat64(fd, &st) == 0) {
             bytes = (off_t) st.st_size;
             if ((bytes % UINT64_C(512)) != 0)
-               fprintf(stderr, "Warning: File size is not a multiple of 512 bytes!"
-                       " Misbehavior is likely!\n\a");
+               cerr << "Warning: File size is not a multiple of 512 bytes!"
+                    << " Misbehavior is likely!\n\a";
             sectors = bytes / UINT64_C(512);
          } // if
       } // if
diff --git a/diskio.cc b/diskio.cc
index 3fc3726..d1d0c3c 100644
--- a/diskio.cc
+++ b/diskio.cc
@@ -114,11 +114,11 @@
    int err = -2, errnum = 0, result = 8, physicalSectorSize = 4096;
    uint64_t diskSize;
 
-   printf("Entering FindAlignment()\n");
+   cout << "Entering FindAlignment()\n";
 #if defined (__linux__) && defined (BLKPBSZGET)
    err = ioctl(fd, BLKPBSZGET, &physicalSectorSize);
-   printf("In FindAlignment(), physicalSectorSize = %d, err = %d\n", physicalSectorSize, err);
-//   printf("Tried to get hardware alignment; err is %d, sector size is %d\n", err, physicalSectorSize);
+   cout << "In FindAlignment(), physicalSectorSize = " << physicalSectorSize
+        << ", err = " << err << "\n";
 #else
    err = -1;
 #endif
diff --git a/diskio.h b/diskio.h
index 2435cc5..8b752ed 100644
--- a/diskio.h
+++ b/diskio.h
@@ -59,10 +59,8 @@
 #endif
    public:
       DiskIO(void);
-//      DiskIO(const DiskIO & orig);
       ~DiskIO(void);
 
-//      DiskIO & operator=(const DiskIO & orig);
       void MakeRealName(void);
       int OpenForRead(string filename);
       int OpenForRead(void);
diff --git a/gdisk.cc b/gdisk.cc
index 0809c3c..2329fac 100644
--- a/gdisk.cc
+++ b/gdisk.cc
@@ -9,18 +9,20 @@
 
 //#include <iostream>
 #include <stdio.h>
-#include <string.h>
 #include <getopt.h>
+#include <string.h>
+#include <string>
+#include <iostream>
 #include "mbr.h"
 #include "gpt.h"
 #include "support.h"
 
 // Function prototypes....
-void MainMenu(char* filename, struct GPTData* theGPT);
+void MainMenu(string filename, struct GPTData* theGPT);
 void ShowCommands(void);
-void ExpertsMenu(char* filename, struct GPTData* theGPT);
+void ExpertsMenu(string filename, struct GPTData* theGPT);
 void ShowExpertCommands(void);
-void RecoveryMenu(char* filename, struct GPTData* theGPT);
+void RecoveryMenu(string filename, struct GPTData* theGPT);
 void ShowRecoveryCommands(void);
 
 int main(int argc, char* argv[]) {
@@ -28,7 +30,7 @@
    int doMore = 1;
    char* device = NULL;
 
-   printf("GPT fdisk (gdisk) version %s\n\n", GPTFDISK_VERSION);
+   cout << "GPT fdisk (gdisk) version " << GPTFDISK_VERSION << "\n\n";
 
     if (argc == 2) { // basic usage
       if (SizesOK()) {
@@ -44,22 +46,22 @@
          } else if (strcmp(argv[2], "-l") == 0) {
             device = argv[1];
          } else { // 3 arguments, but none is "-l"
-            fprintf(stderr, "Usage: %s [-l] device_file\n", argv[0]);
+            cerr << "Usage: " << argv[0] << " [-l] device_file\n";
          } // if/elseif/else
          if (device != NULL) {
             theGPT.JustLooking();
-            doMore = theGPT.LoadPartitions(device);
+            doMore = theGPT.LoadPartitions((string) device);
             if (doMore) theGPT.DisplayGPTData();
          } // if
       } // if
    } else {
-      fprintf(stderr, "Usage: %s [-l] device_file\n", argv[0]);
+      cerr << "Usage: " << argv[0] << " [-l] device_file\n";
    } // if/else
 } // main
 
 // Accept a command and execute it. Returns only when the user
 // wants to exit (such as after a 'w' or 'q' command).
-void MainMenu(char* filename, struct GPTData* theGPT) {
+void MainMenu(string filename, struct GPTData* theGPT) {
    char command, line[255], buFile[255];
    char* junk;
    int goOn = 1;
@@ -67,12 +69,14 @@
    uint32_t temp1, temp2;
 
    do {
-      printf("\nCommand (? for help): ");
+      cout << "\nCommand (? for help): ";
       junk = fgets(line, 255, stdin);
       sscanf(line, "%c", &command);
       switch (command) {
+         case '\n':
+            break;
          case 'b': case 'B':
-            printf("Enter backup filename to save: ");
+            cout << "Enter backup filename to save: ";
             junk = fgets(line, 255, stdin);
             sscanf(line, "%s", (char*) &buFile);
             theGPT->SaveGPTBackup(buFile);
@@ -81,7 +85,7 @@
             if (theGPT->GetPartRange(&temp1, &temp2) > 0)
                theGPT->SetName(theGPT->GetPartNum());
             else
-               printf("No partitions\n");
+               cout << "No partitions\n";
             break;
          case 'd': case 'D':
             theGPT->DeletePartition();
@@ -96,8 +100,8 @@
             theGPT->CreatePartition();
             break;
          case 'o': case 'O':
-            printf("This option deletes all partitions and creates a new "
-                  "protective MBR.\nProceed? ");
+            cout << "This option deletes all partitions and creates a new protective MBR.\n"
+                 << "Proceed? ";
             if (GetYN() == 'Y') {
                theGPT->ClearGPTData();
                theGPT->MakeProtectiveMBR();
@@ -115,7 +119,7 @@
             break;
          case 's': case 'S':
             theGPT->SortGPT();
-            printf("You may need to edit /etc/fstab and/or your boot loader configuration!\n");
+            cout << "You may need to edit /etc/fstab and/or your boot loader configuration!\n";
             break;
          case 't': case 'T':
             theGPT->ChangePartType();
@@ -139,27 +143,27 @@
 } // MainMenu()
 
 void ShowCommands(void) {
-   printf("b\tback up GPT data to a file\n");
-   printf("c\tchange a partition's name\n");
-   printf("d\tdelete a partition\n");
-   printf("i\tshow detailed information on a partition\n");
-   printf("l\tlist known partition types\n");
-   printf("n\tadd a new partition\n");
-   printf("o\tcreate a new empty GUID partition table (GPT)\n");
-   printf("p\tprint the partition table\n");
-   printf("q\tquit without saving changes\n");
-   printf("r\trecovery and transformation options (experts only)\n");
-   printf("s\tsort partitions\n");
-   printf("t\tchange a partition's type code\n");
-   printf("v\tverify disk\n");
-   printf("w\twrite table to disk and exit\n");
-   printf("x\textra functionality (experts only)\n");
-   printf("?\tprint this menu\n");
+   cout << "b\tback up GPT data to a file\n";
+   cout << "c\tchange a partition's name\n";
+   cout << "d\tdelete a partition\n";
+   cout << "i\tshow detailed information on a partition\n";
+   cout << "l\tlist known partition types\n";
+   cout << "n\tadd a new partition\n";
+   cout << "o\tcreate a new empty GUID partition table (GPT)\n";
+   cout << "p\tprint the partition table\n";
+   cout << "q\tquit without saving changes\n";
+   cout << "r\trecovery and transformation options (experts only)\n";
+   cout << "s\tsort partitions\n";
+   cout << "t\tchange a partition's type code\n";
+   cout << "v\tverify disk\n";
+   cout << "w\twrite table to disk and exit\n";
+   cout << "x\textra functionality (experts only)\n";
+   cout << "?\tprint this menu\n";
 } // ShowCommands()
 
 // Accept a recovery & transformation menu command. Returns only when the user
 // issues an exit command, such as 'w' or 'q'.
-void RecoveryMenu(char* filename, struct GPTData* theGPT) {
+void RecoveryMenu(string filename, struct GPTData* theGPT) {
    char command, line[255], buFile[255];
    char* junk;
    PartTypes typeHelper;
@@ -167,16 +171,18 @@
    int goOn = 1;
 
    do {
-      printf("\nRecovery/transformation command (? for help): ");
+      cout << "\nRecovery/transformation command (? for help): ";
       junk = fgets(line, 255, stdin);
       sscanf(line, "%c", &command);
       switch (command) {
+         case '\n':
+            break;
          case 'b': case 'B':
             theGPT->RebuildMainHeader();
             break;
          case 'c': case 'C':
-            printf("Warning! This will probably do weird things if you've converted an MBR to\n"
-                  "GPT form and haven't yet saved the GPT! Proceed? ");
+            cout << "Warning! This will probably do weird things if you've converted an MBR to\n"
+                 << "GPT form and haven't yet saved the GPT! Proceed? ";
             if (GetYN() == 'Y')
                theGPT->LoadSecondTableAsMain();
             break;
@@ -184,18 +190,18 @@
             theGPT->RebuildSecondHeader();
             break;
          case 'e': case 'E':
-            printf("Warning! This will probably do weird things if you've converted an MBR to\n"
-                  "GPT form and haven't yet saved the GPT! Proceed? ");
+            cout << "Warning! This will probably do weird things if you've converted an MBR to\n"
+                 << "GPT form and haven't yet saved the GPT! Proceed? ";
             if (GetYN() == 'Y')
                theGPT->LoadMainTable();
             break;
          case 'f': case 'F':
-            printf("Warning! This will destroy the currently defined partitions! Proceed? ");
+            cout << "Warning! This will destroy the currently defined partitions! Proceed? ";
             if (GetYN() == 'Y') {
                if (theGPT->LoadMBR(filename) == 1) { // successful load
                   theGPT->XFormPartitions();
                } else {
-                  printf("Problem loading MBR! GPT is untouched; regenerating protective MBR!\n");
+                  cout << "Problem loading MBR! GPT is untouched; regenerating protective MBR!\n";
                   theGPT->MakeProtectiveMBR();
                } // if/else
             } // if
@@ -203,13 +209,13 @@
          case 'g': case 'G':
             temp1 = theGPT->XFormToMBR();
             if (temp1 > 0) {
-               printf("Converted %d partitions. Finalize and exit? ", temp1);
+               cout << "Converted " << temp1 << " partitions. Finalize and exit? ";
                if (GetYN() == 'Y') {
                   if (theGPT->DestroyGPT(0) > 0)
                      goOn = 0;
                } else {
                   theGPT->MakeProtectiveMBR();
-                  printf("Note: New protective MBR created.\n");
+                  cout << "Note: New protective MBR created.\n";
                } // if/else
             } // if
             break;
@@ -220,7 +226,7 @@
             theGPT->ShowDetails();
             break;
          case 'l': case 'L':
-            printf("Enter backup filename to load: ");
+            cout << "Enter backup filename to load: ";
             junk = fgets(line, 255, stdin);
             sscanf(line, "%s", (char*) &buFile);
             theGPT->LoadGPTBackup(buFile);
@@ -261,29 +267,29 @@
 } // RecoveryMenu()
 
 void ShowRecoveryCommands(void) {
-   printf("b\tuse backup GPT header (rebuilding main)\n");
-   printf("c\tload backup partition table from disk (rebuilding main)\n");
-   printf("d\tuse main GPT header (rebuilding backup)\n");
-   printf("e\tload main partition table from disk (rebuilding backup)\n");
-   printf("f\tload MBR and build fresh GPT from it\n");
-   printf("g\tconvert GPT into MBR and exit\n");
-   printf("h\tmake hybrid MBR\n");
-   printf("i\tshow detailed information on a partition\n");
-   printf("l\tload partition data from a backup file\n");
-   printf("m\treturn to main menu\n");
-   printf("o\tprint protective MBR data\n");
-   printf("p\tprint the partition table\n");
-   printf("q\tquit without saving changes\n");
-   printf("t\ttransform BSD disklabel partition\n");
-   printf("v\tverify disk\n");
-   printf("w\twrite table to disk and exit\n");
-   printf("x\textra functionality (experts only)\n");
-   printf("?\tprint this menu\n");
+   cout << "b\tuse backup GPT header (rebuilding main)\n";
+   cout << "c\tload backup partition table from disk (rebuilding main)\n";
+   cout << "d\tuse main GPT header (rebuilding backup)\n";
+   cout << "e\tload main partition table from disk (rebuilding backup)\n";
+   cout << "f\tload MBR and build fresh GPT from it\n";
+   cout << "g\tconvert GPT into MBR and exit\n";
+   cout << "h\tmake hybrid MBR\n";
+   cout << "i\tshow detailed information on a partition\n";
+   cout << "l\tload partition data from a backup file\n";
+   cout << "m\treturn to main menu\n";
+   cout << "o\tprint protective MBR data\n";
+   cout << "p\tprint the partition table\n";
+   cout << "q\tquit without saving changes\n";
+   cout << "t\ttransform BSD disklabel partition\n";
+   cout << "v\tverify disk\n";
+   cout << "w\twrite table to disk and exit\n";
+   cout << "x\textra functionality (experts only)\n";
+   cout << "?\tprint this menu\n";
 } // ShowRecoveryCommands()
 
 // Accept an experts' menu command. Returns only after the user
 // selects an exit command, such as 'w' or 'q'.
-void ExpertsMenu(char* filename, struct GPTData* theGPT) {
+void ExpertsMenu(string filename, struct GPTData* theGPT) {
    char command, line[255];
    char* junk;
    PartTypes typeHelper;
@@ -292,40 +298,43 @@
    int goOn = 1;
 
    do {
-      printf("\nExpert command (? for help): ");
+      cout << "\nExpert command (? for help): ";
       junk = fgets(line, 255, stdin);
       sscanf(line, "%c", &command);
       switch (command) {
+         case '\n':
+            break;
          case 'a': case 'A':
             if (theGPT->GetPartRange(&temp1, &temp2) > 0)
                theGPT->SetAttributes(theGPT->GetPartNum());
            else
-               printf("No partitions\n");
+               cout << "No partitions\n";
             break;
          case 'c': case 'C':
             if (theGPT->GetPartRange(&temp1, &temp2) > 0) {
                pn = theGPT->GetPartNum();
-               printf("Enter the partition's new unique GUID:\n");
+               cout << "Enter the partition's new unique GUID:\n";
                theGPT->SetPartitionGUID(pn, GetGUID());
-            } else printf("No partitions\n");
+            } else cout << "No partitions\n";
             break;
          case 'd': case 'D':
-            printf("Partitions will begin on %d-sector boundaries.\n",
-                   theGPT->GetAlignment());
+            cout << "Partitions will begin on " << theGPT->GetAlignment()
+                 << "-sector boundaries.\n";
             break;
          case 'e': case 'E':
-            printf("Relocating backup data structures to the end of the disk\n");
+            cout << "Relocating backup data structures to the end of the disk\n";
             theGPT->MoveSecondHeaderToEnd();
             break;
          case 'g': case 'G':
-            printf("Enter the disk's unique GUID:\n");
+            cout << "Enter the disk's unique GUID:\n";
             theGPT->SetDiskGUID(GetGUID());
             break;
          case 'i': case 'I':
             theGPT->ShowDetails();
             break;
          case 'l': case 'L':
-            temp1 = GetNumber(1, 128, 8, "Enter the sector alignment value (1-128, default = 8): ");
+            temp1 = GetNumber(1, 128, 8, (string)
+                              "Enter the sector alignment value (1-128, default = 8): ");
             theGPT->SetAlignment(temp1);
             break;
          case 'm': case 'M':
@@ -372,22 +381,22 @@
 } // ExpertsMenu()
 
 void ShowExpertCommands(void) {
-   printf("a\tset attributes\n");
-   printf("c\tchange partition GUID\n");
-   printf("d\tdisplay the sector alignment value\n");
-   printf("e\trelocate backup data structures to the end of the disk\n");
-   printf("g\tchange disk GUID\n");
-   printf("i\tshow detailed information on a partition\n");
-   printf("l\tset the sector alignment value\n");
-   printf("m\treturn to main menu\n");
-   printf("n\tcreate a new protective MBR\n");
-   printf("o\tprint protective MBR data\n");
-   printf("p\tprint the partition table\n");
-   printf("q\tquit without saving changes\n");
-   printf("r\trecovery and transformation options (experts only)\n");
-   printf("s\tresize partition table\n");
-   printf("v\tverify disk\n");
-   printf("w\twrite table to disk and exit\n");
-   printf("z\tzap (destroy) GPT data structures and exit\n");
-   printf("?\tprint this menu\n");
+   cout << "a\tset attributes\n";
+   cout << "c\tchange partition GUID\n";
+   cout << "d\tdisplay the sector alignment value\n";
+   cout << "e\trelocate backup data structures to the end of the disk\n";
+   cout << "g\tchange disk GUID\n";
+   cout << "i\tshow detailed information on a partition\n";
+   cout << "l\tset the sector alignment value\n";
+   cout << "m\treturn to main menu\n";
+   cout << "n\tcreate a new protective MBR\n";
+   cout << "o\tprint protective MBR data\n";
+   cout << "p\tprint the partition table\n";
+   cout << "q\tquit without saving changes\n";
+   cout << "r\trecovery and transformation options (experts only)\n";
+   cout << "s\tresize partition table\n";
+   cout << "v\tverify disk\n";
+   cout << "w\twrite table to disk and exit\n";
+   cout << "z\tzap (destroy) GPT data structures and exit\n";
+   cout << "?\tprint this menu\n";
 } // ShowExpertCommands()
diff --git a/gpt.cc b/gpt.cc
index 867c3ff..e5c9852 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -18,6 +18,7 @@
 #include <time.h>
 #include <sys/stat.h>
 #include <errno.h>
+#include <iostream>
 #include "crc32.h"
 #include "gpt.h"
 #include "bsd.h"
@@ -40,7 +41,7 @@
    diskSize = 0;
    partitions = NULL;
    state = gpt_valid;
-   strcpy(device, "");
+   device = "";
    justLooking = 0;
    mainCrcOk = 0;
    secondCrcOk = 0;
@@ -57,12 +58,12 @@
 } // GPTData default constructor
 
 // The following constructor loads GPT data from a device file
-GPTData::GPTData(char* filename) {
+GPTData::GPTData(string filename) {
    blockSize = SECTOR_SIZE; // set a default
    diskSize = 0;
    partitions = NULL;
    state = gpt_invalid;
-   strcpy(device, "");
+   device = "";
    justLooking = 0;
    mainCrcOk = 0;
    secondCrcOk = 0;
@@ -77,7 +78,7 @@
    mainHeader.numParts = 0;
    if (!LoadPartitions(filename))
       exit(2);
-} // GPTData(char* filename) constructor
+} // GPTData(string filename) constructor
 
 // Destructor
 GPTData::~GPTData(void) {
@@ -102,116 +103,109 @@
    // First, check for CRC errors in the GPT data....
    if (!mainCrcOk) {
       problems++;
-      printf("\nProblem: The CRC for the main GPT header is invalid. The main GPT header may\n"
-             "be corrupt. Consider loading the backup GPT header to rebuild the main GPT\n"
-             "header ('b' on the recovery & transformation menu). This report may be a false\n"
-             "alarm if you've already corrected other problems.\n");
+      cout << "\nProblem: The CRC for the main GPT header is invalid. The main GPT header may\n"
+           << "be corrupt. Consider loading the backup GPT header to rebuild the main GPT\n"
+           << "header ('b' on the recovery & transformation menu). This report may be a false\n"
+           << "alarm if you've already corrected other problems.\n";
    } // if
    if (!mainPartsCrcOk) {
       problems++;
-      printf("\nProblem: The CRC for the main partition table is invalid. This table may be\n"
-             "corrupt. Consider loading the backup partition table ('c' on the recovery &\n"
-             "transformation menu). This report may be a false alarm if you've already\n"
-             "corrected other problems.\n");
+      cout << "\nProblem: The CRC for the main partition table is invalid. This table may be\n"
+           << "corrupt. Consider loading the backup partition table ('c' on the recovery &\n"
+           << "transformation menu). This report may be a false alarm if you've already\n"
+           << "corrected other problems.\n";
    } // if
    if (!secondCrcOk) {
       problems++;
-      printf("\nProblem: The CRC for the backup GPT header is invalid. The backup GPT header\n"
-            "may be corrupt. Consider using the main GPT header to rebuild the backup GPT\n"
-            "header ('d' on the recovery & transformation menu). This report may be a false\n"
-            "alarm if you've already corrected other problems.\n");
+      cout << "\nProblem: The CRC for the backup GPT header is invalid. The backup GPT header\n"
+           << "may be corrupt. Consider using the main GPT header to rebuild the backup GPT\n"
+           << "header ('d' on the recovery & transformation menu). This report may be a false\n"
+           << "alarm if you've already corrected other problems.\n";
    } // if
    if (!secondPartsCrcOk) {
       problems++;
-      printf("\nCaution: The CRC for the backup partition table is invalid. This table may\n"
-             "be corrupt. This program will automatically create a new backup partition\n"
-             "table when you save your partitions.\n");
+      cout << "\nCaution: The CRC for the backup partition table is invalid. This table may\n"
+           << "be corrupt. This program will automatically create a new backup partition\n"
+           << "table when you save your partitions.\n";
    } // if
 
    // Now check that the main and backup headers both point to themselves....
    if (mainHeader.currentLBA != 1) {
       problems++;
-      printf("\nProblem: The main header's self-pointer doesn't point to itself. This problem\n"
-             "is being automatically corrected, but it may be a symptom of more serious\n"
-             "problems. Think carefully before saving changes with 'w' or using this disk.\n");
+      cout << "\nProblem: The main header's self-pointer doesn't point to itself. This problem\n"
+           << "is being automatically corrected, but it may be a symptom of more serious\n"
+           << "problems. Think carefully before saving changes with 'w' or using this disk.\n";
       mainHeader.currentLBA = 1;
    } // if
    if (secondHeader.currentLBA != (diskSize - UINT64_C(1))) {
       problems++;
-      printf("\nProblem: The secondary header's self-pointer indicates that it doesn't reside\n"
-             "at the end of the disk. If you've added a disk to a RAID array, use the 'e'\n"
-             "option on the experts' menu to adjust the secondary header's and partition\n"
-             "table's locations.\n");
+      cout << "\nProblem: The secondary header's self-pointer indicates that it doesn't reside\n"
+           << "at the end of the disk. If you've added a disk to a RAID array, use the 'e'\n"
+           << "option on the experts' menu to adjust the secondary header's and partition\n"
+           << "table's locations.\n";
    } // if
 
    // Now check that critical main and backup GPT entries match each other
    if (mainHeader.currentLBA != secondHeader.backupLBA) {
       problems++;
-      printf("\nProblem: main GPT header's current LBA pointer (%llu) doesn't\n"
-            "match the backup GPT header's LBA pointer(%llu).\n",
-            (unsigned long long) mainHeader.currentLBA,
-             (unsigned long long) secondHeader.backupLBA);
+      cout << "\nProblem: main GPT header's current LBA pointer (" << mainHeader.currentLBA
+           << ") doesn't\nmatch the backup GPT header's alternate LBA pointer("
+           << secondHeader.backupLBA << ").\n";
    } // if
    if (mainHeader.backupLBA != secondHeader.currentLBA) {
       problems++;
-      printf("\nProblem: main GPT header's backup LBA pointer (%llu) doesn't\n"
-             "match the backup GPT header's current LBA pointer (%llu).\n"
-             "The 'e' option on the experts' menu may fix this problem.\n",
-             (unsigned long long) mainHeader.backupLBA,
-             (unsigned long long) secondHeader.currentLBA);
+      cout << "\nProblem: main GPT header's backup LBA pointer (" << mainHeader.backupLBA
+           << ") doesn't\nmatch the backup GPT header's current LBA pointer ("
+           << secondHeader.currentLBA << ").\n"
+           << "The 'e' option on the experts' menu may fix this problem.\n";
    } // if
    if (mainHeader.firstUsableLBA != secondHeader.firstUsableLBA) {
       problems++;
-      printf("\nProblem: main GPT header's first usable LBA pointer (%llu) doesn't\n"
-             "match the backup GPT header's first usable LBA pointer (%llu)\n",
-             (unsigned long long) mainHeader.firstUsableLBA,
-             (unsigned long long) secondHeader.firstUsableLBA);
+      cout << "\nProblem: main GPT header's first usable LBA pointer (" << mainHeader.firstUsableLBA
+           << ") doesn't\nmatch the backup GPT header's first usable LBA pointer ("
+           << secondHeader.firstUsableLBA << ")\n";
    } // if
    if (mainHeader.lastUsableLBA != secondHeader.lastUsableLBA) {
       problems++;
-      printf("\nProblem: main GPT header's last usable LBA pointer (%llu) doesn't\n"
-             "match the backup GPT header's last usable LBA pointer (%llu)\n",
-             (unsigned long long) mainHeader.lastUsableLBA,
-             (unsigned long long) secondHeader.lastUsableLBA);
-      printf("The 'e' option on the experts' menu can probably fix this problem.\n");
+      cout << "\nProblem: main GPT header's last usable LBA pointer (" << mainHeader.lastUsableLBA
+           << ") doesn't\nmatch the backup GPT header's last usable LBA pointer ("
+           << secondHeader.lastUsableLBA << ")\n"
+           << "The 'e' option on the experts' menu can probably fix this problem.\n";
    } // if
    if ((mainHeader.diskGUID.data1 != secondHeader.diskGUID.data1) ||
         (mainHeader.diskGUID.data2 != secondHeader.diskGUID.data2)) {
       problems++;
-      printf("\nProblem: main header's disk GUID (%s) doesn't\n",
-             GUIDToStr(mainHeader.diskGUID, tempStr));
-      printf("match the backup GPT header's disk GUID (%s)\n",
-             GUIDToStr(secondHeader.diskGUID, tempStr));
-      printf("You should use the 'b' or 'd' option on the recovery & transformation menu to\n"
-             "select one or the other header.\n");
+      cout << "\nProblem: main header's disk GUID (" << GUIDToStr(mainHeader.diskGUID)
+           << ") doesn't\nmatch the backup GPT header's disk GUID ("
+           << GUIDToStr(secondHeader.diskGUID) << ")\n"
+           << "You should use the 'b' or 'd' option on the recovery & transformation menu to\n"
+           << "select one or the other header.\n";
    } // if
    if (mainHeader.numParts != secondHeader.numParts) {
       problems++;
-      printf("\nProblem: main GPT header's number of partitions (%lu) doesn't\n"
-            "match the backup GPT header's number of partitions (%lu)\n",
-            (unsigned long) mainHeader.numParts,
-            (unsigned long) secondHeader.numParts);
-      printf("Resizing the partition table ('s' on the experts' menu) may help.\n");
+      cout << "\nProblem: main GPT header's number of partitions (" << mainHeader.numParts
+           << ") doesn't\nmatch the backup GPT header's number of partitions ("
+           << secondHeader.numParts << ")\n"
+           << "Resizing the partition table ('s' on the experts' menu) may help.\n";
    } // if
    if (mainHeader.sizeOfPartitionEntries != secondHeader.sizeOfPartitionEntries) {
       problems++;
-      printf("\nProblem: main GPT header's size of partition entries (%lu) doesn't\n"
-            "match the backup GPT header's size of partition entries (%lu)\n",
-            (unsigned long) mainHeader.sizeOfPartitionEntries,
-            (unsigned long) secondHeader.sizeOfPartitionEntries);
-      printf("You should use the 'b' or 'd' option on the recovery & transformation menu to\n"
-            "select one or the other header.\n");
+      cout << "\nProblem: main GPT header's size of partition entries ("
+           << mainHeader.sizeOfPartitionEntries << ") doesn't\n"
+           << "match the backup GPT header's size of partition entries ("
+           << secondHeader.sizeOfPartitionEntries << ")\n"
+           << "You should use the 'b' or 'd' option on the recovery & transformation menu to\n"
+           << "select one or the other header.\n";
    } // if
 
    // Now check for a few other miscellaneous problems...
    // Check that the disk size will hold the data...
    if (mainHeader.backupLBA > diskSize) {
       problems++;
-      printf("\nProblem: Disk is too small to hold all the data!\n");
-      printf("(Disk size is %llu sectors, needs to be %llu sectors.)\n",
-             (unsigned long long) diskSize,
-             (unsigned long long) mainHeader.backupLBA);
-      printf("The 'e' option on the experts' menu may fix this problem.\n");
+      cout << "\nProblem: Disk is too small to hold all the data!\n"
+           << "(Disk size is " << diskSize << " sectors, needs to be "
+           << mainHeader.backupLBA << " sectors.)\n"
+           << "The 'e' option on the experts' menu may fix this problem.\n";
    } // if
 
    // Check for overlapping partitions....
@@ -227,9 +221,9 @@
    // Format and similar disks)....
    for (i = 0; i < mainHeader.numParts; i++) {
       if ((partitions[i].GetFirstLBA() % sectorAlignment) != 0) {
-         printf("\nCaution: Partition %d doesn't begin on a %d-sector boundary. This may\n"
-                "result in degraded performance on some modern (2010 and later) hard disks.\n",
-                i + 1, sectorAlignment);
+         cout << "\nCaution: Partition " << i + 1 << " doesn't begin on a "
+              << sectorAlignment << "-sector boundary. This may\nresult "
+              << "in degraded performance on some modern (2009 and later) hard disks.\n";
       } // if
    } // for
 
@@ -237,14 +231,15 @@
    // problems could affect the results
    if (problems == 0) {
       totalFree = FindFreeBlocks(&numSegments, &largestSegment);
-      BytesToSI(totalFree * (uint64_t) blockSize, siTotal);
-      BytesToSI(largestSegment * (uint64_t) blockSize, siLargest);
-      printf("No problems found. %llu free sectors ", (unsigned long long) totalFree);
-      printf("(%s) available in %u\n", siTotal, numSegments);
-      printf("segments, the largest of which is %llu sectors ", (unsigned long long) largestSegment);
-      printf("(%s) in size\n", siLargest);
+      strcpy(siTotal, BytesToSI(totalFree * (uint64_t) blockSize).c_str());
+      strcpy(siLargest, BytesToSI(largestSegment * (uint64_t) blockSize).c_str());
+      cout << "No problems found. " << totalFree << " free sectors ("
+           << BytesToSI(totalFree * (uint64_t) blockSize) << ") available in "
+           << numSegments << "\nsegments, the largest of which is "
+           << largestSegment << " (" << BytesToSI(largestSegment * (uint64_t) blockSize)
+           << ") in size\n";
    } else {
-      printf("\nIdentified %d problems!\n", problems);
+      cout << "\nIdentified %d problems!\n", problems;
    } // if/else
 
    return (problems);
@@ -275,27 +270,25 @@
    if (diskSize != 0) {
       if (mainHeader.firstUsableLBA > firstUsedBlock) {
          overlap = mainHeader.firstUsableLBA - firstUsedBlock;
-         printf("Warning! Main partition table overlaps the first partition by %lu blocks!\n",
-                (unsigned long) overlap);
+         cout << "Warning! Main partition table overlaps the first partition by "
+              << overlap << " blocks!\n";
          if (firstUsedBlock > 2) {
-            printf("Try reducing the partition table size by %lu entries.\n",
-                   (unsigned long) (overlap * 4));
-            printf("(Use the 's' item on the experts' menu.)\n");
+            cout << "Try reducing the partition table size by " << overlap * 4
+                 << " entries.\n(Use the 's' item on the experts' menu.)\n";
          } else {
-            printf("You will need to delete this partition or resize it in another utility.\n");
+            cout << "You will need to delete this partition or resize it in another utility.\n";
          } // if/else
          numProbs++;
       } // Problem at start of disk
       if (mainHeader.lastUsableLBA < lastUsedBlock) {
          overlap = lastUsedBlock - mainHeader.lastUsableLBA;
-         printf("Warning! Secondary partition table overlaps the last partition by %lu blocks!\n",
-                (unsigned long) overlap);
+         cout << "Warning! Secondary partition table overlaps the last partition by "
+              << overlap << " blocks!\n";
          if (lastUsedBlock > (diskSize - 2)) {
-            printf("You will need to delete this partition or resize it in another utility.\n");
+            cout << "You will need to delete this partition or resize it in another utility.\n";
          } else {
-            printf("Try reducing the partition table size by %lu entries.\n",
-                   (unsigned long) (overlap * 4));
-            printf("(Use the 's' item on the experts' menu.)\n");
+            cout << "Try reducing the partition table size by " << overlap * 4
+                 << " entries.\n(Use the 's' item on the experts' menu.)\n";
          } // if/else
          numProbs++;
       } // Problem at end of disk
@@ -310,24 +303,31 @@
 int GPTData::CheckHeaderValidity(void) {
    int valid = 3;
 
+   cout.setf(ios::uppercase);
+   cout.fill('0');
+
+   // Note: failed GPT signature checks produce no error message because
+   // a message is displayed in the ReversePartitionBytes() function
    if (mainHeader.signature != GPT_SIGNATURE) {
       valid -= 1;
-//      printf("Main GPT signature invalid; read 0x%016llX, should be\n0x%016llX\n",
-//             (unsigned long long) mainHeader.signature, (unsigned long long) GPT_SIGNATURE);
    } else if ((mainHeader.revision != 0x00010000) && valid) {
       valid -= 1;
-      printf("Unsupported GPT version in main header; read 0x%08lX, should be\n0x%08lX\n",
-             (unsigned long) mainHeader.revision, (unsigned long) UINT32_C(0x00010000));
+      cout << "Unsupported GPT version in main header; read 0x";
+      cout.width(8);
+      cout << hex << mainHeader.revision << ", should be\n0x";
+      cout.width(8);
+      cout << UINT32_C(0x00010000) << dec << "\n";
    } // if/else/if
 
    if (secondHeader.signature != GPT_SIGNATURE) {
       valid -= 2;
-//      printf("Secondary GPT signature invalid; read 0x%016llX, should be\n0x%016llX\n",
-//             (unsigned long long) secondHeader.signature, (unsigned long long) GPT_SIGNATURE);
    } else if ((secondHeader.revision != 0x00010000) && valid) {
       valid -= 2;
-      printf("Unsupported GPT version in backup header; read 0x%08lX, should be\n0x%08lX\n",
-             (unsigned long) mainHeader.revision, (unsigned long) UINT32_C(0x00010000));
+      cout << "Unsupported GPT version in backup header; read 0x";
+      cout.width(8);
+      cout << hex << secondHeader.revision << ", should be\n0x";
+      cout.width(8);
+      cout << UINT32_C(0x00010000) << dec << "\n";
    } // if/else/if
 
    // If MBR bad, check for an Apple disk signature
@@ -336,8 +336,9 @@
         (mainHeader.signature << 32) == APM_SIGNATURE2)) {
       apmFound = 1; // Will display warning message later
    } // if
+   cout.fill(' ');
 
-        return valid;
+   return valid;
 } // GPTData::CheckHeaderValidity()
 
 // Check the header CRC to see if it's OK...
@@ -474,10 +475,15 @@
          } while ((!found) && (j < mainHeader.numParts));
          if (!found) {
             numFound++;
-            printf("\nWarning! Mismatched GPT and MBR partitions! MBR partition "
-                   "%d, of type 0x%02X,\nhas no corresponding GPT partition! "
-                   "You may continue, but this condition\nmight cause data loss"
-                   " in the future!\a\n", i + 1, protectiveMBR.GetType(i));
+            cout << "\nWarning! Mismatched GPT and MBR partition! MBR partition "
+                 << i + 1 << ", of type 0x";
+            cout.fill('0');
+            cout.setf(ios::uppercase);
+            cout.width(2);
+            cout << hex << (int) protectiveMBR.GetType(i) << ",\n"
+                 << "has no corresponding GPT partition! You may continue, but this condition\n"
+                 << "might cause data loss in the future!\a\n" << dec;
+            cout.fill(' ');
          } // if
       } // if
    } // for
@@ -493,13 +499,11 @@
       for (j = 0; j < i; j++) {
          if (partitions[i].DoTheyOverlap(&partitions[j])) {
             problems++;
-            printf("\nProblem: partitions %d and %d overlap:\n", i + 1, j + 1);
-            printf("  Partition %d: %llu to %llu\n", i,
-                   (unsigned long long) partitions[i].GetFirstLBA(),
-                    (unsigned long long) partitions[i].GetLastLBA());
-            printf("  Partition %d: %llu to %llu\n", j,
-                   (unsigned long long) partitions[j].GetFirstLBA(),
-                    (unsigned long long) partitions[j].GetLastLBA());
+            cout << "\nProblem: partitions " << i + 1 << " and " << j + 1 << " overlap:\n";
+            cout << "  Partition " << i + 1 << ": " << partitions[i].GetFirstLBA()
+                 << " to " << partitions[i].GetLastLBA() << "\n";
+            cout << "  Partition " << j + 1 << ": " << partitions[j].GetFirstLBA()
+                 << " to " << partitions[j].GetLastLBA() << "\n";
          } // if
       } // for j...
    } // for i...
@@ -527,44 +531,44 @@
    ForceLoadGPTData();
 
    if (!beQuiet) {
-      printf("Partition table scan:\n");
+      cout << "Partition table scan:\n";
       protectiveMBR.ShowState();
       bsdDisklabel.ShowState();
       ShowAPMState(); // Show whether there's an Apple Partition Map present
       ShowGPTState(); // Show GPT status
-      printf("\n");
+      cout << "\n";
    } // if
 
    if (apmFound) {
-      printf("\n*******************************************************************\n");
-      printf("This disk appears to contain an Apple-format (APM) partition table!\n");
+      cout << "\n*******************************************************************\n"
+           << "This disk appears to contain an Apple-format (APM) partition table!\n";
       if (!justLooking) {
-         printf("It will be destroyed if you continue!\n");
+         cout << "It will be destroyed if you continue!\n";
       } // if
-      printf("*******************************************************************\n\n\a");
+      cout << "*******************************************************************\n\n\a";
    } // if
 } // GPTData::PartitionScan()
 
 // Read GPT data from a disk.
-int GPTData::LoadPartitions(char* deviceFilename) {
-   int fd, err;
+int GPTData::LoadPartitions(string deviceFilename) {
+   int err;
    int allOK = 1, i;
    uint64_t firstBlock, lastBlock;
    BSDData bsdDisklabel;
+   MBRValidity mbrState;
 
    // First, do a test to see if writing will be possible later....
-   fd = myDisk.OpenForWrite(deviceFilename);
-   if ((fd == -1) && (!justLooking)) {
-      printf("\aNOTE: Write test failed with error number %d. It will be "
-             "impossible to save\nchanges to this disk's partition table!\n",
-             errno);
+   err = myDisk.OpenForWrite(deviceFilename);
+   if ((err == 0) && (!justLooking)) {
+      cout << "\aNOTE: Write test failed with error number " << errno
+           << ". It will be impossible to save\nchanges to this disk's partition table!\n";
 #ifdef __FreeBSD__
-      printf("You may be able to enable writes by exiting this program, typing\n"
-             "'sysctl kern.geom.debugflags=16' at a shell prompt, and re-running this\n"
-             "program.\n");
+      cout << "You may be able to enable writes by exiting this program, typing\n"
+           << "'sysctl kern.geom.debugflags=16' at a shell prompt, and re-running this\n"
+           << "program.\n";
 #endif
-      printf("\n");
-      justLooking = 1;
+      cout << "\n";
+//      justLooking = 1;
    } // if
    myDisk.Close();
 
@@ -574,7 +578,7 @@
       diskSize = myDisk.DiskSize(&err);
       blockSize = (uint32_t) myDisk.GetBlockSize();
       sectorAlignment = myDisk.FindAlignment();
-      strcpy(device, deviceFilename);
+      device = deviceFilename;
       PartitionScan(); // Check for partition types, load GPT, & print summary
 
       whichWasUsed = UseWhichPartitions();
@@ -590,6 +594,9 @@
             XFormDisklabel(&bsdDisklabel, 0);
             break;
          case use_gpt:
+            mbrState = protectiveMBR.GetValidity();
+            if ((mbrState == invalid) || (mbrState == mbr))
+               protectiveMBR.MakeProtectiveMBR();
             break;
          case use_new:
             ClearGPTData();
@@ -597,7 +604,7 @@
             break;
          case use_abort:
             allOK = 0;
-            printf("Aborting because of invalid partition data!\n");
+            cerr << "Aborting because of invalid partition data!\n";
             break;
       } // switch
 
@@ -616,10 +623,10 @@
       } // if
    } else {
       allOK = 0;
-      fprintf(stderr, "Problem opening %s for reading! Error is %d\n",
-              deviceFilename, errno);
+      cerr << "Problem opening " << deviceFilename << " for reading! Error is "
+           << errno << "\n";
       if (errno == EACCES) { // User is probably not running as root
-         fprintf(stderr, "You must run this program as root or use sudo!\n");
+         cerr << "You must run this program as root or use sudo!\n";
       } // if
    } // if/else
    return (allOK);
@@ -630,13 +637,13 @@
 int GPTData::ForceLoadGPTData(void) {
    int allOK = 1, validHeaders;
    off_t seekTo;
-   char* storage;
+   uint8_t* storage;
    uint32_t newCRC, sizeOfParts;
 
    // Seek to and read the main GPT header
    if (myDisk.Seek(1)) {
       if (myDisk.Read(&mainHeader, 512) != 512) { // read main GPT header
-         fprintf(stderr, "Warning! Error %d reading main GPT header!\n", errno);
+         cerr << "Warning! Error " << errno << " reading main GPT header!\n";
       } // if read not OK
    } else allOK = 0; // if/else seek OK
    mainCrcOk = CheckHeaderCRC(&mainHeader);
@@ -653,10 +660,10 @@
          seekTo = mainHeader.backupLBA;
       } else {
          seekTo = diskSize - UINT64_C(1);
-         printf("Warning! Disk size is smaller than the main header indicates! Loading\n"
-                "secondary header from the last sector of the disk! You should use 'v' to\n"
-                "verify disk integrity, and perhaps options on the experts' menu to repair\n"
-                "the disk.\n");
+         cout << "Warning! Disk size is smaller than the main header indicates! Loading\n"
+              << "secondary header from the last sector of the disk! You should use 'v' to\n"
+              << "verify disk integrity, and perhaps options on the experts' menu to repair\n"
+              << "the disk.\n";
       } // else
    } else {
       seekTo = diskSize - UINT64_C(1);
@@ -664,7 +671,7 @@
 
    if (myDisk.Seek(seekTo)) {
       if (myDisk.Read(&secondHeader, 512) != 512) { // read secondary GPT header
-         fprintf(stderr, "Warning! Error %d reading secondary GPT header!\n", errno);
+         cerr << "Warning! Error " << errno << " reading secondary GPT header!\n";
       } // if
       secondCrcOk = CheckHeaderCRC(&secondHeader);
       if (IsLittleEndian() == 0) // big-endian system; adjust header byte order....
@@ -672,8 +679,8 @@
    } else {
       allOK = 0;
       state = gpt_invalid;
-      fprintf(stderr, "Unable to seek to secondary GPT header at sector %llu!\n",
-              (unsigned long long) (diskSize - (UINT64_C(1))));
+      cerr << "Unable to seek to secondary GPT header at sector "
+           << (diskSize - (UINT64_C(1))) << "!\n";
    } // if/else lseek
 
    // Return valid headers code: 0 = both headers bad; 1 = main header
@@ -692,14 +699,14 @@
       // of the two headers is corrupt. If so, use the one that seems to
       // be in better shape to regenerate the bad one
       if (validHeaders == 1) { // valid main header, invalid backup header
-         fprintf(stderr, "\aCaution: invalid backup GPT header, but valid main header; regenerating\n"
-                 "backup header from main header.\n\n");
+         cerr << "\aCaution: invalid backup GPT header, but valid main header; regenerating\n"
+              << "backup header from main header.\n\n";
          RebuildSecondHeader();
          state = gpt_corrupt;
          secondCrcOk = mainCrcOk; // Since regenerated, use CRC validity of main
       } else if (validHeaders == 2) { // valid backup header, invalid main header
-         fprintf(stderr, "\aCaution: invalid main GPT header, but valid backup; regenerating main header\n"
-                 "from backup!\n\n");
+         cerr << "\aCaution: invalid main GPT header, but valid backup; regenerating main header\n"
+              << "from backup!\n\n";
          RebuildMainHeader();
          state = gpt_corrupt;
          mainCrcOk = secondCrcOk; // Since copied, use CRC validity of backup
@@ -714,11 +721,11 @@
       } else { // bad main header CRC and backup header CRC is OK
          state = gpt_corrupt;
          if (LoadSecondTableAsMain()) {
-            fprintf(stderr, "\aWarning: Invalid CRC on main header data; loaded backup partition table.\n");
+            cerr << "\aWarning: Invalid CRC on main header data; loaded backup partition table.\n";
          } else { // backup table bad, bad main header CRC, but try main table in desperation....
             if (LoadMainTable() == 0) {
                allOK = 0;
-               fprintf(stderr, "\a\aWarning! Unable to load either main or backup partition table!\n");
+               cerr << "\a\aWarning! Unable to load either main or backup partition table!\n";
             } // if
          } // if/else (LoadSecondTableAsMain())
       } // if/else (load partition table)
@@ -729,9 +736,9 @@
       seekTo = secondHeader.partitionEntriesLBA;
       if ((myDisk.Seek(seekTo)) && (secondCrcOk)) {
          sizeOfParts = secondHeader.numParts * secondHeader.sizeOfPartitionEntries;
-         storage = (char*) malloc(sizeOfParts);
+         storage = (uint8_t*) malloc(sizeOfParts);
          if (myDisk.Read(storage, sizeOfParts) != sizeOfParts) {
-            fprintf(stderr, "Warning! Error %d reading backup partition table!\n", errno);
+            cerr << "Warning! Error " << errno << " reading backup partition table!\n";
          } // if
          newCRC = chksum_crc32((unsigned char*) storage,  sizeOfParts);
          free(storage);
@@ -742,14 +749,14 @@
       if (secondPartsCrcOk && secondCrcOk && !mainPartsCrcOk) {
          state = gpt_corrupt;
          allOK = allOK && LoadSecondTableAsMain();
-         fprintf(stderr, "\aWarning! Main partition table CRC mismatch! Loaded backup "
-                         "partition table\ninstead of main partition table!\n\n");
+         cerr << "\aWarning! Main partition table CRC mismatch! Loaded backup "
+              << "partition table\ninstead of main partition table!\n\n";
       } // if
 
       // Check for valid CRCs and warn if there are problems
       if ((mainCrcOk == 0) || (secondCrcOk == 0) || (mainPartsCrcOk == 0) ||
            (secondPartsCrcOk == 0)) {
-         printf("Warning! One or more CRCs don't match. You should repair the disk!\n\n");
+         cerr << "Warning! One or more CRCs don't match. You should repair the disk!\n\n";
          state = gpt_corrupt;
       } // if
    } else {
@@ -776,7 +783,7 @@
          retval = 0;
       sizeOfParts = mainHeader.numParts * mainHeader.sizeOfPartitionEntries;
       if (myDisk.Read(partitions, sizeOfParts) != sizeOfParts) {
-         fprintf(stderr, "Warning! Error %d when loading the main partition table!\n", errno);
+         cerr << "Warning! Error " << errno << " when loading the main partition table!\n";
          retval = 0;
       } // if
       newCRC = chksum_crc32((unsigned char*) partitions, sizeOfParts);
@@ -803,7 +810,7 @@
          SetGPTSize(secondHeader.numParts);
          sizeOfParts = secondHeader.numParts * secondHeader.sizeOfPartitionEntries;
          if (myDisk.Read(partitions, sizeOfParts) != sizeOfParts) {
-            fprintf(stderr, "Warning! Read error %d! Misbehavior now likely!\n", errno);
+            cerr << "Warning! Read error " << errno << "! Misbehavior now likely!\n";
             retval = 0;
          } // if
          newCRC = chksum_crc32((unsigned char*) partitions, sizeOfParts);
@@ -812,13 +819,14 @@
          if (IsLittleEndian() == 0)
             ReversePartitionBytes();
          if (!secondPartsCrcOk) {
-            printf("Error! After loading backup partitions, the CRC still doesn't check out!\n");
+            cout << "Caution! After loading backup partitions, the CRC still doesn't check out!\n";
          } // if
       } else {
-         printf("Error! Couldn't seek to backup partition table!\n", retval);
+         cerr << "Error! Couldn't seek to backup partition table!\n";
       } // if/else
    } else {
-      printf("Error! Couldn't open device %s when recovering backup partition table!\n", device);
+      cerr << "Error! Couldn't open device " << device
+           << " when recovering backup partition table!\n";
       retval = 0;
    } // if/else
    return retval;
@@ -833,15 +841,15 @@
    uint32_t numParts;
    off_t offset;
 
-   if (strlen(device) == 0) {
-      printf("Device not defined.\n");
+   if (device == "") {
+      cerr << "Device not defined.\n";
    } // if
 
    // First do some final sanity checks....
 
    // This test should only fail on read-only disks....
    if (justLooking) {
-      printf("The justLooking flag is set. This probably means you can't write to the disk.\n");
+      cout << "The justLooking flag is set. This probably means you can't write to the disk.\n";
       allOK = 0;
    } // if
 
@@ -853,29 +861,28 @@
 
    // Check that disk is really big enough to handle this...
    if (mainHeader.backupLBA > diskSize) {
-      fprintf(stderr, "Error! Disk is too small! The 'e' option on the experts' menu might fix the\n"
-              "problem (or it might not). Aborting!\n");
-      printf("(Disk size is %llu sectors, needs to be %llu sectors.)\n",
-             (unsigned long long) diskSize, (unsigned long long) mainHeader.backupLBA);
+      cerr << "Error! Disk is too small! The 'e' option on the experts' menu might fix the\n"
+           << "problem (or it might not). Aborting!\n(Disk size is "
+           << diskSize << " sectors, needs to be " << mainHeader.backupLBA << " sectors.)\n";
       allOK = 0;
    } // if
    // Check that second header is properly placed. Warn and ask if this should
    // be corrected if the test fails....
    if ((mainHeader.backupLBA < (diskSize - UINT64_C(1))) && (quiet == 0)) {
-      printf("Warning! Secondary header is placed too early on the disk! Do you want to\n"
-             "correct this problem? ");
+      cout << "Warning! Secondary header is placed too early on the disk! Do you want to\n"
+           << "correct this problem? ";
       if (GetYN() == 'Y') {
          MoveSecondHeaderToEnd();
-         printf("Have moved second header and partition table to correct location.\n");
+         cout << "Have moved second header and partition table to correct location.\n";
       } else {
-         printf("Have not corrected the problem. Strange problems may occur in the future!\n");
+         cout << "Have not corrected the problem. Strange problems may occur in the future!\n";
       } // if correction requested
    } // if
 
    // Check for overlapping partitions....
    if (FindOverlaps() > 0) {
       allOK = 0;
-      fprintf(stderr, "Aborting write operation!\n");
+      cerr << "Aborting write operation!\n";
    } // if
 
    // Check for mismatched MBR and GPT data, but let it pass if found
@@ -896,12 +903,11 @@
    RecomputeCRCs();
 
    if ((allOK) && (!quiet)) {
-      printf("\nFinal checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING\n");
-      printf("MBR PARTITIONS!!\n\n");
-      printf("Do you want to proceed, possibly destroying your data? ");
+      cout << "\nFinal checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING\n"
+           << "PARTITIONS!!\n\nDo you want to proceed, possibly destroying your data? ";
       answer = GetYN();
       if (answer == 'Y') {
-         printf("OK; writing new GUID partition table (GPT).\n");
+         cout << "OK; writing new GUID partition table (GPT).\n";
       } else {
          allOK = 0;
       } // if/else
@@ -933,8 +939,8 @@
             offset = (off_t) secondTable;
             if (myDisk.Seek(offset) != 1) {
                allOK = 0;
-               printf("Unable to seek to end of disk! Perhaps the 'e' option on the experts' menu\n"
-                      "will resolve this problem.\n");
+               cerr << "Unable to seek to end of disk! Perhaps the 'e' option on the experts' menu\n"
+                    << "will resolve this problem.\n";
             } // if
          } // if
 
@@ -959,20 +965,20 @@
          } // if
 
          if (allOK) { // writes completed OK
-            printf("The operation has completed successfully.\n");
+            cout << "The operation has completed successfully.\n";
          } else {
-            printf("Warning! An error was reported when writing the partition table! This error\n");
-            printf("MIGHT be harmless, but you may have trashed the disk! Use parted and, if\n");
-            printf("necessary, restore your original partition table.\n");
+            cerr << "Warning! An error was reported when writing the partition table! This error\n"
+                 << "MIGHT be harmless, but you may have trashed the disk! Use parted and, if\n"
+                 << "necessary, restore your original partition table.\n";
          } // if/else
          myDisk.Close();
       } else {
-         fprintf(stderr, "Unable to open device %s for writing! Errno is %d! Aborting write!\n",
-                 device, errno);
+         cerr << "Unable to open device " << device << " for writing! Errno is "
+              << errno << "! Aborting write!\n";
          allOK = 0;
       } // if/else
    } else {
-      printf("Aborting write of new partition table.\n");
+      cout << "Aborting write of new partition table.\n";
    } // if
 
    if (IsLittleEndian() == 0) {
@@ -992,7 +998,7 @@
 // the main GPT header, the backup GPT header, and the main partition
 // table; it discards the backup partition table, since it should be
 // identical to the main partition table on healthy disks.
-int GPTData::SaveGPTBackup(char* filename) {
+int GPTData::SaveGPTBackup(string filename) {
    int fd, allOK = 1;
    uint32_t numParts;
    DiskIO backupFile;
@@ -1036,10 +1042,10 @@
       } // if
 
       if (allOK) { // writes completed OK
-         printf("The operation has completed successfully.\n");
+         cout << "The operation has completed successfully.\n";
       } else {
-         printf("Warning! An error was reported when writing the backup file.\n");
-         printf("It may not be usable!\n");
+         cerr << "Warning! An error was reported when writing the backup file.\n"
+              << "It may not be usable!\n";
       } // if/else
       backupFile.Close();
 
@@ -1050,7 +1056,7 @@
          ReversePartitionBytes();
       } // if
    } else {
-      fprintf(stderr, "Unable to open file %s for writing! Aborting!\n", filename);
+      cerr << "Unable to open file " << filename << " for writing! Aborting!\n";
       allOK = 0;
    } // if/else
    return allOK;
@@ -1060,7 +1066,7 @@
 // does minimal error checking. It returns 1 if it completed successfully,
 // 0 if there was a problem. In the latter case, it creates a new empty
 // set of partitions.
-int GPTData::LoadGPTBackup(char* filename) {
+int GPTData::LoadGPTBackup(string filename) {
    int fd, allOK = 1, val;
    uint32_t numParts, sizeOfEntries, sizeOfParts, newCRC;
    int littleEndian = 1;
@@ -1077,7 +1083,7 @@
       // Load the main GPT header, check its vaility, and set the GPT
       // size based on the data
       if (backupFile.Read(&mainHeader, 512) != 512) {
-         fprintf(stderr, "Warning! Read error %d; strange behavior now likely!\n", errno);
+         cerr << "Warning! Read error " << errno << "; strange behavior now likely!\n";
       } // if
       mainCrcOk = CheckHeaderCRC(&mainHeader);
 
@@ -1089,7 +1095,7 @@
       // Load the backup GPT header in much the same way as the main
       // GPT header....
       if (backupFile.Read(&secondHeader, 512) != 512) {
-         fprintf(stderr, "Warning! Read error %d; strange behavior now likely!\n", errno);
+         cerr << "Warning! Read error " << errno << "; strange behavior now likely!\n";
       } // if
       secondCrcOk = CheckHeaderCRC(&secondHeader);
 
@@ -1116,8 +1122,8 @@
 
          // If current disk size doesn't match that of backup....
          if (secondHeader.currentLBA != diskSize - UINT64_C(1)) {
-            printf("Warning! Current disk size doesn't match that of the backup!\n"
-                  "Adjusting sizes to match, but subsequent problems are possible!\n");
+            cout << "Warning! Current disk size doesn't match that of the backup!\n"
+                 << "Adjusting sizes to match, but subsequent problems are possible!\n";
             MoveSecondHeaderToEnd();
          } // if
 
@@ -1125,7 +1131,7 @@
          // matches the stored value
          sizeOfParts = numParts * sizeOfEntries;
          if (backupFile.Read(partitions, sizeOfParts) != sizeOfParts) {
-            fprintf(stderr, "Warning! Read error %d; strange behavior now likely!\n", errno);
+            cerr << "Warning! Read error " << errno << "; strange behavior now likely!\n";
          } // if
 
          newCRC = chksum_crc32((unsigned char*) partitions, sizeOfParts);
@@ -1141,7 +1147,7 @@
       } // if/else
    } else {
       allOK = 0;
-      fprintf(stderr, "Unable to open file %s for reading! Aborting!\n", filename);
+      cerr << "Unable to open file " << filename << " for reading! Aborting!\n";
    } // if/else
 
    // Something went badly wrong, so blank out partitions
@@ -1155,25 +1161,25 @@
 // Tell user whether Apple Partition Map (APM) was discovered....
 void GPTData::ShowAPMState(void) {
    if (apmFound)
-      printf("  APM: present\n");
+      cout << "  APM: present\n";
    else
-      printf("  APM: not present\n");
+      cout << "  APM: not present\n";
 } // GPTData::ShowAPMState()
 
 // Tell user about the state of the GPT data....
 void GPTData::ShowGPTState(void) {
    switch (state) {
       case gpt_invalid:
-         printf("  GPT: not present\n");
+         cout << "  GPT: not present\n";
          break;
       case gpt_valid:
-         printf("  GPT: present\n");
+         cout << "  GPT: present\n";
          break;
       case gpt_corrupt:
-         printf("  GPT: damaged\n");
+         cout << "  GPT: damaged\n";
          break;
       default:
-         printf("\a  GPT: unknown -- bug!\n");
+         cout << "\a  GPT: unknown -- bug!\n";
          break;
    } // switch
 } // GPTData::ShowGPTState()
@@ -1181,24 +1187,20 @@
 // Display the basic GPT data
 void GPTData::DisplayGPTData(void) {
    int i;
-   char sizeInSI[255]; // String to hold size of disk in SI units
-   char tempStr[255];
+//   char tempStr[255];
    uint64_t temp, totalFree;
 
-   BytesToSI(diskSize * blockSize, sizeInSI);
-   printf("Disk %s: %llu sectors, ", device,
-          (unsigned long long) diskSize);
-   printf("%s\n", sizeInSI);
-   printf("Logical sector size: %d bytes\n", blockSize);
-   printf("Disk identifier (GUID): %s\n", GUIDToStr(mainHeader.diskGUID, tempStr));
-   printf("Partition table holds up to %lu entries\n", (unsigned long) mainHeader.numParts);
-   printf("First usable sector is %llu, last usable sector is %llu\n",
-          (unsigned long long) mainHeader.firstUsableLBA,
-          (unsigned long long) mainHeader.lastUsableLBA);
+   cout << "Disk " << device << ": " << diskSize << " sectors, "
+        << BytesToSI(diskSize * blockSize) << "\n";
+   cout << "Logical sector size: " << blockSize << " bytes\n";
+   cout << "Disk identifier (GUID): " << GUIDToStr(mainHeader.diskGUID) << "\n";
+   cout << "Partition table holds up to " << mainHeader.numParts << " entries\n";
+   cout << "First usable sector is " << mainHeader.firstUsableLBA
+        << ", last usable sector is " << mainHeader.lastUsableLBA << "\n";
    totalFree = FindFreeBlocks(&i, &temp);
-   printf("Total free space is %llu sectors ", (unsigned long long) totalFree);
-   printf("(%s)\n", BytesToSI(totalFree * (uint64_t) blockSize, sizeInSI));
-   printf("\nNumber  Start (sector)    End (sector)  Size       Code  Name\n");
+   cout << "Total free space is " << totalFree << " sectors ("
+        << BytesToSI(totalFree * (uint64_t) blockSize) << ")\n";
+   cout << "\nNumber  Start (sector)    End (sector)  Size       Code  Name\n";
    for (i = 0; i < mainHeader.numParts; i++) {
       partitions[i].ShowSummary(i, blockSize);
    } // for
@@ -1214,7 +1216,7 @@
       partNum = GetPartNum();
       ShowPartDetails(partNum);
    } else {
-      printf("No partitions\n");
+      cout << "No partitions\n";
    } // if/else
 } // GPTData::ShowDetails()
 
@@ -1223,7 +1225,7 @@
    if (partitions[partNum].GetFirstLBA() != 0) {
       partitions[partNum].ShowDetails(blockSize);
    } else {
-      printf("Partition #%d does not exist.", (int) (partNum + 1));
+      cout << "Partition #" << partNum + 1 << " does not exist.";
    } // if
 } // GPTData::ShowPartDetails()
 
@@ -1253,8 +1255,7 @@
    char prompt[255];
    uint32_t curLow, curHigh;
 
-   printf("Current partition table size is %lu.\n",
-          (unsigned long) mainHeader.numParts);
+   cout << "Current partition table size is " << mainHeader.numParts << ".\n";
    GetPartRange(&curLow, &curHigh);
    curHigh++; // since GetPartRange() returns numbers starting from 0...
    // There's no point in having fewer than four partitions....
@@ -1264,10 +1265,10 @@
            (int) NUM_GPT_ENTRIES);
    newSize = GetNumber(4, 65535, 128, prompt);
    if (newSize < 128) {
-      printf("Caution: The partition table size should officially be 16KB or larger,\n"
-            "which works out to 128 entries. In practice, smaller tables seem to\n"
-            "work with most OSes, but this practice is risky. I'm proceeding with\n"
-            "the resize, but you may want to reconsider this action and undo it.\n\n");
+      cout << "Caution: The partition table size should officially be 16KB or larger,\n"
+           << "which works out to 128 entries. In practice, smaller tables seem to\n"
+           << "work with most OSes, but this practice is risky. I'm proceeding with\n"
+           << "the resize, but you may want to reconsider this action and undo it.\n\n";
    } // if
    SetGPTSize(newSize);
 } // GPTData::ResizePartitionTable()
@@ -1295,7 +1296,7 @@
          partNum = GetNumber(firstFreePart + 1, mainHeader.numParts,
                              firstFreePart + 1, prompt) - 1;
          if (partitions[partNum].GetFirstLBA() != 0)
-            printf("partition %d is in use.\n", partNum + 1);
+            cout << "partition " << partNum + 1 << " is in use.\n";
       } while (partitions[partNum].GetFirstLBA() != 0);
 
       // Get first block for new partition...
@@ -1320,9 +1321,9 @@
 
       firstFreePart = CreatePartition(partNum, firstBlock, lastBlock);
       partitions[partNum].ChangeType();
-      partitions[partNum].SetName((unsigned char*) partitions[partNum].GetNameType().c_str());
+      partitions[partNum].SetName(partitions[partNum].GetNameType());
    } else {
-      printf("No free sectors available\n");
+      cout << "No free sectors available\n";
    } // if/else
 } // GPTData::CreatePartition()
 
@@ -1337,7 +1338,7 @@
       partNum = GetNumber(low + 1, high + 1, low, prompt);
       DeletePartition(partNum - 1);
    } else {
-      printf("No partitions\n");
+      cout << "No partitions\n";
    } // if/else
 } // GPTData::DeletePartition()
 
@@ -1351,7 +1352,7 @@
       partNum = GetPartNum();
       partitions[partNum].ChangeType();
    } else {
-      printf("No partitions\n");
+      cout << "No partitions\n";
    } // if/else
 } // GPTData::ChangePartType()
 
@@ -1374,52 +1375,45 @@
 // MBR.
 int GPTData::DestroyGPT(int prompt) {
    int fd, i, sum, tableSize;
-   char blankSector[512], goOn = 'Y', blank = 'N';
-   char* emptyTable;
+   uint8_t blankSector[512], goOn = 'Y', blank = 'N';
+   uint8_t* emptyTable;
 
    for (i = 0; i < 512; i++) {
-      blankSector[i] = '\0';
+      blankSector[i] = 0;
    } // for
 
    if (((apmFound) || (bsdFound)) && (prompt > 0)) {
-      printf("WARNING: APM or BSD disklabel structures detected! This operation could\n"
-             "damage any APM or BSD partitions on this disk!\n");
+      cout << "WARNING: APM or BSD disklabel structures detected! This operation could\n"
+           << "damage any APM or BSD partitions on this disk!\n";
    } // if APM or BSD
    if (prompt > 0) {
-      printf("\a\aAbout to wipe out GPT on %s. Proceed? ", device);
+      cout << "\a\aAbout to wipe out GPT on " << device << ". Proceed? ";
       goOn = GetYN();
    } // if
    if (goOn == 'Y') {
-/*      OpenForWrite(device);
-#ifdef __APPLE__
-      // MacOS X requires a shared lock under some circumstances....
-      if (fd < 0) {
-         fd = open(device, O_WRONLY|O_SHLOCK);
-      } // if
-#endif */
       if (myDisk.OpenForWrite(device)) {
          myDisk.Seek(mainHeader.currentLBA); // seek to GPT header
          if (myDisk.Write(blankSector, 512) != 512) { // blank it out
-            fprintf(stderr, "Warning! GPT main header not overwritten! Error is %d\n", errno);
+            cerr << "Warning! GPT main header not overwritten! Error is " << errno << "\n";
          } // if
          myDisk.Seek(mainHeader.partitionEntriesLBA); // seek to partition table
          tableSize = mainHeader.numParts * mainHeader.sizeOfPartitionEntries;
-         emptyTable = (char*) malloc(tableSize);
+         emptyTable = (uint8_t*) malloc(tableSize);
          for (i = 0; i < tableSize; i++)
-            emptyTable[i] = (char) 0;
+            emptyTable[i] = 0;
          sum = myDisk.Write(emptyTable, tableSize);
          if (sum != tableSize)
-            fprintf(stderr, "Warning! GPT main partition table not overwritten! Error is %d\n", errno);
+            cerr << "Warning! GPT main partition table not overwritten! Error is " << errno << "\n";
          myDisk.Seek(secondHeader.partitionEntriesLBA); // seek to partition table
          sum = myDisk.Write(emptyTable, tableSize);
          if (sum != tableSize)
-            fprintf(stderr, "Warning! GPT backup partition table not overwritten! Error is %d\n", errno);
+            cerr << "Warning! GPT backup partition table not overwritten! Error is " << errno << "\n";
          myDisk.Seek(secondHeader.currentLBA); // seek to GPT header
          if (myDisk.Write(blankSector, 512) != 512) { // blank it out
-            fprintf(stderr, "Warning! GPT backup header not overwritten! Error is %d\n", errno);
+            cerr << "Warning! GPT backup header not overwritten! Error is " << errno << "\n";
          } // if
          if (prompt > 0) {
-            printf("Blank out MBR? ");
+            cout << "Blank out MBR? ";
             blank = GetYN();
          } // if
          // Note on below: Touch the MBR only if the user wants it completely
@@ -1430,18 +1424,18 @@
          if ((blank == 'Y') || (prompt < 0)) {
             myDisk.Seek(0);
             if (myDisk.Write(blankSector, 512) != 512) { // blank it out
-               fprintf(stderr, "Warning! MBR not overwritten! Error is %d!\n", errno);
+               cerr << "Warning! MBR not overwritten! Error is " << errno << "!\n";
             } // if
          } else {
-            printf("MBR is unchanged. You may need to delete an EFI GPT (0xEE) partition\n"
-                   "with fdisk or another tool.\n");
+            cout << "MBR is unchanged. You may need to delete an EFI GPT (0xEE) partition\n"
+                 << "with fdisk or another tool.\n";
          } // if/else
          myDisk.DiskSync();
          myDisk.Close();
-         printf("GPT data structures destroyed! You may now partition the disk using fdisk or\n"
-               "other utilities. Program will now terminate.\n");
+         cout << "GPT data structures destroyed! You may now partition the disk using fdisk or\n"
+              << "other utilities. Program will now terminate.\n";
       } else {
-         printf("Problem opening %s for writing! Program will now terminate.\n", device);
+         cerr << "Problem opening " << device << " for writing! Program will now terminate.\n";
       } // if/else (fd != -1)
    } // if (goOn == 'Y')
    return (goOn == 'Y');
@@ -1465,54 +1459,55 @@
    mbrState = protectiveMBR.GetValidity();
 
    if ((state == gpt_invalid) && ((mbrState == mbr) || (mbrState == hybrid))) {
-      printf("\n***************************************************************\n"
-             "Found invalid GPT and valid MBR; converting MBR to GPT format.\n");
+      cout << "\n***************************************************************\n"
+           << "Found invalid GPT and valid MBR; converting MBR to GPT format.\n";
       if (!justLooking) {
-         printf("\aTHIS OPERATON IS POTENTIALLY DESTRUCTIVE! Exit by typing 'q' if\n"
-               "you don't want to convert your MBR partitions to GPT format!\n");
+         cout << "\aTHIS OPERATON IS POTENTIALLY DESTRUCTIVE! Exit by typing 'q' if\n"
+              << "you don't want to convert your MBR partitions to GPT format!\n";
       } // if
-      printf("***************************************************************\n\n");
+      cout << "***************************************************************\n\n";
       which = use_mbr;
    } // if
 
    if ((state == gpt_invalid) && bsdFound) {
-      printf("\n**********************************************************************\n"
-            "Found invalid GPT and valid BSD disklabel; converting BSD disklabel\n"
-            "to GPT format.");
+      cout << "\n**********************************************************************\n"
+           << "Found invalid GPT and valid BSD disklabel; converting BSD disklabel\n"
+           << "to GPT format.";
       if (!justLooking) {
-      printf("\a THIS OPERATON IS POTENTIALLY DESTRUCTIVE! Your first\n"
-            "BSD partition will likely be unusable. Exit by typing 'q' if you don't\n"
-            "want to convert your BSD partitions to GPT format!");
+      cout << "\a THIS OPERATON IS POTENTIALLY DESTRUCTIVE! Your first\n"
+           << "BSD partition will likely be unusable. Exit by typing 'q' if you don't\n"
+           << "want to convert your BSD partitions to GPT format!";
       } // if
-      printf("\n**********************************************************************\n\n");
+      cout << "\n**********************************************************************\n\n";
       which = use_bsd;
    } // if
 
    if ((state == gpt_valid) && (mbrState == gpt)) {
       which = use_gpt;
       if (!beQuiet)
-         printf("Found valid GPT with protective MBR; using GPT.\n");
+         cout << "Found valid GPT with protective MBR; using GPT.\n";
    } // if
    if ((state == gpt_valid) && (mbrState == hybrid)) {
       which = use_gpt;
       if (!beQuiet)
-         printf("Found valid GPT with hybrid MBR; using GPT.\n");
+         cout << "Found valid GPT with hybrid MBR; using GPT.\n";
    } // if
    if ((state == gpt_valid) && (mbrState == invalid)) {
-      printf("\aFound valid GPT with corrupt MBR; using GPT and will create new\nprotective MBR on save.\n");
+      cout << "\aFound valid GPT with corrupt MBR; using GPT and will create new\n"
+           << "protective MBR on save.\n";
       which = use_gpt;
       protectiveMBR.MakeProtectiveMBR();
    } // if
    if ((state == gpt_valid) && (mbrState == mbr)) {
       if (!beQuiet) {
-         printf("Found valid MBR and GPT. Which do you want to use?\n");
-         answer = GetNumber(1, 3, 2, (char*) " 1 - MBR\n 2 - GPT\n 3 - Create blank GPT\n\nYour answer: ");
+         cout << "Found valid MBR and GPT. Which do you want to use?\n";
+         answer = GetNumber(1, 3, 2, " 1 - MBR\n 2 - GPT\n 3 - Create blank GPT\n\nYour answer: ");
          if (answer == 1) {
             which = use_mbr;
          } else if (answer == 2) {
             which = use_gpt;
             protectiveMBR.MakeProtectiveMBR();
-            printf("Using GPT and creating fresh protective MBR.\n");
+            cout << "Using GPT and creating fresh protective MBR.\n";
          } else which = use_new;
       } else which = use_abort;
    } // if
@@ -1524,34 +1519,33 @@
          which = use_abort;
       } else {
          if ((mbrState == mbr) || (mbrState == hybrid)) {
-            printf("Found valid MBR and corrupt GPT. Which do you want to use? (Using the\n"
-                  "GPT MAY permit recovery of GPT data.)\n");
-            answer = GetNumber(1, 3, 2, (char*) " 1 - MBR\n 2 - GPT\n 3 - Create blank GPT\n\nYour answer: ");
+            cout << "Found valid MBR and corrupt GPT. Which do you want to use? (Using the\n"
+                 << "GPT MAY permit recovery of GPT data.)\n";
+            answer = GetNumber(1, 3, 2, " 1 - MBR\n 2 - GPT\n 3 - Create blank GPT\n\nYour answer: ");
             if (answer == 1) {
                which = use_mbr;
-   //            protectiveMBR.MakeProtectiveMBR();
             } else if (answer == 2) {
                which = use_gpt;
             } else which = use_new;
          } else if (mbrState == invalid) {
-            printf("Found invalid MBR and corrupt GPT. What do you want to do? (Using the\n"
-                  "GPT MAY permit recovery of GPT data.)\n");
-            answer = GetNumber(1, 2, 1, (char*) " 1 - GPT\n 2 - Create blank GPT\n\nYour answer: ");
+            cout << "Found invalid MBR and corrupt GPT. What do you want to do? (Using the\n"
+                 << "GPT MAY permit recovery of GPT data.)\n";
+            answer = GetNumber(1, 2, 1, " 1 - GPT\n 2 - Create blank GPT\n\nYour answer: ");
             if (answer == 1) {
                which = use_gpt;
             } else which = use_new;
          } else { // corrupt GPT, MBR indicates it's a GPT disk....
-            printf("\a\a****************************************************************************\n"
-                  "Caution: Found protective or hybrid MBR and corrupt GPT. Using GPT, but disk\n"
-                  "verification and recovery are STRONGLY recommended.\n"
-                  "****************************************************************************\n");
+            cout << "\a\a****************************************************************************\n"
+                 << "Caution: Found protective or hybrid MBR and corrupt GPT. Using GPT, but disk\n"
+                 << "verification and recovery are STRONGLY recommended.\n"
+                 << "****************************************************************************\n";
             which = use_gpt;
          } // if/else/else
       } // else (beQuiet)
    } // if (corrupt GPT)
 
    if (which == use_new)
-      printf("Creating new GPT entries.\n");
+      cout << "Creating new GPT entries.\n";
 
    return which;
 } // UseWhichPartitions()
@@ -1611,30 +1605,30 @@
       // Now see if the specified partition has a BSD type code....
       hexCode = partitions[partNum].GetHexType();
       if ((hexCode != 0xa500) && (hexCode != 0xa900)) {
-         printf("Specified partition doesn't have a disklabel partition type "
-               "code.\nContinue anyway?");
+         cout << "Specified partition doesn't have a disklabel partition type "
+              << "code.\nContinue anyway? ";
          goOn = (GetYN() == 'Y');
       } // if
 
       // If all is OK, read the disklabel and convert it.
       if (goOn) {
-         goOn = disklabel.ReadBSDData(device, partitions[partNum].GetFirstLBA(),
+         goOn = disklabel.ReadBSDData(&myDisk, partitions[partNum].GetFirstLBA(),
                                       partitions[partNum].GetLastLBA());
          if ((goOn) && (disklabel.IsDisklabel())) {
             numDone = XFormDisklabel(&disklabel, startPart);
             if (numDone == 1)
-               printf("Converted %d BSD partition.\n", numDone);
+               cout << "Converted " << numDone << " BSD partition.\n";
             else
-               printf("Converted %d BSD partitions.\n", numDone);
+               cout << "Converted " << numDone << " BSD partitions.\n";
          } else {
-            printf("Unable to convert partitions! Unrecognized BSD disklabel.\n");
+            cout << "Unable to convert partitions! Unrecognized BSD disklabel.\n";
          } // if/else
       } // if
       if (numDone > 0) { // converted partitions; delete carrier
          partitions[partNum].BlankPartition();
       } // if
    } else {
-      printf("No partitions\n");
+      cout << "No partitions\n";
    } // if/else
    return numDone;
 } // GPTData::XFormDisklable(int i)
@@ -1667,42 +1661,48 @@
    char line[255];
    char* junk;
 
+   cout.setf(ios::uppercase);
+   cout.fill('0');
+
    if ((mbrPart < 0) || (mbrPart > 3)) {
-      printf("MBR partition %d is out of range; omitting it.\n", mbrPart + 1);
+      cout << "MBR partition " << mbrPart + 1 << " is out of range; omitting it.\n";
       allOK = 0;
    } // if
    if (gptPart >= mainHeader.numParts) {
-      printf("GPT partition %d is out of range; omitting it.\n", gptPart + 1);
+      cout << "GPT partition " << gptPart + 1 << " is out of range; omitting it.\n";
       allOK = 0;
    } // if
    if (allOK && (partitions[gptPart].GetLastLBA() == UINT64_C(0))) {
-      printf("GPT partition %d is undefined; omitting it.\n", gptPart + 1);
+      cout << "GPT partition " << gptPart + 1 << " is undefined; omitting it.\n";
       allOK = 0;
    } // if
    if (allOK && (partitions[gptPart].GetFirstLBA() <= UINT32_MAX) &&
        (partitions[gptPart].GetLengthLBA() <= UINT32_MAX)) {
       if (partitions[gptPart].GetLastLBA() > UINT32_MAX) {
-         printf("Caution: Partition end point past 32-bit pointer boundary;"
-                " some OSes may\nreact strangely.\n");
+         cout << "Caution: Partition end point past 32-bit pointer boundary;"
+              << " some OSes may\nreact strangely.\n";
       } // if partition ends past 32-bit (usually 2TiB) boundary
       do {
-         printf("Enter an MBR hex code (default %02X): ",
-                  typeHelper.GUIDToID(partitions[gptPart].GetType()) / 256);
+         cout << "Enter an MBR hex code (default " << hex;
+         cout.width(2);
+         cout << typeHelper.GUIDToID(partitions[gptPart].GetType()) / 256 << "): ";
          junk = fgets(line, 255, stdin);
-         sscanf(line, "%x", &typeCode);
          if (line[0] == '\n')
             typeCode = partitions[gptPart].GetHexType() / 256;
+         else
+            sscanf(line, "%x", &typeCode);
       } while ((typeCode <= 0) || (typeCode > 255));
-      printf("Set the bootable flag? ");
+      cout << "Set the bootable flag? ";
       bootable = (GetYN() == 'Y');
       length = partitions[gptPart].GetLengthLBA();
       protectiveMBR.MakePart(mbrPart, (uint32_t) partitions[gptPart].GetFirstLBA(),
                              (uint32_t) length, typeCode, bootable);
    } else { // partition out of range
-      printf("Partition %d begins beyond the 32-bit pointer limit of MBR "
-             "partitions, or is\n too big; omitting it.\n", gptPart + 1);
+      cout << "Partition " << gptPart + 1 << " begins beyond the 32-bit pointer limit of MBR "
+           << "partitions, or is\n too big; omitting it.\n";
       allOK = 0;
    } // if/else
+   cout.fill(' ');
    return allOK;
 } // GPTData::OnePartToMBR()
 
@@ -1720,15 +1720,15 @@
    // Get the numbers of up to four partitions to add to the
    // hybrid MBR....
    numParts = CountParts();
-   printf("Counted %d partitions.\n", numParts);
+   cout << "Counted " << numParts << " partitions.\n";
 
    // Prepare the MBR for conversion (empty it of existing partitions).
    protectiveMBR.EmptyMBR(0);
    protectiveMBR.SetDiskSize(diskSize);
 
    if (numParts > 4) { // Over four partitions; engage in triage
-      printf("Type from one to four GPT partition numbers, separated by spaces, to be\n"
-            "used in the MBR, in sequence: ");
+      cout << "Type from one to four GPT partition numbers, separated by spaces, to be\n"
+           << "used in the MBR, in sequence: ";
       junk = fgets(line, 255, stdin);
       numParts = sscanf(line, "%d %d %d %d", &partNums[0], &partNums[1],
                         &partNums[2], &partNums[3]);
@@ -1743,10 +1743,10 @@
 
    for (i = 0; i < numParts; i++) {
       j = partNums[i] - 1;
-      printf("\nCreating entry for partition #%d\n", j + 1);
+      cout << "\nCreating entry for partition #" << j + 1 << "\n";
       numConverted += OnePartToMBR(j, i);
    } // for
-   printf("MBR writing returned %d\n", protectiveMBR.WriteMBRData(&myDisk));
+   cout << "MBR writing returned " << protectiveMBR.WriteMBRData(&myDisk) << "\n";
    return numConverted;
 } // GPTData::XFormToMBR()
 
@@ -1760,14 +1760,14 @@
    char fillItUp = 'M'; // fill extra partition entries? (Yes/No/Maybe)
    char eeFirst = 'Y'; // Whether EFI GPT (0xEE) partition comes first in table
 
-   printf("\nWARNING! Hybrid MBRs are flaky and potentially dangerous! If you decide not\n"
-         "to use one, just hit the Enter key at the below prompt and your MBR\n"
-         "partition table will be untouched.\n\n\a");
+   cout << "\nWARNING! Hybrid MBRs are flaky and potentially dangerous! If you decide not\n"
+        << "to use one, just hit the Enter key at the below prompt and your MBR\n"
+        << "partition table will be untouched.\n\n\a";
 
    // Now get the numbers of up to three partitions to add to the
    // hybrid MBR....
-   printf("Type from one to three GPT partition numbers, separated by spaces, to be\n"
-         "added to the hybrid MBR, in sequence: ");
+   cout << "Type from one to three GPT partition numbers, separated by spaces, to be\n"
+        << "added to the hybrid MBR, in sequence: ";
    junk = fgets(line, 255, stdin);
    numParts = sscanf(line, "%d %d %d", &partNums[0], &partNums[1], &partNums[2]);
 
@@ -1776,13 +1776,13 @@
       // alone....
       protectiveMBR.EmptyMBR(0);
       protectiveMBR.SetDiskSize(diskSize);
-      printf("Place EFI GPT (0xEE) partition first in MBR (good for GRUB)? ");
+      cout << "Place EFI GPT (0xEE) partition first in MBR (good for GRUB)? ";
       eeFirst = GetYN();
    } // if
 
    for (i = 0; i < numParts; i++) {
       j = partNums[i] - 1;
-      printf("\nCreating entry for partition #%d\n", j + 1);
+      cout << "\nCreating entry for partition #" << j + 1 << "\n";
       if (eeFirst == 'Y')
          mbrNum = i + 1;
       else
@@ -1811,13 +1811,13 @@
       for (i = 0; i < 4; i++) {
          if (protectiveMBR.GetType(i) == 0x00) { // unused entry....
             if (fillItUp == 'M') {
-               printf("\nUnused partition space(s) found. Use one to protect more partitions? ");
+               cout << "\nUnused partition space(s) found. Use one to protect more partitions? ";
                fillItUp = GetYN();
                typeCode = 0x00; // use this to flag a need to get type code
             } // if
             if (fillItUp == 'Y') {
                while ((typeCode <= 0) || (typeCode > 255)) {
-                  printf("Enter an MBR hex code (EE is EFI GPT, but may confuse MacOS): ");
+                  cout << "Enter an MBR hex code (EE is EFI GPT, but may confuse MacOS): ";
                   // Comment on above: Mac OS treats disks with more than one
                   // 0xEE MBR partition as MBR disks, not as GPT disks.
                   junk = fgets(line, 255, stdin);
@@ -1852,9 +1852,9 @@
    // that fills the allocated sectors
    i = blockSize / GPT_SIZE;
    if ((numEntries % i) != 0) {
-      printf("Adjusting GPT size from %lu ", (unsigned long) numEntries);
+      cout << "Adjusting GPT size from " << numEntries << " to ";
       numEntries = ((numEntries / i) + 1) * i;
-      printf("to %lu to fill the sector\n", (unsigned long) numEntries);
+      cout << numEntries << " to fill the sector\n";
    } // if
 
    // Do the work only if the # of partitions is changing. Along with being
@@ -1869,9 +1869,10 @@
          if (partitions != NULL) { // existing partitions; copy them over
             GetPartRange(&i, &high);
             if (numEntries < (high + 1)) { // Highest entry too high for new #
-               printf("The highest-numbered partition is %lu, which is greater than the requested\n"
-                     "partition table size of %d; cannot resize. Perhaps sorting will help.\n",
-                     (unsigned long) (high + 1), numEntries);
+               cout << "The highest-numbered partition is " << high + 1
+                    << ", which is greater than the requested\n"
+                    << "partition table size of " << numEntries
+                    << "; cannot resize. Perhaps sorting will help.\n";
                allOK = 0;
             } else { // go ahead with copy
                if (numEntries < mainHeader.numParts)
@@ -1896,7 +1897,7 @@
          if (diskSize > 0)
             CheckGPTSize();
       } else { // Bad memory allocation
-         fprintf(stderr, "Error allocating memory for partition table!\n");
+         cerr << "Error allocating memory for partition table!\n";
          allOK = 0;
       } // if/else
    } // if/else
@@ -1930,7 +1931,7 @@
       // Now delete the GPT partition
       partitions[partNum].BlankPartition();
    } else {
-      fprintf(stderr, "Partition number %d out of range!\n", partNum + 1);
+      cerr << "Partition number " << partNum + 1 << " out of range!\n";
       retval = 0;
    } // if/else
    return retval;
@@ -2001,7 +2002,8 @@
    int goOn = 1, i;
 
    // Set up the partition table....
-   free(partitions);
+   if (partitions != NULL)
+      free(partitions);
    partitions = NULL;
    SetGPTSize(NUM_GPT_ENTRIES);
 
@@ -2051,11 +2053,12 @@
    secondHeader.partitionEntriesLBA = secondHeader.lastUsableLBA + UINT64_C(1);
 } // GPTData::FixSecondHeaderLocation()
 
-int GPTData::SetName(uint32_t partNum, char* theName) {
+int GPTData::SetName(uint32_t partNum, string theName) {
    int retval = 1;
-   if (!IsFreePartNum(partNum))
-      partitions[partNum].SetName((unsigned char*) theName);
-   else retval = 0;
+
+   if (!IsFreePartNum(partNum)) {
+      partitions[partNum].SetName(theName);
+   } else retval = 0;
 
    return retval;
 } // GPTData::SetName
@@ -2117,7 +2120,6 @@
       // Check to see that every sector between the earlier one and the
       // requested one is clear, and that it's not too early....
       if (earlier >= mainHeader.firstUsableLBA) {
-//         printf("earlier is %llu, first usable is %llu\n", earlier, mainHeader.firstUsableLBA);
          sectorOK = 1;
          testSector = earlier;
          do {
@@ -2125,7 +2127,6 @@
          } while ((sectorOK == 1) && (testSector < *sector));
          if (sectorOK == 1) {
             *sector = earlier;
-//            printf("Moved sector earlier.\n");
          } // if
       } // if firstUsableLBA check
 
@@ -2138,22 +2139,21 @@
          } while ((sectorOK == 1) && (testSector > *sector));
          if (sectorOK == 1) {
             *sector = later;
-//            printf("Moved sector later\n");
          } // if
       } // if
 
       // If sector was changed successfully, inform the user of this fact.
       // Otherwise, notify the user that it couldn't be done....
       if (sectorOK == 1) {
-         printf("Information: Moved requested sector from %llu to %llu for\n"
-                "alignment purposes.\n",
-                (unsigned long long) original, (unsigned long long) *sector);
+         cout << "Information: Moved requested sector from " << original << " to "
+              << *sector << " for\nalignment purposes.\n";
          if (!beQuiet)
-            printf("Use 'l' on the experts' menu to adjust alignment\n");
+            cout << "Use 'l' on the experts' menu to adjust alignment\n";
       } else {
-         printf("Information: Sector not aligned on %d-sector boundary and could not be moved.\n"
-                "If you're using a Western Digital Advanced Format or similar disk with\n"
-                "underlying 4096-byte sectors, performance may suffer.\n", sectorAlignment);
+         cout << "Information: Sector not aligned on " << sectorAlignment
+              << "-sector boundary and could not be moved.\n"
+              << "If you're using a Western Digital Advanced Format or similar disk with\n"
+              << "underlying 4096-byte sectors, performance may suffer.\n";
          retval = 0;
       } // if/else
    } // if
@@ -2408,8 +2408,8 @@
    // if the function is called out of order. Unfortunately, it'll also
    // mismatch if there's data corruption.
    if ((mainHeader.signature != GPT_SIGNATURE) && (IsLittleEndian() == 0)) {
-      printf("GPT signature mismatch in GPTData::ReversePartitionBytes(). This indicates\n"
-            "data corruption or a misplaced call to this function.\n");
+      cerr << "GPT signature mismatch in GPTData::ReversePartitionBytes(). This indicates\n"
+           << "data corruption or a misplaced call to this function.\n";
    } // if signature mismatch....
    for (i = 0; i < mainHeader.numParts; i++) {
       partitions[i].ReversePartBytes();
@@ -2430,42 +2430,41 @@
    int allOK = 1;
 
    if (sizeof(uint8_t) != 1) {
-      fprintf(stderr, "uint8_t is %lu bytes, should be 1 byte; aborting!\n", sizeof(uint8_t));
+      cerr << "uint8_t is " << sizeof(uint8_t) << " bytes, should be 1 byte; aborting!\n";
       allOK = 0;
    } // if
    if (sizeof(uint16_t) != 2) {
-      fprintf(stderr, "uint16_t is %lu bytes, should be 2 bytes; aborting!\n", sizeof(uint16_t));
+      cerr << "uint16_t is " << sizeof(uint16_t) << " bytes, should be 2 bytes; aborting!\n";
       allOK = 0;
    } // if
    if (sizeof(uint32_t) != 4) {
-      fprintf(stderr, "uint32_t is %lu bytes, should be 4 bytes; aborting!\n", sizeof(uint32_t));
+      cerr << "uint32_t is " << sizeof(uint32_t) << " bytes, should be 4 bytes; aborting!\n";
       allOK = 0;
    } // if
    if (sizeof(uint64_t) != 8) {
-      fprintf(stderr, "uint64_t is %lu bytes, should be 8 bytes; aborting!\n", sizeof(uint64_t));
+      cerr << "uint64_t is " << sizeof(uint64_t) << " bytes, should be 8 bytes; aborting!\n";
       allOK = 0;
    } // if
    if (sizeof(struct MBRRecord) != 16) {
-      fprintf(stderr, "MBRRecord is %lu bytes, should be 16 bytes; aborting!\n", sizeof(MBRRecord));
+      cerr << "MBRRecord is " << sizeof(MBRRecord) << " bytes, should be 16 bytes; aborting!\n";
       allOK = 0;
    } // if
    if (sizeof(struct TempMBR) != 512) {
-      fprintf(stderr, "TempMBR is %lu bytes, should be 512 bytes; aborting!\n", sizeof(TempMBR));
+      cerr << "TempMBR is " <<  sizeof(TempMBR) << " bytes, should be 512 bytes; aborting!\n";
       allOK = 0;
    } // if
    if (sizeof(struct GPTHeader) != 512) {
-      fprintf(stderr, "GPTHeader is %lu bytes, should be 512 bytes; aborting!\n", sizeof(GPTHeader));
+      cerr << "GPTHeader is " << sizeof(GPTHeader) << " bytes, should be 512 bytes; aborting!\n";
       allOK = 0;
    } // if
    if (sizeof(GPTPart) != 128) {
-      fprintf(stderr, "GPTPart is %lu bytes, should be 128 bytes; aborting!\n", sizeof(GPTPart));
+      cerr << "GPTPart is " << sizeof(GPTPart) << " bytes, should be 128 bytes; aborting!\n";
       allOK = 0;
    } // if
-// Determine endianness; set allOK = 0 if running on big-endian hardware
+   // Determine endianness; warn user if running on big-endian (PowerPC, etc.) hardware
    if (IsLittleEndian() == 0) {
-      fprintf(stderr, "\aRunning on big-endian hardware. Big-endian support is new and poorly"
-            " tested!\nBeware!\n");
-      // allOK = 0;
+      cerr << "\aRunning on big-endian hardware. Big-endian support is new and poorly"
+            " tested!\n";
    } // if
    return (allOK);
 } // SizesOK()
diff --git a/gpt.h b/gpt.h
index 1d605b5..76f1678 100644
--- a/gpt.h
+++ b/gpt.h
@@ -16,7 +16,7 @@
 #ifndef __GPTSTRUCTS
 #define __GPTSTRUCTS
 
-#define GPTFDISK_VERSION "0.6.2-pre1"
+#define GPTFDISK_VERSION "0.6.2-pre2"
 
 using namespace std;
 
@@ -59,7 +59,7 @@
    GPTPart *partitions;
    struct GPTHeader secondHeader;
    MBRData protectiveMBR;
-   char device[256]; // device filename
+   string device; // device filename
    DiskIO myDisk;
    uint32_t blockSize; // device block size
    uint64_t diskSize; // size of device, in blocks
@@ -78,7 +78,7 @@
 public:
    // Basic necessary functions....
    GPTData(void);
-   GPTData(char* deviceFilename);
+   GPTData(string deviceFilename);
    ~GPTData(void);
 
    // Verify (or update) data integrity
@@ -93,15 +93,15 @@
    int FindOverlaps(void);
 
    // Load or save data from/to disk
-   int LoadMBR(char* f) {return protectiveMBR.ReadMBRData(f);}
+   int LoadMBR(string f) {return protectiveMBR.ReadMBRData(f);}
    void PartitionScan(void);
-   int LoadPartitions(char* deviceFilename);
+   int LoadPartitions(string deviceFilename);
    int ForceLoadGPTData(void);
    int LoadMainTable(void);
    int LoadSecondTableAsMain(void);
    int SaveGPTData(int quiet = 0);
-   int SaveGPTBackup(char* filename);
-   int LoadGPTBackup(char* filename);
+   int SaveGPTBackup(string filename);
+   int LoadGPTBackup(string filename);
 
    // Display data....
    void ShowAPMState(void);
@@ -137,7 +137,7 @@
    void SortGPT(void);
    int ClearGPTData(void);
    void MoveSecondHeaderToEnd();
-   int SetName(uint32_t partNum, char* theName = NULL);
+   int SetName(uint32_t partNum, string theName = "");
    void SetDiskGUID(GUIDData newGUID);
    int SetPartitionGUID(uint32_t pn, GUIDData theGUID);
    int ChangePartType(uint32_t pn, uint16_t hexCode);
diff --git a/gptpart.cc b/gptpart.cc
index 076f115..c6504c1 100644
--- a/gptpart.cc
+++ b/gptpart.cc
@@ -15,8 +15,9 @@
 #define __STDC_LIMIT_MACROS
 #define __STDC_CONSTANT_MACROS
 
-#include <stdio.h>
 #include <string.h>
+#include <stdio.h>
+#include <iostream>
 #include "gptpart.h"
 #include "attributes.h"
 
@@ -34,14 +35,14 @@
 GPTPart::~GPTPart(void) {
 } // destructor
 
-// Return partition's name field
+// Return partition's name field, converted to a C++ ASCII string
 string GPTPart::GetName(void) {
    string theName;
+   int i;
 
-/*   if (ref == NULL)
-      ref = (unsigned char*) malloc(NAME_SIZE * sizeof (unsigned char));
-   strcpy((char*) ref, (char*) name); */
-   theName = (const char*) name;
+   for (i = 0; i < NAME_SIZE; i += 2) {
+      theName += name[i];
+   } // for
    return theName;
 } // GPTPart::GetName()
 
@@ -53,12 +54,7 @@
 // Return a plain-text description of the partition type (e.g., "Linux/Windows
 // data" or "Linux swap").
 string GPTPart::GetNameType(void) {
-   string temp;
-   char theName[255];
-
-   temp = typeHelper.GUIDToName(partitionType, theName);
-
-   return temp;
+   return typeHelper.GUIDToName(partitionType);
 } // GPTPart::GetNameType()
 
 // Compute and return the partition's length (or 0 if the end is incorrectly
@@ -141,50 +137,56 @@
 
 // Display summary information; does nothing if the partition is empty.
 void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
-   char sizeInSI[255];
-   int j = 0;
+   string sizeInSI;
+   int i;
 
    if (firstLBA != 0) {
-      BytesToSI(blockSize * (lastLBA - firstLBA + 1), sizeInSI);
-      printf("%4d  %14lu  %14lu", partNum + 1, (unsigned long) firstLBA,
-             (unsigned long) lastLBA);
-      printf("   %-10s  %04X  ", sizeInSI,
-             typeHelper.GUIDToID(partitionType));
-      while ((name[j] != '\0') && (j < 44)) {
-         printf("%c", name[j]);
-         j += 2;
-      } // while
-      printf("\n");
+      sizeInSI = BytesToSI(blockSize * (lastLBA - firstLBA + 1));
+      cout.width(4);
+      cout << partNum + 1 << "  ";
+      cout.width(14);
+      cout << firstLBA << "  ";
+      cout.width(14);
+      cout << lastLBA  << "   ";
+      cout << BytesToSI(blockSize * (lastLBA - firstLBA + 1)) << "   ";
+      for (i = 0; i < 9 - sizeInSI.length(); i++) cout << " ";
+      cout.fill('0');
+      cout.width(4);
+      cout.setf(ios::uppercase);
+      cout << hex << typeHelper.GUIDToID(partitionType) << "  " << dec;
+      cout.fill(' ');
+      cout.setf(ios::right);
+      cout << GetName().substr(0, 23) << "\n";
+      cout.fill(' ');
    } // if
 } // GPTPart::ShowSummary()
 
 // Show detailed partition information. Does nothing if the partition is
 // empty (as determined by firstLBA being 0).
 void GPTPart::ShowDetails(uint32_t blockSize) {
-   char temp[255];
-   int i;
    uint64_t size;
 
    if (firstLBA != 0) {
-      printf("Partition GUID code: %s ", GUIDToStr(partitionType, temp));
-      printf("(%s)\n", typeHelper.GUIDToName(partitionType, temp));
-      printf("Partition unique GUID: %s\n", GUIDToStr(uniqueGUID, temp));
+      cout << "Partition GUID code: " << GUIDToStr(partitionType);
+      cout << " (" << typeHelper.GUIDToName(partitionType) << ")\n";
+      cout << "Partition unique GUID: " << GUIDToStr(uniqueGUID) << "\n";
 
-      printf("First sector: %llu ", firstLBA);
-      printf("(at %s)\n", BytesToSI(firstLBA * blockSize, temp));
-      printf("Last sector: %llu ", (unsigned long long) lastLBA);
-      printf("(at %s)\n", BytesToSI(lastLBA * blockSize, temp));
+      cout << "First sector: " << firstLBA << " (at "
+           << BytesToSI(firstLBA * blockSize) << ")\n";
+      cout << "Last sector: " << lastLBA << " (at "
+           << BytesToSI(lastLBA * blockSize) << ")\n";
       size = (lastLBA - firstLBA + 1);
-      printf("Partition size: %llu sectors ", (unsigned long long) size);
-      printf("(%s)\n", BytesToSI(size * ((uint64_t) blockSize), temp));
-      printf("Attribute flags: %016llx\n", (unsigned long long) attributes);
-      printf("Partition name: ");
-      i = 0;
-      while ((name[i] != '\0') && (i < NAME_SIZE)) {
-         printf("%c", name[i]);
-         i += 2;
-      } // while
-      printf("\n");
+      cout << "Partition size: " << size << " sectors ("
+           << BytesToSI(size * ((uint64_t) blockSize)) << ")\n";
+      cout << "Attribute flags: ";
+      cout.fill('0');
+      cout.width(16);
+      cout << right;
+      cout << hex;
+      cout << attributes << "\n";
+      cout << left;
+      cout << dec;
+      cout << "Partition name: " << GetName() << "\n";
    }  // if
 } // GPTPart::ShowDetails()
 
@@ -194,14 +196,14 @@
 
 // Change the type code on the partition.
 void GPTPart::ChangeType(void) {
-   char typeName[255], line[255];
+   char line[255];
    char* junk;
    int typeNum = 0xFFFF;
    GUIDData newType;
 
-   printf("Current type is '%s'\n", GetNameType().c_str());
+   cout << "Current type is '" << GetNameType() << "'\n";
    while ((!typeHelper.Valid(typeNum)) && (typeNum != 0)) {
-      printf("Hex code (L to show codes, 0 to enter raw code, Enter = 0700): ");
+      cout << "Hex code (L to show codes, 0 to enter raw code, Enter = 0700): ";
       junk = fgets(line, 255, stdin);
       sscanf(line, "%X", &typeNum);
       if ((line[0] == 'L') || (line[0] == 'l'))
@@ -215,25 +217,24 @@
    else // user wants to enter the GUID directly, so do that
       newType = GetGUID();
    partitionType = newType;
-   printf("Changed type of partition to '%s'\n",
-          typeHelper.GUIDToName(partitionType, typeName));
+   cout << "Changed type of partition to '" << typeHelper.GUIDToName(partitionType) << "'\n";
 } // GPTPart::ChangeType()
 
 // Set the name for a partition to theName, or prompt for a name if
-// theName is a NULL pointer. Note that theName is a standard C-style
+// theName is empty. Note that theName is a standard C++-style ASCII
 // string, although the GUID partition definition requires a UTF-16LE
 // string. This function creates a simple-minded copy for this.
-void GPTPart::SetName(unsigned char* theName) {
+void GPTPart::SetName(string theName) {
    char newName[NAME_SIZE]; // New name
-   char* junk;
+   char *junk;
    int i;
 
    // Blank out new name string, just to be on the safe side....
    for (i = 0; i < NAME_SIZE; i++)
       newName[i] = '\0';
 
-   if (theName == NULL) { // No name specified, so get one from the user
-      printf("Enter name: ");
+   if (theName == "") { // No name specified, so get one from the user
+      cout << "Enter name: ";
       junk = fgets(newName, NAME_SIZE / 2, stdin);
 
       // Input is likely to include a newline, so remove it....
@@ -241,7 +242,7 @@
       if (newName[i - 1] == '\n')
          newName[i - 1] = '\0';
    } else {
-      strcpy(newName, (char*) theName);
+      strcpy(newName, theName.substr(0, NAME_SIZE / 2).c_str());
    } // if
 
    // Copy the C-style ASCII string from newName into a form that the GPT
diff --git a/gptpart.h b/gptpart.h
index 2ae27e3..dc499b9 100644
--- a/gptpart.h
+++ b/gptpart.h
@@ -69,7 +69,7 @@
       void SetFirstLBA(uint64_t f) {firstLBA = f;}
       void SetLastLBA(uint64_t l) {lastLBA = l;}
       void SetAttributes(uint64_t a) {attributes = a;}
-      void SetName(unsigned char* n);
+      void SetName(string n);
 
       // Additional functions
       GPTPart & operator=(const GPTPart & orig);
diff --git a/mbr.cc b/mbr.cc
index 029b576..411cae5 100644
--- a/mbr.cc
+++ b/mbr.cc
@@ -18,6 +18,7 @@
 #include <time.h>
 #include <sys/stat.h>
 #include <errno.h>
+#include <iostream>
 #include "mbr.h"
 #include "support.h"
 
@@ -32,7 +33,7 @@
 MBRData::MBRData(void) {
    blockSize = SECTOR_SIZE;
    diskSize = 0;
-   strcpy(device, "");
+   device = "";
    state = invalid;
    srand((unsigned int) time(NULL));
    numHeads = MAX_HEADS;
@@ -40,10 +41,10 @@
    EmptyMBR();
 } // MBRData default constructor
 
-MBRData::MBRData(char *filename) {
+MBRData::MBRData(string filename) {
    blockSize = SECTOR_SIZE;
    diskSize = 0;
-   strcpy(device, filename);
+   device = filename;
    state = invalid;
    numHeads = MAX_HEADS;
    numSecspTrack = MAX_SECSPERTRACK;
@@ -52,7 +53,7 @@
    // Try to read the specified partition table, but if it fails....
    if (!ReadMBRData(filename)) {
       EmptyMBR();
-      strcpy(device, "");
+      device = "";
    } // if
 } // MBRData(char *filename) constructor
 
@@ -67,7 +68,7 @@
 
 // Read data from MBR. Returns 1 if read was successful (even if the
 // data isn't a valid MBR), 0 if the read failed.
-int MBRData::ReadMBRData(char* deviceFilename) {
+int MBRData::ReadMBRData(string deviceFilename) {
    int fd, allOK = 1;
 
    if (myDisk->OpenForRead(deviceFilename)) {
@@ -77,7 +78,7 @@
    } // if
 
    if (allOK)
-      strcpy(device, deviceFilename);
+      device = deviceFilename;
 
    return allOK;
 } // MBRData::ReadMBRData(char* deviceFilename)
@@ -101,7 +102,7 @@
      if (myDisk->Read(&tempMBR, 512))
         err = 0;
    if (err) {
-      fprintf(stderr, "Problem reading disk in MBRData::ReadMBRData!\n");
+      cerr << "Problem reading disk in MBRData::ReadMBRData!\n";
    } else {
       for (i = 0; i < 440; i++)
          code[i] = tempMBR.code[i];
@@ -152,7 +153,7 @@
                logicalNum = ReadLogicalPart(partitions[i].firstLBA, UINT32_C(0), 4);
                if ((logicalNum < 0) || (logicalNum >= MAX_MBR_PARTS)) {
                   allOK = 0;
-                  fprintf(stderr, "Error reading logical partitions! List may be truncated!\n");
+                  cerr << "Error reading logical partitions! List may be truncated!\n";
                } // if maxLogicals valid
             } // if primary partition is extended
          } // for primary partition loop
@@ -202,14 +203,13 @@
    // function as of GPT fdisk version 0.5.0 doesn't do so.
    if ((partNum < MAX_MBR_PARTS) && (partNum >= 0)) {
       offset = (uint64_t) (extendedStart + diskOffset);
-//      if (lseek64(fd, offset, SEEK_SET) == (off_t) -1) { // seek to EBR record
       if (myDisk->Seek(offset) == 0) { // seek to EBR record
-         fprintf(stderr, "Unable to seek to %lu! Aborting!\n", (unsigned long) offset);
+         cerr << "Unable to seek to " << offset << "! Aborting!\n";
          partNum = -1;
       }
       if (myDisk->Read(&ebr, 512) != 512) { // Load the data....
-         fprintf(stderr, "Error seeking to or reading logical partition data from %lu!\nAborting!\n",
-                 (unsigned long) offset);
+         cerr << "Error seeking to or reading logical partition data from " << offset
+              << "!\nAborting!\n";
          partNum = -1;
       } else if (IsLittleEndian() != 1) { // Reverse byte ordering of some data....
          ReverseBytes(&ebr.MBRSignature, 2);
@@ -221,8 +221,14 @@
 
       if (ebr.MBRSignature != MBR_SIGNATURE) {
          partNum = -1;
-         fprintf(stderr, "MBR signature in logical partition invalid; read 0x%04X, but should be 0x%04X\n",
-                (unsigned int) ebr.MBRSignature, (unsigned int) MBR_SIGNATURE);
+         cerr << "MBR signature in logical partition invalid; read 0x";
+         cerr.fill('0');
+         cerr.width(4);
+         cerr.setf(ios::uppercase);
+         cerr << hex << ebr.MBRSignature << ", but should be 0x";
+         cerr.width(4);
+         cerr << MBR_SIGNATURE << dec << "\n";
+         cerr.fill(' ');
       } // if
 
       // Copy over the basic data....
@@ -297,11 +303,11 @@
    if (allOK && theDisk->Seek(0)) {
       if (theDisk->Write(&tempMBR, 512) != 512) {
          allOK = 0;
-         fprintf(stderr, "Warning! Error %d when saving MBR!\n", errno);
+         cerr << "Warning! Error " << errno << " when saving MBR!\n";
       } // if
    } else {
       allOK = 0;
-      fprintf(stderr, "Warning! Error %d when seeking to MBR to write it!\n", errno);
+      cerr << "Warning! Error " << errno << " when seeking to MBR to write it!\n";
    } // if/else
    theDisk->Close();
 
@@ -318,8 +324,8 @@
    return allOK;
 } // MBRData::WriteMBRData(DiskIO theDisk)
 
-int MBRData::WriteMBRData(char* deviceFilename) {
-   strcpy(device, deviceFilename);
+int MBRData::WriteMBRData(string deviceFilename) {
+   device = deviceFilename;
    return WriteMBRData();
 } // MBRData::WriteMBRData(char* deviceFilename)
 
@@ -335,22 +341,34 @@
    char tempStr[255];
    char bootCode;
 
-   printf("MBR disk identifier: 0x%08X\n", (unsigned int) diskSignature);
-   printf("MBR partitions:\n");
-   printf("Number\t Boot\t Start (sector)\t Length (sectors)\tType\n");
+   cout << "MBR disk identifier: 0x";
+   cout.width(8);
+   cout.fill('0');
+   cout.setf(ios::uppercase);
+   cout << hex << diskSignature << dec << "\n";
+   cout << "MBR partitions:\n";
+   cout << "Number\t Boot\t Start (sector)\t Length (sectors)\tType\n";
    for (i = 0; i < MAX_MBR_PARTS; i++) {
       if (partitions[i].lengthLBA != 0) {
          if (partitions[i].status && 0x80) // it's bootable
             bootCode = '*';
          else
             bootCode = ' ';
-         printf("%4d\t   %c\t%13lu\t%15lu \t0x%02X\n", i + 1, bootCode,
-                (unsigned long) partitions[i].firstLBA,
-                (unsigned long) partitions[i].lengthLBA, partitions[i].partitionType);
+         cout.fill(' ');
+         cout.width(4);
+         cout << i + 1 << "\t   " << bootCode << "\t";
+         cout.width(13);
+         cout << partitions[i].firstLBA << "\t";
+         cout.width(15);
+         cout << partitions[i].lengthLBA << " \t0x";
+         cout.width(2);
+         cout.fill('0');
+         cout << hex << (int) partitions[i].partitionType << dec << "\n";
       } // if
+      cout.fill(' ');
    } // for
-   printf("\nDisk size is %llu sectors ", (unsigned long long) diskSize);
-   printf("(%s)\n", BytesToSI(diskSize * (uint64_t) blockSize, tempStr));
+   cout << "\nDisk size is " << diskSize << " sectors ("
+        << BytesToSI(diskSize * (uint64_t) blockSize) << "\n";
 } // MBRData::DisplayMBRData()
 
 // Displays the state, as a word, on stdout. Used for debugging & to
@@ -358,19 +376,19 @@
 void MBRData::ShowState(void) {
    switch (state) {
       case invalid:
-         printf("  MBR: not present\n");
+         cout << "  MBR: not present\n";
          break;
       case gpt:
-         printf("  MBR: protective\n");
+         cout << "  MBR: protective\n";
          break;
       case hybrid:
-         printf("  MBR: hybrid\n");
+         cout << "  MBR: hybrid\n";
          break;
       case mbr:
-         printf("  MBR: MBR only\n");
+         cout << "  MBR: MBR only\n";
          break;
       default:
-         printf("\a  MBR: unknown -- bug!\n");
+         cout << "\a  MBR: unknown -- bug!\n";
          break;
    } // switch
 } // MBRData::ShowState()
@@ -390,7 +408,7 @@
       numHeads = h;
       numSecspTrack = s;
    } else {
-      printf("Warning! Attempt to set invalid CHS geometry!\n");
+      cout << "Warning! Attempt to set invalid CHS geometry!\n";
    } // if/else
 } // MBRData::SetCHSGeom()
 
@@ -807,7 +825,7 @@
          newPart.SetType(((uint16_t) origType) * 0x0100);
          newPart.SetUniqueGUID(1);
          newPart.SetAttributes(0);
-         newPart.SetName((unsigned char*) newPart.GetNameType().c_str());
+         newPart.SetName(newPart.GetNameType());
       } // if not extended, protective, or non-existent
    } // if (origPart != NULL)
    return newPart;
diff --git a/mbr.h b/mbr.h
index c8711fc..9fc749b 100644
--- a/mbr.h
+++ b/mbr.h
@@ -71,16 +71,16 @@
    uint64_t numHeads; // number of heads, in CHS scheme
    uint64_t numSecspTrack; // number of sectors per track, in CHS scheme
    DiskIO* myDisk;
-   char device[256];
+   string device;
    MBRValidity state;
    struct MBRRecord* GetPartition(int i); // Return primary or logical partition
 public:
    MBRData(void);
-   MBRData(char* deviceFilename);
+   MBRData(string deviceFilename);
    ~MBRData(void);
 
    // File I/O functions...
-   int ReadMBRData(char* deviceFilename);
+   int ReadMBRData(string deviceFilename);
    void ReadMBRData(DiskIO * theDisk, int checkBlockSize = 1);
    // ReadLogicalPart() returns last partition # read to logicals[] array,
    // or -1 if there was a problem....
@@ -88,7 +88,7 @@
                        int partNum);
    int WriteMBRData(void);
    int WriteMBRData(DiskIO *theDisk);
-   int WriteMBRData(char* deviceFilename);
+   int WriteMBRData(string deviceFilename);
 
    // Display data for user...
    void DisplayMBRData(void);
diff --git a/parttypes.cc b/parttypes.cc
index 20289c6..d4e4a92 100644
--- a/parttypes.cc
+++ b/parttypes.cc
@@ -11,6 +11,7 @@
 #include <string.h>
 #include <stdint.h>
 #include <stdio.h>
+#include <iostream>
 #include "parttypes.h"
 
 using namespace std;
@@ -236,20 +237,24 @@
 void PartTypes::ShowTypes(void) {
    int colCount = 1; // column count
    AType* thisType = allTypes;
-   char tempStr[20];
 
+   cout.unsetf(ios::uppercase);
    while (thisType != NULL) {
       if (thisType->display == 1) { // show it
-         strncpy(tempStr, thisType->name, 19);
-	 tempStr[19] = '\0';
-         printf("%04x %-19s  ", thisType->MBRType, tempStr);
+         cout.fill('0');
+         cout.width(4);
+         cout << hex << thisType->MBRType << " ";
+         cout.fill(' ');
+         cout.setf(ios::left);
+         cout.width(19);
+         cout << ((string) thisType->name).substr(0, 19) << "  ";
          if ((colCount % 3) == 0)
-            printf("\n");
+            cout << "\n";
          colCount++;
       } // if
       thisType = thisType->next;
    } // while
-   printf("\n");
+   cout << "\n";
 } // PartTypes::ShowTypes()
 
 // Returns 1 if code is a valid extended MBR code, 0 if it's not
@@ -267,21 +272,24 @@
 } // PartTypes::Valid()
 
 // Convert a GUID code to a name.
-char* PartTypes::GUIDToName(struct GUIDData typeCode, char typeName[]) {
+string PartTypes::GUIDToName(struct GUIDData typeCode) {
    AType* theItem = allTypes;
    int found = 0;
+   string typeName;
 
    while ((theItem != NULL) && (!found)) {
       if ((theItem->GUIDType.data1 == typeCode.data1) &&
           (theItem->GUIDType.data2 == typeCode.data2)) { // found it!
-         strcpy(typeName, theItem->name);
+//         strcpy(typeName, theItem->name);
+         typeName = theItem->name;
 	 found = 1;
       } else {
          theItem = theItem->next;
       } // if/else
    } // while
    if (!found) {
-      strcpy(typeName, (char*) "Unknown");
+      typeName = "Unknown";
+//      strcpy(typeName, (char*) "Unknown");
    } // if (!found)
    return typeName;
 } // PartTypes::GUIDToName()
@@ -310,8 +318,11 @@
       } // if/else
    } // while
    if (!found) {
-      printf("Exact type match not found for type code %04X; assigning type code for\n'Linux/Windows data'\n",
-             ID);
+      cout.setf(ios::uppercase);
+      cout.fill('0');
+      cout << "Exact type match not found for type code ";
+      cout.width(4);
+      cout << hex << ID << "; assigning type code for\n'Linux/Windows data'\n" << dec;
    } // if (!found)
    return theGUID;
 } // PartTypes::IDToGUID()
diff --git a/parttypes.h b/parttypes.h
index 5a34d30..7e6d892 100644
--- a/parttypes.h
+++ b/parttypes.h
@@ -4,7 +4,7 @@
 #include <stdint.h>
 #include <unistd.h>
 #include <stdlib.h>
-#include <string.h>
+#include <string>
 #include "support.h"
 
 #ifndef __PARTITION_TYPES
@@ -39,7 +39,7 @@
                const char* name, int toDisplay = 1);
    void ShowTypes(void);
    int Valid(uint16_t);
-   char* GUIDToName(struct GUIDData typeCode, char typeName[]);
+   string GUIDToName(struct GUIDData typeCode);
    struct GUIDData IDToGUID(uint16_t ID);
    uint16_t GUIDToID(struct GUIDData);
 };
diff --git a/sgdisk.cc b/sgdisk.cc
index 5c346b7..14f95e5 100644
--- a/sgdisk.cc
+++ b/sgdisk.cc
@@ -13,6 +13,7 @@
 #include <string>
 #include <popt.h>
 #include <errno.h>
+#include <iostream>
 #include "mbr.h"
 #include "gpt.h"
 #include "support.h"
@@ -87,7 +88,7 @@
             pretend = 1;
             break;
          case 'V':
-            printf("GPT fdisk (sgdisk) version %s\n\n", GPTFDISK_VERSION);
+            cout << "GPT fdisk (sgdisk) version " << GPTFDISK_VERSION << "\n\n";
             break;
          default:
             break;
@@ -102,7 +103,7 @@
    if (device != NULL) {
       theGPT.JustLooking(); // reset as necessary
       theGPT.BeQuiet(); // Tell called functions to be less verbose & interactive
-      if (theGPT.LoadPartitions(device)) {
+      if (theGPT.LoadPartitions((string) device)) {
          if ((theGPT.WhichWasUsed() == use_mbr) || (theGPT.WhichWasUsed() == use_bsd))
             saveNonGPT = 0; // flag so we don't overwrite unless directed to do so
          while ((opt = poptGetNextOpt(poptCon)) > 0) {
@@ -117,11 +118,11 @@
                case 'c':
                   theGPT.JustLooking(0);
                   partNum = (int) GetInt(partName, 1) - 1;
-                  if (theGPT.SetName(partNum, (char*) GetString(partName, 2).c_str())) {
+                  if (theGPT.SetName(partNum, GetString(partName, 2))) {
                      saveData = 1;
                   } else {
-                     fprintf(stderr, "Unable set set partition %d's name to '%s'!\n",
-                             partNum + 1, GetString(partName, 2).c_str());
+                     cerr << "Unable set set partition " << partNum + 1
+                          << "'s name to '" << GetString(partName, 2) << "'!\n";
                      neverSaveData = 1;
                   } // if/else
                   free(partName);
@@ -129,7 +130,7 @@
                case 'd':
                   theGPT.JustLooking(0);
                   if (theGPT.DeletePartition(deletePartNum - 1) == 0) {
-                     fprintf(stderr, "Error %d deleting partition!\n", errno);
+                     cerr << "Error " << errno << " deleting partition!\n";
                      neverSaveData = 1;
                   } else saveData = 1;
                   break;
@@ -139,10 +140,10 @@
                   saveData = 1;
                   break;
                case 'E':
-                  printf("%llu\n", (unsigned long long) theGPT.FindLastAvailable(theGPT.FindFirstInLargest()));
+                  cout << theGPT.FindLastAvailable(theGPT.FindFirstInLargest()) << "\n";
                   break;
                case 'f':
-                  printf("%llu\n", (unsigned long long) theGPT.FindFirstInLargest());
+                  cout << theGPT.FindFirstInLargest() << "\n";
                   break;
                case 'g':
                   theGPT.JustLooking(0);
@@ -153,12 +154,12 @@
                   theGPT.ShowPartDetails(infoPartNum - 1);
                   break;
                case 'l':
-                  if (theGPT.LoadGPTBackup(backupFile) == 1)
+                  if (theGPT.LoadGPTBackup((string) backupFile) == 1)
                      saveData = 1;
                   else {
                      saveData = 0;
                      neverSaveData = 1;
-                     fprintf(stderr, "Error loading backup file!\n");
+                     cerr << "Error loading backup file!\n";
                   } // else
                   free(backupFile);
                   break;
@@ -172,8 +173,8 @@
                   if (theGPT.CreatePartition(partNum, startSector, endSector)) {
                      saveData = 1;
                   } else {
-                     fprintf(stderr, "Could not create partition %d from %llu to %llu!\n",
-                             partNum, startSector, endSector);
+                     cerr << "Could not create partition " << partNum << " from "
+                          << startSector << " to " << endSector << "\n";
                      neverSaveData = 1;
                   } // if/else
                   free(newPartInfo);
@@ -208,8 +209,8 @@
                   if (theGPT.ChangePartType(partNum, hexCode)) {
                      saveData = 1;
                   } else {
-                     fprintf(stderr, "Could not change partition %d's type code to %x!\n",
-                             partNum + 1, hexCode);
+                     cerr << "Could not change partition " << partNum + 1
+                          << "'s type code to " << hex << hexCode << "!\n" << dec;
                      neverSaveData = 1;
                   } // if/else
                   free(typeCode);
@@ -228,18 +229,18 @@
                   saveNonGPT = 0;
                   break;
                default:
-                  printf("Unknown option (-%c)!\n", opt);
+                  cerr << "Unknown option (-" << opt << ")!\n";
                   break;
             } // switch
          } // while
          if ((saveData) && (!neverSaveData) && (saveNonGPT) && (!pretend))
             theGPT.SaveGPTData(1);
          if (saveData && (!saveNonGPT)) {
-            printf("Non-GPT disk; not saving changes. Use -g to override.\n");
+            cout << "Non-GPT disk; not saving changes. Use -g to override.\n";
             retval = 3;
          } // if
          if (neverSaveData) {
-            printf("Error encountered; not saving changes.\n");
+            cerr << "Error encountered; not saving changes.\n";
             retval = 4;
          } // if
       } else { // if loaded OK
@@ -267,8 +268,6 @@
    endPos--;
 
    sscanf(Info.substr(startPos, endPos - startPos + 1).c_str(), "%llu", &retval);
-/*   printf("In GetInt(), startPos = %d, endPos = %d, retval = %llu\n", startPos,
-          endPos, (unsigned long long) retval); */
    return retval;
 } // GetInt()
 
diff --git a/support.cc b/support.cc
index 388b71a..3e4ad6c 100644
--- a/support.cc
+++ b/support.cc
@@ -10,11 +10,13 @@
 #define __STDC_CONSTANT_MACROS
 
 #include <stdio.h>
-#include <string>
 #include <stdint.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <string.h>
 #include <sys/stat.h>
+#include <string>
+#include <iostream>
 #include "support.h"
 
 #include <sys/types.h>
@@ -33,26 +35,25 @@
 // If user provides no input, def (default value) is returned.
 // (If def is outside of the low-high range, an explicit response
 // is required.)
-int GetNumber(int low, int high, int def, const char prompt[]) {
+int GetNumber(int low, int high, int def, const string & prompt) {
    int response, num;
    char line[255];
-   char* junk;
 
    if (low != high) { // bother only if low and high differ...
       response = low - 1; // force one loop by setting response outside range
       while ((response < low) || (response > high)) {
-         printf("%s", prompt);
-         junk = fgets(line, 255, stdin);
+         cout << prompt;
+         cin.getline(line, 255);
          num = sscanf(line, "%d", &response);
          if (num == 1) { // user provided a response
             if ((response < low) || (response > high))
-               printf("Value out of range\n");
+               cout << "Value out of range\n";
          } else { // user hit enter; return default
             response = def;
          } // if/else
       } // while
    } else { // low == high, so return this value
-      printf("Using %d\n", low);
+      cout << "Using " << low << "\n";
       response = low;
    } // else
    return (response);
@@ -62,10 +63,10 @@
 char GetYN(void) {
    char line[255];
    char response = '\0';
-   char* junk;
+   char *junk;
 
    while ((response != 'Y') && (response != 'N')) {
-      printf("(Y/N): ");
+      cout << "(Y/N): ";
       junk = fgets(line, 255, stdin);
       sscanf(line, "%c", &response);
       if (response == 'y') response = 'Y';
@@ -81,18 +82,17 @@
 // If a "-" prefix is used, use the high value minus the user-
 // specified number of sectors (or KiB, MiB, etc.). Use the def
  //value as the default if the user just hits Enter
-uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, char prompt[]) {
+uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const string & prompt) {
    unsigned long long response;
    int num, plusFlag = 0;
    uint64_t mult = 1;
    char suffix;
    char line[255];
-   char* junk;
 
    response = low - 1; // Ensure one pass by setting a too-low initial value
    while ((response < low) || (response > high)) {
-      printf("%s", prompt);
-      junk = fgets(line, 255, stdin);
+      cout << prompt;
+      cin.getline(line, 255);
 
       // Remove leading spaces, if present
       while (line[0] == ' ')
@@ -164,65 +164,65 @@
 // Takes a size in bytes (in size) and converts this to a size in
 // SI units (KiB, MiB, GiB, TiB, or PiB), returned in C++ string
 // form
-char* BytesToSI(uint64_t size, char theValue[]) {
-   char units[8];
+string BytesToSI(uint64_t size) {
+   string units;
+   char theValue[99];
    float sizeInSI;
 
-   if (theValue != NULL) {
-      sizeInSI = (float) size;
-      strcpy (units, " bytes");
-      if (sizeInSI > 1024.0) {
-         sizeInSI /= 1024.0;
-         strcpy(units, " KiB");
-      } // if
-      if (sizeInSI > 1024.0) {
-         sizeInSI /= 1024.0;
-         strcpy(units, " MiB");
-      } // if
-      if (sizeInSI > 1024.0) {
-         sizeInSI /= 1024.0;
-         strcpy(units, " GiB");
-      } // if
-      if (sizeInSI > 1024.0) {
-         sizeInSI /= 1024.0;
-         strcpy(units, " TiB");
-      } // if
-      if (sizeInSI > 1024.0) {
-         sizeInSI /= 1024.0;
-         strcpy(units, " PiB");
-      } // if
-      if (strcmp(units, " bytes") == 0) { // in bytes, so no decimal point
-         sprintf(theValue, "%1.0f%s", sizeInSI, units);
-      } else {
-         sprintf(theValue, "%1.1f%s", sizeInSI, units);
-      } // if/else
+   theValue[0] = '\0';
+   sizeInSI = (float) size;
+   units = " bytes";
+   if (sizeInSI > 1024.0) {
+      sizeInSI /= 1024.0;
+      units = " KiB";
    } // if
+   if (sizeInSI > 1024.0) {
+      sizeInSI /= 1024.0;
+      units = " MiB";
+   } // if
+   if (sizeInSI > 1024.0) {
+      sizeInSI /= 1024.0;
+      units = " GiB";
+   } // if
+   if (sizeInSI > 1024.0) {
+      sizeInSI /= 1024.0;
+      units = " TiB";
+   } // if
+   if (sizeInSI > 1024.0) {
+      sizeInSI /= 1024.0;
+      units = " PiB";
+   } // if
+   if (units == " bytes") { // in bytes, so no decimal point
+      sprintf(theValue, "%1.0f%s", sizeInSI, units.c_str());
+   } else {
+      sprintf(theValue, "%1.1f%s", sizeInSI, units.c_str());
+   } // if/else
    return theValue;
 } // BlocksToSI()
 
 // Return a plain-text name for a partition type.
 // Convert a GUID to a string representation, suitable for display
 // to humans....
-char* GUIDToStr(struct GUIDData theGUID, char* theString) {
+string GUIDToStr(struct GUIDData theGUID) {
    unsigned long long blocks[11], block;
+   char theString[40];
 
-     if (theString != NULL) {
-      blocks[0] = (theGUID.data1 & UINT64_C(0x00000000FFFFFFFF));
-      blocks[1] = (theGUID.data1 & UINT64_C(0x0000FFFF00000000)) >> 32;
-      blocks[2] = (theGUID.data1 & UINT64_C(0xFFFF000000000000)) >> 48;
-      blocks[3] = (theGUID.data2 & UINT64_C(0x00000000000000FF));
-      blocks[4] = (theGUID.data2 & UINT64_C(0x000000000000FF00)) >> 8;
-      blocks[5] = (theGUID.data2 & UINT64_C(0x0000000000FF0000)) >> 16;
-      blocks[6] = (theGUID.data2 & UINT64_C(0x00000000FF000000)) >> 24;
-      blocks[7] = (theGUID.data2 & UINT64_C(0x000000FF00000000)) >> 32;
-      blocks[8] = (theGUID.data2 & UINT64_C(0x0000FF0000000000)) >> 40;
-      blocks[9] = (theGUID.data2 & UINT64_C(0x00FF000000000000)) >> 48;
-      blocks[10] = (theGUID.data2 & UINT64_C(0xFF00000000000000)) >> 56;
-      sprintf(theString,
-              "%08llX-%04llX-%04llX-%02llX%02llX-%02llX%02llX%02llX%02llX%02llX%02llX",
-              blocks[0], blocks[1], blocks[2], blocks[3], blocks[4], blocks[5],
-              blocks[6], blocks[7], blocks[8], blocks[9], blocks[10]);
-     } // if
+   theString[0] = '\0';;
+   blocks[0] = (theGUID.data1 & UINT64_C(0x00000000FFFFFFFF));
+   blocks[1] = (theGUID.data1 & UINT64_C(0x0000FFFF00000000)) >> 32;
+   blocks[2] = (theGUID.data1 & UINT64_C(0xFFFF000000000000)) >> 48;
+   blocks[3] = (theGUID.data2 & UINT64_C(0x00000000000000FF));
+   blocks[4] = (theGUID.data2 & UINT64_C(0x000000000000FF00)) >> 8;
+   blocks[5] = (theGUID.data2 & UINT64_C(0x0000000000FF0000)) >> 16;
+   blocks[6] = (theGUID.data2 & UINT64_C(0x00000000FF000000)) >> 24;
+   blocks[7] = (theGUID.data2 & UINT64_C(0x000000FF00000000)) >> 32;
+   blocks[8] = (theGUID.data2 & UINT64_C(0x0000FF0000000000)) >> 40;
+   blocks[9] = (theGUID.data2 & UINT64_C(0x00FF000000000000)) >> 48;
+   blocks[10] = (theGUID.data2 & UINT64_C(0xFF00000000000000)) >> 56;
+   sprintf(theString,
+            "%08llX-%04llX-%04llX-%02llX%02llX-%02llX%02llX%02llX%02llX%02llX%02llX",
+            blocks[0], blocks[1], blocks[2], blocks[3], blocks[4], blocks[5],
+            blocks[6], blocks[7], blocks[8], blocks[9], blocks[10]);
    return theString;
 } // GUIDToStr()
 
@@ -234,10 +234,10 @@
    char* junk;
    GUIDData theGUID;
 
-   printf("\nA GUID is entered in five segments of from two to six bytes, with\n"
-          "dashes between segments.\n");
-   printf("Enter the entire GUID, a four-byte hexadecimal number for the first segment, or\n"
-          "'R' to generate the entire GUID randomly: ");
+   cout << "\nA GUID is entered in five segments of from two to six bytes, with\n"
+        << "dashes between segments.\n";
+   cout << "Enter the entire GUID, a four-byte hexadecimal number for the first segment, or\n"
+        << "'R' to generate the entire GUID randomly: ";
    junk = fgets(temp, 255, stdin);
 
    // If user entered 'r' or 'R', generate GUID randomly....
@@ -280,17 +280,17 @@
    // entry....
    if (entered == 0) {
       sscanf(temp, "%llx", &part1);
-      printf("Enter a two-byte hexadecimal number for the second segment: ");
+      cout << "Enter a two-byte hexadecimal number for the second segment: ";
       junk = fgets(temp, 255, stdin);
       sscanf(temp, "%llx", &part2);
-      printf("Enter a two-byte hexadecimal number for the third segment: ");
+      cout << "Enter a two-byte hexadecimal number for the third segment: ";
       junk = fgets(temp, 255, stdin);
       sscanf(temp, "%llx", &part3);
       theGUID.data1 = (part3 << 48) + (part2 << 32) + part1;
-      printf("Enter a two-byte hexadecimal number for the fourth segment: ");
+      cout << "Enter a two-byte hexadecimal number for the fourth segment: ";
       junk = fgets(temp, 255, stdin);
       sscanf(temp, "%llx", &part4);
-      printf("Enter a six-byte hexadecimal number for the fifth segment: ");
+      cout << "Enter a six-byte hexadecimal number for the fifth segment: ";
       junk = fgets(temp, 255, stdin);
       sscanf(temp, "%llx", &part5);
       theGUID.data2 = ((part4 & UINT64_C(0x000000000000FF00)) >> 8) +
@@ -303,7 +303,7 @@
                       ((part5 & UINT64_C(0x00000000000000FF)) << 56);
       entered = 1;
    } // if/else
-   printf("New GUID: %s\n", GUIDToStr(theGUID, temp));
+   cout << "New GUID: " << GUIDToStr(theGUID) << "\n";
    return theGUID;
 } // GetGUID()
 
@@ -324,17 +324,16 @@
 
 // Reverse the byte order of theValue; numBytes is number of bytes
 void ReverseBytes(void* theValue, int numBytes) {
-   char* origValue;
-   char* tempValue;
+   char* tempValue = NULL;
    int i;
 
-   origValue = (char*) theValue;
    tempValue = (char*) malloc(numBytes);
-   for (i = 0; i < numBytes; i++)
-      tempValue[i] = origValue[i];
-   for (i = 0; i < numBytes; i++)
-      origValue[i] = tempValue[numBytes - i - 1];
-   free(tempValue);
+   if (tempValue != NULL) {
+      memcpy(tempValue, theValue, numBytes);
+      for (i = 0; i < numBytes; i++)
+         ((char*) theValue)[i] = tempValue[numBytes - i - 1];
+      free(tempValue);
+   } // if
 } // ReverseBytes()
 
 // Compute (2 ^ value). Given the return type, value must be 63 or less.
diff --git a/support.h b/support.h
index 3a102ae..79e62a9 100644
--- a/support.h
+++ b/support.h
@@ -4,7 +4,7 @@
 #include <stdint.h>
 #include <unistd.h>
 #include <stdlib.h>
-#include <string.h>
+#include <string>
 
 #ifndef __GPTSUPPORT
 #define __GPTSUPPORT
@@ -35,6 +35,9 @@
 #define APM_SIGNATURE1 UINT64_C(0x00004D5000000000)
 #define APM_SIGNATURE2 UINT64_C(0x0000535400000000)
 
+// Maximum line length ignored on some input functions
+#define MAX_IGNORED 999
+
 /**************************
  * Some GPT constants.... *
  **************************/
@@ -58,11 +61,11 @@
 
 static char theFile[255];
 
-int GetNumber(int low, int high, int def, const char prompt[]);
+int GetNumber(int low, int high, int def, const string & prompt);
 char GetYN(void);
-uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, char prompt[]);
-char* BytesToSI(uint64_t size, char theValue[]);
-char* GUIDToStr(struct GUIDData theGUID, char* theString);
+uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const string & prompt);
+string BytesToSI(uint64_t size);
+string GUIDToStr(struct GUIDData theGUID);
 GUIDData GetGUID(void);
 int IsLittleEndian(void); // Returns 1 if CPU is little-endian, 0 if it's big-endian
 void ReverseBytes(void* theValue, int numBytes); // Reverses byte-order of theValue