1 // fixparts
2 // Program to fix certain types of damaged Master Boot Record (MBR) partition
3 // tables
4 //
5 // Copyright 2011 by Roderick W. Smith
6 //
7 // This program is distributed under the terms of the GNU GPL, as described
8 // in the COPYING file.
9 //
10 // Based on C++ classes originally created for GPT fdisk (gdisk and sgdisk)
11 // programs
12 
13 #include <stdio.h>
14 #include <string.h>
15 #include <string>
16 #include <iostream>
17 #include <sstream>
18 #include "basicmbr.h"
19 #include "support.h"
20 
21 using namespace std;
22 
23 void DoMBR(BasicMBRData & mbrTable);
24 
main(int argc,char * argv[])25 int main(int argc, char* argv[]) {
26    BasicMBRData mbrTable;
27    string device;
28 
29    cout << "FixParts " << GPTFDISK_VERSION << "\n";
30 
31    switch (argc) {
32       case 1:
33          cout << "Type device filename, or press <Enter> to exit: ";
34          device = ReadString();
35          if (device.length() == 0)
36             exit(0);
37          break;
38       case 2:
39          device = argv[1];
40          break;
41       default:
42          cerr << "Usage: " << argv[0] << " device_filename\n";
43          exit(1);
44    } // switch
45 
46    cout << "\nLoading MBR data from " << device << "\n";
47    if (!mbrTable.ReadMBRData(device)) {
48       cerr << "\nUnable to read MBR data from '" << device << "'! Exiting!\n\n";
49       exit(1);
50    } // if
51 
52    // This switch() statement weeds out disks with GPT signatures and non-MBR
53    // disks so we don't accidentally damage them....
54    switch(mbrTable.GetValidity()) {
55       case hybrid: case gpt:
56          cerr << "\nThis disk appears to be a GPT disk. Use GNU Parted or GPT fdisk on it!\n";
57          cerr << "Exiting!\n\n";
58          exit(1);
59          break;
60       case invalid:
61          cerr << "\nCannot find valid MBR data on '" << device << "'! Exiting!\n\n";
62          exit(1);
63          break;
64       case mbr:
65          DoMBR(mbrTable);
66          break;
67       default:
68          cerr << "\nCannot determine the validity of the disk on '" << device
69               << "'! Exiting!\n\n";
70          exit(1);
71          break;
72    } // switch()
73    return 0;
74 } // main()
75 
76 // Do the bulk of the processing on actual MBR disks. First checks for old
77 // GPT data (note this is different from the earlier check; this one only
78 // looks for the GPT signatures in the main and backup GPT area, not for
79 // a protective partition in the MBR, which we know is NOT present, since
80 // if it were, this function would NOT be called!) and offers to destroy
81 // it, if found; then makes sure the partitions are in a consistent and
82 // legal state; then presents the MBR menu and, if it returns a "1" value
83 // (meaning the user opted to write changes), writes the table to disk.
DoMBR(BasicMBRData & mbrTable)84 void DoMBR(BasicMBRData & mbrTable) {
85    int doItAgain;
86 
87    if (mbrTable.CheckForGPT() > 0) {
88       cout << "\nNOTICE: GPT signatures detected on the disk, but no 0xEE protective "
89            << "partition!\nThe GPT signatures are probably left over from a previous "
90            << "partition table.\nDo you want to delete them (if you answer 'Y', this "
91            << "will happen\nimmediately)? ";
92       if (GetYN() == 'Y') {
93          cout << "Erasing GPT data!\n";
94          if (mbrTable.BlankGPTData() != 1)
95             cerr << "GPT signature erasure failed!\n";
96       } // if
97    } // if
98 
99    mbrTable.MakeItLegal();
100    do {
101       doItAgain = 0;
102       if (mbrTable.DoMenu() > 0) {
103          cout << "\nFinal checks complete. About to write MBR data. THIS WILL OVERWRITE "
104               << "EXISTING\nPARTITIONS!!\n\nDo you want to proceed? ";
105          if (GetYN() == 'Y') {
106             mbrTable.WriteMBRData();
107             mbrTable.DiskSync();
108             doItAgain = 0;
109          } else {
110             doItAgain = 1;
111          } // else
112       } // if
113    } while (doItAgain);
114 } // DoMBR()
115