Second patchset from Florian & a few other small changes

This commit is contained in:
srs5694
2011-03-15 23:53:31 -04:00
parent 9a46b042c5
commit 01f7f08624
7 changed files with 109 additions and 175 deletions

View File

@@ -455,7 +455,7 @@ void BasicMBRData::DisplayMBRData(void) {
int i;
cout << "\nDisk size is " << diskSize << " sectors ("
<< BytesToSI(diskSize, blockSize) << ")\n";
<< BytesToIeee(diskSize, blockSize) << ")\n";
cout << "MBR disk identifier: 0x";
cout.width(8);
cout.fill('0');

63
gpt.cc
View File

@@ -121,7 +121,7 @@ GPTData & GPTData::operator=(const GPTData & orig) {
myDisk.OpenForRead(orig.myDisk.GetName());
delete[] partitions;
partitions = new GPTPart [numParts * sizeof (GPTPart)];
partitions = new GPTPart [numParts];
if (partitions != NULL) {
for (i = 0; i < numParts; i++) {
partitions[i] = orig.partitions[i];
@@ -290,9 +290,9 @@ int GPTData::Verify(void) {
if (problems == 0) {
totalFree = FindFreeBlocks(&numSegments, &largestSegment);
cout << "\nNo problems found. " << totalFree << " free sectors ("
<< BytesToSI(totalFree, blockSize) << ") available in "
<< BytesToIeee(totalFree, blockSize) << ") available in "
<< numSegments << "\nsegments, the largest of which is "
<< largestSegment << " (" << BytesToSI(largestSegment, blockSize)
<< largestSegment << " (" << BytesToIeee(largestSegment, blockSize)
<< ") in size.\n";
} else {
cout << "\nIdentified " << problems << " problems!\n";
@@ -474,8 +474,6 @@ void GPTData::RecomputeCRCs(void) {
// Rebuild the main GPT header, using the secondary header as a model.
// Typically called when the main header has been found to be corrupt.
void GPTData::RebuildMainHeader(void) {
int i;
mainHeader.signature = GPT_SIGNATURE;
mainHeader.revision = secondHeader.revision;
mainHeader.headerSize = secondHeader.headerSize;
@@ -490,16 +488,13 @@ void GPTData::RebuildMainHeader(void) {
mainHeader.numParts = secondHeader.numParts;
mainHeader.sizeOfPartitionEntries = secondHeader.sizeOfPartitionEntries;
mainHeader.partitionEntriesCRC = secondHeader.partitionEntriesCRC;
for (i = 0 ; i < GPT_RESERVED; i++)
mainHeader.reserved2[i] = secondHeader.reserved2[i];
memcpy(mainHeader.reserved2, secondHeader.reserved2, sizeof(mainHeader.reserved2));
mainCrcOk = secondCrcOk;
SetGPTSize(mainHeader.numParts);
} // GPTData::RebuildMainHeader()
// Rebuild the secondary GPT header, using the main header as a model.
void GPTData::RebuildSecondHeader(void) {
int i;
secondHeader.signature = GPT_SIGNATURE;
secondHeader.revision = mainHeader.revision;
secondHeader.headerSize = mainHeader.headerSize;
@@ -514,8 +509,7 @@ void GPTData::RebuildSecondHeader(void) {
secondHeader.numParts = mainHeader.numParts;
secondHeader.sizeOfPartitionEntries = mainHeader.sizeOfPartitionEntries;
secondHeader.partitionEntriesCRC = mainHeader.partitionEntriesCRC;
for (i = 0 ; i < GPT_RESERVED; i++)
secondHeader.reserved2[i] = mainHeader.reserved2[i];
memcpy(secondHeader.reserved2, mainHeader.reserved2, sizeof(secondHeader.reserved2));
secondCrcOk = mainCrcOk;
SetGPTSize(secondHeader.numParts);
} // GPTData::RebuildSecondHeader()
@@ -1210,13 +1204,11 @@ int GPTData::SaveMBR(void) {
// MBR.
// Returns 1 if the operation succeeds, 0 if not.
int GPTData::DestroyGPT(void) {
int i, sum, tableSize, allOK = 1;
int sum, tableSize, allOK = 1;
uint8_t blankSector[512];
uint8_t* emptyTable;
for (i = 0; i < 512; i++) {
blankSector[i] = 0;
} // for
memset(blankSector, 0, sizeof(blankSector));
if (myDisk.OpenForWrite()) {
if (!myDisk.Seek(mainHeader.currentLBA))
@@ -1229,8 +1221,7 @@ int GPTData::DestroyGPT(void) {
allOK = 0;
tableSize = numParts * mainHeader.sizeOfPartitionEntries;
emptyTable = new uint8_t[tableSize];
for (i = 0; i < tableSize; i++)
emptyTable[i] = 0;
memset(emptyTable, 0, tableSize);
if (allOK) {
sum = myDisk.Write(emptyTable, tableSize);
if (sum != tableSize) {
@@ -1270,18 +1261,13 @@ int GPTData::DestroyGPT(void) {
// Wipe MBR data from the disk (zero it out completely)
// Returns 1 on success, 0 on failure.
int GPTData::DestroyMBR(void) {
int allOK = 1, i;
int allOK;
uint8_t blankSector[512];
for (i = 0; i < 512; i++)
blankSector[i] = 0;
memset(blankSector, 0, sizeof(blankSector));
allOK = myDisk.OpenForWrite() && myDisk.Seek(0) && (myDisk.Write(blankSector, 512) == 512);
if (myDisk.OpenForWrite()) {
if (myDisk.Seek(0)) {
if (myDisk.Write(blankSector, 512) != 512)
allOK = 0;
} else allOK = 0;
} else allOK = 0;
if (!allOK)
cerr << "Warning! MBR not overwritten! Error is " << errno << "!\n";
return allOK;
@@ -1319,7 +1305,7 @@ void GPTData::DisplayGPTData(void) {
uint64_t temp, totalFree;
cout << "Disk " << device << ": " << diskSize << " sectors, "
<< BytesToSI(diskSize, blockSize) << "\n";
<< BytesToIeee(diskSize, blockSize) << "\n";
cout << "Logical sector size: " << blockSize << " bytes\n";
cout << "Disk identifier (GUID): " << mainHeader.diskGUID << "\n";
cout << "Partition table holds up to " << numParts << " entries\n";
@@ -1328,7 +1314,7 @@ void GPTData::DisplayGPTData(void) {
totalFree = FindFreeBlocks(&i, &temp);
cout << "Partitions will be aligned on " << sectorAlignment << "-sector boundaries\n";
cout << "Total free space is " << totalFree << " sectors ("
<< BytesToSI(totalFree, blockSize) << ")\n";
<< BytesToIeee(totalFree, blockSize) << ")\n";
cout << "\nNumber Start (sector) End (sector) Size Code Name\n";
for (i = 0; i < numParts; i++) {
partitions[i].ShowSummary(i, blockSize);
@@ -1566,7 +1552,6 @@ int GPTData::OnePartToMBR(uint32_t gptPart, int mbrPart) {
// well, 0 if an error is encountered.
int GPTData::SetGPTSize(uint32_t numEntries) {
GPTPart* newParts;
GPTPart* trash;
uint32_t i, high, copyNum;
int allOK = 1;
@@ -1585,7 +1570,7 @@ int GPTData::SetGPTSize(uint32_t numEntries) {
// array that's been expanded because this function is called when loading
// data.
if (((numEntries != numParts) || (partitions == NULL)) && (numEntries > 0)) {
newParts = new GPTPart [numEntries * sizeof (GPTPart)];
newParts = new GPTPart [numEntries];
if (newParts != NULL) {
if (partitions != NULL) { // existing partitions; copy them over
GetPartRange(&i, &high);
@@ -1603,9 +1588,8 @@ int GPTData::SetGPTSize(uint32_t numEntries) {
for (i = 0; i < copyNum; i++) {
newParts[i] = partitions[i];
} // for
trash = partitions;
delete[] partitions;
partitions = newParts;
delete[] trash;
} // if
} else { // No existing partition table; just create it
partitions = newParts;
@@ -1687,7 +1671,7 @@ uint32_t GPTData::CreatePartition(uint32_t partNum, uint64_t startSector, uint64
// ordering.
void GPTData::SortGPT(void) {
if (numParts > 0)
sort(partitions, partitions + numParts - 1);
sort(partitions, partitions + numParts);
} // GPTData::SortGPT()
// Swap the contents of two partitions.
@@ -2119,15 +2103,8 @@ int GPTData::IsFree(uint64_t sector, uint32_t *partNum) {
// Returns 1 if partNum is unused.
int GPTData::IsFreePartNum(uint32_t partNum) {
int retval = 1;
if ((partNum < numParts) && (partitions != NULL)) {
if (partitions[partNum].IsUsed()) {
retval = 0;
} // if partition is in use
} else retval = 0;
return retval;
return ((partNum < numParts) && (partitions != NULL) &&
(!partitions[partNum].IsUsed()));
} // GPTData::IsFreePartNum()
@@ -2233,7 +2210,7 @@ const GPTPart & GPTData::operator[](uint32_t partNum) const {
cerr << "Partition number out of range: " << partNum << "\n";
partNum = 0;
if ((numParts == 0) || (partitions == NULL)) {
cerr << "No partitions defined; fatal error!\n";
cerr << "No partitions defined in GPTData::operator[]; fatal error!\n";
exit(1);
} // if
} // if

1
gpt.h
View File

@@ -148,7 +148,6 @@ public:
int DeletePartition(uint32_t partNum);
uint32_t CreatePartition(uint32_t partNum, uint64_t startSector, uint64_t endSector);
void SortGPT(void);
void QuickSortGPT(int start, int finish);
int SwapPartitions(uint32_t partNum1, uint32_t partNum2);
int ClearGPTData(void);
void MoveSecondHeaderToEnd();

View File

@@ -146,11 +146,11 @@ bool GPTPart::operator<(const GPTPart &other) const {
// Display summary information; does nothing if the partition is empty.
void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
string sizeInSI;
string sizeInIeee;
size_t i;
if (firstLBA != 0) {
sizeInSI = BytesToSI(lastLBA - firstLBA + 1, blockSize);
sizeInIeee = BytesToIeee(lastLBA - firstLBA + 1, blockSize);
cout.fill(' ');
cout.width(4);
cout << partNum + 1 << " ";
@@ -158,8 +158,9 @@ void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
cout << firstLBA << " ";
cout.width(14);
cout << lastLBA << " ";
cout << BytesToSI(lastLBA - firstLBA + 1, blockSize) << " ";
for (i = 0; i < 10 - sizeInSI.length(); i++)
cout << BytesToIeee(lastLBA - firstLBA + 1, blockSize) << " ";
if (sizeInIeee.length() < 10)
for (i = 0; i < 10 - sizeInIeee.length(); i++)
cout << " ";
cout.fill('0');
cout.width(4);
@@ -182,12 +183,12 @@ void GPTPart::ShowDetails(uint32_t blockSize) {
cout << "Partition unique GUID: " << uniqueGUID << "\n";
cout << "First sector: " << firstLBA << " (at "
<< BytesToSI(firstLBA, blockSize) << ")\n";
<< BytesToIeee(firstLBA, blockSize) << ")\n";
cout << "Last sector: " << lastLBA << " (at "
<< BytesToSI(lastLBA, blockSize) << ")\n";
<< BytesToIeee(lastLBA, blockSize) << ")\n";
size = (lastLBA - firstLBA + 1);
cout << "Partition size: " << size << " sectors ("
<< BytesToSI(size, blockSize) << ")\n";
<< BytesToIeee(size, blockSize) << ")\n";
cout << "Attribute flags: ";
cout.fill('0');
cout.width(16);

View File

@@ -266,8 +266,8 @@ int main(int argc, char *argv[]) {
partNum = theGPT.FindFirstFreePart();
low = theGPT.FindFirstInLargest();
high = theGPT.FindLastInFree(low);
startSector = SIToInt(GetString(newPartInfo, 2), sSize, low, high, low);
endSector = SIToInt(GetString(newPartInfo, 3), sSize, startSector, high, high);
startSector = IeeeToInt(GetString(newPartInfo, 2), sSize, low, high, low);
endSector = IeeeToInt(GetString(newPartInfo, 3), sSize, startSector, high, high);
if (theGPT.CreatePartition(partNum, startSector, endSector)) {
saveData = 1;
} else {

View File

@@ -74,11 +74,7 @@ char GetYN(void) {
do {
cout << "(Y/N): ";
ReadCString(line, sizeof(line));
sscanf(line, "%c", &response);
if (response == 'y')
response = 'Y';
if (response == 'n')
response = 'N';
response = toupper(line[0]);
} while ((response != 'Y') && (response != 'N'));
return response;
} // GetYN(void)
@@ -99,22 +95,23 @@ uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, uint64_t sSize,
do {
cout << prompt;
cin.getline(line, 255);
response = SIToInt(line, sSize, low, high, def);
response = IeeeToInt(line, sSize, low, high, def);
} while ((response < low) || (response > high));
return response;
} // GetSectorNum()
// Convert an SI value (K, M, G, T, or P) to its equivalent in
// Convert an IEEE-1541-2002 value (K, M, G, T, P, or E) to its equivalent in
// number of sectors. If no units are appended, interprets as the number
// of sectors; otherwise, interprets as number of specified units and
// converts to sectors. For instance, with 512-byte sectors, "1K" converts
// to 2. If value includes a "+", adds low and subtracts 1; if SIValue
// inclues a "-", subtracts from high. If SIValue is empty, returns def.
// inclues a "-", subtracts from high. If IeeeValue is empty, returns def.
// Returns integral sector value.
uint64_t SIToInt(string SIValue, uint64_t sSize, uint64_t low, uint64_t high, uint64_t def) {
int plusFlag = 0, badInput = 0;
uint64_t response = def, mult = 1, divide = 1;
char suffix;
uint64_t IeeeToInt(string inValue, uint64_t sSize, uint64_t low, uint64_t high, uint64_t def) {
uint64_t response = def, bytesPerUnit = 1, mult = 1, divide = 1;
size_t foundAt = 0;
char suffix, plusFlag = ' ';
string suffixes = "KMGTPE";
if (sSize == 0) {
sSize = SECTOR_SIZE;
@@ -122,68 +119,42 @@ uint64_t SIToInt(string SIValue, uint64_t sSize, uint64_t low, uint64_t high, ui
} // if
// Remove leading spaces, if present
while (SIValue[0] == ' ')
SIValue.erase(0, 1);
while (inValue[0] == ' ')
inValue.erase(0, 1);
// If present, flag and remove leading plus sign
if (SIValue[0] == '+') {
plusFlag = 1;
SIValue.erase(0, 1);
} // if
// If present, flag and remove leading minus sign
if (SIValue[0] == '-') {
plusFlag = -1;
SIValue.erase(0, 1);
// If present, flag and remove leading plus or minus sign
if ((inValue[0] == '+') || (inValue[0] == '-')) {
plusFlag = inValue[0];
inValue.erase(0, 1);
} // if
// Extract numeric response and, if present, suffix
istringstream inString(SIValue);
if (((inString.peek() < '0') || (inString.peek() > '9')) && (inString.peek() != -1))
badInput = 1;
istringstream inString(inValue);
if (((inString.peek() >= '0') && (inString.peek() <= '9')) || (inString.peek() == -1)) {
inString >> response >> suffix;
suffix = toupper(suffix);
// If no response, or if response == 0, use default (def)
if ((SIValue.length() == 0) || (response == 0)) {
if ((inValue.length() == 0) || (response == 0)) {
response = def;
suffix = ' ';
plusFlag = 0;
} // if
// Set multiplier based on suffix
switch (suffix) {
case 'K':
case 'k':
mult = UINT64_C(1024) / sSize;
divide = sSize / UINT64_C(1024);
break;
case 'M':
case 'm':
mult = UINT64_C(1048576) / sSize;
divide = sSize / UINT64_C(1048576);
break;
case 'G':
case 'g':
mult = UINT64_C(1073741824) / sSize;
break;
case 'T':
case 't':
mult = UINT64_C(1099511627776) / sSize;
break;
case 'P':
case 'p':
mult = UINT64_C(1125899906842624) / sSize;
break;
default:
mult = 1;
} // switch
// Find multiplication and division factors for the suffix
foundAt = suffixes.find(suffix);
if (foundAt != string::npos) {
bytesPerUnit = UINT64_C(1) << (10 * (foundAt + 1));
mult = bytesPerUnit / sSize;
divide = sSize / bytesPerUnit;
} // if
// Adjust response based on multiplier and plus flag, if present
if (mult > 1)
response *= mult;
else if (divide > 1)
response /= divide;
if (plusFlag == 1) {
if (plusFlag == '+') {
// Recompute response based on low part of range (if default = high
// value, which should be the case when prompting for the end of a
// range) or the defaut value (if default != high, which should be
@@ -192,57 +163,43 @@ uint64_t SIToInt(string SIValue, uint64_t sSize, uint64_t low, uint64_t high, ui
response = response + low - UINT64_C(1);
else
response = response + def;
} // if
if (plusFlag == -1) {
} else if (plusFlag == '-') {
response = high - response;
} // if
if (badInput)
} else { // user input is invalid
response = high + UINT64_C(1);
} // if/else
return response;
} // SIToInt()
} // IeeeToInt()
// Takes a size and converts this to a size in SI units (KiB, MiB, GiB,
// TiB, or PiB), returned in C++ string form. The size is either in units
// of the sector size or, if that parameter is omitted, in bytes.
// Takes a size and converts this to a size in IEEE-1541-2002 units (KiB, MiB,
// GiB, TiB, PiB, or EiB), returned in C++ string form. The size is either in
// units of the sector size or, if that parameter is omitted, in bytes.
// (sectorSize defaults to 1).
string BytesToSI(uint64_t size, uint32_t sectorSize) {
string units;
string BytesToIeee(uint64_t size, uint32_t sectorSize) {
float sizeInIeee;
uint index = 0;
string units, prefixes = " KMGTPE";
ostringstream theValue;
float sizeInSI;
sizeInSI = (float) size * (float) sectorSize;
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
sizeInIeee = size * (float) sectorSize;
while ((sizeInIeee > 1024.0) && (index < (prefixes.length() - 1))) {
index++;
sizeInIeee /= 1024.0;
} // while
theValue.setf(ios::fixed);
if (units == " bytes") { // in bytes, so no decimal point
if (prefixes[index] == ' ') {
units = " bytes";
theValue.precision(0);
} else {
units = " iB";
units[1] = prefixes[index];
theValue.precision(1);
} // if/else
theValue << sizeInSI << units;
theValue << sizeInIeee << units;
return theValue.str();
} // BlocksToSI()
} // BlocksToIeee()
// Converts two consecutive characters in the input string into a
// number, interpreting the string as a hexadecimal number, starting

View File

@@ -8,7 +8,7 @@
#ifndef __GPTSUPPORT
#define __GPTSUPPORT
#define GPTFDISK_VERSION "0.7.0"
#define GPTFDISK_VERSION "0.7.1-pre1"
#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__)
// Darwin (Mac OS) only: disk IOCTLs are different, and there is no lseek64
@@ -60,8 +60,8 @@ void ReadCString(char *inStr, int numchars);
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, uint64_t sSize, const std::string& prompt);
uint64_t SIToInt(string SIValue, uint64_t sSize, uint64_t low, uint64_t high, uint64_t def = 0);
string BytesToSI(uint64_t size, uint32_t sectorSize = 1);
uint64_t IeeeToInt(string IeeeValue, uint64_t sSize, uint64_t low, uint64_t high, uint64_t def = 0);
string BytesToIeee(uint64_t size, uint32_t sectorSize = 1);
unsigned char StrToHex(const string & input, unsigned int position);
int IsHex(const string & input); // Returns 1 if input can be hexadecimal number....
int IsLittleEndian(void); // Returns 1 if CPU is little-endian, 0 if it's big-endian