summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsrs5694 <srs5694@users.sourceforge.net>2010-01-28 21:10:52 -0500
committersrs5694 <srs5694@users.sourceforge.net>2010-01-28 21:10:52 -0500
commit0a6973119c9e9984ad47a6da3231e8d16f996c5c (patch)
tree456b81b56315eca6ac64688db34cbb0a25a87f41
parent91544e13fb56ef339277a8f73f761ff004b2e74f (diff)
downloadsgdisk-0a6973119c9e9984ad47a6da3231e8d16f996c5c.tar.gz
Nearing 0.6.2 release; Windows version now works.
-rw-r--r--CHANGELOG4
-rw-r--r--Makefile3
-rw-r--r--Makefile.mingw13
-rw-r--r--bsd.cc6
-rw-r--r--bsd.h2
-rw-r--r--diskio-windows.cc101
-rw-r--r--diskio.cc8
-rw-r--r--diskio.h10
-rw-r--r--gdisk.88
-rw-r--r--gdisk.cc11
-rw-r--r--gpt.cc32
-rw-r--r--gpt.h12
-rw-r--r--gptpart.cc213
-rw-r--r--gptpart.h8
-rw-r--r--mbr.cc40
-rw-r--r--mbr.h4
-rw-r--r--parttypes.cc9
17 files changed, 247 insertions, 237 deletions
diff --git a/CHANGELOG b/CHANGELOG
index a5a7c84..1a72009 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,10 @@
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
MBR was invalid and the GPT was damaged and the user opts to try to
use the GPT data.
diff --git a/Makefile b/Makefile
index 52ce8ef..807d10f 100644
--- a/Makefile
+++ b/Makefile
@@ -19,9 +19,6 @@ gdisk: $(LIB_OBJS) gdisk.o
sgdisk: $(LIB_OBJS) sgdisk.o
$(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 $(SRCS)
diff --git a/Makefile.mingw b/Makefile.mingw
index 0976a5a..664fda4 100644
--- a/Makefile.mingw
+++ b/Makefile.mingw
@@ -1,7 +1,8 @@
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 -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_SRCS=$(NAMES:=.cc)
LIB_OBJS=$(LIB_NAMES:=.o)
@@ -17,16 +18,16 @@ gdisk: $(LIB_OBJS) gdisk.o
$(CXX) $(LIB_OBJS) gdisk.o -o gdisk.exe
sgdisk: $(LIB_OBJS) sgdisk.o
- $(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
+ $(CXX) $(LIB_OBJS) sgdisk.o -L/opt/local/lib -L/usr/local/lib -lpopt -o sgdisk.exe
lint: #no pre-reqs
lint $(SRCS)
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
depend: $(SRCS)
diff --git a/bsd.cc b/bsd.cc
index 1db68ea..88c25d0 100644
--- a/bsd.cc
+++ b/bsd.cc
@@ -43,12 +43,12 @@ BSDData::~BSDData(void) {
// Read BSD disklabel data from the specified device filename. This function
// 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.
-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;
DiskIO myDisk;
- if (*device != "") {
- if (myDisk.OpenForRead(*device)) {
+ if (device != "") {
+ if (myDisk.OpenForRead(device)) {
allOK = ReadBSDData(&myDisk, startSector, endSector);
} else {
allOK = 0;
diff --git a/bsd.h b/bsd.h
index 54f5899..16f3d2c 100644
--- a/bsd.h
+++ b/bsd.h
@@ -72,7 +72,7 @@ class BSDData {
public:
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);
void ReverseMetaBytes(void);
void DisplayBSDData(void);
diff --git a/diskio-windows.cc b/diskio-windows.cc
index 84b77ee..a060103 100644
--- a/diskio-windows.cc
+++ b/diskio-windows.cc
@@ -42,9 +42,9 @@ void DiskIO::MakeRealName(void) {
if ((colonPos != string::npos) && (colonPos <= 3)) {
realFilename = "\\\\.\\physicaldrive";
realFilename += userFilename.substr(0, colonPos);
+ } else {
+ realFilename = userFilename;
} // if/else
- printf("Exiting DiskIO::MakeRealName(); translated '%s' ", userFilename.c_str());
- printf("to '%s'\n", realFilename.c_str());
} // DiskIO::MakeRealName()
// Open the currently on-record file for reading
@@ -60,12 +60,11 @@ int DiskIO::OpenForRead(void) {
} // if
if (shouldOpen) {
- printf("Opening '%s' for reading.\n", realFilename.c_str());
fd = CreateFile(realFilename.c_str(),GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fd == INVALID_HANDLE_VALUE) {
CloseHandle(fd);
- fprintf(stderr, "Problem opening %s for reading!\n", realFilename.c_str());
+ cerr << "Problem opening " << realFilename << " for reading!\n";
realFilename = "";
userFilename = "";
isOpen = 0;
@@ -94,11 +93,12 @@ int DiskIO::OpenForWrite(void) {
FILE_ATTRIBUTE_NORMAL, NULL);
if (fd == INVALID_HANDLE_VALUE) {
CloseHandle(fd);
- isOpen = 1;
- openForWrite = 1;
- } else {
isOpen = 0;
openForWrite = 0;
+ errno = GetLastError();
+ } else {
+ isOpen = 1;
+ openForWrite = 1;
} // if/else
return isOpen;
} // DiskIO::OpenForWrite(void)
@@ -133,6 +133,7 @@ int DiskIO::GetBlockSize(void) {
__out LPDWORD lpTotalNumberOfClusters
); */
// err = GetDiskFreeSpace(realFilename.c_str(), &junk1, &blockSize, &junk2, &junk3);
+ // Above call is fubared -- returns weird values for blockSize....
err = 1;
blockSize = 512;
@@ -142,9 +143,9 @@ int DiskIO::GetBlockSize(void) {
// file, so don't display the warning message....
// 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....
- if ((errno != ENOTTY) && (errno != EINVAL)) {
- printf("\aError %d when determining sector size! Setting sector size to %d\n",
- GetLastError(), SECTOR_SIZE);
+ if (errno != 267) { // 267 is returned on ordinary files
+ cerr << "\aError " << GetLastError() << " when determining sector size! "
+ << "Setting sector size to " << SECTOR_SIZE << "\n";
} // if
} // if (err == -1)
} // if (isOpen)
@@ -155,21 +156,26 @@ int DiskIO::GetBlockSize(void) {
// Resync disk caches so the OS uses the new partition table. This code varies
// a lot from one OS to another.
void DiskIO::DiskSync(void) {
- int i;
+ DWORD i;
+ GET_LENGTH_INFORMATION buf;
// If disk isn't open, try to open it....
- if (!isOpen) {
- OpenForRead();
+ if (!openForWrite) {
+ OpenForWrite();
} // if
if (isOpen) {
-#ifndef MINGW
- sync();
-#endif
-#ifdef MINGW
- printf("Warning: I don't know how to sync disks in Windows! The old partition table is\n"
- "probably still in use!\n");
-#endif
+ if (DeviceIoControl(fd, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, &buf, sizeof(buf), &i, NULL) == 0) {
+ cout << "Disk synchronization failed! The computer may use the old partition table\n"
+ << "until you reboot or remove and re-insert the disk!\n";
+ } else {
+ cout << "Disk synchronization succeeded! The computer should now use the new\n"
+ << "partition table.\n";
+ } // 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)
} // DiskIO::DiskSync()
@@ -186,22 +192,11 @@ int DiskIO::Seek(uint64_t sector) {
} // if
if (isOpen) {
- bytePos = 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); */
+ seekTo.QuadPart = sector * (uint64_t) GetBlockSize();
retval = SetFilePointerEx(fd, seekTo, NULL, FILE_BEGIN);
if (retval == 0) {
errno = GetLastError();
- fprintf(stderr, "Error when seeking to %lld! Error is %d\n",
- seekTo.QuadPart, errno);
+ cerr << "Error when seeking to " << seekTo.QuadPart << "! Error is " << errno << "\n";
retval = 0;
} // if
} // if
@@ -235,9 +230,7 @@ int DiskIO::Read(void* buffer, int numBytes) {
} // if/else
// Read the data into temporary space, then copy it to buffer
-// retval = read(fd, tempSpace, numBlocks * blockSize);
ReadFile(fd, tempSpace, numBlocks * blockSize, &retval, NULL);
- printf("In DiskIO::Read(), have read %d bytes.\n", (int) retval);
for (i = 0; i < numBytes; i++) {
((char*) buffer)[i] = tempSpace[i];
} // for
@@ -284,7 +277,6 @@ int DiskIO::Write(void* buffer, int numBytes) {
for (i = numBytes; i < numBlocks * blockSize; i++) {
tempSpace[i] = 0;
} // for
-// retval = write(fd, tempSpace, numBlocks * blockSize);
WriteFile(fd, tempSpace, numBlocks * blockSize, &numWritten, NULL);
retval = (int) numWritten;
@@ -300,8 +292,7 @@ int DiskIO::Write(void* buffer, int numBytes) {
// Returns the size of the disk in blocks.
uint64_t DiskIO::DiskSize(int *err) {
uint64_t sectors = 0; // size in sectors
- off_t bytes = 0; // size in bytes
- struct stat64 st;
+ DWORD bytes, moreBytes; // low- and high-order bytes of file size
GET_LENGTH_INFORMATION buf;
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
// systems but not on 64-bit. Keep this in mind in case of
// 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)) {
sectors = (uint64_t) buf.Length.QuadPart / GetBlockSize();
-// printf("disk_get_size_win32 IOCTL_DISK_GET_LENGTH_INFO = %llu\n",
-// (long long unsigned) sectors);
- } else {
- fprintf(stderr, "Couldn't determine disk size!\n");
- }
-
-/* // 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)
+ *err = 0;
+ } else { // doesn't seem to be a disk device; assume it's an image file....
+ bytes = GetFileSize(fd, &moreBytes);
+ sectors = ((uint64_t) bytes + ((uint64_t) moreBytes) * UINT32_MAX) / GetBlockSize();
+ *err = 0;
+ } // if
+ } else {
+ *err = -1;
+ sectors = 0;
+ } // if/else (isOpen)
+
return sectors;
} // DiskIO::DiskSize()
diff --git a/diskio.cc b/diskio.cc
index d1d0c3c..0f58ab5 100644
--- a/diskio.cc
+++ b/diskio.cc
@@ -15,7 +15,7 @@
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
-#ifdef MINGW
+#ifdef _WIN32
#include <windows.h>
#include <winioctl.h>
#define fstat64 fstat
@@ -52,7 +52,7 @@ DiskIO::~DiskIO(void) {
} // destructor
// 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;
if (isOpen) { // file is already open
@@ -74,7 +74,7 @@ int DiskIO::OpenForRead(string filename) {
// Open a disk for reading and writing by filename.
// Returns 1 on success, 0 on failure.
-int DiskIO::OpenForWrite(string filename) {
+int DiskIO::OpenForWrite(const string & filename) {
int retval = 0;
if ((isOpen) && (openForWrite) && ((filename == realFilename) || (filename == userFilename))) {
@@ -151,7 +151,7 @@ int DiskIO::FindAlignment(void) {
} // DiskIO::FindAlignment(int) */
// 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 retval = 1;
diff --git a/diskio.h b/diskio.h
index 8b752ed..b27e977 100644
--- a/diskio.h
+++ b/diskio.h
@@ -18,7 +18,7 @@
#include <string>
#include <stdint.h>
#include <sys/types.h>
-#ifdef MINGW
+#ifdef _WIN32
#include <windows.h>
#include <winioctl.h>
#else
@@ -52,7 +52,7 @@ class DiskIO {
int isOpen;
int openForWrite;
uint8_t *sectorData;
-#ifdef MINGW
+#ifdef _WIN32
HANDLE fd;
#else
int fd;
@@ -62,9 +62,9 @@ class DiskIO {
~DiskIO(void);
void MakeRealName(void);
- int OpenForRead(string filename);
+ int OpenForRead(const string & filename);
int OpenForRead(void);
- int OpenForWrite(string filename);
+ int OpenForWrite(const string & filename);
int OpenForWrite(void);
void Close();
int Seek(uint64_t sector);
@@ -73,7 +73,7 @@ class DiskIO {
void DiskSync(void); // resync disk caches to use new partitions
int GetBlockSize(void);
int FindAlignment(void);
- int FindAlignment(string filename);
+ int FindAlignment(const string & filename);
int IsOpen(void) {return isOpen;}
int IsOpenForWrite(void) {return openForWrite;}
diff --git a/gdisk.8 b/gdisk.8
index b3f4f22..dad9265 100644
--- a/gdisk.8
+++ b/gdisk.8
@@ -2,7 +2,7 @@
.\" May be distributed under the GNU General Public License
.TH "GDISK" "8" "0.5.3" "Roderick W. Smith" "GPT fdisk Manual"
.SH "NAME"
-gdisk \- Interactive GUID partition table (GPT) manipulator for Linux and Unix
+gdisk \- Interactive GUID partition table (GPT) manipulator
.SH "SYNOPSIS"
.BI "gdisk "
[ \-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.
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
-sectors per physical sector with this option. The default is 8, except on
-Linux 2.6.32 and later, in which case it's read from the disk. A value of 8
-will result in a tiny amount of wasted disk space on older disks with true
-512-byte sectors but will otherwise be harmless.
+sectors per physical sector with this option. The default is 1 on disks
+smaller than 800GB and 8 on larger disks.
.TP
.B m
diff --git a/gdisk.cc b/gdisk.cc
index 2329fac..3dddc9e 100644
--- a/gdisk.cc
+++ b/gdisk.cc
@@ -34,6 +34,17 @@ int main(int argc, char* argv[]) {
if (argc == 2) { // basic usage
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]);
if (doMore) {
MainMenu(argv[1], &theGPT);
diff --git a/gpt.cc b/gpt.cc
index e5c9852..3bd56c5 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -239,7 +239,7 @@ int GPTData::Verify(void) {
<< largestSegment << " (" << BytesToSI(largestSegment * (uint64_t) blockSize)
<< ") in size\n";
} else {
- cout << "\nIdentified %d problems!\n", problems;
+ cout << "\nIdentified " << problems << " problems!\n";
} // if/else
return (problems);
@@ -497,7 +497,7 @@ int GPTData::FindOverlaps(void) {
for (i = 1; i < mainHeader.numParts; i++) {
for (j = 0; j < i; j++) {
- if (partitions[i].DoTheyOverlap(&partitions[j])) {
+ if (partitions[i].DoTheyOverlap(partitions[j])) {
problems++;
cout << "\nProblem: partitions " << i + 1 << " and " << j + 1 << " overlap:\n";
cout << " Partition " << i + 1 << ": " << partitions[i].GetFirstLBA()
@@ -550,7 +550,7 @@ void GPTData::PartitionScan(void) {
} // GPTData::PartitionScan()
// Read GPT data from a disk.
-int GPTData::LoadPartitions(string deviceFilename) {
+int GPTData::LoadPartitions(const string & deviceFilename) {
int err;
int allOK = 1, i;
uint64_t firstBlock, lastBlock;
@@ -636,7 +636,7 @@ int GPTData::LoadPartitions(string deviceFilename) {
// succeeded, 0 if there are obvious problems....
int GPTData::ForceLoadGPTData(void) {
int allOK = 1, validHeaders;
- off_t seekTo;
+ uint64_t seekTo;
uint8_t* storage;
uint32_t newCRC, sizeOfParts;
@@ -839,7 +839,7 @@ int GPTData::SaveGPTData(int quiet) {
char answer, line[256];
uint64_t secondTable;
uint32_t numParts;
- off_t offset;
+ uint64_t offset;
if (device == "") {
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....
if (allOK) {
- offset = (off_t) secondTable;
+ offset = (uint64_t) secondTable;
if (myDisk.Seek(offset) != 1) {
allOK = 0;
cerr << "Unable to seek to end of disk! Perhaps the 'e' option on the experts' menu\n"
@@ -998,12 +998,11 @@ int GPTData::SaveGPTData(int quiet) {
// the main GPT header, the backup GPT header, and the main partition
// table; it discards the backup partition table, since it should be
// identical to the main partition table on healthy disks.
-int GPTData::SaveGPTBackup(string filename) {
- int fd, allOK = 1;
+int GPTData::SaveGPTBackup(const string & filename) {
+ int allOK = 1;
uint32_t numParts;
DiskIO backupFile;
-// if ((fd = open(filename, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH)) != -1) {
if (backupFile.OpenForWrite(filename)) {
// Reverse the byte order, if necessary....
numParts = mainHeader.numParts;
@@ -1066,13 +1065,12 @@ int GPTData::SaveGPTBackup(string filename) {
// does minimal error checking. It returns 1 if it completed successfully,
// 0 if there was a problem. In the latter case, it creates a new empty
// set of partitions.
-int GPTData::LoadGPTBackup(string filename) {
- int fd, allOK = 1, val;
+int GPTData::LoadGPTBackup(const string & filename) {
+ int allOK = 1, val;
uint32_t numParts, sizeOfEntries, sizeOfParts, newCRC;
int littleEndian = 1;
DiskIO backupFile;
-// if ((fd = open(filename, O_RDONLY)) != -1) {
if (backupFile.OpenForRead(filename)) {
if (IsLittleEndian() == 0)
littleEndian = 0;
@@ -1473,7 +1471,7 @@ WhichToUse GPTData::UseWhichPartitions(void) {
cout << "\n**********************************************************************\n"
<< "Found invalid GPT and valid BSD disklabel; converting BSD disklabel\n"
<< "to GPT format.";
- if (!justLooking) {
+ if ((!justLooking) && (!beQuiet)) {
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"
<< "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";
} // if
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";
which = use_gpt;
- protectiveMBR.MakeProtectiveMBR();
} // if
if ((state == gpt_valid) && (mbrState == mbr)) {
if (!beQuiet) {
@@ -1506,7 +1503,6 @@ WhichToUse GPTData::UseWhichPartitions(void) {
which = use_mbr;
} else if (answer == 2) {
which = use_gpt;
- protectiveMBR.MakeProtectiveMBR();
cout << "Using GPT and creating fresh protective MBR.\n";
} else which = use_new;
} else which = use_abort;
@@ -1612,7 +1608,7 @@ int GPTData::XFormDisklabel(int i) {
// If all is OK, read the disklabel and convert it.
if (goOn) {
- goOn = disklabel.ReadBSDData(&myDisk, partitions[partNum].GetFirstLBA(),
+ goOn = disklabel.ReadBSDData(device, partitions[partNum].GetFirstLBA(),
partitions[partNum].GetLastLBA());
if ((goOn) && (disklabel.IsDisklabel())) {
numDone = XFormDisklabel(&disklabel, startPart);
@@ -2053,7 +2049,7 @@ void GPTData::MoveSecondHeaderToEnd() {
secondHeader.partitionEntriesLBA = secondHeader.lastUsableLBA + UINT64_C(1);
} // GPTData::FixSecondHeaderLocation()
-int GPTData::SetName(uint32_t partNum, string theName) {
+int GPTData::SetName(uint32_t partNum, const string & theName) {
int retval = 1;
if (!IsFreePartNum(partNum)) {
diff --git a/gpt.h b/gpt.h
index 76f1678..e1780a1 100644
--- a/gpt.h
+++ b/gpt.h
@@ -93,15 +93,15 @@ public:
int FindOverlaps(void);
// 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);
- int LoadPartitions(string deviceFilename);
+ int LoadPartitions(const string & deviceFilename);
int ForceLoadGPTData(void);
int LoadMainTable(void);
int LoadSecondTableAsMain(void);
int SaveGPTData(int quiet = 0);
- int SaveGPTBackup(string filename);
- int LoadGPTBackup(string filename);
+ int SaveGPTBackup(const string & filename);
+ int LoadGPTBackup(const string & filename);
// Display data....
void ShowAPMState(void);
@@ -137,7 +137,7 @@ public:
void SortGPT(void);
int ClearGPTData(void);
void MoveSecondHeaderToEnd();
- int SetName(uint32_t partNum, string theName = "");
+ int SetName(uint32_t partNum, const string & theName = "");
void SetDiskGUID(GUIDData newGUID);
int SetPartitionGUID(uint32_t pn, GUIDData theGUID);
int ChangePartType(uint32_t pn, uint16_t hexCode);
@@ -170,7 +170,7 @@ public:
WhichToUse WhichWasUsed(void) {return whichWasUsed;}
// Endianness functions
- void ReverseHeaderBytes(struct GPTHeader* header); // for endianness
+ void ReverseHeaderBytes(struct GPTHeader* header);
void ReversePartitionBytes(); // for endianness
}; // class GPTData
diff --git a/gptpart.cc b/gptpart.cc
index c6504c1..29b2df9 100644
--- a/gptpart.cc
+++ b/gptpart.cc
@@ -35,17 +35,6 @@ GPTPart::GPTPart(void) {
GPTPart::~GPTPart(void) {
} // 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
uint16_t GPTPart::GetHexType(void) {
return typeHelper.GUIDToID(partitionType);
@@ -66,18 +55,30 @@ uint64_t GPTPart::GetLengthLBA(void) {
return length;
} // 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;
- 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
+ theName = "";
+ for (i = 0; i < NAME_SIZE; i += 2) {
+ if (name[i] != '\0')
+ theName += name[i];
+ } // for
+ return theName;
+} // GPTPart::GetName()
+
+// 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,
// depending on the parameter: 0 = 0, anything else = random
@@ -93,47 +94,54 @@ void GPTPart::SetUniqueGUID(int zeroOrRandom) {
}
} // GPTPart::SetUniqueGUID()
-// Blank (delete) a single partition
-void GPTPart::BlankPartition(void) {
- int j;
- GUIDData zeroGUID;
+// 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
+// string. This function creates a simple-minded copy for this.
+void GPTPart::SetName(const string & theName) {
+ char newName[NAME_SIZE]; // New name
+ char *junk;
+ int i;
- 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
+ // Blank out new name string, just to be on the safe side....
+ for (i = 0; i < NAME_SIZE; i++)
+ newName[i] = '\0';
-// Returns 1 if the two partitions overlap, 0 if they don't
-int GPTPart::DoTheyOverlap(GPTPart* other) {
- int theyDo = 0;
+ if (theName == "") { // No name specified, so get one from the user
+ cout << "Enter name: ";
+ junk = fgets(newName, NAME_SIZE / 2, stdin);
- // 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;
+ // Input is likely to include a newline, so remove it....
+ i = strlen(newName);
+ if (newName[i - 1] == '\n')
+ newName[i - 1] = '\0';
+ } else {
+ strcpy(newName, theName.substr(0, NAME_SIZE / 2).c_str());
} // 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()
+ // Copy the C-style ASCII string from newName into a form that the GPT
+ // table will accept....
+ for (i = 0; i < NAME_SIZE; i++) {
+ if ((i % 2) == 0) {
+ name[i] = newName[(i / 2)];
+ } else {
+ name[i] = '\0';
+ } // if/else
+ } // for
+} // 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) {
@@ -155,7 +163,7 @@ void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
cout.setf(ios::uppercase);
cout << hex << typeHelper.GUIDToID(partitionType) << " " << dec;
cout.fill(' ');
- cout.setf(ios::right);
+// cout.setf(ios::right);
cout << GetName().substr(0, 23) << "\n";
cout.fill(' ');
} // if
@@ -172,24 +180,65 @@ void GPTPart::ShowDetails(uint32_t blockSize) {
cout << "Partition unique GUID: " << GUIDToStr(uniqueGUID) << "\n";
cout << "First sector: " << firstLBA << " (at "
- << BytesToSI(firstLBA * blockSize) << ")\n";
+ << BytesToSI(firstLBA * blockSize) << ")\n";
cout << "Last sector: " << lastLBA << " (at "
- << BytesToSI(lastLBA * blockSize) << ")\n";
+ << BytesToSI(lastLBA * blockSize) << ")\n";
size = (lastLBA - firstLBA + 1);
cout << "Partition size: " << size << " sectors ("
- << BytesToSI(size * ((uint64_t) blockSize)) << ")\n";
+ << 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";
+ 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 *
****************************************/
@@ -216,46 +265,10 @@ void GPTPart::ChangeType(void) {
newType = typeHelper.IDToGUID((uint16_t) typeNum);
else // user wants to enter the GUID directly, so do that
newType = GetGUID();
- partitionType = newType;
+ SetType(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
-// theName is empty. Note that theName is a standard C++-style ASCII
-// string, although the GUID partition definition requires a UTF-16LE
-// string. This function creates a simple-minded copy for this.
-void GPTPart::SetName(string theName) {
- char newName[NAME_SIZE]; // New name
- char *junk;
- int i;
-
- // Blank out new name string, just to be on the safe side....
- for (i = 0; i < NAME_SIZE; i++)
- newName[i] = '\0';
-
- if (theName == "") { // No name specified, so get one from the user
- cout << "Enter name: ";
- junk = fgets(newName, NAME_SIZE / 2, stdin);
-
- // Input is likely to include a newline, so remove it....
- i = strlen(newName);
- if (newName[i - 1] == '\n')
- newName[i - 1] = '\0';
- } else {
- strcpy(newName, theName.substr(0, NAME_SIZE / 2).c_str());
- } // if
-
- // Copy the C-style ASCII string from newName into a form that the GPT
- // table will accept....
- for (i = 0; i < NAME_SIZE; i++) {
- if ((i % 2) == 0) {
- name[i] = newName[(i / 2)];
- } else {
- name[i] = '\0';
- } // if/else
- } // for
-} // GPTPart::SetName()
-
/***********************************
* Non-class but related functions *
***********************************/
diff --git a/gptpart.h b/gptpart.h
index dc499b9..d24ed87 100644
--- a/gptpart.h
+++ b/gptpart.h
@@ -62,21 +62,21 @@ class GPTPart {
string GetName(void);
// Simple data assignment:
- void SetType(struct GUIDData t) {partitionType = t;}
- void SetType(uint16_t hex) {partitionType = typeHelper.IDToGUID(hex);}
+ 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 SetFirstLBA(uint64_t f) {firstLBA = f;}
void SetLastLBA(uint64_t l) {lastLBA = l;}
void SetAttributes(uint64_t a) {attributes = a;}
- void SetName(string n);
+ void SetName(const string & n);
// Additional functions
GPTPart & operator=(const GPTPart & orig);
void ShowSummary(int partNum, uint32_t blockSize); // display summary information (1-line)
void ShowDetails(uint32_t blockSize); // display detailed information (multi-line)
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
// Functions requiring user interaction
diff --git a/mbr.cc b/mbr.cc
index 411cae5..b1daa3c 100644
--- a/mbr.cc
+++ b/mbr.cc
@@ -38,6 +38,7 @@ MBRData::MBRData(void) {
srand((unsigned int) time(NULL));
numHeads = MAX_HEADS;
numSecspTrack = MAX_SECSPERTRACK;
+ myDisk = NULL;
EmptyMBR();
} // MBRData default constructor
@@ -48,6 +49,7 @@ MBRData::MBRData(string filename) {
state = invalid;
numHeads = MAX_HEADS;
numSecspTrack = MAX_SECSPERTRACK;
+ myDisk = NULL;
srand((unsigned int) time(NULL));
// Try to read the specified partition table, but if it fails....
@@ -55,9 +57,10 @@ MBRData::MBRData(string filename) {
EmptyMBR();
device = "";
} // if
-} // MBRData(char *filename) constructor
+} // MBRData(string filename) constructor
MBRData::~MBRData(void) {
+// delete myDisk;
} // MBRData destructor
/**********************
@@ -68,9 +71,11 @@ MBRData::~MBRData(void) {
// Read data from MBR. Returns 1 if read was successful (even if the
// 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;
+ if (myDisk == NULL)
+ myDisk = new DiskIO;
if (myDisk->OpenForRead(deviceFilename)) {
ReadMBRData(myDisk);
} else {
@@ -81,7 +86,7 @@ int MBRData::ReadMBRData(string deviceFilename) {
device = deviceFilename;
return allOK;
-} // MBRData::ReadMBRData(char* deviceFilename)
+} // MBRData::ReadMBRData(const string & deviceFilename)
// Read data from MBR. If checkBlockSize == 1 (the default), the block
// 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;
TempMBR tempMBR;
+ if (myDisk != NULL)
+ delete myDisk;
+
myDisk = theDisk;
// Empty existing MBR data, including the logical partitions...
@@ -102,7 +110,7 @@ void MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
if (myDisk->Read(&tempMBR, 512))
err = 0;
if (err) {
- cerr << "Problem reading disk in MBRData::ReadMBRData!\n";
+ cerr << "Problem reading disk in MBRData::ReadMBRData()!\n";
} else {
for (i = 0; i < 440; i++)
code[i] = tempMBR.code[i];
@@ -183,7 +191,7 @@ void MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
} // for
} // if (hybrid detection code)
} // 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
// 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
// ONLY the MBR itself, not the logical partition data.
int MBRData::WriteMBRData(void) {
- int allOK = 1, fd;
+ int allOK = 1;
- if (myDisk->OpenForWrite(device) != 0) {
- allOK = WriteMBRData(myDisk);
- } else {
- allOK = 0;
- } // if/else
- myDisk->Close();
+ if (myDisk != NULL) {
+ if (myDisk->OpenForWrite(device) != 0) {
+ allOK = WriteMBRData(myDisk);
+ } else {
+ allOK = 0;
+ } // if/else
+ myDisk->Close();
+ } else allOK = 0;
return allOK;
} // MBRData::WriteMBRData(void)
@@ -322,12 +332,12 @@ int MBRData::WriteMBRData(DiskIO *theDisk) {
} // for
}// if
return allOK;
-} // MBRData::WriteMBRData(DiskIO theDisk)
+} // MBRData::WriteMBRData(DiskIO *theDisk)
-int MBRData::WriteMBRData(string deviceFilename) {
+int MBRData::WriteMBRData(const string & deviceFilename) {
device = deviceFilename;
return WriteMBRData();
-} // MBRData::WriteMBRData(char* deviceFilename)
+} // MBRData::WriteMBRData(const string & deviceFilename)
/********************************************
* *
diff --git a/mbr.h b/mbr.h
index 9fc749b..e83de7e 100644
--- a/mbr.h
+++ b/mbr.h
@@ -80,7 +80,7 @@ public:
~MBRData(void);
// File I/O functions...
- int ReadMBRData(string deviceFilename);
+ int ReadMBRData(const string & deviceFilename);
void ReadMBRData(DiskIO * theDisk, int checkBlockSize = 1);
// ReadLogicalPart() returns last partition # read to logicals[] array,
// or -1 if there was a problem....
@@ -88,7 +88,7 @@ public:
int partNum);
int WriteMBRData(void);
int WriteMBRData(DiskIO *theDisk);
- int WriteMBRData(string deviceFilename);
+ int WriteMBRData(const string & deviceFilename);
// Display data for user...
void DisplayMBRData(void);
diff --git a/parttypes.cc b/parttypes.cc
index d4e4a92..2593caa 100644
--- a/parttypes.cc
+++ b/parttypes.cc
@@ -236,6 +236,7 @@ int PartTypes::AddType(uint16_t mbrType, uint64_t guidData1, uint64_t guidData2,
// in an ugly way.
void PartTypes::ShowTypes(void) {
int colCount = 1; // column count
+ int i;
AType* thisType = allTypes;
cout.unsetf(ios::uppercase);
@@ -244,17 +245,16 @@ void PartTypes::ShowTypes(void) {
cout.fill('0');
cout.width(4);
cout << hex << thisType->MBRType << " ";
- cout.fill(' ');
- cout.setf(ios::left);
- cout.width(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)
cout << "\n";
colCount++;
} // if
thisType = thisType->next;
} // while
- cout << "\n";
+ cout.fill(' ');
+ cout << "\n" << dec;
} // PartTypes::ShowTypes()
// 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.width(4);
cout << hex << ID << "; assigning type code for\n'Linux/Windows data'\n" << dec;
+ cout.fill(' ');
} // if (!found)
return theGUID;
} // PartTypes::IDToGUID()