summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS16
-rw-r--r--gptcl.cc5
-rw-r--r--gptpart.cc12
-rw-r--r--gptpart.h5
-rw-r--r--gpttext.cc43
-rw-r--r--gpttext.h3
-rw-r--r--support.h2
7 files changed, 68 insertions, 18 deletions
diff --git a/NEWS b/NEWS
index 35f9769..09e0006 100644
--- a/NEWS
+++ b/NEWS
@@ -9,12 +9,16 @@
hybridized partition when creating a hybrid MBR.
- Fixed bug that caused gdisk and sgdisk to create hybridized partitions
- that ended above the 2^32 sector point with incorrect end values. The
- program now refuses to create such hybridized partitions at all. (A case
- could be made for allowing creation of such partitions so long as the
- start sector is below 2^32 and the size is under 2^32, but as a practical
- matter, many OSes flake out with such partitions, so I'm erring on the
- side of caution on this one.)
+ that ended at or above the 2^32 sector point with incorrect end values.
+ The behavior now varies between gdisk and sgdisk: gdisk now creates
+ hybrid partitions that begin below 2^32 sectors and that are smaller than
+ 2^32 sectors, since this is technically legal; but gdisk displays a
+ warning, because some OSes (such as DOS, Windows XP, OS/2, and BeOS)
+ misbehave with such partitions. AFAIK, only Linux, FreeBSD, and Windows 7
+ work properly with such partitions. Because of this fact and because
+ sgdisk is a more automated tool, it's stricter in how it handles things:
+ It refuses to create a hybrid partition if the original ends at or above
+ the 2^32 sector mark.
0.8.9 (2/17/2014):
------------------
diff --git a/gptcl.cc b/gptcl.cc
index ac2917a..cd77495 100644
--- a/gptcl.cc
+++ b/gptcl.cc
@@ -474,7 +474,7 @@ int GPTDataCL::BuildMBR(char* argument, int isHybrid) {
newMBR.SetDisk(GetDisk());
for (i = 0; i < numParts; i++) {
origPartNum = GetInt(argument, i + 1) - 1;
- if (IsUsedPartNum(origPartNum) && partitions[origPartNum].IsSizedForMBR()) {
+ if (IsUsedPartNum(origPartNum) && (partitions[origPartNum].IsSizedForMBR() == MBR_SIZED_GOOD)) {
newPart.SetInclusion(PRIMARY);
newPart.SetLocation(operator[](origPartNum).GetFirstLBA(),
operator[](origPartNum).GetLengthLBA());
@@ -493,7 +493,8 @@ int GPTDataCL::BuildMBR(char* argument, int isHybrid) {
newPart.SetType(0xEE);
newMBR.AddPart(0, newPart);
} // if
- SetProtectiveMBR(newMBR);
+ if (allOK)
+ SetProtectiveMBR(newMBR);
} else allOK = 0;
} else allOK = 0;
if (!allOK)
diff --git a/gptpart.cc b/gptpart.cc
index d06145c..d780ec1 100644
--- a/gptpart.cc
+++ b/gptpart.cc
@@ -138,9 +138,17 @@ int GPTPart::IsUsed(void) {
return (partitionType != GUIDData("0x00"));
} // GPTPart::IsUsed()
-// Returns 1 if the partition's end point is under (2^32 - 1) sectors, 0 if it's over that value.
+// Returns MBR_SIZED_GOOD, MBR_SIZED_IFFY, or MBR_SIZED_BAD; see comments
+// in header file for details.
int GPTPart::IsSizedForMBR(void) {
- return (lastLBA < UINT32_MAX);
+ int retval = MBR_SIZED_GOOD;
+
+ if ((firstLBA > UINT32_MAX) || ((lastLBA - firstLBA) > UINT32_MAX) || (firstLBA > lastLBA))
+ retval = MBR_SIZED_BAD;
+ else if (lastLBA > UINT32_MAX)
+ retval = MBR_SIZED_IFFY;
+
+ return (retval);
} // GPTPart::IsSizedForMBR()
// Set the type code to the specified one. Also changes the partition
diff --git a/gptpart.h b/gptpart.h
index f62d5b5..657b3f9 100644
--- a/gptpart.h
+++ b/gptpart.h
@@ -25,6 +25,11 @@
using namespace std;
+// Values returned by GPTPart::IsSizedForMBR()
+#define MBR_SIZED_GOOD 0 /* Whole partition under 2^32 sectors */
+#define MBR_SIZED_IFFY 1 /* Partition starts under 2^32 & is less than 2^32, but ends over 2^32 */
+#define MBR_SIZED_BAD 2 /* Partition starts over 2^32, is bigger than 2^32, or otherwise bad */
+
/****************************************
* *
* GPTPart class and related structures *
diff --git a/gpttext.cc b/gpttext.cc
index b5e8ac2..15fba7b 100644
--- a/gpttext.cc
+++ b/gpttext.cc
@@ -394,9 +394,9 @@ void GPTDataTextUI::ShowDetails(void) {
// Create a hybrid MBR -- an ugly, funky thing that helps GPT work with
// OSes that don't understand GPT.
void GPTDataTextUI::MakeHybrid(void) {
- uint32_t partNums[3];
+ uint32_t partNums[3] = {0, 0, 0};
string line;
- int numPartsToCvt = 0, i, j, mbrNum = 0;
+ int numPartsToCvt = 0, numConverted = 0, i, j, mbrNum = 0;
unsigned int hexCode = 0;
MBRPart hybridPart;
MBRData hybridMBR;
@@ -418,7 +418,9 @@ void GPTDataTextUI::MakeHybrid(void) {
line = ReadString();
istringstream inLine(line);
do {
- inLine >> partNums[numPartsToCvt++];
+ inLine >> partNums[numPartsToCvt];
+ if (partNums[numPartsToCvt] > 0)
+ numPartsToCvt++;
} while (!inLine.eof() && (numPartsToCvt < 3));
if (numPartsToCvt > 0) {
@@ -428,7 +430,7 @@ void GPTDataTextUI::MakeHybrid(void) {
for (i = 0; i < numPartsToCvt; i++) {
j = partNums[i] - 1;
- if (partitions[j].IsUsed() && partitions[j].IsSizedForMBR()) {
+ if (partitions[j].IsUsed() && (partitions[j].IsSizedForMBR() != MBR_SIZED_BAD)) {
mbrNum = i + (eeFirst == 'Y');
cout << "\nCreating entry for GPT partition #" << j + 1
<< " (MBR partition #" << mbrNum + 1 << ")\n";
@@ -441,13 +443,16 @@ void GPTDataTextUI::MakeHybrid(void) {
else
hybridPart.SetStatus(0x00);
hybridPart.SetInclusion(PRIMARY);
+ if (partitions[j].IsSizedForMBR() == MBR_SIZED_IFFY)
+ WarnAboutIffyMBRPart(j + 1);
+ numConverted++;
} else {
cerr << "\nGPT partition #" << j + 1 << " does not exist or is too big; skipping.\n";
} // if/else
hybridMBR.AddPart(mbrNum, hybridPart);
} // for
- if (numPartsToCvt > 0) { // User opted to create a hybrid MBR....
+ if (numConverted > 0) { // User opted to create a hybrid MBR....
// Create EFI protective partition that covers the start of the disk.
// If this location (covering the main GPT data structures) is omitted,
// Linux won't find any partitions on the disk.
@@ -459,7 +464,7 @@ void GPTDataTextUI::MakeHybrid(void) {
if (eeFirst == 'Y') {
hybridMBR.AddPart(0, hybridPart);
} else {
- hybridMBR.AddPart(numPartsToCvt, hybridPart);
+ hybridMBR.AddPart(numConverted, hybridPart);
} // else
hybridMBR.SetHybrid();
@@ -477,7 +482,9 @@ void GPTDataTextUI::MakeHybrid(void) {
} // if (GetYN() == 'Y')
} // if unused entry
protectiveMBR = hybridMBR;
- } // if (numPartsToCvt > 0)
+ } else {
+ cout << "\nNo partitions converted; original protective/hybrid MBR is unmodified!\n";
+ } // if/else (numConverted > 0)
} // GPTDataTextUI::MakeHybrid()
// Convert the GPT to MBR form, storing partitions in the protectiveMBR
@@ -494,6 +501,10 @@ int GPTDataTextUI::XFormToMBR(void) {
protectiveMBR.EmptyMBR(0);
for (i = 0; i < numParts; i++) {
if (partitions[i].IsUsed()) {
+ if (partitions[i].IsSizedForMBR() == MBR_SIZED_IFFY)
+ WarnAboutIffyMBRPart(i + 1);
+ // Note: MakePart() checks for oversized partitions, so don't
+ // bother checking other IsSizedForMBR() return values....
protectiveMBR.MakePart(i, partitions[i].GetFirstLBA(),
partitions[i].GetLengthLBA(),
partitions[i].GetHexType() / 0x0100, 0);
@@ -503,6 +514,24 @@ int GPTDataTextUI::XFormToMBR(void) {
return protectiveMBR.DoMenu();
} // GPTDataTextUI::XFormToMBR()
+/******************************************************
+ * *
+ * Display informational messages for the user.... *
+ * *
+ ******************************************************/
+
+// Although an MBR partition that begins below sector 2^32 and is less than 2^32 sectors in
+// length is technically legal even if it ends above the 2^32-sector mark, such a partition
+// tends to confuse a lot of OSes, so warn the user about such partitions. This function is
+// called by XFormToMBR() and MakeHybrid(); it's a separate function just to consolidate the
+// lengthy message in one place.
+void GPTDataTextUI::WarnAboutIffyMBRPart(int partNum) {
+ cout << "\a\nWarning! GPT partition " << partNum << " ends after the 2^32 sector mark! The partition\n"
+ << "begins before this point, and is smaller than 2^32 sectors. This is technically\n"
+ << "legal, but will confuse some OSes. The partition IS being added to the MBR, but\n"
+ << "if your OS misbehaves or can't see the partition, the partition may simply be\n"
+ << "unusable in that OS and may need to be resized or omitted from the MBR.\n\n";
+} // GPTDataTextUI::WarnAboutIffyMBRPart()
/*********************************************************************
* *
diff --git a/gpttext.h b/gpttext.h
index 111ca1f..385fa27 100644
--- a/gpttext.h
+++ b/gpttext.h
@@ -54,6 +54,9 @@ class GPTDataTextUI : public GPTData {
void MakeHybrid(void);
int XFormToMBR(void); // convert GPT to MBR, wiping GPT afterwards. Returns 1 if successful
+ // An informational function....
+ void WarnAboutIffyMBRPart(int partNum);
+
// Main menu functions
void MainMenu(string filename);
void ShowCommands(void);
diff --git a/support.h b/support.h
index 71fff50..d4286e7 100644
--- a/support.h
+++ b/support.h
@@ -8,7 +8,7 @@
#ifndef __GPTSUPPORT
#define __GPTSUPPORT
-#define GPTFDISK_VERSION "0.8.9.1"
+#define GPTFDISK_VERSION "0.8.9.2"
#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__)
// Darwin (Mac OS) & FreeBSD: disk IOCTLs are different, and there is no lseek64