summaryrefslogtreecommitdiff
path: root/mbr.cc
diff options
context:
space:
mode:
authorsrs5694 <srs5694@users.sourceforge.net>2009-08-31 10:13:04 -0400
committersrs5694 <srs5694@users.sourceforge.net>2009-08-31 10:13:04 -0400
commite4ac11ebee0ad586a538f49b9c0e32ad19cae665 (patch)
tree63b482ab258c59aba571032ad095eefa87fc8759 /mbr.cc
parent221e08768de7fe42ba533ca22baf671420569c07 (diff)
downloadsgdisk-e4ac11ebee0ad586a538f49b9c0e32ad19cae665.tar.gz
Updated to version 0.4.1
Adds relative partition sizing and placement options for both start and end sectors; improves hybrid MBR synchronization (deletes matching MBR partition when a GPT partition is deleted, warns about inconsistencies when verifying or writing a partition table).
Diffstat (limited to 'mbr.cc')
-rw-r--r--mbr.cc90
1 files changed, 89 insertions, 1 deletions
diff --git a/mbr.cc b/mbr.cc
index b4bc6f4..28745b3 100644
--- a/mbr.cc
+++ b/mbr.cc
@@ -496,6 +496,61 @@ int MBRData::MakeBiggestPart(int i, int type) {
return found;
} // MBRData::MakeBiggestPart(int i)
+// Delete a partition if one exists at the specified location.
+// Returns 1 if a partition was deleted, 0 otherwise....
+// Used to help keep GPT & hybrid MBR partitions in sync....
+int MBRData::DeleteByLocation(uint64_t start64, uint64_t length64) {
+ uint32_t start32, length32;
+ int i, j, deleted = 0;
+
+ if ((state == hybrid) && (start64 < UINT32_MAX) && (length64 < UINT32_MAX)) {
+ start32 = (uint32_t) start64;
+ length32 = (uint32_t) length64;
+ for (i = 0; i < 4; i++) {
+ if ((partitions[i].firstLBA == start32) && (partitions[i].lengthLBA = length32) &&
+ (partitions[i].partitionType != 0xEE)) {
+ partitions[i].firstLBA = UINT32_C(0);
+ partitions[i].lengthLBA = UINT32_C(0);
+ partitions[i].status = UINT8_C(0);
+ partitions[i].partitionType = UINT8_C(0);
+ for (j = 0; j < 3; j++) {
+ partitions[i].firstSector[j] = UINT8_C(0);
+ partitions[i].lastSector[j] = UINT8_C(0);
+ } // for j (CHS data blanking)
+ OptimizeEESize();
+ deleted = 1;
+ } // if (match found)
+ } // for i (partition scan)
+ } // if (hybrid & GPT partition < 2TiB)
+ return deleted;
+} // MBRData::DeleteByLocation()
+
+// Optimizes the size of the 0xEE (EFI GPT) partition
+void MBRData::OptimizeEESize(void) {
+ int i, typeFlag = 0;
+ uint32_t after;
+
+ for (i = 0; i < 4; i++) {
+ // Check for non-empty and non-0xEE partitions
+ if ((partitions[i].partitionType != 0xEE) && (partitions[i].partitionType != 0x00))
+ typeFlag++;
+ if (partitions[i].partitionType == 0xEE) {
+ // Blank space before this partition; fill it....
+ if (IsFree(partitions[i].firstLBA - 1)) {
+ partitions[i].firstLBA = FindFirstInFree(partitions[i].firstLBA - 1);
+ } // if
+ // Blank space after this partition; fill it....
+ after = partitions[i].firstLBA + partitions[i].lengthLBA;
+ if (IsFree(after)) {
+ partitions[i].lengthLBA = FindLastInFree(after) - partitions[i].firstLBA + 1;
+ } // if free space after
+ } // if partition is 0xEE
+ if (typeFlag == 0) { // No non-hybrid partitions found
+ MakeProtectiveMBR(); // ensure it's a fully compliant hybrid MBR.
+ } // if
+ } // for partition loop
+} // MBRData::OptimizeEESize()
+
// Return a pointer to a primary or logical partition, or NULL if
// the partition is out of range....
struct MBRRecord* MBRData::GetPartition(int i) {
@@ -582,6 +637,7 @@ uint32_t MBRData::FindFirstAvailable(uint32_t start) {
return (first);
} // MBRData::FindFirstAvailable()
+// Finds the last free sector on the disk from start forward.
uint32_t MBRData::FindLastInFree(uint32_t start) {
uint32_t nearestStart;
uint32_t i;
@@ -597,7 +653,39 @@ uint32_t MBRData::FindLastInFree(uint32_t start) {
} // if
} // for
return (nearestStart);
-} // MBRData::FindLastInFree
+} // MBRData::FindLastInFree()
+
+// Finds the first free sector on the disk from start backward.
+uint32_t MBRData::FindFirstInFree(uint32_t start) {
+ uint32_t nearestStart, bestLastLBA, thisLastLBA;
+ int i;
+
+ bestLastLBA = 1;
+ for (i = 0; i < 4; i++) {
+ thisLastLBA = partitions[i].firstLBA + partitions[i].lengthLBA;
+ if (thisLastLBA > 0) thisLastLBA--;
+ if ((thisLastLBA > bestLastLBA) && (thisLastLBA < start)) {
+ bestLastLBA = thisLastLBA + 1;
+ } // if
+ } // for
+ return (bestLastLBA);
+} // MBRData::FindFirstInFree()
+
+// Returns 1 if the specified sector is unallocated, 0 if it's
+// allocated.
+int MBRData::IsFree(uint32_t sector) {
+ int i, isFree = 1;
+ uint32_t first, last;
+
+ for (i = 0; i < 4; i++) {
+ first = partitions[i].firstLBA;
+ last = first + partitions[i].lengthLBA;
+ if (last > 0) last--;
+ if ((first <= sector) && (last >= sector))
+ isFree = 0;
+ } // for
+ return isFree;
+} // MBRData::IsFree()
uint8_t MBRData::GetStatus(int i) {
MBRRecord* thePart;