Misc. updates and bug fixes

This commit is contained in:
srs5694
2010-01-27 23:03:40 -05:00
parent 546a9c7c36
commit fed16d043a
20 changed files with 800 additions and 758 deletions

View File

@@ -1,6 +1,10 @@
0.6.2 (?/??/2010): 0.6.2 (?/??/2010):
------------------ ------------------
- Fixed bug that caused new protective MBR to not be created when the
MBR was invalid and the GPT was damaged and the user opts to try to
use the GPT data.
- Enabled default partition type code of 0700 when creating partitions - Enabled default partition type code of 0700 when creating partitions
or changing their type codes. (Type 0700, Linux/Windows data, is set if or changing their type codes. (Type 0700, Linux/Windows data, is set if
the user hits the Enter key alone.) the user hits the Enter key alone.)

View File

@@ -11,6 +11,7 @@
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <iostream>
#include "attributes.h" #include "attributes.h"
using namespace std; using namespace std;
@@ -25,14 +26,14 @@ Attributes::Attributes(void) {
// appropriate name // appropriate name
for (i = 1; i < NUM_ATR; i++) { for (i = 1; i < NUM_ATR; i++) {
sprintf(temp, "Undefined bit #%d", i); sprintf(temp, "Undefined bit #%d", i);
strcpy(atNames[i], temp); atNames[i] = temp;
} // for } // for
// Now reset those names that are defined.... // Now reset those names that are defined....
strcpy(atNames[0], "system partition"); atNames[0] = "system partition";
strcpy(atNames[60], "read-only"); atNames[60] = "read-only";
strcpy(atNames[62], "hidden"); atNames[62] = "hidden";
strcpy(atNames[63], "do not automount"); atNames[63] = "do not automount";
} // Attributes constructor } // Attributes constructor
// Destructor. // Destructor.
@@ -43,16 +44,18 @@ Attributes::~Attributes(void) {
void Attributes::DisplayAttributes(void) { void Attributes::DisplayAttributes(void) {
int i; int i;
printf("Attribute value is %llX. Set fields are:\n", cout << "Attribute value is ";
(unsigned long long) attributes); cout.setf(ios::uppercase);
cout.fill('0');
cout.width(16);
cout << hex << attributes << dec << ". Set fields are:\n";
for (i = 0; i < NUM_ATR; i++) { for (i = 0; i < NUM_ATR; i++) {
if (((attributes >> i) % 2) == 1) { // bit is set if (((attributes >> i) % 2) == 1) { // bit is set
/* if (strncmp("Undefined", atNames[i], 9) != 0) if (atNames[NUM_ATR - i - 1].substr(0, 9) != "Undefined")
printf("%s\n", atNames[i]); */ cout << atNames[NUM_ATR - i - 1] << "\n";
if (strncmp("Undefined", atNames[NUM_ATR - i - 1], 9) != 0)
printf("%s\n", atNames[NUM_ATR - i - 1]);
} // if } // if
} // for } // for
cout.fill(' ');
} // Attributes::DisplayAttributes() } // Attributes::DisplayAttributes()
// Prompt user for attribute changes // Prompt user for attribute changes
@@ -60,23 +63,22 @@ void Attributes::ChangeAttributes(void) {
int response, i; int response, i;
uint64_t bitValue; uint64_t bitValue;
printf("Known attributes are:\n"); cout << "Known attributes are:\n";
for (i = 0; i < NUM_ATR; i++) { for (i = 0; i < NUM_ATR; i++) {
if (strncmp("Undefined", atNames[i], 9) != 0) if (atNames[i].substr(0, 9) != "Undefined")
printf("%d - %s\n", i, atNames[i]); cout << i << " - " << atNames[i] << "\n";
} // for } // for
do { do {
response = GetNumber(0, 64, -1, "Toggle which attribute field (0-63, 64 to exit): "); response = GetNumber(0, 64, -1, (string) "Toggle which attribute field (0-63, 64 to exit): ");
if (response != 64) { if (response != 64) {
bitValue = PowerOf2(NUM_ATR - response - 1); // Find the integer value of the bit bitValue = PowerOf2(NUM_ATR - response - 1); // Find the integer value of the bit
// bitValue = PowerOf2(response); // Find the integer value of the bit
if ((bitValue & attributes) == bitValue) { // bit is set if ((bitValue & attributes) == bitValue) { // bit is set
attributes -= bitValue; // so unset it attributes -= bitValue; // so unset it
printf("Have disabled the '%s' attribute.\n", atNames[response]); cout << "Have disabled the '" << atNames[response] << "' attribute.\n";
} else { // bit is not set } else { // bit is not set
attributes += bitValue; // so set it attributes += bitValue; // so set it
printf("Have enabled the '%s' attribute.\n", atNames[response]); cout << "Have enabled the '" << atNames[response] << "' attribute.\n";
} // if/else } // if/else
} // if } // if
} while (response != 64); } while (response != 64);

View File

@@ -18,7 +18,7 @@ using namespace std;
class Attributes { class Attributes {
protected: protected:
uint64_t attributes; uint64_t attributes;
char atNames[NUM_ATR][ATR_NAME_SIZE]; string atNames[NUM_ATR];
public: public:
Attributes(void); Attributes(void);
~Attributes(void); ~Attributes(void);

115
bsd.cc
View File

@@ -14,9 +14,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <fcntl.h> #include <fcntl.h>
#include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <iostream>
#include <string>
#include "support.h" #include "support.h"
#include "bsd.h" #include "bsd.h"
@@ -41,39 +42,30 @@ BSDData::~BSDData(void) {
// Read BSD disklabel data from the specified device filename. This function // Read BSD disklabel data from the specified device filename. This function
// just opens the device file and then calls an overloaded function to do // just opens the device file and then calls an overloaded function to do
// the bulk of the work. // the bulk of the work. Returns 1 on success, 0 on failure.
int BSDData::ReadBSDData(char* device, uint64_t startSector, uint64_t endSector) { int BSDData::ReadBSDData(string *device, uint64_t startSector, uint64_t endSector) {
int allOK = 1, tempMyDisk = 0; int allOK = 1;
DiskIO myDisk;
if (device != NULL) { if (*device != "") {
if (myDisk == NULL) { if (myDisk.OpenForRead(*device)) {
myDisk = new DiskIO; allOK = ReadBSDData(&myDisk, startSector, endSector);
tempMyDisk = 1;
} // if
if (myDisk->OpenForRead(device)) {
ReadBSDData(myDisk, startSector, endSector);
} else { } else {
allOK = 0; allOK = 0;
} // if/else } // if/else
myDisk->Close(); myDisk.Close();
} else { } else {
allOK = 0; allOK = 0;
} // if/else } // if/else
if (tempMyDisk) {
delete myDisk;
myDisk = NULL;
} // if
return allOK; return allOK;
} // BSDData::ReadBSDData() (device filename version) } // BSDData::ReadBSDData() (device filename version)
// Load the BSD disklabel data from an already-opened disk // Load the BSD disklabel data from an already-opened disk
// file, starting with the specified sector number. // file, starting with the specified sector number.
void BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSector) { int BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSector) {
uint8_t buffer[4096]; // I/O buffer uint8_t buffer[4096]; // I/O buffer
int i, err, foundSig = 0, bigEnd = 0; int i, err, foundSig = 0, bigEnd = 0, allOK = 1;
int relative = 0; // assume absolute partition sector numbering int relative = 0; // assume absolute partition sector numbering
uint32_t realSig; uint32_t realSig;
uint32_t* temp32; uint32_t* temp32;
@@ -81,54 +73,59 @@ void BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSec
BSDRecord* tempRecords; BSDRecord* tempRecords;
int offset[NUM_OFFSETS] = { LABEL_OFFSET1, LABEL_OFFSET2 }; int offset[NUM_OFFSETS] = { LABEL_OFFSET1, LABEL_OFFSET2 };
myDisk = theDisk; // myDisk = theDisk;
labelFirstLBA = startSector; labelFirstLBA = startSector;
labelLastLBA = endSector; labelLastLBA = endSector;
offset[1] = myDisk->GetBlockSize(); offset[1] = theDisk->GetBlockSize();
// Read 4096 bytes (eight 512-byte sectors or equivalent) // Read 4096 bytes (eight 512-byte sectors or equivalent)
// into memory; we'll extract data from this buffer. // into memory; we'll extract data from this buffer.
// (Done to work around FreeBSD limitation on size of reads // (Done to work around FreeBSD limitation on size of reads
// from block devices.) // from block devices.)
myDisk->Seek(startSector /* * myDisk->GetBlockSize() */); allOK = theDisk->Seek(startSector);
myDisk->Read(buffer, 4096); if (allOK) allOK = theDisk->Read(buffer, 4096);
// Do some strangeness to support big-endian architectures... // Do some strangeness to support big-endian architectures...
bigEnd = (IsLittleEndian() == 0); bigEnd = (IsLittleEndian() == 0);
realSig = BSD_SIGNATURE; realSig = BSD_SIGNATURE;
if (bigEnd) if (bigEnd && allOK)
ReverseBytes(&realSig, 4); ReverseBytes(&realSig, 4);
// Look for the signature at any of two locations. // Look for the signature at any of two locations.
// Note that the signature is repeated at both the original // Note that the signature is repeated at both the original
// offset and 132 bytes later, so we need two checks.... // offset and 132 bytes later, so we need two checks....
i = 0; if (allOK) {
do { i = 0;
temp32 = (uint32_t*) &buffer[offset[i]]; do {
signature = *temp32; temp32 = (uint32_t*) &buffer[offset[i]];
if (signature == realSig) { // found first, look for second signature = *temp32;
temp32 = (uint32_t*) &buffer[offset[i] + 132]; if (signature == realSig) { // found first, look for second
signature2 = *temp32; temp32 = (uint32_t*) &buffer[offset[i] + 132];
if (signature2 == realSig) { signature2 = *temp32;
foundSig = 1; if (signature2 == realSig) {
labelStart = offset[i]; foundSig = 1;
} // if found signature labelStart = offset[i];
} // if/else } // if found signature
i++; } // if/else
} while ((!foundSig) && (i < NUM_OFFSETS)); i++;
} while ((!foundSig) && (i < NUM_OFFSETS));
allOK = foundSig;
} // if
// Load partition metadata from the buffer.... // Load partition metadata from the buffer....
temp32 = (uint32_t*) &buffer[labelStart + 40]; if (allOK) {
sectorSize = *temp32; temp32 = (uint32_t*) &buffer[labelStart + 40];
temp16 = (uint16_t*) &buffer[labelStart + 138]; sectorSize = *temp32;
numParts = *temp16; temp16 = (uint16_t*) &buffer[labelStart + 138];
numParts = *temp16;
} // if
// Make it big-endian-aware.... // Make it big-endian-aware....
if (IsLittleEndian() == 0) if ((IsLittleEndian() == 0) && allOK)
ReverseMetaBytes(); ReverseMetaBytes();
// Check validity of the data and flag it appropriately.... // Check validity of the data and flag it appropriately....
if (foundSig && (numParts <= MAX_BSD_PARTS)) { if (foundSig && (numParts <= MAX_BSD_PARTS) && allOK) {
state = bsd; state = bsd;
} else { } else {
state = bsd_invalid; state = bsd_invalid;
@@ -167,7 +164,8 @@ void BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSec
} // if } // if
} // if signatures OK } // if signatures OK
// DisplayBSDData(); // DisplayBSDData();
} // BSDData::ReadBSDData(int fd, uint64_t startSector) return allOK;
} // BSDData::ReadBSDData(DiskIO* theDisk, uint64_t startSector)
// Reverse metadata's byte order; called only on big-endian systems // Reverse metadata's byte order; called only on big-endian systems
void BSDData::ReverseMetaBytes(void) { void BSDData::ReverseMetaBytes(void) {
@@ -182,12 +180,19 @@ void BSDData::DisplayBSDData(void) {
int i; int i;
if (state == bsd) { if (state == bsd) {
printf("BSD partitions:\n"); cout << "BSD partitions:\n";
printf("Number\t Start (sector)\t Length (sectors)\tType\n");
for (i = 0; i < numParts; i++) { for (i = 0; i < numParts; i++) {
printf("%4d\t%13lu\t%15lu \t0x%02X\n", i + 1, cout.width(4);
(unsigned long) partitions[i].firstLBA, cout << i + 1 << "\t";
(unsigned long) partitions[i].lengthLBA, partitions[i].fsType); cout.width(13);
cout << partitions[i].firstLBA << "\t";
cout.width(15);
cout << partitions[i].lengthLBA << " \t0x";
cout.width(2);
cout.fill('0');
cout.setf(ios::uppercase);
cout << hex << (int) partitions[i].fsType << "\n" << dec;
cout.fill(' ');
} // for } // for
} // if } // if
} // BSDData::DisplayBSDData() } // BSDData::DisplayBSDData()
@@ -199,14 +204,14 @@ int BSDData::ShowState(void) {
switch (state) { switch (state) {
case bsd_invalid: case bsd_invalid:
printf(" BSD: not present\n"); cout << " BSD: not present\n";
break; break;
case bsd: case bsd:
printf(" BSD: present\n"); cout << " BSD: present\n";
retval = 1; retval = 1;
break; break;
default: default:
printf("\a BSD: unknown -- bug!\n"); cout << "\a BSD: unknown -- bug!\n";
break; break;
} // switch } // switch
return retval; return retval;
@@ -318,7 +323,7 @@ GPTPart BSDData::AsGPT(int i) {
guid.SetType(0x0700); break; guid.SetType(0x0700); break;
} // switch } // switch
// Set the partition name to the name of the type code.... // Set the partition name to the name of the type code....
guid.SetName((unsigned char*) guid.GetNameType().c_str()); guid.SetName(guid.GetNameType());
} // if } // if
return guid; return guid;
} // BSDData::AsGPT() } // BSDData::AsGPT()

5
bsd.h
View File

@@ -69,12 +69,11 @@ class BSDData {
uint64_t labelLastLBA; // final sector of BSD disklabel uint64_t labelLastLBA; // final sector of BSD disklabel
uint64_t labelStart; // BSD disklabel start point in bytes from labelFirstLBA uint64_t labelStart; // BSD disklabel start point in bytes from labelFirstLBA
BSDValidity state; BSDValidity state;
DiskIO *myDisk;
public: public:
BSDData(void); BSDData(void);
~BSDData(void); ~BSDData(void);
int ReadBSDData(char* deviceFilename, uint64_t startSector, uint64_t endSector); int ReadBSDData(string *deviceFilename, uint64_t startSector, uint64_t endSector);
void ReadBSDData(DiskIO *myDisk, uint64_t startSector, uint64_t endSector); int ReadBSDData(DiskIO *myDisk, uint64_t startSector, uint64_t endSector);
void ReverseMetaBytes(void); void ReverseMetaBytes(void);
void DisplayBSDData(void); void DisplayBSDData(void);
int ShowState(void); // returns 1 if BSD disklabel detected int ShowState(void); // returns 1 if BSD disklabel detected

View File

@@ -16,7 +16,7 @@
#define __STDC_CONSTANT_MACROS #define __STDC_CONSTANT_MACROS
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <stdio.h> #include <string.h>
#include <string> #include <string>
#include <stdint.h> #include <stdint.h>
#include <errno.h> #include <errno.h>
@@ -24,7 +24,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <iostream> #include <iostream>
#include "support.h"
#include "diskio.h" #include "diskio.h"
using namespace std; using namespace std;
@@ -50,10 +49,9 @@ int DiskIO::OpenForRead(void) {
if (shouldOpen) { if (shouldOpen) {
fd = open(realFilename.c_str(), O_RDONLY); fd = open(realFilename.c_str(), O_RDONLY);
if (fd == -1) { if (fd == -1) {
fprintf(stderr, "Problem opening %s for reading! Error is %d\n", cerr << "Problem opening " << realFilename << " for reading! Error is " << errno << "\n";
realFilename.c_str(), errno);
if (errno == EACCES) { // User is probably not running as root if (errno == EACCES) { // User is probably not running as root
fprintf(stderr, "You must run this program as root or use sudo!\n"); cerr << "You must run this program as root or use sudo!\n";
} // if } // if
realFilename = ""; realFilename = "";
userFilename = ""; userFilename = "";
@@ -82,7 +80,7 @@ int DiskIO::OpenForWrite(void) {
#ifdef __APPLE__ #ifdef __APPLE__
// MacOS X requires a shared lock under some circumstances.... // MacOS X requires a shared lock under some circumstances....
if (fd < 0) { if (fd < 0) {
fd = open(realFilename.c_str(), O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH | O_SHLOCK); fd = open(realFilename.c_str(), O_WRONLY | O_SHLOCK);
} // if } // if
#endif #endif
if (fd >= 0) { if (fd >= 0) {
@@ -133,8 +131,8 @@ int DiskIO::GetBlockSize(void) {
// 32-bit code returns EINVAL, I don't know why. I know I'm treading on // 32-bit code returns EINVAL, I don't know why. I know I'm treading on
// thin ice here, but it should be OK in all but very weird cases.... // thin ice here, but it should be OK in all but very weird cases....
if ((errno != ENOTTY) && (errno != EINVAL)) { if ((errno != ENOTTY) && (errno != EINVAL)) {
printf("\aError %d when determining sector size! Setting sector size to %d\n", cerr << "\aError " << errno << " when determining sector size! Setting sector size to "
errno, SECTOR_SIZE); << SECTOR_SIZE << "\n";
} // if } // if
} // if (err == -1) } // if (err == -1)
} // if (isOpen) } // if (isOpen)
@@ -155,8 +153,8 @@ void DiskIO::DiskSync(void) {
if (isOpen) { if (isOpen) {
sync(); sync();
#ifdef __APPLE__ #ifdef __APPLE__
printf("Warning: The kernel may continue to use old or deleted partitions.\n" cout << "Warning: The kernel may continue to use old or deleted partitions.\n"
"You should reboot or remove the drive.\n"); << "You should reboot or remove the drive.\n";
/* don't know if this helps /* don't know if this helps
* it definitely will get things on disk though: * it definitely will get things on disk though:
* http://topiks.org/mac-os-x/0321278542/ch12lev1sec8.html */ * http://topiks.org/mac-os-x/0321278542/ch12lev1sec8.html */
@@ -166,22 +164,22 @@ void DiskIO::DiskSync(void) {
#ifdef __FreeBSD__ #ifdef __FreeBSD__
sleep(2); sleep(2);
i = ioctl(fd, DIOCGFLUSH); i = ioctl(fd, DIOCGFLUSH);
printf("Warning: The kernel may continue to use old or deleted partitions.\n" cout << "Warning: The kernel may continue to use old or deleted partitions.\n"
"You should reboot or remove the drive.\n"); << "You should reboot or remove the drive.\n";
platformFound++; platformFound++;
#endif #endif
#ifdef __linux__ #ifdef __linux__
sleep(2); sleep(2);
i = ioctl(fd, BLKRRPART); i = ioctl(fd, BLKRRPART);
if (i) if (i)
printf("Warning: The kernel is still using the old partition table.\n" cout << "Warning: The kernel is still using the old partition table.\n"
"The new table will be used at the next reboot.\n"); << "The new table will be used at the next reboot.\n";
platformFound++; platformFound++;
#endif #endif
if (platformFound == 0) if (platformFound == 0)
fprintf(stderr, "Warning: Platform not recognized!\n"); cerr << "Warning: Platform not recognized!\n";
if (platformFound > 1) if (platformFound > 1)
fprintf(stderr, "\nWarning: We seem to be running on multiple platforms!\n"); cerr << "\nWarning: We seem to be running on multiple platforms!\n";
} // if (isOpen) } // if (isOpen)
} // DiskIO::DiskSync() } // DiskIO::DiskSync()
@@ -233,9 +231,6 @@ int DiskIO::Read(void* buffer, int numBytes) {
// Read the data into temporary space, then copy it to buffer // Read the data into temporary space, then copy it to buffer
retval = read(fd, tempSpace, numBlocks * blockSize); retval = read(fd, tempSpace, numBlocks * blockSize);
memcpy(buffer, tempSpace, numBytes); memcpy(buffer, tempSpace, numBytes);
/* for (i = 0; i < numBytes; i++) {
((char*) buffer)[i] = tempSpace[i];
} // for */
// Adjust the return value, if necessary.... // Adjust the return value, if necessary....
if (((numBlocks * blockSize) != numBytes) && (retval > 0)) if (((numBlocks * blockSize) != numBytes) && (retval > 0))
@@ -347,7 +342,7 @@ uint64_t DiskIO::DiskSize(int *err) {
platformFound++; platformFound++;
#endif #endif
if (platformFound != 1) if (platformFound != 1)
fprintf(stderr, "Warning! We seem to be running on no known platform!\n"); cerr << "Warning! We seem to be running on no known platform!\n";
// The above methods have failed, so let's assume it's a regular // The above methods have failed, so let's assume it's a regular
// file (a QEMU image, dd backup, or what have you) and see what // file (a QEMU image, dd backup, or what have you) and see what
@@ -356,8 +351,8 @@ uint64_t DiskIO::DiskSize(int *err) {
if (fstat64(fd, &st) == 0) { if (fstat64(fd, &st) == 0) {
bytes = (off_t) st.st_size; bytes = (off_t) st.st_size;
if ((bytes % UINT64_C(512)) != 0) if ((bytes % UINT64_C(512)) != 0)
fprintf(stderr, "Warning: File size is not a multiple of 512 bytes!" cerr << "Warning: File size is not a multiple of 512 bytes!"
" Misbehavior is likely!\n\a"); << " Misbehavior is likely!\n\a";
sectors = bytes / UINT64_C(512); sectors = bytes / UINT64_C(512);
} // if } // if
} // if } // if

View File

@@ -114,11 +114,11 @@ int DiskIO::FindAlignment(void) {
int err = -2, errnum = 0, result = 8, physicalSectorSize = 4096; int err = -2, errnum = 0, result = 8, physicalSectorSize = 4096;
uint64_t diskSize; uint64_t diskSize;
printf("Entering FindAlignment()\n"); cout << "Entering FindAlignment()\n";
#if defined (__linux__) && defined (BLKPBSZGET) #if defined (__linux__) && defined (BLKPBSZGET)
err = ioctl(fd, BLKPBSZGET, &physicalSectorSize); err = ioctl(fd, BLKPBSZGET, &physicalSectorSize);
printf("In FindAlignment(), physicalSectorSize = %d, err = %d\n", physicalSectorSize, err); cout << "In FindAlignment(), physicalSectorSize = " << physicalSectorSize
// printf("Tried to get hardware alignment; err is %d, sector size is %d\n", err, physicalSectorSize); << ", err = " << err << "\n";
#else #else
err = -1; err = -1;
#endif #endif

View File

@@ -59,10 +59,8 @@ class DiskIO {
#endif #endif
public: public:
DiskIO(void); DiskIO(void);
// DiskIO(const DiskIO & orig);
~DiskIO(void); ~DiskIO(void);
// DiskIO & operator=(const DiskIO & orig);
void MakeRealName(void); void MakeRealName(void);
int OpenForRead(string filename); int OpenForRead(string filename);
int OpenForRead(void); int OpenForRead(void);

185
gdisk.cc
View File

@@ -9,18 +9,20 @@
//#include <iostream> //#include <iostream>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <getopt.h> #include <getopt.h>
#include <string.h>
#include <string>
#include <iostream>
#include "mbr.h" #include "mbr.h"
#include "gpt.h" #include "gpt.h"
#include "support.h" #include "support.h"
// Function prototypes.... // Function prototypes....
void MainMenu(char* filename, struct GPTData* theGPT); void MainMenu(string filename, struct GPTData* theGPT);
void ShowCommands(void); void ShowCommands(void);
void ExpertsMenu(char* filename, struct GPTData* theGPT); void ExpertsMenu(string filename, struct GPTData* theGPT);
void ShowExpertCommands(void); void ShowExpertCommands(void);
void RecoveryMenu(char* filename, struct GPTData* theGPT); void RecoveryMenu(string filename, struct GPTData* theGPT);
void ShowRecoveryCommands(void); void ShowRecoveryCommands(void);
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
@@ -28,7 +30,7 @@ int main(int argc, char* argv[]) {
int doMore = 1; int doMore = 1;
char* device = NULL; char* device = NULL;
printf("GPT fdisk (gdisk) version %s\n\n", GPTFDISK_VERSION); cout << "GPT fdisk (gdisk) version " << GPTFDISK_VERSION << "\n\n";
if (argc == 2) { // basic usage if (argc == 2) { // basic usage
if (SizesOK()) { if (SizesOK()) {
@@ -44,22 +46,22 @@ int main(int argc, char* argv[]) {
} else if (strcmp(argv[2], "-l") == 0) { } else if (strcmp(argv[2], "-l") == 0) {
device = argv[1]; device = argv[1];
} else { // 3 arguments, but none is "-l" } else { // 3 arguments, but none is "-l"
fprintf(stderr, "Usage: %s [-l] device_file\n", argv[0]); cerr << "Usage: " << argv[0] << " [-l] device_file\n";
} // if/elseif/else } // if/elseif/else
if (device != NULL) { if (device != NULL) {
theGPT.JustLooking(); theGPT.JustLooking();
doMore = theGPT.LoadPartitions(device); doMore = theGPT.LoadPartitions((string) device);
if (doMore) theGPT.DisplayGPTData(); if (doMore) theGPT.DisplayGPTData();
} // if } // if
} // if } // if
} else { } else {
fprintf(stderr, "Usage: %s [-l] device_file\n", argv[0]); cerr << "Usage: " << argv[0] << " [-l] device_file\n";
} // if/else } // if/else
} // main } // main
// Accept a command and execute it. Returns only when the user // Accept a command and execute it. Returns only when the user
// wants to exit (such as after a 'w' or 'q' command). // wants to exit (such as after a 'w' or 'q' command).
void MainMenu(char* filename, struct GPTData* theGPT) { void MainMenu(string filename, struct GPTData* theGPT) {
char command, line[255], buFile[255]; char command, line[255], buFile[255];
char* junk; char* junk;
int goOn = 1; int goOn = 1;
@@ -67,12 +69,14 @@ void MainMenu(char* filename, struct GPTData* theGPT) {
uint32_t temp1, temp2; uint32_t temp1, temp2;
do { do {
printf("\nCommand (? for help): "); cout << "\nCommand (? for help): ";
junk = fgets(line, 255, stdin); junk = fgets(line, 255, stdin);
sscanf(line, "%c", &command); sscanf(line, "%c", &command);
switch (command) { switch (command) {
case '\n':
break;
case 'b': case 'B': case 'b': case 'B':
printf("Enter backup filename to save: "); cout << "Enter backup filename to save: ";
junk = fgets(line, 255, stdin); junk = fgets(line, 255, stdin);
sscanf(line, "%s", (char*) &buFile); sscanf(line, "%s", (char*) &buFile);
theGPT->SaveGPTBackup(buFile); theGPT->SaveGPTBackup(buFile);
@@ -81,7 +85,7 @@ void MainMenu(char* filename, struct GPTData* theGPT) {
if (theGPT->GetPartRange(&temp1, &temp2) > 0) if (theGPT->GetPartRange(&temp1, &temp2) > 0)
theGPT->SetName(theGPT->GetPartNum()); theGPT->SetName(theGPT->GetPartNum());
else else
printf("No partitions\n"); cout << "No partitions\n";
break; break;
case 'd': case 'D': case 'd': case 'D':
theGPT->DeletePartition(); theGPT->DeletePartition();
@@ -96,8 +100,8 @@ void MainMenu(char* filename, struct GPTData* theGPT) {
theGPT->CreatePartition(); theGPT->CreatePartition();
break; break;
case 'o': case 'O': case 'o': case 'O':
printf("This option deletes all partitions and creates a new " cout << "This option deletes all partitions and creates a new protective MBR.\n"
"protective MBR.\nProceed? "); << "Proceed? ";
if (GetYN() == 'Y') { if (GetYN() == 'Y') {
theGPT->ClearGPTData(); theGPT->ClearGPTData();
theGPT->MakeProtectiveMBR(); theGPT->MakeProtectiveMBR();
@@ -115,7 +119,7 @@ void MainMenu(char* filename, struct GPTData* theGPT) {
break; break;
case 's': case 'S': case 's': case 'S':
theGPT->SortGPT(); theGPT->SortGPT();
printf("You may need to edit /etc/fstab and/or your boot loader configuration!\n"); cout << "You may need to edit /etc/fstab and/or your boot loader configuration!\n";
break; break;
case 't': case 'T': case 't': case 'T':
theGPT->ChangePartType(); theGPT->ChangePartType();
@@ -139,27 +143,27 @@ void MainMenu(char* filename, struct GPTData* theGPT) {
} // MainMenu() } // MainMenu()
void ShowCommands(void) { void ShowCommands(void) {
printf("b\tback up GPT data to a file\n"); cout << "b\tback up GPT data to a file\n";
printf("c\tchange a partition's name\n"); cout << "c\tchange a partition's name\n";
printf("d\tdelete a partition\n"); cout << "d\tdelete a partition\n";
printf("i\tshow detailed information on a partition\n"); cout << "i\tshow detailed information on a partition\n";
printf("l\tlist known partition types\n"); cout << "l\tlist known partition types\n";
printf("n\tadd a new partition\n"); cout << "n\tadd a new partition\n";
printf("o\tcreate a new empty GUID partition table (GPT)\n"); cout << "o\tcreate a new empty GUID partition table (GPT)\n";
printf("p\tprint the partition table\n"); cout << "p\tprint the partition table\n";
printf("q\tquit without saving changes\n"); cout << "q\tquit without saving changes\n";
printf("r\trecovery and transformation options (experts only)\n"); cout << "r\trecovery and transformation options (experts only)\n";
printf("s\tsort partitions\n"); cout << "s\tsort partitions\n";
printf("t\tchange a partition's type code\n"); cout << "t\tchange a partition's type code\n";
printf("v\tverify disk\n"); cout << "v\tverify disk\n";
printf("w\twrite table to disk and exit\n"); cout << "w\twrite table to disk and exit\n";
printf("x\textra functionality (experts only)\n"); cout << "x\textra functionality (experts only)\n";
printf("?\tprint this menu\n"); cout << "?\tprint this menu\n";
} // ShowCommands() } // ShowCommands()
// Accept a recovery & transformation menu command. Returns only when the user // Accept a recovery & transformation menu command. Returns only when the user
// issues an exit command, such as 'w' or 'q'. // issues an exit command, such as 'w' or 'q'.
void RecoveryMenu(char* filename, struct GPTData* theGPT) { void RecoveryMenu(string filename, struct GPTData* theGPT) {
char command, line[255], buFile[255]; char command, line[255], buFile[255];
char* junk; char* junk;
PartTypes typeHelper; PartTypes typeHelper;
@@ -167,16 +171,18 @@ void RecoveryMenu(char* filename, struct GPTData* theGPT) {
int goOn = 1; int goOn = 1;
do { do {
printf("\nRecovery/transformation command (? for help): "); cout << "\nRecovery/transformation command (? for help): ";
junk = fgets(line, 255, stdin); junk = fgets(line, 255, stdin);
sscanf(line, "%c", &command); sscanf(line, "%c", &command);
switch (command) { switch (command) {
case '\n':
break;
case 'b': case 'B': case 'b': case 'B':
theGPT->RebuildMainHeader(); theGPT->RebuildMainHeader();
break; break;
case 'c': case 'C': case 'c': case 'C':
printf("Warning! This will probably do weird things if you've converted an MBR to\n" cout << "Warning! This will probably do weird things if you've converted an MBR to\n"
"GPT form and haven't yet saved the GPT! Proceed? "); << "GPT form and haven't yet saved the GPT! Proceed? ";
if (GetYN() == 'Y') if (GetYN() == 'Y')
theGPT->LoadSecondTableAsMain(); theGPT->LoadSecondTableAsMain();
break; break;
@@ -184,18 +190,18 @@ void RecoveryMenu(char* filename, struct GPTData* theGPT) {
theGPT->RebuildSecondHeader(); theGPT->RebuildSecondHeader();
break; break;
case 'e': case 'E': case 'e': case 'E':
printf("Warning! This will probably do weird things if you've converted an MBR to\n" cout << "Warning! This will probably do weird things if you've converted an MBR to\n"
"GPT form and haven't yet saved the GPT! Proceed? "); << "GPT form and haven't yet saved the GPT! Proceed? ";
if (GetYN() == 'Y') if (GetYN() == 'Y')
theGPT->LoadMainTable(); theGPT->LoadMainTable();
break; break;
case 'f': case 'F': case 'f': case 'F':
printf("Warning! This will destroy the currently defined partitions! Proceed? "); cout << "Warning! This will destroy the currently defined partitions! Proceed? ";
if (GetYN() == 'Y') { if (GetYN() == 'Y') {
if (theGPT->LoadMBR(filename) == 1) { // successful load if (theGPT->LoadMBR(filename) == 1) { // successful load
theGPT->XFormPartitions(); theGPT->XFormPartitions();
} else { } else {
printf("Problem loading MBR! GPT is untouched; regenerating protective MBR!\n"); cout << "Problem loading MBR! GPT is untouched; regenerating protective MBR!\n";
theGPT->MakeProtectiveMBR(); theGPT->MakeProtectiveMBR();
} // if/else } // if/else
} // if } // if
@@ -203,13 +209,13 @@ void RecoveryMenu(char* filename, struct GPTData* theGPT) {
case 'g': case 'G': case 'g': case 'G':
temp1 = theGPT->XFormToMBR(); temp1 = theGPT->XFormToMBR();
if (temp1 > 0) { if (temp1 > 0) {
printf("Converted %d partitions. Finalize and exit? ", temp1); cout << "Converted " << temp1 << " partitions. Finalize and exit? ";
if (GetYN() == 'Y') { if (GetYN() == 'Y') {
if (theGPT->DestroyGPT(0) > 0) if (theGPT->DestroyGPT(0) > 0)
goOn = 0; goOn = 0;
} else { } else {
theGPT->MakeProtectiveMBR(); theGPT->MakeProtectiveMBR();
printf("Note: New protective MBR created.\n"); cout << "Note: New protective MBR created.\n";
} // if/else } // if/else
} // if } // if
break; break;
@@ -220,7 +226,7 @@ void RecoveryMenu(char* filename, struct GPTData* theGPT) {
theGPT->ShowDetails(); theGPT->ShowDetails();
break; break;
case 'l': case 'L': case 'l': case 'L':
printf("Enter backup filename to load: "); cout << "Enter backup filename to load: ";
junk = fgets(line, 255, stdin); junk = fgets(line, 255, stdin);
sscanf(line, "%s", (char*) &buFile); sscanf(line, "%s", (char*) &buFile);
theGPT->LoadGPTBackup(buFile); theGPT->LoadGPTBackup(buFile);
@@ -261,29 +267,29 @@ void RecoveryMenu(char* filename, struct GPTData* theGPT) {
} // RecoveryMenu() } // RecoveryMenu()
void ShowRecoveryCommands(void) { void ShowRecoveryCommands(void) {
printf("b\tuse backup GPT header (rebuilding main)\n"); cout << "b\tuse backup GPT header (rebuilding main)\n";
printf("c\tload backup partition table from disk (rebuilding main)\n"); cout << "c\tload backup partition table from disk (rebuilding main)\n";
printf("d\tuse main GPT header (rebuilding backup)\n"); cout << "d\tuse main GPT header (rebuilding backup)\n";
printf("e\tload main partition table from disk (rebuilding backup)\n"); cout << "e\tload main partition table from disk (rebuilding backup)\n";
printf("f\tload MBR and build fresh GPT from it\n"); cout << "f\tload MBR and build fresh GPT from it\n";
printf("g\tconvert GPT into MBR and exit\n"); cout << "g\tconvert GPT into MBR and exit\n";
printf("h\tmake hybrid MBR\n"); cout << "h\tmake hybrid MBR\n";
printf("i\tshow detailed information on a partition\n"); cout << "i\tshow detailed information on a partition\n";
printf("l\tload partition data from a backup file\n"); cout << "l\tload partition data from a backup file\n";
printf("m\treturn to main menu\n"); cout << "m\treturn to main menu\n";
printf("o\tprint protective MBR data\n"); cout << "o\tprint protective MBR data\n";
printf("p\tprint the partition table\n"); cout << "p\tprint the partition table\n";
printf("q\tquit without saving changes\n"); cout << "q\tquit without saving changes\n";
printf("t\ttransform BSD disklabel partition\n"); cout << "t\ttransform BSD disklabel partition\n";
printf("v\tverify disk\n"); cout << "v\tverify disk\n";
printf("w\twrite table to disk and exit\n"); cout << "w\twrite table to disk and exit\n";
printf("x\textra functionality (experts only)\n"); cout << "x\textra functionality (experts only)\n";
printf("?\tprint this menu\n"); cout << "?\tprint this menu\n";
} // ShowRecoveryCommands() } // ShowRecoveryCommands()
// Accept an experts' menu command. Returns only after the user // Accept an experts' menu command. Returns only after the user
// selects an exit command, such as 'w' or 'q'. // selects an exit command, such as 'w' or 'q'.
void ExpertsMenu(char* filename, struct GPTData* theGPT) { void ExpertsMenu(string filename, struct GPTData* theGPT) {
char command, line[255]; char command, line[255];
char* junk; char* junk;
PartTypes typeHelper; PartTypes typeHelper;
@@ -292,40 +298,43 @@ void ExpertsMenu(char* filename, struct GPTData* theGPT) {
int goOn = 1; int goOn = 1;
do { do {
printf("\nExpert command (? for help): "); cout << "\nExpert command (? for help): ";
junk = fgets(line, 255, stdin); junk = fgets(line, 255, stdin);
sscanf(line, "%c", &command); sscanf(line, "%c", &command);
switch (command) { switch (command) {
case '\n':
break;
case 'a': case 'A': case 'a': case 'A':
if (theGPT->GetPartRange(&temp1, &temp2) > 0) if (theGPT->GetPartRange(&temp1, &temp2) > 0)
theGPT->SetAttributes(theGPT->GetPartNum()); theGPT->SetAttributes(theGPT->GetPartNum());
else else
printf("No partitions\n"); cout << "No partitions\n";
break; break;
case 'c': case 'C': case 'c': case 'C':
if (theGPT->GetPartRange(&temp1, &temp2) > 0) { if (theGPT->GetPartRange(&temp1, &temp2) > 0) {
pn = theGPT->GetPartNum(); pn = theGPT->GetPartNum();
printf("Enter the partition's new unique GUID:\n"); cout << "Enter the partition's new unique GUID:\n";
theGPT->SetPartitionGUID(pn, GetGUID()); theGPT->SetPartitionGUID(pn, GetGUID());
} else printf("No partitions\n"); } else cout << "No partitions\n";
break; break;
case 'd': case 'D': case 'd': case 'D':
printf("Partitions will begin on %d-sector boundaries.\n", cout << "Partitions will begin on " << theGPT->GetAlignment()
theGPT->GetAlignment()); << "-sector boundaries.\n";
break; break;
case 'e': case 'E': case 'e': case 'E':
printf("Relocating backup data structures to the end of the disk\n"); cout << "Relocating backup data structures to the end of the disk\n";
theGPT->MoveSecondHeaderToEnd(); theGPT->MoveSecondHeaderToEnd();
break; break;
case 'g': case 'G': case 'g': case 'G':
printf("Enter the disk's unique GUID:\n"); cout << "Enter the disk's unique GUID:\n";
theGPT->SetDiskGUID(GetGUID()); theGPT->SetDiskGUID(GetGUID());
break; break;
case 'i': case 'I': case 'i': case 'I':
theGPT->ShowDetails(); theGPT->ShowDetails();
break; break;
case 'l': case 'L': case 'l': case 'L':
temp1 = GetNumber(1, 128, 8, "Enter the sector alignment value (1-128, default = 8): "); temp1 = GetNumber(1, 128, 8, (string)
"Enter the sector alignment value (1-128, default = 8): ");
theGPT->SetAlignment(temp1); theGPT->SetAlignment(temp1);
break; break;
case 'm': case 'M': case 'm': case 'M':
@@ -372,22 +381,22 @@ void ExpertsMenu(char* filename, struct GPTData* theGPT) {
} // ExpertsMenu() } // ExpertsMenu()
void ShowExpertCommands(void) { void ShowExpertCommands(void) {
printf("a\tset attributes\n"); cout << "a\tset attributes\n";
printf("c\tchange partition GUID\n"); cout << "c\tchange partition GUID\n";
printf("d\tdisplay the sector alignment value\n"); cout << "d\tdisplay the sector alignment value\n";
printf("e\trelocate backup data structures to the end of the disk\n"); cout << "e\trelocate backup data structures to the end of the disk\n";
printf("g\tchange disk GUID\n"); cout << "g\tchange disk GUID\n";
printf("i\tshow detailed information on a partition\n"); cout << "i\tshow detailed information on a partition\n";
printf("l\tset the sector alignment value\n"); cout << "l\tset the sector alignment value\n";
printf("m\treturn to main menu\n"); cout << "m\treturn to main menu\n";
printf("n\tcreate a new protective MBR\n"); cout << "n\tcreate a new protective MBR\n";
printf("o\tprint protective MBR data\n"); cout << "o\tprint protective MBR data\n";
printf("p\tprint the partition table\n"); cout << "p\tprint the partition table\n";
printf("q\tquit without saving changes\n"); cout << "q\tquit without saving changes\n";
printf("r\trecovery and transformation options (experts only)\n"); cout << "r\trecovery and transformation options (experts only)\n";
printf("s\tresize partition table\n"); cout << "s\tresize partition table\n";
printf("v\tverify disk\n"); cout << "v\tverify disk\n";
printf("w\twrite table to disk and exit\n"); cout << "w\twrite table to disk and exit\n";
printf("z\tzap (destroy) GPT data structures and exit\n"); cout << "z\tzap (destroy) GPT data structures and exit\n";
printf("?\tprint this menu\n"); cout << "?\tprint this menu\n";
} // ShowExpertCommands() } // ShowExpertCommands()

701
gpt.cc

File diff suppressed because it is too large Load Diff

16
gpt.h
View File

@@ -16,7 +16,7 @@
#ifndef __GPTSTRUCTS #ifndef __GPTSTRUCTS
#define __GPTSTRUCTS #define __GPTSTRUCTS
#define GPTFDISK_VERSION "0.6.2-pre1" #define GPTFDISK_VERSION "0.6.2-pre2"
using namespace std; using namespace std;
@@ -59,7 +59,7 @@ protected:
GPTPart *partitions; GPTPart *partitions;
struct GPTHeader secondHeader; struct GPTHeader secondHeader;
MBRData protectiveMBR; MBRData protectiveMBR;
char device[256]; // device filename string device; // device filename
DiskIO myDisk; DiskIO myDisk;
uint32_t blockSize; // device block size uint32_t blockSize; // device block size
uint64_t diskSize; // size of device, in blocks uint64_t diskSize; // size of device, in blocks
@@ -78,7 +78,7 @@ protected:
public: public:
// Basic necessary functions.... // Basic necessary functions....
GPTData(void); GPTData(void);
GPTData(char* deviceFilename); GPTData(string deviceFilename);
~GPTData(void); ~GPTData(void);
// Verify (or update) data integrity // Verify (or update) data integrity
@@ -93,15 +93,15 @@ public:
int FindOverlaps(void); int FindOverlaps(void);
// Load or save data from/to disk // Load or save data from/to disk
int LoadMBR(char* f) {return protectiveMBR.ReadMBRData(f);} int LoadMBR(string f) {return protectiveMBR.ReadMBRData(f);}
void PartitionScan(void); void PartitionScan(void);
int LoadPartitions(char* deviceFilename); int LoadPartitions(string deviceFilename);
int ForceLoadGPTData(void); int ForceLoadGPTData(void);
int LoadMainTable(void); int LoadMainTable(void);
int LoadSecondTableAsMain(void); int LoadSecondTableAsMain(void);
int SaveGPTData(int quiet = 0); int SaveGPTData(int quiet = 0);
int SaveGPTBackup(char* filename); int SaveGPTBackup(string filename);
int LoadGPTBackup(char* filename); int LoadGPTBackup(string filename);
// Display data.... // Display data....
void ShowAPMState(void); void ShowAPMState(void);
@@ -137,7 +137,7 @@ public:
void SortGPT(void); void SortGPT(void);
int ClearGPTData(void); int ClearGPTData(void);
void MoveSecondHeaderToEnd(); void MoveSecondHeaderToEnd();
int SetName(uint32_t partNum, char* theName = NULL); int SetName(uint32_t partNum, string theName = "");
void SetDiskGUID(GUIDData newGUID); void SetDiskGUID(GUIDData newGUID);
int SetPartitionGUID(uint32_t pn, GUIDData theGUID); int SetPartitionGUID(uint32_t pn, GUIDData theGUID);
int ChangePartType(uint32_t pn, uint16_t hexCode); int ChangePartType(uint32_t pn, uint16_t hexCode);

View File

@@ -15,8 +15,9 @@
#define __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS #define __STDC_CONSTANT_MACROS
#include <stdio.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <iostream>
#include "gptpart.h" #include "gptpart.h"
#include "attributes.h" #include "attributes.h"
@@ -34,14 +35,14 @@ GPTPart::GPTPart(void) {
GPTPart::~GPTPart(void) { GPTPart::~GPTPart(void) {
} // destructor } // destructor
// Return partition's name field // Return partition's name field, converted to a C++ ASCII string
string GPTPart::GetName(void) { string GPTPart::GetName(void) {
string theName; string theName;
int i;
/* if (ref == NULL) for (i = 0; i < NAME_SIZE; i += 2) {
ref = (unsigned char*) malloc(NAME_SIZE * sizeof (unsigned char)); theName += name[i];
strcpy((char*) ref, (char*) name); */ } // for
theName = (const char*) name;
return theName; return theName;
} // GPTPart::GetName() } // GPTPart::GetName()
@@ -53,12 +54,7 @@ uint16_t GPTPart::GetHexType(void) {
// Return a plain-text description of the partition type (e.g., "Linux/Windows // Return a plain-text description of the partition type (e.g., "Linux/Windows
// data" or "Linux swap"). // data" or "Linux swap").
string GPTPart::GetNameType(void) { string GPTPart::GetNameType(void) {
string temp; return typeHelper.GUIDToName(partitionType);
char theName[255];
temp = typeHelper.GUIDToName(partitionType, theName);
return temp;
} // GPTPart::GetNameType() } // GPTPart::GetNameType()
// Compute and return the partition's length (or 0 if the end is incorrectly // Compute and return the partition's length (or 0 if the end is incorrectly
@@ -141,50 +137,56 @@ void GPTPart::ReversePartBytes(void) {
// Display summary information; does nothing if the partition is empty. // Display summary information; does nothing if the partition is empty.
void GPTPart::ShowSummary(int partNum, uint32_t blockSize) { void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
char sizeInSI[255]; string sizeInSI;
int j = 0; int i;
if (firstLBA != 0) { if (firstLBA != 0) {
BytesToSI(blockSize * (lastLBA - firstLBA + 1), sizeInSI); sizeInSI = BytesToSI(blockSize * (lastLBA - firstLBA + 1));
printf("%4d %14lu %14lu", partNum + 1, (unsigned long) firstLBA, cout.width(4);
(unsigned long) lastLBA); cout << partNum + 1 << " ";
printf(" %-10s %04X ", sizeInSI, cout.width(14);
typeHelper.GUIDToID(partitionType)); cout << firstLBA << " ";
while ((name[j] != '\0') && (j < 44)) { cout.width(14);
printf("%c", name[j]); cout << lastLBA << " ";
j += 2; cout << BytesToSI(blockSize * (lastLBA - firstLBA + 1)) << " ";
} // while for (i = 0; i < 9 - sizeInSI.length(); i++) cout << " ";
printf("\n"); cout.fill('0');
cout.width(4);
cout.setf(ios::uppercase);
cout << hex << typeHelper.GUIDToID(partitionType) << " " << dec;
cout.fill(' ');
cout.setf(ios::right);
cout << GetName().substr(0, 23) << "\n";
cout.fill(' ');
} // if } // if
} // GPTPart::ShowSummary() } // GPTPart::ShowSummary()
// Show detailed partition information. Does nothing if the partition is // Show detailed partition information. Does nothing if the partition is
// empty (as determined by firstLBA being 0). // empty (as determined by firstLBA being 0).
void GPTPart::ShowDetails(uint32_t blockSize) { void GPTPart::ShowDetails(uint32_t blockSize) {
char temp[255];
int i;
uint64_t size; uint64_t size;
if (firstLBA != 0) { if (firstLBA != 0) {
printf("Partition GUID code: %s ", GUIDToStr(partitionType, temp)); cout << "Partition GUID code: " << GUIDToStr(partitionType);
printf("(%s)\n", typeHelper.GUIDToName(partitionType, temp)); cout << " (" << typeHelper.GUIDToName(partitionType) << ")\n";
printf("Partition unique GUID: %s\n", GUIDToStr(uniqueGUID, temp)); cout << "Partition unique GUID: " << GUIDToStr(uniqueGUID) << "\n";
printf("First sector: %llu ", firstLBA); cout << "First sector: " << firstLBA << " (at "
printf("(at %s)\n", BytesToSI(firstLBA * blockSize, temp)); << BytesToSI(firstLBA * blockSize) << ")\n";
printf("Last sector: %llu ", (unsigned long long) lastLBA); cout << "Last sector: " << lastLBA << " (at "
printf("(at %s)\n", BytesToSI(lastLBA * blockSize, temp)); << BytesToSI(lastLBA * blockSize) << ")\n";
size = (lastLBA - firstLBA + 1); size = (lastLBA - firstLBA + 1);
printf("Partition size: %llu sectors ", (unsigned long long) size); cout << "Partition size: " << size << " sectors ("
printf("(%s)\n", BytesToSI(size * ((uint64_t) blockSize), temp)); << BytesToSI(size * ((uint64_t) blockSize)) << ")\n";
printf("Attribute flags: %016llx\n", (unsigned long long) attributes); cout << "Attribute flags: ";
printf("Partition name: "); cout.fill('0');
i = 0; cout.width(16);
while ((name[i] != '\0') && (i < NAME_SIZE)) { cout << right;
printf("%c", name[i]); cout << hex;
i += 2; cout << attributes << "\n";
} // while cout << left;
printf("\n"); cout << dec;
cout << "Partition name: " << GetName() << "\n";
} // if } // if
} // GPTPart::ShowDetails() } // GPTPart::ShowDetails()
@@ -194,14 +196,14 @@ void GPTPart::ShowDetails(uint32_t blockSize) {
// Change the type code on the partition. // Change the type code on the partition.
void GPTPart::ChangeType(void) { void GPTPart::ChangeType(void) {
char typeName[255], line[255]; char line[255];
char* junk; char* junk;
int typeNum = 0xFFFF; int typeNum = 0xFFFF;
GUIDData newType; GUIDData newType;
printf("Current type is '%s'\n", GetNameType().c_str()); cout << "Current type is '" << GetNameType() << "'\n";
while ((!typeHelper.Valid(typeNum)) && (typeNum != 0)) { while ((!typeHelper.Valid(typeNum)) && (typeNum != 0)) {
printf("Hex code (L to show codes, 0 to enter raw code, Enter = 0700): "); cout << "Hex code (L to show codes, 0 to enter raw code, Enter = 0700): ";
junk = fgets(line, 255, stdin); junk = fgets(line, 255, stdin);
sscanf(line, "%X", &typeNum); sscanf(line, "%X", &typeNum);
if ((line[0] == 'L') || (line[0] == 'l')) if ((line[0] == 'L') || (line[0] == 'l'))
@@ -215,25 +217,24 @@ void GPTPart::ChangeType(void) {
else // user wants to enter the GUID directly, so do that else // user wants to enter the GUID directly, so do that
newType = GetGUID(); newType = GetGUID();
partitionType = newType; partitionType = newType;
printf("Changed type of partition to '%s'\n", cout << "Changed type of partition to '" << typeHelper.GUIDToName(partitionType) << "'\n";
typeHelper.GUIDToName(partitionType, typeName));
} // GPTPart::ChangeType() } // GPTPart::ChangeType()
// Set the name for a partition to theName, or prompt for a name if // Set the name for a partition to theName, or prompt for a name if
// theName is a NULL pointer. Note that theName is a standard C-style // theName is empty. Note that theName is a standard C++-style ASCII
// string, although the GUID partition definition requires a UTF-16LE // string, although the GUID partition definition requires a UTF-16LE
// string. This function creates a simple-minded copy for this. // string. This function creates a simple-minded copy for this.
void GPTPart::SetName(unsigned char* theName) { void GPTPart::SetName(string theName) {
char newName[NAME_SIZE]; // New name char newName[NAME_SIZE]; // New name
char* junk; char *junk;
int i; int i;
// Blank out new name string, just to be on the safe side.... // Blank out new name string, just to be on the safe side....
for (i = 0; i < NAME_SIZE; i++) for (i = 0; i < NAME_SIZE; i++)
newName[i] = '\0'; newName[i] = '\0';
if (theName == NULL) { // No name specified, so get one from the user if (theName == "") { // No name specified, so get one from the user
printf("Enter name: "); cout << "Enter name: ";
junk = fgets(newName, NAME_SIZE / 2, stdin); junk = fgets(newName, NAME_SIZE / 2, stdin);
// Input is likely to include a newline, so remove it.... // Input is likely to include a newline, so remove it....
@@ -241,7 +242,7 @@ void GPTPart::SetName(unsigned char* theName) {
if (newName[i - 1] == '\n') if (newName[i - 1] == '\n')
newName[i - 1] = '\0'; newName[i - 1] = '\0';
} else { } else {
strcpy(newName, (char*) theName); strcpy(newName, theName.substr(0, NAME_SIZE / 2).c_str());
} // if } // if
// Copy the C-style ASCII string from newName into a form that the GPT // Copy the C-style ASCII string from newName into a form that the GPT

View File

@@ -69,7 +69,7 @@ class GPTPart {
void SetFirstLBA(uint64_t f) {firstLBA = f;} void SetFirstLBA(uint64_t f) {firstLBA = f;}
void SetLastLBA(uint64_t l) {lastLBA = l;} void SetLastLBA(uint64_t l) {lastLBA = l;}
void SetAttributes(uint64_t a) {attributes = a;} void SetAttributes(uint64_t a) {attributes = a;}
void SetName(unsigned char* n); void SetName(string n);
// Additional functions // Additional functions
GPTPart & operator=(const GPTPart & orig); GPTPart & operator=(const GPTPart & orig);

84
mbr.cc
View File

@@ -18,6 +18,7 @@
#include <time.h> #include <time.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <iostream>
#include "mbr.h" #include "mbr.h"
#include "support.h" #include "support.h"
@@ -32,7 +33,7 @@ using namespace std;
MBRData::MBRData(void) { MBRData::MBRData(void) {
blockSize = SECTOR_SIZE; blockSize = SECTOR_SIZE;
diskSize = 0; diskSize = 0;
strcpy(device, ""); device = "";
state = invalid; state = invalid;
srand((unsigned int) time(NULL)); srand((unsigned int) time(NULL));
numHeads = MAX_HEADS; numHeads = MAX_HEADS;
@@ -40,10 +41,10 @@ MBRData::MBRData(void) {
EmptyMBR(); EmptyMBR();
} // MBRData default constructor } // MBRData default constructor
MBRData::MBRData(char *filename) { MBRData::MBRData(string filename) {
blockSize = SECTOR_SIZE; blockSize = SECTOR_SIZE;
diskSize = 0; diskSize = 0;
strcpy(device, filename); device = filename;
state = invalid; state = invalid;
numHeads = MAX_HEADS; numHeads = MAX_HEADS;
numSecspTrack = MAX_SECSPERTRACK; numSecspTrack = MAX_SECSPERTRACK;
@@ -52,7 +53,7 @@ MBRData::MBRData(char *filename) {
// Try to read the specified partition table, but if it fails.... // Try to read the specified partition table, but if it fails....
if (!ReadMBRData(filename)) { if (!ReadMBRData(filename)) {
EmptyMBR(); EmptyMBR();
strcpy(device, ""); device = "";
} // if } // if
} // MBRData(char *filename) constructor } // MBRData(char *filename) constructor
@@ -67,7 +68,7 @@ MBRData::~MBRData(void) {
// Read data from MBR. Returns 1 if read was successful (even if the // Read data from MBR. Returns 1 if read was successful (even if the
// data isn't a valid MBR), 0 if the read failed. // data isn't a valid MBR), 0 if the read failed.
int MBRData::ReadMBRData(char* deviceFilename) { int MBRData::ReadMBRData(string deviceFilename) {
int fd, allOK = 1; int fd, allOK = 1;
if (myDisk->OpenForRead(deviceFilename)) { if (myDisk->OpenForRead(deviceFilename)) {
@@ -77,7 +78,7 @@ int MBRData::ReadMBRData(char* deviceFilename) {
} // if } // if
if (allOK) if (allOK)
strcpy(device, deviceFilename); device = deviceFilename;
return allOK; return allOK;
} // MBRData::ReadMBRData(char* deviceFilename) } // MBRData::ReadMBRData(char* deviceFilename)
@@ -101,7 +102,7 @@ void MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
if (myDisk->Read(&tempMBR, 512)) if (myDisk->Read(&tempMBR, 512))
err = 0; err = 0;
if (err) { if (err) {
fprintf(stderr, "Problem reading disk in MBRData::ReadMBRData!\n"); cerr << "Problem reading disk in MBRData::ReadMBRData!\n";
} else { } else {
for (i = 0; i < 440; i++) for (i = 0; i < 440; i++)
code[i] = tempMBR.code[i]; code[i] = tempMBR.code[i];
@@ -152,7 +153,7 @@ void MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
logicalNum = ReadLogicalPart(partitions[i].firstLBA, UINT32_C(0), 4); logicalNum = ReadLogicalPart(partitions[i].firstLBA, UINT32_C(0), 4);
if ((logicalNum < 0) || (logicalNum >= MAX_MBR_PARTS)) { if ((logicalNum < 0) || (logicalNum >= MAX_MBR_PARTS)) {
allOK = 0; allOK = 0;
fprintf(stderr, "Error reading logical partitions! List may be truncated!\n"); cerr << "Error reading logical partitions! List may be truncated!\n";
} // if maxLogicals valid } // if maxLogicals valid
} // if primary partition is extended } // if primary partition is extended
} // for primary partition loop } // for primary partition loop
@@ -202,14 +203,13 @@ int MBRData::ReadLogicalPart(uint32_t extendedStart,
// function as of GPT fdisk version 0.5.0 doesn't do so. // function as of GPT fdisk version 0.5.0 doesn't do so.
if ((partNum < MAX_MBR_PARTS) && (partNum >= 0)) { if ((partNum < MAX_MBR_PARTS) && (partNum >= 0)) {
offset = (uint64_t) (extendedStart + diskOffset); offset = (uint64_t) (extendedStart + diskOffset);
// if (lseek64(fd, offset, SEEK_SET) == (off_t) -1) { // seek to EBR record
if (myDisk->Seek(offset) == 0) { // seek to EBR record if (myDisk->Seek(offset) == 0) { // seek to EBR record
fprintf(stderr, "Unable to seek to %lu! Aborting!\n", (unsigned long) offset); cerr << "Unable to seek to " << offset << "! Aborting!\n";
partNum = -1; partNum = -1;
} }
if (myDisk->Read(&ebr, 512) != 512) { // Load the data.... if (myDisk->Read(&ebr, 512) != 512) { // Load the data....
fprintf(stderr, "Error seeking to or reading logical partition data from %lu!\nAborting!\n", cerr << "Error seeking to or reading logical partition data from " << offset
(unsigned long) offset); << "!\nAborting!\n";
partNum = -1; partNum = -1;
} else if (IsLittleEndian() != 1) { // Reverse byte ordering of some data.... } else if (IsLittleEndian() != 1) { // Reverse byte ordering of some data....
ReverseBytes(&ebr.MBRSignature, 2); ReverseBytes(&ebr.MBRSignature, 2);
@@ -221,8 +221,14 @@ int MBRData::ReadLogicalPart(uint32_t extendedStart,
if (ebr.MBRSignature != MBR_SIGNATURE) { if (ebr.MBRSignature != MBR_SIGNATURE) {
partNum = -1; partNum = -1;
fprintf(stderr, "MBR signature in logical partition invalid; read 0x%04X, but should be 0x%04X\n", cerr << "MBR signature in logical partition invalid; read 0x";
(unsigned int) ebr.MBRSignature, (unsigned int) MBR_SIGNATURE); cerr.fill('0');
cerr.width(4);
cerr.setf(ios::uppercase);
cerr << hex << ebr.MBRSignature << ", but should be 0x";
cerr.width(4);
cerr << MBR_SIGNATURE << dec << "\n";
cerr.fill(' ');
} // if } // if
// Copy over the basic data.... // Copy over the basic data....
@@ -297,11 +303,11 @@ int MBRData::WriteMBRData(DiskIO *theDisk) {
if (allOK && theDisk->Seek(0)) { if (allOK && theDisk->Seek(0)) {
if (theDisk->Write(&tempMBR, 512) != 512) { if (theDisk->Write(&tempMBR, 512) != 512) {
allOK = 0; allOK = 0;
fprintf(stderr, "Warning! Error %d when saving MBR!\n", errno); cerr << "Warning! Error " << errno << " when saving MBR!\n";
} // if } // if
} else { } else {
allOK = 0; allOK = 0;
fprintf(stderr, "Warning! Error %d when seeking to MBR to write it!\n", errno); cerr << "Warning! Error " << errno << " when seeking to MBR to write it!\n";
} // if/else } // if/else
theDisk->Close(); theDisk->Close();
@@ -318,8 +324,8 @@ int MBRData::WriteMBRData(DiskIO *theDisk) {
return allOK; return allOK;
} // MBRData::WriteMBRData(DiskIO theDisk) } // MBRData::WriteMBRData(DiskIO theDisk)
int MBRData::WriteMBRData(char* deviceFilename) { int MBRData::WriteMBRData(string deviceFilename) {
strcpy(device, deviceFilename); device = deviceFilename;
return WriteMBRData(); return WriteMBRData();
} // MBRData::WriteMBRData(char* deviceFilename) } // MBRData::WriteMBRData(char* deviceFilename)
@@ -335,22 +341,34 @@ void MBRData::DisplayMBRData(void) {
char tempStr[255]; char tempStr[255];
char bootCode; char bootCode;
printf("MBR disk identifier: 0x%08X\n", (unsigned int) diskSignature); cout << "MBR disk identifier: 0x";
printf("MBR partitions:\n"); cout.width(8);
printf("Number\t Boot\t Start (sector)\t Length (sectors)\tType\n"); cout.fill('0');
cout.setf(ios::uppercase);
cout << hex << diskSignature << dec << "\n";
cout << "MBR partitions:\n";
cout << "Number\t Boot\t Start (sector)\t Length (sectors)\tType\n";
for (i = 0; i < MAX_MBR_PARTS; i++) { for (i = 0; i < MAX_MBR_PARTS; i++) {
if (partitions[i].lengthLBA != 0) { if (partitions[i].lengthLBA != 0) {
if (partitions[i].status && 0x80) // it's bootable if (partitions[i].status && 0x80) // it's bootable
bootCode = '*'; bootCode = '*';
else else
bootCode = ' '; bootCode = ' ';
printf("%4d\t %c\t%13lu\t%15lu \t0x%02X\n", i + 1, bootCode, cout.fill(' ');
(unsigned long) partitions[i].firstLBA, cout.width(4);
(unsigned long) partitions[i].lengthLBA, partitions[i].partitionType); cout << i + 1 << "\t " << bootCode << "\t";
cout.width(13);
cout << partitions[i].firstLBA << "\t";
cout.width(15);
cout << partitions[i].lengthLBA << " \t0x";
cout.width(2);
cout.fill('0');
cout << hex << (int) partitions[i].partitionType << dec << "\n";
} // if } // if
cout.fill(' ');
} // for } // for
printf("\nDisk size is %llu sectors ", (unsigned long long) diskSize); cout << "\nDisk size is " << diskSize << " sectors ("
printf("(%s)\n", BytesToSI(diskSize * (uint64_t) blockSize, tempStr)); << BytesToSI(diskSize * (uint64_t) blockSize) << "\n";
} // MBRData::DisplayMBRData() } // MBRData::DisplayMBRData()
// Displays the state, as a word, on stdout. Used for debugging & to // Displays the state, as a word, on stdout. Used for debugging & to
@@ -358,19 +376,19 @@ void MBRData::DisplayMBRData(void) {
void MBRData::ShowState(void) { void MBRData::ShowState(void) {
switch (state) { switch (state) {
case invalid: case invalid:
printf(" MBR: not present\n"); cout << " MBR: not present\n";
break; break;
case gpt: case gpt:
printf(" MBR: protective\n"); cout << " MBR: protective\n";
break; break;
case hybrid: case hybrid:
printf(" MBR: hybrid\n"); cout << " MBR: hybrid\n";
break; break;
case mbr: case mbr:
printf(" MBR: MBR only\n"); cout << " MBR: MBR only\n";
break; break;
default: default:
printf("\a MBR: unknown -- bug!\n"); cout << "\a MBR: unknown -- bug!\n";
break; break;
} // switch } // switch
} // MBRData::ShowState() } // MBRData::ShowState()
@@ -390,7 +408,7 @@ void MBRData::SetCHSGeom(uint32_t h, uint32_t s) {
numHeads = h; numHeads = h;
numSecspTrack = s; numSecspTrack = s;
} else { } else {
printf("Warning! Attempt to set invalid CHS geometry!\n"); cout << "Warning! Attempt to set invalid CHS geometry!\n";
} // if/else } // if/else
} // MBRData::SetCHSGeom() } // MBRData::SetCHSGeom()
@@ -807,7 +825,7 @@ GPTPart MBRData::AsGPT(int i) {
newPart.SetType(((uint16_t) origType) * 0x0100); newPart.SetType(((uint16_t) origType) * 0x0100);
newPart.SetUniqueGUID(1); newPart.SetUniqueGUID(1);
newPart.SetAttributes(0); newPart.SetAttributes(0);
newPart.SetName((unsigned char*) newPart.GetNameType().c_str()); newPart.SetName(newPart.GetNameType());
} // if not extended, protective, or non-existent } // if not extended, protective, or non-existent
} // if (origPart != NULL) } // if (origPart != NULL)
return newPart; return newPart;

8
mbr.h
View File

@@ -71,16 +71,16 @@ protected:
uint64_t numHeads; // number of heads, in CHS scheme uint64_t numHeads; // number of heads, in CHS scheme
uint64_t numSecspTrack; // number of sectors per track, in CHS scheme uint64_t numSecspTrack; // number of sectors per track, in CHS scheme
DiskIO* myDisk; DiskIO* myDisk;
char device[256]; string device;
MBRValidity state; MBRValidity state;
struct MBRRecord* GetPartition(int i); // Return primary or logical partition struct MBRRecord* GetPartition(int i); // Return primary or logical partition
public: public:
MBRData(void); MBRData(void);
MBRData(char* deviceFilename); MBRData(string deviceFilename);
~MBRData(void); ~MBRData(void);
// File I/O functions... // File I/O functions...
int ReadMBRData(char* deviceFilename); int ReadMBRData(string deviceFilename);
void ReadMBRData(DiskIO * theDisk, int checkBlockSize = 1); void ReadMBRData(DiskIO * theDisk, int checkBlockSize = 1);
// ReadLogicalPart() returns last partition # read to logicals[] array, // ReadLogicalPart() returns last partition # read to logicals[] array,
// or -1 if there was a problem.... // or -1 if there was a problem....
@@ -88,7 +88,7 @@ public:
int partNum); int partNum);
int WriteMBRData(void); int WriteMBRData(void);
int WriteMBRData(DiskIO *theDisk); int WriteMBRData(DiskIO *theDisk);
int WriteMBRData(char* deviceFilename); int WriteMBRData(string deviceFilename);
// Display data for user... // Display data for user...
void DisplayMBRData(void); void DisplayMBRData(void);

View File

@@ -11,6 +11,7 @@
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <iostream>
#include "parttypes.h" #include "parttypes.h"
using namespace std; using namespace std;
@@ -236,20 +237,24 @@ int PartTypes::AddType(uint16_t mbrType, uint64_t guidData1, uint64_t guidData2,
void PartTypes::ShowTypes(void) { void PartTypes::ShowTypes(void) {
int colCount = 1; // column count int colCount = 1; // column count
AType* thisType = allTypes; AType* thisType = allTypes;
char tempStr[20];
cout.unsetf(ios::uppercase);
while (thisType != NULL) { while (thisType != NULL) {
if (thisType->display == 1) { // show it if (thisType->display == 1) { // show it
strncpy(tempStr, thisType->name, 19); cout.fill('0');
tempStr[19] = '\0'; cout.width(4);
printf("%04x %-19s ", thisType->MBRType, tempStr); cout << hex << thisType->MBRType << " ";
cout.fill(' ');
cout.setf(ios::left);
cout.width(19);
cout << ((string) thisType->name).substr(0, 19) << " ";
if ((colCount % 3) == 0) if ((colCount % 3) == 0)
printf("\n"); cout << "\n";
colCount++; colCount++;
} // if } // if
thisType = thisType->next; thisType = thisType->next;
} // while } // while
printf("\n"); cout << "\n";
} // PartTypes::ShowTypes() } // PartTypes::ShowTypes()
// Returns 1 if code is a valid extended MBR code, 0 if it's not // Returns 1 if code is a valid extended MBR code, 0 if it's not
@@ -267,21 +272,24 @@ int PartTypes::Valid(uint16_t code) {
} // PartTypes::Valid() } // PartTypes::Valid()
// Convert a GUID code to a name. // Convert a GUID code to a name.
char* PartTypes::GUIDToName(struct GUIDData typeCode, char typeName[]) { string PartTypes::GUIDToName(struct GUIDData typeCode) {
AType* theItem = allTypes; AType* theItem = allTypes;
int found = 0; int found = 0;
string typeName;
while ((theItem != NULL) && (!found)) { while ((theItem != NULL) && (!found)) {
if ((theItem->GUIDType.data1 == typeCode.data1) && if ((theItem->GUIDType.data1 == typeCode.data1) &&
(theItem->GUIDType.data2 == typeCode.data2)) { // found it! (theItem->GUIDType.data2 == typeCode.data2)) { // found it!
strcpy(typeName, theItem->name); // strcpy(typeName, theItem->name);
typeName = theItem->name;
found = 1; found = 1;
} else { } else {
theItem = theItem->next; theItem = theItem->next;
} // if/else } // if/else
} // while } // while
if (!found) { if (!found) {
strcpy(typeName, (char*) "Unknown"); typeName = "Unknown";
// strcpy(typeName, (char*) "Unknown");
} // if (!found) } // if (!found)
return typeName; return typeName;
} // PartTypes::GUIDToName() } // PartTypes::GUIDToName()
@@ -310,8 +318,11 @@ struct GUIDData PartTypes::IDToGUID(uint16_t ID) {
} // if/else } // if/else
} // while } // while
if (!found) { if (!found) {
printf("Exact type match not found for type code %04X; assigning type code for\n'Linux/Windows data'\n", cout.setf(ios::uppercase);
ID); cout.fill('0');
cout << "Exact type match not found for type code ";
cout.width(4);
cout << hex << ID << "; assigning type code for\n'Linux/Windows data'\n" << dec;
} // if (!found) } // if (!found)
return theGUID; return theGUID;
} // PartTypes::IDToGUID() } // PartTypes::IDToGUID()

View File

@@ -4,7 +4,7 @@
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string>
#include "support.h" #include "support.h"
#ifndef __PARTITION_TYPES #ifndef __PARTITION_TYPES
@@ -39,7 +39,7 @@ public:
const char* name, int toDisplay = 1); const char* name, int toDisplay = 1);
void ShowTypes(void); void ShowTypes(void);
int Valid(uint16_t); int Valid(uint16_t);
char* GUIDToName(struct GUIDData typeCode, char typeName[]); string GUIDToName(struct GUIDData typeCode);
struct GUIDData IDToGUID(uint16_t ID); struct GUIDData IDToGUID(uint16_t ID);
uint16_t GUIDToID(struct GUIDData); uint16_t GUIDToID(struct GUIDData);
}; };

View File

@@ -13,6 +13,7 @@
#include <string> #include <string>
#include <popt.h> #include <popt.h>
#include <errno.h> #include <errno.h>
#include <iostream>
#include "mbr.h" #include "mbr.h"
#include "gpt.h" #include "gpt.h"
#include "support.h" #include "support.h"
@@ -87,7 +88,7 @@ int main(int argc, char *argv[]) {
pretend = 1; pretend = 1;
break; break;
case 'V': case 'V':
printf("GPT fdisk (sgdisk) version %s\n\n", GPTFDISK_VERSION); cout << "GPT fdisk (sgdisk) version " << GPTFDISK_VERSION << "\n\n";
break; break;
default: default:
break; break;
@@ -102,7 +103,7 @@ int main(int argc, char *argv[]) {
if (device != NULL) { if (device != NULL) {
theGPT.JustLooking(); // reset as necessary theGPT.JustLooking(); // reset as necessary
theGPT.BeQuiet(); // Tell called functions to be less verbose & interactive theGPT.BeQuiet(); // Tell called functions to be less verbose & interactive
if (theGPT.LoadPartitions(device)) { if (theGPT.LoadPartitions((string) device)) {
if ((theGPT.WhichWasUsed() == use_mbr) || (theGPT.WhichWasUsed() == use_bsd)) if ((theGPT.WhichWasUsed() == use_mbr) || (theGPT.WhichWasUsed() == use_bsd))
saveNonGPT = 0; // flag so we don't overwrite unless directed to do so saveNonGPT = 0; // flag so we don't overwrite unless directed to do so
while ((opt = poptGetNextOpt(poptCon)) > 0) { while ((opt = poptGetNextOpt(poptCon)) > 0) {
@@ -117,11 +118,11 @@ int main(int argc, char *argv[]) {
case 'c': case 'c':
theGPT.JustLooking(0); theGPT.JustLooking(0);
partNum = (int) GetInt(partName, 1) - 1; partNum = (int) GetInt(partName, 1) - 1;
if (theGPT.SetName(partNum, (char*) GetString(partName, 2).c_str())) { if (theGPT.SetName(partNum, GetString(partName, 2))) {
saveData = 1; saveData = 1;
} else { } else {
fprintf(stderr, "Unable set set partition %d's name to '%s'!\n", cerr << "Unable set set partition " << partNum + 1
partNum + 1, GetString(partName, 2).c_str()); << "'s name to '" << GetString(partName, 2) << "'!\n";
neverSaveData = 1; neverSaveData = 1;
} // if/else } // if/else
free(partName); free(partName);
@@ -129,7 +130,7 @@ int main(int argc, char *argv[]) {
case 'd': case 'd':
theGPT.JustLooking(0); theGPT.JustLooking(0);
if (theGPT.DeletePartition(deletePartNum - 1) == 0) { if (theGPT.DeletePartition(deletePartNum - 1) == 0) {
fprintf(stderr, "Error %d deleting partition!\n", errno); cerr << "Error " << errno << " deleting partition!\n";
neverSaveData = 1; neverSaveData = 1;
} else saveData = 1; } else saveData = 1;
break; break;
@@ -139,10 +140,10 @@ int main(int argc, char *argv[]) {
saveData = 1; saveData = 1;
break; break;
case 'E': case 'E':
printf("%llu\n", (unsigned long long) theGPT.FindLastAvailable(theGPT.FindFirstInLargest())); cout << theGPT.FindLastAvailable(theGPT.FindFirstInLargest()) << "\n";
break; break;
case 'f': case 'f':
printf("%llu\n", (unsigned long long) theGPT.FindFirstInLargest()); cout << theGPT.FindFirstInLargest() << "\n";
break; break;
case 'g': case 'g':
theGPT.JustLooking(0); theGPT.JustLooking(0);
@@ -153,12 +154,12 @@ int main(int argc, char *argv[]) {
theGPT.ShowPartDetails(infoPartNum - 1); theGPT.ShowPartDetails(infoPartNum - 1);
break; break;
case 'l': case 'l':
if (theGPT.LoadGPTBackup(backupFile) == 1) if (theGPT.LoadGPTBackup((string) backupFile) == 1)
saveData = 1; saveData = 1;
else { else {
saveData = 0; saveData = 0;
neverSaveData = 1; neverSaveData = 1;
fprintf(stderr, "Error loading backup file!\n"); cerr << "Error loading backup file!\n";
} // else } // else
free(backupFile); free(backupFile);
break; break;
@@ -172,8 +173,8 @@ int main(int argc, char *argv[]) {
if (theGPT.CreatePartition(partNum, startSector, endSector)) { if (theGPT.CreatePartition(partNum, startSector, endSector)) {
saveData = 1; saveData = 1;
} else { } else {
fprintf(stderr, "Could not create partition %d from %llu to %llu!\n", cerr << "Could not create partition " << partNum << " from "
partNum, startSector, endSector); << startSector << " to " << endSector << "\n";
neverSaveData = 1; neverSaveData = 1;
} // if/else } // if/else
free(newPartInfo); free(newPartInfo);
@@ -208,8 +209,8 @@ int main(int argc, char *argv[]) {
if (theGPT.ChangePartType(partNum, hexCode)) { if (theGPT.ChangePartType(partNum, hexCode)) {
saveData = 1; saveData = 1;
} else { } else {
fprintf(stderr, "Could not change partition %d's type code to %x!\n", cerr << "Could not change partition " << partNum + 1
partNum + 1, hexCode); << "'s type code to " << hex << hexCode << "!\n" << dec;
neverSaveData = 1; neverSaveData = 1;
} // if/else } // if/else
free(typeCode); free(typeCode);
@@ -228,18 +229,18 @@ int main(int argc, char *argv[]) {
saveNonGPT = 0; saveNonGPT = 0;
break; break;
default: default:
printf("Unknown option (-%c)!\n", opt); cerr << "Unknown option (-" << opt << ")!\n";
break; break;
} // switch } // switch
} // while } // while
if ((saveData) && (!neverSaveData) && (saveNonGPT) && (!pretend)) if ((saveData) && (!neverSaveData) && (saveNonGPT) && (!pretend))
theGPT.SaveGPTData(1); theGPT.SaveGPTData(1);
if (saveData && (!saveNonGPT)) { if (saveData && (!saveNonGPT)) {
printf("Non-GPT disk; not saving changes. Use -g to override.\n"); cout << "Non-GPT disk; not saving changes. Use -g to override.\n";
retval = 3; retval = 3;
} // if } // if
if (neverSaveData) { if (neverSaveData) {
printf("Error encountered; not saving changes.\n"); cerr << "Error encountered; not saving changes.\n";
retval = 4; retval = 4;
} // if } // if
} else { // if loaded OK } else { // if loaded OK
@@ -267,8 +268,6 @@ uint64_t GetInt(char* argument, int itemNum) {
endPos--; endPos--;
sscanf(Info.substr(startPos, endPos - startPos + 1).c_str(), "%llu", &retval); sscanf(Info.substr(startPos, endPos - startPos + 1).c_str(), "%llu", &retval);
/* printf("In GetInt(), startPos = %d, endPos = %d, retval = %llu\n", startPos,
endPos, (unsigned long long) retval); */
return retval; return retval;
} // GetInt() } // GetInt()

View File

@@ -10,11 +10,13 @@
#define __STDC_CONSTANT_MACROS #define __STDC_CONSTANT_MACROS
#include <stdio.h> #include <stdio.h>
#include <string>
#include <stdint.h> #include <stdint.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <string>
#include <iostream>
#include "support.h" #include "support.h"
#include <sys/types.h> #include <sys/types.h>
@@ -33,26 +35,25 @@ using namespace std;
// If user provides no input, def (default value) is returned. // If user provides no input, def (default value) is returned.
// (If def is outside of the low-high range, an explicit response // (If def is outside of the low-high range, an explicit response
// is required.) // is required.)
int GetNumber(int low, int high, int def, const char prompt[]) { int GetNumber(int low, int high, int def, const string & prompt) {
int response, num; int response, num;
char line[255]; char line[255];
char* junk;
if (low != high) { // bother only if low and high differ... if (low != high) { // bother only if low and high differ...
response = low - 1; // force one loop by setting response outside range response = low - 1; // force one loop by setting response outside range
while ((response < low) || (response > high)) { while ((response < low) || (response > high)) {
printf("%s", prompt); cout << prompt;
junk = fgets(line, 255, stdin); cin.getline(line, 255);
num = sscanf(line, "%d", &response); num = sscanf(line, "%d", &response);
if (num == 1) { // user provided a response if (num == 1) { // user provided a response
if ((response < low) || (response > high)) if ((response < low) || (response > high))
printf("Value out of range\n"); cout << "Value out of range\n";
} else { // user hit enter; return default } else { // user hit enter; return default
response = def; response = def;
} // if/else } // if/else
} // while } // while
} else { // low == high, so return this value } else { // low == high, so return this value
printf("Using %d\n", low); cout << "Using " << low << "\n";
response = low; response = low;
} // else } // else
return (response); return (response);
@@ -62,10 +63,10 @@ int GetNumber(int low, int high, int def, const char prompt[]) {
char GetYN(void) { char GetYN(void) {
char line[255]; char line[255];
char response = '\0'; char response = '\0';
char* junk; char *junk;
while ((response != 'Y') && (response != 'N')) { while ((response != 'Y') && (response != 'N')) {
printf("(Y/N): "); cout << "(Y/N): ";
junk = fgets(line, 255, stdin); junk = fgets(line, 255, stdin);
sscanf(line, "%c", &response); sscanf(line, "%c", &response);
if (response == 'y') response = 'Y'; if (response == 'y') response = 'Y';
@@ -81,18 +82,17 @@ char GetYN(void) {
// If a "-" prefix is used, use the high value minus the user- // If a "-" prefix is used, use the high value minus the user-
// specified number of sectors (or KiB, MiB, etc.). Use the def // specified number of sectors (or KiB, MiB, etc.). Use the def
//value as the default if the user just hits Enter //value as the default if the user just hits Enter
uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, char prompt[]) { uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const string & prompt) {
unsigned long long response; unsigned long long response;
int num, plusFlag = 0; int num, plusFlag = 0;
uint64_t mult = 1; uint64_t mult = 1;
char suffix; char suffix;
char line[255]; char line[255];
char* junk;
response = low - 1; // Ensure one pass by setting a too-low initial value response = low - 1; // Ensure one pass by setting a too-low initial value
while ((response < low) || (response > high)) { while ((response < low) || (response > high)) {
printf("%s", prompt); cout << prompt;
junk = fgets(line, 255, stdin); cin.getline(line, 255);
// Remove leading spaces, if present // Remove leading spaces, if present
while (line[0] == ' ') while (line[0] == ' ')
@@ -164,65 +164,65 @@ uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, char prompt[])
// Takes a size in bytes (in size) and converts this to a size in // Takes a size in bytes (in size) and converts this to a size in
// SI units (KiB, MiB, GiB, TiB, or PiB), returned in C++ string // SI units (KiB, MiB, GiB, TiB, or PiB), returned in C++ string
// form // form
char* BytesToSI(uint64_t size, char theValue[]) { string BytesToSI(uint64_t size) {
char units[8]; string units;
char theValue[99];
float sizeInSI; float sizeInSI;
if (theValue != NULL) { theValue[0] = '\0';
sizeInSI = (float) size; sizeInSI = (float) size;
strcpy (units, " bytes"); units = " bytes";
if (sizeInSI > 1024.0) { if (sizeInSI > 1024.0) {
sizeInSI /= 1024.0; sizeInSI /= 1024.0;
strcpy(units, " KiB"); units = " KiB";
} // if
if (sizeInSI > 1024.0) {
sizeInSI /= 1024.0;
strcpy(units, " MiB");
} // if
if (sizeInSI > 1024.0) {
sizeInSI /= 1024.0;
strcpy(units, " GiB");
} // if
if (sizeInSI > 1024.0) {
sizeInSI /= 1024.0;
strcpy(units, " TiB");
} // if
if (sizeInSI > 1024.0) {
sizeInSI /= 1024.0;
strcpy(units, " PiB");
} // if
if (strcmp(units, " bytes") == 0) { // in bytes, so no decimal point
sprintf(theValue, "%1.0f%s", sizeInSI, units);
} else {
sprintf(theValue, "%1.1f%s", sizeInSI, units);
} // if/else
} // if } // if
if (sizeInSI > 1024.0) {
sizeInSI /= 1024.0;
units = " MiB";
} // if
if (sizeInSI > 1024.0) {
sizeInSI /= 1024.0;
units = " GiB";
} // if
if (sizeInSI > 1024.0) {
sizeInSI /= 1024.0;
units = " TiB";
} // if
if (sizeInSI > 1024.0) {
sizeInSI /= 1024.0;
units = " PiB";
} // if
if (units == " bytes") { // in bytes, so no decimal point
sprintf(theValue, "%1.0f%s", sizeInSI, units.c_str());
} else {
sprintf(theValue, "%1.1f%s", sizeInSI, units.c_str());
} // if/else
return theValue; return theValue;
} // BlocksToSI() } // BlocksToSI()
// Return a plain-text name for a partition type. // Return a plain-text name for a partition type.
// Convert a GUID to a string representation, suitable for display // Convert a GUID to a string representation, suitable for display
// to humans.... // to humans....
char* GUIDToStr(struct GUIDData theGUID, char* theString) { string GUIDToStr(struct GUIDData theGUID) {
unsigned long long blocks[11], block; unsigned long long blocks[11], block;
char theString[40];
if (theString != NULL) { theString[0] = '\0';;
blocks[0] = (theGUID.data1 & UINT64_C(0x00000000FFFFFFFF)); blocks[0] = (theGUID.data1 & UINT64_C(0x00000000FFFFFFFF));
blocks[1] = (theGUID.data1 & UINT64_C(0x0000FFFF00000000)) >> 32; blocks[1] = (theGUID.data1 & UINT64_C(0x0000FFFF00000000)) >> 32;
blocks[2] = (theGUID.data1 & UINT64_C(0xFFFF000000000000)) >> 48; blocks[2] = (theGUID.data1 & UINT64_C(0xFFFF000000000000)) >> 48;
blocks[3] = (theGUID.data2 & UINT64_C(0x00000000000000FF)); blocks[3] = (theGUID.data2 & UINT64_C(0x00000000000000FF));
blocks[4] = (theGUID.data2 & UINT64_C(0x000000000000FF00)) >> 8; blocks[4] = (theGUID.data2 & UINT64_C(0x000000000000FF00)) >> 8;
blocks[5] = (theGUID.data2 & UINT64_C(0x0000000000FF0000)) >> 16; blocks[5] = (theGUID.data2 & UINT64_C(0x0000000000FF0000)) >> 16;
blocks[6] = (theGUID.data2 & UINT64_C(0x00000000FF000000)) >> 24; blocks[6] = (theGUID.data2 & UINT64_C(0x00000000FF000000)) >> 24;
blocks[7] = (theGUID.data2 & UINT64_C(0x000000FF00000000)) >> 32; blocks[7] = (theGUID.data2 & UINT64_C(0x000000FF00000000)) >> 32;
blocks[8] = (theGUID.data2 & UINT64_C(0x0000FF0000000000)) >> 40; blocks[8] = (theGUID.data2 & UINT64_C(0x0000FF0000000000)) >> 40;
blocks[9] = (theGUID.data2 & UINT64_C(0x00FF000000000000)) >> 48; blocks[9] = (theGUID.data2 & UINT64_C(0x00FF000000000000)) >> 48;
blocks[10] = (theGUID.data2 & UINT64_C(0xFF00000000000000)) >> 56; blocks[10] = (theGUID.data2 & UINT64_C(0xFF00000000000000)) >> 56;
sprintf(theString, sprintf(theString,
"%08llX-%04llX-%04llX-%02llX%02llX-%02llX%02llX%02llX%02llX%02llX%02llX", "%08llX-%04llX-%04llX-%02llX%02llX-%02llX%02llX%02llX%02llX%02llX%02llX",
blocks[0], blocks[1], blocks[2], blocks[3], blocks[4], blocks[5], blocks[0], blocks[1], blocks[2], blocks[3], blocks[4], blocks[5],
blocks[6], blocks[7], blocks[8], blocks[9], blocks[10]); blocks[6], blocks[7], blocks[8], blocks[9], blocks[10]);
} // if
return theString; return theString;
} // GUIDToStr() } // GUIDToStr()
@@ -234,10 +234,10 @@ GUIDData GetGUID(void) {
char* junk; char* junk;
GUIDData theGUID; GUIDData theGUID;
printf("\nA GUID is entered in five segments of from two to six bytes, with\n" cout << "\nA GUID is entered in five segments of from two to six bytes, with\n"
"dashes between segments.\n"); << "dashes between segments.\n";
printf("Enter the entire GUID, a four-byte hexadecimal number for the first segment, or\n" cout << "Enter the entire GUID, a four-byte hexadecimal number for the first segment, or\n"
"'R' to generate the entire GUID randomly: "); << "'R' to generate the entire GUID randomly: ";
junk = fgets(temp, 255, stdin); junk = fgets(temp, 255, stdin);
// If user entered 'r' or 'R', generate GUID randomly.... // If user entered 'r' or 'R', generate GUID randomly....
@@ -280,17 +280,17 @@ GUIDData GetGUID(void) {
// entry.... // entry....
if (entered == 0) { if (entered == 0) {
sscanf(temp, "%llx", &part1); sscanf(temp, "%llx", &part1);
printf("Enter a two-byte hexadecimal number for the second segment: "); cout << "Enter a two-byte hexadecimal number for the second segment: ";
junk = fgets(temp, 255, stdin); junk = fgets(temp, 255, stdin);
sscanf(temp, "%llx", &part2); sscanf(temp, "%llx", &part2);
printf("Enter a two-byte hexadecimal number for the third segment: "); cout << "Enter a two-byte hexadecimal number for the third segment: ";
junk = fgets(temp, 255, stdin); junk = fgets(temp, 255, stdin);
sscanf(temp, "%llx", &part3); sscanf(temp, "%llx", &part3);
theGUID.data1 = (part3 << 48) + (part2 << 32) + part1; theGUID.data1 = (part3 << 48) + (part2 << 32) + part1;
printf("Enter a two-byte hexadecimal number for the fourth segment: "); cout << "Enter a two-byte hexadecimal number for the fourth segment: ";
junk = fgets(temp, 255, stdin); junk = fgets(temp, 255, stdin);
sscanf(temp, "%llx", &part4); sscanf(temp, "%llx", &part4);
printf("Enter a six-byte hexadecimal number for the fifth segment: "); cout << "Enter a six-byte hexadecimal number for the fifth segment: ";
junk = fgets(temp, 255, stdin); junk = fgets(temp, 255, stdin);
sscanf(temp, "%llx", &part5); sscanf(temp, "%llx", &part5);
theGUID.data2 = ((part4 & UINT64_C(0x000000000000FF00)) >> 8) + theGUID.data2 = ((part4 & UINT64_C(0x000000000000FF00)) >> 8) +
@@ -303,7 +303,7 @@ GUIDData GetGUID(void) {
((part5 & UINT64_C(0x00000000000000FF)) << 56); ((part5 & UINT64_C(0x00000000000000FF)) << 56);
entered = 1; entered = 1;
} // if/else } // if/else
printf("New GUID: %s\n", GUIDToStr(theGUID, temp)); cout << "New GUID: " << GUIDToStr(theGUID) << "\n";
return theGUID; return theGUID;
} // GetGUID() } // GetGUID()
@@ -324,17 +324,16 @@ int IsLittleEndian(void) {
// Reverse the byte order of theValue; numBytes is number of bytes // Reverse the byte order of theValue; numBytes is number of bytes
void ReverseBytes(void* theValue, int numBytes) { void ReverseBytes(void* theValue, int numBytes) {
char* origValue; char* tempValue = NULL;
char* tempValue;
int i; int i;
origValue = (char*) theValue;
tempValue = (char*) malloc(numBytes); tempValue = (char*) malloc(numBytes);
for (i = 0; i < numBytes; i++) if (tempValue != NULL) {
tempValue[i] = origValue[i]; memcpy(tempValue, theValue, numBytes);
for (i = 0; i < numBytes; i++) for (i = 0; i < numBytes; i++)
origValue[i] = tempValue[numBytes - i - 1]; ((char*) theValue)[i] = tempValue[numBytes - i - 1];
free(tempValue); free(tempValue);
} // if
} // ReverseBytes() } // ReverseBytes()
// Compute (2 ^ value). Given the return type, value must be 63 or less. // Compute (2 ^ value). Given the return type, value must be 63 or less.

View File

@@ -4,7 +4,7 @@
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string>
#ifndef __GPTSUPPORT #ifndef __GPTSUPPORT
#define __GPTSUPPORT #define __GPTSUPPORT
@@ -35,6 +35,9 @@
#define APM_SIGNATURE1 UINT64_C(0x00004D5000000000) #define APM_SIGNATURE1 UINT64_C(0x00004D5000000000)
#define APM_SIGNATURE2 UINT64_C(0x0000535400000000) #define APM_SIGNATURE2 UINT64_C(0x0000535400000000)
// Maximum line length ignored on some input functions
#define MAX_IGNORED 999
/************************** /**************************
* Some GPT constants.... * * Some GPT constants.... *
**************************/ **************************/
@@ -58,11 +61,11 @@ struct GUIDData {
static char theFile[255]; static char theFile[255];
int GetNumber(int low, int high, int def, const char prompt[]); int GetNumber(int low, int high, int def, const string & prompt);
char GetYN(void); char GetYN(void);
uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, char prompt[]); uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const string & prompt);
char* BytesToSI(uint64_t size, char theValue[]); string BytesToSI(uint64_t size);
char* GUIDToStr(struct GUIDData theGUID, char* theString); string GUIDToStr(struct GUIDData theGUID);
GUIDData GetGUID(void); GUIDData GetGUID(void);
int IsLittleEndian(void); // Returns 1 if CPU is little-endian, 0 if it's big-endian int IsLittleEndian(void); // Returns 1 if CPU is little-endian, 0 if it's big-endian
void ReverseBytes(void* theValue, int numBytes); // Reverses byte-order of theValue void ReverseBytes(void* theValue, int numBytes); // Reverses byte-order of theValue