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