From 96312236d7f0c857efc95871a31857e24ecdc81b Mon Sep 17 00:00:00 2001 From: srs5694 Date: Sat, 12 Mar 2011 01:22:42 -0500 Subject: Added files for 0.7.0 --- mbrpart.cc | 337 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 mbrpart.cc (limited to 'mbrpart.cc') 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 +#include +#include +#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 -- cgit v1.2.1