summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG27
-rw-r--r--Makefile9
-rw-r--r--Makefile.mingw9
-rw-r--r--README35
-rw-r--r--README.Windows9
-rw-r--r--attributes.cc2
-rw-r--r--bsd.cc4
-rw-r--r--gdisk.82
-rw-r--r--gdisk.cc12
-rw-r--r--gpt.cc118
-rw-r--r--gpt.h5
-rw-r--r--gptpart.cc93
-rw-r--r--gptpart.h24
-rw-r--r--mbr.cc20
-rw-r--r--mbr.h1
-rw-r--r--parttypes.cc445
-rw-r--r--parttypes.h36
-rw-r--r--sgdisk.82
-rw-r--r--sgdisk.cc4
-rw-r--r--support.cc117
-rw-r--r--support.h16
21 files changed, 468 insertions, 522 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 6768c46..7139adb 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,30 @@
+0.6.3 (2/3/2010):
+------------------
+
+- Fixed serious data corruption bug on big-endian (PowerPC and similar)
+ systems.
+
+- Changed several GPT fdisk Solaris type codes to correct a duplicate
+
+- Corrected error in GPT fdisk type codes for NetBSD LFS and NetBSD RAID;
+ they were identical, but I've now changed NetBSD RAID to A906, which
+ is unique.
+
+- Added GUID for IBM General Parallel File System (GPFS) partition type
+ code. Somewhat arbitrarily set it to use the 7501 number (MBR code 0x75
+ is used by IBM PC/IX, so it's at least the right company, by my loose
+ numbering rules....).
+
+- Improved GUID generation. Prior versions generated completely random
+ numbers for GUIDs. This works, but is technically a violation of the
+ spec. Unix versions now employ libuuid to generate GUIDs in a more
+ correct way. The Windows version still generates random numbers, though.
+
+- Turned PartTypes class into a derived class of GUIDData, and renamed
+ it to PartType.
+
+- Created new GUIDData class, to replace the original GUIDData struct.
+
0.6.2 (1/29/2010):
------------------
diff --git a/Makefile b/Makefile
index 83381ed..8e14b07 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ CC=gcc
CXX=g++
CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g
CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
-LIB_NAMES=crc32 support gptpart mbr gpt bsd parttypes attributes diskio diskio-unix
+LIB_NAMES=crc32 support guid gptpart mbr gpt bsd parttypes attributes diskio diskio-unix
LIB_SRCS=$(NAMES:=.cc)
LIB_OBJS=$(LIB_NAMES:=.o)
LIB_HEADERS=$(LIB_NAMES:=.h)
@@ -11,10 +11,13 @@ DEPEND= makedepend $(CFLAGS)
all: gdisk sgdisk
gdisk: $(LIB_OBJS) gdisk.o
- $(CXX) $(LIB_OBJS) gdisk.o -o gdisk
+ $(CXX) $(LIB_OBJS) gdisk.o -L/opt/local/lib -L/usr/local/lib -luuid -o gdisk
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 -luuid -lpopt -o sgdisk
+
+testguid: $(LIB_OBJS) testguid.o
+ $(CXX) $(LIB_OBJS) testguid.o -o testguid
lint: #no pre-reqs
lint $(SRCS)
diff --git a/Makefile.mingw b/Makefile.mingw
index 1a59f2d..96ef8a0 100644
--- a/Makefile.mingw
+++ b/Makefile.mingw
@@ -2,8 +2,9 @@ CC=/usr/bin/i586-mingw32msvc-gcc
CXX=/usr/bin/i586-mingw32msvc-g++
STRIP=/usr/bin/i586-mingw32msvc-strip
CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g
-CXXFLAGS=-O2 -Wall -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
+CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -g
+#CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
+LIB_NAMES=guid gptpart bsd parttypes attributes crc32 mbr gpt support diskio diskio-windows
LIB_SRCS=$(NAMES:=.cc)
LIB_OBJS=$(LIB_NAMES:=.o)
LIB_HEADERS=$(LIB_NAMES:=.h)
@@ -12,10 +13,10 @@ DEPEND= makedepend $(CFLAGS)
all: gdisk
gdisk: $(LIB_OBJS) gdisk.o
- $(CXX) $(LIB_OBJS) gdisk.o -o gdisk.exe
+ $(CXX) $(LIB_OBJS) gdisk.o -luuid -o gdisk.exe
sgdisk: $(LIB_OBJS) sgdisk.o
- $(CXX) $(LIB_OBJS) sgdisk.o -L/opt/local/lib -L/usr/local/lib -lpopt -o sgdisk.exe
+ $(CXX) $(LIB_OBJS) sgdisk.o -lpopt -o sgdisk.exe
lint: #no pre-reqs
lint $(SRCS)
diff --git a/README b/README
index cfca4fa..9bf133c 100644
--- a/README
+++ b/README
@@ -50,22 +50,31 @@ Installing
To compile GPT fdisk, you must have appropriate development tools
installed, most notably the GNU Compiler Collection (GCC) and its g++
-compiler for C++. The sgdisk program also requires the popt library and its
-development files (headers). Most Linux distributions install popt by
-default, but you may need to install a package called popt-dev, popt-devel,
-or something similar to obtain the header files. Mac OS users can find a
-version of popt for Mac OS from http://popt.darwinports.com; however,
-you'll first need to install DarwinPorts (instructions exist on the
-preceding page). Alternatively, you can compile gdisk alone, without
-sgdisk; gdisk doesn't require popt.
+compiler for C++. In addition, note these requirements:
+
+* On Linux, FreeBSD, and OS X, libuuid must be installed. This is the
+ standard for Linux and OS X, although you may need to install a package
+ called uuid-dev or something similar to get the headers. On FreeBSD, the
+ e2fsprogs-libuuid port must be installed.
+
+* The sgdisk program also requires the popt library and its development
+ files (headers). Most Linux distributions install popt by default, but
+ you may need to install a package called popt-dev, popt-devel, or
+ something similar to obtain the header files. Mac OS users can find a
+ version of popt for Mac OS from http://popt.darwinports.com; however,
+ you'll first need to install DarwinPorts (instructions exist on the
+ preceding page). Alternatively, you can compile gdisk alone, without
+ sgdisk; gdisk doesn't require popt.
When all the necessary development tools and libraries are installed, you
can uncompress the package and type "make" at the command prompt in the
-resulting directory. The result should be program files called gdisk and
-sgdisk. Typing "make gdisk" or "make sgdisk" will compile only the requested
-programs. You can use these programs in place or copy the files to a
-suitable directory, such as /usr/local/sbin. You can copy the man pages
-(gdisk.8 and sgdisk.8) to /usr/local/man/man8 to make them available.
+resulting directory. (You may need to type "make -f Makefile.mac" on Mac OS
+X or "make -f Makefile.mingw" to compile using MinGW for Windows.) The
+result should be program files called gdisk and sgdisk. Typing "make gdisk"
+or "make sgdisk" will compile only the requested programs. You can use
+these programs in place or copy the files to a suitable directory, such as
+/usr/local/sbin. You can copy the man pages (gdisk.8 and sgdisk.8) to
+/usr/local/man/man8 to make them available.
Caveats
-------
diff --git a/README.Windows b/README.Windows
index a88d29d..91074c4 100644
--- a/README.Windows
+++ b/README.Windows
@@ -70,6 +70,15 @@ support of GPT, see Microsoft's Web page on the topic:
http://www.microsoft.com/whdc/device/storage/GPT_FAQ.mspx
+The GUIDs generated by the program to uniquely identify disks and
+partitions aren't "proper" GUIDs; they're purely random numbers. In
+practice, this has caused me no problems; however, it's conceivable that
+some disk utility will complain. The Unix versions of GPT fdisk generate
+proper GUIDs, as of version 0.6.3. Note that this limitation applies ONLY
+to the unique GUIDs for disks and partitions, not to the GUIDs used to
+identify partition type codes; those are standardized and are handled
+correctly by all versions of GPT fdisk.
+
Source Code and Compilation Issues
----------------------------------
diff --git a/attributes.cc b/attributes.cc
index 9bdd428..b0800fa 100644
--- a/attributes.cc
+++ b/attributes.cc
@@ -30,7 +30,7 @@ Attributes::Attributes(void) {
} // for
// Now reset those names that are defined....
- atNames[0] = "system partition";
+ atNames[0] = "system partition"; // required for computer to operate
atNames[60] = "read-only";
atNames[62] = "hidden";
atNames[63] = "do not automount";
diff --git a/bsd.cc b/bsd.cc
index 75dca60..f1d1ade 100644
--- a/bsd.cc
+++ b/bsd.cc
@@ -291,7 +291,7 @@ GPTPart BSDData::AsGPT(int i) {
guid.SetFirstLBA(sectorOne);
guid.SetLastLBA(sectorEnd);
// Now set a random unique GUID for the partition....
- guid.SetUniqueGUID(1);
+ guid.RandomizeUniqueGUID();
// ... zero out the attributes and name fields....
guid.SetAttributes(UINT64_C(0));
// Most BSD disklabel type codes seem to be archaic or rare.
@@ -321,7 +321,7 @@ GPTPart BSDData::AsGPT(int i) {
guid.SetType(0x0700); break;
} // switch
// Set the partition name to the name of the type code....
- guid.SetName(guid.GetNameType());
+ guid.SetName(guid.GetTypeName());
} // if
return guid;
} // BSDData::AsGPT()
diff --git a/gdisk.8 b/gdisk.8
index dad9265..3a683c7 100644
--- a/gdisk.8
+++ b/gdisk.8
@@ -1,6 +1,6 @@
.\" Copyright 2009 Roderick W. Smith (rodsmith@rodsbooks.com)
.\" 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.6.3" "Roderick W. Smith" "GPT fdisk Manual"
.SH "NAME"
gdisk \- Interactive GUID partition table (GPT) manipulator
.SH "SYNOPSIS"
diff --git a/gdisk.cc b/gdisk.cc
index 3dddc9e..5a2c905 100644
--- a/gdisk.cc
+++ b/gdisk.cc
@@ -29,6 +29,7 @@ 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";
@@ -76,7 +77,7 @@ void MainMenu(string filename, struct GPTData* theGPT) {
char command, line[255], buFile[255];
char* junk;
int goOn = 1;
- PartTypes typeHelper;
+ PartType typeHelper;
uint32_t temp1, temp2;
do {
@@ -105,7 +106,7 @@ void MainMenu(string filename, struct GPTData* theGPT) {
theGPT->ShowDetails();
break;
case 'l': case 'L':
- typeHelper.ShowTypes();
+ typeHelper.ShowAllTypes();
break;
case 'n': case 'N':
theGPT->CreatePartition();
@@ -177,7 +178,6 @@ void ShowCommands(void) {
void RecoveryMenu(string filename, struct GPTData* theGPT) {
char command, line[255], buFile[255];
char* junk;
- PartTypes typeHelper;
uint32_t temp1;
int goOn = 1;
@@ -303,10 +303,10 @@ void ShowRecoveryCommands(void) {
void ExpertsMenu(string filename, struct GPTData* theGPT) {
char command, line[255];
char* junk;
- PartTypes typeHelper;
uint32_t pn;
uint32_t temp1, temp2;
int goOn = 1;
+ GUIDData aGUID;
do {
cout << "\nExpert command (? for help): ";
@@ -325,7 +325,7 @@ void ExpertsMenu(string filename, struct GPTData* theGPT) {
if (theGPT->GetPartRange(&temp1, &temp2) > 0) {
pn = theGPT->GetPartNum();
cout << "Enter the partition's new unique GUID:\n";
- theGPT->SetPartitionGUID(pn, GetGUID());
+ theGPT->SetPartitionGUID(pn, aGUID.GetGUIDFromUser());
} else cout << "No partitions\n";
break;
case 'd': case 'D':
@@ -338,7 +338,7 @@ void ExpertsMenu(string filename, struct GPTData* theGPT) {
break;
case 'g': case 'G':
cout << "Enter the disk's unique GUID:\n";
- theGPT->SetDiskGUID(GetGUID());
+ theGPT->SetDiskGUID(aGUID.GetGUIDFromUser());
break;
case 'i': case 'I':
theGPT->ShowDetails();
diff --git a/gpt.cc b/gpt.cc
index 9bb6763..562a085 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -173,12 +173,11 @@ int GPTData::Verify(void) {
<< secondHeader.lastUsableLBA << ")\n"
<< "The 'e' option on the experts' menu can probably fix this problem.\n";
} // if
- if ((mainHeader.diskGUID.data1 != secondHeader.diskGUID.data1) ||
- (mainHeader.diskGUID.data2 != secondHeader.diskGUID.data2)) {
+ if ((mainHeader.diskGUID != secondHeader.diskGUID)) {
problems++;
- cout << "\nProblem: main header's disk GUID (" << GUIDToStr(mainHeader.diskGUID)
+ cout << "\nProblem: main header's disk GUID (" << mainHeader.diskGUID.AsString()
<< ") doesn't\nmatch the backup GPT header's disk GUID ("
- << GUIDToStr(secondHeader.diskGUID) << ")\n"
+ << secondHeader.diskGUID.AsString() << ")\n"
<< "You should use the 'b' or 'd' option on the recovery & transformation menu to\n"
<< "select one or the other header.\n";
} // if
@@ -368,8 +367,9 @@ int GPTData::CheckHeaderCRC(struct GPTHeader* header) {
return (oldCRC == newCRC);
} // GPTData::CheckHeaderCRC()
-// Recompute all the CRCs. Must be called before saving (but after reversing
-// byte order on big-endian systems) if any changes have been made.
+// Recompute all the CRCs. Must be called before saving if any changes have
+// been made. Must be called on platform-ordered data (this function reverses
+// byte order and then undoes that reversal.)
void GPTData::RecomputeCRCs(void) {
uint32_t crc, hSize, trueNumParts;
int littleEndian = 1;
@@ -377,13 +377,21 @@ void GPTData::RecomputeCRCs(void) {
// Initialize CRC functions...
chksum_crc32gentab();
+ // Save some key data from header before reversing byte order....
+ trueNumParts = mainHeader.numParts;
hSize = mainHeader.headerSize;
- littleEndian = IsLittleEndian();
+
+ if ((littleEndian = IsLittleEndian()) == 0) {
+ ReversePartitionBytes();
+ ReverseHeaderBytes(&mainHeader);
+ ReverseHeaderBytes(&secondHeader);
+ } // if
+/* if ((littleEndian = IsLittleEndian()) == 0) {
+ ReverseBytes(&trueNumParts, 4);
+ ReverseBytes(&hSize, 4);
+ } // if */
// Compute CRC of partition tables & store in main and secondary headers
- trueNumParts = mainHeader.numParts;
- if (littleEndian == 0)
- ReverseBytes(&trueNumParts, 4); // unreverse this key piece of data....
crc = chksum_crc32((unsigned char*) partitions, trueNumParts * GPT_SIZE);
mainHeader.partitionEntriesCRC = crc;
secondHeader.partitionEntriesCRC = crc;
@@ -405,6 +413,12 @@ void GPTData::RecomputeCRCs(void) {
if (littleEndian == 0)
ReverseBytes(&crc, 4);
secondHeader.headerCRC = crc;
+
+ if ((littleEndian = IsLittleEndian()) == 0) {
+ ReverseHeaderBytes(&mainHeader);
+ ReverseHeaderBytes(&secondHeader);
+ ReversePartitionBytes();
+ } // if
} // GPTData::RecomputeCRCs()
// Rebuild the main GPT header, using the secondary header as a model.
@@ -421,8 +435,7 @@ void GPTData::RebuildMainHeader(void) {
mainHeader.backupLBA = secondHeader.currentLBA;
mainHeader.firstUsableLBA = secondHeader.firstUsableLBA;
mainHeader.lastUsableLBA = secondHeader.lastUsableLBA;
- mainHeader.diskGUID.data1 = secondHeader.diskGUID.data1;
- mainHeader.diskGUID.data2 = secondHeader.diskGUID.data2;
+ mainHeader.diskGUID = secondHeader.diskGUID;
mainHeader.partitionEntriesLBA = UINT64_C(2);
mainHeader.numParts = secondHeader.numParts;
mainHeader.sizeOfPartitionEntries = secondHeader.sizeOfPartitionEntries;
@@ -445,8 +458,7 @@ void GPTData::RebuildSecondHeader(void) {
secondHeader.backupLBA = mainHeader.currentLBA;
secondHeader.firstUsableLBA = mainHeader.firstUsableLBA;
secondHeader.lastUsableLBA = mainHeader.lastUsableLBA;
- secondHeader.diskGUID.data1 = mainHeader.diskGUID.data1;
- secondHeader.diskGUID.data2 = mainHeader.diskGUID.data2;
+ secondHeader.diskGUID = mainHeader.diskGUID;
secondHeader.partitionEntriesLBA = secondHeader.lastUsableLBA + UINT64_C(1);
secondHeader.numParts = mainHeader.numParts;
secondHeader.sizeOfPartitionEntries = mainHeader.sizeOfPartitionEntries;
@@ -836,12 +848,14 @@ int GPTData::LoadSecondTableAsMain(void) {
// 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;
+ int allOK = 1, littleEndian;
char answer;
uint64_t secondTable;
uint32_t numParts;
uint64_t offset;
+ littleEndian = IsLittleEndian();
+
if (device == "") {
cerr << "Device not defined.\n";
} // if
@@ -894,14 +908,17 @@ int GPTData::SaveGPTData(int quiet) {
// big-endian systems....
numParts = mainHeader.numParts;
secondTable = secondHeader.partitionEntriesLBA;
- if (IsLittleEndian() == 0) {
+/* if (IsLittleEndian() == 0) {
// Reverse partition bytes first, since that function requires non-reversed
// data from the main header....
ReversePartitionBytes();
ReverseHeaderBytes(&mainHeader);
ReverseHeaderBytes(&secondHeader);
- } // if
+ } // if */
RecomputeCRCs();
+/* ReverseHeaderBytes(&mainHeader);
+ ReverseHeaderBytes(&secondHeader);
+ ReversePartitionBytes(); */
if ((allOK) && (!quiet)) {
cout << "\nFinal checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING\n"
@@ -922,16 +939,24 @@ 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()...)
// 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()...)
} // if (allOK)
@@ -947,18 +972,26 @@ int GPTData::SaveGPTData(int quiet) {
// Now write the secondary partition tables....
if (allOK) {
+ if (!littleEndian)
+ ReversePartitionBytes();
if (myDisk.Write(partitions, GPT_SIZE * numParts) == -1)
allOK = 0;
- } // if (allOK)
+ if (!littleEndian)
+ ReversePartitionBytes();
+ } // if (allOK)
// Now write the secondary GPT header...
if (allOK) {
offset = mainHeader.backupLBA;
- if (myDisk.Seek(offset)) {
+ if (!littleEndian)
+ ReverseHeaderBytes(&secondHeader);
+ if (myDisk.Seek(offset)) {
if (myDisk.Write(&secondHeader, 512) == -1)
allOK = 0;
} else allOK = 0; // if (myDisk.Seek()...)
- } // if (allOK)
+ if (!littleEndian)
+ ReverseHeaderBytes(&secondHeader);
+ } // if (allOK)
// re-read the partition table
if (allOK) {
@@ -982,13 +1015,13 @@ int GPTData::SaveGPTData(int quiet) {
cout << "Aborting write of new partition table.\n";
} // if
- if (IsLittleEndian() == 0) {
+/* if (IsLittleEndian() == 0) {
// Reverse (normalize) header bytes first, since ReversePartitionBytes()
// requires non-reversed data in mainHeader...
ReverseHeaderBytes(&mainHeader);
ReverseHeaderBytes(&secondHeader);
ReversePartitionBytes();
- } // if
+ } // if */
return (allOK);
} // GPTData::SaveGPTData()
@@ -1005,6 +1038,12 @@ int GPTData::SaveGPTBackup(const string & filename) {
DiskIO backupFile;
if (backupFile.OpenForWrite(filename)) {
+ // Recomputing the CRCs is likely to alter them, which could be bad
+ // if the intent is to save a potentially bad GPT for later analysis;
+ // but if we don't do this, we get bogus errors when we load the
+ // backup. I'm favoring misses over false alarms....
+ RecomputeCRCs();
+
// Reverse the byte order, if necessary....
numParts = mainHeader.numParts;
if (IsLittleEndian() == 0) {
@@ -1013,12 +1052,6 @@ int GPTData::SaveGPTBackup(const string & filename) {
ReverseHeaderBytes(&secondHeader);
} // if
- // Recomputing the CRCs is likely to alter them, which could be bad
- // if the intent is to save a potentially bad GPT for later analysis;
- // but if we don't do this, we get bogus errors when we load the
- // backup. I'm favoring misses over false alarms....
- RecomputeCRCs();
-
// Now write the protective MBR...
protectiveMBR.WriteMBRData(&backupFile);
@@ -1191,7 +1224,7 @@ void GPTData::DisplayGPTData(void) {
cout << "Disk " << device << ": " << diskSize << " sectors, "
<< BytesToSI(diskSize * blockSize) << "\n";
cout << "Logical sector size: " << blockSize << " bytes\n";
- cout << "Disk identifier (GUID): " << GUIDToStr(mainHeader.diskGUID) << "\n";
+ cout << "Disk identifier (GUID): " << mainHeader.diskGUID.AsString() << "\n";
cout << "Partition table holds up to " << mainHeader.numParts << " entries\n";
cout << "First usable sector is " << mainHeader.firstUsableLBA
<< ", last usable sector is " << mainHeader.lastUsableLBA << "\n";
@@ -1320,7 +1353,7 @@ void GPTData::CreatePartition(void) {
firstFreePart = CreatePartition(partNum, firstBlock, lastBlock);
partitions[partNum].ChangeType();
- partitions[partNum].SetName(partitions[partNum].GetNameType());
+ partitions[partNum].SetDefaultDescription();
} else {
cout << "No free sectors available\n";
} // if/else
@@ -1551,7 +1584,6 @@ WhichToUse GPTData::UseWhichPartitions(void) {
int GPTData::XFormPartitions(void) {
int i, numToConvert;
uint8_t origType;
- struct newGUID;
// Clear out old data & prepare basics....
ClearGPTData();
@@ -1567,7 +1599,7 @@ int GPTData::XFormPartitions(void) {
// don't waste CPU time trying to convert extended, hybrid protective, or
// null (non-existent) partitions
if ((origType != 0x05) && (origType != 0x0f) && (origType != 0x85) &&
- (origType != 0x00) && (origType != 0xEE))
+ (origType != 0x00) && (origType != 0xEE))
partitions[i] = protectiveMBR.AsGPT(i);
} // for
@@ -1583,6 +1615,7 @@ int GPTData::XFormPartitions(void) {
// Transforms BSD disklabel on the specified partition (numbered from 0).
// If an invalid partition number is given, the program prompts for one.
+// (Default for i is -1; called without an option, it therefore prompts.)
// Returns the number of new partitions created.
int GPTData::XFormDisklabel(int i) {
uint32_t low, high, partNum, startPart;
@@ -1635,7 +1668,7 @@ int GPTData::XFormDisklabel(BSDData* disklabel, uint32_t startPart) {
int i, numDone = 0;
if ((disklabel->IsDisklabel()) && (startPart >= 0) &&
- (startPart < mainHeader.numParts)) {
+ (startPart < mainHeader.numParts)) {
for (i = 0; i < disklabel->GetNumParts(); i++) {
partitions[i + startPart] = disklabel->AsGPT(i);
if (partitions[i + startPart].GetFirstLBA() != UINT64_C(0))
@@ -1682,7 +1715,7 @@ int GPTData::OnePartToMBR(uint32_t gptPart, int mbrPart) {
do {
cout << "Enter an MBR hex code (default " << hex;
cout.width(2);
- cout << typeHelper.GUIDToID(partitions[gptPart].GetType()) / 256 << "): ";
+ cout << partitions[gptPart].GetHexType() / 0x0100 << "): ";
junk = fgets(line, 255, stdin);
if (line[0] == '\n')
typeCode = partitions[gptPart].GetHexType() / 256;
@@ -1948,7 +1981,7 @@ uint32_t GPTData::CreatePartition(uint32_t partNum, uint64_t startSector, uint64
partitions[partNum].SetFirstLBA(startSector);
partitions[partNum].SetLastLBA(endSector);
partitions[partNum].SetType(0x0700);
- partitions[partNum].SetUniqueGUID(1);
+ partitions[partNum].RandomizeUniqueGUID();
} else retval = 0; // if free space until endSector
} else retval = 0; // if startSector is free
} else retval = 0; // if legal partition number
@@ -2021,9 +2054,7 @@ int GPTData::ClearGPTData(void) {
mainHeader.lastUsableLBA = diskSize - mainHeader.firstUsableLBA;
// Set a unique GUID for the disk, based on random numbers
- // rand() is only 32 bits, so multiply together to fill a 64-bit value
- mainHeader.diskGUID.data1 = (uint64_t) rand() * (uint64_t) rand();
- mainHeader.diskGUID.data2 = (uint64_t) rand() * (uint64_t) rand();
+ mainHeader.diskGUID.Randomize();
// Copy main header to backup header
RebuildSecondHeader();
@@ -2392,8 +2423,7 @@ void GPTData::ReverseHeaderBytes(struct GPTHeader* header) {
ReverseBytes(&header->sizeOfPartitionEntries, 4);
ReverseBytes(&header->partitionEntriesCRC, 4);
ReverseBytes(&header->reserved2, GPT_RESERVED);
- ReverseBytes(&header->diskGUID.data1, 8);
- ReverseBytes(&header->diskGUID.data2, 8);
+// header->diskGUID.ReverseGUIDBytes();
} // GPTData::ReverseHeaderBytes()
// IMPORTANT NOTE: This function requires non-reversed mainHeader
@@ -2458,6 +2488,14 @@ int SizesOK(void) {
cerr << "GPTPart is " << sizeof(GPTPart) << " bytes, should be 128 bytes; aborting!\n";
allOK = 0;
} // if
+ if (sizeof(GUIDData) != 16) {
+ cerr << "GUIDData is " << sizeof(GUIDData) << " bytes, should be 16 bytes; aborting!\n";
+ allOK = 0;
+ } // if
+ if (sizeof(PartType) != 16) {
+ cerr << "PartType is " << sizeof(GUIDData) << " bytes, should be 16 bytes; aborting!\n";
+ allOK = 0;
+ } // if
// Determine endianness; warn user if running on big-endian (PowerPC, etc.) hardware
if (IsLittleEndian() == 0) {
cerr << "\aRunning on big-endian hardware. Big-endian support is new and poorly"
diff --git a/gpt.h b/gpt.h
index ca04ec4..f122570 100644
--- a/gpt.h
+++ b/gpt.h
@@ -16,7 +16,7 @@
#ifndef __GPTSTRUCTS
#define __GPTSTRUCTS
-#define GPTFDISK_VERSION "0.6.2"
+#define GPTFDISK_VERSION "0.6.3"
using namespace std;
@@ -44,7 +44,7 @@ struct GPTHeader {
uint64_t backupLBA;
uint64_t firstUsableLBA;
uint64_t lastUsableLBA;
- struct GUIDData diskGUID;
+ GUIDData diskGUID;
uint64_t partitionEntriesLBA;
uint32_t numParts;
uint32_t sizeOfPartitionEntries;
@@ -72,7 +72,6 @@ protected:
int apmFound; // set to 1 if APM detected
int bsdFound; // set to 1 if BSD disklabel detected in MBR
int sectorAlignment; // Start & end partitions at multiples of sectorAlignment
- PartTypes typeHelper;
int beQuiet;
WhichToUse whichWasUsed;
public:
diff --git a/gptpart.cc b/gptpart.cc
index 40c426c..1cba0a0 100644
--- a/gptpart.cc
+++ b/gptpart.cc
@@ -23,8 +23,6 @@
using namespace std;
-PartTypes GPTPart::typeHelper;
-
GPTPart::GPTPart(void) {
int i;
@@ -37,13 +35,13 @@ GPTPart::~GPTPart(void) {
// Return the gdisk-specific two-byte hex code for the partition
uint16_t GPTPart::GetHexType(void) {
- return typeHelper.GUIDToID(partitionType);
+ return partitionType.GetHexType();
} // GPTPart::GetHexType()
// Return a plain-text description of the partition type (e.g., "Linux/Windows
// data" or "Linux swap").
-string GPTPart::GetNameType(void) {
- return typeHelper.GUIDToName(partitionType);
+string GPTPart::GetTypeName(void) {
+ return partitionType.TypeName();
} // GPTPart::GetNameType()
// Compute and return the partition's length (or 0 if the end is incorrectly
@@ -56,7 +54,7 @@ uint64_t GPTPart::GetLengthLBA(void) {
} // GPTPart::GetLengthLBA()
// Return partition's name field, converted to a C++ ASCII string
-string GPTPart::GetName(void) {
+string GPTPart::GetDescription(void) {
string theName;
int i;
@@ -66,32 +64,18 @@ string GPTPart::GetName(void) {
theName += name[i];
} // for
return theName;
-} // GPTPart::GetName()
+} // GPTPart::GetDescription()
// 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) {
- if (GetName() == typeHelper.GUIDToName(partitionType)) {
- SetName(typeHelper.GUIDToName(t));
+void GPTPart::SetType(PartType t) {
+ if (GetDescription() == partitionType.TypeName()) {
+ SetName(t.TypeName());
} // if
partitionType = t;
} // GPTPart::SetType()
-// Sets the unique GUID to a value of 0 or a random value,
-// depending on the parameter: 0 = 0, anything else = random
-void GPTPart::SetUniqueGUID(int zeroOrRandom) {
- if (zeroOrRandom == 0) {
- uniqueGUID.data1 = 0;
- uniqueGUID.data2 = 0;
- } else {
- // rand() is only 32 bits on 32-bit systems, so multiply together to
- // fill a 64-bit value.
- uniqueGUID.data1 = (uint64_t) rand() * (uint64_t) rand();
- uniqueGUID.data2 = (uint64_t) rand() * (uint64_t) rand();
- }
-} // GPTPart::SetUniqueGUID()
-
// 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
// string, although the GUID partition definition requires a UTF-16LE
@@ -111,8 +95,9 @@ void GPTPart::SetName(const string & theName) {
// Input is likely to include a newline, so remove it....
i = strlen(newName);
- if (newName[i - 1] == '\n')
- newName[i - 1] = '\0';
+ if ((i > 0) && (i <= NAME_SIZE))
+ if (newName[i - 1] == '\n')
+ newName[i - 1] = '\0';
} else {
strcpy(newName, theName.substr(0, NAME_SIZE / 2).c_str());
} // if
@@ -128,6 +113,12 @@ void GPTPart::SetName(const string & theName) {
} // for
} // GPTPart::SetName()
+// Set the name for the partition based on the current GUID partition type
+// code's associated name
+void GPTPart::SetDefaultDescription(void) {
+ SetName(partitionType.TypeName());
+} // GPTPart::SetDefaultDescription()
+
GPTPart & GPTPart::operator=(const GPTPart & orig) {
int i;
@@ -159,10 +150,9 @@ void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
cout.fill('0');
cout.width(4);
cout.setf(ios::uppercase);
- cout << hex << typeHelper.GUIDToID(partitionType) << " " << dec;
+ cout << hex << partitionType.GetHexType() << " " << dec;
cout.fill(' ');
-// cout.setf(ios::right);
- cout << GetName().substr(0, 23) << "\n";
+ cout << GetDescription().substr(0, 23) << "\n";
cout.fill(' ');
} // if
} // GPTPart::ShowSummary()
@@ -173,9 +163,9 @@ 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 << "Partition GUID code: " << partitionType.AsString();
+ cout << " (" << partitionType.TypeName() << ")\n";
+ cout << "Partition unique GUID: " << uniqueGUID.AsString() << "\n";
cout << "First sector: " << firstLBA << " (at "
<< BytesToSI(firstLBA * blockSize) << ")\n";
@@ -190,7 +180,7 @@ void GPTPart::ShowDetails(uint32_t blockSize) {
cout << hex;
cout << attributes << "\n";
cout << dec;
- cout << "Partition name: " << GetName() << "\n";
+ cout << "Partition name: " << GetDescription() << "\n";
cout.fill(' ');
} // if
} // GPTPart::ShowDetails()
@@ -198,12 +188,9 @@ void GPTPart::ShowDetails(uint32_t blockSize) {
// Blank (delete) a single partition
void GPTPart::BlankPartition(void) {
int j;
- GUIDData zeroGUID;
- zeroGUID.data1 = 0;
- zeroGUID.data2 = 0;
- uniqueGUID = zeroGUID;
- partitionType = zeroGUID;
+ uniqueGUID.Zero();
+ partitionType.Zero();
firstLBA = 0;
lastLBA = 0;
attributes = 0;
@@ -228,10 +215,8 @@ int GPTPart::DoTheyOverlap(const GPTPart & other) {
// 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);
+// partitionType.ReverseGUIDBytes();
+// uniqueGUID.ReverseGUIDBytes();
ReverseBytes(&firstLBA, 8);
ReverseBytes(&lastLBA, 8);
ReverseBytes(&attributes, 8);
@@ -241,30 +226,34 @@ void GPTPart::ReversePartBytes(void) {
* Functions requiring user interaction *
****************************************/
-// Change the type code on the partition.
+// Change the type code on the partition. Also changes the name if the original
+// name is the generic one for the partition type.
void GPTPart::ChangeType(void) {
char line[255];
char* junk;
- int typeNum = 0xFFFF;
- GUIDData newType;
+ unsigned int typeNum = 0xFFFF, changeName = 0;
- cout << "Current type is '" << GetNameType() << "'\n";
- while ((!typeHelper.Valid(typeNum)) && (typeNum != 0)) {
+ if (GetDescription() == GetTypeName())
+ changeName = 1;
+ cout << "Current type is '" << GetTypeName() << "'\n";
+ while ((!partitionType.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();
+ partitionType.ShowAllTypes();
if (line[0] == '\n') {
typeNum = 0x0700;
} // if
} // while
if (typeNum != 0) // user entered a code, so convert it
- newType = typeHelper.IDToGUID((uint16_t) typeNum);
+ partitionType = 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";
+ partitionType.GetGUIDFromUser();
+ cout << "Changed type of partition to '" << partitionType.TypeName() << "'\n";
+ if (changeName) {
+ SetDefaultDescription();
+ } // if
} // GPTPart::ChangeType()
/***********************************
diff --git a/gptpart.h b/gptpart.h
index d24ed87..e6467c1 100644
--- a/gptpart.h
+++ b/gptpart.h
@@ -20,6 +20,7 @@
#include <sys/types.h>
#include "support.h"
#include "parttypes.h"
+#include "guid.h"
using namespace std;
@@ -38,38 +39,37 @@ class GPTPart {
// adjusting the data-load operation in GPTData::LoadMainTable() and
// GPTData::LoadSecondTableAsMain() and then removing the GPTPart
// size check in SizesOK() (in gpt.cc file).
- struct GUIDData partitionType;
- struct GUIDData uniqueGUID;
+ PartType partitionType;
+ GUIDData uniqueGUID;
uint64_t firstLBA;
uint64_t lastLBA;
uint64_t attributes;
unsigned char name[NAME_SIZE];
-
- static PartTypes typeHelper;
public:
GPTPart(void);
~GPTPart(void);
// Simple data retrieval:
- struct GUIDData GetType(void) {return partitionType;}
+ PartType & GetType(void) {return partitionType;}
uint16_t GetHexType(void);
- string GetNameType(void);
- struct GUIDData GetUniqueGUID(void) {return uniqueGUID;}
+ string GetTypeName(void);
+ GUIDData GetUniqueGUID(void) {return uniqueGUID;}
uint64_t GetFirstLBA(void) {return firstLBA;}
uint64_t GetLastLBA(void) {return lastLBA;}
uint64_t GetLengthLBA(void);
uint64_t GetAttributes(void) {return attributes;}
- string GetName(void);
+ string GetDescription(void);
// Simple data assignment:
- void SetType(struct GUIDData t);
- void SetType(uint16_t hex) {SetType(typeHelper.IDToGUID(hex));}
- void SetUniqueGUID(struct GUIDData u) {uniqueGUID = u;}
- void SetUniqueGUID(int zeroOrRandom);
+ void SetType(PartType t);
+ void SetType(uint16_t hex) {partitionType = hex;}
+ void SetUniqueGUID(GUIDData u) {uniqueGUID = u;}
+ void RandomizeUniqueGUID(void) {uniqueGUID.Randomize();}
void SetFirstLBA(uint64_t f) {firstLBA = f;}
void SetLastLBA(uint64_t l) {lastLBA = l;}
void SetAttributes(uint64_t a) {attributes = a;}
void SetName(const string & n);
+ void SetDefaultDescription(void);
// Additional functions
GPTPart & operator=(const GPTPart & orig);
diff --git a/mbr.cc b/mbr.cc
index 214fcb0..2417d77 100644
--- a/mbr.cc
+++ b/mbr.cc
@@ -39,6 +39,7 @@ MBRData::MBRData(void) {
numHeads = MAX_HEADS;
numSecspTrack = MAX_SECSPERTRACK;
myDisk = NULL;
+ canDeleteMyDisk = 0;
EmptyMBR();
} // MBRData default constructor
@@ -50,6 +51,7 @@ MBRData::MBRData(string filename) {
numHeads = MAX_HEADS;
numSecspTrack = MAX_SECSPERTRACK;
myDisk = NULL;
+ canDeleteMyDisk = 0;
srand((unsigned int) time(NULL));
// Try to read the specified partition table, but if it fails....
@@ -59,8 +61,12 @@ MBRData::MBRData(string filename) {
} // if
} // MBRData(string filename) constructor
+// Free space used by myDisk only if that's OK -- sometimes it will be
+// copied from an outside source, in which case that source should handle
+// it!
MBRData::~MBRData(void) {
-// delete myDisk;
+ if (canDeleteMyDisk)
+ delete myDisk;
} // MBRData destructor
/**********************
@@ -74,8 +80,10 @@ MBRData::~MBRData(void) {
int MBRData::ReadMBRData(const string & deviceFilename) {
int allOK = 1;
- if (myDisk == NULL)
+ if (myDisk == NULL) {
myDisk = new DiskIO;
+ canDeleteMyDisk = 1;
+ } // if
if (myDisk->OpenForRead(deviceFilename)) {
ReadMBRData(myDisk);
} else {
@@ -98,8 +106,10 @@ void MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
int err = 1;
TempMBR tempMBR;
- if (myDisk != NULL)
+ if ((myDisk != NULL) && (canDeleteMyDisk)) {
delete myDisk;
+ canDeleteMyDisk = 0;
+ } // if
myDisk = theDisk;
@@ -831,9 +841,9 @@ GPTPart MBRData::AsGPT(int i) {
if (lastSector > 0) lastSector--;
newPart.SetLastLBA(lastSector);
newPart.SetType(((uint16_t) origType) * 0x0100);
- newPart.SetUniqueGUID(1);
+ newPart.RandomizeUniqueGUID();
newPart.SetAttributes(0);
- newPart.SetName(newPart.GetNameType());
+ newPart.SetName(newPart.GetTypeName());
} // if not extended, protective, or non-existent
} // if (origPart != NULL)
return newPart;
diff --git a/mbr.h b/mbr.h
index e83de7e..35cd107 100644
--- a/mbr.h
+++ b/mbr.h
@@ -71,6 +71,7 @@ protected:
uint64_t numHeads; // number of heads, in CHS scheme
uint64_t numSecspTrack; // number of sectors per track, in CHS scheme
DiskIO* myDisk;
+ int canDeleteMyDisk;
string device;
MBRValidity state;
struct MBRRecord* GetPartition(int i); // Return primary or logical partition
diff --git a/parttypes.cc b/parttypes.cc
index 85ce6b0..850b1e3 100644
--- a/parttypes.cc
+++ b/parttypes.cc
@@ -16,9 +16,9 @@
using namespace std;
-int PartTypes::numInstances = 0;
-AType* PartTypes::allTypes = NULL;
-AType* PartTypes::lastType = NULL;
+int PartType::numInstances = 0;
+AType* PartType::allTypes = NULL;
+AType* PartType::lastType = NULL;
// Constructor. Its main task is to initialize the data list, but only
// if this is the first instance, since it's a static linked list.
@@ -31,166 +31,28 @@ AType* PartTypes::lastType = NULL;
// by typing "L" at the main gdisk menu.
// See http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
// for a list of MBR partition type codes.
-PartTypes::PartTypes(void) {
-
+PartType::PartType(void) : GUIDData() {
numInstances++;
if (numInstances == 1) {
-
- // Start with the "unused entry," which should normally appear only
- // on empty partition table entries....
- AddType(0x0000, UINT64_C(0x0000000000000000), UINT64_C(0x0000000000000000),
- "Unused entry", 0);
-
- // DOS/Windows partition types, which confusingly Linux also uses in GPT
- AddType(0x0100, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 0); // FAT-12
- AddType(0x0400, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 0); // FAT-16 < 32M
- AddType(0x0600, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 0); // FAT-16
- AddType(0x0700, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 1); // NTFS (or could be HPFS)
- AddType(0x0b00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 0); // FAT-32
- AddType(0x0c00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 0); // FAT-32 LBA
- AddType(0x0c01, UINT64_C(0x4DB80B5CE3C9E316), UINT64_C(0xAE1502F02DF97D81),
- "Microsoft Reserved"); // Microsoft reserved
- AddType(0x0e00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 0); // FAT-16 LBA
- AddType(0x1100, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 0); // Hidden FAT-12
- AddType(0x1400, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 0); // Hidden FAT-16 < 32M
- AddType(0x1600, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 0); // Hidden FAT-16
- AddType(0x1700, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 0); // Hidden NTFS (or could be HPFS)
- AddType(0x1b00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 0); // Hidden FAT-32
- AddType(0x1c00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 0); // Hidden FAT-32 LBA
- AddType(0x1e00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 0); // Hidden FAT-16 LBA
- AddType(0x2700, UINT64_C(0x4D4006D1DE94BBA4), UINT64_C(0xACD67901D5BF6AA1),
- "Windows RE"); // Windows RE
- AddType(0x4200, UINT64_C(0x4F621431Af9B60A0), UINT64_C(0xAD694A71113368BC),
- "Windows LDM data"); // Logical disk manager
- AddType(0x4201, UINT64_C(0x42E07E8F5808C8AA), UINT64_C(0xB3CF3404E9E1D285),
- "Windows LDM metadata"); // Logical disk manager
-
- // Linux-specific partition types....
- AddType(0x8200, UINT64_C(0x43C4A4AB0657FD6D), UINT64_C(0x4F4F4BC83309E584),
- "Linux swap"); // Linux swap (or could be Solaris)
- AddType(0x8300, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
- "Linux/Windows data", 0); // Linux native
- AddType(0x8301, UINT64_C(0x60C000078DA63339), UINT64_C(0x080923C83A0836C4),
- "Linux Reserved"); // Linux reserved
- AddType(0x8e00, UINT64_C(0x44C2F507E6D6D379), UINT64_C(0x28F93D2A8F233CA2),
- "Linux LVM"); // Linux LVM
-
- // FreeBSD partition types....
- // Note: Rather than extract FreeBSD disklabel data, convert FreeBSD
- // partitions in-place, and let FreeBSD sort out the details....
- AddType(0xa500, UINT64_C(0x11D66ECF516E7CB4), UINT64_C(0x2B71092D0200F88F),
- "FreeBSD disklabel"); // FreeBSD disklabel
- AddType(0xa501, UINT64_C(0x11DC7F4183BD6B9D), UINT64_C(0x0F4FB86015000BBE),
- "FreeBSD boot"); // FreeBSD boot
- AddType(0xa502, UINT64_C(0x11D66ECF516E7CB5), UINT64_C(0x2B71092D0200F88F),
- "FreeBSD swap"); // FreeBSD swap
- AddType(0xa503, UINT64_C(0x11D66ECF516E7CB6), UINT64_C(0x2B71092D0200F88F),
- "FreeBSD UFS"); // FreeBSD UFS
- AddType(0xa504, UINT64_C(0x11D66ECF516E7CBA), UINT64_C(0x2B71092D0200F88F),
- "FreeBSD ZFS"); // FreeBSD ZFS
- AddType(0xa505, UINT64_C(0x11D66ECF516E7CB8), UINT64_C(0x2B71092D0200F88F),
- "FreeBSD Vinum/RAID"); // FreeBSD Vinum
-
- // A MacOS partition type, separated from others by NetBSD partition types...
- AddType(0xa800, UINT64_C(0x11AA000055465300), UINT64_C(0xACEC4365300011AA),
- "Apple UFS"); // MacOS X
-
- // NetBSD partition types. Note that the main entry sets it up as a
- // FreeBSD disklabel. I'm not 100% certain this is the correct behavior.
- AddType(0xa900, UINT64_C(0x11D66ECF516E7CB4), UINT64_C(0x2B71092D0200F88F),
- "FreeBSD disklabel", 0); // NetBSD disklabel
- AddType(0xa901, UINT64_C(0x11DCB10E49F48D32), UINT64_C(0x489687D119009BB9),
- "NetBSD swap");
- AddType(0xa902, UINT64_C(0x11DCB10E49F48D5A), UINT64_C(0x489687D119009BB9),
- "NetBSD FFS");
- AddType(0xa903, UINT64_C(0x11DCB10E49F48D82), UINT64_C(0x489687D119009BB9),
- "NetBSD LFS");
- AddType(0xa903, UINT64_C(0x11DCB10E49F48DAA), UINT64_C(0x489687D119009BB9),
- "NetBSD RAID");
- AddType(0xa904, UINT64_C(0x11DCB10F2DB519C4), UINT64_C(0x489687D119009BB9),
- "NetBSD concatenated");
- AddType(0xa905, UINT64_C(0x11DCB10F2DB519EC), UINT64_C(0x489687D119009BB9),
- "NetBSD encrypted");
-
- // MacOS partition types (See also 0xa800, above)....
- AddType(0xab00, UINT64_C(0x11AA0000426F6F74), UINT64_C(0xACEC4365300011AA),
- "Apple boot"); // MacOS X
- AddType(0xaf00, UINT64_C(0x11AA000048465300), UINT64_C(0xACEC4365300011AA),
- "Apple HFS/HFS+"); // MacOS X
- AddType(0xaf01, UINT64_C(0x11AA000052414944), UINT64_C(0xACEC4365300011AA),
- "Apple RAID"); // MacOS X
- AddType(0xaf02, UINT64_C(0x11AA5F4F52414944), UINT64_C(0xACEC4365300011AA),
- "Apple RAID offline"); // MacOS X
- AddType(0xaf03, UINT64_C(0x11AA6C004C616265), UINT64_C(0xACEC4365300011AA),
- "Apple label"); // MacOS X
- AddType(0xaf04, UINT64_C(0x11AA76655265636F), UINT64_C(0xACEC4365300011AA),
- "AppleTV recovery"); // MacOS X
-
- // Solaris partition types (one of which is shared with MacOS)
- AddType(0xbe00, UINT64_C(0x11B21DD26A82CB45), UINT64_C(0x316673200008A699),
- "Solaris boot"); // Solaris boot
- AddType(0xbf00, UINT64_C(0x11B21DD26a85CF4D), UINT64_C(0x316673200008A699),
- "Solaris root"); // Solaris root
- AddType(0xbf01, UINT64_C(0x11B21DD26A898CC3), UINT64_C(0x316673200008A699),
- "Solaris /usr & Mac ZFS"); // MacOS X & Solaris
- AddType(0xbf02, UINT64_C(0x11B21DD26A87C46F), UINT64_C(0x316673200008A699),
- "Solaris swap");
- AddType(0xbf03, UINT64_C(0x11B21DD26A8B642B), UINT64_C(0x316673200008A699),
- "Solaris backup");
- AddType(0xbf04, UINT64_C(0x11B21DD26A8EF2E9), UINT64_C(0x316673200008A699),
- "Solaris /var");
- AddType(0xbf05, UINT64_C(0x11B21DD26A90BA39), UINT64_C(0x316673200008A699),
- "Solaris /home");
- AddType(0xbf05, UINT64_C(0x11B21DD26A9283A5), UINT64_C(0x316673200008A699),
- "Solaris EFI_ALTSCTR");
- AddType(0xbf06, UINT64_C(0x11B21DD26A945A3B), UINT64_C(0x316673200008A699),
- "Solaris Reserved 1");
- AddType(0xbf07, UINT64_C(0x11B21DD26A9630D1), UINT64_C(0x316673200008A699),
- "Solaris Reserved 2");
- AddType(0xbf08, UINT64_C(0x11B21DD26A980767), UINT64_C(0x316673200008A699),
- "Solaris Reserved 3");
- AddType(0xbf09, UINT64_C(0x11B21DD26A96237F), UINT64_C(0x316673200008A699),
- "Solaris Reserved 4");
- AddType(0xbf0a, UINT64_C(0x11B21DD26A8D2AC7), UINT64_C(0x316673200008A699),
- "Solaris Reserved 5");
-
- // I can find no MBR equivalents for these, but they're on the
- // Wikipedia page for GPT, so here we go....
- AddType(0xc001, UINT64_C(0x11D33AEB75894C1E), UINT64_C(0x000000A0037BC1B7),
- "HP-UX data");
- AddType(0xc002, UINT64_C(0x11D632E3E2A1E728), UINT64_C(0x000000A0037B82A6),
- "HP-UX service");
-
- // EFI system and related partitions
- AddType(0xEF00, UINT64_C(0x11d2f81fc12a7328), UINT64_C(0x3bc93ec9a0004bba),
- "EFI System"); // EFI System (parted marks Linux boot
- // partitions like this)
- AddType(0xEF01, UINT64_C(0x11d333e7024dee41), UINT64_C(0x9FF381C70800699d),
- "MBR partition scheme"); // Used to nest an MBR table on a GPT disk
- AddType(0xEF02, UINT64_C(0x6E6F644921686148), UINT64_C(0x4946456465654E74),
- "BIOS boot partition"); //
-
- // A straggler Linux partition type....
- AddType(0xfd00, UINT64_C(0x4D3B05FCA19D880F), UINT64_C(0x1E91840F3F7406A0),
- "Linux RAID"); // Linux RAID
+ AddAllTypes();
} // if
} // default constructor
-PartTypes::~PartTypes(void) {
+PartType::PartType(const PartType & orig) : GUIDData(orig) {
+ numInstances++;
+ if (numInstances == 1) { // should never happen; just being paranoid
+ AddAllTypes();
+ } // if
+} // PartType copy constructor
+
+PartType::PartType(const GUIDData & orig) : GUIDData(orig) {
+ numInstances++;
+ if (numInstances == 1) {
+ AddAllTypes();
+ } // if
+} // PartType copy constructor
+
+PartType::~PartType(void) {
AType* tempType;
numInstances--;
@@ -203,19 +65,117 @@ PartTypes::~PartTypes(void) {
} // if
} // destructor
+// Add all partition type codes to the internal linked-list structure.
+// Used by constructors.
+void PartType::AddAllTypes(void) {
+ // Start with the "unused entry," which should normally appear only
+ // on empty partition table entries....
+ AddType(0x0000, "00000000-0000-0000-0000-000000000000", "Unused entry", 0);
+
+ // DOS/Windows partition types, which confusingly Linux also uses in GPT
+ AddType(0x0100, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // FAT-12
+ AddType(0x0400, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // FAT-16 < 32M
+ AddType(0x0600, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // FAT-16
+ AddType(0x0700, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 1); // NTFS (or HPFS)
+ AddType(0x0b00, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // FAT-32
+ AddType(0x0c00, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // FAT-32 LBA
+ AddType(0x0c01, "E3C9E316-0B5C-4DB8-817D-F92DF00215AE", "Microsoft reserved");
+ AddType(0x0e00, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // FAT-16 LBA
+ AddType(0x1100, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Hidden FAT-12
+ AddType(0x1400, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Hidden FAT-16 < 32M
+ AddType(0x1600, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Hidden FAT-16
+ AddType(0x1700, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Hidden NTFS (or HPFS)
+ AddType(0x1b00, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Hidden FAT-32
+ AddType(0x1c00, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Hidden FAT-32 LBA
+ AddType(0x1e00, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Hidden FAT-16 LBA
+ AddType(0x2700, "DE94BBA4-06D1-4D40-A16A-BFD50179D6AC", "Windows RE");
+ AddType(0x4200, "AF9B60A0-1431-4F62-BC68-3311714A69AD", "Windows LDM data"); // Logical disk manager
+ AddType(0x4201, "5808C8AA-7E8F-42E0-85D2-E1E90434CFB3", "Windows LDM metadata"); // Logical disk manager
+
+ // An oddball IBM filesystem....
+ AddType(0x7501, "37AFFC90-EF7D-4E96-91C3-2D7AE055B174", "IBM GPFS"); // General Parallel File System (GPFS)
+
+ // Linux-specific partition types....
+ AddType(0x8200, "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F", "Linux swap"); // Linux swap (or Solaris)
+ AddType(0x8300, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Linux native
+ AddType(0x8301, "8DA63339-0007-60C0-C436-083AC8230908", "Linux reserved");
+ AddType(0x8e00, "E6D6D379-F507-44C2-A23C-238F2A3DF928", "Linux LVM");
+
+ // 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(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");
+ AddType(0xa504, "516E7CBA-6ECF-11D6-8FF8-00022D09712B", "FreeBSD ZFS");
+ AddType(0xa505, "516E7CB8-6ECF-11D6-8FF8-00022D09712B", "FreeBSD Vinum/RAID");
+
+ // A MacOS partition type, separated from others by NetBSD partition types...
+ AddType(0xa800, "55465300-0000-11AA-AA11-00306543ECAC", "Apple UFS"); // Mac OS X
+
+ // NetBSD partition types. Note that the main entry sets it up as a
+ // FreeBSD disklabel. I'm not 100% certain this is the correct behavior.
+ AddType(0xa900, "516E7CB4-6ECF-11D6-8FF8-00022D09712B", "FreeBSD disklabel", 0); // NetBSD disklabel
+ AddType(0xa901, "49F48D32-B10E-11DC-B99B-0019D1879648", "NetBSD swap");
+ AddType(0xa902, "49F48D5A-B10E-11DC-B99B-0019D1879648", "NetBSD FFS");
+ AddType(0xa903, "49F48D82-B10E-11DC-B99B-0019D1879648", "NetBSD LFS");
+ AddType(0xa904, "2DB519C4-B10F-11DC-B99B-0019D1879648", "NetBSD concatenated");
+ AddType(0xa905, "2DB519EC-B10F-11DC-B99B-0019D1879648", "NetBSD encrypted");
+ AddType(0xa906, "49F48DAA-B10E-11DC-B99B-0019D1879648", "NetBSD RAID");
+
+ // Mac OS partition types (See also 0xa800, above)....
+ AddType(0xab00, "426F6F74-0000-11AA-AA11-00306543ECAC", "Apple boot");
+ AddType(0xaf00, "48465300-0000-11AA-AA11-00306543ECAC", "Apple HFS/HFS+");
+ AddType(0xaf01, "52414944-0000-11AA-AA11-00306543ECAC", "Apple RAID");
+ AddType(0xaf02, "52414944-5F4F-11AA-AA11-00306543ECAC", "Apple RAID offline");
+ AddType(0xaf03, "4C616265-6C00-11AA-AA11-00306543ECAC", "Apple label");
+ AddType(0xaf04, "5265636F-7665-11AA-AA11-00306543ECAC", "AppleTV recovery");
+
+ // Solaris partition types (one of which is shared with MacOS)
+ AddType(0xbe00, "6A82CB45-1DD2-11B2-99A6-080020736631", "Solaris boot");
+ AddType(0xbf00, "6A85CF4D-1DD2-11B2-99A6-080020736631", "Solaris root");
+ AddType(0xbf01, "6A898CC3-1DD2-11B2-99A6-080020736631", "Solaris /usr & Mac ZFS"); // Solaris/MacOS
+ AddType(0xbf02, "6A87C46F-1DD2-11B2-99A6-080020736631", "Solaris swap");
+ AddType(0xbf03, "6A8B642B-1DD2-11B2-99A6-080020736631", "Solaris backup");
+ AddType(0xbf04, "6A8EF2E9-1DD2-11B2-99A6-080020736631", "Solaris /var");
+ AddType(0xbf05, "6A90BA39-1DD2-11B2-99A6-080020736631", "Solaris /home");
+ AddType(0xbf06, "6A9283A5-1DD2-11B2-99A6-080020736631", "Solaris alternate sector");
+ AddType(0xbf07, "6A945A3B-1DD2-11B2-99A6-080020736631", "Solaris Reserved 1");
+ AddType(0xbf08, "6A9630D1-1DD2-11B2-99A6-080020736631", "Solaris Reserved 2");
+ AddType(0xbf09, "6A980767-1DD2-11B2-99A6-080020736631", "Solaris Reserved 3");
+ AddType(0xbf0a, "6A96237F-1DD2-11B2-99A6-080020736631", "Solaris Reserved 4");
+ AddType(0xbf0b, "6A8D2AC7-1DD2-11B2-99A6-080020736631", "Solaris Reserved 5");
+
+ // I can find no MBR equivalents for these, but they're on the
+ // Wikipedia page for GPT, so here we go....
+ AddType(0xc001, "75894C1E-3AEB-11D3-B7C1-7B03A0000000", "HP-UX data");
+ AddType(0xc002, "E2A1E728-32E3-11D6-A682-7B03A0000000", "HP-UX service");
+
+ // EFI system and related partitions
+ AddType(0xef00, "C12A7328-F81F-11D2-BA4B-00A0C93EC93B", "EFI System"); // Parted marks Linux boot partitions as this
+ AddType(0xef01, "024DEE41-33E7-11D3-9D69-0008C781F39F", "MBR partition scheme"); // Used to nest MBR in GPT
+ AddType(0xef02, "21686148-6449-6E6F-744E-656564454649", "BIOS boot partition"); // Boot loader
+
+ // A straggler Linux partition type....
+ AddType(0xfd00, "A19D880F-05FC-4D3B-A006-743F0F84911E", "Linux RAID");
+
+ // Note: DO NOT use the 0xffff code; that's reserved to indicate an
+ // unknown type code.
+} // PartType::AddAllTypes()
+
// Add a single type to the linked list of types. Returns 1 if operation
// succeeds, 0 otherwise.
-int PartTypes::AddType(uint16_t mbrType, uint64_t guidData1, uint64_t guidData2,
- const char * n, int toDisplay) {
+int PartType::AddType(uint16_t mbrType, const char * guidData, const char * name,
+ int toDisplay) {
AType* tempType;
int allOK = 1;
tempType = new AType;
if (tempType != NULL) {
tempType->MBRType = mbrType;
- tempType->GUIDType.data1 = guidData1;
- tempType->GUIDType.data2 = guidData2;
- tempType->name = n;
+ tempType->GUIDType = guidData;
+ tempType->name = name;
tempType->display = toDisplay;
tempType->next = NULL;
if (allTypes == NULL) { // first entry
@@ -228,122 +188,70 @@ int PartTypes::AddType(uint16_t mbrType, uint64_t guidData1, uint64_t guidData2,
allOK = 0;
} // if/else
return allOK;
-} // PartTypes::AddType()
-
-// Displays the available types and my extended MBR codes for same....
-// Note: This function assumes an 80-column display. On wider displays,
-// it stops at under 80 columns; on narrower displays, lines will wrap
-// in an ugly way.
-void PartTypes::ShowTypes(void) {
- int colCount = 1; // column count
- size_t i;
- AType* thisType = allTypes;
+} // GUID::AddType(const char* variant)
- cout.unsetf(ios::uppercase);
- while (thisType != NULL) {
- if (thisType->display == 1) { // show it
- cout.fill('0');
- cout.width(4);
- cout << hex << thisType->MBRType << " ";
- cout << thisType->name.substr(0, 20);
- for (i = 0; i < (20 - (thisType->name.substr(0, 20).length())); i++) cout << " ";
- if ((colCount % 3) == 0)
- cout << "\n";
- else
- cout << " ";
- colCount++;
- } // if
- thisType = thisType->next;
- } // while
- cout.fill(' ');
- cout << "\n" << dec;
-} // PartTypes::ShowTypes()
-
-// Returns 1 if code is a valid extended MBR code, 0 if it's not
-int PartTypes::Valid(uint16_t code) {
- AType* thisType = allTypes;
- int found = 0;
-
- while ((thisType != NULL) && (!found)) {
- if (thisType->MBRType == code) {
- found = 1;
- } // if
- thisType = thisType->next;
- } // while
- return found;
-} // PartTypes::Valid()
-
-// Convert a GUID code to a name.
-string PartTypes::GUIDToName(struct GUIDData typeCode) {
+// Assign a GUID based on my custom 2-byte (16-bit) MBR hex ID variant
+GUIDData & PartType::operator=(uint16_t ID) {
AType* theItem = allTypes;
int found = 0;
- string typeName;
+ // Assign a default value....
+ GUIDData::operator=("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"); // 0700, Linux/Windows data
+
+ // Now search the type list for a match to the ID....
while ((theItem != NULL) && (!found)) {
- if ((theItem->GUIDType.data1 == typeCode.data1) &&
- (theItem->GUIDType.data2 == typeCode.data2)) { // found it!
- typeName = theItem->name;
- found = 1;
+ if (theItem->MBRType == ID) { // found it!
+ GUIDData::operator=(theItem->GUIDType);
+ found = 1;
} else {
theItem = theItem->next;
} // if/else
} // while
if (!found) {
- typeName = "Unknown";
+ cout.setf(ios::uppercase);
+ 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;
+ cout.fill(' ');
} // if (!found)
- return typeName;
-} // PartTypes::GUIDToName()
+ return *this;
+} // PartType::operator=(uint16_t ID)
-// This function takes a variant of the MBR partition type code and
-// converts it to a GUID type code
-struct GUIDData PartTypes::IDToGUID(uint16_t ID) {
+// Return the English description of the partition type (e.g., "Linux/Windows data")
+string PartType::TypeName(void) {
AType* theItem = allTypes;
int found = 0;
- struct GUIDData theGUID;
-
- // Start by assigning a default GUID for the return value. Done
- // "raw" to avoid the necessity for a recursive call and the
- // remote possibility of an infinite recursive loop that this
- // approach would present....
- theGUID.data1 = UINT64_C(0x4433B9E5EBD0A0A2);
- theGUID.data2 = UINT64_C(0xC79926B7B668C087);
+ string typeName;
- // Now search the type list for a match to the ID....
while ((theItem != NULL) && (!found)) {
- if (theItem->MBRType == ID) { // found it!
- theGUID = theItem->GUIDType;
- found = 1;
+ if (theItem->GUIDType == *this) { // found it!
+ typeName = theItem->name;
+ found = 1;
} else {
theItem = theItem->next;
} // if/else
} // while
if (!found) {
- cout.setf(ios::uppercase);
- 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;
- cout.fill(' ');
+ typeName = "Unknown";
} // if (!found)
- return theGUID;
-} // PartTypes::IDToGUID()
+ return typeName;
+} // PartType::TypeName()
-// Convert a GUID to a 16-bit variant of the MBR ID number.
+// Return the custom GPT fdisk 2-byte (16-bit) hex code for this GUID partition type
// Note that this function ignores entries for which the display variable
// is set to 0. This enables control of which values get returned when
// there are multiple possibilities, but opens the algorithm up to the
// potential for problems should the data in the list be bad.
-uint16_t PartTypes::GUIDToID(struct GUIDData typeCode) {
+uint16_t PartType::GetHexType() {
AType* theItem = allTypes;
int found = 0;
uint16_t theID = 0xFFFF;
while ((theItem != NULL) && (!found)) {
- if ((theItem->GUIDType.data1 == typeCode.data1) &&
- (theItem->GUIDType.data2 == typeCode.data2) &&
- (theItem->display == 1)) { // found it!
+ if ((theItem->GUIDType == *this) && (theItem->display == 1)) { // found it!
theID = theItem->MBRType;
- found = 1;
+ found = 1;
} else {
theItem = theItem->next;
} // if/else
@@ -352,4 +260,47 @@ uint16_t PartTypes::GUIDToID(struct GUIDData typeCode) {
theID = 0xFFFF;
} // if (!found)
return theID;
-} // PartTypes::GUIDToID()
+} // PartType::GetHex()
+
+// Displays the available types and my extended MBR codes for same....
+// Note: This function assumes an 80-column display. On wider displays,
+// it stops at under 80 columns; on narrower displays, lines will wrap
+// in an ugly way.
+void PartType::ShowAllTypes(void) {
+ int colCount = 1; // column count
+ size_t i;
+ AType* thisType = allTypes;
+
+ cout.unsetf(ios::uppercase);
+ while (thisType != NULL) {
+ if (thisType->display == 1) { // show it
+ cout.fill('0');
+ cout.width(4);
+ cout << hex << thisType->MBRType << " ";
+ cout << thisType->name.substr(0, 20);
+ for (i = 0; i < (20 - (thisType->name.substr(0, 20).length())); i++) cout << " ";
+ if ((colCount % 3) == 0)
+ cout << "\n";
+ else
+ cout << " ";
+ colCount++;
+ } // if
+ thisType = thisType->next;
+ } // while
+ cout.fill(' ');
+ cout << "\n" << dec;
+} // PartType::ShowTypes()
+
+// Returns 1 if code is a valid extended MBR code, 0 if it's not
+int PartType::Valid(uint16_t code) {
+ AType* thisType = allTypes;
+ int found = 0;
+
+ while ((thisType != NULL) && (!found)) {
+ if (thisType->MBRType == code) {
+ found = 1;
+ } // if
+ thisType = thisType->next;
+ } // while
+ return found;
+} // PartType::Valid()
diff --git a/parttypes.h b/parttypes.h
index 1534a52..1f82d1d 100644
--- a/parttypes.h
+++ b/parttypes.h
@@ -6,6 +6,7 @@
#include <stdlib.h>
#include <string>
#include "support.h"
+#include "guid.h"
#ifndef __PARTITION_TYPES
#define __PARTITION_TYPES
@@ -18,27 +19,42 @@ struct AType {
// type codes, so as to permit disambiguation and use of new
// codes required by GPT
uint16_t MBRType;
- struct GUIDData GUIDType;
+ GUIDData GUIDType;
string name;
int display; // 1 to show to users as available type, 0 not to
AType* next;
}; // struct AType
-class PartTypes {
+class PartType : public GUIDData {
protected:
static int numInstances;
static AType* allTypes; // Linked list holding all the data
static AType* lastType; // Pointer to last entry in the list
+ void AddAllTypes(void);
public:
- PartTypes(void);
- ~PartTypes(void);
- int AddType(uint16_t mbrType, uint64_t guidData1, uint64_t guidData2,
- const char * name, int toDisplay = 1);
- void ShowTypes(void);
+ PartType(void);
+ PartType(const PartType & orig);
+ PartType(const GUIDData & orig);
+ ~PartType(void);
+
+ // Set up type information
+ int AddType(uint16_t mbrType, const char * guidData, const char * name, int toDisplay = 1);
+
+ // Assignment operators based on base class....
+ GUIDData & operator=(const GUIDData & orig) {return GUIDData::operator=(orig);}
+ GUIDData & operator=(const string & orig) {return GUIDData::operator=(orig);}
+ 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
+
+ // Retrieve transformed GUID data based on type code matches
+ string TypeName(void);
+ uint16_t GetHexType();
+
+ // Information relating to all type data
+ void ShowAllTypes(void);
int Valid(uint16_t);
- string GUIDToName(struct GUIDData typeCode);
- struct GUIDData IDToGUID(uint16_t ID);
- uint16_t GUIDToID(struct GUIDData);
};
#endif
diff --git a/sgdisk.8 b/sgdisk.8
index 1a26a61..5a554cd 100644
--- a/sgdisk.8
+++ b/sgdisk.8
@@ -1,6 +1,6 @@
.\" Copyright 2009 Roderick W. Smith (rodsmith@rodsbooks.com)
.\" May be distributed under the GNU General Public License
-.TH "SGDISK" "8" "0.6.0" "Roderick W. Smith" "GPT fdisk Manual"
+.TH "SGDISK" "8" "0.6.3" "Roderick W. Smith" "GPT fdisk Manual"
.SH "NAME"
sgdisk \- Command\-line GUID partition table (GPT) manipulator for Linux and Unix
.SH "SYNOPSIS"
diff --git a/sgdisk.cc b/sgdisk.cc
index bdb2eb2..e97e57d 100644
--- a/sgdisk.cc
+++ b/sgdisk.cc
@@ -37,7 +37,7 @@ int main(int argc, char *argv[]) {
char *device = NULL;
char *newPartInfo = NULL, *typeCode = NULL, *partName;
char *backupFile = NULL;
- PartTypes typeHelper;
+ PartType typeHelper;
poptContext poptCon;
struct poptOption theOptions[] =
@@ -82,7 +82,7 @@ int main(int argc, char *argv[]) {
while ((opt = poptGetNextOpt(poptCon)) > 0) {
switch (opt) {
case 'L':
- typeHelper.ShowTypes();
+ typeHelper.ShowAllTypes();
break;
case 'P':
pretend = 1;
diff --git a/support.cc b/support.cc
index 3137635..56a2dd3 100644
--- a/support.cc
+++ b/support.cc
@@ -200,112 +200,19 @@ string BytesToSI(uint64_t size) {
return theValue;
} // BlocksToSI()
-// Return a plain-text name for a partition type.
-// Convert a GUID to a string representation, suitable for display
-// to humans....
-string GUIDToStr(struct GUIDData theGUID) {
- unsigned long long blocks[11];
- char theString[40];
-
- theString[0] = '\0';;
- blocks[0] = (theGUID.data1 & UINT64_C(0x00000000FFFFFFFF));
- blocks[1] = (theGUID.data1 & UINT64_C(0x0000FFFF00000000)) >> 32;
- blocks[2] = (theGUID.data1 & UINT64_C(0xFFFF000000000000)) >> 48;
- blocks[3] = (theGUID.data2 & UINT64_C(0x00000000000000FF));
- blocks[4] = (theGUID.data2 & UINT64_C(0x000000000000FF00)) >> 8;
- blocks[5] = (theGUID.data2 & UINT64_C(0x0000000000FF0000)) >> 16;
- blocks[6] = (theGUID.data2 & UINT64_C(0x00000000FF000000)) >> 24;
- blocks[7] = (theGUID.data2 & UINT64_C(0x000000FF00000000)) >> 32;
- blocks[8] = (theGUID.data2 & UINT64_C(0x0000FF0000000000)) >> 40;
- blocks[9] = (theGUID.data2 & UINT64_C(0x00FF000000000000)) >> 48;
- blocks[10] = (theGUID.data2 & UINT64_C(0xFF00000000000000)) >> 56;
- sprintf(theString,
- "%08llX-%04llX-%04llX-%02llX%02llX-%02llX%02llX%02llX%02llX%02llX%02llX",
- blocks[0], blocks[1], blocks[2], blocks[3], blocks[4], blocks[5],
- blocks[6], blocks[7], blocks[8], blocks[9], blocks[10]);
- return theString;
-} // GUIDToStr()
-
-// Get a GUID from the user
-GUIDData GetGUID(void) {
- unsigned long long part1, part2, part3, part4, part5;
- int entered = 0;
- char temp[255], temp2[255];
- char* junk;
- GUIDData theGUID;
-
- cout << "\nA GUID is entered in five segments of from two to six bytes, with\n"
- << "dashes between segments.\n";
- cout << "Enter the entire GUID, a four-byte hexadecimal number for the first segment, or\n"
- << "'R' to generate the entire GUID randomly: ";
- junk = fgets(temp, 255, stdin);
-
- // If user entered 'r' or 'R', generate GUID randomly....
- if ((temp[0] == 'r') || (temp[0] == 'R')) {
- theGUID.data1 = (uint64_t) rand() * (uint64_t) rand();
- theGUID.data2 = (uint64_t) rand() * (uint64_t) rand();
- entered = 1;
- } // if user entered 'R' or 'r'
-
- // If string length is right for whole entry, try to parse it....
- if ((strlen(temp) == 37) && (entered == 0)) {
- strncpy(temp2, &temp[0], 8);
- temp2[8] = '\0';
- sscanf(temp2, "%llx", &part1);
- strncpy(temp2, &temp[9], 4);
- temp2[4] = '\0';
- sscanf(temp2, "%llx", &part2);
- strncpy(temp2, &temp[14], 4);
- temp2[4] = '\0';
- sscanf(temp2, "%llx", &part3);
- theGUID.data1 = (part3 << 48) + (part2 << 32) + part1;
- strncpy(temp2, &temp[19], 4);
- temp2[4] = '\0';
- sscanf(temp2, "%llx", &part4);
- strncpy(temp2, &temp[24], 12);
- temp2[12] = '\0';
- sscanf(temp2, "%llx", &part5);
- theGUID.data2 = ((part4 & UINT64_C(0x000000000000FF00)) >> 8) +
- ((part4 & UINT64_C(0x00000000000000FF)) << 8) +
- ((part5 & UINT64_C(0x0000FF0000000000)) >> 24) +
- ((part5 & UINT64_C(0x000000FF00000000)) >> 8) +
- ((part5 & UINT64_C(0x00000000FF000000)) << 8) +
- ((part5 & UINT64_C(0x0000000000FF0000)) << 24) +
- ((part5 & UINT64_C(0x000000000000FF00)) << 40) +
- ((part5 & UINT64_C(0x00000000000000FF)) << 56);
- entered = 1;
+// Converts two consecutive characters in the input string into a
+// number, interpreting the string as a hexadecimal number, starting
+// at the specified position.
+unsigned char StrToHex(const string & input, unsigned int position) {
+ unsigned char retval = 0x00;
+ unsigned int temp;
+
+ if (input.length() >= (position + 2)) {
+ sscanf(input.substr(position, 2).c_str(), "%x", &temp);
+ retval = (unsigned char) temp;
} // if
-
- // If neither of the above methods of entry was used, use prompted
- // entry....
- if (entered == 0) {
- sscanf(temp, "%llx", &part1);
- cout << "Enter a two-byte hexadecimal number for the second segment: ";
- junk = fgets(temp, 255, stdin);
- sscanf(temp, "%llx", &part2);
- cout << "Enter a two-byte hexadecimal number for the third segment: ";
- junk = fgets(temp, 255, stdin);
- sscanf(temp, "%llx", &part3);
- theGUID.data1 = (part3 << 48) + (part2 << 32) + part1;
- cout << "Enter a two-byte hexadecimal number for the fourth segment: ";
- junk = fgets(temp, 255, stdin);
- sscanf(temp, "%llx", &part4);
- cout << "Enter a six-byte hexadecimal number for the fifth segment: ";
- junk = fgets(temp, 255, stdin);
- sscanf(temp, "%llx", &part5);
- theGUID.data2 = ((part4 & UINT64_C(0x000000000000FF00)) >> 8) +
- ((part4 & UINT64_C(0x00000000000000FF)) << 8) +
- ((part5 & UINT64_C(0x0000FF0000000000)) >> 24) +
- ((part5 & UINT64_C(0x000000FF00000000)) >> 8) +
- ((part5 & UINT64_C(0x00000000FF000000)) << 8) +
- ((part5 & UINT64_C(0x0000000000FF0000)) << 24) +
- ((part5 & UINT64_C(0x000000000000FF00)) << 40) +
- ((part5 & UINT64_C(0x00000000000000FF)) << 56);
- entered = 1;
- } // if/else
- cout << "New GUID: " << GUIDToStr(theGUID) << "\n";
- return theGUID;
-} // GetGUID()
+ return retval;
+} // StrToHex()
// Return 1 if the CPU architecture is little endian, 0 if it's big endian....
int IsLittleEndian(void) {
diff --git a/support.h b/support.h
index 0123ee0..f17b14c 100644
--- a/support.h
+++ b/support.h
@@ -23,11 +23,6 @@
#include <linux/fs.h>
#endif
-/* #ifdef __FreeBSD__
-#define fstat64 fstat
-#define stat64 stat
-#endif */
-
// Set this as a default
#define SECTOR_SIZE UINT32_C(512)
@@ -53,20 +48,11 @@
using namespace std;
-// a GUID
-struct GUIDData {
- uint64_t data1;
- uint64_t data2;
-}; // struct GUIDData
-
-// static char theFile[255];
-
int GetNumber(int low, int high, int def, const string & prompt);
char GetYN(void);
uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const string & prompt);
string BytesToSI(uint64_t size);
-string GUIDToStr(struct GUIDData theGUID);
-GUIDData GetGUID(void);
+unsigned char StrToHex(const string & input, unsigned int position);
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
uint64_t PowerOf2(int value);