From 01f7f08624f0c942001977415214a578621f6495 Mon Sep 17 00:00:00 2001 From: srs5694 Date: Tue, 15 Mar 2011 23:53:31 -0400 Subject: [PATCH] Second patchset from Florian & a few other small changes --- basicmbr.cc | 2 +- gpt.cc | 63 ++++++----------- gpt.h | 1 - gptpart.cc | 17 ++--- sgdisk.cc | 4 +- support.cc | 191 ++++++++++++++++++++-------------------------------- support.h | 6 +- 7 files changed, 109 insertions(+), 175 deletions(-) diff --git a/basicmbr.cc b/basicmbr.cc index 0af3a82..3cc1e64 100644 --- a/basicmbr.cc +++ b/basicmbr.cc @@ -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'); diff --git a/gpt.cc b/gpt.cc index 4f5683a..2c5e138 100644 --- a/gpt.cc +++ b/gpt.cc @@ -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 diff --git a/gpt.h b/gpt.h index e452663..ee50bda 100644 --- a/gpt.h +++ b/gpt.h @@ -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(); diff --git a/gptpart.cc b/gptpart.cc index 062206a..a938c52 100644 --- a/gptpart.cc +++ b/gptpart.cc @@ -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,9 +158,10 @@ 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 << " "; + 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); cout.setf(ios::uppercase); @@ -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); diff --git a/sgdisk.cc b/sgdisk.cc index 1f3e792..2ae8767 100644 --- a/sgdisk.cc +++ b/sgdisk.cc @@ -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 { diff --git a/support.cc b/support.cc index 200cbca..1994cd2 100644 --- a/support.cc +++ b/support.cc @@ -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,127 +119,87 @@ 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; - inString >> response >> suffix; - - // If no response, or if response == 0, use default (def) - if ((SIValue.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 - - // Adjust response based on multiplier and plus flag, if present - if (mult > 1) - response *= mult; - else if (divide > 1) - response /= divide; - if (plusFlag == 1) { - // 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 - // the case for the first sector of a partition). - if (def == high) - response = response + low - UINT64_C(1); - else - response = response + def; - } // if - if (plusFlag == -1) { - response = high - response; - } // if - - if (badInput) + 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 ((inValue.length() == 0) || (response == 0)) { + response = def; + suffix = ' '; + plusFlag = 0; + } // if + + // 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 == '+') { + // 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 + // the case for the first sector of a partition). + if (def == high) + response = response + low - UINT64_C(1); + else + response = response + def; + } else if (plusFlag == '-') { + response = high - response; + } // if + } 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 @@ -344,4 +301,4 @@ string GetString(string argument, int itemNum) { retVal = argument.substr(startPos, endPos - startPos); return retVal; -} // GetString() \ No newline at end of file +} // GetString() diff --git a/support.h b/support.h index 73363b7..e77c02f 100644 --- a/support.h +++ b/support.h @@ -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