diff options
-rw-r--r-- | NEWS | 19 | ||||
-rw-r--r-- | gpt.cc | 15 | ||||
-rw-r--r-- | gpt.h | 4 | ||||
-rw-r--r-- | mbr.cc | 38 | ||||
-rw-r--r-- | mbr.h | 1 | ||||
-rw-r--r-- | partnotes.cc | 24 | ||||
-rw-r--r-- | partnotes.h | 1 | ||||
-rw-r--r-- | sgdisk.8 | 7 | ||||
-rw-r--r-- | sgdisk.cc | 18 |
9 files changed, 115 insertions, 12 deletions
@@ -1,7 +1,24 @@ 0.6.11 (??/??/2010): -------------------- -- +- The -t option to sgdisk now accepts GUID values as well as the + sgdisk/gdisk-specific two-byte hex codes. + +- Added check that the protective 0xEE MBR partition begins on sector 1 + to the verify function. If it doesn't, a warning message is displayed, + but it doesn't count as an error. + +- Added check for overlapping MBR partitions to verify function (gdisk "v" + function on all menus; sgdisk -v/--verify function). Also warns about + multiple MBR 0xEE partitions (causes problems in some OSes). + +- Added check to GPT-to-MBR and hybrid MBR creation options to prevent + creation of disks with duplicate partitions. When told to create a disk + with duplicates, sgdisk now aborts with the error message "Problem + creating MBR!" When attempting to create a hybrid MBR with duplicates, + gdisk silently drops duplicate partitions, leaving fewer than requested. + Creating duplicates should not be possible in sgdisk when converting to + MBR form. 0.6.10 (8/22/2010): ------------------- @@ -227,6 +227,9 @@ int GPTData::Verify(void) { // Check for mismatched MBR and GPT partitions... problems += FindHybridMismatches(); + // Check for MBR-specific problems.... + problems += VerifyMBR(); + // Verify that partitions don't run into GPT data areas.... problems += CheckGPTSize(); @@ -1512,6 +1515,7 @@ int GPTData::PartsToMBR(PartNotes & notes) { protectiveMBR.EmptyMBR(0); protectiveMBR.SetDiskSize(diskSize); + notes.MakeItLegal(); notes.Rewind(); while (notes.GetNextInfo(&convInfo) >= 0) { if ((convInfo.gptPartNum >= 0) && (convInfo.type == PRIMARY)) { @@ -1860,6 +1864,17 @@ int GPTData::ChangePartType(uint32_t partNum, uint16_t hexCode) { return retval; } // GPTData::ChangePartType() +// Change partition type code non-interactively. Returns 1 if +// successful, 0 if not.... +int GPTData::ChangePartType(uint32_t partNum, PartType theGUID) { + int retval = 1; + + if (!IsFreePartNum(partNum)) { + partitions[partNum].SetType(theGUID); + } else retval = 0; + return retval; +} // GPTData::ChangePartType() + // Recompute the CHS values of all the MBR partitions. Used to reset // CHS values that some BIOSes require, despite the fact that the // resulting CHS values violate the GPT standard. @@ -16,7 +16,7 @@ #ifndef __GPTSTRUCTS #define __GPTSTRUCTS -#define GPTFDISK_VERSION "0.6.10" +#define GPTFDISK_VERSION "0.6.11-pre1" // Constants used by GPTData::PartsToMBR(). MBR_EMPTY must be the lowest- // numbered value to refer to partition numbers. (Most will be 0 or positive, @@ -113,6 +113,7 @@ public: void RecomputeCRCs(void); void RebuildMainHeader(void); void RebuildSecondHeader(void); + int VerifyMBR(void) {return protectiveMBR.Verify();} int FindHybridMismatches(void); int FindOverlaps(void); int FindInsanePartitions(void); @@ -162,6 +163,7 @@ public: int SetPartitionGUID(uint32_t pn, GUIDData theGUID); void RandomizeGUIDs(void); int ChangePartType(uint32_t pn, uint16_t hexCode); + int ChangePartType(uint32_t pn, PartType theGUID); void MakeProtectiveMBR(void) {protectiveMBR.MakeProtectiveMBR();} void RecomputeCHS(void); int Align(uint64_t* sector); @@ -535,6 +535,44 @@ int MBRData::LBAtoCHS(uint64_t lba, uint8_t * chs) { return (retval); } // MBRData::LBAtoCHS() +// Look for problems -- overlapping partitions, etc. +int MBRData::Verify(void) { + int i, j, theyOverlap, numProbs = 0, numEE = 0; + uint32_t firstLBA1, firstLBA2, lastLBA1, lastLBA2; + + for (i = 0; i < MAX_MBR_PARTS; i++) { + for (j = i + 1; j < MAX_MBR_PARTS; j++) { + theyOverlap = 0; + firstLBA1 = partitions[i].firstLBA; + firstLBA2 = partitions[j].firstLBA; + if ((firstLBA1 != 0) && (firstLBA2 != 0)) { + lastLBA1 = partitions[i].firstLBA + partitions[i].lengthLBA - 1; + lastLBA2 = partitions[j].firstLBA + partitions[j].lengthLBA - 1; + if ((firstLBA1 < lastLBA2) && (lastLBA1 >= firstLBA2)) + theyOverlap = 1; + if ((firstLBA2 < lastLBA1) && (lastLBA2 >= firstLBA1)) + theyOverlap = 1; + } // if + if (theyOverlap) { + numProbs++; + cout << "\nProblem: MBR partitions " << i + 1 << " and " << j + 1 + << " overlap!\n"; + } // if + } // for (j...) + if (partitions[i].partitionType == 0xEE) { + numEE++; + if (partitions[i].firstLBA != 1) + cout << "\nWarning: 0xEE partition doesn't start on sector 1. This can cause problems\n" + << "in some OSes.\n"; + } // if + } // for (i...) + if (numEE > 1) + cout << "\nCaution: More than one 0xEE MBR partition found. This can cause problems\n" + << "in some OSes.\n"; + + return numProbs; +} // MBRData::Verify() + /***************************************************** * * * Functions to create, delete, or change partitions * @@ -110,6 +110,7 @@ public: void SetHybrid(void) {state = hybrid;} // Set hybrid flag void SetCHSGeom(uint32_t h, uint32_t s); int LBAtoCHS(uint64_t lba, uint8_t * chs); // Convert LBA to CHS + int Verify(void); // Functions to create, delete, or change partitions // Pass EmptyMBR 1 to clear the boot loader code, 0 to leave it intact diff --git a/partnotes.cc b/partnotes.cc index c7954e7..1edd5b8 100644 --- a/partnotes.cc +++ b/partnotes.cc @@ -451,8 +451,28 @@ int PartNotes::IsLegal(void) { * * *************************************************************************/ +// Remove duplicate partitions from the list. +void PartNotes::RemoveDuplicates(void) { + struct PartInfo *n1, *n2; + + n1 = notes; + while (n1 != NULL) { + n2 = n1->next; + while (n2 != NULL) { + if ((n1->firstLBA == n2->firstLBA) && (n1->lastLBA == n2->lastLBA)) { + n1->next = n2->next; + delete n2; + n2 = n1->next; + } else { + n2 = n2->next; + } // if/else + } // while (n2 != NULL) + n1 = n1->next; + } // while (n1 != NULL) +} // PartNotes::RemoveDuplicates() + // Creates a legal mix of primaries and logicals, maximizing the number -// of included partitions. +// of included partitions. Also removes duplicates. // Returns 1 if successful, 0 if not (if missing notes list, say) int PartNotes::MakeItLegal(void) { struct PartInfo *theNote, *lastPrimary; @@ -460,6 +480,8 @@ int PartNotes::MakeItLegal(void) { if (notes == NULL) return 0; + RemoveDuplicates(); + if (!IsLegal()) { // Start by eliminating or converting excessive extended partitions... while (GetNumExtended() > 1) diff --git a/partnotes.h b/partnotes.h index 31b850c..735e1df 100644 --- a/partnotes.h +++ b/partnotes.h @@ -89,6 +89,7 @@ class PartNotes { int IsLegal(void); // returns boolean // Manipulate data or metadata + void RemoveDuplicates(void); int MakeItLegal(void); void TrimSmallestExtended(void); @@ -369,9 +369,10 @@ changes. Such changes will be reflected in your device filenames, so you may need to edit \fI/etc/fstab\fR if you use this option. .TP -.B \-t, \-\-typecode=partnum:hexcode -Change a single partition's type code. You enter the type code using a -two\-byte hexadecimal number, as described earlier. +.B \-t, \-\-typecode=partnum:{hexcode|GUID} +Change a single partition's type code. You enter the type code using either +a two\-byte hexadecimal number, as described earlier, or a fully-specified +GUID value, such as EBD0A0A2-B9E5-4433-87C0-68B6B72699C7. .TP .B \-T, \-\-transform\-bsd=partnum @@ -43,7 +43,7 @@ int main(int argc, char *argv[]) { char *newPartInfo = NULL, *typeCode = NULL, *partName = NULL; char *backupFile = NULL, *twoParts = NULL, *hybrids = NULL, *mbrParts; char *partGUID = NULL, *diskGUID = NULL, *outDevice = NULL; - string cmd; + string cmd, typeGUID; PartType typeHelper; poptContext poptCon; @@ -75,7 +75,7 @@ int main(int argc, char *argv[]) { {"replicate", 'R', POPT_ARG_STRING, &outDevice, 'R', "replicate partition table", "device_filename"}, {"sort", 's', POPT_ARG_NONE, NULL, 's', "sort partition table entries", ""}, {"resize-table", 'S', POPT_ARG_INT, &tableSize, 'S', "resize partition table", "numparts"}, - {"typecode", 't', POPT_ARG_STRING, &typeCode, 't', "change partition type code", "partnum:hexcode"}, + {"typecode", 't', POPT_ARG_STRING, &typeCode, 't', "change partition type code", "partnum:{hexcode|GUID}"}, {"transform-bsd", 'T', POPT_ARG_INT, &bsdPartNum, 'T', "transform BSD disklabel partition to GPT", "partnum"}, {"partition-guid", 'u', POPT_ARG_STRING, &partGUID, 'u', "set partition GUID", "partnum:guid"}, {"disk-guid", 'U', POPT_ARG_STRING, &diskGUID, 'U', "set disk GUID", "guid"}, @@ -305,12 +305,18 @@ int main(int argc, char *argv[]) { case 't': theGPT.JustLooking(0); partNum = (int) GetInt(typeCode, 1) - 1; - sscanf(GetString(typeCode, 2).c_str(), "%x", &hexCode); - if (theGPT.ChangePartType(partNum, hexCode)) { + cout << "Got string '" << GetString(typeCode, 2) << "'\n"; + if (GetString(typeCode, 2).length() < 10) { + sscanf(GetString(typeCode, 2).c_str(), "%x", &hexCode); + typeHelper = hexCode; + } else { + typeHelper = GetString(typeCode, 2); + } // if/else hexCode or GUID + if (theGPT.ChangePartType(partNum, typeHelper)) { saveData = 1; } else { cerr << "Could not change partition " << partNum + 1 - << "'s type code to " << hex << hexCode << "!\n" << dec; + << "'s type code to " << GetString(typeCode, 2) << "!\n"; neverSaveData = 1; } // if/else free(typeCode); @@ -370,7 +376,7 @@ int main(int argc, char *argv[]) { while ((opt = poptGetNextOpt(poptCon)) > 0) { switch (opt) { case 'v': - cout << "Verification may miss some problems!\n"; + cout << "Verification may miss some problems or report too many!\n"; theGPT.Verify(); break; case 'z': |