A few minor bug fixes; backup function now accepts dd output of MBR,
main header, and main partition table, as well as gdisk-generated backups.
This commit is contained in:
19
CHANGELOG
19
CHANGELOG
@@ -1,3 +1,22 @@
|
||||
0.6.4 (??/??/2010):
|
||||
-------------------
|
||||
|
||||
- Fixed bug in the -E option to sgdisk; it was actually returning the
|
||||
last free sector, not the last free sector in the largest free block.
|
||||
|
||||
- Fixed bug in -t option to sgdisk; it was corrupting partition type
|
||||
codes.
|
||||
|
||||
- Fixed minor alignment bug in partition summary list ('p' from any menu)
|
||||
when partition sizes are between 1000 and 1024 units.
|
||||
|
||||
- Backup restore function ('l' on recovery & transformation menu) now
|
||||
accepts both backups generated by GPT fdisk and backups created by a
|
||||
direct copy (via dd, etc.) of the MBR, main GPT header, and main GPT
|
||||
partition table, in that order. ("dd if=/dev/sda of=backup.gpt bs=512
|
||||
count=34" will do this on Linux for a disk with a typical-sized GPT table
|
||||
of 128 entries.)
|
||||
|
||||
0.6.3 (2/3/2010):
|
||||
------------------
|
||||
|
||||
|
||||
4
bsd.cc
4
bsd.cc
@@ -37,7 +37,7 @@ BSDData::BSDData(void) {
|
||||
} // default constructor
|
||||
|
||||
BSDData::~BSDData(void) {
|
||||
free(partitions);
|
||||
delete[] partitions;
|
||||
} // destructor
|
||||
|
||||
// Read BSD disklabel data from the specified device filename. This function
|
||||
@@ -132,7 +132,7 @@ int BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSect
|
||||
|
||||
// If the state is good, go ahead and load the main partition data....
|
||||
if (state == bsd) {
|
||||
partitions = (struct BSDRecord*) malloc(numParts * sizeof (struct BSDRecord));
|
||||
partitions = new struct BSDRecord[numParts * sizeof(struct BSDRecord)];
|
||||
for (i = 0; i < numParts; i++) {
|
||||
// Once again, we use the buffer, but index it using a BSDRecord
|
||||
// pointer (dangerous, but effective)....
|
||||
|
||||
@@ -184,6 +184,7 @@ void DiskIO::DiskSync(void) {
|
||||
} // DiskIO::DiskSync()
|
||||
|
||||
// Seek to the specified sector. Returns 1 on success, 0 on failure.
|
||||
// Note that seeking beyond the end of the file is NOT detected as a failure!
|
||||
int DiskIO::Seek(uint64_t sector) {
|
||||
int retval = 1;
|
||||
off_t seekTo, sought;
|
||||
@@ -208,7 +209,7 @@ int DiskIO::Seek(uint64_t sector) {
|
||||
// size with the number of bytes read.
|
||||
// Returns the number of bytes read into buffer.
|
||||
int DiskIO::Read(void* buffer, int numBytes) {
|
||||
int blockSize = 512, numBlocks, retval = 0;
|
||||
int blockSize, numBlocks, retval = 0;
|
||||
char* tempSpace;
|
||||
|
||||
// If disk isn't open, try to open it....
|
||||
@@ -221,11 +222,12 @@ int DiskIO::Read(void* buffer, int numBytes) {
|
||||
blockSize = GetBlockSize();
|
||||
if (numBytes <= blockSize) {
|
||||
numBlocks = 1;
|
||||
tempSpace = (char*) malloc(blockSize);
|
||||
tempSpace = new char [blockSize];
|
||||
} else {
|
||||
numBlocks = numBytes / blockSize;
|
||||
if ((numBytes % blockSize) != 0) numBlocks++;
|
||||
tempSpace = (char*) malloc(numBlocks * blockSize);
|
||||
if ((numBytes % blockSize) != 0)
|
||||
numBlocks++;
|
||||
tempSpace = new char [numBlocks * blockSize];
|
||||
} // if/else
|
||||
|
||||
// Read the data into temporary space, then copy it to buffer
|
||||
@@ -236,7 +238,7 @@ int DiskIO::Read(void* buffer, int numBytes) {
|
||||
if (((numBlocks * blockSize) != numBytes) && (retval > 0))
|
||||
retval = numBytes;
|
||||
|
||||
free(tempSpace);
|
||||
delete[] tempSpace;
|
||||
} // if (isOpen)
|
||||
return retval;
|
||||
} // DiskIO::Read()
|
||||
@@ -259,17 +261,14 @@ int DiskIO::Write(void* buffer, int numBytes) {
|
||||
blockSize = GetBlockSize();
|
||||
if (numBytes <= blockSize) {
|
||||
numBlocks = 1;
|
||||
tempSpace = (char*) malloc(blockSize);
|
||||
tempSpace = new char [blockSize];
|
||||
} else {
|
||||
numBlocks = numBytes / blockSize;
|
||||
if ((numBytes % blockSize) != 0) numBlocks++;
|
||||
tempSpace = (char*) malloc(numBlocks * blockSize);
|
||||
tempSpace = new char [numBlocks * blockSize];
|
||||
} // if/else
|
||||
|
||||
// Copy the data to my own buffer, then write it
|
||||
/* for (i = 0; i < numBytes; i++) {
|
||||
tempSpace[i] = ((char*) buffer)[i];
|
||||
} // for */
|
||||
memcpy(tempSpace, buffer, numBytes);
|
||||
for (i = numBytes; i < numBlocks * blockSize; i++) {
|
||||
tempSpace[i] = 0;
|
||||
@@ -280,7 +279,7 @@ int DiskIO::Write(void* buffer, int numBytes) {
|
||||
if (((numBlocks * blockSize) != numBytes) && (retval > 0))
|
||||
retval = numBytes;
|
||||
|
||||
free(tempSpace);
|
||||
delete[] tempSpace;
|
||||
} // if (isOpen)
|
||||
return retval;
|
||||
} // DiskIO:Write()
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <winioctl.h>
|
||||
#define fstat64 fstat
|
||||
#define stat64 stat
|
||||
#define S_IRGRP 0
|
||||
//#define S_IRGRP 0
|
||||
#define S_IROTH 0
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
@@ -64,7 +64,9 @@ int DiskIO::OpenForRead(void) {
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (fd == INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(fd);
|
||||
cerr << "Problem opening " << realFilename << " for reading!\n";
|
||||
cerr << "Problem opening ";
|
||||
cerr << realFilename;
|
||||
cerr << " for reading!\n";
|
||||
realFilename = "";
|
||||
userFilename = "";
|
||||
isOpen = 0;
|
||||
@@ -220,11 +222,12 @@ int DiskIO::Read(void* buffer, int numBytes) {
|
||||
blockSize = GetBlockSize();
|
||||
if (numBytes <= blockSize) {
|
||||
numBlocks = 1;
|
||||
tempSpace = (char*) malloc(blockSize);
|
||||
tempSpace = new char [blockSize];
|
||||
} else {
|
||||
numBlocks = numBytes / blockSize;
|
||||
if ((numBytes % blockSize) != 0) numBlocks++;
|
||||
tempSpace = (char*) malloc(numBlocks * blockSize);
|
||||
if ((numBytes % blockSize) != 0)
|
||||
numBlocks++;
|
||||
tempSpace = new char [numBlocks * blockSize];
|
||||
} // if/else
|
||||
|
||||
// Read the data into temporary space, then copy it to buffer
|
||||
@@ -237,7 +240,7 @@ int DiskIO::Read(void* buffer, int numBytes) {
|
||||
if (((numBlocks * blockSize) != numBytes) && (retval > 0))
|
||||
retval = numBytes;
|
||||
|
||||
free(tempSpace);
|
||||
delete[] tempSpace;
|
||||
} // if (isOpen)
|
||||
return retval;
|
||||
} // DiskIO::Read()
|
||||
@@ -261,11 +264,11 @@ int DiskIO::Write(void* buffer, int numBytes) {
|
||||
blockSize = GetBlockSize();
|
||||
if (numBytes <= blockSize) {
|
||||
numBlocks = 1;
|
||||
tempSpace = (char*) malloc(blockSize);
|
||||
tempSpace = new char [blockSize];
|
||||
} else {
|
||||
numBlocks = numBytes / blockSize;
|
||||
if ((numBytes % blockSize) != 0) numBlocks++;
|
||||
tempSpace = (char*) malloc(numBlocks * blockSize);
|
||||
tempSpace = new char [numBlocks * blockSize];
|
||||
} // if/else
|
||||
|
||||
// Copy the data to my own buffer, then write it
|
||||
@@ -282,7 +285,7 @@ int DiskIO::Write(void* buffer, int numBytes) {
|
||||
if (((numBlocks * blockSize) != numBytes) && (retval > 0))
|
||||
retval = numBytes;
|
||||
|
||||
free(tempSpace);
|
||||
delete[] tempSpace;
|
||||
} // if (isOpen)
|
||||
return retval;
|
||||
} // DiskIO:Write()
|
||||
|
||||
@@ -43,12 +43,10 @@ DiskIO::DiskIO(void) {
|
||||
realFilename = "";
|
||||
isOpen = 0;
|
||||
openForWrite = 0;
|
||||
sectorData = NULL;
|
||||
} // constructor
|
||||
|
||||
DiskIO::~DiskIO(void) {
|
||||
Close();
|
||||
free(sectorData);
|
||||
} // destructor
|
||||
|
||||
// Open a disk device for reading. Returns 1 on success, 0 on failure.
|
||||
|
||||
2
diskio.h
2
diskio.h
@@ -51,7 +51,6 @@ class DiskIO {
|
||||
string realFilename;
|
||||
int isOpen;
|
||||
int openForWrite;
|
||||
uint8_t *sectorData;
|
||||
#ifdef _WIN32
|
||||
HANDLE fd;
|
||||
#else
|
||||
@@ -76,6 +75,7 @@ class DiskIO {
|
||||
int FindAlignment(const string & filename);
|
||||
int IsOpen(void) {return isOpen;}
|
||||
int IsOpenForWrite(void) {return openForWrite;}
|
||||
string GetName(void) {return realFilename;}
|
||||
|
||||
uint64_t DiskSize(int* err);
|
||||
}; // struct GPTPart
|
||||
|
||||
1
gdisk.cc
1
gdisk.cc
@@ -29,7 +29,6 @@ int main(int argc, char* argv[]) {
|
||||
GPTData theGPT;
|
||||
int doMore = 1;
|
||||
char* device = NULL;
|
||||
PartType typeHelper; // unused, but necessary to initialize partition type linked list
|
||||
|
||||
cout << "GPT fdisk (gdisk) version " << GPTFDISK_VERSION << "\n\n";
|
||||
|
||||
|
||||
417
gpt.cc
417
gpt.cc
@@ -82,7 +82,7 @@ GPTData::GPTData(string filename) {
|
||||
|
||||
// Destructor
|
||||
GPTData::~GPTData(void) {
|
||||
free(partitions);
|
||||
delete[] partitions;
|
||||
} // GPTData destructor
|
||||
|
||||
/*********************************************************************
|
||||
@@ -342,8 +342,8 @@ int GPTData::CheckHeaderValidity(void) {
|
||||
} // GPTData::CheckHeaderValidity()
|
||||
|
||||
// Check the header CRC to see if it's OK...
|
||||
// Note: Must be called BEFORE byte-order reversal on big-endian
|
||||
// systems!
|
||||
// Note: Must be called with header in LITTLE-ENDIAN
|
||||
// (x86, x86-64, etc.) byte order.
|
||||
int GPTData::CheckHeaderCRC(struct GPTHeader* header) {
|
||||
uint32_t oldCRC, newCRC, hSize;
|
||||
|
||||
@@ -648,53 +648,22 @@ int GPTData::LoadPartitions(const string & deviceFilename) {
|
||||
// Loads the GPT, as much as possible. Returns 1 if this seems to have
|
||||
// succeeded, 0 if there are obvious problems....
|
||||
int GPTData::ForceLoadGPTData(void) {
|
||||
int allOK = 1, validHeaders;
|
||||
uint64_t seekTo;
|
||||
uint8_t* storage;
|
||||
uint32_t newCRC, sizeOfParts;
|
||||
int allOK, validHeaders, loadedTable = 1;
|
||||
|
||||
// Seek to and read the main GPT header
|
||||
if (myDisk.Seek(1)) {
|
||||
if (myDisk.Read(&mainHeader, 512) != 512) { // read main GPT header
|
||||
cerr << "Warning! Error " << errno << " reading main GPT header!\n";
|
||||
} // if read not OK
|
||||
} else allOK = 0; // if/else seek OK
|
||||
mainCrcOk = CheckHeaderCRC(&mainHeader);
|
||||
if (IsLittleEndian() == 0) // big-endian system; adjust header byte order....
|
||||
ReverseHeaderBytes(&mainHeader);
|
||||
allOK = LoadHeader(&mainHeader, myDisk, 1, &mainCrcOk);
|
||||
|
||||
// Load backup header, check its CRC, and store the results of the
|
||||
// check for future reference. Load backup header using pointer in main
|
||||
// header if possible; but if main header has a CRC error, or if it
|
||||
// points to beyond the end of the disk, load the last sector of the
|
||||
// disk instead.
|
||||
if (mainCrcOk) {
|
||||
if (mainHeader.backupLBA < diskSize) {
|
||||
seekTo = mainHeader.backupLBA;
|
||||
if (mainCrcOk && (mainHeader.backupLBA < diskSize)) {
|
||||
allOK = LoadHeader(&secondHeader, myDisk, mainHeader.backupLBA, &secondCrcOk) && allOK;
|
||||
} else {
|
||||
seekTo = diskSize - UINT64_C(1);
|
||||
if (mainHeader.backupLBA >= diskSize)
|
||||
cout << "Warning! Disk size is smaller than the main header indicates! Loading\n"
|
||||
<< "secondary header from the last sector of the disk! You should use 'v' to\n"
|
||||
<< "verify disk integrity, and perhaps options on the experts' menu to repair\n"
|
||||
<< "the disk.\n";
|
||||
} // else
|
||||
} else {
|
||||
seekTo = diskSize - UINT64_C(1);
|
||||
} // if/else (mainCrcOk)
|
||||
|
||||
if (myDisk.Seek(seekTo)) {
|
||||
if (myDisk.Read(&secondHeader, 512) != 512) { // read secondary GPT header
|
||||
cerr << "Warning! Error " << errno << " reading secondary GPT header!\n";
|
||||
} // if
|
||||
secondCrcOk = CheckHeaderCRC(&secondHeader);
|
||||
if (IsLittleEndian() == 0) // big-endian system; adjust header byte order....
|
||||
ReverseHeaderBytes(&secondHeader);
|
||||
} else {
|
||||
allOK = 0;
|
||||
allOK = LoadHeader(&secondHeader, myDisk, diskSize - UINT64_C(1), &secondCrcOk) && allOK;
|
||||
} // if/else
|
||||
if (!allOK)
|
||||
state = gpt_invalid;
|
||||
cerr << "Unable to seek to secondary GPT header at sector "
|
||||
<< (diskSize - (UINT64_C(1))) << "!\n";
|
||||
} // if/else lseek
|
||||
|
||||
// Return valid headers code: 0 = both headers bad; 1 = main header
|
||||
// good, backup bad; 2 = backup header good, main header bad;
|
||||
@@ -734,37 +703,32 @@ int GPTData::ForceLoadGPTData(void) {
|
||||
} else { // bad main header CRC and backup header CRC is OK
|
||||
state = gpt_corrupt;
|
||||
if (LoadSecondTableAsMain()) {
|
||||
loadedTable = 2;
|
||||
cerr << "\aWarning: Invalid CRC on main header data; loaded backup partition table.\n";
|
||||
} else { // backup table bad, bad main header CRC, but try main table in desperation....
|
||||
if (LoadMainTable() == 0) {
|
||||
allOK = 0;
|
||||
loadedTable = 0;
|
||||
cerr << "\a\aWarning! Unable to load either main or backup partition table!\n";
|
||||
} // if
|
||||
} // if/else (LoadSecondTableAsMain())
|
||||
} // if/else (load partition table)
|
||||
|
||||
// Load backup partition table into temporary storage to check
|
||||
// its CRC and store the results, then discard this temporary
|
||||
// storage, since we don't use it in any but recovery operations
|
||||
seekTo = secondHeader.partitionEntriesLBA;
|
||||
if ((myDisk.Seek(seekTo)) && (secondCrcOk)) {
|
||||
sizeOfParts = secondHeader.numParts * secondHeader.sizeOfPartitionEntries;
|
||||
storage = (uint8_t*) malloc(sizeOfParts);
|
||||
if (myDisk.Read(storage, sizeOfParts) != (int) sizeOfParts) {
|
||||
cerr << "Warning! Error " << errno << " reading backup partition table!\n";
|
||||
} // if
|
||||
newCRC = chksum_crc32((unsigned char*) storage, sizeOfParts);
|
||||
free(storage);
|
||||
secondPartsCrcOk = (newCRC == secondHeader.partitionEntriesCRC);
|
||||
} // if
|
||||
if (loadedTable == 1)
|
||||
secondPartsCrcOk = CheckTable(&secondHeader);
|
||||
else if (loadedTable == 2)
|
||||
mainPartsCrcOk = CheckTable(&mainHeader);
|
||||
else
|
||||
mainPartsCrcOk = secondPartsCrcOk = 0;
|
||||
|
||||
// Problem with main partition table; if backup is OK, use it instead....
|
||||
if (secondPartsCrcOk && secondCrcOk && !mainPartsCrcOk) {
|
||||
state = gpt_corrupt;
|
||||
allOK = allOK && LoadSecondTableAsMain();
|
||||
mainPartsCrcOk = 0; // LoadSecondTableAsMain() resets this, so re-flag as bad
|
||||
cerr << "\aWarning! Main partition table CRC mismatch! Loaded backup "
|
||||
<< "partition table\ninstead of main partition table!\n\n";
|
||||
} // if
|
||||
} // if */
|
||||
|
||||
// Check for valid CRCs and warn if there are problems
|
||||
if ((mainCrcOk == 0) || (secondCrcOk == 0) || (mainPartsCrcOk == 0) ||
|
||||
@@ -783,28 +747,7 @@ int GPTData::ForceLoadGPTData(void) {
|
||||
// sensible!
|
||||
// Returns 1 on success, 0 on failure. CRC errors do NOT count as failure.
|
||||
int GPTData::LoadMainTable(void) {
|
||||
int retval = 1;
|
||||
uint32_t newCRC, sizeOfParts;
|
||||
|
||||
if (myDisk.OpenForRead(device)) {
|
||||
// Set internal data structures for number of partitions on the disk
|
||||
SetGPTSize(mainHeader.numParts);
|
||||
|
||||
// Load main partition table, and record whether its CRC
|
||||
// matches the stored value
|
||||
if (!myDisk.Seek(mainHeader.partitionEntriesLBA))
|
||||
retval = 0;
|
||||
sizeOfParts = mainHeader.numParts * mainHeader.sizeOfPartitionEntries;
|
||||
if (myDisk.Read(partitions, sizeOfParts) != (int) sizeOfParts) {
|
||||
cerr << "Warning! Error " << errno << " when loading the main partition table!\n";
|
||||
retval = 0;
|
||||
} // if
|
||||
newCRC = chksum_crc32((unsigned char*) partitions, sizeOfParts);
|
||||
mainPartsCrcOk = (newCRC == mainHeader.partitionEntriesCRC);
|
||||
if (IsLittleEndian() == 0)
|
||||
ReversePartitionBytes();
|
||||
} else retval = 0; // if open for read....
|
||||
return retval;
|
||||
return LoadPartitionTable(mainHeader, myDisk);
|
||||
} // GPTData::LoadMainTable()
|
||||
|
||||
// Load the second (backup) partition table as the primary partition
|
||||
@@ -812,47 +755,103 @@ int GPTData::LoadMainTable(void) {
|
||||
// partition table is damaged.
|
||||
// Returns 1 on success, 0 on failure. CRC errors do NOT count as failure.
|
||||
int GPTData::LoadSecondTableAsMain(void) {
|
||||
uint64_t seekTo;
|
||||
uint32_t sizeOfParts, newCRC;
|
||||
int retval = 1;
|
||||
return LoadPartitionTable(secondHeader, myDisk);
|
||||
} // GPTData::LoadSecondTableAsMain()
|
||||
|
||||
if (myDisk.OpenForRead(device)) {
|
||||
seekTo = secondHeader.partitionEntriesLBA;
|
||||
retval = myDisk.Seek(seekTo);
|
||||
// Load a single GPT header (main or backup) from the specified disk device and
|
||||
// sector. Applies byte-order corrections on big-endian platforms. Sets crcOk
|
||||
// value appropriately.
|
||||
// Returns 1 on success, 0 on failure. Note that CRC errors do NOT qualify as
|
||||
// failure.
|
||||
int GPTData::LoadHeader(struct GPTHeader *header, DiskIO & disk, uint64_t sector, int *crcOk) {
|
||||
int allOK = 1;
|
||||
|
||||
disk.Seek(sector);
|
||||
if (disk.Read(header, 512) != 512) {
|
||||
cerr << "Warning! Read error " << errno << "; strange behavior now likely!\n";
|
||||
allOK = 0;
|
||||
} // if
|
||||
*crcOk = CheckHeaderCRC(header);
|
||||
|
||||
// Reverse byte order, if necessary
|
||||
if (IsLittleEndian() == 0) {
|
||||
ReverseHeaderBytes(header);
|
||||
} // if
|
||||
return allOK;
|
||||
} // GPTData::LoadHeader
|
||||
|
||||
// Load a partition table (either main or secondary) from the specified disk,
|
||||
// using header as a reference for what to load. If sector != 0 (the default
|
||||
// is 0), loads from the specified sector; otherwise loads from the sector
|
||||
// indicated in header.
|
||||
// Returns 1 on success, 0 on failure. CRC errors do NOT count as failure.
|
||||
int GPTData::LoadPartitionTable(const struct GPTHeader & header, DiskIO & disk, uint64_t sector) {
|
||||
uint32_t sizeOfParts, newCRC;
|
||||
int retval;
|
||||
|
||||
if (disk.OpenForRead()) {
|
||||
if (sector == 0) {
|
||||
retval = disk.Seek(header.partitionEntriesLBA);
|
||||
} else {
|
||||
retval = disk.Seek(sector);
|
||||
} // if/else
|
||||
if (retval == 1) {
|
||||
SetGPTSize(secondHeader.numParts);
|
||||
sizeOfParts = secondHeader.numParts * secondHeader.sizeOfPartitionEntries;
|
||||
if (myDisk.Read(partitions, sizeOfParts) != (int) sizeOfParts) {
|
||||
SetGPTSize(header.numParts);
|
||||
sizeOfParts = header.numParts * header.sizeOfPartitionEntries;
|
||||
if (disk.Read(partitions, sizeOfParts) != (int) sizeOfParts) {
|
||||
cerr << "Warning! Read error " << errno << "! Misbehavior now likely!\n";
|
||||
retval = 0;
|
||||
} // if
|
||||
newCRC = chksum_crc32((unsigned char*) partitions, sizeOfParts);
|
||||
secondPartsCrcOk = (newCRC == secondHeader.partitionEntriesCRC);
|
||||
mainPartsCrcOk = secondPartsCrcOk;
|
||||
mainPartsCrcOk = secondPartsCrcOk = (newCRC == header.partitionEntriesCRC);
|
||||
if (IsLittleEndian() == 0)
|
||||
ReversePartitionBytes();
|
||||
if (!secondPartsCrcOk) {
|
||||
cout << "Caution! After loading backup partitions, the CRC still doesn't check out!\n";
|
||||
if (!mainPartsCrcOk) {
|
||||
cout << "Caution! After loading partitions, the CRC doesn't check out!\n";
|
||||
} // if
|
||||
} else {
|
||||
cerr << "Error! Couldn't seek to backup partition table!\n";
|
||||
cerr << "Error! Couldn't seek to partition table!\n";
|
||||
} // if/else
|
||||
} else {
|
||||
cerr << "Error! Couldn't open device " << device
|
||||
<< " when recovering backup partition table!\n";
|
||||
<< " when reading partition table!\n";
|
||||
retval = 0;
|
||||
} // if/else
|
||||
return retval;
|
||||
} // GPTData::LoadSecondTableAsMain()
|
||||
} // GPTData::LoadPartitionsTable()
|
||||
|
||||
// Check the partition table pointed to by header, but don't keep it
|
||||
// around.
|
||||
// Returns 1 if the CRC is OK, 0 if not or if there was a read error.
|
||||
int GPTData::CheckTable(struct GPTHeader *header) {
|
||||
uint32_t sizeOfParts, newCRC;
|
||||
uint8_t *storage;
|
||||
int newCrcOk = 0;
|
||||
|
||||
// Load backup partition table into temporary storage to check
|
||||
// its CRC and store the results, then discard this temporary
|
||||
// storage, since we don't use it in any but recovery operations
|
||||
if (myDisk.Seek(header->partitionEntriesLBA)) {
|
||||
sizeOfParts = secondHeader.numParts * secondHeader.sizeOfPartitionEntries;
|
||||
storage = new uint8_t[sizeOfParts];
|
||||
if (myDisk.Read(storage, sizeOfParts) != (int) sizeOfParts) {
|
||||
cerr << "Warning! Error " << errno << " reading backup partition table!\n";
|
||||
} else {
|
||||
newCRC = chksum_crc32((unsigned char*) storage, sizeOfParts);
|
||||
newCrcOk = (newCRC == header->partitionEntriesCRC);
|
||||
} // if/else
|
||||
delete[] storage;
|
||||
} // if
|
||||
return newCrcOk;
|
||||
} // GPTData::CheckTable()
|
||||
|
||||
// Writes GPT (and protective MBR) to disk. Returns 1 on successful
|
||||
// write, 0 if there was a problem.
|
||||
int GPTData::SaveGPTData(int quiet) {
|
||||
int allOK = 1, littleEndian;
|
||||
char answer;
|
||||
uint64_t secondTable;
|
||||
// uint64_t secondTable;
|
||||
uint32_t numParts;
|
||||
uint64_t offset;
|
||||
|
||||
littleEndian = IsLittleEndian();
|
||||
|
||||
@@ -907,18 +906,8 @@ int GPTData::SaveGPTData(int quiet) {
|
||||
// Pull out some data that's needed before doing byte-order reversal on
|
||||
// big-endian systems....
|
||||
numParts = mainHeader.numParts;
|
||||
secondTable = secondHeader.partitionEntriesLBA;
|
||||
/* if (IsLittleEndian() == 0) {
|
||||
// Reverse partition bytes first, since that function requires non-reversed
|
||||
// data from the main header....
|
||||
ReversePartitionBytes();
|
||||
ReverseHeaderBytes(&mainHeader);
|
||||
ReverseHeaderBytes(&secondHeader);
|
||||
} // if */
|
||||
|
||||
RecomputeCRCs();
|
||||
/* ReverseHeaderBytes(&mainHeader);
|
||||
ReverseHeaderBytes(&secondHeader);
|
||||
ReversePartitionBytes(); */
|
||||
|
||||
if ((allOK) && (!quiet)) {
|
||||
cout << "\nFinal checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING\n"
|
||||
@@ -938,59 +927,22 @@ int GPTData::SaveGPTData(int quiet) {
|
||||
|
||||
if (allOK && myDisk.OpenForWrite(device)) {
|
||||
// Now write the main GPT header...
|
||||
if (myDisk.Seek(1) == 1) {
|
||||
if (!littleEndian)
|
||||
ReverseHeaderBytes(&mainHeader);
|
||||
if (myDisk.Write(&mainHeader, 512) != 512)
|
||||
allOK = 0;
|
||||
if (!littleEndian)
|
||||
ReverseHeaderBytes(&mainHeader);
|
||||
} else allOK = 0; // if (myDisk.Seek()...)
|
||||
allOK = SaveHeader(&mainHeader, myDisk, 1);
|
||||
|
||||
// Now write the main partition tables...
|
||||
if (allOK) {
|
||||
offset = mainHeader.partitionEntriesLBA;
|
||||
if (myDisk.Seek(offset)) {
|
||||
if (!littleEndian)
|
||||
ReversePartitionBytes();
|
||||
if (myDisk.Write(partitions, GPT_SIZE * numParts) == -1)
|
||||
allOK = 0;
|
||||
if (!littleEndian)
|
||||
ReversePartitionBytes();
|
||||
} else allOK = 0; // if (myDisk.Seek()...)
|
||||
allOK = SavePartitionTable(myDisk, mainHeader.partitionEntriesLBA);
|
||||
} // if (allOK)
|
||||
|
||||
// Now seek to near the end to write the secondary GPT....
|
||||
if (allOK) {
|
||||
offset = (uint64_t) secondTable;
|
||||
if (myDisk.Seek(offset) != 1) {
|
||||
allOK = 0;
|
||||
cerr << "Unable to seek to end of disk! Perhaps the 'e' option on the experts' menu\n"
|
||||
<< "will resolve this problem.\n";
|
||||
} // if
|
||||
} // if
|
||||
|
||||
// Now write the secondary partition tables....
|
||||
if (allOK) {
|
||||
if (!littleEndian)
|
||||
ReversePartitionBytes();
|
||||
if (myDisk.Write(partitions, GPT_SIZE * numParts) == -1)
|
||||
allOK = 0;
|
||||
if (!littleEndian)
|
||||
ReversePartitionBytes();
|
||||
} // if (allOK)
|
||||
allOK = SavePartitionTable(myDisk, secondHeader.partitionEntriesLBA);
|
||||
if (!allOK)
|
||||
cerr << "Unable to save backup partition table! Perhaps the 'e' option on the experts'\n"
|
||||
<< "menu will resolve this problem.\n";
|
||||
|
||||
// Now write the secondary GPT header...
|
||||
if (allOK) {
|
||||
offset = mainHeader.backupLBA;
|
||||
if (!littleEndian)
|
||||
ReverseHeaderBytes(&secondHeader);
|
||||
if (myDisk.Seek(offset)) {
|
||||
if (myDisk.Write(&secondHeader, 512) == -1)
|
||||
allOK = 0;
|
||||
} else allOK = 0; // if (myDisk.Seek()...)
|
||||
if (!littleEndian)
|
||||
ReverseHeaderBytes(&secondHeader);
|
||||
allOK = SaveHeader(&secondHeader, myDisk, mainHeader.backupLBA);
|
||||
} // if (allOK)
|
||||
|
||||
// re-read the partition table
|
||||
@@ -1015,14 +967,6 @@ int GPTData::SaveGPTData(int quiet) {
|
||||
cout << "Aborting write of new partition table.\n";
|
||||
} // if
|
||||
|
||||
/* if (IsLittleEndian() == 0) {
|
||||
// Reverse (normalize) header bytes first, since ReversePartitionBytes()
|
||||
// requires non-reversed data in mainHeader...
|
||||
ReverseHeaderBytes(&mainHeader);
|
||||
ReverseHeaderBytes(&secondHeader);
|
||||
ReversePartitionBytes();
|
||||
} // if */
|
||||
|
||||
return (allOK);
|
||||
} // GPTData::SaveGPTData()
|
||||
|
||||
@@ -1034,7 +978,6 @@ int GPTData::SaveGPTData(int quiet) {
|
||||
// identical to the main partition table on healthy disks.
|
||||
int GPTData::SaveGPTBackup(const string & filename) {
|
||||
int allOK = 1;
|
||||
uint32_t numParts;
|
||||
DiskIO backupFile;
|
||||
|
||||
if (backupFile.OpenForWrite(filename)) {
|
||||
@@ -1044,35 +987,19 @@ int GPTData::SaveGPTBackup(const string & filename) {
|
||||
// backup. I'm favoring misses over false alarms....
|
||||
RecomputeCRCs();
|
||||
|
||||
// Reverse the byte order, if necessary....
|
||||
numParts = mainHeader.numParts;
|
||||
if (IsLittleEndian() == 0) {
|
||||
ReversePartitionBytes();
|
||||
ReverseHeaderBytes(&mainHeader);
|
||||
ReverseHeaderBytes(&secondHeader);
|
||||
} // if
|
||||
|
||||
// Now write the protective MBR...
|
||||
protectiveMBR.WriteMBRData(&backupFile);
|
||||
|
||||
// Now write the main GPT header...
|
||||
if (allOK)
|
||||
if (allOK) {
|
||||
// MBR write closed disk, so re-open and seek to end....
|
||||
backupFile.OpenForWrite();
|
||||
backupFile.Seek(1);
|
||||
if (backupFile.Write(&mainHeader, 512) == -1)
|
||||
allOK = 0;
|
||||
allOK = SaveHeader(&mainHeader, backupFile, 1);
|
||||
} // if (allOK)
|
||||
|
||||
// Now write the secondary GPT header...
|
||||
if (allOK)
|
||||
if (backupFile.Write(&secondHeader, 512) == -1)
|
||||
allOK = 0;
|
||||
allOK = SaveHeader(&secondHeader, backupFile, 2);
|
||||
|
||||
// Now write the main partition tables...
|
||||
if (allOK) {
|
||||
if (backupFile.Write(partitions, GPT_SIZE * numParts) == -1)
|
||||
allOK = 0;
|
||||
} // if
|
||||
if (allOK)
|
||||
allOK = SavePartitionTable(backupFile, 3);
|
||||
|
||||
if (allOK) { // writes completed OK
|
||||
cout << "The operation has completed successfully.\n";
|
||||
@@ -1081,13 +1008,6 @@ int GPTData::SaveGPTBackup(const string & filename) {
|
||||
<< "It may not be usable!\n";
|
||||
} // if/else
|
||||
backupFile.Close();
|
||||
|
||||
// Now reverse the byte-order reversal, if necessary....
|
||||
if (IsLittleEndian() == 0) {
|
||||
ReverseHeaderBytes(&mainHeader);
|
||||
ReverseHeaderBytes(&secondHeader);
|
||||
ReversePartitionBytes();
|
||||
} // if
|
||||
} else {
|
||||
cerr << "Unable to open file " << filename << " for writing! Aborting!\n";
|
||||
allOK = 0;
|
||||
@@ -1095,14 +1015,54 @@ int GPTData::SaveGPTBackup(const string & filename) {
|
||||
return allOK;
|
||||
} // GPTData::SaveGPTBackup()
|
||||
|
||||
// Write a GPT header (main or backup) to the specified sector. Used by both
|
||||
// the SaveGPTData() and SaveGPTBackup() functions.
|
||||
// Should be passed an architecture-appropriate header (DO NOT call
|
||||
// ReverseHeaderBytes() on the header before calling this function)
|
||||
// Returns 1 on success, 0 on failure
|
||||
int GPTData::SaveHeader(struct GPTHeader *header, DiskIO & disk, uint64_t sector) {
|
||||
int littleEndian, allOK = 1;
|
||||
|
||||
littleEndian = IsLittleEndian();
|
||||
if (!littleEndian)
|
||||
ReverseHeaderBytes(header);
|
||||
if (disk.Seek(sector)) {
|
||||
if (disk.Write(header, 512) == -1)
|
||||
allOK = 0;
|
||||
} else allOK = 0; // if (disk.Seek()...)
|
||||
if (!littleEndian)
|
||||
ReverseHeaderBytes(header);
|
||||
return allOK;
|
||||
} // GPTData::SaveHeader()
|
||||
|
||||
// Save the partitions to the specified sector. Used by both the SaveGPTData()
|
||||
// and SaveGPTBackup() functions.
|
||||
// Should be passed an architecture-appropriate header (DO NOT call
|
||||
// ReverseHeaderBytes() on the header before calling this function)
|
||||
// Returns 1 on success, 0 on failure
|
||||
int GPTData::SavePartitionTable(DiskIO & disk, uint64_t sector) {
|
||||
int littleEndian, allOK = 1;
|
||||
|
||||
littleEndian = IsLittleEndian();
|
||||
if (disk.Seek(sector)) {
|
||||
if (!littleEndian)
|
||||
ReversePartitionBytes();
|
||||
if (disk.Write(partitions, mainHeader.sizeOfPartitionEntries * mainHeader.numParts) == -1)
|
||||
allOK = 0;
|
||||
if (!littleEndian)
|
||||
ReversePartitionBytes();
|
||||
} else allOK = 0; // if (myDisk.Seek()...)
|
||||
return allOK;
|
||||
} // GPTData::SavePartitionTable()
|
||||
|
||||
// Load GPT data from a backup file created by SaveGPTBackup(). This function
|
||||
// does minimal error checking. It returns 1 if it completed successfully,
|
||||
// 0 if there was a problem. In the latter case, it creates a new empty
|
||||
// set of partitions.
|
||||
int GPTData::LoadGPTBackup(const string & filename) {
|
||||
int allOK = 1, val;
|
||||
uint32_t numParts, sizeOfEntries, sizeOfParts, newCRC;
|
||||
int littleEndian = 1;
|
||||
int allOK = 1, val, err;
|
||||
uint32_t numParts, sizeOfEntries;
|
||||
int littleEndian = 1, shortBackup = 0;
|
||||
DiskIO backupFile;
|
||||
|
||||
if (backupFile.OpenForRead(filename)) {
|
||||
@@ -1112,29 +1072,20 @@ int GPTData::LoadGPTBackup(const string & filename) {
|
||||
// Let the MBRData class load the saved MBR...
|
||||
protectiveMBR.ReadMBRData(&backupFile, 0); // 0 = don't check block size
|
||||
|
||||
// Load the main GPT header, check its vaility, and set the GPT
|
||||
// size based on the data
|
||||
if (backupFile.Read(&mainHeader, 512) != 512) {
|
||||
cerr << "Warning! Read error " << errno << "; strange behavior now likely!\n";
|
||||
} // if
|
||||
mainCrcOk = CheckHeaderCRC(&mainHeader);
|
||||
LoadHeader(&mainHeader, backupFile, 1, &mainCrcOk);
|
||||
|
||||
// Reverse byte order, if necessary
|
||||
if (littleEndian == 0) {
|
||||
ReverseHeaderBytes(&mainHeader);
|
||||
} // if
|
||||
|
||||
// Load the backup GPT header in much the same way as the main
|
||||
// GPT header....
|
||||
if (backupFile.Read(&secondHeader, 512) != 512) {
|
||||
cerr << "Warning! Read error " << errno << "; strange behavior now likely!\n";
|
||||
} // if
|
||||
secondCrcOk = CheckHeaderCRC(&secondHeader);
|
||||
|
||||
// Reverse byte order, if necessary
|
||||
if (littleEndian == 0) {
|
||||
ReverseHeaderBytes(&secondHeader);
|
||||
} // if
|
||||
// Check backup file size and rebuild second header if file is right
|
||||
// size to be direct dd copy of MBR, main header, and main partition
|
||||
// table; if other size, treat it like a GPT fdisk-generated backup
|
||||
// file
|
||||
shortBackup = ((backupFile.DiskSize(&err) * backupFile.GetBlockSize()) ==
|
||||
(mainHeader.numParts * mainHeader.sizeOfPartitionEntries) + 1024);
|
||||
if (shortBackup) {
|
||||
RebuildSecondHeader();
|
||||
secondCrcOk = mainCrcOk;
|
||||
} else {
|
||||
LoadHeader(&secondHeader, backupFile, 2, &secondCrcOk);
|
||||
} // if/else
|
||||
|
||||
// Return valid headers code: 0 = both headers bad; 1 = main header
|
||||
// good, backup bad; 2 = backup header good, main header bad;
|
||||
@@ -1152,27 +1103,15 @@ int GPTData::LoadGPTBackup(const string & filename) {
|
||||
|
||||
SetGPTSize(numParts);
|
||||
|
||||
// If current disk size doesn't match that of backup....
|
||||
if (secondHeader.currentLBA != diskSize - UINT64_C(1)) {
|
||||
cout << "Warning! Current disk size doesn't match that of the backup!\n"
|
||||
<< "Adjusting sizes to match, but subsequent problems are possible!\n";
|
||||
MoveSecondHeaderToEnd();
|
||||
} // if
|
||||
|
||||
// Load main partition table, and record whether its CRC
|
||||
// matches the stored value
|
||||
sizeOfParts = numParts * sizeOfEntries;
|
||||
if (backupFile.Read(partitions, sizeOfParts) != (int) sizeOfParts) {
|
||||
cerr << "Warning! Read error " << errno << "; strange behavior now likely!\n";
|
||||
} // if
|
||||
|
||||
newCRC = chksum_crc32((unsigned char*) partitions, sizeOfParts);
|
||||
mainPartsCrcOk = (newCRC == mainHeader.partitionEntriesCRC);
|
||||
secondPartsCrcOk = (newCRC == secondHeader.partitionEntriesCRC);
|
||||
// Reverse byte order, if necessary
|
||||
if (littleEndian == 0) {
|
||||
ReversePartitionBytes();
|
||||
} // if
|
||||
if (!LoadPartitionTable(mainHeader, backupFile, (uint64_t) (3 - shortBackup)))
|
||||
cerr << "Warning! Read error " << errno
|
||||
<< " loading partition table; strange behavior now likely!\n";
|
||||
|
||||
} else {
|
||||
allOK = 0;
|
||||
@@ -1318,7 +1257,7 @@ void GPTData::CreatePartition(void) {
|
||||
|
||||
if (((firstBlock = FindFirstAvailable()) != 0) &&
|
||||
(firstFreePart < mainHeader.numParts)) {
|
||||
lastBlock = FindLastAvailable(firstBlock);
|
||||
lastBlock = FindLastAvailable();
|
||||
firstInLargest = FindFirstInLargest();
|
||||
|
||||
// Get partition number....
|
||||
@@ -1430,7 +1369,7 @@ int GPTData::DestroyGPT(int prompt) {
|
||||
} // if
|
||||
myDisk.Seek(mainHeader.partitionEntriesLBA); // seek to partition table
|
||||
tableSize = mainHeader.numParts * mainHeader.sizeOfPartitionEntries;
|
||||
emptyTable = (uint8_t*) malloc(tableSize);
|
||||
emptyTable = new uint8_t[tableSize];
|
||||
for (i = 0; i < tableSize; i++)
|
||||
emptyTable[i] = 0;
|
||||
sum = myDisk.Write(emptyTable, tableSize);
|
||||
@@ -1466,6 +1405,7 @@ int GPTData::DestroyGPT(int prompt) {
|
||||
myDisk.Close();
|
||||
cout << "GPT data structures destroyed! You may now partition the disk using fdisk or\n"
|
||||
<< "other utilities. Program will now terminate.\n";
|
||||
delete[] emptyTable;
|
||||
} else {
|
||||
cerr << "Problem opening " << device << " for writing! Program will now terminate.\n";
|
||||
} // if/else (fd != -1)
|
||||
@@ -1894,7 +1834,7 @@ int GPTData::SetGPTSize(uint32_t numEntries) {
|
||||
// data.
|
||||
if ((numEntries != mainHeader.numParts) || (numEntries != secondHeader.numParts)
|
||||
|| (partitions == NULL)) {
|
||||
newParts = (GPTPart*) calloc(numEntries, sizeof (GPTPart));
|
||||
newParts = new GPTPart [numEntries * sizeof (GPTPart)];
|
||||
if (newParts != NULL) {
|
||||
if (partitions != NULL) { // existing partitions; copy them over
|
||||
GetPartRange(&i, &high);
|
||||
@@ -1914,7 +1854,7 @@ int GPTData::SetGPTSize(uint32_t numEntries) {
|
||||
} // for
|
||||
trash = partitions;
|
||||
partitions = newParts;
|
||||
free(trash);
|
||||
delete[] trash;
|
||||
} // if
|
||||
} else { // No existing partition table; just create it
|
||||
partitions = newParts;
|
||||
@@ -2033,7 +1973,7 @@ int GPTData::ClearGPTData(void) {
|
||||
|
||||
// Set up the partition table....
|
||||
if (partitions != NULL)
|
||||
free(partitions);
|
||||
delete[] partitions;
|
||||
partitions = NULL;
|
||||
SetGPTSize(NUM_GPT_ENTRIES);
|
||||
|
||||
@@ -2297,10 +2237,9 @@ uint64_t GPTData::FindFirstInLargest(void) {
|
||||
return selectedSegment;
|
||||
} // GPTData::FindFirstInLargest()
|
||||
|
||||
// Find the last available block on the disk at or after the start
|
||||
// block. Returns 0 if there are no available partitions after
|
||||
// (or including) start.
|
||||
uint64_t GPTData::FindLastAvailable(uint64_t start) {
|
||||
// Find the last available block on the disk.
|
||||
// Returns 0 if there are no available partitions
|
||||
uint64_t GPTData::FindLastAvailable(void) {
|
||||
uint64_t last;
|
||||
uint32_t i;
|
||||
int lastMoved = 0;
|
||||
|
||||
11
gpt.h
11
gpt.h
@@ -8,7 +8,6 @@
|
||||
#include <sys/types.h>
|
||||
#include "gptpart.h"
|
||||
#include "support.h"
|
||||
#include "parttypes.h"
|
||||
#include "mbr.h"
|
||||
#include "bsd.h"
|
||||
#include "gptpart.h"
|
||||
@@ -16,7 +15,7 @@
|
||||
#ifndef __GPTSTRUCTS
|
||||
#define __GPTSTRUCTS
|
||||
|
||||
#define GPTFDISK_VERSION "0.6.3"
|
||||
#define GPTFDISK_VERSION "0.6.4-pre1"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -74,6 +73,12 @@ protected:
|
||||
int sectorAlignment; // Start & end partitions at multiples of sectorAlignment
|
||||
int beQuiet;
|
||||
WhichToUse whichWasUsed;
|
||||
|
||||
int LoadHeader(struct GPTHeader *header, DiskIO & disk, uint64_t sector, int *crcOk);
|
||||
int LoadPartitionTable(const struct GPTHeader & header, DiskIO & disk, uint64_t sector = 0);
|
||||
int CheckTable(struct GPTHeader *header);
|
||||
int SaveHeader(struct GPTHeader *header, DiskIO & disk, uint64_t sector);
|
||||
int SavePartitionTable(DiskIO & disk, uint64_t sector);
|
||||
public:
|
||||
// Basic necessary functions....
|
||||
GPTData(void);
|
||||
@@ -155,7 +160,7 @@ public:
|
||||
// Find information about free space
|
||||
uint64_t FindFirstAvailable(uint64_t start = 0);
|
||||
uint64_t FindFirstInLargest(void);
|
||||
uint64_t FindLastAvailable(uint64_t start);
|
||||
uint64_t FindLastAvailable();
|
||||
uint64_t FindLastInFree(uint64_t start);
|
||||
uint64_t FindFreeBlocks(uint32_t *numSegments, uint64_t *largestSegment);
|
||||
int IsFree(uint64_t sector);
|
||||
|
||||
@@ -146,7 +146,8 @@ void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
|
||||
cout.width(14);
|
||||
cout << lastLBA << " ";
|
||||
cout << BytesToSI(blockSize * (lastLBA - firstLBA + 1)) << " ";
|
||||
for (i = 0; i < 9 - (int) sizeInSI.length(); i++) cout << " ";
|
||||
for (i = 0; i < 10 - (int) sizeInSI.length(); i++)
|
||||
cout << " ";
|
||||
cout.fill('0');
|
||||
cout.width(4);
|
||||
cout.setf(ios::uppercase);
|
||||
|
||||
@@ -104,7 +104,7 @@ void PartType::AddAllTypes(void) {
|
||||
// FreeBSD partition types....
|
||||
// Note: Rather than extract FreeBSD disklabel data, convert FreeBSD
|
||||
// partitions in-place, and let FreeBSD sort out the details....
|
||||
AddType(0xa500, "516E7CB4-6ECF-11D6-8FF8-00022D09712B", "FreeBSD Disklabel");
|
||||
AddType(0xa500, "516E7CB4-6ECF-11D6-8FF8-00022D09712B", "FreeBSD disklabel");
|
||||
AddType(0xa501, "83BD6B9D-7F41-11DC-BE0B-001560B84F0F", "FreeBSD boot");
|
||||
AddType(0xa502, "516E7CB5-6ECF-11D6-8FF8-00022D09712B", "FreeBSD swap");
|
||||
AddType(0xa503, "516E7CB6-6ECF-11D6-8FF8-00022D09712B", "FreeBSD UFS");
|
||||
@@ -191,7 +191,7 @@ int PartType::AddType(uint16_t mbrType, const char * guidData, const char * name
|
||||
} // GUID::AddType(const char* variant)
|
||||
|
||||
// Assign a GUID based on my custom 2-byte (16-bit) MBR hex ID variant
|
||||
GUIDData & PartType::operator=(uint16_t ID) {
|
||||
PartType & PartType::operator=(uint16_t ID) {
|
||||
AType* theItem = allTypes;
|
||||
int found = 0;
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
GUIDData & operator=(const char * orig) {return GUIDData::operator=(orig);}
|
||||
|
||||
// New data assignment
|
||||
GUIDData & operator=(uint16_t ID); // Use MBR type code time 0x0100 to assign GUID
|
||||
PartType & operator=(uint16_t ID); // Use MBR type code times 0x0100 to assign GUID
|
||||
|
||||
// Retrieve transformed GUID data based on type code matches
|
||||
string TypeName(void);
|
||||
|
||||
@@ -140,7 +140,7 @@ int main(int argc, char *argv[]) {
|
||||
saveData = 1;
|
||||
break;
|
||||
case 'E':
|
||||
cout << theGPT.FindLastAvailable(theGPT.FindFirstInLargest()) << "\n";
|
||||
cout << theGPT.FindLastInFree(theGPT.FindFirstInLargest()) << "\n";
|
||||
break;
|
||||
case 'f':
|
||||
cout << theGPT.FindFirstInLargest() << "\n";
|
||||
@@ -205,7 +205,7 @@ int main(int argc, char *argv[]) {
|
||||
case 't':
|
||||
theGPT.JustLooking(0);
|
||||
partNum = (int) GetInt(typeCode, 1) - 1;
|
||||
sscanf(GetString(typeCode, 2).c_str(), "%ux", &hexCode);
|
||||
sscanf(GetString(typeCode, 2).c_str(), "%x", &hexCode);
|
||||
if (theGPT.ChangePartType(partNum, hexCode)) {
|
||||
saveData = 1;
|
||||
} else {
|
||||
|
||||
@@ -234,12 +234,12 @@ void ReverseBytes(void* theValue, int numBytes) {
|
||||
char* tempValue = NULL;
|
||||
int i;
|
||||
|
||||
tempValue = (char*) malloc(numBytes);
|
||||
tempValue = new char [numBytes];
|
||||
if (tempValue != NULL) {
|
||||
memcpy(tempValue, theValue, numBytes);
|
||||
for (i = 0; i < numBytes; i++)
|
||||
((char*) theValue)[i] = tempValue[numBytes - i - 1];
|
||||
free(tempValue);
|
||||
delete[] tempValue;
|
||||
} // if
|
||||
} // ReverseBytes()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user