Added files for 0.7.0
diff --git a/mbrpart.cc b/mbrpart.cc
new file mode 100644
index 0000000..0214f48
--- /dev/null
+++ b/mbrpart.cc
@@ -0,0 +1,337 @@
+/*
+    MBRPart class, part of GPT fdisk program family.
+    Copyright (C) 2011  Roderick W. Smith
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#define __STDC_LIMIT_MACROS
+#define __STDC_CONSTANT_MACROS
+
+#include <stddef.h>
+#include <stdint.h>
+#include <iostream>
+#include "support.h"
+#include "mbrpart.h"
+
+using namespace std;
+
+uint32_t MBRPart::numHeads = MAX_HEADS;
+uint32_t MBRPart::numSecspTrack = MAX_SECSPERTRACK;
+uint64_t MBRPart::diskSize = 0;
+uint32_t MBRPart::blockSize = 512;
+int MBRPart::numInstances = 0;
+
+MBRPart::MBRPart() {
+   int i;
+
+   status = 0;
+   for (i = 0; i < 3; i++) {
+      firstSector[i] = 0;
+      lastSector[i] = 0;
+   } // for
+   partitionType = 0x00;
+   firstLBA = 0;
+   lengthLBA = 0;
+   includeAs = NONE;
+   canBePrimary = 0;
+   canBeLogical = 0;
+   if (numInstances == 0) {
+      numHeads = MAX_HEADS;
+      numSecspTrack = MAX_SECSPERTRACK;
+      diskSize = 0;
+      blockSize = 512;
+   } // if
+   numInstances++;
+}
+
+MBRPart::MBRPart(const MBRPart& orig) {
+   numInstances++;
+   operator=(orig);
+}
+
+MBRPart::~MBRPart() {
+   numInstances--;
+}
+
+MBRPart& MBRPart::operator=(const MBRPart& orig) {
+   int i;
+
+   status = orig.status;
+   for (i = 0; i < 3; i++) {
+      firstSector[i] = orig.firstSector[i];
+      lastSector[i] = orig.lastSector[i];
+   } // for
+   partitionType = orig.partitionType;
+   firstLBA = orig.firstLBA;
+   lengthLBA = orig.lengthLBA;
+   includeAs = orig.includeAs;
+   canBePrimary = orig.canBePrimary;
+   canBeLogical = orig.canBeLogical;
+   return *this;
+} // MBRPart::operator=(const MBRPart& orig)
+
+// Set partition data from packed MBRRecord structure.
+MBRPart& MBRPart::operator=(const struct MBRRecord& orig) {
+   int i;
+
+   status = orig.status;
+   for (i = 0; i < 3; i++) {
+      firstSector[i] = orig.firstSector[i];
+      lastSector[i] = orig.lastSector[i];
+   } // for
+   partitionType = orig.partitionType;
+   firstLBA = orig.firstLBA;
+   lengthLBA = orig.lengthLBA;
+   if (lengthLBA > 0)
+      includeAs = PRIMARY;
+   else
+      includeAs = NONE;
+   return *this;
+} // MBRPart::operator=(const struct MBRRecord& orig)
+
+/**************************************************
+ *                                                *
+ * Set information on partitions or disks without *
+ * interacting with the user....                  *
+ *                                                *
+ **************************************************/
+
+void MBRPart::SetGeometry(uint32_t heads, uint32_t sectors, uint64_t diskSize,
+                          uint32_t blockSize) {
+   numHeads = heads;
+   numSecspTrack = sectors;
+} // MBRPart::SetGeometry
+
+// Empty the partition (zero out all values).
+void MBRPart::Empty(void) {
+   status = UINT8_C(0);
+   firstSector[0] = UINT8_C(0);
+   firstSector[1] = UINT8_C(0);
+   firstSector[2] = UINT8_C(0);
+   partitionType = UINT8_C(0);
+   lastSector[0] = UINT8_C(0);
+   lastSector[1] = UINT8_C(0);
+   lastSector[2] = UINT8_C(0);
+   firstLBA = UINT32_C(0);
+   lengthLBA = UINT32_C(0);
+   includeAs = NONE;
+} // MBRPart::Empty()
+
+// Sets the type code, but silently refuses to change it to an extended type
+// code.
+// Returns 1 on success, 0 on failure (extended type code)
+int MBRPart::SetType(uint8_t typeCode, int isExtended) {
+   int allOK = 0;
+
+   if ((isExtended == 1) || ((typeCode != 0x05) && (typeCode != 0x0f) && (typeCode != 0x85))) {
+      partitionType = typeCode;
+      allOK = 1;
+   } // if
+   return allOK;
+} // MBRPart::SetType()
+
+void MBRPart::SetStartLBA(uint64_t start) {
+   if (start > UINT32_MAX)
+      cerr << "Partition start out of range! Continuing, but problems now likely!\n";
+   firstLBA = (uint32_t) start;
+   RecomputeCHS();
+} // MBRPart::SetStartLBA()
+
+void MBRPart::SetLengthLBA(uint64_t length) {
+   if (length > UINT32_MAX)
+      cerr << "Partition length out of range! Continuing, but problems now likely!\n";
+   lengthLBA = (uint32_t) length;
+   RecomputeCHS();
+} // MBRPart::SetLengthLBA()
+
+// Set the start point and length of the partition. This function takes LBA
+// values, sets them directly, and sets the CHS values based on the LBA
+// values and the current geometry settings.
+void MBRPart::SetLocation(uint64_t start, uint64_t length) {
+   if ((start > UINT32_MAX) || (length > UINT32_MAX)) {
+      cerr << "Partition values out of range in MBRPart::SetLocation()!\n"
+           << "Continuing, but strange problems are now likely!\n";
+   } // if
+   firstLBA = (uint32_t) start;
+   lengthLBA = (uint32_t) length;
+   RecomputeCHS();
+
+   // If this is a complete 0xEE protective MBR partition, max out its
+   // CHS last sector value, as per the GPT spec. (Set to 0xffffff,
+   // although the maximum legal MBR value is 0xfeffff, which is
+   // actually what GNU Parted and Apple's Disk Utility use, in
+   // violation of the GPT spec.)
+   if ((partitionType == 0xEE) && (firstLBA == 1) && (lengthLBA == diskSize - 2)) {
+      lastSector[0] = lastSector[1] = lastSector[2] = 0xFF;
+   } // if
+} // MBRPart::SetLocation()
+
+// Store the MBR data in the packed structure used for disk I/O...
+void MBRPart::StoreInStruct(MBRRecord* theStruct) {
+   int i;
+   
+   theStruct->firstLBA = firstLBA;
+   theStruct->lengthLBA = lengthLBA;
+   theStruct->partitionType = partitionType;
+   theStruct->status = status;
+   for (i = 0; i < 3; i++) {
+      theStruct->firstSector[i] = firstSector[i];
+      theStruct->lastSector[i] = lastSector[i];
+   } // for
+} // MBRPart::StoreInStruct()
+
+/**********************************************
+*                                            *
+* Get information on partitions or disks.... *
+*                                            *
+**********************************************/
+
+// Returns the last LBA value. Note that this can theoretically be a 33-bit
+// value, so we return a 64-bit value. If lengthLBA == 0, returns 0, even if
+// firstLBA is non-0.
+uint64_t MBRPart::GetLastLBA(void) const {
+   if (lengthLBA > 0)
+      return (uint64_t) firstLBA + (uint64_t) lengthLBA - UINT64_C(1);
+   else
+      return 0;
+} // MBRPart::GetLastLBA()
+
+// Returns 1 if other overlaps with the current partition, 0 if they don't
+// overlap
+int MBRPart::DoTheyOverlap (const MBRPart& other) {
+   return lengthLBA && other.lengthLBA &&
+          (firstLBA <= other.GetLastLBA()) != (GetLastLBA() < other.firstLBA);
+} // MBRPart::DoTheyOverlap()
+
+/*************************************************
+ *                                               *
+ * Adjust information on partitions or disks.... *
+ *                                               *
+ *************************************************/
+
+void MBRPart::RecomputeCHS(void) {
+   if (lengthLBA > 0) {
+      LBAtoCHS(firstLBA, firstSector);
+      LBAtoCHS(firstLBA + lengthLBA - 1, lastSector);
+   } // if
+} // MBRPart::RecomputeCHS()
+
+// Converts 32-bit LBA value to MBR-style CHS value. Returns 1 if conversion
+// was within the range that can be expressed by CHS (including 0, for an
+// empty partition), 0 if the value is outside that range, and -1 if chs is
+// invalid.
+int MBRPart::LBAtoCHS(uint32_t lba, uint8_t * chs) {
+   uint64_t cylinder, head, sector; // all numbered from 0
+   uint64_t remainder;
+   int retval = 1;
+   int done = 0;
+
+   if (chs != NULL) {
+      // Special case: In case of 0 LBA value, zero out CHS values....
+      if (lba == 0) {
+         chs[0] = chs[1] = chs[2] = UINT8_C(0);
+         done = 1;
+      } // if
+      // If LBA value is too large for CHS, max out CHS values....
+      if ((!done) && (lba >= (numHeads * numSecspTrack * MAX_CYLINDERS))) {
+         chs[0] = 254;
+         chs[1] = chs[2] = 255;
+         done = 1;
+         retval = 0;
+      } // if
+      // If neither of the above applies, compute CHS values....
+      if (!done) {
+         cylinder = lba / (numHeads * numSecspTrack);
+         remainder = lba - (cylinder * numHeads * numSecspTrack);
+         head = remainder / numSecspTrack;
+         remainder -= head * numSecspTrack;
+         sector = remainder;
+         if (head < numHeads)
+            chs[0] = (uint8_t) head;
+         else
+            retval = 0;
+         if (sector < numSecspTrack) {
+            chs[1] = (uint8_t) ((sector + 1) + (cylinder >> 8) * 64);
+            chs[2] = (uint8_t) (cylinder & UINT32_C(0xFF));
+         } else {
+            retval = 0;
+         } // if/else
+      } // if value is expressible and non-0
+   } else { // Invalid (NULL) chs pointer
+      retval = -1;
+   } // if CHS pointer valid
+   return (retval);
+} // MBRPart::LBAtoCHS()
+
+// Reverses the byte order, but only if we're on a big-endian platform.
+// Note that most data come in 8-bit structures, so don't need reversing;
+// only the LBA data needs to be reversed....
+void MBRPart::ReverseByteOrder(void) {
+   if (IsLittleEndian() == 0) {
+      ReverseBytes(&firstLBA, 4);
+      ReverseBytes(&lengthLBA, 4);
+   } // if
+} // MBRPart::ReverseByteOrder()
+
+/**************************
+ *                        *
+ * User I/O functions.... *
+ *                        *
+ **************************/
+
+// Show MBR data. Should update canBeLogical flags before calling.
+// If isGpt == 1, omits the "can be logical" and "can be primary" columns.
+void MBRPart::ShowData(int isGpt) {
+   char bootCode = ' ';
+
+   if (status && 0x80) // it's bootable
+      bootCode = '*';
+   cout.fill(' ');
+   cout << bootCode << "  ";
+   cout.width(13);
+   cout << firstLBA;
+   cout.width(13);
+   cout << GetLastLBA() << "   ";
+   switch (includeAs) {
+      case PRIMARY:
+         cout << "primary";
+         break;
+      case LOGICAL:
+         cout << "logical";
+         break;
+      case NONE:
+         cout << "omitted";
+         break;
+      default:
+         cout << "error  ";
+         break;
+   } // switch
+   cout.width(7);
+   if (!isGpt) {
+      if (canBeLogical)
+         cout << "     Y      ";
+      else
+         cout << "            ";
+      if (canBePrimary)
+         cout << "  Y      ";
+      else
+         cout << "         ";
+   } // if
+   cout << "0x";
+   cout.width(2);
+   cout.fill('0');
+   cout << hex << (int) partitionType << dec << "\n";
+} // MBRPart::ShowData()
\ No newline at end of file