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
21using namespace std;
22
23void DoMBR(BasicMBRData & mbrTable);
24
25int 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.
84void 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