A few minor changes.
diff --git a/Makefile b/Makefile
index 7f04243..06c576f 100644
--- a/Makefile
+++ b/Makefile
@@ -14,10 +14,10 @@
all: gdisk sgdisk fixparts
gdisk: $(LIB_OBJS) gdisk.o gpttext.o
- $(CXX) $(LIB_OBJS) gdisk.o gpttext.o $(LDFLAGS) -licui18n -licuio -luuid -o gdisk
+ $(CXX) $(LIB_OBJS) gdisk.o gpttext.o $(LDFLAGS) -licuio -luuid -o gdisk
sgdisk: $(LIB_OBJS) sgdisk.o
- $(CXX) $(LIB_OBJS) sgdisk.o $(LDFLAGS) -licui18n -licuio -luuid -lpopt -o sgdisk
+ $(CXX) $(LIB_OBJS) sgdisk.o $(LDFLAGS) -licuio -luuid -lpopt -o sgdisk
fixparts: $(MBR_LIB_OBJS) fixparts.o
$(CXX) $(MBR_LIB_OBJS) fixparts.o $(LDFLAGS) -o fixparts
diff --git a/Makefile.mac b/Makefile.mac
index c9fe488..3793624 100644
--- a/Makefile.mac
+++ b/Makefile.mac
@@ -12,11 +12,11 @@
all: gdisk sgdisk fixparts
-gdisk: $(LIB_OBJS) gpttext.o gdisk.o
- $(CXX) $(LIB_OBJS) gpttext.o gdisk.o -o gdisk
+gdisk: $(LIB_OBJS) gpttext.o gdisk.o
+ $(CXX) $(LIB_OBJS) -L/usr/local/lib -licuuc -licuio -licudata gpttext.o gdisk.o -o gdisk
sgdisk: $(LIB_OBJS) sgdisk.o
- $(CXX) $(LIB_OBJS) sgdisk.o -L/opt/local/lib -lpopt -o sgdisk
+ $(CXX) $(LIB_OBJS) sgdisk.o -L/opt/local/lib -L/usr/local/lib -licudata -licuio -licuuc -lpopt -o sgdisk
fixparts: $(MBR_LIB_OBJS) fixparts.o
$(CXX) $(MBR_LIB_OBJS) fixparts.o $(LDFLAGS) -o fixparts
diff --git a/NEWS b/NEWS
index 5827153..678b913 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,9 @@
0.7.1 (?/?/2011):
-----------------
+- Fixed bug that caused the protective MBR to not be written when
+ restoring a backup of the GPT data.
+
- Fixed bug that caused second protective MBR partition, when created
as part of a hybrid MBR, to always be of type 0xEE, even when the
user specified something else.
diff --git a/gdisk.cc b/gdisk.cc
index 35f7e9d..22de86b 100644
--- a/gdisk.cc
+++ b/gdisk.cc
@@ -293,7 +293,7 @@
// selects an exit command, such as 'w' or 'q'.
void ExpertsMenu(string filename, GPTDataTextUI* theGPT) {
GPTData secondDevice;
- uint32_t pn, temp1, temp2;
+ uint32_t temp1, temp2;
int goOn = 1;
string guidStr, device;
GUIDData aGUID;
@@ -311,17 +311,7 @@
cout << "No partitions\n";
break;
case 'c': case 'C':
- if (theGPT->GetPartRange(&temp1, &temp2) > 0) {
- pn = theGPT->GetPartNum();
- cout << "Enter the partition's new unique GUID ('R' to randomize): ";
- guidStr = ReadString();
- if ((guidStr.length() >= 32) || (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";
+ theGPT->ChangeUniqueGuid();
break;
case 'd': case 'D':
cout << "Partitions will begin on " << theGPT->GetAlignment()
diff --git a/gpt.cc b/gpt.cc
index bf99c6a..ea0a0a3 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -1140,6 +1140,7 @@
// Let the MBRData class load the saved MBR...
protectiveMBR.ReadMBRData(&backupFile, 0); // 0 = don't check block size
+ protectiveMBR.SetDisk(&myDisk);
LoadHeader(&mainHeader, backupFile, 1, &mainCrcOk);
@@ -1580,6 +1581,7 @@
<< "partition table size of " << numEntries
<< "; cannot resize. Perhaps sorting will help.\n";
allOK = 0;
+ delete[] newParts;
} else { // go ahead with copy
if (numEntries < numParts)
copyNum = numEntries;
@@ -2101,12 +2103,17 @@
return (isFree);
} // GPTData::IsFree()
-// Returns 1 if partNum is unused.
+// Returns 1 if partNum is unused AND if it's a legal value.
int GPTData::IsFreePartNum(uint32_t partNum) {
return ((partNum < numParts) && (partitions != NULL) &&
(!partitions[partNum].IsUsed()));
} // GPTData::IsFreePartNum()
+// Returns 1 if partNum is in use.
+int GPTData::IsUsedPartNum(uint32_t partNum) {
+ return ((partNum < numParts) && (partitions != NULL) &&
+ (partitions[partNum].IsUsed()));
+} // GPTData::IsUsedPartNum()
/***********************************************************
* *
@@ -2207,12 +2214,13 @@
// functions.
const GPTPart & GPTData::operator[](uint32_t partNum) const {
if (partNum >= numParts) {
- cerr << "Partition number out of range: " << partNum << "\n";
- partNum = 0;
- if ((numParts == 0) || (partitions == NULL)) {
- cerr << "No partitions defined in GPTData::operator[]; fatal error!\n";
- exit(1);
- } // if
+ cerr << "Partition number out of range (" << partNum << " requested, but only "
+ << numParts << " available)\n";
+ exit(1);
+ } // if
+ if (partitions == NULL) {
+ cerr << "No partitions defined in GPTData::operator[]; fatal error!\n";
+ exit(1);
} // if
return partitions[partNum];
} // operator[]
diff --git a/gpt.h b/gpt.h
index eb91bb3..41fa3d1 100644
--- a/gpt.h
+++ b/gpt.h
@@ -65,7 +65,7 @@
protected:
struct GPTHeader mainHeader;
GPTPart *partitions;
- uint32_t numParts;
+ uint32_t numParts; // # of partitions the table can hold
struct GPTHeader secondHeader;
MBRData protectiveMBR;
string device; // device filename
@@ -95,7 +95,6 @@
GPTData(string deviceFilename);
virtual ~GPTData(void);
GPTData & operator=(const GPTData & orig);
-// bool operator<(const GPTData &other) const;
// Verify (or update) data integrity
int Verify(void);
@@ -185,7 +184,8 @@
uint64_t FindFreeBlocks(uint32_t *numSegments, uint64_t *largestSegment);
int IsFree(uint64_t sector, uint32_t *partNum = NULL);
int IsFreePartNum(uint32_t partNum);
-
+ int IsUsedPartNum(uint32_t partNum);
+
// Change how functions work, or return information on same
void SetAlignment(uint32_t n);
uint32_t ComputeAlignment(void); // Set alignment based on current partitions
diff --git a/gpttext.cc b/gpttext.cc
index ff63be9..0b02672 100644
--- a/gpttext.cc
+++ b/gpttext.cc
@@ -271,6 +271,27 @@
} // if/else
} // GPTDataTextUI::ChangePartType()
+// Prompt user for a partition number, then change its unique
+// GUID.
+void GPTDataTextUI::ChangeUniqueGuid(void) {
+ int partNum;
+ uint32_t low, high;
+ string guidStr;
+
+ if (GetPartRange(&low, &high) > 0) {
+ partNum = GetPartNum();
+ cout << "Enter the partition's new unique GUID ('R' to randomize): ";
+ guidStr = ReadString();
+ if ((guidStr.length() >= 32) || (guidStr[0] == 'R') || (guidStr[0] == 'r')) {
+ SetPartitionGUID(partNum, (GUIDData) guidStr);
+ cout << "New GUID is " << partitions[partNum].GetUniqueGUID() << "\n";
+ } else {
+ cout << "GUID is too short!\n";
+ } // if/else
+ } else
+ cout << "No partitions\n";
+} // GPTDataTextUI::ChangeUniqueGuid()
+
// Partition attributes seem to be rarely used, but I want a way to
// adjust them for completeness....
void GPTDataTextUI::SetAttributes(uint32_t partNum) {
diff --git a/gpttext.h b/gpttext.h
index cb8f1e0..33b7486 100644
--- a/gpttext.h
+++ b/gpttext.h
@@ -45,6 +45,7 @@
void CreatePartition(void);
void DeletePartition(void);
void ChangePartType(void);
+ void ChangeUniqueGuid(void);
void SetAttributes(uint32_t partNum);
int SwapPartitions(void);
int DestroyGPTwPrompt(void); // Returns 1 if user proceeds
diff --git a/sgdisk.cc b/sgdisk.cc
index 802e49b..83cb663 100644
--- a/sgdisk.cc
+++ b/sgdisk.cc
@@ -48,7 +48,7 @@
uint64_t startSector, endSector;
uint64_t temp; // temporary variable; free to use in any case
char *attributeOperation = NULL;
- char *device = NULL;
+ char *device;
char *newPartInfo = NULL, *typeCode = NULL, *partName = NULL;
char *backupFile = NULL, *twoParts = NULL, *hybrids = NULL, *mbrParts;
char *partGUID = NULL, *diskGUID = NULL, *outDevice = NULL;
@@ -440,17 +440,21 @@
if ((&theGPT != NULL) && (argument != NULL)) {
numParts = CountColons(argument) + 1;
- cout << "numParts = " << numParts << "\n";
if (numParts <= (4 - isHybrid)) {
newMBR.SetDisk(theGPT.GetDisk());
for (i = 0; i < numParts; i++) {
origPartNum = GetInt(argument, i + 1) - 1;
- newPart.SetInclusion(PRIMARY);
- newPart.SetLocation(theGPT[origPartNum].GetFirstLBA(),
- theGPT[origPartNum].GetLengthLBA());
- newPart.SetStatus(0);
- newPart.SetType((uint8_t)(theGPT[origPartNum].GetHexType() / 0x0100));
- newMBR.AddPart(i + isHybrid, newPart);
+ if (theGPT.IsUsedPartNum(origPartNum)) {
+ newPart.SetInclusion(PRIMARY);
+ newPart.SetLocation(theGPT[origPartNum].GetFirstLBA(),
+ theGPT[origPartNum].GetLengthLBA());
+ newPart.SetStatus(0);
+ newPart.SetType((uint8_t)(theGPT[origPartNum].GetHexType() / 0x0100));
+ newMBR.AddPart(i + isHybrid, newPart);
+ } else {
+ cerr << "Partition " << origPartNum << " does not exist! Aborting operation!\n";
+ allOK = 0;
+ } // if/else
} // for
if (isHybrid) {
newPart.SetInclusion(PRIMARY);
diff --git a/support.cc b/support.cc
index 4e7c874..00c0e12 100644
--- a/support.cc
+++ b/support.cc
@@ -15,7 +15,6 @@
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
-#include <unicode/ustdio.h>
#include <string>
#include <iostream>
#include <sstream>
@@ -110,7 +109,9 @@
// 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 IeeeValue is empty, returns def.
-// Returns integral sector value.
+// Returns final sector value. In case inValue works out to something that
+// is not in the range of low to high (inclusive), returns high + 1; the
+// calling function is responsible for checking the validity of this value.
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;