A few minor bug fixes; backup function now accepts dd output of MBR,
main header, and main partition table, as well as gdisk-generated
backups.
diff --git a/gpt.cc b/gpt.cc
index 562a085..a2e216f 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -82,7 +82,7 @@
// Destructor
GPTData::~GPTData(void) {
- free(partitions);
+ delete[] partitions;
} // GPTData destructor
/*********************************************************************
@@ -342,8 +342,8 @@
} // GPTData::CheckHeaderValidity()
// Check the header CRC to see if it's OK...
-// Note: Must be called BEFORE byte-order reversal on big-endian
-// systems!
+// Note: Must be called with header in LITTLE-ENDIAN
+// (x86, x86-64, etc.) byte order.
int GPTData::CheckHeaderCRC(struct GPTHeader* header) {
uint32_t oldCRC, newCRC, hSize;
@@ -648,53 +648,22 @@
// Loads the GPT, as much as possible. Returns 1 if this seems to have
// succeeded, 0 if there are obvious problems....
int GPTData::ForceLoadGPTData(void) {
- int allOK = 1, validHeaders;
- uint64_t seekTo;
- uint8_t* storage;
- uint32_t newCRC, sizeOfParts;
+ int allOK, validHeaders, loadedTable = 1;
- // Seek to and read the main GPT header
- if (myDisk.Seek(1)) {
- if (myDisk.Read(&mainHeader, 512) != 512) { // read main GPT header
- cerr << "Warning! Error " << errno << " reading main GPT header!\n";
- } // if read not OK
- } else allOK = 0; // if/else seek OK
- mainCrcOk = CheckHeaderCRC(&mainHeader);
- if (IsLittleEndian() == 0) // big-endian system; adjust header byte order....
- ReverseHeaderBytes(&mainHeader);
+ allOK = LoadHeader(&mainHeader, myDisk, 1, &mainCrcOk);
- // Load backup header, check its CRC, and store the results of the
- // check for future reference. Load backup header using pointer in main
- // header if possible; but if main header has a CRC error, or if it
- // points to beyond the end of the disk, load the last sector of the
- // disk instead.
- if (mainCrcOk) {
- if (mainHeader.backupLBA < diskSize) {
- seekTo = mainHeader.backupLBA;
- } else {
- seekTo = diskSize - UINT64_C(1);
+ if (mainCrcOk && (mainHeader.backupLBA < diskSize)) {
+ allOK = LoadHeader(&secondHeader, myDisk, mainHeader.backupLBA, &secondCrcOk) && allOK;
+ } else {
+ if (mainHeader.backupLBA >= diskSize)
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);
- } // if/else (mainCrcOk)
-
- if (myDisk.Seek(seekTo)) {
- if (myDisk.Read(&secondHeader, 512) != 512) { // read secondary GPT header
- cerr << "Warning! Error " << errno << " reading secondary GPT header!\n";
- } // if
- secondCrcOk = CheckHeaderCRC(&secondHeader);
- if (IsLittleEndian() == 0) // big-endian system; adjust header byte order....
- ReverseHeaderBytes(&secondHeader);
- } else {
- allOK = 0;
+ allOK = LoadHeader(&secondHeader, myDisk, diskSize - UINT64_C(1), &secondCrcOk) && allOK;
+ } // if/else
+ if (!allOK)
state = gpt_invalid;
- 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
// good, backup bad; 2 = backup header good, main header bad;
@@ -734,37 +703,32 @@
} else { // bad main header CRC and backup header CRC is OK
state = gpt_corrupt;
if (LoadSecondTableAsMain()) {
+ loadedTable = 2;
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;
+ loadedTable = 0;
cerr << "\a\aWarning! Unable to load either main or backup partition table!\n";
} // if
} // if/else (LoadSecondTableAsMain())
} // if/else (load partition table)
- // Load backup partition table into temporary storage to check
- // its CRC and store the results, then discard this temporary
- // storage, since we don't use it in any but recovery operations
- seekTo = secondHeader.partitionEntriesLBA;
- if ((myDisk.Seek(seekTo)) && (secondCrcOk)) {
- sizeOfParts = secondHeader.numParts * secondHeader.sizeOfPartitionEntries;
- storage = (uint8_t*) malloc(sizeOfParts);
- if (myDisk.Read(storage, sizeOfParts) != (int) sizeOfParts) {
- cerr << "Warning! Error " << errno << " reading backup partition table!\n";
- } // if
- newCRC = chksum_crc32((unsigned char*) storage, sizeOfParts);
- free(storage);
- secondPartsCrcOk = (newCRC == secondHeader.partitionEntriesCRC);
- } // if
+ if (loadedTable == 1)
+ secondPartsCrcOk = CheckTable(&secondHeader);
+ else if (loadedTable == 2)
+ mainPartsCrcOk = CheckTable(&mainHeader);
+ else
+ mainPartsCrcOk = secondPartsCrcOk = 0;
// Problem with main partition table; if backup is OK, use it instead....
if (secondPartsCrcOk && secondCrcOk && !mainPartsCrcOk) {
state = gpt_corrupt;
allOK = allOK && LoadSecondTableAsMain();
+ mainPartsCrcOk = 0; // LoadSecondTableAsMain() resets this, so re-flag as bad
cerr << "\aWarning! Main partition table CRC mismatch! Loaded backup "
<< "partition table\ninstead of main partition table!\n\n";
- } // if
+ } // if */
// Check for valid CRCs and warn if there are problems
if ((mainCrcOk == 0) || (secondCrcOk == 0) || (mainPartsCrcOk == 0) ||
@@ -783,28 +747,7 @@
// sensible!
// Returns 1 on success, 0 on failure. CRC errors do NOT count as failure.
int GPTData::LoadMainTable(void) {
- int retval = 1;
- uint32_t newCRC, sizeOfParts;
-
- if (myDisk.OpenForRead(device)) {
- // Set internal data structures for number of partitions on the disk
- SetGPTSize(mainHeader.numParts);
-
- // Load main partition table, and record whether its CRC
- // matches the stored value
- if (!myDisk.Seek(mainHeader.partitionEntriesLBA))
- retval = 0;
- sizeOfParts = mainHeader.numParts * mainHeader.sizeOfPartitionEntries;
- if (myDisk.Read(partitions, sizeOfParts) != (int) sizeOfParts) {
- cerr << "Warning! Error " << errno << " when loading the main partition table!\n";
- retval = 0;
- } // if
- newCRC = chksum_crc32((unsigned char*) partitions, sizeOfParts);
- mainPartsCrcOk = (newCRC == mainHeader.partitionEntriesCRC);
- if (IsLittleEndian() == 0)
- ReversePartitionBytes();
- } else retval = 0; // if open for read....
- return retval;
+ return LoadPartitionTable(mainHeader, myDisk);
} // GPTData::LoadMainTable()
// Load the second (backup) partition table as the primary partition
@@ -812,47 +755,103 @@
// partition table is damaged.
// Returns 1 on success, 0 on failure. CRC errors do NOT count as failure.
int GPTData::LoadSecondTableAsMain(void) {
- uint64_t seekTo;
- uint32_t sizeOfParts, newCRC;
- int retval = 1;
+ return LoadPartitionTable(secondHeader, myDisk);
+} // GPTData::LoadSecondTableAsMain()
- if (myDisk.OpenForRead(device)) {
- seekTo = secondHeader.partitionEntriesLBA;
- retval = myDisk.Seek(seekTo);
+// Load a single GPT header (main or backup) from the specified disk device and
+// sector. Applies byte-order corrections on big-endian platforms. Sets crcOk
+// value appropriately.
+// Returns 1 on success, 0 on failure. Note that CRC errors do NOT qualify as
+// failure.
+int GPTData::LoadHeader(struct GPTHeader *header, DiskIO & disk, uint64_t sector, int *crcOk) {
+ int allOK = 1;
+
+ disk.Seek(sector);
+ if (disk.Read(header, 512) != 512) {
+ cerr << "Warning! Read error " << errno << "; strange behavior now likely!\n";
+ allOK = 0;
+ } // if
+ *crcOk = CheckHeaderCRC(header);
+
+ // Reverse byte order, if necessary
+ if (IsLittleEndian() == 0) {
+ ReverseHeaderBytes(header);
+ } // if
+ return allOK;
+} // GPTData::LoadHeader
+
+// Load a partition table (either main or secondary) from the specified disk,
+// using header as a reference for what to load. If sector != 0 (the default
+// is 0), loads from the specified sector; otherwise loads from the sector
+// indicated in header.
+// Returns 1 on success, 0 on failure. CRC errors do NOT count as failure.
+int GPTData::LoadPartitionTable(const struct GPTHeader & header, DiskIO & disk, uint64_t sector) {
+ uint32_t sizeOfParts, newCRC;
+ int retval;
+
+ if (disk.OpenForRead()) {
+ if (sector == 0) {
+ retval = disk.Seek(header.partitionEntriesLBA);
+ } else {
+ retval = disk.Seek(sector);
+ } // if/else
if (retval == 1) {
- SetGPTSize(secondHeader.numParts);
- sizeOfParts = secondHeader.numParts * secondHeader.sizeOfPartitionEntries;
- if (myDisk.Read(partitions, sizeOfParts) != (int) sizeOfParts) {
+ SetGPTSize(header.numParts);
+ sizeOfParts = header.numParts * header.sizeOfPartitionEntries;
+ if (disk.Read(partitions, sizeOfParts) != (int) sizeOfParts) {
cerr << "Warning! Read error " << errno << "! Misbehavior now likely!\n";
retval = 0;
} // if
newCRC = chksum_crc32((unsigned char*) partitions, sizeOfParts);
- secondPartsCrcOk = (newCRC == secondHeader.partitionEntriesCRC);
- mainPartsCrcOk = secondPartsCrcOk;
+ mainPartsCrcOk = secondPartsCrcOk = (newCRC == header.partitionEntriesCRC);
if (IsLittleEndian() == 0)
ReversePartitionBytes();
- if (!secondPartsCrcOk) {
- cout << "Caution! After loading backup partitions, the CRC still doesn't check out!\n";
+ if (!mainPartsCrcOk) {
+ cout << "Caution! After loading partitions, the CRC doesn't check out!\n";
} // if
} else {
- cerr << "Error! Couldn't seek to backup partition table!\n";
+ cerr << "Error! Couldn't seek to partition table!\n";
} // if/else
} else {
cerr << "Error! Couldn't open device " << device
- << " when recovering backup partition table!\n";
+ << " when reading partition table!\n";
retval = 0;
} // if/else
return retval;
-} // GPTData::LoadSecondTableAsMain()
+} // GPTData::LoadPartitionsTable()
+
+// Check the partition table pointed to by header, but don't keep it
+// around.
+// Returns 1 if the CRC is OK, 0 if not or if there was a read error.
+int GPTData::CheckTable(struct GPTHeader *header) {
+ uint32_t sizeOfParts, newCRC;
+ uint8_t *storage;
+ int newCrcOk = 0;
+
+ // Load backup partition table into temporary storage to check
+ // its CRC and store the results, then discard this temporary
+ // storage, since we don't use it in any but recovery operations
+ if (myDisk.Seek(header->partitionEntriesLBA)) {
+ sizeOfParts = secondHeader.numParts * secondHeader.sizeOfPartitionEntries;
+ storage = new uint8_t[sizeOfParts];
+ if (myDisk.Read(storage, sizeOfParts) != (int) sizeOfParts) {
+ cerr << "Warning! Error " << errno << " reading backup partition table!\n";
+ } else {
+ newCRC = chksum_crc32((unsigned char*) storage, sizeOfParts);
+ newCrcOk = (newCRC == header->partitionEntriesCRC);
+ } // if/else
+ delete[] storage;
+ } // if
+ return newCrcOk;
+} // GPTData::CheckTable()
// Writes GPT (and protective MBR) to disk. Returns 1 on successful
// write, 0 if there was a problem.
int GPTData::SaveGPTData(int quiet) {
int allOK = 1, littleEndian;
char answer;
- uint64_t secondTable;
+// uint64_t secondTable;
uint32_t numParts;
- uint64_t offset;
littleEndian = IsLittleEndian();
@@ -907,18 +906,8 @@
// Pull out some data that's needed before doing byte-order reversal on
// big-endian systems....
numParts = mainHeader.numParts;
- secondTable = secondHeader.partitionEntriesLBA;
-/* if (IsLittleEndian() == 0) {
- // Reverse partition bytes first, since that function requires non-reversed
- // data from the main header....
- ReversePartitionBytes();
- ReverseHeaderBytes(&mainHeader);
- ReverseHeaderBytes(&secondHeader);
- } // if */
+
RecomputeCRCs();
-/* ReverseHeaderBytes(&mainHeader);
- ReverseHeaderBytes(&secondHeader);
- ReversePartitionBytes(); */
if ((allOK) && (!quiet)) {
cout << "\nFinal checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING\n"
@@ -938,59 +927,22 @@
if (allOK && myDisk.OpenForWrite(device)) {
// Now write the main GPT header...
- if (myDisk.Seek(1) == 1) {
- if (!littleEndian)
- ReverseHeaderBytes(&mainHeader);
- if (myDisk.Write(&mainHeader, 512) != 512)
- allOK = 0;
- if (!littleEndian)
- ReverseHeaderBytes(&mainHeader);
- } else allOK = 0; // if (myDisk.Seek()...)
+ allOK = SaveHeader(&mainHeader, myDisk, 1);
// Now write the main partition tables...
if (allOK) {
- offset = mainHeader.partitionEntriesLBA;
- if (myDisk.Seek(offset)) {
- if (!littleEndian)
- ReversePartitionBytes();
- if (myDisk.Write(partitions, GPT_SIZE * numParts) == -1)
- allOK = 0;
- if (!littleEndian)
- ReversePartitionBytes();
- } else allOK = 0; // if (myDisk.Seek()...)
+ allOK = SavePartitionTable(myDisk, mainHeader.partitionEntriesLBA);
} // if (allOK)
// Now seek to near the end to write the secondary GPT....
- if (allOK) {
- offset = (uint64_t) secondTable;
- if (myDisk.Seek(offset) != 1) {
- allOK = 0;
- cerr << "Unable to seek to end of disk! Perhaps the 'e' option on the experts' menu\n"
- << "will resolve this problem.\n";
- } // if
- } // if
-
- // Now write the secondary partition tables....
- if (allOK) {
- if (!littleEndian)
- ReversePartitionBytes();
- if (myDisk.Write(partitions, GPT_SIZE * numParts) == -1)
- allOK = 0;
- if (!littleEndian)
- ReversePartitionBytes();
- } // if (allOK)
+ allOK = SavePartitionTable(myDisk, secondHeader.partitionEntriesLBA);
+ if (!allOK)
+ cerr << "Unable to save backup partition table! Perhaps the 'e' option on the experts'\n"
+ << "menu will resolve this problem.\n";
// Now write the secondary GPT header...
if (allOK) {
- offset = mainHeader.backupLBA;
- if (!littleEndian)
- ReverseHeaderBytes(&secondHeader);
- if (myDisk.Seek(offset)) {
- if (myDisk.Write(&secondHeader, 512) == -1)
- allOK = 0;
- } else allOK = 0; // if (myDisk.Seek()...)
- if (!littleEndian)
- ReverseHeaderBytes(&secondHeader);
+ allOK = SaveHeader(&secondHeader, myDisk, mainHeader.backupLBA);
} // if (allOK)
// re-read the partition table
@@ -1015,14 +967,6 @@
cout << "Aborting write of new partition table.\n";
} // if
-/* if (IsLittleEndian() == 0) {
- // Reverse (normalize) header bytes first, since ReversePartitionBytes()
- // requires non-reversed data in mainHeader...
- ReverseHeaderBytes(&mainHeader);
- ReverseHeaderBytes(&secondHeader);
- ReversePartitionBytes();
- } // if */
-
return (allOK);
} // GPTData::SaveGPTData()
@@ -1034,7 +978,6 @@
// identical to the main partition table on healthy disks.
int GPTData::SaveGPTBackup(const string & filename) {
int allOK = 1;
- uint32_t numParts;
DiskIO backupFile;
if (backupFile.OpenForWrite(filename)) {
@@ -1044,35 +987,19 @@
// backup. I'm favoring misses over false alarms....
RecomputeCRCs();
- // Reverse the byte order, if necessary....
- numParts = mainHeader.numParts;
- if (IsLittleEndian() == 0) {
- ReversePartitionBytes();
- ReverseHeaderBytes(&mainHeader);
- ReverseHeaderBytes(&secondHeader);
- } // if
-
- // Now write the protective MBR...
protectiveMBR.WriteMBRData(&backupFile);
- // Now write the main GPT header...
- if (allOK)
+ if (allOK) {
// MBR write closed disk, so re-open and seek to end....
backupFile.OpenForWrite();
- backupFile.Seek(1);
- if (backupFile.Write(&mainHeader, 512) == -1)
- allOK = 0;
+ allOK = SaveHeader(&mainHeader, backupFile, 1);
+ } // if (allOK)
- // Now write the secondary GPT header...
if (allOK)
- if (backupFile.Write(&secondHeader, 512) == -1)
- allOK = 0;
+ allOK = SaveHeader(&secondHeader, backupFile, 2);
- // Now write the main partition tables...
- if (allOK) {
- if (backupFile.Write(partitions, GPT_SIZE * numParts) == -1)
- allOK = 0;
- } // if
+ if (allOK)
+ allOK = SavePartitionTable(backupFile, 3);
if (allOK) { // writes completed OK
cout << "The operation has completed successfully.\n";
@@ -1081,13 +1008,6 @@
<< "It may not be usable!\n";
} // if/else
backupFile.Close();
-
- // Now reverse the byte-order reversal, if necessary....
- if (IsLittleEndian() == 0) {
- ReverseHeaderBytes(&mainHeader);
- ReverseHeaderBytes(&secondHeader);
- ReversePartitionBytes();
- } // if
} else {
cerr << "Unable to open file " << filename << " for writing! Aborting!\n";
allOK = 0;
@@ -1095,14 +1015,54 @@
return allOK;
} // GPTData::SaveGPTBackup()
+// Write a GPT header (main or backup) to the specified sector. Used by both
+// the SaveGPTData() and SaveGPTBackup() functions.
+// Should be passed an architecture-appropriate header (DO NOT call
+// ReverseHeaderBytes() on the header before calling this function)
+// Returns 1 on success, 0 on failure
+int GPTData::SaveHeader(struct GPTHeader *header, DiskIO & disk, uint64_t sector) {
+ int littleEndian, allOK = 1;
+
+ littleEndian = IsLittleEndian();
+ if (!littleEndian)
+ ReverseHeaderBytes(header);
+ if (disk.Seek(sector)) {
+ if (disk.Write(header, 512) == -1)
+ allOK = 0;
+ } else allOK = 0; // if (disk.Seek()...)
+ if (!littleEndian)
+ ReverseHeaderBytes(header);
+ return allOK;
+} // GPTData::SaveHeader()
+
+// Save the partitions to the specified sector. Used by both the SaveGPTData()
+// and SaveGPTBackup() functions.
+// Should be passed an architecture-appropriate header (DO NOT call
+// ReverseHeaderBytes() on the header before calling this function)
+// Returns 1 on success, 0 on failure
+int GPTData::SavePartitionTable(DiskIO & disk, uint64_t sector) {
+ int littleEndian, allOK = 1;
+
+ littleEndian = IsLittleEndian();
+ if (disk.Seek(sector)) {
+ if (!littleEndian)
+ ReversePartitionBytes();
+ if (disk.Write(partitions, mainHeader.sizeOfPartitionEntries * mainHeader.numParts) == -1)
+ allOK = 0;
+ if (!littleEndian)
+ ReversePartitionBytes();
+ } else allOK = 0; // if (myDisk.Seek()...)
+ return allOK;
+} // GPTData::SavePartitionTable()
+
// Load GPT data from a backup file created by SaveGPTBackup(). This function
// 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(const string & filename) {
- int allOK = 1, val;
- uint32_t numParts, sizeOfEntries, sizeOfParts, newCRC;
- int littleEndian = 1;
+ int allOK = 1, val, err;
+ uint32_t numParts, sizeOfEntries;
+ int littleEndian = 1, shortBackup = 0;
DiskIO backupFile;
if (backupFile.OpenForRead(filename)) {
@@ -1112,29 +1072,20 @@
// Let the MBRData class load the saved MBR...
protectiveMBR.ReadMBRData(&backupFile, 0); // 0 = don't check block size
- // Load the main GPT header, check its vaility, and set the GPT
- // size based on the data
- if (backupFile.Read(&mainHeader, 512) != 512) {
- cerr << "Warning! Read error " << errno << "; strange behavior now likely!\n";
- } // if
- mainCrcOk = CheckHeaderCRC(&mainHeader);
+ LoadHeader(&mainHeader, backupFile, 1, &mainCrcOk);
- // Reverse byte order, if necessary
- if (littleEndian == 0) {
- ReverseHeaderBytes(&mainHeader);
- } // if
-
- // Load the backup GPT header in much the same way as the main
- // GPT header....
- if (backupFile.Read(&secondHeader, 512) != 512) {
- cerr << "Warning! Read error " << errno << "; strange behavior now likely!\n";
- } // if
- secondCrcOk = CheckHeaderCRC(&secondHeader);
-
- // Reverse byte order, if necessary
- if (littleEndian == 0) {
- ReverseHeaderBytes(&secondHeader);
- } // if
+ // Check backup file size and rebuild second header if file is right
+ // size to be direct dd copy of MBR, main header, and main partition
+ // table; if other size, treat it like a GPT fdisk-generated backup
+ // file
+ shortBackup = ((backupFile.DiskSize(&err) * backupFile.GetBlockSize()) ==
+ (mainHeader.numParts * mainHeader.sizeOfPartitionEntries) + 1024);
+ if (shortBackup) {
+ RebuildSecondHeader();
+ secondCrcOk = mainCrcOk;
+ } else {
+ LoadHeader(&secondHeader, backupFile, 2, &secondCrcOk);
+ } // if/else
// Return valid headers code: 0 = both headers bad; 1 = main header
// good, backup bad; 2 = backup header good, main header bad;
@@ -1152,27 +1103,15 @@
SetGPTSize(numParts);
- // If current disk size doesn't match that of backup....
if (secondHeader.currentLBA != diskSize - UINT64_C(1)) {
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
- // Load main partition table, and record whether its CRC
- // matches the stored value
- sizeOfParts = numParts * sizeOfEntries;
- if (backupFile.Read(partitions, sizeOfParts) != (int) sizeOfParts) {
- cerr << "Warning! Read error " << errno << "; strange behavior now likely!\n";
- } // if
-
- newCRC = chksum_crc32((unsigned char*) partitions, sizeOfParts);
- mainPartsCrcOk = (newCRC == mainHeader.partitionEntriesCRC);
- secondPartsCrcOk = (newCRC == secondHeader.partitionEntriesCRC);
- // Reverse byte order, if necessary
- if (littleEndian == 0) {
- ReversePartitionBytes();
- } // if
+ if (!LoadPartitionTable(mainHeader, backupFile, (uint64_t) (3 - shortBackup)))
+ cerr << "Warning! Read error " << errno
+ << " loading partition table; strange behavior now likely!\n";
} else {
allOK = 0;
@@ -1318,7 +1257,7 @@
if (((firstBlock = FindFirstAvailable()) != 0) &&
(firstFreePart < mainHeader.numParts)) {
- lastBlock = FindLastAvailable(firstBlock);
+ lastBlock = FindLastAvailable();
firstInLargest = FindFirstInLargest();
// Get partition number....
@@ -1430,7 +1369,7 @@
} // if
myDisk.Seek(mainHeader.partitionEntriesLBA); // seek to partition table
tableSize = mainHeader.numParts * mainHeader.sizeOfPartitionEntries;
- emptyTable = (uint8_t*) malloc(tableSize);
+ emptyTable = new uint8_t[tableSize];
for (i = 0; i < tableSize; i++)
emptyTable[i] = 0;
sum = myDisk.Write(emptyTable, tableSize);
@@ -1466,6 +1405,7 @@
myDisk.Close();
cout << "GPT data structures destroyed! You may now partition the disk using fdisk or\n"
<< "other utilities. Program will now terminate.\n";
+ delete[] emptyTable;
} else {
cerr << "Problem opening " << device << " for writing! Program will now terminate.\n";
} // if/else (fd != -1)
@@ -1894,7 +1834,7 @@
// data.
if ((numEntries != mainHeader.numParts) || (numEntries != secondHeader.numParts)
|| (partitions == NULL)) {
- newParts = (GPTPart*) calloc(numEntries, sizeof (GPTPart));
+ newParts = new GPTPart [numEntries * sizeof (GPTPart)];
if (newParts != NULL) {
if (partitions != NULL) { // existing partitions; copy them over
GetPartRange(&i, &high);
@@ -1914,7 +1854,7 @@
} // for
trash = partitions;
partitions = newParts;
- free(trash);
+ delete[] trash;
} // if
} else { // No existing partition table; just create it
partitions = newParts;
@@ -2033,7 +1973,7 @@
// Set up the partition table....
if (partitions != NULL)
- free(partitions);
+ delete[] partitions;
partitions = NULL;
SetGPTSize(NUM_GPT_ENTRIES);
@@ -2297,10 +2237,9 @@
return selectedSegment;
} // GPTData::FindFirstInLargest()
-// Find the last available block on the disk at or after the start
-// block. Returns 0 if there are no available partitions after
-// (or including) start.
-uint64_t GPTData::FindLastAvailable(uint64_t start) {
+// Find the last available block on the disk.
+// Returns 0 if there are no available partitions
+uint64_t GPTData::FindLastAvailable(void) {
uint64_t last;
uint32_t i;
int lastMoved = 0;