GPT fdisk 0.5.0
Added several features, including a restructuring of the menu system,
GPT-to-MBR conversion, and the ability to re-read the MBR to generate
a fresh GPT from the current on-disk MBR.
diff --git a/gdisk.cc b/gdisk.cc
index dcc2c51..a69d3b4 100644
--- a/gdisk.cc
+++ b/gdisk.cc
@@ -17,25 +17,27 @@
// Function prototypes....
// int ReadPartitions(char* filename, struct GPTData* theGPT);
-int DoCommand(char* filename, struct GPTData* theGPT);
+void MainMenu(char* filename, struct GPTData* theGPT);
void ShowCommands(void);
+void ExpertsMenu(char* filename, struct GPTData* theGPT);
void ShowExpertCommands(void);
-int ExpertsMenu(char* filename, struct GPTData* theGPT);
+void RecoveryMenu(char* filename, struct GPTData* theGPT);
+void ShowRecoveryCommands(void);
int main(int argc, char* argv[]) {
GPTData theGPT;
int doMore = 1;
char* device = NULL;
- printf("GPT fdisk (gdisk) version 0.4.2\n\n");
+ printf("GPT fdisk (gdisk) version 0.5.0\n\n");
if (argc == 2) { // basic usage
if (SizesOK()) {
doMore = theGPT.LoadPartitions(argv[1]);
- while (doMore) {
- doMore = DoCommand(argv[1], &theGPT);
- } // while
- } // if
+ if (doMore) {
+ MainMenu(argv[1], &theGPT);
+ } // if (doMore)
+ } // if (SizesOK())
} else if (argc == 3) { // usage with "-l" option
if (SizesOK()) {
if (strcmp(argv[1], "-l") == 0) {
@@ -55,112 +57,242 @@
} // if/else
} // main
-// Accept a command and execute it. Returns 0 if the command includes
-// an exit condition (such as a q or w command), 1 if more commands
-// should be processed.
-int DoCommand(char* filename, struct GPTData* theGPT) {
- char command, line[255];
- int retval = 1;
+// Accept a command and execute it. Returns only when the user
+// wants to exit (such as after a 'w' or 'q' command).
+void MainMenu(char* filename, struct GPTData* theGPT) {
+ char command, line[255], buFile[255];
+ int goOn = 1;
PartTypes typeHelper;
uint32_t temp1, temp2;
- printf("\nCommand (m for help): ");
- fgets(line, 255, stdin);
- sscanf(line, "%c", &command);
- switch (command) {
- case 'b': case 'B':
- theGPT->XFormDisklabel();
- break;
- case 'c': case 'C':
- if (theGPT->GetPartRange(&temp1, &temp2) > 0)
- theGPT->SetName(theGPT->GetPartNum());
- else
- printf("No partitions\n");
- break;
- case 'd': case 'D':
- theGPT->DeletePartition();
- break;
- case 'i': case 'I':
- theGPT->ShowDetails();
- break;
- case 'l': case 'L':
- typeHelper.ShowTypes();
- break;
- case 'n': case 'N':
- theGPT->CreatePartition();
- break;
- case 'o': case 'O':
- printf("This option deletes all partitions and creates a new "
- "protective MBR.\nProceed? ");
- if (GetYN() == 'Y') {
- theGPT->ClearGPTData();
- theGPT->MakeProtectiveMBR();
- } // if
- break;
- case 'p': case 'P':
- theGPT->DisplayGPTData();
- break;
- case 'q': case 'Q':
- retval = 0;
- break;
- case 's': case 'S':
- theGPT->SortGPT();
- printf("You may need to edit /etc/fstab and/or your boot loader configuration!\n");
- break;
- case 't': case 'T':
- theGPT->ChangePartType();
- break;
- case 'v': case 'V':
- if (theGPT->Verify() > 0) { // problems found
- printf("You may be able to correct the problems by using options on the experts\n"
- "menu (press 'x' at the command prompt). Good luck!\n");
- } // if
- break;
- case 'w': case 'W':
- if (theGPT->SaveGPTData() == 1)
- retval = 0;
- break;
- case 'x': case 'X':
- retval = ExpertsMenu(filename, theGPT);
- break;
- default:
- ShowCommands();
- break;
- } // switch
- return (retval);
-} // DoCommand()
+ do {
+ printf("\nCommand (? for help): ");
+ fgets(line, 255, stdin);
+ sscanf(line, "%c", &command);
+ switch (command) {
+ case 'b': case 'B':
+ printf("Enter backup filename to save: ");
+ fgets(line, 255, stdin);
+ sscanf(line, "%s", &buFile);
+ theGPT->SaveGPTBackup(buFile);
+ break;
+ case 'c': case 'C':
+ if (theGPT->GetPartRange(&temp1, &temp2) > 0)
+ theGPT->SetName(theGPT->GetPartNum());
+ else
+ printf("No partitions\n");
+ break;
+ case 'd': case 'D':
+ theGPT->DeletePartition();
+ break;
+ case 'i': case 'I':
+ theGPT->ShowDetails();
+ break;
+ case 'l': case 'L':
+ typeHelper.ShowTypes();
+ break;
+ case 'n': case 'N':
+ theGPT->CreatePartition();
+ break;
+ case 'o': case 'O':
+ printf("This option deletes all partitions and creates a new "
+ "protective MBR.\nProceed? ");
+ if (GetYN() == 'Y') {
+ theGPT->ClearGPTData();
+ theGPT->MakeProtectiveMBR();
+ } // if
+ break;
+ case 'p': case 'P':
+ theGPT->DisplayGPTData();
+ break;
+ case 'q': case 'Q':
+ goOn = 0;
+ break;
+ case 'r': case 'R':
+ RecoveryMenu(filename, theGPT);
+ goOn = 0;
+ break;
+ case 's': case 'S':
+ theGPT->SortGPT();
+ printf("You may need to edit /etc/fstab and/or your boot loader configuration!\n");
+ break;
+ case 't': case 'T':
+ theGPT->ChangePartType();
+ break;
+ case 'v': case 'V':
+ if (theGPT->Verify() > 0) { // problems found
+ printf("You may be able to correct the problems by using options on the experts\n"
+ "menu (press 'x' at the command prompt). Good luck!\n");
+ } // if
+ break;
+ case 'w': case 'W':
+ if (theGPT->SaveGPTData() == 1)
+ goOn = 0;
+ break;
+ case 'x': case 'X':
+ ExpertsMenu(filename, theGPT);
+ goOn = 0;
+ break;
+ default:
+ ShowCommands();
+ break;
+ } // switch
+ } while (goOn);
+} // MainMenu()
void ShowCommands(void) {
- printf("b\tconvert BSD disklabel partitions\n");
+ printf("b\tback up GPT data to a file\n");
printf("c\tchange a partition's name\n");
printf("d\tdelete a partition\n");
printf("i\tshow detailed information on a partition\n");
- printf("l\tlist available partition types\n");
- printf("m\tprint this menu\n");
+ printf("l\tlist known partition types\n");
printf("n\tadd a new partition\n");
printf("o\tcreate a new empty GUID partition table (GPT)\n");
printf("p\tprint the partition table\n");
printf("q\tquit without saving changes\n");
+ printf("r\trecovery and transformation options (experts only)\n");
printf("s\tsort partitions\n");
printf("t\tchange a partition's type code\n");
printf("v\tverify disk\n");
printf("w\twrite table to disk and exit\n");
printf("x\textra functionality (experts only)\n");
+ printf("?\tprint this menu\n");
} // ShowCommands()
-// Accept a command and execute it. Returns 0 if the command includes
-// an exit condition (such as a q or w command), 1 if more commands
-// should be processed.
-int ExpertsMenu(char* filename, struct GPTData* theGPT) {
+// Accept a recovery & transformation menu command. Returns only when the user
+// issues an exit command, such as 'w' or 'q'.
+void RecoveryMenu(char* filename, struct GPTData* theGPT) {
char command, line[255], buFile[255];
- int retval = 1;
+ PartTypes typeHelper;
+ uint32_t temp1;
+ int goOn = 1;
+
+ do {
+ printf("\nrecovery/transformation command (? for help): ");
+ fgets(line, 255, stdin);
+ sscanf(line, "%c", &command);
+ switch (command) {
+ case 'b': case 'B':
+ theGPT->RebuildMainHeader();
+ break;
+ case 'c': case 'C':
+ printf("Warning! This will probably do weird things if you've converted an MBR to\n"
+ "GPT form and haven't yet saved the GPT! Proceed? ");
+ if (GetYN() == 'Y')
+ theGPT->LoadSecondTableAsMain();
+ break;
+ case 'd': case 'D':
+ theGPT->RebuildSecondHeader();
+ break;
+ case 'e': case 'E':
+ printf("Warning! This will probably do weird things if you've converted an MBR to\n"
+ "GPT form and haven't yet saved the GPT! Proceed? ");
+ if (GetYN() == 'Y')
+ theGPT->LoadMainTable();
+ break;
+ case 'f': case 'F':
+ printf("Warning! This will destroy the currently defined partitions! Proceed? ");
+ if (GetYN() == 'Y') {
+ if (theGPT->LoadMBR(filename) == 1) { // successful load
+ theGPT->XFormPartitions();
+ } else {
+ printf("Problem loading MBR! GPT is untouched; regenerating protective MBR!\n");
+ theGPT->MakeProtectiveMBR();
+ } // if/else
+ } // if
+ break;
+ case 'g': case 'G':
+ temp1 = theGPT->XFormToMBR();
+ if (temp1 > 0) {
+ printf("Converted %d partitions. Finalize and exit? ", temp1);
+ if (GetYN() == 'Y') {
+ if (theGPT->DestroyGPT(0) > 0)
+ goOn = 0;
+ } else {
+ theGPT->MakeProtectiveMBR();
+ printf("Note: New protective MBR created.\n");
+ } // if/else
+ } // if
+ break;
+ case 'h': case 'H':
+ theGPT->MakeHybrid();
+ break;
+ case 'i': case 'I':
+ theGPT->ShowDetails();
+ break;
+ case 'l': case 'L':
+ printf("Enter backup filename to load: ");
+ fgets(line, 255, stdin);
+ sscanf(line, "%s", &buFile);
+ theGPT->LoadGPTBackup(buFile);
+ break;
+ case 'm': case 'M':
+ MainMenu(filename, theGPT);
+ goOn = 0;
+ break;
+ case 'o': case 'O':
+ theGPT->DisplayMBRData();
+ break;
+ case 'p': case 'P':
+ theGPT->DisplayGPTData();
+ break;
+ case 'q': case 'Q':
+ goOn = 0;
+ break;
+ case 't': case 'T':
+ theGPT->XFormDisklabel();
+ break;
+ case 'v': case 'V':
+ theGPT->Verify();
+ break;
+ case 'w': case 'W':
+ if (theGPT->SaveGPTData() == 1) {
+ goOn = 0;
+ } // if
+ break;
+ case 'x': case 'X':
+ ExpertsMenu(filename, theGPT);
+ goOn = 0;
+ break;
+ default:
+ ShowRecoveryCommands();
+ break;
+ } // switch
+ } while (goOn);
+} // RecoveryMenu()
+
+void ShowRecoveryCommands(void) {
+ printf("b\tuse backup GPT header (rebuilding main)\n");
+ printf("c\tload backup partition table from disk (rebuilding main)\n");
+ printf("d\tuse main GPT header (rebuilding backup)\n");
+ printf("e\tload main partition table from disk (rebuilding backup)\n");
+ printf("f\tload MBR and build fresh GPT from it\n");
+ printf("g\tconvert GPT into MBR and exit\n");
+ printf("h\tmake hybrid MBR\n");
+ printf("i\tshow detailed information on a partition\n");
+ printf("l\tload partition data from a backup file\n");
+ printf("m\treturn to main menu\n");
+ printf("o\tprint protective MBR data\n");
+ printf("p\tprint the partition table\n");
+ printf("q\tquit without saving changes\n");
+ printf("t\ttransform BSD disklabel partition\n");
+ printf("v\tverify disk\n");
+ printf("w\twrite table to disk and exit\n");
+ printf("x\textra functionality (experts only)\n");
+ printf("?\tprint this menu\n");
+} // ShowRecoveryCommands()
+
+// Accept an experts' menu command. Returns only after the user
+// selects an exit command, such as 'w' or 'q'.
+void ExpertsMenu(char* filename, struct GPTData* theGPT) {
+ char command, line[255];
PartTypes typeHelper;
uint32_t pn;
uint32_t temp1, temp2;
int goOn = 1;
do {
- printf("\nExpert command (m for help): ");
+ printf("\nExpert command (? for help): ");
fgets(line, 255, stdin);
sscanf(line, "%c", &command);
switch (command) {
@@ -170,25 +302,7 @@
else
printf("No partitions\n");
break;
- case 'b': case 'B':
- theGPT->RebuildMainHeader();
- break;
case 'c': case 'C':
- printf("Warning! This will probably do weird things if you've converted an MBR to\n"
- "GPT form and haven't yet saved the GPT! Proceed? ");
- if (GetYN() == 'Y')
- theGPT->LoadSecondTableAsMain();
- break;
- case 'd': case 'D':
- theGPT->RebuildSecondHeader();
- break;
- case 'e': case 'E':
- printf("Warning! This will probably do weird things if you've converted an MBR to\n"
- "GPT form and haven't yet saved the GPT! Proceed? ");
- if (GetYN() == 'Y')
- theGPT->LoadMainTable();
- break;
- case 'f': case 'F':
if (theGPT->GetPartRange(&temp1, &temp2) > 0) {
pn = theGPT->GetPartNum();
printf("Enter the partition's new unique GUID:\n");
@@ -199,23 +313,12 @@
printf("Enter the disk's unique GUID:\n");
theGPT->SetDiskGUID(GetGUID());
break;
- case 'h': case 'H':
- theGPT->MakeHybrid();
- break;
case 'i': case 'I':
theGPT->ShowDetails();
break;
- case 'k': case 'K':
- printf("Enter backup filename to save: ");
- fgets(line, 255, stdin);
- sscanf(line, "%s", &buFile);
- theGPT->SaveGPTBackup(buFile);
- break;
- case 'l': case 'L':
- printf("Enter backup filename to load: ");
- fgets(line, 255, stdin);
- sscanf(line, "%s", &buFile);
- theGPT->LoadGPTBackup(buFile);
+ case 'm': case 'M':
+ MainMenu(filename, theGPT);
+ goOn = 0;
break;
case 'n': case 'N':
theGPT->MakeProtectiveMBR();
@@ -227,10 +330,10 @@
theGPT->DisplayGPTData();
break;
case 'q': case 'Q':
- retval = 0;
goOn = 0;
break;
case 'r': case 'R':
+ RecoveryMenu(filename, theGPT);
goOn = 0;
break;
case 's': case 'S':
@@ -241,14 +344,12 @@
break;
case 'w': case 'W':
if (theGPT->SaveGPTData() == 1) {
- retval = 0;
goOn = 0;
} // if
break;
case 'z': case 'Z':
if (theGPT->DestroyGPT() == 1) {
- retval = 0;
- goOn = 0;
+ goOn = 0;
}
break;
default:
@@ -256,29 +357,22 @@
break;
} // switch
} while (goOn);
- return (retval);
} // ExpertsMenu()
void ShowExpertCommands(void) {
printf("a\tset attributes\n");
- printf("b\tuse backup GPT header (rebuilding main)\n");
- printf("c\tload backup partition table from disk (rebuilding main)\n");
- printf("d\tuse main GPT header (rebuilding backup)\n");
- printf("e\tload main partition table from disk (rebuilding backup)\n");
- printf("f\tchange partition GUID\n");
+ printf("c\tchange partition GUID\n");
printf("g\tchange disk GUID\n");
- printf("h\tmake hybrid MBR\n");
printf("i\tshow detailed information on a partition\n");
- printf("k\tsave partition data to a backup file\n");
- printf("l\tload partition data from a backup file\n");
- printf("m\tprint this menu\n");
+ printf("m\treturn to main menu\n");
printf("n\tcreate a new protective MBR\n");
printf("o\tprint protective MBR data\n");
printf("p\tprint the partition table\n");
printf("q\tquit without saving changes\n");
- printf("r\treturn to main menu\n");
+ printf("r\trecovery and transformation options (experts only)\n");
printf("s\tresize partition table\n");
printf("v\tverify disk\n");
printf("w\twrite table to disk and exit\n");
- printf("z\tDestroy GPT data structures and exit\n");
+ printf("z\tzap (destroy) GPT data structures and exit\n");
+ printf("?\tprint this menu\n");
} // ShowExpertCommands()