Nearing 0.6.2 release; Windows version now works.

This commit is contained in:
srs5694
2010-01-28 21:10:52 -05:00
parent 91544e13fb
commit 0a6973119c
17 changed files with 295 additions and 285 deletions

View File

@@ -1,6 +1,10 @@
0.6.2 (?/??/2010): 0.6.2 (?/??/2010):
------------------ ------------------
- The change-type ('t' on main menu) option now changes the partition's
name *IF* the current name is the generic one for the partition type.
If the current name is not the generic name, it is NOT changed.
- Fixed bug that caused new protective MBR to not be created when the - 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 MBR was invalid and the GPT was damaged and the user opts to try to
use the GPT data. use the GPT data.

View File

@@ -19,9 +19,6 @@ gdisk: $(LIB_OBJS) gdisk.o
sgdisk: $(LIB_OBJS) sgdisk.o sgdisk: $(LIB_OBJS) sgdisk.o
$(CXX) $(LIB_OBJS) sgdisk.o -L/opt/local/lib -L/usr/local/lib -lpopt -o sgdisk $(CXX) $(LIB_OBJS) sgdisk.o -L/opt/local/lib -L/usr/local/lib -lpopt -o sgdisk
wipegpt: $(LIB_OBJS) wipegpt.o
$(CXX) $(LIB_OBJS) wipegpt.o -o wipegpt
lint: #no pre-reqs lint: #no pre-reqs
lint $(SRCS) lint $(SRCS)

View File

@@ -1,7 +1,8 @@
CC=/usr/bin/i586-mingw32msvc-gcc CC=/usr/bin/i586-mingw32msvc-gcc
CXX=/usr/bin/i586-mingw32msvc-g++ CXX=/usr/bin/i586-mingw32msvc-g++
STRIP=/usr/bin/i586-mingw32msvc-strip
CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g
CXXFLAGS=-O2 -DMINGW -Wuninitialized -Wreturn-type -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g CXXFLAGS=-O2 -Wuninitialized -Wreturn-type -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
LIB_NAMES=gptpart bsd parttypes attributes crc32 mbr gpt support diskio diskio-windows LIB_NAMES=gptpart bsd parttypes attributes crc32 mbr gpt support diskio diskio-windows
LIB_SRCS=$(NAMES:=.cc) LIB_SRCS=$(NAMES:=.cc)
LIB_OBJS=$(LIB_NAMES:=.o) LIB_OBJS=$(LIB_NAMES:=.o)
@@ -17,16 +18,16 @@ gdisk: $(LIB_OBJS) gdisk.o
$(CXX) $(LIB_OBJS) gdisk.o -o gdisk.exe $(CXX) $(LIB_OBJS) gdisk.o -o gdisk.exe
sgdisk: $(LIB_OBJS) sgdisk.o sgdisk: $(LIB_OBJS) sgdisk.o
$(CXX) $(LIB_OBJS) sgdisk.o -L/opt/local/lib -L/usr/local/lib -lpopt -o sgdisk $(CXX) $(LIB_OBJS) sgdisk.o -L/opt/local/lib -L/usr/local/lib -lpopt -o sgdisk.exe
wipegpt: $(LIB_OBJS) wipegpt.o
$(CXX) $(LIB_OBJS) wipegpt.o -o wipegpt
lint: #no pre-reqs lint: #no pre-reqs
lint $(SRCS) lint $(SRCS)
clean: #no pre-reqs clean: #no pre-reqs
rm -f core *.o *~ gdisk sgdisk rm -f core *.o *~ gdisk.exe sgdisk.exe
strip: #no pre-reqs
$(STRIP) gdisk.exe
# what are the source dependencies # what are the source dependencies
depend: $(SRCS) depend: $(SRCS)

6
bsd.cc
View File

