summaryrefslogtreecommitdiff
path: root/gdisk.cc
blob: dcc2c513e7c79cdba030414d0ef897ce21653efc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
// gdisk.cc
// Program modelled after Linux fdisk, but it manipulates GPT partitions
// rather than MBR partitions.
//
// by Rod Smith, project began February 2009

/* This program is copyright (c) 2009 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"

// Function prototypes....
// int ReadPartitions(char* filename, struct GPTData* theGPT);
int DoCommand(char* filename, struct GPTData* theGPT);
void ShowCommands(void);
void ShowExpertCommands(void);
int ExpertsMenu(char* filename, struct GPTData* theGPT);

int main(int argc, char* argv[]) {
   GPTData theGPT;
   int doMore = 1;
   char* device = NULL;

   printf("GPT fdisk (gdisk) version 0.4.2\n\n");

    if (argc == 2) { // basic usage
      if (SizesOK()) {
         doMore = theGPT.LoadPartitions(argv[1]);
         while (doMore) {
            doMore = DoCommand(argv[1], &theGPT);
         } // while
      } // if
   } else if (argc == 3) { // usage with "-l" option
      if (SizesOK()) {
         if (strcmp(argv[1], "-l") == 0) {
            device = argv[2];
         } else if (strcmp(argv[2], "-l") == 0) {
            device = argv[1];
         } else { // 3 arguments, but none is "-l"
            fprintf(stderr, "Usage: %s [-l] device_file\n", argv[0]);
         } // if/elseif/else
         if (device != NULL) {
            doMore = theGPT.LoadPartitions(device);
            if (doMore) theGPT.DisplayGPTData();
         } // if
      } // if
   } else {
      fprintf(stderr, "Usage: %s [-l] device_file\n", argv[0]);
   } // 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;
   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()

void ShowCommands(void) {
   printf("b\tconvert BSD disklabel partitions\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("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("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");
} // 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) {
   char command, line[255], buFile[255];
   int retval = 1;
   PartTypes typeHelper;
   uint32_t pn;
   uint32_t temp1, temp2;
   int goOn = 1;

   do {
      printf("\nExpert command (m for help): ");
      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 '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");
               theGPT->SetPartitionGUID(pn, GetGUID());
            } else printf("No partitions\n");
            break;
         case 'g': case 'G':
            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);
            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':
            retval = 0;
	    goOn = 0;
	    break;
         case 'r': case 'R':
            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) {
               retval = 0;
               goOn = 0;
            } // if
            break;
         case 'z': case 'Z':
            if (theGPT->DestroyGPT() == 1) {
               retval = 0;
	       goOn = 0;
            }
            break;
         default:
            ShowExpertCommands();
            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("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("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("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");
} // ShowExpertCommands()