Updates for version 0.4.2
New feature: Ability to edit disk images.
Several small bug fixes and feature enhancements (see CHANGELOG).
diff --git a/gpt.cc b/gpt.cc
index 9498a86..3b7f9d9 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -83,7 +83,7 @@
// do *NOT* recover from these problems. Returns the total number of
// problems identified.
int GPTData::Verify(void) {
- int problems = 0, numSegments, i, j;
+ int problems = 0, numSegments;
uint64_t totalFree, largestSegment;
char tempStr[255], siTotal[255], siLargest[255];
@@ -282,7 +282,7 @@
} // if/else/if
// If MBR bad, check for an Apple disk signature
- if ((protectiveMBR.GetValidity() == invalid) &&
+ if ((protectiveMBR.GetValidity() == invalid) &&
(((mainHeader.signature << 32) == APM_SIGNATURE1) ||
(mainHeader.signature << 32) == APM_SIGNATURE2)) {
apmFound = 1; // Will display warning message later
@@ -317,7 +317,7 @@
// byte order on big-endian systems) if any changes have been made.
void GPTData::RecomputeCRCs(void) {
uint32_t crc;
- uint32_t trueNumParts, crcTemp;
+ uint32_t trueNumParts;
int littleEndian = 1;
// Initialize CRC functions...
@@ -703,7 +703,7 @@
// Writes GPT (and protective MBR) to disk. Returns 1 on successful
// write, 0 if there was a problem.
int GPTData::SaveGPTData(void) {
- int allOK = 1, i, j;
+ int allOK = 1, i;
char answer, line[256];
int fd;
uint64_t secondTable;
@@ -806,27 +806,7 @@
// re-read the partition table
if (allOK) {
- sync();
-#ifdef __APPLE__
- printf("Warning: The kernel may continue to use old or deleted partitions.\n"
- "You should reboot or remove the drive.\n");
- /* don't know if this helps
- * it definitely will get things on disk though:
- * http://topiks.org/mac-os-x/0321278542/ch12lev1sec8.html */
- i = ioctl(fd, DKIOCSYNCHRONIZECACHE);
-#else
-#ifdef __FreeBSD__
- sleep(2);
- i = ioctl(fd, DIOCGFLUSH);
- printf("Warning: The kernel may still provide disk access using old partition IDs.\n");
-#else
- sleep(2);
- i = ioctl(fd, BLKRRPART);
- if (i)
- printf("Warning: The kernel is still using the old partition table.\n"
- "The new table will be used at the next reboot.\n");
-#endif
-#endif
+ DiskSync(fd);
} // if
if (allOK) { // writes completed OK
@@ -1035,7 +1015,7 @@
// Display the basic GPT data
void GPTData::DisplayGPTData(void) {
- int i, j;
+ int i;
char sizeInSI[255]; // String to hold size of disk in SI units
char tempStr[255];
uint64_t temp, totalFree;
@@ -1233,13 +1213,17 @@
// This function destroys the on-disk GPT structures. Returns 1 if the
// user confirms destruction, 0 if the user aborts.
int GPTData::DestroyGPT(void) {
- int fd, i, doMore;
+ int fd, i;
char blankSector[512], goOn;
for (i = 0; i < 512; i++) {
blankSector[i] = '\0';
} // for
+ if ((apmFound) || (bsdFound)) {
+ printf("WARNING: APM or BSD disklabel structures detected! This operation could\n"
+ "damage any APM or BSD partitions on this disk!\n");
+ } // if APM or BSD
printf("\a\aAbout to wipe out GPT on %s. Proceed? ", device);
goOn = GetYN();
if (goOn == 'Y') {
@@ -1265,7 +1249,16 @@
if (GetYN() == 'Y') {
lseek64(fd, 0, SEEK_SET);
write(fd, blankSector, 512); // blank it out
- } // if blank MBR
+ } else { // write current protective MBR, in case it's hybrid....
+ // find and delete 0xEE partitions in MBR
+ for (i = 0; i < 4; i++) {
+ if (protectiveMBR.GetType(i) == (uint8_t) 0xEE) {
+ protectiveMBR.DeletePartition(i);
+ } // if
+ } // for
+ protectiveMBR.WriteMBRData(fd);
+ } // if/else
+ DiskSync(fd);
close(fd);
printf("GPT data structures destroyed! You may now partition the disk using fdisk or\n"
"other utilities. Program will now terminate.\n");
@@ -1376,7 +1369,6 @@
int i, numToConvert;
uint8_t origType;
struct newGUID;
- char name[NAME_SIZE];
// Clear out old data & prepare basics....
ClearGPTData();
@@ -1391,7 +1383,7 @@
origType = protectiveMBR.GetType(i);
// don't waste CPU time trying to convert extended, hybrid protective, or
// null (non-existent) partitions
- if ((origType != 0x05) && (origType != 0x0f) && (origType != 0x85) &&
+ if ((origType != 0x05) && (origType != 0x0f) && (origType != 0x85) &&
(origType != 0x00) && (origType != 0xEE))
partitions[i] = protectiveMBR.AsGPT(i);
} // for
@@ -1509,7 +1501,8 @@
j = partNums[i] - 1;
printf("\nCreating entry for partition #%d\n", j + 1);
if ((j >= 0) && (j < mainHeader.numParts)) {
- if (partitions[j].GetLastLBA() < UINT32_MAX) {
+ if ((partitions[j].GetLastLBA() < UINT32_MAX) &&
+ (partitions[j].GetLastLBA() > UINT64_C(0))) {
do {
printf("Enter an MBR hex code (default %02X): ",
typeHelper.GUIDToID(partitions[j].GetType()) / 256);
@@ -1529,7 +1522,8 @@
(uint32_t) length, typeCode, bootable);
protectiveMBR.SetHybrid();
} else { // partition out of range
- printf("Partition %d ends beyond the 2TiB limit of MBR partitions; omitting it.\n",
+ printf("Partition %d ends beyond the 2TiB limit of MBR partitions or does not exist;\n"
+ "omitting it.\n",
j + 1);
} // if/else
} else {
@@ -1683,8 +1677,12 @@
// Set up data structures for entirely new set of partitions on the
// specified device. Returns 1 if OK, 0 if there were problems.
+// Note that this function does NOT clear the protectiveMBR data
+// structure, since it may hold the original MBR partitions if the
+// program was launched on an MBR disk, and those may need to be
+// converted to GPT format.
int GPTData::ClearGPTData(void) {
- int goOn, i;
+ int goOn = 1, i;
// Set up the partition table....
free(partitions);
@@ -1835,7 +1833,7 @@
// Finds the first available sector in the largest block of unallocated
// space on the disk. Returns 0 if there are no available blocks left
uint64_t GPTData::FindFirstInLargest(void) {
- uint64_t start, firstBlock, lastBlock, segmentSize, selectedSize = 0, selectedSegment;
+ uint64_t start, firstBlock, lastBlock, segmentSize, selectedSize = 0, selectedSegment = 0;
start = 0;
do {
@@ -1937,7 +1935,7 @@
isFree = 0;
} // if
} // for
- if ((sector < mainHeader.firstUsableLBA) ||
+ if ((sector < mainHeader.firstUsableLBA) ||
(sector > mainHeader.lastUsableLBA)) {
isFree = 0;
} // if