Changes to sector alignment policies and behavior when restoring a
backup fails
diff --git a/gpt.cc b/gpt.cc
index ac42995..a407d37 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -14,6 +14,7 @@
#include <stdint.h>
#include <fcntl.h>
#include <string.h>
+#include <math.h>
#include <time.h>
#include <sys/stat.h>
#include <errno.h>
@@ -641,6 +642,7 @@
if (allOK)
CheckGPTSize();
myDisk.Close();
+ ComputeAlignment();
} else {
allOK = 0;
} // if/else
@@ -1116,20 +1118,20 @@
if (!LoadPartitionTable(mainHeader, backupFile, (uint64_t) (3 - shortBackup)))
cerr << "Warning! Read error " << errno
<< " loading partition table; strange behavior now likely!\n";
-
} else {
allOK = 0;
} // if/else
+ // Something went badly wrong, so blank out partitions
+ if (allOK == 0) {
+ cerr << "Improper backup file! Clearing all partition data!\n";
+ ClearGPTData();
+ protectiveMBR.MakeProtectiveMBR();
+ } // if
} else {
allOK = 0;
cerr << "Unable to open file " << filename << " for reading! Aborting!\n";
} // if/else
- // Something went badly wrong, so blank out partitions
- if (allOK == 0) {
- ClearGPTData();
- protectiveMBR.MakeProtectiveMBR();
- } // if
return allOK;
} // GPTData::LoadGPTBackup()
@@ -2123,6 +2125,60 @@
return retval;
} // GPTData::IsFreePartNum()
+
+/***********************************************************
+ * *
+ * Change how functions work or return information on them *
+ * *
+ ***********************************************************/
+
+// Set partition alignment value; partitions will begin on multiples of
+// the specified value
+void GPTData::SetAlignment(uint32_t n) {
+ uint32_t l2;
+
+ sectorAlignment = n;
+ l2 = (uint32_t) log2(n);
+ if (PowerOf2(l2) != n)
+ cout << "Information: Your alignment value is not a power of 2.\n";
+} // GPTData::SetAlignment()
+
+// Compute sector alignment based on the current partitions (if any). Each
+// partition's starting LBA is examined, and if it's divisible by a power-of-2
+// value less than the maximum found so far (or 2^31 for the first partition
+// found), then the alignment value is adjusted down. If the computed
+// alignment is less than 8 and the disk is bigger than SMALLEST_ADVANCED_FORMAT,
+// resets it to 8. This is a safety measure for WD Advanced Format and
+// similar drives. If no partitions are defined, the alignment value is set
+// to DEFAULT_ALIGNMENT (2048). The result is that new drives are aligned to
+// 2048-sector multiples but the program won't complain about other alignments
+// on existing disks unless a smaller-than-8 alignment is used on small disks
+// (as safety for WD Advanced Format drives).
+// Returns the computed alignment value.
+uint32_t GPTData::ComputeAlignment(void) {
+ uint32_t i = 0, found, exponent = 31;
+ uint64_t align = DEFAULT_ALIGNMENT;
+
+ for (i = 0; i < mainHeader.numParts; i++) {
+ if (partitions[i].IsUsed()) {
+ found = 0;
+ while (!found) {
+ align = PowerOf2(exponent);
+ if ((partitions[i].GetFirstLBA() % align) == 0) {
+ found = 1;
+ } else {
+ exponent--;
+ } // if/else
+ } // while
+ } // if
+ } // for
+ if ((align < 8) && (diskSize >= SMALLEST_ADVANCED_FORMAT))
+ align = 8;
+// cout << "Setting alignment to " << align << "\n";
+ SetAlignment(align);
+ return align;
+} // GPTData::ComputeAlignment()
+
/********************************
* *
* Endianness support functions *