blob: f78643114f1b576723f5b57776981a57e33fd2cc [file] [log] [blame]
srs5694e7b4ff92009-08-18 13:16:10 -04001// gdisk.cc
2// Program modelled after Linux fdisk, but it manipulates GPT partitions
3// rather than MBR partitions.
4//
srs5694e4ac11e2009-08-31 10:13:04 -04005// by Rod Smith, project began February 2009
srs5694e7b4ff92009-08-18 13:16:10 -04006
srs569464cbd172011-03-01 22:03:54 -05007/* This program is copyright (c) 2009-2011 by Roderick W. Smith. It is distributed
srs5694221e0872009-08-29 15:00:31 -04008 under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
9
srs5694e7b4ff92009-08-18 13:16:10 -040010#include <stdio.h>
srs569408bb0da2010-02-19 17:19:55 -050011//#include <getopt.h>
srs5694fed16d02010-01-27 23:03:40 -050012#include <string.h>
13#include <string>
14#include <iostream>
srs569455d92612010-03-07 22:16:07 -050015#include <sstream>
srs56940283dae2010-04-28 16:44:34 -040016#include <locale>
srs5694e7b4ff92009-08-18 13:16:10 -040017#include "mbr.h"
srs569408bb0da2010-02-19 17:19:55 -050018#include "gpttext.h"
srs5694e7b4ff92009-08-18 13:16:10 -040019#include "support.h"
20
21// Function prototypes....
srs569408bb0da2010-02-19 17:19:55 -050022void MainMenu(string filename, GPTDataTextUI* theGPT);
srs5694e7b4ff92009-08-18 13:16:10 -040023void ShowCommands(void);
srs569408bb0da2010-02-19 17:19:55 -050024void ExpertsMenu(string filename, GPTDataTextUI* theGPT);
srs5694e7b4ff92009-08-18 13:16:10 -040025void ShowExpertCommands(void);
srs569408bb0da2010-02-19 17:19:55 -050026void RecoveryMenu(string filename, GPTDataTextUI* theGPT);
srs5694978041c2009-09-21 20:51:47 -040027void ShowRecoveryCommands(void);
srs569455d92612010-03-07 22:16:07 -050028void WinWarning(void);
srs5694e7b4ff92009-08-18 13:16:10 -040029
30int main(int argc, char* argv[]) {
srs569408bb0da2010-02-19 17:19:55 -050031 GPTDataTextUI theGPT;
srs569464cbd172011-03-01 22:03:54 -050032 size_t i;
33 char *device = NULL;
srs5694e7b4ff92009-08-18 13:16:10 -040034
srs5694fed16d02010-01-27 23:03:40 -050035 cout << "GPT fdisk (gdisk) version " << GPTFDISK_VERSION << "\n\n";
srs5694e7b4ff92009-08-18 13:16:10 -040036
srs569455d92612010-03-07 22:16:07 -050037 if (!SizesOK())
38 exit(1);
39
40 switch (argc) {
41 case 1:
42 WinWarning();
43 cout << "Type device filename, or press <Enter> to exit: ";
44 device = new char[255];
srs569464cbd172011-03-01 22:03:54 -050045 if (!fgets(device, 255, stdin)) {
46 cerr << "Critical error! Failed fgets() in main()!\n";
47 exit(1);
srs569455d92612010-03-07 22:16:07 -050048 } // if
srs569464cbd172011-03-01 22:03:54 -050049 i = strlen(device);
50 if (i && device[i - 1] == '\n')
51 device[i - 1] = '\0';
52 if (*device && theGPT.LoadPartitions(device))
53 MainMenu(device, &theGPT);
srs569455d92612010-03-07 22:16:07 -050054 delete[] device;
55 break;
56 case 2: // basic usage
57 WinWarning();
srs569464cbd172011-03-01 22:03:54 -050058 if (theGPT.LoadPartitions(argv[1]))
srs5694978041c2009-09-21 20:51:47 -040059 MainMenu(argv[1], &theGPT);
srs569455d92612010-03-07 22:16:07 -050060 break;
61 case 3: // usage with "-l" option
srs5694e7b4ff92009-08-18 13:16:10 -040062 if (strcmp(argv[1], "-l") == 0) {
63 device = argv[2];
64 } else if (strcmp(argv[2], "-l") == 0) {
65 device = argv[1];
66 } else { // 3 arguments, but none is "-l"
srs5694fed16d02010-01-27 23:03:40 -050067 cerr << "Usage: " << argv[0] << " [-l] device_file\n";
srs5694e7b4ff92009-08-18 13:16:10 -040068 } // if/elseif/else
69 if (device != NULL) {
srs56945d58fe02010-01-03 20:57:08 -050070 theGPT.JustLooking();
srs569464cbd172011-03-01 22:03:54 -050071 if (theGPT.LoadPartitions((string) device))
72 theGPT.DisplayGPTData();
srs5694e7b4ff92009-08-18 13:16:10 -040073 } // if
srs569455d92612010-03-07 22:16:07 -050074 break;
75 default:
76 cerr << "Usage: " << argv[0] << " [-l] device_file\n";
77 break;
78 } // switch
srs5694e7b4ff92009-08-18 13:16:10 -040079} // main
80
srs5694978041c2009-09-21 20:51:47 -040081// Accept a command and execute it. Returns only when the user
82// wants to exit (such as after a 'w' or 'q' command).
srs569408bb0da2010-02-19 17:19:55 -050083void MainMenu(string filename, GPTDataTextUI* theGPT) {
srs569464cbd172011-03-01 22:03:54 -050084 char line[255], buFile[255];
srs5694978041c2009-09-21 20:51:47 -040085 int goOn = 1;
srs56946699b012010-02-04 00:55:30 -050086 PartType typeHelper;
srs5694e7b4ff92009-08-18 13:16:10 -040087 uint32_t temp1, temp2;
88
srs5694978041c2009-09-21 20:51:47 -040089 do {
srs5694fed16d02010-01-27 23:03:40 -050090 cout << "\nCommand (? for help): ";
srs569464cbd172011-03-01 22:03:54 -050091 if (!fgets(line, 255, stdin)) {
92 cerr << "Critical error! Failed fgets() in MainMenu()!\n";
93 exit(1);
94 } // if
95 switch (*line) {
srs5694fed16d02010-01-27 23:03:40 -050096 case '\n':
97 break;
srs5694978041c2009-09-21 20:51:47 -040098 case 'b': case 'B':
srs5694fed16d02010-01-27 23:03:40 -050099 cout << "Enter backup filename to save: ";
srs569464cbd172011-03-01 22:03:54 -0500100 if (!fgets(line, 255, stdin)) {
101 exit(1);
102 cerr << "Critical error! Failed fgets() in MainMenu()!\n";
103 } // if
104 sscanf(line, "%s", buFile);
srs5694978041c2009-09-21 20:51:47 -0400105 theGPT->SaveGPTBackup(buFile);
106 break;
107 case 'c': case 'C':
108 if (theGPT->GetPartRange(&temp1, &temp2) > 0)
109 theGPT->SetName(theGPT->GetPartNum());
110 else
srs5694fed16d02010-01-27 23:03:40 -0500111 cout << "No partitions\n";
srs5694978041c2009-09-21 20:51:47 -0400112 break;
113 case 'd': case 'D':
114 theGPT->DeletePartition();
115 break;
116 case 'i': case 'I':
117 theGPT->ShowDetails();
118 break;
119 case 'l': case 'L':
srs56946699b012010-02-04 00:55:30 -0500120 typeHelper.ShowAllTypes();
srs5694978041c2009-09-21 20:51:47 -0400121 break;
122 case 'n': case 'N':
123 theGPT->CreatePartition();
124 break;
125 case 'o': case 'O':
srs5694fed16d02010-01-27 23:03:40 -0500126 cout << "This option deletes all partitions and creates a new protective MBR.\n"
127 << "Proceed? ";
srs5694978041c2009-09-21 20:51:47 -0400128 if (GetYN() == 'Y') {
129 theGPT->ClearGPTData();
130 theGPT->MakeProtectiveMBR();
131 } // if
132 break;
133 case 'p': case 'P':
134 theGPT->DisplayGPTData();
135 break;
136 case 'q': case 'Q':
137 goOn = 0;
138 break;
139 case 'r': case 'R':
140 RecoveryMenu(filename, theGPT);
141 goOn = 0;
142 break;
143 case 's': case 'S':
144 theGPT->SortGPT();
srs5694fed16d02010-01-27 23:03:40 -0500145 cout << "You may need to edit /etc/fstab and/or your boot loader configuration!\n";
srs5694978041c2009-09-21 20:51:47 -0400146 break;
147 case 't': case 'T':
148 theGPT->ChangePartType();
149 break;
150 case 'v': case 'V':
srs5694546a9c72010-01-26 16:00:26 -0500151 theGPT->Verify();
srs5694978041c2009-09-21 20:51:47 -0400152 break;
153 case 'w': case 'W':
154 if (theGPT->SaveGPTData() == 1)
155 goOn = 0;
156 break;
157 case 'x': case 'X':
158 ExpertsMenu(filename, theGPT);
159 goOn = 0;
160 break;
161 default:
162 ShowCommands();
163 break;
164 } // switch
165 } while (goOn);
166} // MainMenu()
srs5694e7b4ff92009-08-18 13:16:10 -0400167
168void ShowCommands(void) {
srs5694fed16d02010-01-27 23:03:40 -0500169 cout << "b\tback up GPT data to a file\n";
170 cout << "c\tchange a partition's name\n";
171 cout << "d\tdelete a partition\n";
172 cout << "i\tshow detailed information on a partition\n";
173 cout << "l\tlist known partition types\n";
174 cout << "n\tadd a new partition\n";
175 cout << "o\tcreate a new empty GUID partition table (GPT)\n";
176 cout << "p\tprint the partition table\n";
177 cout << "q\tquit without saving changes\n";
178 cout << "r\trecovery and transformation options (experts only)\n";
179 cout << "s\tsort partitions\n";
180 cout << "t\tchange a partition's type code\n";
181 cout << "v\tverify disk\n";
182 cout << "w\twrite table to disk and exit\n";
183 cout << "x\textra functionality (experts only)\n";
184 cout << "?\tprint this menu\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400185} // ShowCommands()
186
srs5694978041c2009-09-21 20:51:47 -0400187// Accept a recovery & transformation menu command. Returns only when the user
188// issues an exit command, such as 'w' or 'q'.
srs569408bb0da2010-02-19 17:19:55 -0500189void RecoveryMenu(string filename, GPTDataTextUI* theGPT) {
srs569464cbd172011-03-01 22:03:54 -0500190 char line[255], buFile[255];
srs569455d92612010-03-07 22:16:07 -0500191 uint32_t temp1, numParts;
srs5694978041c2009-09-21 20:51:47 -0400192 int goOn = 1;
193
194 do {
srs5694fed16d02010-01-27 23:03:40 -0500195 cout << "\nRecovery/transformation command (? for help): ";
srs569464cbd172011-03-01 22:03:54 -0500196 if (!fgets(line, 255, stdin)) {
197 cerr << "Critical error! Failed fgets() in RecoveryMenu()!\n";
198 exit(1);
199 } // if
200 switch (*line) {
srs5694fed16d02010-01-27 23:03:40 -0500201 case '\n':
202 break;
srs5694978041c2009-09-21 20:51:47 -0400203 case 'b': case 'B':
204 theGPT->RebuildMainHeader();
205 break;
206 case 'c': case 'C':
srs5694fed16d02010-01-27 23:03:40 -0500207 cout << "Warning! This will probably do weird things if you've converted an MBR to\n"
208 << "GPT form and haven't yet saved the GPT! Proceed? ";
srs5694978041c2009-09-21 20:51:47 -0400209 if (GetYN() == 'Y')
210 theGPT->LoadSecondTableAsMain();
211 break;
212 case 'd': case 'D':
213 theGPT->RebuildSecondHeader();
214 break;
215 case 'e': case 'E':
srs5694fed16d02010-01-27 23:03:40 -0500216 cout << "Warning! This will probably do weird things if you've converted an MBR to\n"
217 << "GPT form and haven't yet saved the GPT! Proceed? ";
srs5694978041c2009-09-21 20:51:47 -0400218 if (GetYN() == 'Y')
219 theGPT->LoadMainTable();
220 break;
221 case 'f': case 'F':
srs5694fed16d02010-01-27 23:03:40 -0500222 cout << "Warning! This will destroy the currently defined partitions! Proceed? ";
srs5694978041c2009-09-21 20:51:47 -0400223 if (GetYN() == 'Y') {
224 if (theGPT->LoadMBR(filename) == 1) { // successful load
225 theGPT->XFormPartitions();
226 } else {
srs5694fed16d02010-01-27 23:03:40 -0500227 cout << "Problem loading MBR! GPT is untouched; regenerating protective MBR!\n";
srs5694978041c2009-09-21 20:51:47 -0400228 theGPT->MakeProtectiveMBR();
229 } // if/else
230 } // if
231 break;
232 case 'g': case 'G':
srs569455d92612010-03-07 22:16:07 -0500233 numParts = theGPT->GetNumParts();
srs5694978041c2009-09-21 20:51:47 -0400234 temp1 = theGPT->XFormToMBR();
235 if (temp1 > 0) {
srs569455d92612010-03-07 22:16:07 -0500236 cout << "\nConverted " << temp1 << " partitions. Finalize and exit? ";
srs5694978041c2009-09-21 20:51:47 -0400237 if (GetYN() == 'Y') {
srs569455d92612010-03-07 22:16:07 -0500238 if ((theGPT->DestroyGPT() > 0) && (theGPT->SaveMBR()))
srs5694978041c2009-09-21 20:51:47 -0400239 goOn = 0;
240 } else {
241 theGPT->MakeProtectiveMBR();
srs569455d92612010-03-07 22:16:07 -0500242 theGPT->SetGPTSize(numParts);
243 cout << "Note: New protective MBR created\n\n";
srs5694978041c2009-09-21 20:51:47 -0400244 } // if/else
245 } // if
246 break;
247 case 'h': case 'H':
248 theGPT->MakeHybrid();
249 break;
250 case 'i': case 'I':
251 theGPT->ShowDetails();
252 break;
253 case 'l': case 'L':
srs5694fed16d02010-01-27 23:03:40 -0500254 cout << "Enter backup filename to load: ";
srs569464cbd172011-03-01 22:03:54 -0500255 if (!fgets(line, 255, stdin)) {
256 cerr << "Critical error! Failed fgets() in RecoveryMenu()!\n";
257 exit(1);
258 } // if
259 sscanf(line, "%s", buFile);
srs5694978041c2009-09-21 20:51:47 -0400260 theGPT->LoadGPTBackup(buFile);
261 break;
262 case 'm': case 'M':
263 MainMenu(filename, theGPT);
264 goOn = 0;
265 break;
266 case 'o': case 'O':
267 theGPT->DisplayMBRData();
268 break;
269 case 'p': case 'P':
270 theGPT->DisplayGPTData();
271 break;
272 case 'q': case 'Q':
273 goOn = 0;
274 break;
275 case 't': case 'T':
276 theGPT->XFormDisklabel();
277 break;
278 case 'v': case 'V':
279 theGPT->Verify();
280 break;
281 case 'w': case 'W':
282 if (theGPT->SaveGPTData() == 1) {
283 goOn = 0;
284 } // if
285 break;
286 case 'x': case 'X':
287 ExpertsMenu(filename, theGPT);
288 goOn = 0;
289 break;
290 default:
291 ShowRecoveryCommands();
292 break;
293 } // switch
294 } while (goOn);
295} // RecoveryMenu()
296
297void ShowRecoveryCommands(void) {
srs5694fed16d02010-01-27 23:03:40 -0500298 cout << "b\tuse backup GPT header (rebuilding main)\n";
299 cout << "c\tload backup partition table from disk (rebuilding main)\n";
300 cout << "d\tuse main GPT header (rebuilding backup)\n";
301 cout << "e\tload main partition table from disk (rebuilding backup)\n";
302 cout << "f\tload MBR and build fresh GPT from it\n";
303 cout << "g\tconvert GPT into MBR and exit\n";
304 cout << "h\tmake hybrid MBR\n";
305 cout << "i\tshow detailed information on a partition\n";
306 cout << "l\tload partition data from a backup file\n";
307 cout << "m\treturn to main menu\n";
308 cout << "o\tprint protective MBR data\n";
309 cout << "p\tprint the partition table\n";
310 cout << "q\tquit without saving changes\n";
311 cout << "t\ttransform BSD disklabel partition\n";
312 cout << "v\tverify disk\n";
313 cout << "w\twrite table to disk and exit\n";
314 cout << "x\textra functionality (experts only)\n";
315 cout << "?\tprint this menu\n";
srs5694978041c2009-09-21 20:51:47 -0400316} // ShowRecoveryCommands()
317
318// Accept an experts' menu command. Returns only after the user
319// selects an exit command, such as 'w' or 'q'.
srs569408bb0da2010-02-19 17:19:55 -0500320void ExpertsMenu(string filename, GPTDataTextUI* theGPT) {
srs569464cbd172011-03-01 22:03:54 -0500321 GPTData secondDevice;
322 char line[255], *device;
srs569408bb0da2010-02-19 17:19:55 -0500323 uint32_t pn, temp1, temp2;
srs569464cbd172011-03-01 22:03:54 -0500324 int goOn = 1;
325 size_t i;
srs56945a081752010-09-24 20:39:41 -0400326 char guidStr[255];
srs56946699b012010-02-04 00:55:30 -0500327 GUIDData aGUID;
srs5694a8582cf2010-03-19 14:21:59 -0400328 ostringstream prompt;
srs5694e7b4ff92009-08-18 13:16:10 -0400329
330 do {
srs5694fed16d02010-01-27 23:03:40 -0500331 cout << "\nExpert command (? for help): ";
srs569464cbd172011-03-01 22:03:54 -0500332 if (!fgets(line, 255, stdin)) {
333 cerr << "Critical error! Failed fgets() in ExpertsMenu()!\n";
334 exit(1);
335 } // if
336 switch (*line) {
srs5694fed16d02010-01-27 23:03:40 -0500337 case '\n':
338 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400339 case 'a': case 'A':
340 if (theGPT->GetPartRange(&temp1, &temp2) > 0)
341 theGPT->SetAttributes(theGPT->GetPartNum());
342 else
srs5694fed16d02010-01-27 23:03:40 -0500343 cout << "No partitions\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400344 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400345 case 'c': case 'C':
srs5694e7b4ff92009-08-18 13:16:10 -0400346 if (theGPT->GetPartRange(&temp1, &temp2) > 0) {
347 pn = theGPT->GetPartNum();
srs56945a081752010-09-24 20:39:41 -0400348 cout << "Enter the partition's new unique GUID ('R' to randomize): ";
srs569464cbd172011-03-01 22:03:54 -0500349 if (!fgets(guidStr, 255, stdin)) {
350 cerr << "Critical error! Failed fgets() in ExpertsMenu()!\n";
351 exit(1);
352 } // if
srs56945a081752010-09-24 20:39:41 -0400353 if ((strlen(guidStr) >= 33) || (guidStr[0] == 'R') || (guidStr[0] == 'r')) {
354 theGPT->SetPartitionGUID(pn, (GUIDData) guidStr);
355 cout << "New GUID is " << theGPT->operator[](pn).GetUniqueGUID() << "\n";
356 } else {
357 cout << "GUID is too short!\n";
358 } // if/else
srs5694fed16d02010-01-27 23:03:40 -0500359 } else cout << "No partitions\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400360 break;
srs56941d1448a2009-12-31 21:20:19 -0500361 case 'd': case 'D':
srs5694fed16d02010-01-27 23:03:40 -0500362 cout << "Partitions will begin on " << theGPT->GetAlignment()
363 << "-sector boundaries.\n";
srs56941d1448a2009-12-31 21:20:19 -0500364 break;
srs56948bb78762009-11-24 15:43:49 -0500365 case 'e': case 'E':
srs5694fed16d02010-01-27 23:03:40 -0500366 cout << "Relocating backup data structures to the end of the disk\n";
srs5694247657a2009-11-26 18:36:12 -0500367 theGPT->MoveSecondHeaderToEnd();
srs56948bb78762009-11-24 15:43:49 -0500368 break;
srs56949ba54212010-05-18 23:24:02 -0400369 case 'f': case 'F':
370 theGPT->RandomizeGUIDs();
371 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400372 case 'g': case 'G':
srs56945a081752010-09-24 20:39:41 -0400373 cout << "Enter the disk's unique GUID ('R' to randomize): ";
srs569464cbd172011-03-01 22:03:54 -0500374 if (!fgets(guidStr, 255, stdin)) {
375 cerr << "Critical error! Failed fgets() in ExpertsMenu()!\n";
376 exit(1);
377 } // if
srs56945a081752010-09-24 20:39:41 -0400378 if ((strlen(guidStr) >= 33) || (guidStr[0] == 'R') || (guidStr[0] == 'r')) {
379 theGPT->SetDiskGUID((GUIDData) guidStr);
380 cout << "The new disk GUID is " << theGPT->GetDiskGUID() << "\n";
381 } else
382 cout << "GUID is too short!\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400383 break;
srs56949ba54212010-05-18 23:24:02 -0400384 case 'h': case 'H':
385 theGPT->RecomputeCHS();
386 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400387 case 'i': case 'I':
388 theGPT->ShowDetails();
389 break;
srs56941d1448a2009-12-31 21:20:19 -0500390 case 'l': case 'L':
srs5694a8582cf2010-03-19 14:21:59 -0400391 prompt.seekp(0);
392 prompt << "Enter the sector alignment value (1-" << MAX_ALIGNMENT << ", default = "
393 << DEFAULT_ALIGNMENT << "): ";
394 temp1 = GetNumber(1, MAX_ALIGNMENT, DEFAULT_ALIGNMENT, prompt.str());
srs56941d1448a2009-12-31 21:20:19 -0500395 theGPT->SetAlignment(temp1);
396 break;
srs5694978041c2009-09-21 20:51:47 -0400397 case 'm': case 'M':
398 MainMenu(filename, theGPT);
399 goOn = 0;
srs5694e7b4ff92009-08-18 13:16:10 -0400400 break;
401 case 'n': case 'N':
402 theGPT->MakeProtectiveMBR();
403 break;
404 case 'o': case 'O':
405 theGPT->DisplayMBRData();
406 break;
407 case 'p': case 'P':
408 theGPT->DisplayGPTData();
srs569408bb0da2010-02-19 17:19:55 -0500409 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400410 case 'q': case 'Q':
srs569464cbd172011-03-01 22:03:54 -0500411 goOn = 0;
412 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400413 case 'r': case 'R':
srs5694978041c2009-09-21 20:51:47 -0400414 RecoveryMenu(filename, theGPT);
srs5694e7b4ff92009-08-18 13:16:10 -0400415 goOn = 0;
416 break;
417 case 's': case 'S':
418 theGPT->ResizePartitionTable();
419 break;
srs569464cbd172011-03-01 22:03:54 -0500420 case 't': case 'T':
421 theGPT->SwapPartitions();
422 break;
srs5694f9312b02010-07-06 15:39:51 -0400423 case 'u': case 'U':
424 cout << "Type device filename, or press <Enter> to exit: ";
425 device = new char[255];
srs569464cbd172011-03-01 22:03:54 -0500426 if (!fgets(device, 255, stdin)) {
427 cerr << "Critical error! Failed fgets() in ExpertsMenu()!\n";
428 exit(1);
srs5694f9312b02010-07-06 15:39:51 -0400429 } // if
srs569464cbd172011-03-01 22:03:54 -0500430 i = strlen(device);
431 if (i && device[i - 1] == '\n')
432 device[i - 1] = '\0';
433 if (*device && strlen(device) > 0) {
434 secondDevice = *theGPT;
435 secondDevice.SetFile(device);
436 secondDevice.SaveGPTData(0);
437 } // if
srs5694f9312b02010-07-06 15:39:51 -0400438 delete[] device;
439 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400440 case 'v': case 'V':
441 theGPT->Verify();
442 break;
443 case 'w': case 'W':
444 if (theGPT->SaveGPTData() == 1) {
srs5694e7b4ff92009-08-18 13:16:10 -0400445 goOn = 0;
446 } // if
447 break;
srs5694c0ca8f82009-08-20 21:35:25 -0400448 case 'z': case 'Z':
srs569408bb0da2010-02-19 17:19:55 -0500449 if (theGPT->DestroyGPTwPrompt() == 1) {
srs5694978041c2009-09-21 20:51:47 -0400450 goOn = 0;
srs5694c0ca8f82009-08-20 21:35:25 -0400451 }
452 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400453 default:
454 ShowExpertCommands();
455 break;
456 } // switch
457 } while (goOn);
srs5694e7b4ff92009-08-18 13:16:10 -0400458} // ExpertsMenu()
459
460void ShowExpertCommands(void) {
srs5694fed16d02010-01-27 23:03:40 -0500461 cout << "a\tset attributes\n";
462 cout << "c\tchange partition GUID\n";
463 cout << "d\tdisplay the sector alignment value\n";
464 cout << "e\trelocate backup data structures to the end of the disk\n";
465 cout << "g\tchange disk GUID\n";
srs56949ba54212010-05-18 23:24:02 -0400466 cout << "h\trecompute CHS values in protective/hybrid MBR\n";
srs5694fed16d02010-01-27 23:03:40 -0500467 cout << "i\tshow detailed information on a partition\n";
468 cout << "l\tset the sector alignment value\n";
469 cout << "m\treturn to main menu\n";
470 cout << "n\tcreate a new protective MBR\n";
471 cout << "o\tprint protective MBR data\n";
472 cout << "p\tprint the partition table\n";
473 cout << "q\tquit without saving changes\n";
474 cout << "r\trecovery and transformation options (experts only)\n";
475 cout << "s\tresize partition table\n";
srs569408bb0da2010-02-19 17:19:55 -0500476 cout << "t\ttranspose two partition table entries\n";
srs5694f9312b02010-07-06 15:39:51 -0400477 cout << "u\tReplicate partition table on new device\n";
srs5694fed16d02010-01-27 23:03:40 -0500478 cout << "v\tverify disk\n";
479 cout << "w\twrite table to disk and exit\n";
480 cout << "z\tzap (destroy) GPT data structures and exit\n";
481 cout << "?\tprint this menu\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400482} // ShowExpertCommands()
srs569455d92612010-03-07 22:16:07 -0500483
484// On Windows, display a warning and ask whether to continue. If the user elects
485// not to continue, exit immediately.
486void WinWarning(void) {
487#ifdef _WIN32
488 cout << "\a************************************************************************\n"
489 << "Most versions of Windows cannot boot from a GPT disk, and most varieties\n"
490 << "prior to Vista cannot read GPT disks. Therefore, you should exit now\n"
491 << "unless you understand the implications of converting MBR to GPT, editing\n"
492 << "an existing GPT disk, or creating a new GPT disk layout!\n"
493 << "************************************************************************\n\n";
494 cout << "Are you SURE you want to continue? ";
495 if (GetYN() != 'Y')
496 exit(0);
497#endif
498} // WinWarning()