blob: 35f7e9deb166f519a601bbe19ea47e154ef9f6d2 [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>
srs5694fed16d02010-01-27 23:03:40 -050011#include <string.h>
12#include <string>
13#include <iostream>
srs569455d92612010-03-07 22:16:07 -050014#include <sstream>
srs56940283dae2010-04-28 16:44:34 -040015#include <locale>
srs5694e7b4ff92009-08-18 13:16:10 -040016#include "mbr.h"
srs569408bb0da2010-02-19 17:19:55 -050017#include "gpttext.h"
srs5694e7b4ff92009-08-18 13:16:10 -040018#include "support.h"
19
20// Function prototypes....
srs569408bb0da2010-02-19 17:19:55 -050021void MainMenu(string filename, GPTDataTextUI* theGPT);
srs5694e7b4ff92009-08-18 13:16:10 -040022void ShowCommands(void);
srs569408bb0da2010-02-19 17:19:55 -050023void ExpertsMenu(string filename, GPTDataTextUI* theGPT);
srs5694e7b4ff92009-08-18 13:16:10 -040024void ShowExpertCommands(void);
srs569408bb0da2010-02-19 17:19:55 -050025void RecoveryMenu(string filename, GPTDataTextUI* theGPT);
srs5694978041c2009-09-21 20:51:47 -040026void ShowRecoveryCommands(void);
srs569455d92612010-03-07 22:16:07 -050027void WinWarning(void);
srs5694e7b4ff92009-08-18 13:16:10 -040028
29int main(int argc, char* argv[]) {
srs569408bb0da2010-02-19 17:19:55 -050030 GPTDataTextUI theGPT;
srs56945a608532011-03-17 13:53:01 -040031 string device = "";
32 UnicodeString uString;
srs5694e7b4ff92009-08-18 13:16:10 -040033
srs5694fed16d02010-01-27 23:03:40 -050034 cout << "GPT fdisk (gdisk) version " << GPTFDISK_VERSION << "\n\n";
srs5694e7b4ff92009-08-18 13:16:10 -040035
srs569455d92612010-03-07 22:16:07 -050036 if (!SizesOK())
37 exit(1);
38
39 switch (argc) {
40 case 1:
41 WinWarning();
42 cout << "Type device filename, or press <Enter> to exit: ";
srs56945a608532011-03-17 13:53:01 -040043 device = ReadString();
44 if (device.length() == 0)
45 exit(0);
46 else if (theGPT.LoadPartitions(device)) {
srs569464cbd172011-03-01 22:03:54 -050047 MainMenu(device, &theGPT);
srs56945a608532011-03-17 13:53:01 -040048 } // if/elseif
srs569455d92612010-03-07 22:16:07 -050049 break;
50 case 2: // basic usage
51 WinWarning();
srs569464cbd172011-03-01 22:03:54 -050052 if (theGPT.LoadPartitions(argv[1]))
srs5694978041c2009-09-21 20:51:47 -040053 MainMenu(argv[1], &theGPT);
srs569455d92612010-03-07 22:16:07 -050054 break;
55 case 3: // usage with "-l" option
srs5694e7b4ff92009-08-18 13:16:10 -040056 if (strcmp(argv[1], "-l") == 0) {
srs56945a608532011-03-17 13:53:01 -040057 device = (string) argv[2];
srs5694e7b4ff92009-08-18 13:16:10 -040058 } else if (strcmp(argv[2], "-l") == 0) {
srs56945a608532011-03-17 13:53:01 -040059 device = (string) argv[1];
srs5694e7b4ff92009-08-18 13:16:10 -040060 } else { // 3 arguments, but none is "-l"
srs5694fed16d02010-01-27 23:03:40 -050061 cerr << "Usage: " << argv[0] << " [-l] device_file\n";
srs5694e7b4ff92009-08-18 13:16:10 -040062 } // if/elseif/else
srs56945a608532011-03-17 13:53:01 -040063 if (device != "") {
srs56945d58fe02010-01-03 20:57:08 -050064 theGPT.JustLooking();
srs56945a608532011-03-17 13:53:01 -040065 if (theGPT.LoadPartitions(device))
srs569464cbd172011-03-01 22:03:54 -050066 theGPT.DisplayGPTData();
srs5694e7b4ff92009-08-18 13:16:10 -040067 } // if
srs569455d92612010-03-07 22:16:07 -050068 break;
69 default:
70 cerr << "Usage: " << argv[0] << " [-l] device_file\n";
71 break;
72 } // switch
srs5694e7b4ff92009-08-18 13:16:10 -040073} // main
74
srs5694978041c2009-09-21 20:51:47 -040075// Accept a command and execute it. Returns only when the user
76// wants to exit (such as after a 'w' or 'q' command).
srs569408bb0da2010-02-19 17:19:55 -050077void MainMenu(string filename, GPTDataTextUI* theGPT) {
srs5694978041c2009-09-21 20:51:47 -040078 int goOn = 1;
srs56946699b012010-02-04 00:55:30 -050079 PartType typeHelper;
srs5694e7b4ff92009-08-18 13:16:10 -040080 uint32_t temp1, temp2;
81
srs5694978041c2009-09-21 20:51:47 -040082 do {
srs5694fed16d02010-01-27 23:03:40 -050083 cout << "\nCommand (? for help): ";
srs56945a608532011-03-17 13:53:01 -040084 switch (ReadString()[0]) {
85 case '\0':
srs5694fed16d02010-01-27 23:03:40 -050086 break;
srs5694978041c2009-09-21 20:51:47 -040087 case 'b': case 'B':
srs5694fed16d02010-01-27 23:03:40 -050088 cout << "Enter backup filename to save: ";
srs56945a608532011-03-17 13:53:01 -040089 theGPT->SaveGPTBackup(ReadString());
srs5694978041c2009-09-21 20:51:47 -040090 break;
91 case 'c': case 'C':
92 if (theGPT->GetPartRange(&temp1, &temp2) > 0)
93 theGPT->SetName(theGPT->GetPartNum());
94 else
srs5694fed16d02010-01-27 23:03:40 -050095 cout << "No partitions\n";
srs5694978041c2009-09-21 20:51:47 -040096 break;
97 case 'd': case 'D':
98 theGPT->DeletePartition();
99 break;
100 case 'i': case 'I':
101 theGPT->ShowDetails();
102 break;
103 case 'l': case 'L':
srs56946699b012010-02-04 00:55:30 -0500104 typeHelper.ShowAllTypes();
srs5694978041c2009-09-21 20:51:47 -0400105 break;
106 case 'n': case 'N':
107 theGPT->CreatePartition();
108 break;
109 case 'o': case 'O':
srs5694fed16d02010-01-27 23:03:40 -0500110 cout << "This option deletes all partitions and creates a new protective MBR.\n"
111 << "Proceed? ";
srs5694978041c2009-09-21 20:51:47 -0400112 if (GetYN() == 'Y') {
113 theGPT->ClearGPTData();
114 theGPT->MakeProtectiveMBR();
115 } // if
116 break;
117 case 'p': case 'P':
118 theGPT->DisplayGPTData();
119 break;
120 case 'q': case 'Q':
121 goOn = 0;
122 break;
123 case 'r': case 'R':
124 RecoveryMenu(filename, theGPT);
125 goOn = 0;
126 break;
127 case 's': case 'S':
128 theGPT->SortGPT();
srs5694fed16d02010-01-27 23:03:40 -0500129 cout << "You may need to edit /etc/fstab and/or your boot loader configuration!\n";
srs5694978041c2009-09-21 20:51:47 -0400130 break;
131 case 't': case 'T':
132 theGPT->ChangePartType();
133 break;
134 case 'v': case 'V':
srs5694546a9c72010-01-26 16:00:26 -0500135 theGPT->Verify();
srs5694978041c2009-09-21 20:51:47 -0400136 break;
137 case 'w': case 'W':
138 if (theGPT->SaveGPTData() == 1)
139 goOn = 0;
140 break;
141 case 'x': case 'X':
142 ExpertsMenu(filename, theGPT);
143 goOn = 0;
144 break;
145 default:
146 ShowCommands();
147 break;
148 } // switch
149 } while (goOn);
150} // MainMenu()
srs5694e7b4ff92009-08-18 13:16:10 -0400151
152void ShowCommands(void) {
srs5694fed16d02010-01-27 23:03:40 -0500153 cout << "b\tback up GPT data to a file\n";
154 cout << "c\tchange a partition's name\n";
155 cout << "d\tdelete a partition\n";
156 cout << "i\tshow detailed information on a partition\n";
157 cout << "l\tlist known partition types\n";
158 cout << "n\tadd a new partition\n";
159 cout << "o\tcreate a new empty GUID partition table (GPT)\n";
160 cout << "p\tprint the partition table\n";
161 cout << "q\tquit without saving changes\n";
162 cout << "r\trecovery and transformation options (experts only)\n";
163 cout << "s\tsort partitions\n";
164 cout << "t\tchange a partition's type code\n";
165 cout << "v\tverify disk\n";
166 cout << "w\twrite table to disk and exit\n";
167 cout << "x\textra functionality (experts only)\n";
168 cout << "?\tprint this menu\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400169} // ShowCommands()
170
srs5694978041c2009-09-21 20:51:47 -0400171// Accept a recovery & transformation menu command. Returns only when the user
172// issues an exit command, such as 'w' or 'q'.
srs569408bb0da2010-02-19 17:19:55 -0500173void RecoveryMenu(string filename, GPTDataTextUI* theGPT) {
srs5694bf8950c2011-03-12 01:23:12 -0500174 uint32_t numParts;
175 int goOn = 1, temp1;
srs5694978041c2009-09-21 20:51:47 -0400176
177 do {
srs5694fed16d02010-01-27 23:03:40 -0500178 cout << "\nRecovery/transformation command (? for help): ";
srs56945a608532011-03-17 13:53:01 -0400179 switch (ReadString()[0]) {
180 case '\0':
srs5694fed16d02010-01-27 23:03:40 -0500181 break;
srs5694978041c2009-09-21 20:51:47 -0400182 case 'b': case 'B':
183 theGPT->RebuildMainHeader();
184 break;
185 case 'c': case 'C':
srs5694fed16d02010-01-27 23:03:40 -0500186 cout << "Warning! This will probably do weird things if you've converted an MBR to\n"
187 << "GPT form and haven't yet saved the GPT! Proceed? ";
srs5694978041c2009-09-21 20:51:47 -0400188 if (GetYN() == 'Y')
189 theGPT->LoadSecondTableAsMain();
190 break;
191 case 'd': case 'D':
192 theGPT->RebuildSecondHeader();
193 break;
194 case 'e': case 'E':
srs5694fed16d02010-01-27 23:03:40 -0500195 cout << "Warning! This will probably do weird things if you've converted an MBR to\n"
196 << "GPT form and haven't yet saved the GPT! Proceed? ";
srs5694978041c2009-09-21 20:51:47 -0400197 if (GetYN() == 'Y')
198 theGPT->LoadMainTable();
199 break;
200 case 'f': case 'F':
srs5694fed16d02010-01-27 23:03:40 -0500201 cout << "Warning! This will destroy the currently defined partitions! Proceed? ";
srs5694978041c2009-09-21 20:51:47 -0400202 if (GetYN() == 'Y') {
203 if (theGPT->LoadMBR(filename) == 1) { // successful load
204 theGPT->XFormPartitions();
205 } else {
srs5694fed16d02010-01-27 23:03:40 -0500206 cout << "Problem loading MBR! GPT is untouched; regenerating protective MBR!\n";
srs5694978041c2009-09-21 20:51:47 -0400207 theGPT->MakeProtectiveMBR();
208 } // if/else
209 } // if
210 break;
211 case 'g': case 'G':
srs569455d92612010-03-07 22:16:07 -0500212 numParts = theGPT->GetNumParts();
srs5694978041c2009-09-21 20:51:47 -0400213 temp1 = theGPT->XFormToMBR();
srs5694bf8950c2011-03-12 01:23:12 -0500214 if (temp1 > 0)
srs569455d92612010-03-07 22:16:07 -0500215 cout << "\nConverted " << temp1 << " partitions. Finalize and exit? ";
srs5694bf8950c2011-03-12 01:23:12 -0500216 if ((temp1 > 0) && (GetYN() == 'Y')) {
217 if ((theGPT->DestroyGPT() > 0) && (theGPT->SaveMBR())) {
218 goOn = 0;
219 } // if
220 } else {
221 theGPT->MakeProtectiveMBR();
222 theGPT->SetGPTSize(numParts);
223 cout << "Note: New protective MBR created\n\n";
224 } // if/else
srs5694978041c2009-09-21 20:51:47 -0400225 break;
226 case 'h': case 'H':
227 theGPT->MakeHybrid();
228 break;
229 case 'i': case 'I':
230 theGPT->ShowDetails();
231 break;
232 case 'l': case 'L':
srs5694fed16d02010-01-27 23:03:40 -0500233 cout << "Enter backup filename to load: ";
srs56945a608532011-03-17 13:53:01 -0400234 theGPT->LoadGPTBackup(ReadString());
srs5694978041c2009-09-21 20:51:47 -0400235 break;
236 case 'm': case 'M':
237 MainMenu(filename, theGPT);
238 goOn = 0;
239 break;
240 case 'o': case 'O':
241 theGPT->DisplayMBRData();
242 break;
243 case 'p': case 'P':
244 theGPT->DisplayGPTData();
245 break;
246 case 'q': case 'Q':
247 goOn = 0;
248 break;
249 case 't': case 'T':
250 theGPT->XFormDisklabel();
251 break;
252 case 'v': case 'V':
253 theGPT->Verify();
254 break;
255 case 'w': case 'W':
256 if (theGPT->SaveGPTData() == 1) {
257 goOn = 0;
258 } // if
259 break;
260 case 'x': case 'X':
261 ExpertsMenu(filename, theGPT);
262 goOn = 0;
263 break;
264 default:
265 ShowRecoveryCommands();
266 break;
267 } // switch
268 } while (goOn);
269} // RecoveryMenu()
270
271void ShowRecoveryCommands(void) {
srs5694fed16d02010-01-27 23:03:40 -0500272 cout << "b\tuse backup GPT header (rebuilding main)\n";
273 cout << "c\tload backup partition table from disk (rebuilding main)\n";
274 cout << "d\tuse main GPT header (rebuilding backup)\n";
275 cout << "e\tload main partition table from disk (rebuilding backup)\n";
276 cout << "f\tload MBR and build fresh GPT from it\n";
277 cout << "g\tconvert GPT into MBR and exit\n";
278 cout << "h\tmake hybrid MBR\n";
279 cout << "i\tshow detailed information on a partition\n";
280 cout << "l\tload partition data from a backup file\n";
281 cout << "m\treturn to main menu\n";
282 cout << "o\tprint protective MBR data\n";
283 cout << "p\tprint the partition table\n";
284 cout << "q\tquit without saving changes\n";
285 cout << "t\ttransform BSD disklabel partition\n";
286 cout << "v\tverify disk\n";
287 cout << "w\twrite table to disk and exit\n";
288 cout << "x\textra functionality (experts only)\n";
289 cout << "?\tprint this menu\n";
srs5694978041c2009-09-21 20:51:47 -0400290} // ShowRecoveryCommands()
291
292// Accept an experts' menu command. Returns only after the user
293// selects an exit command, such as 'w' or 'q'.
srs569408bb0da2010-02-19 17:19:55 -0500294void ExpertsMenu(string filename, GPTDataTextUI* theGPT) {
srs569464cbd172011-03-01 22:03:54 -0500295 GPTData secondDevice;
srs569408bb0da2010-02-19 17:19:55 -0500296 uint32_t pn, temp1, temp2;
srs569464cbd172011-03-01 22:03:54 -0500297 int goOn = 1;
srs56945a608532011-03-17 13:53:01 -0400298 string guidStr, device;
srs56946699b012010-02-04 00:55:30 -0500299 GUIDData aGUID;
srs5694a8582cf2010-03-19 14:21:59 -0400300 ostringstream prompt;
srs5694e7b4ff92009-08-18 13:16:10 -0400301
302 do {
srs5694fed16d02010-01-27 23:03:40 -0500303 cout << "\nExpert command (? for help): ";
srs56945a608532011-03-17 13:53:01 -0400304 switch (ReadString()[0]) {
305 case '\0':
srs5694fed16d02010-01-27 23:03:40 -0500306 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400307 case 'a': case 'A':
308 if (theGPT->GetPartRange(&temp1, &temp2) > 0)
309 theGPT->SetAttributes(theGPT->GetPartNum());
310 else
srs5694fed16d02010-01-27 23:03:40 -0500311 cout << "No partitions\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400312 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400313 case 'c': case 'C':
srs5694e7b4ff92009-08-18 13:16:10 -0400314 if (theGPT->GetPartRange(&temp1, &temp2) > 0) {
315 pn = theGPT->GetPartNum();
srs56945a081752010-09-24 20:39:41 -0400316 cout << "Enter the partition's new unique GUID ('R' to randomize): ";
srs56945a608532011-03-17 13:53:01 -0400317 guidStr = ReadString();
318 if ((guidStr.length() >= 32) || (guidStr[0] == 'R') || (guidStr[0] == 'r')) {
srs56945a081752010-09-24 20:39:41 -0400319 theGPT->SetPartitionGUID(pn, (GUIDData) guidStr);
320 cout << "New GUID is " << theGPT->operator[](pn).GetUniqueGUID() << "\n";
321 } else {
322 cout << "GUID is too short!\n";
323 } // if/else
srs5694fed16d02010-01-27 23:03:40 -0500324 } else cout << "No partitions\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400325 break;
srs56941d1448a2009-12-31 21:20:19 -0500326 case 'd': case 'D':
srs5694fed16d02010-01-27 23:03:40 -0500327 cout << "Partitions will begin on " << theGPT->GetAlignment()
328 << "-sector boundaries.\n";
srs56941d1448a2009-12-31 21:20:19 -0500329 break;
srs56948bb78762009-11-24 15:43:49 -0500330 case 'e': case 'E':
srs5694fed16d02010-01-27 23:03:40 -0500331 cout << "Relocating backup data structures to the end of the disk\n";
srs5694247657a2009-11-26 18:36:12 -0500332 theGPT->MoveSecondHeaderToEnd();
srs56948bb78762009-11-24 15:43:49 -0500333 break;
srs56949ba54212010-05-18 23:24:02 -0400334 case 'f': case 'F':
335 theGPT->RandomizeGUIDs();
336 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400337 case 'g': case 'G':
srs56945a081752010-09-24 20:39:41 -0400338 cout << "Enter the disk's unique GUID ('R' to randomize): ";
srs56945a608532011-03-17 13:53:01 -0400339 guidStr = ReadString();
340 if ((guidStr.length() >= 32) || (guidStr[0] == 'R') || (guidStr[0] == 'r')) {
srs56945a081752010-09-24 20:39:41 -0400341 theGPT->SetDiskGUID((GUIDData) guidStr);
342 cout << "The new disk GUID is " << theGPT->GetDiskGUID() << "\n";
srs56945a608532011-03-17 13:53:01 -0400343 } else {
srs56945a081752010-09-24 20:39:41 -0400344 cout << "GUID is too short!\n";
srs56945a608532011-03-17 13:53:01 -0400345 } // if/else
srs5694e7b4ff92009-08-18 13:16:10 -0400346 break;
srs56949ba54212010-05-18 23:24:02 -0400347 case 'h': case 'H':
348 theGPT->RecomputeCHS();
349 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400350 case 'i': case 'I':
351 theGPT->ShowDetails();
352 break;
srs56941d1448a2009-12-31 21:20:19 -0500353 case 'l': case 'L':
srs5694a8582cf2010-03-19 14:21:59 -0400354 prompt.seekp(0);
355 prompt << "Enter the sector alignment value (1-" << MAX_ALIGNMENT << ", default = "
356 << DEFAULT_ALIGNMENT << "): ";
357 temp1 = GetNumber(1, MAX_ALIGNMENT, DEFAULT_ALIGNMENT, prompt.str());
srs56941d1448a2009-12-31 21:20:19 -0500358 theGPT->SetAlignment(temp1);
359 break;
srs5694978041c2009-09-21 20:51:47 -0400360 case 'm': case 'M':
361 MainMenu(filename, theGPT);
362 goOn = 0;
srs5694e7b4ff92009-08-18 13:16:10 -0400363 break;
364 case 'n': case 'N':
365 theGPT->MakeProtectiveMBR();
366 break;
367 case 'o': case 'O':
368 theGPT->DisplayMBRData();
369 break;
370 case 'p': case 'P':
371 theGPT->DisplayGPTData();
srs569408bb0da2010-02-19 17:19:55 -0500372 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400373 case 'q': case 'Q':
srs569464cbd172011-03-01 22:03:54 -0500374 goOn = 0;
375 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400376 case 'r': case 'R':
srs5694978041c2009-09-21 20:51:47 -0400377 RecoveryMenu(filename, theGPT);
srs5694e7b4ff92009-08-18 13:16:10 -0400378 goOn = 0;
379 break;
380 case 's': case 'S':
381 theGPT->ResizePartitionTable();
382 break;
srs569464cbd172011-03-01 22:03:54 -0500383 case 't': case 'T':
384 theGPT->SwapPartitions();
385 break;
srs5694f9312b02010-07-06 15:39:51 -0400386 case 'u': case 'U':
387 cout << "Type device filename, or press <Enter> to exit: ";
srs56945a608532011-03-17 13:53:01 -0400388 device = ReadString();
389 if (device.length() > 0) {
srs569464cbd172011-03-01 22:03:54 -0500390 secondDevice = *theGPT;
srs5694bf8950c2011-03-12 01:23:12 -0500391 secondDevice.SetDisk(device);
srs569464cbd172011-03-01 22:03:54 -0500392 secondDevice.SaveGPTData(0);
393 } // if
srs5694f9312b02010-07-06 15:39:51 -0400394 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400395 case 'v': case 'V':
396 theGPT->Verify();
397 break;
398 case 'w': case 'W':
399 if (theGPT->SaveGPTData() == 1) {
srs5694e7b4ff92009-08-18 13:16:10 -0400400 goOn = 0;
401 } // if
402 break;
srs5694c0ca8f82009-08-20 21:35:25 -0400403 case 'z': case 'Z':
srs569408bb0da2010-02-19 17:19:55 -0500404 if (theGPT->DestroyGPTwPrompt() == 1) {
srs5694978041c2009-09-21 20:51:47 -0400405 goOn = 0;
srs5694c0ca8f82009-08-20 21:35:25 -0400406 }
407 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400408 default:
409 ShowExpertCommands();
410 break;
411 } // switch
412 } while (goOn);
srs5694e7b4ff92009-08-18 13:16:10 -0400413} // ExpertsMenu()
414
415void ShowExpertCommands(void) {
srs5694fed16d02010-01-27 23:03:40 -0500416 cout << "a\tset attributes\n";
417 cout << "c\tchange partition GUID\n";
418 cout << "d\tdisplay the sector alignment value\n";
419 cout << "e\trelocate backup data structures to the end of the disk\n";
420 cout << "g\tchange disk GUID\n";
srs56949ba54212010-05-18 23:24:02 -0400421 cout << "h\trecompute CHS values in protective/hybrid MBR\n";
srs5694fed16d02010-01-27 23:03:40 -0500422 cout << "i\tshow detailed information on a partition\n";
423 cout << "l\tset the sector alignment value\n";
424 cout << "m\treturn to main menu\n";
425 cout << "n\tcreate a new protective MBR\n";
426 cout << "o\tprint protective MBR data\n";
427 cout << "p\tprint the partition table\n";
428 cout << "q\tquit without saving changes\n";
429 cout << "r\trecovery and transformation options (experts only)\n";
430 cout << "s\tresize partition table\n";
srs569408bb0da2010-02-19 17:19:55 -0500431 cout << "t\ttranspose two partition table entries\n";
srs5694f9312b02010-07-06 15:39:51 -0400432 cout << "u\tReplicate partition table on new device\n";
srs5694fed16d02010-01-27 23:03:40 -0500433 cout << "v\tverify disk\n";
434 cout << "w\twrite table to disk and exit\n";
435 cout << "z\tzap (destroy) GPT data structures and exit\n";
436 cout << "?\tprint this menu\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400437} // ShowExpertCommands()
srs569455d92612010-03-07 22:16:07 -0500438
439// On Windows, display a warning and ask whether to continue. If the user elects
440// not to continue, exit immediately.
441void WinWarning(void) {
442#ifdef _WIN32
443 cout << "\a************************************************************************\n"
444 << "Most versions of Windows cannot boot from a GPT disk, and most varieties\n"
445 << "prior to Vista cannot read GPT disks. Therefore, you should exit now\n"
446 << "unless you understand the implications of converting MBR to GPT, editing\n"
447 << "an existing GPT disk, or creating a new GPT disk layout!\n"
448 << "************************************************************************\n\n";
449 cout << "Are you SURE you want to continue? ";
450 if (GetYN() != 'Y')
451 exit(0);
452#endif
453} // WinWarning()