diff options
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | gdisk.cc | 20 | ||||
-rw-r--r-- | gpt.cc | 50 | ||||
-rw-r--r-- | gpt.h | 6 | ||||
-rw-r--r-- | gptpart.cc | 4 | ||||
-rw-r--r-- | gptpart.h | 6 | ||||
-rw-r--r-- | gpttext.cc | 12 | ||||
-rw-r--r-- | gpttext.h | 3 | ||||
-rw-r--r-- | guid.cc | 70 | ||||
-rw-r--r-- | guid.h | 9 | ||||
-rw-r--r-- | parttypes.cc | 8 | ||||
-rw-r--r-- | parttypes.h | 8 | ||||
-rw-r--r-- | sgdisk.cc | 23 |
13 files changed, 114 insertions, 109 deletions
@@ -1,8 +1,8 @@ 0.6.11 (??/??/2010): -------------------- -- Changed partition type code entry in gdisk so that it directly - accepts GUID values rather than requiring typing "0" to do so. +- Streamlined GUID code entry in gdisk; it no longer offers the option + to enter GUIDs in separate segments. - The -t option to sgdisk now accepts GUID values as well as the sgdisk/gdisk-specific two-byte hex codes. @@ -318,6 +318,7 @@ void ExpertsMenu(string filename, GPTDataTextUI* theGPT) { char* junk; uint32_t pn, temp1, temp2; int goOn = 1, i; + char guidStr[255]; GUIDData aGUID; ostringstream prompt; @@ -337,8 +338,14 @@ void ExpertsMenu(string filename, GPTDataTextUI* theGPT) { case 'c': case 'C': if (theGPT->GetPartRange(&temp1, &temp2) > 0) { pn = theGPT->GetPartNum(); - cout << "Enter the partition's new unique GUID:\n"; - theGPT->SetPartitionGUID(pn, aGUID.GetGUIDFromUser()); + cout << "Enter the partition's new unique GUID ('R' to randomize): "; + junk = fgets(guidStr, 255, stdin); + if ((strlen(guidStr) >= 33) || (guidStr[0] == 'R') || (guidStr[0] == 'r')) { + theGPT->SetPartitionGUID(pn, (GUIDData) guidStr); + cout << "New GUID is " << theGPT->operator[](pn).GetUniqueGUID() << "\n"; + } else { + cout << "GUID is too short!\n"; + } // if/else } else cout << "No partitions\n"; break; case 'd': case 'D': @@ -353,8 +360,13 @@ void ExpertsMenu(string filename, GPTDataTextUI* theGPT) { theGPT->RandomizeGUIDs(); break; case 'g': case 'G': - cout << "Enter the disk's unique GUID:\n"; - theGPT->SetDiskGUID(aGUID.GetGUIDFromUser()); + cout << "Enter the disk's unique GUID ('R' to randomize): "; + junk = fgets(guidStr, 255, stdin); + if ((strlen(guidStr) >= 33) || (guidStr[0] == 'R') || (guidStr[0] == 'r')) { + theGPT->SetDiskGUID((GUIDData) guidStr); + cout << "The new disk GUID is " << theGPT->GetDiskGUID() << "\n"; + } else + cout << "GUID is too short!\n"; break; case 'h': case 'H': theGPT->RecomputeCHS(); @@ -185,9 +185,9 @@ int GPTData::Verify(void) { } // if if ((mainHeader.diskGUID != secondHeader.diskGUID)) { problems++; - cout << "\nProblem: main header's disk GUID (" << mainHeader.diskGUID.AsString() + cout << "\nProblem: main header's disk GUID (" << mainHeader.diskGUID << ") doesn't\nmatch the backup GPT header's disk GUID (" - << secondHeader.diskGUID.AsString() << ")\n" + << 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 @@ -1268,7 +1268,7 @@ void GPTData::DisplayGPTData(void) { cout << "Disk " << device << ": " << diskSize << " sectors, " << BytesToSI(diskSize * blockSize) << "\n"; cout << "Logical sector size: " << blockSize << " bytes\n"; - cout << "Disk identifier (GUID): " << mainHeader.diskGUID.AsString() << "\n"; + cout << "Disk identifier (GUID): " << mainHeader.diskGUID << "\n"; cout << "Partition table holds up to " << numParts << " entries\n"; cout << "First usable sector is " << mainHeader.firstUsableLBA << ", last usable sector is " << mainHeader.lastUsableLBA << "\n"; @@ -1661,9 +1661,14 @@ int GPTData::DeletePartition(uint32_t partNum) { // Returns 1 if the operation was successful, 0 if a problem was discovered. uint32_t GPTData::CreatePartition(uint32_t partNum, uint64_t startSector, uint64_t endSector) { int retval = 1; // assume there'll be no problems + uint64_t origSector = startSector; if (IsFreePartNum(partNum)) { - Align(&startSector); // Align sector to correct multiple + if (Align(&startSector)) { + cout << "Information: Moved requested sector from " << origSector << " to " + << startSector << " in\norder to align on " << sectorAlignment + << "-sector boundaries.\n"; + } // if if (IsFree(startSector) && (startSector <= endSector)) { if (FindLastInFree(startSector) >= endSector) { partitions[partNum].SetFirstLBA(startSector); @@ -1891,7 +1896,6 @@ int GPTData::Align(uint64_t* sector) { if ((*sector % sectorAlignment) != 0) { original = *sector; - retval = 1; earlier = (*sector / sectorAlignment) * sectorAlignment; later = earlier + (uint64_t) sectorAlignment; @@ -1905,6 +1909,7 @@ int GPTData::Align(uint64_t* sector) { } while ((sectorOK == 1) && (testSector < *sector)); if (sectorOK == 1) { *sector = earlier; + retval = 1; } // if } // if firstUsableLBA check @@ -1917,25 +1922,9 @@ int GPTData::Align(uint64_t* sector) { } while ((sectorOK == 1) && (testSector > *sector)); if (sectorOK == 1) { *sector = later; + retval = 1; } // 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) { - cout << "Information: Moved requested sector from " << original << " to " - << *sector << " in\norder to align on " << sectorAlignment - << "-sector boundaries.\n"; - if (!beQuiet) - cout << "Use 'l' on the experts' menu to adjust alignment\n"; - } else { - 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 or certain types of RAID array, performance\n" - << "may suffer.\n"; - retval = 0; - } // if/else } // if return retval; } // GPTData::Align() @@ -2259,12 +2248,27 @@ void GPTData::ReversePartitionBytes() { // Validate partition number bool GPTData::ValidPartNum (const uint32_t partNum) { if (partNum >= numParts) { - cerr << "Partition number out of range: " << (signed) partNum << endl; + cerr << "Partition number out of range: " << partNum << "\n"; return false; } // if return true; } // GPTData::ValidPartNum +// Return a single partition for inspection (not modification!) by other +// functions. +const GPTPart & GPTData::operator[](uint32_t partNum) const { + if (partNum >= numParts) { + cerr << "Partition number out of range: " << partNum << "\n"; + partNum = 0; + } // if + return partitions[partNum]; +} // operator[] + +// Return (not for modification!) the disk's GUID value +const GUIDData & GPTData::GetDiskGUID(void) const { + return mainHeader.diskGUID; +} // GPTData::GetDiskGUID() + // Manage attributes for a partition, based on commands passed to this function. // (Function is non-interactive.) // Returns 1 if a modification command succeeded, 0 if the command should not have @@ -16,7 +16,7 @@ #ifndef __GPTSTRUCTS #define __GPTSTRUCTS -#define GPTFDISK_VERSION "0.6.11-pre2" +#define GPTFDISK_VERSION "0.6.11-pre3" // Constants used by GPTData::PartsToMBR(). MBR_EMPTY must be the lowest- // numbered value to refer to partition numbers. (Most will be 0 or positive, @@ -177,10 +177,10 @@ public: uint64_t GetSecondPartsLBA(void) {return secondHeader.partitionEntriesLBA;} uint64_t GetFirstUsableLBA(void) {return mainHeader.firstUsableLBA;} uint64_t GetLastUsableLBA(void) {return mainHeader.lastUsableLBA;} - uint64_t GetPartFirstLBA(uint32_t i) {return partitions[i].GetFirstLBA();} - uint64_t GetPartLastLBA(uint32_t i) {return partitions[i].GetLastLBA();} uint32_t CountParts(void); bool ValidPartNum (const uint32_t partNum); + const GPTPart & operator[](uint32_t partNum) const; + const GUIDData & GetDiskGUID(void) const; // Find information about free space uint64_t FindFirstAvailable(uint64_t start = 0); @@ -177,9 +177,9 @@ void GPTPart::ShowDetails(uint32_t blockSize) { uint64_t size; if (firstLBA != 0) { - cout << "Partition GUID code: " << partitionType.AsString(); + cout << "Partition GUID code: " << partitionType; cout << " (" << partitionType.TypeName() << ")\n"; - cout << "Partition unique GUID: " << uniqueGUID.AsString() << "\n"; + cout << "Partition unique GUID: " << uniqueGUID << "\n"; cout << "First sector: " << firstLBA << " (at " << BytesToSI(firstLBA * blockSize) << ")\n"; @@ -53,9 +53,9 @@ class GPTPart { PartType & GetType(void) {return partitionType;} uint16_t GetHexType(void); string GetTypeName(void); - GUIDData GetUniqueGUID(void) {return uniqueGUID;} - uint64_t GetFirstLBA(void) {return firstLBA;} - uint64_t GetLastLBA(void) {return lastLBA;} + const GUIDData GetUniqueGUID(void) const {return uniqueGUID;} + uint64_t GetFirstLBA(void) const {return firstLBA;} + uint64_t GetLastLBA(void) const {return lastLBA;} uint64_t GetLengthLBA(void); uint64_t GetAttributes(void) {return attributes;} string GetDescription(void); @@ -180,7 +180,7 @@ void GPTDataTextUI::ResizePartitionTable(void) { // Interactively create a partition void GPTDataTextUI::CreatePartition(void) { - uint64_t firstBlock, firstInLargest, lastBlock, sector; + uint64_t firstBlock, firstInLargest, lastBlock, sector, origSector; uint32_t firstFreePart = 0; ostringstream prompt1, prompt2, prompt3; int partNum; @@ -211,7 +211,15 @@ void GPTDataTextUI::CreatePartition(void) { do { sector = GetSectorNum(firstBlock, lastBlock, firstInLargest, prompt2.str()); } while (IsFree(sector) == 0); - Align(§or); // Align sector to correct multiple + origSector = sector; + if (Align(§or)) { + cout << "Information: Moved requested sector from " << origSector << " to " + << sector << " in\norder to align on " << sectorAlignment + << "-sector boundaries.\n"; + if (!beQuiet) + cout << "Use 'l' on the experts' menu to adjust alignment\n"; + } // if + // Align(§or); // Align sector to correct multiple firstBlock = sector; // Get last block for new partitions... @@ -32,6 +32,9 @@ class GPTDataTextUI : public GPTData { GPTDataTextUI(string filename); ~GPTDataTextUI(void); + // This one needs to be explicitly defined, even though it does nothing new.... + const GPTPart & operator[](uint32_t partNum) {return GPTData::operator[](partNum);} + // Extended (interactive) versions of some base-class functions WhichToUse UseWhichPartitions(void); int XFormDisklabel(void); @@ -15,6 +15,7 @@ #define __STDC_CONSTANT_MACROS #include <stdio.h> +#include <time.h> #include <string> #include <iostream> #include "guid.h" @@ -23,6 +24,7 @@ using namespace std; GUIDData::GUIDData(void) { + srand(time(0)); Zero(); } // constructor @@ -119,52 +121,6 @@ GUIDData & GUIDData::operator=(const char * orig) { return operator=((string) orig); } // GUIDData::operator=(const char * orig) -// Read a GUIDData from stdin, prompting the user along the way for the -// correct form. This is a bit more flexible than it claims; it parses -// any entry of 32 or 36 characters as a GUID ( -GUIDData & GUIDData::GetGUIDFromUser(void) { - string part1, part2, part3, part4, part5; - char line[255]; - int entered = 0; - - 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: "; - cin.get(line, 255); - part1 = DeleteSpaces(line); - - // If user entered 'r' or 'R', generate GUID randomly.... - if ((part1[0] == 'r') || (part1[0] == 'R')) { - Randomize(); - entered = 1; - } // if user entered 'R' or 'r' - - // If string length is right for whole entry, try to parse it.... - if (((part1.length() == 36) || (part1.length() == 32)) && (entered == 0)) { - operator=(part1); - entered = 1; - } // if - - // If neither of the above methods of entry was used, use prompted - // entry.... - if (entered == 0) { - cout << "Enter a two-byte hexadecimal number for the second segment: "; - cin >> part2; - cout << "Enter a two-byte hexadecimal number for the third segment: "; - cin >> part3; - cout << "Enter a two-byte hexadecimal number for the fourth segment: "; - cin >> part4; - cout << "Enter a six-byte hexadecimal number for the fifth segment: "; - cin >> part5; - operator=(part1 += (string) "-" += part2 += (string) "-" += part3 - += (string) "-" += part4 += (string) "-" += part5); - } // if/else - cin.ignore(255, '\n'); - cout << "New GUID: " << AsString() << "\n"; - return *this; -} // GUIDData::GetGUIDData(void) - // Erase the contents of the GUID void GUIDData::Zero(void) { int i; @@ -189,12 +145,12 @@ void GUIDData::Randomize(void) { #else int i; for (i = 0; i < 16; i++) - uuidData[i] = rand(); + uuidData[i] = (unsigned char) (256.0 * (rand() / (RAND_MAX + 1.0))); #endif } // GUIDData::Randomize // Equality operator; returns 1 if the GUIDs are equal, 0 if they're unequal -int GUIDData::operator==(const GUIDData & orig) { +int GUIDData::operator==(const GUIDData & orig) const { int retval = 1; // assume they're equal int i; @@ -206,12 +162,12 @@ int GUIDData::operator==(const GUIDData & orig) { } // GUIDData::operator== // Inequality operator; returns 1 if the GUIDs are unequal, 0 if they're equal -int GUIDData::operator!=(const GUIDData & orig) { +int GUIDData::operator!=(const GUIDData & orig) const { return !operator==(orig); } // GUIDData::operator!= // Return the GUID as a string, suitable for display to the user. -string GUIDData::AsString(void) { +string GUIDData::AsString(void) const { char theString[40]; sprintf(theString, @@ -237,3 +193,17 @@ string GUIDData::DeleteSpaces(string s) { } // if return s; } // GUIDData::DeleteSpaces() + +/******************************* + * * + * Non-class support functions * + * * + *******************************/ + +// Display a GUID as a string.... +ostream & operator<<(ostream & os, const GUIDData & data) { + string asString; + + os << data.AsString(); + return os; +} // GUIDData::operator<<()
\ No newline at end of file @@ -44,16 +44,17 @@ class GUIDData { GUIDData & operator=(const GUIDData & orig); GUIDData & operator=(const string & orig); GUIDData & operator=(const char * orig); - GUIDData & GetGUIDFromUser(void); void Zero(void); void Randomize(void); // Data tests.... - int operator==(const GUIDData & orig); - int operator!=(const GUIDData & orig); + int operator==(const GUIDData & orig) const; + int operator!=(const GUIDData & orig) const; // Data retrieval.... - string AsString(void); + string AsString(void) const; }; // class GUIDData +ostream & operator<<(ostream & os, const GUIDData & data); + #endif diff --git a/parttypes.cc b/parttypes.cc index a9cdf79..37f47a7 100644 --- a/parttypes.cc +++ b/parttypes.cc @@ -238,7 +238,7 @@ PartType & PartType::operator=(uint16_t ID) { } // PartType::operator=(uint16_t ID) // Return the English description of the partition type (e.g., "Linux/Windows data") -string PartType::TypeName(void) { +string PartType::TypeName(void) const { AType* theItem = allTypes; int found = 0; string typeName; @@ -262,7 +262,7 @@ string PartType::TypeName(void) { // is set to 0. This enables control of which values get returned when // there are multiple possibilities, but opens the algorithm up to the // potential for problems should the data in the list be bad. -uint16_t PartType::GetHexType() { +uint16_t PartType::GetHexType() const { AType* theItem = allTypes; int found = 0; uint16_t theID = 0xFFFF; @@ -285,7 +285,7 @@ uint16_t PartType::GetHexType() { // Note: This function assumes an 80-column display. On wider displays, // it stops at under 80 columns; on narrower displays, lines will wrap // in an ugly way. -void PartType::ShowAllTypes(void) { +void PartType::ShowAllTypes(void) const { int colCount = 1; // column count size_t i; AType* thisType = allTypes; @@ -312,7 +312,7 @@ void PartType::ShowAllTypes(void) { } // PartType::ShowTypes() // Returns 1 if code is a valid extended MBR code, 0 if it's not -int PartType::Valid(uint16_t code) { +int PartType::Valid(uint16_t code) const { AType* thisType = allTypes; int found = 0; diff --git a/parttypes.h b/parttypes.h index 4d6e547..9f38b76 100644 --- a/parttypes.h +++ b/parttypes.h @@ -50,12 +50,12 @@ public: PartType & operator=(uint16_t ID); // Use MBR type code times 0x0100 to assign GUID // Retrieve transformed GUID data based on type code matches - string TypeName(void); - uint16_t GetHexType(); + string TypeName(void) const; + uint16_t GetHexType() const; // Information relating to all type data - void ShowAllTypes(void); - int Valid(uint16_t); + void ShowAllTypes(void) const; + int Valid(uint16_t code) const; }; #endif @@ -25,7 +25,7 @@ using namespace std; #define MAX_OPTIONS 50 -int BuildMBR(GPTData* theGPT, char* argument, int isHybrid); +int BuildMBR(GPTData& theGPT, char* argument, int isHybrid); int CountColons(char* argument); int main(int argc, char *argv[]) { @@ -37,6 +37,7 @@ int main(int argc, char *argv[]) { int alignment = DEFAULT_ALIGNMENT, retval = 0, pretend = 0; uint32_t tableSize = 128; uint64_t startSector, endSector; + uint64_t temp; // temporary variable; free to use in any case char *attributeOperation = NULL; char *device = NULL; char *newPartInfo = NULL, *typeCode = NULL, *partName = NULL; @@ -58,6 +59,7 @@ int main(int argc, char *argv[]) { {"move-second-header", 'e', POPT_ARG_NONE, NULL, 'e', "move second header to end of disk", ""}, {"end-of-largest", 'E', POPT_ARG_NONE, NULL, 'E', "show end of largest free block", ""}, {"first-in-largest", 'f', POPT_ARG_NONE, NULL, 'f', "show start of the largest free block", ""}, + {"first-aligned-in-largest", 'F', POPT_ARG_NONE, NULL, 'F', "show start of the largest free block, aligned", ""}, {"mbrtogpt", 'g', POPT_ARG_NONE, NULL, 'g', "convert MBR to GPT", ""}, {"randomize-guids", 'G', POPT_ARG_NONE, NULL, 'G', "randomize disk and partition GUIDs", ""}, {"hybrid", 'h', POPT_ARG_STRING, &hybrids, 'h', "create hybrid MBR", "partnum[:partnum...]"}, @@ -195,6 +197,11 @@ int main(int argc, char *argv[]) { case 'f': cout << theGPT.FindFirstInLargest() << "\n"; break; + case 'F': + temp = theGPT.FindFirstInLargest(); + theGPT.Align(&temp); + cout << temp << "\n"; + break; case 'g': theGPT.JustLooking(0); saveData = 1; @@ -207,7 +214,7 @@ int main(int argc, char *argv[]) { break; case 'h': theGPT.JustLooking(0); - if (BuildMBR(&theGPT, hybrids, 1) == 1) + if (BuildMBR(theGPT, hybrids, 1) == 1) saveData = 1; break; case 'i': @@ -227,7 +234,7 @@ int main(int argc, char *argv[]) { break; case 'm': theGPT.JustLooking(0); - if (BuildMBR(&theGPT, mbrParts, 0) == 1) { + if (BuildMBR(theGPT, mbrParts, 0) == 1) { if (!pretend) { if (theGPT.SaveMBR()) theGPT.DestroyGPT(); @@ -399,12 +406,12 @@ int main(int argc, char *argv[]) { } // main // Create a hybrid or regular MBR from GPT data structures -int BuildMBR(GPTData* theGPT, char* argument, int isHybrid) { +int BuildMBR(GPTData & theGPT, char* argument, int isHybrid) { int numParts, allOK = 1, i; PartNotes notes; struct PartInfo *newNote; - if ((theGPT != NULL) && (argument != NULL)) { + if ((&theGPT != NULL) && (argument != NULL)) { numParts = CountColons(argument) + 1; if (numParts <= (4 - isHybrid)) { for (i = 0; i < numParts; i++) { @@ -413,8 +420,8 @@ int BuildMBR(GPTData* theGPT, char* argument, int isHybrid) { newNote->active = 0; newNote->hexCode = 0; // code to compute it from default newNote->type = PRIMARY; - newNote->firstLBA = theGPT->GetPartFirstLBA(newNote->gptPartNum); - newNote->lastLBA = theGPT->GetPartLastLBA(newNote->gptPartNum); + newNote->firstLBA = theGPT[newNote->gptPartNum].GetFirstLBA(); + newNote->lastLBA = theGPT[newNote->gptPartNum].GetLastLBA(); notes.AddToEnd(newNote); } // for if (isHybrid) { @@ -426,7 +433,7 @@ int BuildMBR(GPTData* theGPT, char* argument, int isHybrid) { // newNote firstLBA and lastLBA are computed later... notes.AddToStart(newNote); } // if - if (theGPT->PartsToMBR(notes) != numParts) + if (theGPT.PartsToMBR(notes) != numParts) allOK = 0; } else allOK = 0; } else allOK = 0; |