@@ -43,12 +43,12 @@ 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. Returns 1 on success, 0 on failure. // the bulk of the work. Returns 1 on success, 0 on failure.
int BSDData::ReadBSDData(string *device, uint64_t startSector, uint64_t endSector) { int BSDData::ReadBSDData(const string & device, uint64_t startSector, uint64_t endSector) {
int allOK = 1; int allOK = 1;
DiskIO myDisk; DiskIO myDisk;
if (*device != "") { if (device != "") {
if (myDisk.OpenForRead(*device)) { if (myDisk.OpenForRead(device)) {
allOK = ReadBSDData(&myDisk, startSector, endSector); allOK = ReadBSDData(&myDisk, startSector, endSector);
} else { } else {
allOK = 0; allOK = 0;

2
bsd.h
View File

@@ -72,7 +72,7 @@ class BSDData {
public: public:
BSDData(void); BSDData(void);
~BSDData(void); ~BSDData(void);
int ReadBSDData(string *deviceFilename, uint64_t startSector, uint64_t endSector); int ReadBSDData(const string & deviceFilename, uint64_t startSector, uint64_t endSector);
int 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);

View File

@@ -42,9 +42,9 @@ void DiskIO::MakeRealName(void) {
if ((colonPos != string::npos) && (colonPos <= 3)) { if ((colonPos != string::npos) && (colonPos <= 3)) {
realFilename = "\\\\.\\physicaldrive"; realFilename = "\\\\.\\physicaldrive";
realFilename += userFilename.substr(0, colonPos); realFilename += userFilename.substr(0, colonPos);
} else {
realFilename = userFilename;
} // if/else } // if/else
printf("Exiting DiskIO::MakeRealName(); translated '%s' ", userFilename.c_str());
printf("to '%s'\n", realFilename.c_str());
} // DiskIO::MakeRealName() } // DiskIO::MakeRealName()
// Open the currently on-record file for reading // Open the currently on-record file for reading
@@ -60,12 +60,11 @@ int DiskIO::OpenForRead(void) {
} // if } // if
if (shouldOpen) { if (shouldOpen) {
printf("Opening '%s' for reading.\n", realFilename.c_str());
fd = CreateFile(realFilename.c_str(),GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, fd = CreateFile(realFilename.c_str(),GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fd == INVALID_HANDLE_VALUE) { if (fd == INVALID_HANDLE_VALUE) {
CloseHandle(fd); CloseHandle(fd);
fprintf(stderr, "Problem opening %s for reading!\n", realFilename.c_str()); cerr << "Problem opening " << realFilename << " for reading!\n";
realFilename = ""; realFilename = "";
userFilename = ""; userFilename = "";
isOpen = 0; isOpen = 0;
@@ -94,11 +93,12 @@ int DiskIO::OpenForWrite(void) {
FILE_ATTRIBUTE_NORMAL, NULL); FILE_ATTRIBUTE_NORMAL, NULL);
if (fd == INVALID_HANDLE_VALUE) { if (fd == INVALID_HANDLE_VALUE) {
CloseHandle(fd); CloseHandle(fd);
isOpen = 1;
openForWrite = 1;
} else {
isOpen = 0; isOpen = 0;
openForWrite = 0; openForWrite = 0;
errno = GetLastError();
} else {
isOpen = 1;
openForWrite = 1;
} // if/else } // if/else
return isOpen; return isOpen;
} // DiskIO::OpenForWrite(void) } // DiskIO::OpenForWrite(void)
@@ -133,6 +133,7 @@ int DiskIO::GetBlockSize(void) {
__out LPDWORD lpTotalNumberOfClusters __out LPDWORD lpTotalNumberOfClusters
); */ ); */
// err = GetDiskFreeSpace(realFilename.c_str(), &junk1, &blockSize, &junk2, &junk3); // err = GetDiskFreeSpace(realFilename.c_str(), &junk1, &blockSize, &junk2, &junk3);
// Above call is fubared -- returns weird values for blockSize....
err = 1; err = 1;
blockSize = 512; blockSize = 512;
@@ -142,9 +143,9 @@ int DiskIO::GetBlockSize(void) {
// file, so don't display the warning message.... // file, so don't display the warning message....
// 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 != 267) { // 267 is returned on ordinary files
printf("\aError %d when determining sector size! Setting sector size to %d\n", cerr << "\aError " << GetLastError() << " when determining sector size! "
GetLastError(), SECTOR_SIZE); << "Setting sector size to " << SECTOR_SIZE << "\n";
} // if } // if
} // if (err == -1) } // if (err == -1)
} // if (isOpen) } // if (isOpen)
@@ -155,21 +156,26 @@ int DiskIO::GetBlockSize(void) {
// Resync disk caches so the OS uses the new partition table. This code varies // Resync disk caches so the OS uses the new partition table. This code varies
// a lot from one OS to another. // a lot from one OS to another.
void DiskIO::DiskSync(void) { void DiskIO::DiskSync(void) {
int i; DWORD i;
GET_LENGTH_INFORMATION buf;
// If disk isn't open, try to open it.... // If disk isn't open, try to open it....
if (!isOpen) { if (!openForWrite) {
OpenForRead(); OpenForWrite();
} // if } // if
if (isOpen) { if (isOpen) {
#ifndef MINGW if (DeviceIoControl(fd, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, &buf, sizeof(buf), &i, NULL) == 0) {
sync(); cout << "Disk synchronization failed! The computer may use the old partition table\n"
#endif << "until you reboot or remove and re-insert the disk!\n";
#ifdef MINGW } else {
printf("Warning: I don't know how to sync disks in Windows! The old partition table is\n" cout << "Disk synchronization succeeded! The computer should now use the new\n"
"probably still in use!\n"); << "partition table.\n";
#endif } // if/else
} else {
cout << "Unable to open the disk for synchronization operation! The computer will\n"
<< "continue to use the old partition table until you reboot or remove and\n"
<< "re-insert the disk!\n";
} // if (isOpen) } // if (isOpen)
} // DiskIO::DiskSync() } // DiskIO::DiskSync()
@@ -186,22 +192,11 @@ int DiskIO::Seek(uint64_t sector) {
} // if } // if
if (isOpen) { if (isOpen) {
bytePos = sector * (uint64_t) GetBlockSize(); seekTo.QuadPart = sector * (uint64_t) GetBlockSize();
lowBits = (uint32_t) (bytePos / UINT64_C(4294967296));
highBits = (uint32_t) (bytePos % UINT64_C(4294967296));
seekTo.LowPart = lowBits;
seekTo.HighPart = highBits;
// seekTo.QuadPart = (LONGLONG) (sector * (uint64_t) GetBlockSize());
/* printf("In DiskIO::Seek(), sector = %llu, ", sector);
printf("block size = %d, ", GetBlockSize());
printf("seekTo.QuadPart = %lld\n", seekTo.QuadPart);
printf(" seekTo.LowPart = %lu, ", seekTo.LowPart);
printf("seekTo.HighPart = %lu\n", seekTo.HighPart); */
retval = SetFilePointerEx(fd, seekTo, NULL, FILE_BEGIN); retval = SetFilePointerEx(fd, seekTo, NULL, FILE_BEGIN);
if (retval == 0) { if (retval == 0) {
errno = GetLastError(); errno = GetLastError();
fprintf(stderr, "Error when seeking to %lld! Error is %d\n", cerr << "Error when seeking to " << seekTo.QuadPart << "! Error is " << errno << "\n";
seekTo.QuadPart, errno);
retval = 0; retval = 0;
} // if } // if
} // if } // if
@@ -235,9 +230,7 @@ int DiskIO::Read(void* buffer, int numBytes) {
} // if/else } // if/else
// 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);
ReadFile(fd, tempSpace, numBlocks * blockSize, &retval, NULL); ReadFile(fd, tempSpace, numBlocks * blockSize, &retval, NULL);
printf("In DiskIO::Read(), have read %d bytes.\n", (int) retval);
for (i = 0; i < numBytes; i++) { for (i = 0; i < numBytes; i++) {
((char*) buffer)[i] = tempSpace[i]; ((char*) buffer)[i] = tempSpace[i];
} // for } // for
@@ -284,7 +277,6 @@ int DiskIO::Write(void* buffer, int numBytes) {
for (i = numBytes; i < numBlocks * blockSize; i++) { for (i = numBytes; i < numBlocks * blockSize; i++) {
tempSpace[i] = 0; tempSpace[i] = 0;
} // for } // for
// retval = write(fd, tempSpace, numBlocks * blockSize);
WriteFile(fd, tempSpace, numBlocks * blockSize, &numWritten, NULL); WriteFile(fd, tempSpace, numBlocks * blockSize, &numWritten, NULL);
retval = (int) numWritten; retval = (int) numWritten;
@@ -300,8 +292,7 @@ int DiskIO::Write(void* buffer, int numBytes) {
// Returns the size of the disk in blocks. // Returns the size of the disk in blocks.
uint64_t DiskIO::DiskSize(int *err) { uint64_t DiskIO::DiskSize(int *err) {
uint64_t sectors = 0; // size in sectors uint64_t sectors = 0; // size in sectors
off_t bytes = 0; // size in bytes DWORD bytes, moreBytes; // low- and high-order bytes of file size
struct stat64 st;
GET_LENGTH_INFORMATION buf; GET_LENGTH_INFORMATION buf;
DWORD i; DWORD i;
@@ -316,30 +307,18 @@ uint64_t DiskIO::DiskSize(int *err) {
// on Linux, but I had some problems. IIRC, it ran OK on 32-bit // on Linux, but I had some problems. IIRC, it ran OK on 32-bit
// systems but not on 64-bit. Keep this in mind in case of // systems but not on 64-bit. Keep this in mind in case of
// 32/64-bit issues on MacOS.... // 32/64-bit issues on MacOS....
/* HANDLE fin;
fin = CreateFile(realFilename.c_str(), GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); */
if (DeviceIoControl(fd, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &buf, sizeof(buf), &i, NULL)) { if (DeviceIoControl(fd, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &buf, sizeof(buf), &i, NULL)) {
sectors = (uint64_t) buf.Length.QuadPart / GetBlockSize(); sectors = (uint64_t) buf.Length.QuadPart / GetBlockSize();
// printf("disk_get_size_win32 IOCTL_DISK_GET_LENGTH_INFO = %llu\n", *err = 0;
// (long long unsigned) sectors); } else { // doesn't seem to be a disk device; assume it's an image file....
} else { bytes = GetFileSize(fd, &moreBytes);
fprintf(stderr, "Couldn't determine disk size!\n"); sectors = ((uint64_t) bytes + ((uint64_t) moreBytes) * UINT32_MAX) / GetBlockSize();
} *err = 0;
} // if
} else {
*err = -1;
sectors = 0;
} // if/else (isOpen)
/* // 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
// fstat() gives us....
if ((sectors == 0) || (*err == -1)) {
if (fstat64(fd, &st) == 0) {
bytes = (off_t) st.st_size;
if ((bytes % UINT64_C(512)) != 0)
fprintf(stderr, "Warning: File size is not a multiple of 512 bytes!"
" Misbehavior is likely!\n\a");
sectors = bytes / UINT64_C(512);
} // if
} // if */
} // if (isOpen)
return sectors; return sectors;
} // DiskIO::DiskSize() } // DiskIO::DiskSize()

View File

@@ -15,7 +15,7 @@
#define __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS #define __STDC_CONSTANT_MACROS
#ifdef MINGW #ifdef _WIN32
#include <windows.h> #include <windows.h>
#include <winioctl.h> #include <winioctl.h>
#define fstat64 fstat #define fstat64 fstat
@@ -52,7 +52,7 @@ DiskIO::~DiskIO(void) {
} // destructor } // destructor
// Open a disk device for reading. Returns 1 on success, 0 on failure. // Open a disk device for reading. Returns 1 on success, 0 on failure.
int DiskIO::OpenForRead(string filename) { int DiskIO::OpenForRead(const string & filename) {
int shouldOpen = 1; int shouldOpen = 1;
if (isOpen) { // file is already open if (isOpen) { // file is already open
@@ -74,7 +74,7 @@ int DiskIO::OpenForRead(string filename) {
// Open a disk for reading and writing by filename. // Open a disk for reading and writing by filename.
// Returns 1 on success, 0 on failure. // Returns 1 on success, 0 on failure.
int DiskIO::OpenForWrite(string filename) { int DiskIO::OpenForWrite(const string & filename) {
int retval = 0; int retval = 0;
if ((isOpen) && (openForWrite) && ((filename == realFilename) || (filename == userFilename))) { if ((isOpen) && (openForWrite) && ((filename == realFilename) || (filename == userFilename))) {
@@ -151,7 +151,7 @@ int DiskIO::FindAlignment(void) {
} // DiskIO::FindAlignment(int) */ } // DiskIO::FindAlignment(int) */
// The same as FindAlignment(int), but opens and closes a device by filename // The same as FindAlignment(int), but opens and closes a device by filename
int DiskIO::FindAlignment(string filename) { int DiskIO::FindAlignment(const string & filename) {
int fd; int fd;
int retval = 1; int retval = 1;

View File

@@ -18,7 +18,7 @@
#include <string> #include <string>
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#ifdef MINGW #ifdef _WIN32
#include <windows.h> #include <windows.h>
#include <winioctl.h> #include <winioctl.h>
#else #else
@@ -52,7 +52,7 @@ class DiskIO {
int isOpen; int isOpen;
int openForWrite; int openForWrite;
uint8_t *sectorData; uint8_t *sectorData;
#ifdef MINGW #ifdef _WIN32
HANDLE fd; HANDLE fd;
#else #else
int fd; int fd;
@@ -62,9 +62,9 @@ class DiskIO {
~DiskIO(void); ~DiskIO(void);
void MakeRealName(void); void MakeRealName(void);
int OpenForRead(string filename); int OpenForRead(const string & filename);
int OpenForRead(void); int OpenForRead(void);
int OpenForWrite(string filename); int OpenForWrite(const string & filename);
int OpenForWrite(void); int OpenForWrite(void);
void Close(); void Close();
int Seek(uint64_t sector); int Seek(uint64_t sector);
@@ -73,7 +73,7 @@ class DiskIO {
void DiskSync(void); // resync disk caches to use new partitions void DiskSync(void); // resync disk caches to use new partitions
int GetBlockSize(void); int GetBlockSize(void);
int FindAlignment(void); int FindAlignment(void);
int FindAlignment(string filename); int FindAlignment(const string & filename);
int IsOpen(void) {return isOpen;} int IsOpen(void) {return isOpen;}
int IsOpenForWrite(void) {return openForWrite;} int IsOpenForWrite(void) {return openForWrite;}

View File

@@ -2,7 +2,7 @@
.\" May be distributed under the GNU General Public License .\" May be distributed under the GNU General Public License
.TH "GDISK" "8" "0.5.3" "Roderick W. Smith" "GPT fdisk Manual" .TH "GDISK" "8" "0.5.3" "Roderick W. Smith" "GPT fdisk Manual"
.SH "NAME" .SH "NAME"
gdisk \- Interactive GUID partition table (GPT) manipulator for Linux and Unix gdisk \- Interactive GUID partition table (GPT) manipulator
.SH "SYNOPSIS" .SH "SYNOPSIS"
.BI "gdisk " .BI "gdisk "
[ \-l ] [ \-l ]
@@ -453,10 +453,8 @@ mid-physical-sector, though, performance can suffer on such drives, since
important filesystem data structures can span physical sectors on the disk. important filesystem data structures can span physical sectors on the disk.
To minimize such problems, GPT fdisk aligns the start of partitions on the To minimize such problems, GPT fdisk aligns the start of partitions on the
boundary of presumed physical sectors. You can set the number of logical boundary of presumed physical sectors. You can set the number of logical
sectors per physical sector with this option. The default is 8, except on sectors per physical sector with this option. The default is 1 on disks
Linux 2.6.32 and later, in which case it's read from the disk. A value of 8 smaller than 800GB and 8 on larger disks.
will result in a tiny amount of wasted disk space on older disks with true
512-byte sectors but will otherwise be harmless.
.TP .TP
.B m .B m

View File

@@ -34,6 +34,17 @@ int main(int argc, char* argv[]) {
if (argc == 2) { // basic usage if (argc == 2) { // basic usage
if (SizesOK()) { if (SizesOK()) {
#ifdef _WIN32
cout << "\a************************************************************************\n"
<< "Most versions of Windows cannot boot from a GPT disk, and most varieties\n"
<< "prior to Vista cannot read GPT disks. Therefore, you should exit now\n"
<< "unless you understand the implications of converting MBR to GPT, editing\n"
<< "an existing GPT disk, or creating a new GPT disk layout!\n"
<< "************************************************************************\n\n";
cout << "Are you SURE you want to continue? ";
if (GetYN() != 'Y')
exit(0);
#endif
doMore = theGPT.LoadPartitions(argv[1]); doMore = theGPT.LoadPartitions(argv[1]);
if (doMore) { if (doMore) {
MainMenu(argv[1], &theGPT); MainMenu(argv[1], &theGPT);

32
gpt.cc
View File

@@ -239,7 +239,7 @@ int GPTData::Verify(void) {
<< largestSegment << " (" << BytesToSI(largestSegment * (uint64_t) blockSize) << largestSegment << " (" << BytesToSI(largestSegment * (uint64_t) blockSize)
<< ") in size\n"; << ") in size\n";
} else { } else {
cout << "\nIdentified %d problems!\n", problems; cout << "\nIdentified " << problems << " problems!\n";
} // if/else } // if/else
return (problems); return (problems);
@@ -497,7 +497,7 @@ int GPTData::FindOverlaps(void) {
for (i = 1; i < mainHeader.numParts; i++) { for (i = 1; i < mainHeader.numParts; i++) {
for (j = 0; j < i; j++) { for (j = 0; j < i; j++) {
if (partitions[i].DoTheyOverlap(&partitions[j])) { if (partitions[i].DoTheyOverlap(partitions[j])) {
problems++; problems++;
cout << "\nProblem: partitions " << i + 1 << " and " << j + 1 << " overlap:\n"; cout << "\nProblem: partitions " << i + 1 << " and " << j + 1 << " overlap:\n";
cout << " Partition " << i + 1 << ": " << partitions[i].GetFirstLBA() cout << " Partition " << i + 1 << ": " << partitions[i].GetFirstLBA()
@@ -550,7 +550,7 @@ void GPTData::PartitionScan(void) {
} // GPTData::PartitionScan() } // GPTData::PartitionScan()
// Read GPT data from a disk. // Read GPT data from a disk.
int GPTData::LoadPartitions(string deviceFilename) { int GPTData::LoadPartitions(const string & deviceFilename) {
int err; int err;
int allOK = 1, i; int allOK = 1, i;
uint64_t firstBlock, lastBlock; uint64_t firstBlock, lastBlock;
@@ -636,7 +636,7 @@ int GPTData::LoadPartitions(string deviceFilename) {
// succeeded, 0 if there are obvious problems.... // succeeded, 0 if there are obvious problems....
int GPTData::ForceLoadGPTData(void) { int GPTData::ForceLoadGPTData(void) {
int allOK = 1, validHeaders; int allOK = 1, validHeaders;
off_t seekTo; uint64_t seekTo;
uint8_t* storage; uint8_t* storage;
uint32_t newCRC, sizeOfParts; uint32_t newCRC, sizeOfParts;
@@ -839,7 +839,7 @@ int GPTData::SaveGPTData(int quiet) {
char answer, line[256]; char answer, line[256];
uint64_t secondTable; uint64_t secondTable;
uint32_t numParts; uint32_t numParts;
off_t offset; uint64_t offset;
if (device == "") { if (device == "") {
cerr << "Device not defined.\n"; cerr << "Device not defined.\n";
@@ -936,7 +936,7 @@ int GPTData::SaveGPTData(int quiet) {
// Now seek to near the end to write the secondary GPT.... // Now seek to near the end to write the secondary GPT....
if (allOK) { if (allOK) {
offset = (off_t) secondTable; offset = (uint64_t) secondTable;
if (myDisk.Seek(offset) != 1) { if (myDisk.Seek(offset) != 1) {
allOK = 0; allOK = 0;
cerr << "Unable to seek to end of disk! Perhaps the 'e' option on the experts' menu\n" cerr << "Unable to seek to end of disk! Perhaps the 'e' option on the experts' menu\n"
@@ -998,12 +998,11 @@ int GPTData::SaveGPTData(int quiet) {
// the main GPT header, the backup GPT header, and the main partition // the main GPT header, the backup GPT header, and the main partition
// table; it discards the backup partition table, since it should be // table; it discards the backup partition table, since it should be
// identical to the main partition table on healthy disks. // identical to the main partition table on healthy disks.
int GPTData::SaveGPTBackup(string filename) { int GPTData::SaveGPTBackup(const string & filename) {
int fd, allOK = 1; int allOK = 1;
uint32_t numParts; uint32_t numParts;
DiskIO backupFile; DiskIO backupFile;
// if ((fd = open(filename, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH)) != -1) {
if (backupFile.OpenForWrite(filename)) { if (backupFile.OpenForWrite(filename)) {
// Reverse the byte order, if necessary.... // Reverse the byte order, if necessary....
numParts = mainHeader.numParts; numParts = mainHeader.numParts;
@@ -1066,13 +1065,12 @@ int GPTData::SaveGPTBackup(string filename) {
// does minimal error checking. It returns 1 if it completed successfully, // 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 // 0 if there was a problem. In the latter case, it creates a new empty
// set of partitions. // set of partitions.
int GPTData::LoadGPTBackup(string filename) { int GPTData::LoadGPTBackup(const string & filename) {
int fd, allOK = 1, val; int allOK = 1, val;
uint32_t numParts, sizeOfEntries, sizeOfParts, newCRC; uint32_t numParts, sizeOfEntries, sizeOfParts, newCRC;
int littleEndian = 1; int littleEndian = 1;
DiskIO backupFile; DiskIO backupFile;
// if ((fd = open(filename, O_RDONLY)) != -1) {
if (backupFile.OpenForRead(filename)) { if (backupFile.OpenForRead(filename)) {
if (IsLittleEndian() == 0) if (IsLittleEndian() == 0)
littleEndian = 0; littleEndian = 0;
@@ -1473,7 +1471,7 @@ WhichToUse GPTData::UseWhichPartitions(void) {
cout << "\n**********************************************************************\n" cout << "\n**********************************************************************\n"
<< "Found invalid GPT and valid BSD disklabel; converting BSD disklabel\n" << "Found invalid GPT and valid BSD disklabel; converting BSD disklabel\n"
<< "to GPT format."; << "to GPT format.";
if (!justLooking) { if ((!justLooking) && (!beQuiet)) {
cout << "\a THIS OPERATON IS POTENTIALLY DESTRUCTIVE! Your first\n" cout << "\a THIS OPERATON IS POTENTIALLY DESTRUCTIVE! Your first\n"
<< "BSD partition will likely be unusable. Exit by typing 'q' if you don't\n" << "BSD partition will likely be unusable. Exit by typing 'q' if you don't\n"
<< "want to convert your BSD partitions to GPT format!"; << "want to convert your BSD partitions to GPT format!";
@@ -1493,10 +1491,9 @@ WhichToUse GPTData::UseWhichPartitions(void) {
cout << "Found valid GPT with hybrid MBR; using GPT.\n"; cout << "Found valid GPT with hybrid MBR; using GPT.\n";
} // if } // if
if ((state == gpt_valid) && (mbrState == invalid)) { if ((state == gpt_valid) && (mbrState == invalid)) {
cout << "\aFound valid GPT with corrupt MBR; using GPT and will create new\n" cout << "\aFound valid GPT with corrupt MBR; using GPT and will write new\n"
<< "protective MBR on save.\n"; << "protective MBR on save.\n";
which = use_gpt; which = use_gpt;
protectiveMBR.MakeProtectiveMBR();
} // if } // if
if ((state == gpt_valid) && (mbrState == mbr)) { if ((state == gpt_valid) && (mbrState == mbr)) {
if (!beQuiet) { if (!beQuiet) {
@@ -1506,7 +1503,6 @@ WhichToUse GPTData::UseWhichPartitions(void) {
which = use_mbr; which = use_mbr;
} else if (answer == 2) { } else if (answer == 2) {
which = use_gpt; which = use_gpt;
protectiveMBR.MakeProtectiveMBR();
cout << "Using GPT and creating fresh protective MBR.\n"; cout << "Using GPT and creating fresh protective MBR.\n";
} else which = use_new; } else which = use_new;
} else which = use_abort; } else which = use_abort;
@@ -1612,7 +1608,7 @@ int GPTData::XFormDisklabel(int i) {
// If all is OK, read the disklabel and convert it. // If all is OK, read the disklabel and convert it.
if (goOn) { if (goOn) {
goOn = disklabel.ReadBSDData(&myDisk, partitions[partNum].GetFirstLBA(), goOn = disklabel.ReadBSDData(device, partitions[partNum].GetFirstLBA(),
partitions[partNum].GetLastLBA()); partitions[partNum].GetLastLBA());
if ((goOn) && (disklabel.IsDisklabel())) { if ((goOn) && (disklabel.IsDisklabel())) {
numDone = XFormDisklabel(&disklabel, startPart); numDone = XFormDisklabel(&disklabel, startPart);
@@ -2053,7 +2049,7 @@ void GPTData::MoveSecondHeaderToEnd() {
secondHeader.partitionEntriesLBA = secondHeader.lastUsableLBA + UINT64_C(1); secondHeader.partitionEntriesLBA = secondHeader.lastUsableLBA + UINT64_C(1);
} // GPTData::FixSecondHeaderLocation() } // GPTData::FixSecondHeaderLocation()
int GPTData::SetName(uint32_t partNum, string theName) { int GPTData::SetName(uint32_t partNum, const string & theName) {
int retval = 1; int retval = 1;
if (!IsFreePartNum(partNum)) { if (!IsFreePartNum(partNum)) {

12
gpt.h
View File

@@ -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(string f) {return protectiveMBR.ReadMBRData(f);} int LoadMBR(const string & f) {return protectiveMBR.ReadMBRData(f);}
void PartitionScan(void); void PartitionScan(void);
int LoadPartitions(string deviceFilename); int LoadPartitions(const 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(string filename); int SaveGPTBackup(const string & filename);
int LoadGPTBackup(string filename); int LoadGPTBackup(const 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, string theName = ""); int SetName(uint32_t partNum, const 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);
@@ -170,7 +170,7 @@ public:
WhichToUse WhichWasUsed(void) {return whichWasUsed;} WhichToUse WhichWasUsed(void) {return whichWasUsed;}
// Endianness functions // Endianness functions
void ReverseHeaderBytes(struct GPTHeader* header); // for endianness void ReverseHeaderBytes(struct GPTHeader* header);
void ReversePartitionBytes(); // for endianness void ReversePartitionBytes(); // for endianness
}; // class GPTData }; // class GPTData

View File

@@ -35,17 +35,6 @@ GPTPart::GPTPart(void) {
GPTPart::~GPTPart(void) { GPTPart::~GPTPart(void) {
} // destructor } // destructor
// Return partition's name field, converted to a C++ ASCII string
string GPTPart::GetName(void) {
string theName;
int i;
for (i = 0; i < NAME_SIZE; i += 2) {
theName += name[i];
} // for
return theName;
} // GPTPart::GetName()
// Return the gdisk-specific two-byte hex code for the partition // Return the gdisk-specific two-byte hex code for the partition
uint16_t GPTPart::GetHexType(void) { uint16_t GPTPart::GetHexType(void) {
return typeHelper.GUIDToID(partitionType); return typeHelper.GUIDToID(partitionType);
@@ -66,18 +55,30 @@ uint64_t GPTPart::GetLengthLBA(void) {
return length; return length;
} // GPTPart::GetLengthLBA() } // GPTPart::GetLengthLBA()
GPTPart & GPTPart::operator=(const GPTPart & orig) { // Return partition's name field, converted to a C++ ASCII string
string GPTPart::GetName(void) {
string theName;
int i; int i;
partitionType = orig.partitionType; theName = "";
uniqueGUID = orig.uniqueGUID; for (i = 0; i < NAME_SIZE; i += 2) {
firstLBA = orig.firstLBA; if (name[i] != '\0')
lastLBA = orig.lastLBA; theName += name[i];
attributes = orig.attributes; } // for
for (i = 0; i < NAME_SIZE; i++) return theName;
name[i] = orig.name[i]; } // GPTPart::GetName()
return *this;
} // assignment operator // Set the type code to the specified one. Also changes the partition
// name *IF* the current name is the generic one for the current partition
// type.
void GPTPart::SetType(struct GUIDData t) {
int nameSame = 1, currentLength, i;
if (GetName() == typeHelper.GUIDToName(partitionType)) {
SetName(typeHelper.GUIDToName(t));
} // if
partitionType = t;
} // GPTPart::SetType()
// Sets the unique GUID to a value of 0 or a random value, // Sets the unique GUID to a value of 0 or a random value,
// depending on the parameter: 0 = 0, anything else = random // depending on the parameter: 0 = 0, anything else = random
@@ -93,138 +94,11 @@ void GPTPart::SetUniqueGUID(int zeroOrRandom) {
} }
} // GPTPart::SetUniqueGUID() } // GPTPart::SetUniqueGUID()
// Blank (delete) a single partition
void GPTPart::BlankPartition(void) {
int j;
GUIDData zeroGUID;
zeroGUID.data1 = 0;
zeroGUID.data2 = 0;
uniqueGUID = zeroGUID;
partitionType = zeroGUID;
firstLBA = 0;
lastLBA = 0;
attributes = 0;
for (j = 0; j < NAME_SIZE; j++)
name[j] = '\0';
} // GPTPart::BlankPartition
// Returns 1 if the two partitions overlap, 0 if they don't
int GPTPart::DoTheyOverlap(GPTPart* other) {
int theyDo = 0;
// Don't bother checking unless these are defined (both start and end points
// are 0 for undefined partitions, so just check the start points)
if ((firstLBA != 0) && (other->firstLBA != 0)) {
if ((firstLBA < other->lastLBA) && (lastLBA >= other->firstLBA))
theyDo = 1;
if ((other->firstLBA < lastLBA) && (other->lastLBA >= firstLBA))
theyDo = 1;
} // if
return (theyDo);
} // GPTPart::DoTheyOverlap()
// Reverse the bytes of integral data types; used on big-endian systems.
void GPTPart::ReversePartBytes(void) {
ReverseBytes(&partitionType.data1, 8);
ReverseBytes(&partitionType.data2, 8);
ReverseBytes(&uniqueGUID.data1, 8);
ReverseBytes(&uniqueGUID.data2, 8);
ReverseBytes(&firstLBA, 8);
ReverseBytes(&lastLBA, 8);
ReverseBytes(&attributes, 8);
} // GPTPart::ReverseBytes()
// Display summary information; does nothing if the partition is empty.
void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
string sizeInSI;
int i;
if (firstLBA != 0) {
sizeInSI = BytesToSI(blockSize * (lastLBA - firstLBA + 1));
cout.width(4);
cout << partNum + 1 << " ";
cout.width(14);
cout << firstLBA << " ";
cout.width(14);
cout << lastLBA << " ";
cout << BytesToSI(blockSize * (lastLBA - firstLBA + 1)) << " ";
for (i = 0; i < 9 - sizeInSI.length(); i++) cout << " ";
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
} // GPTPart::ShowSummary()
// Show detailed partition information. Does nothing if the partition is
// empty (as determined by firstLBA being 0).
void GPTPart::ShowDetails(uint32_t blockSize) {
uint64_t size;
if (firstLBA != 0) {
cout << "Partition GUID code: " << GUIDToStr(partitionType);
cout << " (" << typeHelper.GUIDToName(partitionType) << ")\n";
cout << "Partition unique GUID: " << GUIDToStr(uniqueGUID) << "\n";
cout << "First sector: " << firstLBA << " (at "
<< BytesToSI(firstLBA * blockSize) << ")\n";
cout << "Last sector: " << lastLBA << " (at "
<< BytesToSI(lastLBA * blockSize) << ")\n";
size = (lastLBA - firstLBA + 1);
cout << "Partition size: " << size << " sectors ("
<< BytesToSI(size * ((uint64_t) blockSize)) << ")\n";
cout << "Attribute flags: ";
cout.fill('0');
cout.width(16);
cout << right;
cout << hex;
cout << attributes << "\n";
cout << left;
cout << dec;
cout << "Partition name: " << GetName() << "\n";
} // if
} // GPTPart::ShowDetails()
/****************************************
* Functions requiring user interaction *
****************************************/
// Change the type code on the partition.
void GPTPart::ChangeType(void) {
char line[255];
char* junk;
int typeNum = 0xFFFF;
GUIDData newType;
cout << "Current type is '" << GetNameType() << "'\n";
while ((!typeHelper.Valid(typeNum)) && (typeNum != 0)) {
cout << "Hex code (L to show codes, 0 to enter raw code, Enter = 0700): ";
junk = fgets(line, 255, stdin);
sscanf(line, "%X", &typeNum);
if ((line[0] == 'L') || (line[0] == 'l'))
typeHelper.ShowTypes();
if (line[0] == '\n') {
typeNum = 0x0700;
} // if
} // while
if (typeNum != 0) // user entered a code, so convert it
newType = typeHelper.IDToGUID((uint16_t) typeNum);
else // user wants to enter the GUID directly, so do that
newType = GetGUID();
partitionType = newType;
cout << "Changed type of partition to '" << typeHelper.GUIDToName(partitionType) << "'\n";
} // 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 empty. Note that theName is a standard C++-style ASCII // 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(string theName) { void GPTPart::SetName(const string & theName) {
char newName[NAME_SIZE]; // New name char newName[NAME_SIZE]; // New name
char *junk; char *junk;
int i; int i;
@@ -256,6 +130,145 @@ void GPTPart::SetName(string theName) {
} // for } // for
} // GPTPart::SetName() } // GPTPart::SetName()
GPTPart & GPTPart::operator=(const GPTPart & orig) {
int i;
partitionType = orig.partitionType;
uniqueGUID = orig.uniqueGUID;
firstLBA = orig.firstLBA;
lastLBA = orig.lastLBA;
attributes = orig.attributes;
for (i = 0; i < NAME_SIZE; i++)
name[i] = orig.name[i];
return *this;
} // assignment operator
// Display summary information; does nothing if the partition is empty.
void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
string sizeInSI;
int i;
if (firstLBA != 0) {
sizeInSI = BytesToSI(blockSize * (lastLBA - firstLBA + 1));
cout.width(4);
cout << partNum + 1 << " ";
cout.width(14);
cout << firstLBA << " ";
cout.width(14);
cout << lastLBA << " ";
cout << BytesToSI(blockSize * (lastLBA - firstLBA + 1)) << " ";
for (i = 0; i < 9 - sizeInSI.length(); i++) cout << " ";
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
} // GPTPart::ShowSummary()
// Show detailed partition information. Does nothing if the partition is
// empty (as determined by firstLBA being 0).
void GPTPart::ShowDetails(uint32_t blockSize) {
uint64_t size;
if (firstLBA != 0) {
cout << "Partition GUID code: " << GUIDToStr(partitionType);
cout << " (" << typeHelper.GUIDToName(partitionType) << ")\n";
cout << "Partition unique GUID: " << GUIDToStr(uniqueGUID) << "\n";
cout << "First sector: " << firstLBA << " (at "
<< BytesToSI(firstLBA * blockSize) << ")\n";
cout << "Last sector: " << lastLBA << " (at "
<< BytesToSI(lastLBA * blockSize) << ")\n";
size = (lastLBA - firstLBA + 1);
cout << "Partition size: " << size << " sectors ("
<< BytesToSI(size * ((uint64_t) blockSize)) << ")\n";
cout << "Attribute flags: ";
cout.fill('0');
cout.width(16);
cout << hex;
cout << attributes << "\n";
cout << dec;
cout << "Partition name: " << GetName() << "\n";
cout.fill(' ');
} // if
} // GPTPart::ShowDetails()
// Blank (delete) a single partition
void GPTPart::BlankPartition(void) {
int j;
GUIDData zeroGUID;
zeroGUID.data1 = 0;
zeroGUID.data2 = 0;
uniqueGUID = zeroGUID;
partitionType = zeroGUID;
firstLBA = 0;
lastLBA = 0;
attributes = 0;
for (j = 0; j < NAME_SIZE; j++)
name[j] = '\0';
} // GPTPart::BlankPartition
// Returns 1 if the two partitions overlap, 0 if they don't
int GPTPart::DoTheyOverlap(const GPTPart & other) {
int theyDo = 0;
// Don't bother checking unless these are defined (both start and end points
// are 0 for undefined partitions, so just check the start points)
if ((firstLBA != 0) && (other.firstLBA != 0)) {
if ((firstLBA < other.lastLBA) && (lastLBA >= other.firstLBA))
theyDo = 1;
if ((other.firstLBA < lastLBA) && (other.lastLBA >= firstLBA))
theyDo = 1;
} // if
return (theyDo);
} // GPTPart::DoTheyOverlap()
// Reverse the bytes of integral data types; used on big-endian systems.
void GPTPart::ReversePartBytes(void) {
ReverseBytes(&partitionType.data1, 8);
ReverseBytes(&partitionType.data2, 8);
ReverseBytes(&uniqueGUID.data1, 8);
ReverseBytes(&uniqueGUID.data2, 8);
ReverseBytes(&firstLBA, 8);
ReverseBytes(&lastLBA, 8);
ReverseBytes(&attributes, 8);
} // GPTPart::ReverseBytes()
/****************************************
* Functions requiring user interaction *
****************************************/
// Change the type code on the partition.
void GPTPart::ChangeType(void) {
char line[255];
char* junk;
int typeNum = 0xFFFF;
GUIDData newType;
cout << "Current type is '" << GetNameType() << "'\n";
while ((!typeHelper.Valid(typeNum)) && (typeNum != 0)) {
cout << "Hex code (L to show codes, 0 to enter raw code, Enter = 0700): ";
junk = fgets(line, 255, stdin);
sscanf(line, "%X", &typeNum);
if ((line[0] == 'L') || (line[0] == 'l'))
typeHelper.ShowTypes();
if (line[0] == '\n') {
typeNum = 0x0700;
} // if
} // while
if (typeNum != 0) // user entered a code, so convert it
newType = typeHelper.IDToGUID((uint16_t) typeNum);
else // user wants to enter the GUID directly, so do that
newType = GetGUID();
SetType(newType);
cout << "Changed type of partition to '" << typeHelper.GUIDToName(partitionType) << "'\n";
} // GPTPart::ChangeType()
/*********************************** /***********************************
* Non-class but related functions * * Non-class but related functions *
***********************************/ ***********************************/

View File

@@ -62,21 +62,21 @@ class GPTPart {
string GetName(void); string GetName(void);
// Simple data assignment: // Simple data assignment:
void SetType(struct GUIDData t) {partitionType = t;} void SetType(struct GUIDData t);
void SetType(uint16_t hex) {partitionType = typeHelper.IDToGUID(hex);} void SetType(uint16_t hex) {SetType(typeHelper.IDToGUID(hex));}
void SetUniqueGUID(struct GUIDData u) {uniqueGUID = u;} void SetUniqueGUID(struct GUIDData u) {uniqueGUID = u;}
void SetUniqueGUID(int zeroOrRandom); void SetUniqueGUID(int zeroOrRandom);
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(string n); void SetName(const string & n);
// Additional functions // Additional functions
GPTPart & operator=(const GPTPart & orig); GPTPart & operator=(const GPTPart & orig);
void ShowSummary(int partNum, uint32_t blockSize); // display summary information (1-line) void ShowSummary(int partNum, uint32_t blockSize); // display summary information (1-line)
void ShowDetails(uint32_t blockSize); // display detailed information (multi-line) void ShowDetails(uint32_t blockSize); // display detailed information (multi-line)
void BlankPartition(void); // empty partition of data void BlankPartition(void); // empty partition of data
int DoTheyOverlap(GPTPart* other); // returns 1 if there's overlap int DoTheyOverlap(const GPTPart & other); // returns 1 if there's overlap
void ReversePartBytes(void); // reverse byte order of all integer fields void ReversePartBytes(void); // reverse byte order of all integer fields
// Functions requiring user interaction // Functions requiring user interaction

40
mbr.cc
View File

@@ -38,6 +38,7 @@ MBRData::MBRData(void) {
srand((unsigned int) time(NULL)); srand((unsigned int) time(NULL));
numHeads = MAX_HEADS; numHeads = MAX_HEADS;
numSecspTrack = MAX_SECSPERTRACK; numSecspTrack = MAX_SECSPERTRACK;
myDisk = NULL;
EmptyMBR(); EmptyMBR();
} // MBRData default constructor } // MBRData default constructor
@@ -48,6 +49,7 @@ MBRData::MBRData(string filename) {
state = invalid; state = invalid;
numHeads = MAX_HEADS; numHeads = MAX_HEADS;
numSecspTrack = MAX_SECSPERTRACK; numSecspTrack = MAX_SECSPERTRACK;
myDisk = NULL;
srand((unsigned int) time(NULL)); srand((unsigned int) time(NULL));
// Try to read the specified partition table, but if it fails.... // Try to read the specified partition table, but if it fails....
@@ -55,9 +57,10 @@ MBRData::MBRData(string filename) {
EmptyMBR(); EmptyMBR();
device = ""; device = "";
} // if } // if
} // MBRData(char *filename) constructor } // MBRData(string filename) constructor
MBRData::~MBRData(void) { MBRData::~MBRData(void) {
// delete myDisk;
} // MBRData destructor } // MBRData destructor
/********************** /**********************
@@ -68,9 +71,11 @@ 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(string deviceFilename) { int MBRData::ReadMBRData(const string & deviceFilename) {
int fd, allOK = 1; int fd, allOK = 1;
if (myDisk == NULL)
myDisk = new DiskIO;
if (myDisk->OpenForRead(deviceFilename)) { if (myDisk->OpenForRead(deviceFilename)) {
ReadMBRData(myDisk); ReadMBRData(myDisk);
} else { } else {
@@ -81,7 +86,7 @@ int MBRData::ReadMBRData(string deviceFilename) {
device = deviceFilename; device = deviceFilename;
return allOK; return allOK;
} // MBRData::ReadMBRData(char* deviceFilename) } // MBRData::ReadMBRData(const string & deviceFilename)
// Read data from MBR. If checkBlockSize == 1 (the default), the block // Read data from MBR. If checkBlockSize == 1 (the default), the block
// size is checked; otherwise it's set to the default (512 bytes). // size is checked; otherwise it's set to the default (512 bytes).
@@ -93,6 +98,9 @@ void MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
int err = 1; int err = 1;
TempMBR tempMBR; TempMBR tempMBR;
if (myDisk != NULL)
delete myDisk;
myDisk = theDisk; myDisk = theDisk;
// Empty existing MBR data, including the logical partitions... // Empty existing MBR data, including the logical partitions...
@@ -102,7 +110,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) {
cerr << "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];
@@ -183,7 +191,7 @@ void MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
} // for } // for
} // if (hybrid detection code) } // if (hybrid detection code)
} // no initial error } // no initial error
} // MBRData::ReadMBRData(int fd) } // MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize)
// This is a recursive function to read all the logical partitions, following the // This is a recursive function to read all the logical partitions, following the
// logical partition linked list from the disk and storing the basic data in the // logical partition linked list from the disk and storing the basic data in the
@@ -252,14 +260,16 @@ int MBRData::ReadLogicalPart(uint32_t extendedStart,
// Write the MBR data to the default defined device. Note that this writes // Write the MBR data to the default defined device. Note that this writes
// ONLY the MBR itself, not the logical partition data. // ONLY the MBR itself, not the logical partition data.
int MBRData::WriteMBRData(void) { int MBRData::WriteMBRData(void) {
int allOK = 1, fd; int allOK = 1;
if (myDisk->OpenForWrite(device) != 0) { if (myDisk != NULL) {
allOK = WriteMBRData(myDisk); if (myDisk->OpenForWrite(device) != 0) {
} else { allOK = WriteMBRData(myDisk);
allOK = 0; } else {
} // if/else allOK = 0;
myDisk->Close(); } // if/else
myDisk->Close();
} else allOK = 0;
return allOK; return allOK;
} // MBRData::WriteMBRData(void) } // MBRData::WriteMBRData(void)
@@ -322,12 +332,12 @@ int MBRData::WriteMBRData(DiskIO *theDisk) {
} // for } // for
}// if }// if
return allOK; return allOK;
} // MBRData::WriteMBRData(DiskIO theDisk) } // MBRData::WriteMBRData(DiskIO *theDisk)
int MBRData::WriteMBRData(string deviceFilename) { int MBRData::WriteMBRData(const string & deviceFilename) {
device = deviceFilename; device = deviceFilename;
return WriteMBRData(); return WriteMBRData();
} // MBRData::WriteMBRData(char* deviceFilename) } // MBRData::WriteMBRData(const string & deviceFilename)
/******************************************** /********************************************
* * * *

4
mbr.h
View File

@@ -80,7 +80,7 @@ public:
~MBRData(void); ~MBRData(void);
// File I/O functions... // File I/O functions...
int ReadMBRData(string deviceFilename); int ReadMBRData(const 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(string deviceFilename); int WriteMBRData(const string & deviceFilename);
// Display data for user... // Display data for user...
void DisplayMBRData(void); void DisplayMBRData(void);

View File

@@ -236,6 +236,7 @@ int PartTypes::AddType(uint16_t mbrType, uint64_t guidData1, uint64_t guidData2,
// in an ugly way. // in an ugly way.
void PartTypes::ShowTypes(void) { void PartTypes::ShowTypes(void) {
int colCount = 1; // column count int colCount = 1; // column count
int i;
AType* thisType = allTypes; AType* thisType = allTypes;
cout.unsetf(ios::uppercase); cout.unsetf(ios::uppercase);
@@ -244,17 +245,16 @@ void PartTypes::ShowTypes(void) {
cout.fill('0'); cout.fill('0');
cout.width(4); cout.width(4);
cout << hex << thisType->MBRType << " "; cout << hex << thisType->MBRType << " ";
cout.fill(' ');
cout.setf(ios::left);
cout.width(19);
cout << ((string) thisType->name).substr(0, 19) << " "; cout << ((string) thisType->name).substr(0, 19) << " ";
for (i = 0; i < (19 - ((string) thisType->name).substr(0, 19).length()); i ++) cout << " ";
if ((colCount % 3) == 0) if ((colCount % 3) == 0)
cout << "\n"; cout << "\n";
colCount++; colCount++;
} // if } // if
thisType = thisType->next; thisType = thisType->next;
} // while } // while
cout << "\n"; cout.fill(' ');
cout << "\n" << dec;
} // 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
@@ -323,6 +323,7 @@ struct GUIDData PartTypes::IDToGUID(uint16_t ID) {
cout << "Exact type match not found for type code "; cout << "Exact type match not found for type code ";
cout.width(4); cout.width(4);
cout << hex << ID << "; assigning type code for\n'Linux/Windows data'\n" << dec; cout << hex << ID << "; assigning type code for\n'Linux/Windows data'\n" << dec;
cout.fill(' ');
} // if (!found) } // if (!found)
return theGUID; return theGUID;
} // PartTypes::IDToGUID() } // PartTypes::IDToGUID()