blob: ad2f51b2ba78877c51609c52368b688e25b1788d [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
srs5694221e0872009-08-29 15:00:31 -04007/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
8 under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
9
srs5694e7b4ff92009-08-18 13:16:10 -040010//#include <iostream>
11#include <stdio.h>
12#include <string.h>
13#include <getopt.h>
14#include "mbr.h"
15#include "gpt.h"
16#include "support.h"
17
18// Function prototypes....
19// int ReadPartitions(char* filename, struct GPTData* theGPT);
20int DoCommand(char* filename, struct GPTData* theGPT);
21void ShowCommands(void);
22void ShowExpertCommands(void);
23int ExpertsMenu(char* filename, struct GPTData* theGPT);
24
25int main(int argc, char* argv[]) {
26 GPTData theGPT;
27 int doMore = 1;
28 char* device = NULL;
29
srs5694e4ac11e2009-08-31 10:13:04 -040030 printf("GPT fdisk (gdisk) version 0.4.1\n\n");
srs5694e7b4ff92009-08-18 13:16:10 -040031
32 if (argc == 2) { // basic usage
33 if (SizesOK()) {
34 doMore = theGPT.LoadPartitions(argv[1]);
35 while (doMore) {
36 doMore = DoCommand(argv[1], &theGPT);
37 } // while
38 } // if
39 } else if (argc == 3) { // usage with "-l" option
40 if (SizesOK()) {
41 if (strcmp(argv[1], "-l") == 0) {
42 device = argv[2];
43 } else if (strcmp(argv[2], "-l") == 0) {
44 device = argv[1];
45 } else { // 3 arguments, but none is "-l"
46 fprintf(stderr, "Usage: %s [-l] device_file\n", argv[0]);
47 } // if/elseif/else
48 if (device != NULL) {
49 doMore = theGPT.LoadPartitions(device);
50 if (doMore) theGPT.DisplayGPTData();
51 } // if
52 } // if
53 } else {
54 fprintf(stderr, "Usage: %s [-l] device_file\n", argv[0]);
55 } // if/else
56} // main
57
58// Accept a command and execute it. Returns 0 if the command includes
59// an exit condition (such as a q or w command), 1 if more commands
60// should be processed.
61int DoCommand(char* filename, struct GPTData* theGPT) {
62 char command, line[255];
63 int retval = 1;
64 PartTypes typeHelper;
65 uint32_t temp1, temp2;
66
67 printf("\nCommand (m for help): ");
68 fgets(line, 255, stdin);
69 sscanf(line, "%c", &command);
70 switch (command) {
srs5694221e0872009-08-29 15:00:31 -040071 case 'b': case 'B':
72 theGPT->XFormDisklabel();
73 break;
srs5694e7b4ff92009-08-18 13:16:10 -040074 case 'c': case 'C':
75 if (theGPT->GetPartRange(&temp1, &temp2) > 0)
76 theGPT->SetName(theGPT->GetPartNum());
77 else
78 printf("No partitions\n");
79 break;
80 case 'd': case 'D':
81 theGPT->DeletePartition();
82 break;
83 case 'i': case 'I':
84 theGPT->ShowDetails();
85 break;
86 case 'l': case 'L':
87 typeHelper.ShowTypes();
88 break;
89 case 'n': case 'N':
90 theGPT->CreatePartition();
91 break;
92 case 'o': case 'O':
93 theGPT->ClearGPTData();
srs5694c0ca8f82009-08-20 21:35:25 -040094 theGPT->MakeProtectiveMBR();
srs5694e7b4ff92009-08-18 13:16:10 -040095// theGPT->BlankPartitions();
96 break;
97 case 'p': case 'P':
98 theGPT->DisplayGPTData();
99 break;
100 case 'q': case 'Q':
101 retval = 0;
102 break;
103 case 's': case 'S':
104 theGPT->SortGPT();
105 printf("You may need to edit /etc/fstab and/or your boot loader configuration!\n");
106 break;
107 case 't': case 'T':
108 theGPT->ChangePartType();
109 break;
110 case 'v': case 'V':
111 if (theGPT->Verify() > 0) { // problems found
112 printf("You may be able to correct the problems by using options on the experts\n"
113 "menu (press 'x' at the command prompt). Good luck!\n");
114 } // if
115 break;
116 case 'w': case 'W':
117 if (theGPT->SaveGPTData() == 1)
118 retval = 0;
119 break;
120 case 'x': case 'X':
121 retval = ExpertsMenu(filename, theGPT);
122 break;
123 default:
124 ShowCommands();
125 break;
126 } // switch
127 return (retval);
128} // DoCommand()
129
130void ShowCommands(void) {
srs5694221e0872009-08-29 15:00:31 -0400131 printf("b\tconvert BSD disklabel partitions\n");
srs5694e7b4ff92009-08-18 13:16:10 -0400132 printf("c\tchange a partition's name\n");
133 printf("d\tdelete a partition\n");
134 printf("i\tshow detailed information on a partition\n");
135 printf("l\tlist available partition types\n");
136 printf("m\tprint this menu\n");
137 printf("n\tadd a new partition\n");
138 printf("o\tcreate a new empty GUID partition table (GPT)\n");
139 printf("p\tprint the partition table\n");
140 printf("q\tquit without saving changes\n");
141 printf("s\tsort partitions\n");
142 printf("t\tchange a partition's type code\n");
143 printf("v\tverify disk\n");
144 printf("w\twrite table to disk and exit\n");
145 printf("x\textra functionality (experts only)\n");
146} // ShowCommands()
147
148// Accept a command and execute it. Returns 0 if the command includes
149// an exit condition (such as a q or w command), 1 if more commands
150// should be processed.
151int ExpertsMenu(char* filename, struct GPTData* theGPT) {
152 char command, line[255], buFile[255];
153 int retval = 1;
154 PartTypes typeHelper;
155 uint32_t pn;
156 uint32_t temp1, temp2;
157 int goOn = 1;
158
159 do {
160 printf("\nExpert command (m for help): ");
161 fgets(line, 255, stdin);
162 sscanf(line, "%c", &command);
163 switch (command) {
164 case 'a': case 'A':
165 if (theGPT->GetPartRange(&temp1, &temp2) > 0)
166 theGPT->SetAttributes(theGPT->GetPartNum());
167 else
168 printf("No partitions\n");
169 break;
170 case 'b': case 'B':
171 theGPT->RebuildMainHeader();
172 break;
173 case 'c': case 'C':
174 printf("Warning! This will probably do weird things if you've converted an MBR to\n"
175 "GPT form and haven't yet saved the GPT! Proceed? ");
176 if (GetYN() == 'Y')
177 theGPT->LoadSecondTableAsMain();
178 break;
179 case 'd': case 'D':
180 theGPT->RebuildSecondHeader();
181 break;
182 case 'e': case 'E':
183 printf("Warning! This will probably do weird things if you've converted an MBR to\n"
184 "GPT form and haven't yet saved the GPT! Proceed? ");
185 if (GetYN() == 'Y')
186 theGPT->LoadMainTable();
187 break;
188 case 'f': case 'F':
189 if (theGPT->GetPartRange(&temp1, &temp2) > 0) {
190 pn = theGPT->GetPartNum();
191 printf("Enter the partition's new unique GUID:\n");
192 theGPT->SetPartitionGUID(pn, GetGUID());
193 } else printf("No partitions\n");
194 break;
195 case 'g': case 'G':
196 printf("Enter the disk's unique GUID:\n");
197 theGPT->SetDiskGUID(GetGUID());
198 break;
srs5694c0ca8f82009-08-20 21:35:25 -0400199 case 'h': case 'H':
srs5694e7b4ff92009-08-18 13:16:10 -0400200 theGPT->MakeHybrid();
srs5694c0ca8f82009-08-20 21:35:25 -0400201 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400202 case 'i': case 'I':
203 theGPT->ShowDetails();
204 break;
205 case 'k': case 'K':
206 printf("Enter backup filename to save: ");
207 fgets(line, 255, stdin);
208 sscanf(line, "%s", &buFile);
209 theGPT->SaveGPTBackup(buFile);
210 break;
211 case 'l': case 'L':
212 printf("Enter backup filename to load: ");
213 fgets(line, 255, stdin);
214 sscanf(line, "%s", &buFile);
215 theGPT->LoadGPTBackup(buFile);
216 break;
217 case 'n': case 'N':
218 theGPT->MakeProtectiveMBR();
219 break;
220 case 'o': case 'O':
221 theGPT->DisplayMBRData();
222 break;
223 case 'p': case 'P':
224 theGPT->DisplayGPTData();
225 break;
226 case 'q': case 'Q':
227 retval = 0;
228 goOn = 0;
229 break;
230 case 'r': case 'R':
231 goOn = 0;
232 break;
233 case 's': case 'S':
234 theGPT->ResizePartitionTable();
235 break;
236 case 'v': case 'V':
237 theGPT->Verify();
238 break;
239 case 'w': case 'W':
240 if (theGPT->SaveGPTData() == 1) {
241 retval = 0;
242 goOn = 0;
243 } // if
244 break;
srs5694c0ca8f82009-08-20 21:35:25 -0400245 case 'z': case 'Z':
246 if (theGPT->DestroyGPT() == 1) {
247 retval = 0;
248 goOn = 0;
249 }
250 break;
srs5694e7b4ff92009-08-18 13:16:10 -0400251 default:
252 ShowExpertCommands();
253 break;
254 } // switch
255 } while (goOn);
256 return (retval);
257} // ExpertsMenu()
258
259void ShowExpertCommands(void) {
260 printf("a\tset attributes\n");
261 printf("b\tuse backup GPT header (rebuilding main)\n");
262 printf("c\tload backup partition table from disk (rebuilding main)\n");
263 printf("d\tuse main GPT header (rebuilding backup)\n");
264 printf("e\tload main partition table from disk (rebuilding backup)\n");
265 printf("f\tchange partition GUID\n");
266 printf("g\tchange disk GUID\n");
srs5694c0ca8f82009-08-20 21:35:25 -0400267 printf("h\tmake hybrid MBR\n");
srs5694e7b4ff92009-08-18 13:16:10 -0400268 printf("i\tshow detailed information on a partition\n");
269 printf("k\tsave partition data to a backup file\n");
270 printf("l\tload partition data from a backup file\n");
271 printf("m\tprint this menu\n");
272 printf("n\tcreate a new protective MBR\n");
273 printf("o\tprint protective MBR data\n");
274 printf("p\tprint the partition table\n");
275 printf("q\tquit without saving changes\n");
276 printf("r\treturn to main menu\n");
277 printf("s\tresize partition table\n");
278 printf("v\tverify disk\n");
279 printf("w\twrite table to disk and exit\n");
srs5694c0ca8f82009-08-20 21:35:25 -0400280 printf("z\tDestroy GPT data structures and exit\n");
srs5694e7b4ff92009-08-18 13:16:10 -0400281} // ShowExpertCommands()