aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsrs5694 <srs5694@users.sourceforge.net>2009-11-26 18:36:12 -0500
committersrs5694 <srs5694@users.sourceforge.net>2009-11-26 18:36:12 -0500
commit247657a5acbb7eb21c336ba84a68b801b7c19be0 (patch)
treec25a6a4c080352690e5c783d3f26f55f6df72f3f
parent3f2fe99e72648aefc926138132d48efb07a7ad2d (diff)
downloadgptfdisk-247657a5acbb7eb21c336ba84a68b801b7c19be0.tar.gz
0.5.1-pre3; more bug fixes related to handling of mislocated secondary
header and partition table.
-rw-r--r--CHANGELOG4
-rw-r--r--gdisk.cc4
-rw-r--r--gpt.cc111
-rw-r--r--gpt.h2
-rw-r--r--support.cc3
5 files changed, 73 insertions, 51 deletions
diff --git a/CHANGELOG b/CHANGELOG
index c853e5b..9667715 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -13,6 +13,10 @@
- Added 'e' option (relocate backup GPT data structures) to the experts'
menu.
+- Fixed bug that prevented recovery of partitions in case of partially
+ damaged GPT data (bad main and good backup or bad backup and good
+ main header, for instance).
+
0.5.0:
------
diff --git a/gdisk.cc b/gdisk.cc
index ef42ea8..bfee217 100644
--- a/gdisk.cc
+++ b/gdisk.cc
@@ -29,7 +29,7 @@ int main(int argc, char* argv[]) {
int doMore = 1;
char* device = NULL;
- printf("GPT fdisk (gdisk) version 0.5.1-pre2\n\n");
+ printf("GPT fdisk (gdisk) version 0.5.1-pre3\n\n");
if (argc == 2) { // basic usage
if (SizesOK()) {
@@ -311,7 +311,7 @@ void ExpertsMenu(char* filename, struct GPTData* theGPT) {
break;
case 'e': case 'E':
printf("Relocating backup data structures to the end of the disk\n");
- theGPT->FixSecondHeaderLocation();
+ theGPT->MoveSecondHeaderToEnd();
break;
case 'g': case 'G':
printf("Enter the disk's unique GUID:\n");
diff --git a/gpt.cc b/gpt.cc
index f339a72..2e99714 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -124,8 +124,8 @@ int GPTData::Verify(void) {
problems++;
printf("\nProblem: The secondary header's self-pointer indicates that it doesn't reside\n"
"at the end of the disk. If you've added a disk to a RAID array, use the 'e'\n"
- "option on the experts' menu to adjust the secondary header's and partition"
- "table's locations.");
+ "option on the experts' menu to adjust the secondary header's and partition\n"
+ "table's locations.\n");
} // if
// Now check that critical main and backup GPT entries match each other
@@ -676,7 +676,7 @@ int GPTData::ForceLoadGPTData(int fd) {
return allOK;
} // GPTData::ForceLoadGPTData()
-// Loads the partition tables pointed to by the main GPT header. The
+// Loads the partition table pointed to by the main GPT header. The
// main GPT header in memory MUST be valid for this call to do anything
// sensible!
int GPTData::LoadMainTable(void) {
@@ -753,12 +753,24 @@ int GPTData::SaveGPTData(void) {
// Check that disk is really big enough to handle this...
if (mainHeader.backupLBA > diskSize) {
- fprintf(stderr, "Error! Disk is too small -- either the original MBR is corrupt or you're\n");
- fprintf(stderr, "working from an MBR copied to a file! Aborting!\n");
+ fprintf(stderr, "Error! Disk is too small! The 'e' option on the experts' menu might fix the\n"
+ "problem (or it might not). Aborting!\n");
printf("(Disk size is %ld sectors, needs to be %ld sectors.)\n", diskSize,
mainHeader.backupLBA);
allOK = 0;
} // if
+ // Check that second header is properly placed. Warn and ask if this should
+ // be corrected if the test fails....
+ if (mainHeader.backupLBA < (diskSize - UINT64_C(1))) {
+ printf("Warning! Secondary header is placed too early on the disk! Do you want to\n"
+ "correct this problem? ");
+ if (GetYN() == 'Y') {
+ MoveSecondHeaderToEnd();
+ printf("Have moved second header and partition table to correct location.\n");
+ } else {
+ printf("Have not corrected the problem. Strange problems may occur in the future!\n");
+ } // if correction requested
+ } // if
// Check for overlapping partitions....
if (FindOverlaps() > 0) {
@@ -988,10 +1000,7 @@ int GPTData::LoadGPTBackup(char* filename) {
if (secondHeader.currentLBA != diskSize - UINT64_C(1)) {
printf("Warning! Current disk size doesn't match that of the backup!\n"
"Adjusting sizes to match, but subsequent problems are possible!\n");
- secondHeader.currentLBA = mainHeader.backupLBA = diskSize - UINT64_C(1);
- mainHeader.lastUsableLBA = diskSize - mainHeader.firstUsableLBA;
- secondHeader.lastUsableLBA = mainHeader.lastUsableLBA;
- secondHeader.partitionEntriesLBA = secondHeader.lastUsableLBA + UINT64_C(1);
+ MoveSecondHeaderToEnd();
} // if
// Load main partition table, and record whether its CRC
@@ -1398,6 +1407,7 @@ WhichToUse GPTData::UseWhichPartitions(void) {
"Caution: Found protective or hybrid MBR and corrupt GPT. Using GPT, but disk\n"
"verification and recovery are STRONGLY recommended.\n"
"****************************************************************************\n");
+ which = use_gpt;
} // if/else/else
} // if (corrupt GPT)
@@ -1703,42 +1713,47 @@ int GPTData::SetGPTSize(uint32_t numEntries) {
printf("to %lu to fill the sector\n", (unsigned long) numEntries);
} // if
- newParts = (GPTPart*) calloc(numEntries, sizeof (GPTPart));
- if (newParts != NULL) {
- if (partitions != NULL) { // existing partitions; copy them over
- GetPartRange(&i, &high);
- if (numEntries < (high + 1)) { // Highest entry too high for new #
- printf("The highest-numbered partition is %lu, which is greater than the requested\n"
- "partition table size of %d; cannot resize. Perhaps sorting will help.\n",
- (unsigned long) (high + 1), numEntries);
- allOK = 0;
- } else { // go ahead with copy
- if (numEntries < mainHeader.numParts)
- copyNum = numEntries;
- else
- copyNum = mainHeader.numParts;
- for (i = 0; i < copyNum; i++) {
- newParts[i] = partitions[i];
- } // for
- trash = partitions;
+ // Do the work only if the # of partitions is changing. Along with being
+ // efficient, this prevents mucking the with location of the secondary
+ // partition table, which causes problems when loading data from a RAID
+ // array that's been expanded because this function is called when loading
+ // data.
+ if ((numEntries != mainHeader.numParts) || (partitions == NULL)) {
+ newParts = (GPTPart*) calloc(numEntries, sizeof (GPTPart));
+ if (newParts != NULL) {
+ if (partitions != NULL) { // existing partitions; copy them over
+ GetPartRange(&i, &high);
+ if (numEntries < (high + 1)) { // Highest entry too high for new #
+ printf("The highest-numbered partition is %lu, which is greater than the requested\n"
+ "partition table size of %d; cannot resize. Perhaps sorting will help.\n",
+ (unsigned long) (high + 1), numEntries);
+ allOK = 0;
+ } else { // go ahead with copy
+ if (numEntries < mainHeader.numParts)
+ copyNum = numEntries;
+ else
+ copyNum = mainHeader.numParts;
+ for (i = 0; i < copyNum; i++) {
+ newParts[i] = partitions[i];
+ } // for
+ trash = partitions;
+ partitions = newParts;
+ free(trash);
+ } // if
+ } else { // No existing partition table; just create it
partitions = newParts;
- free(trash);
- } // if
- } else { // No existing partition table; just create it
- partitions = newParts;
- } // if/else existing partitions
- mainHeader.numParts = numEntries;
- secondHeader.numParts = numEntries;
- mainHeader.firstUsableLBA = ((numEntries * GPT_SIZE) / blockSize) + 2 ;
- secondHeader.firstUsableLBA = mainHeader.firstUsableLBA;
- mainHeader.lastUsableLBA = diskSize - mainHeader.firstUsableLBA;
- secondHeader.lastUsableLBA = mainHeader.lastUsableLBA;
- secondHeader.partitionEntriesLBA = secondHeader.lastUsableLBA + UINT64_C(1);
- if (diskSize > 0)
- CheckGPTSize();
- } else { // Bad memory allocation
- fprintf(stderr, "Error allocating memory for partition table!\n");
- allOK = 0;
+ } // if/else existing partitions
+ mainHeader.numParts = numEntries;
+ secondHeader.numParts = numEntries;
+ mainHeader.firstUsableLBA = ((numEntries * GPT_SIZE) / blockSize) + 2 ;
+ secondHeader.firstUsableLBA = mainHeader.firstUsableLBA;
+ MoveSecondHeaderToEnd();
+ if (diskSize > 0)
+ CheckGPTSize();
+ } else { // Bad memory allocation
+ fprintf(stderr, "Error allocating memory for partition table!\n");
+ allOK = 0;
+ } // if/else
} // if/else
return (allOK);
} // GPTData::SetGPTSize()
@@ -1832,9 +1847,11 @@ int GPTData::ClearGPTData(void) {
return (goOn);
} // GPTData::ClearGPTData()
-// Set the location of the second GPT header data to the correct location.
-// Intended to help users of RAID arrays that have been resized.
-void GPTData::FixSecondHeaderLocation() {
+// Set the location of the second GPT header data to the end of the disk.
+// Used internally and called by the 'e' option on the recovery &
+// transformation menu, to help users of RAID arrays who add disk space
+// to their arrays.
+void GPTData::MoveSecondHeaderToEnd() {
mainHeader.backupLBA = secondHeader.currentLBA = diskSize - UINT64_C(1);
mainHeader.lastUsableLBA = secondHeader.lastUsableLBA = diskSize - mainHeader.firstUsableLBA;
secondHeader.partitionEntriesLBA = secondHeader.lastUsableLBA + UINT64_C(1);
diff --git a/gpt.h b/gpt.h
index c265169..f22bd61 100644
--- a/gpt.h
+++ b/gpt.h
@@ -127,7 +127,7 @@ public:
void BlankPartitions(void);
void SortGPT(void);
int ClearGPTData(void);
- void FixSecondHeaderLocation();
+ void MoveSecondHeaderToEnd();
void SetName(uint32_t partNum, char* theName = NULL);
void SetDiskGUID(GUIDData newGUID);
int SetPartitionGUID(uint32_t pn, GUIDData theGUID);
diff --git a/support.cc b/support.cc
index 337dfce..bb419ed 100644
--- a/support.cc
+++ b/support.cc
@@ -480,6 +480,7 @@ uint64_t disksize(int fd, int *err) {
sectors = bytes / UINT64_C(512);
} // if
} // if
-// printf("In disksize(), sectors is %lld.\n", sectors);
+// sectors = 25000000;
+// printf("Returning bogus sector size: %d\n", sectors);
return sectors;
}