summaryrefslogtreecommitdiff
path: root/fixparts.cc
blob: 318c65e1ed61e92334e3763f85b59ee8d8b6b777 (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
// fixparts
// Program to fix certain types of damaged Master Boot Record (MBR) partition
// tables
//
// Copyright 2011 by Roderick W. Smith
//
// This program is distributed under the terms of the GNU GPL, as described
// in the COPYING file.
//
// Based on C++ classes originally created for GPT fdisk (gdisk and sgdisk)
// programs

#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <sstream>
#include "basicmbr.h"
#include "support.h"

using namespace std;

void DoMBR(BasicMBRData & mbrTable);

int main(int argc, char* argv[]) {
   BasicMBRData mbrTable;
   string device;

   cout << "FixParts " << GPTFDISK_VERSION << "\n";
   
   switch (argc) {
      case 1:
         cout << "Type device filename, or press <Enter> to exit: ";
         device = ReadString();
         if (device.length() == 0)
            exit(0);
         break;
      case 2:
         device = argv[1];
         break;
      default:
         cerr << "Usage: " << argv[0] << " device_filename\n";
         exit(1);
   } // switch

   cout << "\nLoading MBR data from " << device << "\n";
   if (!mbrTable.ReadMBRData(device)) {
      cerr << "\nUnable to read MBR data from '" << device << "'! Exiting!\n\n";
      exit(1);
   } // if

   // This switch() statement weeds out disks with GPT signatures and non-MBR
   // disks so we don't accidentally damage them....
   switch(mbrTable.GetValidity()) {
      case hybrid: case gpt:
         cerr << "\nThis disk appears to be a GPT disk. Use GNU Parted or GPT fdisk on it!\n";
         cerr << "Exiting!\n\n";
         exit(1);
         break;
      case invalid:
         cerr << "\nCannot find valid MBR data on '" << device << "'! Exiting!\n\n";
         exit(1);
         break;
      case mbr:
         DoMBR(mbrTable);
         break;
      default:
         cerr << "\nCannot determine the validity of the disk on '" << device
              << "'! Exiting!\n\n";
         exit(1);
         break;
   } // switch()
   return 0;
} // main()

// Do the bulk of the processing on actual MBR disks. First checks for old
// GPT data (note this is different from the earlier check; this one only
// looks for the GPT signatures in the main and backup GPT area, not for
// a protective partition in the MBR, which we know is NOT present, since
// if it were, this function would NOT be called!) and offers to destroy
// it, if found; then makes sure the partitions are in a consistent and
// legal state; then presents the MBR menu and, if it returns a "1" value
// (meaning the user opted to write changes), writes the table to disk.
void DoMBR(BasicMBRData & mbrTable) {
   int doItAgain;

   if (mbrTable.CheckForGPT() > 0) {
      cout << "\nNOTICE: GPT signatures detected on the disk, but no 0xEE protective "
           << "partition!\nThe GPT signatures are probably left over from a previous "
           << "partition table.\nDo you want to delete them (if you answer 'Y', this "
           << "will happen\nimmediately)? ";
      if (GetYN() == 'Y') {
         cout << "Erasing GPT data!\n";
         if (mbrTable.BlankGPTData() != 1)
            cerr << "GPT signature erasure failed!\n";
      } // if
   } // if

   mbrTable.MakeItLegal();
   do {
      doItAgain = 0;
      if (mbrTable.DoMenu() > 0) {
         cout << "\nFinal checks complete. About to write MBR data. THIS WILL OVERWRITE "
              << "EXISTING\nPARTITIONS!!\n\nDo you want to proceed? ";
         if (GetYN() == 'Y') {
            mbrTable.WriteMBRData();
            mbrTable.DiskSync();
            doItAgain = 0;
         } else {
            doItAgain = 1;
         } // else
      } // if
   } while (doItAgain);
} // DoMBR()