summaryrefslogtreecommitdiff
path: root/mbrpart.cc
diff options
context:
space:
mode:
authorsrs5694 <srs5694@users.sourceforge.net>2011-03-12 01:22:42 -0500
committersrs5694 <srs5694@users.sourceforge.net>2011-03-12 01:22:42 -0500
commit96312236d7f0c857efc95871a31857e24ecdc81b (patch)
tree265d546e4d67b087399a76f683f3da0e4cb88b4f /mbrpart.cc
parent64cbd171067eb34054741bfcd73f0b91d727a371 (diff)
downloadsgdisk-96312236d7f0c857efc95871a31857e24ecdc81b.tar.gz
Added files for 0.7.0
Diffstat (limited to 'mbrpart.cc')
-rw-r--r--mbrpart.cc337
1 files changed, 337 insertions, 0 deletions
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