summaryrefslogtreecommitdiff
path: root/sgdisk.cc
diff options
context:
space:
mode:
authorsrs5694 <srs5694@users.sourceforge.net>2010-01-05 00:14:19 -0500
committersrs5694 <srs5694@users.sourceforge.net>2010-01-05 00:14:19 -0500
commit1e09372bca227ffbfb9dda48160826d8f63ce9bb (patch)
treefc7985fba7adc24d200c15355126e422ecea912b /sgdisk.cc
parent5d58fe0ea12c9c727c8a970c8e1ac08ea7fbe05f (diff)
downloadsgdisk-1e09372bca227ffbfb9dda48160826d8f63ce9bb.tar.gz
Early support for larger-than-512-byte sectors and even earlier support
for sgdisk program. (The latter is just proof-of-concept at this point; it doesn't do anything useful.)
Diffstat (limited to 'sgdisk.cc')
-rw-r--r--sgdisk.cc464
1 files changed, 464 insertions, 0 deletions
diff --git a/sgdisk.cc b/sgdisk.cc
new file mode 100644
index 0000000..9479afb
--- /dev/null
+++ b/sgdisk.cc
@@ -0,0 +1,464 @@
+// sgdisk.cc
+// Program modelled after Linux sfdisk, but it manipulates GPT partitions
+// rather than MBR partitions. This is effectively a new user interface
+// to my gdisk program.
+//
+// by Rod Smith, project began February 2009
+
+/* This program is copyright (c) 2009, 2010 by Roderick W. Smith. It is distributed
+ under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
+
+//#include <iostream>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include "mbr.h"
+#include "gpt.h"
+#include "support.h"
+
+#define MAX_OPTIONS 50
+
+// Function prototypes....
+/* void MainMenu(char* filename, struct GPTData* theGPT);
+void ShowCommands(void);
+void ExpertsMenu(char* filename, struct GPTData* theGPT);
+void ShowExpertCommands(void);
+void RecoveryMenu(char* filename, struct GPTData* theGPT);
+void ShowRecoveryCommands(void); */
+
+enum Commands { NONE, LIST, VERIFY };
+
+struct Options {
+ Commands theCommand;
+ char* theArgument;
+}; // struct Options
+
+int verbose_flag;
+
+static struct option long_options[] =
+{
+ {"verify", no_argument, NULL, 'v'},
+ {"list", no_argument, NULL, 'l'},
+ {0, 0, NULL, 0}
+};
+
+int ParseOptions(int argc, char* argv[], Options* theOptions, char** device);
+
+int main(int argc, char* argv[]) {
+ GPTData theGPT;
+ int doMore = 1, opt, i, numOptions = 0;
+ char* device = NULL;
+ Options theOptions[MAX_OPTIONS];
+
+ printf("GPT fdisk (sgdisk) version 0.5.4-pre1\n\n");
+ numOptions = ParseOptions(argc, argv, theOptions, &device);
+
+ if (device != NULL) {
+ if (theGPT.LoadPartitions(device)) {
+ for (i = 0; i < numOptions; i++) {
+ switch (theOptions[i].theCommand) {
+ case LIST:
+ theGPT.JustLooking();
+ theGPT.DisplayGPTData();
+ break;
+ case VERIFY:
+ theGPT.JustLooking();
+ theGPT.Verify();
+ break;
+ case NONE:
+ printf("Usage: %s {-lv} device\n", argv[0]);
+ break;
+ } // switch
+ } // for
+ } // if loaded OK
+ } // if (device != NULL)
+
+ return 0;
+} // main
+
+// Parse command-line options. Returns the number of arguments retrieved
+int ParseOptions(int argc, char* argv[], Options* theOptions, char** device) {
+ int opt, i, numOptions = 0;
+ int verbose_flag;
+
+ // Use getopt() to extract commands and their arguments
+ /* getopt_long stores the option index here. */
+ int option_index = 0;
+
+// c = getopt_long (argc, argv, "abc:d:f:",
+// long_options, &option_index);
+
+ while (((opt = getopt_long(argc, argv, "vl", long_options, &option_index)) != -1)
+ && (numOptions < MAX_OPTIONS)) {
+ printf("opt is %c, option_index is %d\n", opt, option_index);
+ switch (opt) {
+ case 'l':
+ printf("Entering list option, numOptions = %d!\n", numOptions);
+ theOptions[numOptions].theCommand = LIST;
+ theOptions[numOptions++].theArgument = NULL;
+ break;
+ case 'v':
+ theOptions[numOptions].theCommand = VERIFY;
+ theOptions[numOptions++].theArgument = NULL;
+ break;
+ default:
+ printf("Default switch; opt is %c\n", opt);
+ break;
+// abort();
+ } // switch
+ } // while
+
+ // Find non-option arguments. If the user types a legal command, there
+ // will be only one of these: The device filename....
+ opt = 0;
+ printf("Searching for device filename; optind is %d\n", optind);
+ for (i = optind; i < argc; i++) {
+ *device = argv[i];
+ printf("Setting device to %s\n", argv[i]);
+ opt++;
+ } // for
+ if (opt > 1) {
+ fprintf(stderr, "Warning! Found stray unrecognized arguments! Program may misbehave!\n");
+ } // if
+
+ return numOptions;
+} // ParseOptions()
+
+/* // 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];
+ char* junk;
+ int goOn = 1;
+ PartTypes typeHelper;
+ uint32_t temp1, temp2;
+
+ do {
+ printf("\nCommand (? for help): ");
+ junk = fgets(line, 255, stdin);
+ sscanf(line, "%c", &command);
+ switch (command) {
+ case 'b': case 'B':
+ printf("Enter backup filename to save: ");
+ junk = fgets(line, 255, stdin);
+ sscanf(line, "%s", (char*) &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\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 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 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];
+ char* junk;
+ PartTypes typeHelper;
+ uint32_t temp1;
+ int goOn = 1;
+
+ do {
+ printf("\nrecovery/transformation command (? for help): ");
+ junk = 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: ");
+ junk = fgets(line, 255, stdin);
+ sscanf(line, "%s", (char*) &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];
+ char* junk;
+ PartTypes typeHelper;
+ uint32_t pn;
+ uint32_t temp1, temp2;
+ int goOn = 1;
+
+ do {
+ printf("\nExpert command (? for help): ");
+ junk = fgets(line, 255, stdin);
+ sscanf(line, "%c", &command);
+ switch (command) {
+ case 'a': case 'A':
+ if (theGPT->GetPartRange(&temp1, &temp2) > 0)
+ theGPT->SetAttributes(theGPT->GetPartNum());
+ else
+ printf("No partitions\n");
+ break;
+ case 'c': case 'C':
+ if (theGPT->GetPartRange(&temp1, &temp2) > 0) {
+ pn = theGPT->GetPartNum();
+ printf("Enter the partition's new unique GUID:\n");
+ theGPT->SetPartitionGUID(pn, GetGUID());
+ } else printf("No partitions\n");
+ break;
+ case 'd': case 'D':
+ printf("The number of logical sectors per physical sector is %d.\n",
+ theGPT->GetAlignment());
+ break;
+ case 'e': case 'E':
+ printf("Relocating backup data structures to the end of the disk\n");
+ theGPT->MoveSecondHeaderToEnd();
+ break;
+ case 'g': case 'G':
+ printf("Enter the disk's unique GUID:\n");
+ theGPT->SetDiskGUID(GetGUID());
+ break;
+ case 'i': case 'I':
+ theGPT->ShowDetails();
+ break;
+ case 'l': case 'L':
+ temp1 = GetNumber(1, 128, 8, "Enter the number of logical sectors in a physical sector on the\ndisk (1-128, default = 8): ");
+ theGPT->SetAlignment(temp1);
+ break;
+ case 'm': case 'M':
+ MainMenu(filename, theGPT);
+ goOn = 0;
+ break;
+ case 'n': case 'N':
+ theGPT->MakeProtectiveMBR();
+ break;
+ case 'o': case 'O':
+ theGPT->DisplayMBRData();
+ 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->ResizePartitionTable();
+ break;
+ case 'v': case 'V':
+ theGPT->Verify();
+ break;
+ case 'w': case 'W':
+ if (theGPT->SaveGPTData() == 1) {
+ goOn = 0;
+ } // if
+ break;
+ case 'z': case 'Z':
+ if (theGPT->DestroyGPT() == 1) {
+ goOn = 0;
+ }
+ break;
+ default:
+ ShowExpertCommands();
+ break;
+ } // switch
+ } while (goOn);
+} // ExpertsMenu()
+
+void ShowExpertCommands(void) {
+ printf("a\tset attributes\n");
+ printf("c\tchange partition GUID\n");
+ printf("d\tdisplay the number of logical sectors per physical sector\n");
+ printf("e\trelocate backup data structures to the end of the disk\n");
+ printf("g\tchange disk GUID\n");
+ printf("i\tshow detailed information on a partition\n");
+ printf("b\tset the number of logical sectors per physical sector\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\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\tzap (destroy) GPT data structures and exit\n");
+ printf("?\tprint this menu\n");
+} // ShowExpertCommands()
+*/