Misc. updates and bug fixes
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
0.6.2 (?/??/2010):
|
||||
------------------
|
||||
|
||||
- Fixed bug that caused new protective MBR to not be created when the
|
||||
MBR was invalid and the GPT was damaged and the user opts to try to
|
||||
use the GPT data.
|
||||
|
||||
- Enabled default partition type code of 0700 when creating partitions
|
||||
or changing their type codes. (Type 0700, Linux/Windows data, is set if
|
||||
the user hits the Enter key alone.)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include "attributes.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -25,14 +26,14 @@ Attributes::Attributes(void) {
|
||||
// appropriate name
|
||||
for (i = 1; i < NUM_ATR; i++) {
|
||||
sprintf(temp, "Undefined bit #%d", i);
|
||||
strcpy(atNames[i], temp);
|
||||
atNames[i] = temp;
|
||||
} // for
|
||||
|
||||
// Now reset those names that are defined....
|
||||
strcpy(atNames[0], "system partition");
|
||||
strcpy(atNames[60], "read-only");
|
||||
strcpy(atNames[62], "hidden");
|
||||
strcpy(atNames[63], "do not automount");
|
||||
atNames[0] = "system partition";
|
||||
atNames[60] = "read-only";
|
||||
atNames[62] = "hidden";
|
||||
atNames[63] = "do not automount";
|
||||
} // Attributes constructor
|
||||
|
||||
// Destructor.
|
||||
@@ -43,16 +44,18 @@ Attributes::~Attributes(void) {
|
||||
void Attributes::DisplayAttributes(void) {
|
||||
int i;
|
||||
|
||||
printf("Attribute value is %llX. Set fields are:\n",
|
||||
(unsigned long long) attributes);
|
||||
cout << "Attribute value is ";
|
||||
cout.setf(ios::uppercase);
|
||||
cout.fill('0');
|
||||
cout.width(16);
|
||||
cout << hex << attributes << dec << ". Set fields are:\n";
|
||||
for (i = 0; i < NUM_ATR; i++) {
|
||||
if (((attributes >> i) % 2) == 1) { // bit is set
|
||||
/* if (strncmp("Undefined", atNames[i], 9) != 0)
|
||||
printf("%s\n", atNames[i]); */
|
||||
if (strncmp("Undefined", atNames[NUM_ATR - i - 1], 9) != 0)
|
||||
printf("%s\n", atNames[NUM_ATR - i - 1]);
|
||||
if (atNames[NUM_ATR - i - 1].substr(0, 9) != "Undefined")
|
||||
cout << atNames[NUM_ATR - i - 1] << "\n";
|
||||
} // if
|
||||
} // for
|
||||
cout.fill(' ');
|
||||
} // Attributes::DisplayAttributes()
|
||||
|
||||
// Prompt user for attribute changes
|
||||
@@ -60,23 +63,22 @@ void Attributes::ChangeAttributes(void) {
|
||||
int response, i;
|
||||
uint64_t bitValue;
|
||||
|
||||
printf("Known attributes are:\n");
|
||||
cout << "Known attributes are:\n";
|
||||
for (i = 0; i < NUM_ATR; i++) {
|
||||
if (strncmp("Undefined", atNames[i], 9) != 0)
|
||||
printf("%d - %s\n", i, atNames[i]);
|
||||
if (atNames[i].substr(0, 9) != "Undefined")
|
||||
cout << i << " - " << atNames[i] << "\n";
|
||||
} // for
|
||||
|
||||
do {
|
||||
response = GetNumber(0, 64, -1, "Toggle which attribute field (0-63, 64 to exit): ");
|
||||
response = GetNumber(0, 64, -1, (string) "Toggle which attribute field (0-63, 64 to exit): ");
|
||||
if (response != 64) {
|
||||
bitValue = PowerOf2(NUM_ATR - response - 1); // Find the integer value of the bit
|
||||
// bitValue = PowerOf2(response); // Find the integer value of the bit
|
||||
if ((bitValue & attributes) == bitValue) { // bit is set
|
||||
attributes -= bitValue; // so unset it
|
||||
printf("Have disabled the '%s' attribute.\n", atNames[response]);
|
||||
cout << "Have disabled the '" << atNames[response] << "' attribute.\n";
|
||||
} else { // bit is not set
|
||||
attributes += bitValue; // so set it
|
||||
printf("Have enabled the '%s' attribute.\n", atNames[response]);
|
||||
cout << "Have enabled the '" << atNames[response] << "' attribute.\n";
|
||||
} // if/else
|
||||
} // if
|
||||
} while (response != 64);
|
||||
|
||||
@@ -18,7 +18,7 @@ using namespace std;
|
||||
class Attributes {
|
||||
protected:
|
||||
uint64_t attributes;
|
||||
char atNames[NUM_ATR][ATR_NAME_SIZE];
|
||||
string atNames[NUM_ATR];
|
||||
public:
|
||||
Attributes(void);
|
||||
~Attributes(void);
|
||||
|
||||
115
bsd.cc
115
bsd.cc
@@ -14,9 +14,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "support.h"
|
||||
#include "bsd.h"
|
||||
|
||||
@@ -41,39 +42,30 @@ 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.
|
||||
int BSDData::ReadBSDData(char* device, uint64_t startSector, uint64_t endSector) {
|
||||
int allOK = 1, tempMyDisk = 0;
|
||||
// the bulk of the work. Returns 1 on success, 0 on failure.
|
||||
int BSDData::ReadBSDData(string *device, uint64_t startSector, uint64_t endSector) {
|
||||
int allOK = 1;
|
||||
DiskIO myDisk;
|
||||
|
||||
if (device != NULL) {
|
||||
if (myDisk == NULL) {
|
||||
myDisk = new DiskIO;
|
||||
tempMyDisk = 1;
|
||||
} // if
|
||||
if (myDisk->OpenForRead(device)) {
|
||||
ReadBSDData(myDisk, startSector, endSector);
|
||||
if (*device != "") {
|
||||
if (myDisk.OpenForRead(*device)) {
|
||||
allOK = ReadBSDData(&myDisk, startSector, endSector);
|
||||
} else {
|
||||
allOK = 0;
|
||||
} // if/else
|
||||
|
||||
myDisk->Close();
|
||||
myDisk.Close();
|
||||
} else {
|
||||
allOK = 0;
|
||||
} // if/else
|
||||
|
||||
if (tempMyDisk) {
|
||||
delete myDisk;
|
||||
myDisk = NULL;
|
||||
} // if
|
||||
|
||||
return allOK;
|
||||
} // BSDData::ReadBSDData() (device filename version)
|
||||
|
||||
// Load the BSD disklabel data from an already-opened disk
|
||||
// file, starting with the specified sector number.
|
||||
void BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSector) {
|
||||
int BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSector) {
|
||||
uint8_t buffer[4096]; // I/O buffer
|
||||
int i, err, foundSig = 0, bigEnd = 0;
|
||||
int i, err, foundSig = 0, bigEnd = 0, allOK = 1;
|
||||
int relative = 0; // assume absolute partition sector numbering
|
||||
uint32_t realSig;
|
||||
uint32_t* temp32;
|
||||
@@ -81,54 +73,59 @@ void BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSec
|
||||
BSDRecord* tempRecords;
|
||||
int offset[NUM_OFFSETS] = { LABEL_OFFSET1, LABEL_OFFSET2 };
|
||||
|
||||
myDisk = theDisk;
|
||||
// myDisk = theDisk;
|
||||
labelFirstLBA = startSector;
|
||||
labelLastLBA = endSector;
|
||||
offset[1] = myDisk->GetBlockSize();
|
||||
offset[1] = theDisk->GetBlockSize();
|
||||
|
||||
// Read 4096 bytes (eight 512-byte sectors or equivalent)
|
||||
// into memory; we'll extract data from this buffer.
|
||||
// (Done to work around FreeBSD limitation on size of reads
|
||||
// from block devices.)
|
||||
myDisk->Seek(startSector /* * myDisk->GetBlockSize() */);
|
||||
myDisk->Read(buffer, 4096);
|
||||
allOK = theDisk->Seek(startSector);
|
||||
if (allOK) allOK = theDisk->Read(buffer, 4096);
|
||||
|
||||
// Do some strangeness to support big-endian architectures...
|
||||
bigEnd = (IsLittleEndian() == 0);
|
||||
realSig = BSD_SIGNATURE;
|
||||
if (bigEnd)
|
||||
if (bigEnd && allOK)
|
||||
ReverseBytes(&realSig, 4);
|
||||
|
||||
// Look for the signature at any of two locations.
|
||||
// Note that the signature is repeated at both the original
|
||||
// offset and 132 bytes later, so we need two checks....
|
||||
i = 0;
|
||||
do {
|
||||
temp32 = (uint32_t*) &buffer[offset[i]];
|
||||
signature = *temp32;
|
||||
if (signature == realSig) { // found first, look for second
|
||||
temp32 = (uint32_t*) &buffer[offset[i] + 132];
|
||||
signature2 = *temp32;
|
||||
if (signature2 == realSig) {
|
||||
foundSig = 1;
|
||||
labelStart = offset[i];
|
||||
} // if found signature
|
||||
} // if/else
|
||||
i++;
|
||||
} while ((!foundSig) && (i < NUM_OFFSETS));
|
||||
if (allOK) {
|
||||
i = 0;
|
||||
do {
|
||||
temp32 = (uint32_t*) &buffer[offset[i]];
|
||||
signature = *temp32;
|
||||
if (signature == realSig) { // found first, look for second
|
||||
temp32 = (uint32_t*) &buffer[offset[i] + 132];
|
||||
signature2 = *temp32;
|
||||
if (signature2 == realSig) {
|
||||
foundSig = 1;
|
||||
labelStart = offset[i];
|
||||
} // if found signature
|
||||
} // if/else
|
||||
i++;
|
||||
} while ((!foundSig) && (i < NUM_OFFSETS));
|
||||
allOK = foundSig;
|
||||
} // if
|
||||
|
||||
// Load partition metadata from the buffer....
|
||||
temp32 = (uint32_t*) &buffer[labelStart + 40];
|
||||
sectorSize = *temp32;
|
||||
temp16 = (uint16_t*) &buffer[labelStart + 138];
|
||||
numParts = *temp16;
|
||||
if (allOK) {
|
||||
temp32 = (uint32_t*) &buffer[labelStart + 40];
|
||||
sectorSize = *temp32;
|
||||
temp16 = (uint16_t*) &buffer[labelStart + 138];
|
||||
numParts = *temp16;
|
||||
} // if
|
||||
|
||||
// Make it big-endian-aware....
|
||||
if (IsLittleEndian() == 0)
|
||||
if ((IsLittleEndian() == 0) && allOK)
|
||||
ReverseMetaBytes();
|
||||
|
||||
// Check validity of the data and flag it appropriately....
|
||||
if (foundSig && (numParts <= MAX_BSD_PARTS)) {
|
||||
if (foundSig && (numParts <= MAX_BSD_PARTS) && allOK) {
|
||||
state = bsd;
|
||||
} else {
|
||||
state = bsd_invalid;
|
||||
@@ -167,7 +164,8 @@ void BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSec
|
||||
} // if
|
||||
} // if signatures OK
|
||||
// DisplayBSDData();
|
||||
} // BSDData::ReadBSDData(int fd, uint64_t startSector)
|
||||
return allOK;
|
||||
} // BSDData::ReadBSDData(DiskIO* theDisk, uint64_t startSector)
|
||||
|
||||
// Reverse metadata's byte order; called only on big-endian systems
|
||||
void BSDData::ReverseMetaBytes(void) {
|
||||
@@ -182,12 +180,19 @@ void BSDData::DisplayBSDData(void) {
|
||||
int i;
|
||||
|
||||
if (state == bsd) {
|
||||
printf("BSD partitions:\n");
|
||||
printf("Number\t Start (sector)\t Length (sectors)\tType\n");
|
||||
cout << "BSD partitions:\n";
|
||||
for (i = 0; i < numParts; i++) {
|
||||
printf("%4d\t%13lu\t%15lu \t0x%02X\n", i + 1,
|
||||
(unsigned long) partitions[i].firstLBA,
|
||||
(unsigned long) partitions[i].lengthLBA, partitions[i].fsType);
|
||||
cout.width(4);
|
||||
cout << i + 1 << "\t";
|
||||
cout.width(13);
|
||||
cout << partitions[i].firstLBA << "\t";
|
||||
cout.width(15);
|
||||
cout << partitions[i].lengthLBA << " \t0x";
|
||||
cout.width(2);
|
||||
cout.fill('0');
|
||||
cout.setf(ios::uppercase);
|
||||
cout << hex << (int) partitions[i].fsType << "\n" << dec;
|
||||
cout.fill(' ');
|
||||
} // for
|
||||
} // if
|
||||
} // BSDData::DisplayBSDData()
|
||||
@@ -199,14 +204,14 @@ int BSDData::ShowState(void) {
|
||||
|
||||
switch (state) {
|
||||
case bsd_invalid:
|
||||
printf(" BSD: not present\n");
|
||||
cout << " BSD: not present\n";
|
||||
break;
|
||||
case bsd:
|
||||
printf(" BSD: present\n");
|
||||
cout << " BSD: present\n";
|
||||
retval = 1;
|
||||
break;
|
||||
default:
|
||||
printf("\a BSD: unknown -- bug!\n");
|
||||
cout << "\a BSD: unknown -- bug!\n";
|
||||
break;
|
||||
} // switch
|
||||
return retval;
|
||||
@@ -318,7 +323,7 @@ GPTPart BSDData::AsGPT(int i) {
|
||||
guid.SetType(0x0700); break;
|
||||
} // switch
|
||||
// Set the partition name to the name of the type code....
|
||||
guid.SetName((unsigned char*) guid.GetNameType().c_str());
|
||||
guid.SetName(guid.GetNameType());
|
||||
} // if
|
||||
return guid;
|
||||
} // BSDData::AsGPT()
|
||||
|
||||
5
bsd.h
5
bsd.h
@@ -69,12 +69,11 @@ class BSDData {
|
||||
uint64_t labelLastLBA; // final sector of BSD disklabel
|
||||
uint64_t labelStart; // BSD disklabel start point in bytes from labelFirstLBA
|
||||
BSDValidity state;
|
||||
DiskIO *myDisk;
|
||||
public:
|
||||
BSDData(void);
|
||||
~BSDData(void);
|
||||
int ReadBSDData(char* deviceFilename, uint64_t startSector, uint64_t endSector);
|
||||
void ReadBSDData(DiskIO *myDisk, uint64_t startSector, uint64_t endSector);
|
||||
int ReadBSDData(string *deviceFilename, uint64_t startSector, uint64_t endSector);
|
||||
int ReadBSDData(DiskIO *myDisk, uint64_t startSector, uint64_t endSector);
|
||||
void ReverseMetaBytes(void);
|
||||
void DisplayBSDData(void);
|
||||
int ShowState(void); // returns 1 if BSD disklabel detected
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <sys/stat.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "support.h"
|
||||
#include "diskio.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -50,10 +49,9 @@ int DiskIO::OpenForRead(void) {
|
||||
if (shouldOpen) {
|
||||
fd = open(realFilename.c_str(), O_RDONLY);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Problem opening %s for reading! Error is %d\n",
|
||||
realFilename.c_str(), errno);
|
||||
cerr << "Problem opening " << realFilename << " for reading! Error is " << errno << "\n";
|
||||
if (errno == EACCES) { // User is probably not running as root
|
||||
fprintf(stderr, "You must run this program as root or use sudo!\n");
|
||||
cerr << "You must run this program as root or use sudo!\n";
|
||||
} // if
|
||||
realFilename = "";
|
||||
userFilename = "";
|
||||
@@ -82,7 +80,7 @@ int DiskIO::OpenForWrite(void) {
|
||||
#ifdef __APPLE__
|
||||
// MacOS X requires a shared lock under some circumstances....
|
||||
if (fd < 0) {
|
||||
fd = open(realFilename.c_str(), O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH | O_SHLOCK);
|
||||
fd = open(realFilename.c_str(), O_WRONLY | O_SHLOCK);
|
||||
} // if
|
||||
#endif
|
||||
if (fd >= 0) {
|
||||
@@ -133,8 +131,8 @@ int DiskIO::GetBlockSize(void) {
|
||||
// 32-bit code returns EINVAL, I don't know why. I know I'm treading on
|
||||
// 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",
|
||||
errno, SECTOR_SIZE);
|
||||
cerr << "\aError " << errno << " when determining sector size! Setting sector size to "
|
||||
<< SECTOR_SIZE << "\n";
|
||||
} // if
|
||||
} // if (err == -1)
|
||||
} // if (isOpen)
|
||||
@@ -155,8 +153,8 @@ void DiskIO::DiskSync(void) {
|
||||
if (isOpen) {
|
||||
sync();
|
||||
#ifdef __APPLE__
|
||||
printf("Warning: The kernel may continue to use old or deleted partitions.\n"
|
||||
"You should reboot or remove the drive.\n");
|
||||
cout << "Warning: The kernel may continue to use old or deleted partitions.\n"
|
||||
<< "You should reboot or remove the drive.\n";
|
||||
/* don't know if this helps
|
||||
* it definitely will get things on disk though:
|
||||
* http://topiks.org/mac-os-x/0321278542/ch12lev1sec8.html */
|
||||
@@ -166,22 +164,22 @@ void DiskIO::DiskSync(void) {
|
||||
#ifdef __FreeBSD__
|
||||
sleep(2);
|
||||
i = ioctl(fd, DIOCGFLUSH);
|
||||
printf("Warning: The kernel may continue to use old or deleted partitions.\n"
|
||||
"You should reboot or remove the drive.\n");
|
||||
cout << "Warning: The kernel may continue to use old or deleted partitions.\n"
|
||||
<< "You should reboot or remove the drive.\n";
|
||||
platformFound++;
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
sleep(2);
|
||||
i = ioctl(fd, BLKRRPART);
|
||||
if (i)
|
||||
printf("Warning: The kernel is still using the old partition table.\n"
|
||||
"The new table will be used at the next reboot.\n");
|
||||
cout << "Warning: The kernel is still using the old partition table.\n"
|
||||
<< "The new table will be used at the next reboot.\n";
|
||||
platformFound++;
|
||||
#endif
|
||||
if (platformFound == 0)
|
||||
fprintf(stderr, "Warning: Platform not recognized!\n");
|
||||
cerr << "Warning: Platform not recognized!\n";
|
||||
if (platformFound > 1)
|
||||
fprintf(stderr, "\nWarning: We seem to be running on multiple platforms!\n");
|
||||
cerr << "\nWarning: We seem to be running on multiple platforms!\n";
|
||||
} // if (isOpen)
|
||||
} // DiskIO::DiskSync()
|
||||
|
||||
@@ -233,9 +231,6 @@ int DiskIO::Read(void* buffer, int numBytes) {
|
||||
// Read the data into temporary space, then copy it to buffer
|
||||
retval = read(fd, tempSpace, numBlocks * blockSize);
|
||||
memcpy(buffer, tempSpace, numBytes);
|
||||
/* for (i = 0; i < numBytes; i++) {
|
||||
((char*) buffer)[i] = tempSpace[i];
|
||||
} // for */
|
||||
|
||||
// Adjust the return value, if necessary....
|
||||
if (((numBlocks * blockSize) != numBytes) && (retval > 0))
|
||||
@@ -347,7 +342,7 @@ uint64_t DiskIO::DiskSize(int *err) {
|
||||
platformFound++;
|
||||
#endif
|
||||
if (platformFound != 1)
|
||||
fprintf(stderr, "Warning! We seem to be running on no known platform!\n");
|
||||
cerr << "Warning! We seem to be running on no known platform!\n";
|
||||
|
||||
// The above methods have failed, so let's assume it's a regular
|
||||
// file (a QEMU image, dd backup, or what have you) and see what
|
||||
@@ -356,8 +351,8 @@ uint64_t DiskIO::DiskSize(int *err) {
|
||||
if (fstat64(fd, &st) == 0) {
|
||||
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");
|
||||
cerr << "Warning: File size is not a multiple of 512 bytes!"
|
||||
<< " Misbehavior is likely!\n\a";
|
||||
sectors = bytes / UINT64_C(512);
|
||||
} // if
|
||||
} // if
|
||||
|
||||
@@ -114,11 +114,11 @@ int DiskIO::FindAlignment(void) {
|
||||
int err = -2, errnum = 0, result = 8, physicalSectorSize = 4096;
|
||||
uint64_t diskSize;
|
||||
|
||||
printf("Entering FindAlignment()\n");
|
||||
cout << "Entering FindAlignment()\n";
|
||||
#if defined (__linux__) && defined (BLKPBSZGET)
|
||||
err = ioctl(fd, BLKPBSZGET, &physicalSectorSize);
|
||||
printf("In FindAlignment(), physicalSectorSize = %d, err = %d\n", physicalSectorSize, err);
|
||||
// printf("Tried to get hardware alignment; err is %d, sector size is %d\n", err, physicalSectorSize);
|
||||
cout << "In FindAlignment(), physicalSectorSize = " << physicalSectorSize
|
||||
<< ", err = " << err << "\n";
|
||||
#else
|
||||
err = -1;
|
||||
#endif
|
||||
|
||||
2
diskio.h
2
diskio.h
@@ -59,10 +59,8 @@ class DiskIO {
|
||||
#endif
|
||||
public:
|
||||
DiskIO(void);
|
||||
// DiskIO(const DiskIO & orig);
|
||||
~DiskIO(void);
|
||||
|
||||
// DiskIO & operator=(const DiskIO & orig);
|
||||
void MakeRealName(void);
|
||||
int OpenForRead(string filename);
|
||||
int OpenForRead(void);
|
||||
|
||||
185
gdisk.cc
185
gdisk.cc
@@ -9,18 +9,20 @@
|
||||
|
||||
//#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "mbr.h"
|
||||
#include "gpt.h"
|
||||
#include "support.h"
|
||||
|
||||
// Function prototypes....
|
||||
void MainMenu(char* filename, struct GPTData* theGPT);
|
||||
void MainMenu(string filename, struct GPTData* theGPT);
|
||||
void ShowCommands(void);
|
||||
void ExpertsMenu(char* filename, struct GPTData* theGPT);
|
||||
void ExpertsMenu(string filename, struct GPTData* theGPT);
|
||||
void ShowExpertCommands(void);
|
||||
void RecoveryMenu(char* filename, struct GPTData* theGPT);
|
||||
void RecoveryMenu(string filename, struct GPTData* theGPT);
|
||||
void ShowRecoveryCommands(void);
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
@@ -28,7 +30,7 @@ int main(int argc, char* argv[]) {
|
||||
int doMore = 1;
|
||||
char* device = NULL;
|
||||
|
||||
printf("GPT fdisk (gdisk) version %s\n\n", GPTFDISK_VERSION);
|
||||
cout << "GPT fdisk (gdisk) version " << GPTFDISK_VERSION << "\n\n";
|
||||
|
||||
if (argc == 2) { // basic usage
|
||||
if (SizesOK()) {
|
||||
@@ -44,22 +46,22 @@ int main(int argc, char* argv[]) {
|
||||
} else if (strcmp(argv[2], "-l") == 0) {
|
||||
device = argv[1];
|
||||
} else { // 3 arguments, but none is "-l"
|
||||
fprintf(stderr, "Usage: %s [-l] device_file\n", argv[0]);
|
||||
cerr << "Usage: " << argv[0] << " [-l] device_file\n";
|
||||
} // if/elseif/else
|
||||
if (device != NULL) {
|
||||
theGPT.JustLooking();
|
||||
doMore = theGPT.LoadPartitions(device);
|
||||
doMore = theGPT.LoadPartitions((string) device);
|
||||
if (doMore) theGPT.DisplayGPTData();
|
||||
} // if
|
||||
} // if
|
||||
} else {
|
||||
fprintf(stderr, "Usage: %s [-l] device_file\n", argv[0]);
|
||||
cerr << "Usage: " << argv[0] << " [-l] device_file\n";
|
||||
} // if/else
|
||||
} // main
|
||||
|
||||
// Accept a command and execute it. Returns only when the user
|
||||
// wants to exit (such as after a 'w' or 'q' command).
|
||||
void MainMenu(char* filename, struct GPTData* theGPT) {
|
||||
void MainMenu(string filename, struct GPTData* theGPT) {
|
||||
char command, line[255], buFile[255];
|
||||
char* junk;
|
||||
int goOn = 1;
|
||||
@@ -67,12 +69,14 @@ void MainMenu(char* filename, struct GPTData* theGPT) {
|
||||
uint32_t temp1, temp2;
|
||||
|
||||
do {
|
||||
printf("\nCommand (? for help): ");
|
||||
cout << "\nCommand (? for help): ";
|
||||
junk = fgets(line, 255, stdin);
|
||||
sscanf(line, "%c", &command);
|
||||
switch (command) {
|
||||
case '\n':
|
||||
break;
|
||||
case 'b': case 'B':
|
||||
printf("Enter backup filename to save: ");
|
||||
cout << "Enter backup filename to save: ";
|
||||
junk = fgets(line, 255, stdin);
|
||||
sscanf(line, "%s", (char*) &buFile);
|
||||
theGPT->SaveGPTBackup(buFile);
|
||||
@@ -81,7 +85,7 @@ void MainMenu(char* filename, struct GPTData* theGPT) {
|
||||
if (theGPT->GetPartRange(&temp1, &temp2) > 0)
|
||||
theGPT->SetName(theGPT->GetPartNum());
|
||||
else
|
||||
printf("No partitions\n");
|
||||
cout << "No partitions\n";
|
||||
break;
|
||||
case 'd': case 'D':
|
||||
theGPT->DeletePartition();
|
||||
@@ -96,8 +100,8 @@ void MainMenu(char* filename, struct GPTData* theGPT) {
|
||||
theGPT->CreatePartition();
|
||||
break;
|
||||
case 'o': case 'O':
|
||||
printf("This option deletes all partitions and creates a new "
|
||||
"protective MBR.\nProceed? ");
|
||||
cout << "This option deletes all partitions and creates a new protective MBR.\n"
|
||||
<< "Proceed? ";
|
||||
if (GetYN() == 'Y') {
|
||||
theGPT->ClearGPTData();
|
||||
theGPT->MakeProtectiveMBR();
|
||||
@@ -115,7 +119,7 @@ void MainMenu(char* filename, struct GPTData* theGPT) {
|
||||
break;
|
||||
case 's': case 'S':
|
||||
theGPT->SortGPT();
|
||||
printf("You may need to edit /etc/fstab and/or your boot loader configuration!\n");
|
||||
cout << "You may need to edit /etc/fstab and/or your boot loader configuration!\n";
|
||||
break;
|
||||
case 't': case 'T':
|
||||
theGPT->ChangePartType();
|
||||
@@ -139,27 +143,27 @@ void MainMenu(char* filename, struct GPTData* theGPT) {
|
||||
} // MainMenu()
|
||||
|
||||
void ShowCommands(void) {
|
||||
printf("b\tback up GPT data to a file\n");
|
||||
printf("c\tchange a partition's name\n");
|
||||
printf("d\tdelete a partition\n");
|
||||
printf("i\tshow detailed information on a partition\n");
|
||||
printf("l\tlist known partition types\n");
|
||||
printf("n\tadd a new partition\n");
|
||||
printf("o\tcreate a new empty GUID partition table (GPT)\n");
|
||||
printf("p\tprint the partition table\n");
|
||||
printf("q\tquit without saving changes\n");
|
||||
printf("r\trecovery and transformation options (experts only)\n");
|
||||
printf("s\tsort partitions\n");
|
||||
printf("t\tchange a partition's type code\n");
|
||||
printf("v\tverify disk\n");
|
||||
printf("w\twrite table to disk and exit\n");
|
||||
printf("x\textra functionality (experts only)\n");
|
||||
printf("?\tprint this menu\n");
|
||||
cout << "b\tback up GPT data to a file\n";
|
||||
cout << "c\tchange a partition's name\n";
|
||||
cout << "d\tdelete a partition\n";
|
||||
cout << "i\tshow detailed information on a partition\n";
|
||||
cout << "l\tlist known partition types\n";
|
||||
cout << "n\tadd a new partition\n";
|
||||
cout << "o\tcreate a new empty GUID partition table (GPT)\n";
|
||||
cout << "p\tprint the partition table\n";
|
||||
cout << "q\tquit without saving changes\n";
|
||||
cout << "r\trecovery and transformation options (experts only)\n";
|
||||
cout << "s\tsort partitions\n";
|
||||
cout << "t\tchange a partition's type code\n";
|
||||
cout << "v\tverify disk\n";
|
||||
cout << "w\twrite table to disk and exit\n";
|
||||
cout << "x\textra functionality (experts only)\n";
|
||||
cout << "?\tprint this menu\n";
|
||||
} // ShowCommands()
|
||||
|
||||
// Accept a recovery & transformation menu command. Returns only when the user
|
||||
// issues an exit command, such as 'w' or 'q'.
|
||||
void RecoveryMenu(char* filename, struct GPTData* theGPT) {
|
||||
void RecoveryMenu(string filename, struct GPTData* theGPT) {
|
||||
char command, line[255], buFile[255];
|
||||
char* junk;
|
||||
PartTypes typeHelper;
|
||||
@@ -167,16 +171,18 @@ void RecoveryMenu(char* filename, struct GPTData* theGPT) {
|
||||
int goOn = 1;
|
||||
|
||||
do {
|
||||
printf("\nRecovery/transformation command (? for help): ");
|
||||
cout << "\nRecovery/transformation command (? for help): ";
|
||||
junk = fgets(line, 255, stdin);
|
||||
sscanf(line, "%c", &command);
|
||||
switch (command) {
|
||||
case '\n':
|
||||
break;
|
||||
case 'b': case 'B':
|
||||
theGPT->RebuildMainHeader();
|
||||
break;
|
||||
case 'c': case 'C':
|
||||
printf("Warning! This will probably do weird things if you've converted an MBR to\n"
|
||||
"GPT form and haven't yet saved the GPT! Proceed? ");
|
||||
cout << "Warning! This will probably do weird things if you've converted an MBR to\n"
|
||||
<< "GPT form and haven't yet saved the GPT! Proceed? ";
|
||||
if (GetYN() == 'Y')
|
||||
theGPT->LoadSecondTableAsMain();
|
||||
break;
|
||||
@@ -184,18 +190,18 @@ void RecoveryMenu(char* filename, struct GPTData* theGPT) {
|
||||
theGPT->RebuildSecondHeader();
|
||||
break;
|
||||
case 'e': case 'E':
|
||||
printf("Warning! This will probably do weird things if you've converted an MBR to\n"
|
||||
"GPT form and haven't yet saved the GPT! Proceed? ");
|
||||
cout << "Warning! This will probably do weird things if you've converted an MBR to\n"
|
||||
<< "GPT form and haven't yet saved the GPT! Proceed? ";
|
||||
if (GetYN() == 'Y')
|
||||
theGPT->LoadMainTable();
|
||||
break;
|
||||
case 'f': case 'F':
|
||||
printf("Warning! This will destroy the currently defined partitions! Proceed? ");
|
||||
cout << "Warning! This will destroy the currently defined partitions! Proceed? ";
|
||||
if (GetYN() == 'Y') {
|
||||
if (theGPT->LoadMBR(filename) == 1) { // successful load
|
||||
theGPT->XFormPartitions();
|
||||
} else {
|
||||
printf("Problem loading MBR! GPT is untouched; regenerating protective MBR!\n");
|
||||
cout << "Problem loading MBR! GPT is untouched; regenerating protective MBR!\n";
|
||||
theGPT->MakeProtectiveMBR();
|
||||
} // if/else
|
||||
} // if
|
||||
@@ -203,13 +209,13 @@ void RecoveryMenu(char* filename, struct GPTData* theGPT) {
|
||||
case 'g': case 'G':
|
||||
temp1 = theGPT->XFormToMBR();
|
||||
if (temp1 > 0) {
|
||||
printf("Converted %d partitions. Finalize and exit? ", temp1);
|
||||
cout << "Converted " << temp1 << " partitions. Finalize and exit? ";
|
||||
if (GetYN() == 'Y') {
|
||||
if (theGPT->DestroyGPT(0) > 0)
|
||||
goOn = 0;
|
||||
} else {
|
||||
theGPT->MakeProtectiveMBR();
|
||||
printf("Note: New protective MBR created.\n");
|
||||
cout << "Note: New protective MBR created.\n";
|
||||
} // if/else
|
||||
} // if
|
||||
break;
|
||||
@@ -220,7 +226,7 @@ void RecoveryMenu(char* filename, struct GPTData* theGPT) {
|
||||
theGPT->ShowDetails();
|
||||
break;
|
||||
case 'l': case 'L':
|
||||
printf("Enter backup filename to load: ");
|
||||
cout << "Enter backup filename to load: ";
|
||||
junk = fgets(line, 255, stdin);
|
||||
sscanf(line, "%s", (char*) &buFile);
|
||||
theGPT->LoadGPTBackup(buFile);
|
||||
@@ -261,29 +267,29 @@ void RecoveryMenu(char* filename, struct GPTData* theGPT) {
|
||||
} // RecoveryMenu()
|
||||
|
||||
void ShowRecoveryCommands(void) {
|
||||
printf("b\tuse backup GPT header (rebuilding main)\n");
|
||||
printf("c\tload backup partition table from disk (rebuilding main)\n");
|
||||
printf("d\tuse main GPT header (rebuilding backup)\n");
|
||||
printf("e\tload main partition table from disk (rebuilding backup)\n");
|
||||
printf("f\tload MBR and build fresh GPT from it\n");
|
||||
printf("g\tconvert GPT into MBR and exit\n");
|
||||
printf("h\tmake hybrid MBR\n");
|
||||
printf("i\tshow detailed information on a partition\n");
|
||||
printf("l\tload partition data from a backup file\n");
|
||||
printf("m\treturn to main menu\n");
|
||||
printf("o\tprint protective MBR data\n");
|
||||
printf("p\tprint the partition table\n");
|
||||
printf("q\tquit without saving changes\n");
|
||||
printf("t\ttransform BSD disklabel partition\n");
|
||||
printf("v\tverify disk\n");
|
||||
printf("w\twrite table to disk and exit\n");
|
||||
printf("x\textra functionality (experts only)\n");
|
||||
printf("?\tprint this menu\n");
|
||||
cout << "b\tuse backup GPT header (rebuilding main)\n";
|
||||
cout << "c\tload backup partition table from disk (rebuilding main)\n";
|
||||
cout << "d\tuse main GPT header (rebuilding backup)\n";
|
||||
cout << "e\tload main partition table from disk (rebuilding backup)\n";
|
||||
cout << "f\tload MBR and build fresh GPT from it\n";
|
||||
cout << "g\tconvert GPT into MBR and exit\n";
|
||||
cout << "h\tmake hybrid MBR\n";
|
||||
cout << "i\tshow detailed information on a partition\n";
|
||||
cout << "l\tload partition data from a backup file\n";
|
||||
cout << "m\treturn to main menu\n";
|
||||
cout << "o\tprint protective MBR data\n";
|
||||
cout << "p\tprint the partition table\n";
|
||||
cout << "q\tquit without saving changes\n";
|
||||
cout << "t\ttransform BSD disklabel partition\n";
|
||||
cout << "v\tverify disk\n";
|
||||
cout << "w\twrite table to disk and exit\n";
|
||||
cout << "x\textra functionality (experts only)\n";
|
||||
cout << "?\tprint this menu\n";
|
||||
} // ShowRecoveryCommands()
|
||||
|
||||
// Accept an experts' menu command. Returns only after the user
|
||||
// selects an exit command, such as 'w' or 'q'.
|
||||
void ExpertsMenu(char* filename, struct GPTData* theGPT) {
|
||||
void ExpertsMenu(string filename, struct GPTData* theGPT) {
|
||||
char command, line[255];
|
||||
char* junk;
|
||||
PartTypes typeHelper;
|
||||
@@ -292,40 +298,43 @@ void ExpertsMenu(char* filename, struct GPTData* theGPT) {
|
||||
int goOn = 1;
|
||||
|
||||
do {
|
||||
printf("\nExpert command (? for help): ");
|
||||
cout << "\nExpert command (? for help): ";
|
||||
junk = fgets(line, 255, stdin);
|
||||
sscanf(line, "%c", &command);
|
||||
switch (command) {
|
||||
case '\n':
|
||||
break;
|
||||
case 'a': case 'A':
|
||||
if (theGPT->GetPartRange(&temp1, &temp2) > 0)
|
||||
theGPT->SetAttributes(theGPT->GetPartNum());
|
||||
else
|
||||
printf("No partitions\n");
|
||||
cout << "No partitions\n";
|
||||
break;
|
||||
case 'c': case 'C':
|
||||
if (theGPT->GetPartRange(&temp1, &temp2) > 0) {
|
||||
pn = theGPT->GetPartNum();
|
||||
printf("Enter the partition's new unique GUID:\n");
|
||||
cout << "Enter the partition's new unique GUID:\n";
|
||||
theGPT->SetPartitionGUID(pn, GetGUID());
|
||||
} else printf("No partitions\n");
|
||||
} else cout << "No partitions\n";
|
||||
break;
|
||||
case 'd': case 'D':
|
||||
printf("Partitions will begin on %d-sector boundaries.\n",
|
||||
theGPT->GetAlignment());
|
||||
cout << "Partitions will begin on " << theGPT->GetAlignment()
|
||||
<< "-sector boundaries.\n";
|
||||
break;
|
||||
case 'e': case 'E':
|
||||
printf("Relocating backup data structures to the end of the disk\n");
|
||||
cout << "Relocating backup data structures to the end of the disk\n";
|
||||
theGPT->MoveSecondHeaderToEnd();
|
||||
break;
|
||||
case 'g': case 'G':
|
||||
printf("Enter the disk's unique GUID:\n");
|
||||
cout << "Enter the disk's unique GUID:\n";
|
||||
theGPT->SetDiskGUID(GetGUID());
|
||||
break;
|
||||
case 'i': case 'I':
|
||||
theGPT->ShowDetails();
|
||||
break;
|
||||
case 'l': case 'L':
|
||||
temp1 = GetNumber(1, 128, 8, "Enter the sector alignment value (1-128, default = 8): ");
|
||||
temp1 = GetNumber(1, 128, 8, (string)
|
||||
"Enter the sector alignment value (1-128, default = 8): ");
|
||||
theGPT->SetAlignment(temp1);
|
||||
break;
|
||||
case 'm': case 'M':
|
||||
@@ -372,22 +381,22 @@ void ExpertsMenu(char* filename, struct GPTData* theGPT) {
|
||||
} // ExpertsMenu()
|
||||
|
||||
void ShowExpertCommands(void) {
|
||||
printf("a\tset attributes\n");
|
||||
printf("c\tchange partition GUID\n");
|
||||
printf("d\tdisplay the sector alignment value\n");
|
||||
printf("e\trelocate backup data structures to the end of the disk\n");
|
||||
printf("g\tchange disk GUID\n");
|
||||
printf("i\tshow detailed information on a partition\n");
|
||||
printf("l\tset the sector alignment value\n");
|
||||
printf("m\treturn to main menu\n");
|
||||
printf("n\tcreate a new protective MBR\n");
|
||||
printf("o\tprint protective MBR data\n");
|
||||
printf("p\tprint the partition table\n");
|
||||
printf("q\tquit without saving changes\n");
|
||||
printf("r\trecovery and transformation options (experts only)\n");
|
||||
printf("s\tresize partition table\n");
|
||||
printf("v\tverify disk\n");
|
||||
printf("w\twrite table to disk and exit\n");
|
||||
printf("z\tzap (destroy) GPT data structures and exit\n");
|
||||
printf("?\tprint this menu\n");
|
||||
cout << "a\tset attributes\n";
|
||||
cout << "c\tchange partition GUID\n";
|
||||
cout << "d\tdisplay the sector alignment value\n";
|
||||
cout << "e\trelocate backup data structures to the end of the disk\n";
|
||||
cout << "g\tchange disk GUID\n";
|
||||
cout << "i\tshow detailed information on a partition\n";
|
||||
cout << "l\tset the sector alignment value\n";
|
||||
cout << "m\treturn to main menu\n";
|
||||
cout << "n\tcreate a new protective MBR\n";
|
||||
cout << "o\tprint protective MBR data\n";
|
||||
cout << "p\tprint the partition table\n";
|
||||
cout << "q\tquit without saving changes\n";
|
||||
cout << "r\trecovery and transformation options (experts only)\n";
|
||||
cout << "s\tresize partition table\n";
|
||||
cout << "v\tverify disk\n";
|
||||
cout << "w\twrite table to disk and exit\n";
|
||||
cout << "z\tzap (destroy) GPT data structures and exit\n";
|
||||
cout << "?\tprint this menu\n";
|
||||
} // ShowExpertCommands()
|
||||
|
||||
16
gpt.h
16
gpt.h
@@ -16,7 +16,7 @@
|
||||
#ifndef __GPTSTRUCTS
|
||||
#define __GPTSTRUCTS
|
||||
|
||||
#define GPTFDISK_VERSION "0.6.2-pre1"
|
||||
#define GPTFDISK_VERSION "0.6.2-pre2"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -59,7 +59,7 @@ protected:
|
||||
GPTPart *partitions;
|
||||
struct GPTHeader secondHeader;
|
||||
MBRData protectiveMBR;
|
||||
char device[256]; // device filename
|
||||
string device; // device filename
|
||||
DiskIO myDisk;
|
||||
uint32_t blockSize; // device block size
|
||||
uint64_t diskSize; // size of device, in blocks
|
||||
@@ -78,7 +78,7 @@ protected:
|
||||
public:
|
||||
// Basic necessary functions....
|
||||
GPTData(void);
|
||||
GPTData(char* deviceFilename);
|
||||
GPTData(string deviceFilename);
|
||||
~GPTData(void);
|
||||
|
||||
// Verify (or update) data integrity
|
||||
@@ -93,15 +93,15 @@ public:
|
||||
int FindOverlaps(void);
|
||||
|
||||
// Load or save data from/to disk
|
||||
int LoadMBR(char* f) {return protectiveMBR.ReadMBRData(f);}
|
||||
int LoadMBR(string f) {return protectiveMBR.ReadMBRData(f);}
|
||||
void PartitionScan(void);
|
||||
int LoadPartitions(char* deviceFilename);
|
||||
int LoadPartitions(string deviceFilename);
|
||||
int ForceLoadGPTData(void);
|
||||
int LoadMainTable(void);
|
||||
int LoadSecondTableAsMain(void);
|
||||
int SaveGPTData(int quiet = 0);
|
||||
int SaveGPTBackup(char* filename);
|
||||
int LoadGPTBackup(char* filename);
|
||||
int SaveGPTBackup(string filename);
|
||||
int LoadGPTBackup(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, char* theName = NULL);
|
||||
int SetName(uint32_t partNum, string theName = "");
|
||||
void SetDiskGUID(GUIDData newGUID);
|
||||
int SetPartitionGUID(uint32_t pn, GUIDData theGUID);
|
||||
int ChangePartType(uint32_t pn, uint16_t hexCode);
|
||||
|
||||
109
gptpart.cc
109
gptpart.cc
@@ -15,8 +15,9 @@
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include "gptpart.h"
|
||||
#include "attributes.h"
|
||||
|
||||
@@ -34,14 +35,14 @@ GPTPart::GPTPart(void) {
|
||||
GPTPart::~GPTPart(void) {
|
||||
} // destructor
|
||||
|
||||
// Return partition's name field
|
||||
// Return partition's name field, converted to a C++ ASCII string
|
||||
string GPTPart::GetName(void) {
|
||||
string theName;
|
||||
int i;
|
||||
|
||||
/* if (ref == NULL)
|
||||
ref = (unsigned char*) malloc(NAME_SIZE * sizeof (unsigned char));
|
||||
strcpy((char*) ref, (char*) name); */
|
||||
theName = (const char*) name;
|
||||
for (i = 0; i < NAME_SIZE; i += 2) {
|
||||
theName += name[i];
|
||||
} // for
|
||||
return theName;
|
||||
} // GPTPart::GetName()
|
||||
|
||||
@@ -53,12 +54,7 @@ uint16_t GPTPart::GetHexType(void) {
|
||||
// Return a plain-text description of the partition type (e.g., "Linux/Windows
|
||||
// data" or "Linux swap").
|
||||
string GPTPart::GetNameType(void) {
|
||||
string temp;
|
||||
char theName[255];
|
||||
|
||||
temp = typeHelper.GUIDToName(partitionType, theName);
|
||||
|
||||
return temp;
|
||||
return typeHelper.GUIDToName(partitionType);
|
||||
} // GPTPart::GetNameType()
|
||||
|
||||
// Compute and return the partition's length (or 0 if the end is incorrectly
|
||||
@@ -141,50 +137,56 @@ void GPTPart::ReversePartBytes(void) {
|
||||
|
||||
// Display summary information; does nothing if the partition is empty.
|
||||
void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
|
||||
char sizeInSI[255];
|
||||
int j = 0;
|
||||
string sizeInSI;
|
||||
int i;
|
||||
|
||||
if (firstLBA != 0) {
|
||||
BytesToSI(blockSize * (lastLBA - firstLBA + 1), sizeInSI);
|
||||
printf("%4d %14lu %14lu", partNum + 1, (unsigned long) firstLBA,
|
||||
(unsigned long) lastLBA);
|
||||
printf(" %-10s %04X ", sizeInSI,
|
||||
typeHelper.GUIDToID(partitionType));
|
||||
while ((name[j] != '\0') && (j < 44)) {
|
||||
printf("%c", name[j]);
|
||||
j += 2;
|
||||
} // while
|
||||
printf("\n");
|
||||
sizeInSI = BytesToSI(blockSize * (lastLBA - firstLBA + 1));
|
||||
cout.width(4);
|
||||
cout << partNum + 1 << " ";
|
||||
cout.width(14);
|
||||
cout << firstLBA << " ";
|
||||
cout.width(14);
|
||||
cout << lastLBA << " ";
|
||||
cout << BytesToSI(blockSize * (lastLBA - firstLBA + 1)) << " ";
|
||||
for (i = 0; i < 9 - sizeInSI.length(); i++) cout << " ";
|
||||
cout.fill('0');
|
||||
cout.width(4);
|
||||
cout.setf(ios::uppercase);
|
||||
cout << hex << typeHelper.GUIDToID(partitionType) << " " << dec;
|
||||
cout.fill(' ');
|
||||
cout.setf(ios::right);
|
||||
cout << GetName().substr(0, 23) << "\n";
|
||||
cout.fill(' ');
|
||||
} // if
|
||||
} // GPTPart::ShowSummary()
|
||||
|
||||
// Show detailed partition information. Does nothing if the partition is
|
||||
// empty (as determined by firstLBA being 0).
|
||||
void GPTPart::ShowDetails(uint32_t blockSize) {
|
||||
char temp[255];
|
||||
int i;
|
||||
uint64_t size;
|
||||
|
||||
if (firstLBA != 0) {
|
||||
printf("Partition GUID code: %s ", GUIDToStr(partitionType, temp));
|
||||
printf("(%s)\n", typeHelper.GUIDToName(partitionType, temp));
|
||||
printf("Partition unique GUID: %s\n", GUIDToStr(uniqueGUID, temp));
|
||||
cout << "Partition GUID code: " << GUIDToStr(partitionType);
|
||||
cout << " (" << typeHelper.GUIDToName(partitionType) << ")\n";
|
||||
cout << "Partition unique GUID: " << GUIDToStr(uniqueGUID) << "\n";
|
||||
|
||||
printf("First sector: %llu ", firstLBA);
|
||||
printf("(at %s)\n", BytesToSI(firstLBA * blockSize, temp));
|
||||
printf("Last sector: %llu ", (unsigned long long) lastLBA);
|
||||
printf("(at %s)\n", BytesToSI(lastLBA * blockSize, temp));
|
||||
cout << "First sector: " << firstLBA << " (at "
|
||||
<< BytesToSI(firstLBA * blockSize) << ")\n";
|
||||
cout << "Last sector: " << lastLBA << " (at "
|
||||
<< BytesToSI(lastLBA * blockSize) << ")\n";
|
||||
size = (lastLBA - firstLBA + 1);
|
||||
printf("Partition size: %llu sectors ", (unsigned long long) size);
|
||||
printf("(%s)\n", BytesToSI(size * ((uint64_t) blockSize), temp));
|
||||
printf("Attribute flags: %016llx\n", (unsigned long long) attributes);
|
||||
printf("Partition name: ");
|
||||
i = 0;
|
||||
while ((name[i] != '\0') && (i < NAME_SIZE)) {
|
||||
printf("%c", name[i]);
|
||||
i += 2;
|
||||
} // while
|
||||
printf("\n");
|
||||
cout << "Partition size: " << size << " sectors ("
|
||||
<< BytesToSI(size * ((uint64_t) blockSize)) << ")\n";
|
||||
cout << "Attribute flags: ";
|
||||
cout.fill('0');
|
||||
cout.width(16);
|
||||
cout << right;
|
||||
cout << hex;
|
||||
cout << attributes << "\n";
|
||||
cout << left;
|
||||
cout << dec;
|
||||
cout << "Partition name: " << GetName() << "\n";
|
||||
} // if
|
||||
} // GPTPart::ShowDetails()
|
||||
|
||||
@@ -194,14 +196,14 @@ void GPTPart::ShowDetails(uint32_t blockSize) {
|
||||
|
||||
// Change the type code on the partition.
|
||||
void GPTPart::ChangeType(void) {
|
||||
char typeName[255], line[255];
|
||||
char line[255];
|
||||
char* junk;
|
||||
int typeNum = 0xFFFF;
|
||||
GUIDData newType;
|
||||
|
||||
printf("Current type is '%s'\n", GetNameType().c_str());
|
||||
cout << "Current type is '" << GetNameType() << "'\n";
|
||||
while ((!typeHelper.Valid(typeNum)) && (typeNum != 0)) {
|
||||
printf("Hex code (L to show codes, 0 to enter raw code, Enter = 0700): ");
|
||||
cout << "Hex code (L to show codes, 0 to enter raw code, Enter = 0700): ";
|
||||
junk = fgets(line, 255, stdin);
|
||||
sscanf(line, "%X", &typeNum);
|
||||
if ((line[0] == 'L') || (line[0] == 'l'))
|
||||
@@ -215,25 +217,24 @@ void GPTPart::ChangeType(void) {
|
||||
else // user wants to enter the GUID directly, so do that
|
||||
newType = GetGUID();
|
||||
partitionType = newType;
|
||||
printf("Changed type of partition to '%s'\n",
|
||||
typeHelper.GUIDToName(partitionType, typeName));
|
||||
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 a NULL pointer. Note that theName is a standard C-style
|
||||
// theName is empty. Note that theName is a standard C++-style ASCII
|
||||
// string, although the GUID partition definition requires a UTF-16LE
|
||||
// string. This function creates a simple-minded copy for this.
|
||||
void GPTPart::SetName(unsigned char* theName) {
|
||||
void GPTPart::SetName(string theName) {
|
||||
char newName[NAME_SIZE]; // New name
|
||||
char* junk;
|
||||
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 == NULL) { // No name specified, so get one from the user
|
||||
printf("Enter name: ");
|
||||
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....
|
||||
@@ -241,7 +242,7 @@ void GPTPart::SetName(unsigned char* theName) {
|
||||
if (newName[i - 1] == '\n')
|
||||
newName[i - 1] = '\0';
|
||||
} else {
|
||||
strcpy(newName, (char*) theName);
|
||||
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
|
||||
|
||||
@@ -69,7 +69,7 @@ class GPTPart {
|
||||
void SetFirstLBA(uint64_t f) {firstLBA = f;}
|
||||
void SetLastLBA(uint64_t l) {lastLBA = l;}
|
||||
void SetAttributes(uint64_t a) {attributes = a;}
|
||||
void SetName(unsigned char* n);
|
||||
void SetName(string n);
|
||||
|
||||
// Additional functions
|
||||
GPTPart & operator=(const GPTPart & orig);
|
||||
|
||||
84
mbr.cc
84
mbr.cc
@@ -18,6 +18,7 @@
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <iostream>
|
||||
#include "mbr.h"
|
||||
#include "support.h"
|
||||
|
||||
@@ -32,7 +33,7 @@ using namespace std;
|
||||
MBRData::MBRData(void) {
|
||||
blockSize = SECTOR_SIZE;
|
||||
diskSize = 0;
|
||||
strcpy(device, "");
|
||||
device = "";
|
||||
state = invalid;
|
||||
srand((unsigned int) time(NULL));
|
||||
numHeads = MAX_HEADS;
|
||||
@@ -40,10 +41,10 @@ MBRData::MBRData(void) {
|
||||
EmptyMBR();
|
||||
} // MBRData default constructor
|
||||
|
||||
MBRData::MBRData(char *filename) {
|
||||
MBRData::MBRData(string filename) {
|
||||
blockSize = SECTOR_SIZE;
|
||||
diskSize = 0;
|
||||
strcpy(device, filename);
|
||||
device = filename;
|
||||
state = invalid;
|
||||
numHeads = MAX_HEADS;
|
||||
numSecspTrack = MAX_SECSPERTRACK;
|
||||
@@ -52,7 +53,7 @@ MBRData::MBRData(char *filename) {
|
||||
// Try to read the specified partition table, but if it fails....
|
||||
if (!ReadMBRData(filename)) {
|
||||
EmptyMBR();
|
||||
strcpy(device, "");
|
||||
device = "";
|
||||
} // if
|
||||
} // MBRData(char *filename) constructor
|
||||
|
||||
@@ -67,7 +68,7 @@ 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(char* deviceFilename) {
|
||||
int MBRData::ReadMBRData(string deviceFilename) {
|
||||
int fd, allOK = 1;
|
||||
|
||||
if (myDisk->OpenForRead(deviceFilename)) {
|
||||
@@ -77,7 +78,7 @@ int MBRData::ReadMBRData(char* deviceFilename) {
|
||||
} // if
|
||||
|
||||
if (allOK)
|
||||
strcpy(device, deviceFilename);
|
||||
device = deviceFilename;
|
||||
|
||||
return allOK;
|
||||
} // MBRData::ReadMBRData(char* deviceFilename)
|
||||
@@ -101,7 +102,7 @@ void MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
|
||||
if (myDisk->Read(&tempMBR, 512))
|
||||
err = 0;
|
||||
if (err) {
|
||||
fprintf(stderr, "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];
|
||||
@@ -152,7 +153,7 @@ void MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
|
||||
logicalNum = ReadLogicalPart(partitions[i].firstLBA, UINT32_C(0), 4);
|
||||
if ((logicalNum < 0) || (logicalNum >= MAX_MBR_PARTS)) {
|
||||
allOK = 0;
|
||||
fprintf(stderr, "Error reading logical partitions! List may be truncated!\n");
|
||||
cerr << "Error reading logical partitions! List may be truncated!\n";
|
||||
} // if maxLogicals valid
|
||||
} // if primary partition is extended
|
||||
} // for primary partition loop
|
||||
@@ -202,14 +203,13 @@ int MBRData::ReadLogicalPart(uint32_t extendedStart,
|
||||
// function as of GPT fdisk version 0.5.0 doesn't do so.
|
||||
if ((partNum < MAX_MBR_PARTS) && (partNum >= 0)) {
|
||||
offset = (uint64_t) (extendedStart + diskOffset);
|
||||
// if (lseek64(fd, offset, SEEK_SET) == (off_t) -1) { // seek to EBR record
|
||||
if (myDisk->Seek(offset) == 0) { // seek to EBR record
|
||||
fprintf(stderr, "Unable to seek to %lu! Aborting!\n", (unsigned long) offset);
|
||||
cerr << "Unable to seek to " << offset << "! Aborting!\n";
|
||||
partNum = -1;
|
||||
}
|
||||
if (myDisk->Read(&ebr, 512) != 512) { // Load the data....
|
||||
fprintf(stderr, "Error seeking to or reading logical partition data from %lu!\nAborting!\n",
|
||||
(unsigned long) offset);
|
||||
cerr << "Error seeking to or reading logical partition data from " << offset
|
||||
<< "!\nAborting!\n";
|
||||
partNum = -1;
|
||||
} else if (IsLittleEndian() != 1) { // Reverse byte ordering of some data....
|
||||
ReverseBytes(&ebr.MBRSignature, 2);
|
||||
@@ -221,8 +221,14 @@ int MBRData::ReadLogicalPart(uint32_t extendedStart,
|
||||
|
||||
if (ebr.MBRSignature != MBR_SIGNATURE) {
|
||||
partNum = -1;
|
||||
fprintf(stderr, "MBR signature in logical partition invalid; read 0x%04X, but should be 0x%04X\n",
|
||||
(unsigned int) ebr.MBRSignature, (unsigned int) MBR_SIGNATURE);
|
||||
cerr << "MBR signature in logical partition invalid; read 0x";
|
||||
cerr.fill('0');
|
||||
cerr.width(4);
|
||||
cerr.setf(ios::uppercase);
|
||||
cerr << hex << ebr.MBRSignature << ", but should be 0x";
|
||||
cerr.width(4);
|
||||
cerr << MBR_SIGNATURE << dec << "\n";
|
||||
cerr.fill(' ');
|
||||
} // if
|
||||
|
||||
// Copy over the basic data....
|
||||
@@ -297,11 +303,11 @@ int MBRData::WriteMBRData(DiskIO *theDisk) {
|
||||
if (allOK && theDisk->Seek(0)) {
|
||||
if (theDisk->Write(&tempMBR, 512) != 512) {
|
||||
allOK = 0;
|
||||
fprintf(stderr, "Warning! Error %d when saving MBR!\n", errno);
|
||||
cerr << "Warning! Error " << errno << " when saving MBR!\n";
|
||||
} // if
|
||||
} else {
|
||||
allOK = 0;
|
||||
fprintf(stderr, "Warning! Error %d when seeking to MBR to write it!\n", errno);
|
||||
cerr << "Warning! Error " << errno << " when seeking to MBR to write it!\n";
|
||||
} // if/else
|
||||
theDisk->Close();
|
||||
|
||||
@@ -318,8 +324,8 @@ int MBRData::WriteMBRData(DiskIO *theDisk) {
|
||||
return allOK;
|
||||
} // MBRData::WriteMBRData(DiskIO theDisk)
|
||||
|
||||
int MBRData::WriteMBRData(char* deviceFilename) {
|
||||
strcpy(device, deviceFilename);
|
||||
int MBRData::WriteMBRData(string deviceFilename) {
|
||||
device = deviceFilename;
|
||||
return WriteMBRData();
|
||||
} // MBRData::WriteMBRData(char* deviceFilename)
|
||||
|
||||
@@ -335,22 +341,34 @@ void MBRData::DisplayMBRData(void) {
|
||||
char tempStr[255];
|
||||
char bootCode;
|
||||
|
||||
printf("MBR disk identifier: 0x%08X\n", (unsigned int) diskSignature);
|
||||
printf("MBR partitions:\n");
|
||||
printf("Number\t Boot\t Start (sector)\t Length (sectors)\tType\n");
|
||||
cout << "MBR disk identifier: 0x";
|
||||
cout.width(8);
|
||||
cout.fill('0');
|
||||
cout.setf(ios::uppercase);
|
||||
cout << hex << diskSignature << dec << "\n";
|
||||
cout << "MBR partitions:\n";
|
||||
cout << "Number\t Boot\t Start (sector)\t Length (sectors)\tType\n";
|
||||
for (i = 0; i < MAX_MBR_PARTS; i++) {
|
||||
if (partitions[i].lengthLBA != 0) {
|
||||
if (partitions[i].status && 0x80) // it's bootable
|
||||
bootCode = '*';
|
||||
else
|
||||
bootCode = ' ';
|
||||
printf("%4d\t %c\t%13lu\t%15lu \t0x%02X\n", i + 1, bootCode,
|
||||
(unsigned long) partitions[i].firstLBA,
|
||||
(unsigned long) partitions[i].lengthLBA, partitions[i].partitionType);
|
||||
cout.fill(' ');
|
||||
cout.width(4);
|
||||
cout << i + 1 << "\t " << bootCode << "\t";
|
||||
cout.width(13);
|
||||
cout << partitions[i].firstLBA << "\t";
|
||||
cout.width(15);
|
||||
cout << partitions[i].lengthLBA << " \t0x";
|
||||
cout.width(2);
|
||||
cout.fill('0');
|
||||
cout << hex << (int) partitions[i].partitionType << dec << "\n";
|
||||
} // if
|
||||
cout.fill(' ');
|
||||
} // for
|
||||
printf("\nDisk size is %llu sectors ", (unsigned long long) diskSize);
|
||||
printf("(%s)\n", BytesToSI(diskSize * (uint64_t) blockSize, tempStr));
|
||||
cout << "\nDisk size is " << diskSize << " sectors ("
|
||||
<< BytesToSI(diskSize * (uint64_t) blockSize) << "\n";
|
||||
} // MBRData::DisplayMBRData()
|
||||
|
||||
// Displays the state, as a word, on stdout. Used for debugging & to
|
||||
@@ -358,19 +376,19 @@ void MBRData::DisplayMBRData(void) {
|
||||
void MBRData::ShowState(void) {
|
||||
switch (state) {
|
||||
case invalid:
|
||||
printf(" MBR: not present\n");
|
||||
cout << " MBR: not present\n";
|
||||
break;
|
||||
case gpt:
|
||||
printf(" MBR: protective\n");
|
||||
cout << " MBR: protective\n";
|
||||
break;
|
||||
case hybrid:
|
||||
printf(" MBR: hybrid\n");
|
||||
cout << " MBR: hybrid\n";
|
||||
break;
|
||||
case mbr:
|
||||
printf(" MBR: MBR only\n");
|
||||
cout << " MBR: MBR only\n";
|
||||
break;
|
||||
default:
|
||||
printf("\a MBR: unknown -- bug!\n");
|
||||
cout << "\a MBR: unknown -- bug!\n";
|
||||
break;
|
||||
} // switch
|
||||
} // MBRData::ShowState()
|
||||
@@ -390,7 +408,7 @@ void MBRData::SetCHSGeom(uint32_t h, uint32_t s) {
|
||||
numHeads = h;
|
||||
numSecspTrack = s;
|
||||
} else {
|
||||
printf("Warning! Attempt to set invalid CHS geometry!\n");
|
||||
cout << "Warning! Attempt to set invalid CHS geometry!\n";
|
||||
} // if/else
|
||||
} // MBRData::SetCHSGeom()
|
||||
|
||||
@@ -807,7 +825,7 @@ GPTPart MBRData::AsGPT(int i) {
|
||||
newPart.SetType(((uint16_t) origType) * 0x0100);
|
||||
newPart.SetUniqueGUID(1);
|
||||
newPart.SetAttributes(0);
|
||||
newPart.SetName((unsigned char*) newPart.GetNameType().c_str());
|
||||
newPart.SetName(newPart.GetNameType());
|
||||
} // if not extended, protective, or non-existent
|
||||
} // if (origPart != NULL)
|
||||
return newPart;
|
||||
|
||||
8
mbr.h
8
mbr.h
@@ -71,16 +71,16 @@ protected:
|
||||
uint64_t numHeads; // number of heads, in CHS scheme
|
||||
uint64_t numSecspTrack; // number of sectors per track, in CHS scheme
|
||||
DiskIO* myDisk;
|
||||
char device[256];
|
||||
string device;
|
||||
MBRValidity state;
|
||||
struct MBRRecord* GetPartition(int i); // Return primary or logical partition
|
||||
public:
|
||||
MBRData(void);
|
||||
MBRData(char* deviceFilename);
|
||||
MBRData(string deviceFilename);
|
||||
~MBRData(void);
|
||||
|
||||
// File I/O functions...
|
||||
int ReadMBRData(char* deviceFilename);
|
||||
int ReadMBRData(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(char* deviceFilename);
|
||||
int WriteMBRData(string deviceFilename);
|
||||
|
||||
// Display data for user...
|
||||
void DisplayMBRData(void);
|
||||
|
||||
33
parttypes.cc
33
parttypes.cc
@@ -11,6 +11,7 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include "parttypes.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -236,20 +237,24 @@ int PartTypes::AddType(uint16_t mbrType, uint64_t guidData1, uint64_t guidData2,
|
||||
void PartTypes::ShowTypes(void) {
|
||||
int colCount = 1; // column count
|
||||
AType* thisType = allTypes;
|
||||
char tempStr[20];
|
||||
|
||||
cout.unsetf(ios::uppercase);
|
||||
while (thisType != NULL) {
|
||||
if (thisType->display == 1) { // show it
|
||||
strncpy(tempStr, thisType->name, 19);
|
||||
tempStr[19] = '\0';
|
||||
printf("%04x %-19s ", thisType->MBRType, tempStr);
|
||||
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) << " ";
|
||||
if ((colCount % 3) == 0)
|
||||
printf("\n");
|
||||
cout << "\n";
|
||||
colCount++;
|
||||
} // if
|
||||
thisType = thisType->next;
|
||||
} // while
|
||||
printf("\n");
|
||||
cout << "\n";
|
||||
} // PartTypes::ShowTypes()
|
||||
|
||||
// Returns 1 if code is a valid extended MBR code, 0 if it's not
|
||||
@@ -267,21 +272,24 @@ int PartTypes::Valid(uint16_t code) {
|
||||
} // PartTypes::Valid()
|
||||
|
||||
// Convert a GUID code to a name.
|
||||
char* PartTypes::GUIDToName(struct GUIDData typeCode, char typeName[]) {
|
||||
string PartTypes::GUIDToName(struct GUIDData typeCode) {
|
||||
AType* theItem = allTypes;
|
||||
int found = 0;
|
||||
string typeName;
|
||||
|
||||
while ((theItem != NULL) && (!found)) {
|
||||
if ((theItem->GUIDType.data1 == typeCode.data1) &&
|
||||
(theItem->GUIDType.data2 == typeCode.data2)) { // found it!
|
||||
strcpy(typeName, theItem->name);
|
||||
// strcpy(typeName, theItem->name);
|
||||
typeName = theItem->name;
|
||||
found = 1;
|
||||
} else {
|
||||
theItem = theItem->next;
|
||||
} // if/else
|
||||
} // while
|
||||
if (!found) {
|
||||
strcpy(typeName, (char*) "Unknown");
|
||||
typeName = "Unknown";
|
||||
// strcpy(typeName, (char*) "Unknown");
|
||||
} // if (!found)
|
||||
return typeName;
|
||||
} // PartTypes::GUIDToName()
|
||||
@@ -310,8 +318,11 @@ struct GUIDData PartTypes::IDToGUID(uint16_t ID) {
|
||||
} // if/else
|
||||
} // while
|
||||
if (!found) {
|
||||
printf("Exact type match not found for type code %04X; assigning type code for\n'Linux/Windows data'\n",
|
||||
ID);
|
||||
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;
|
||||
} // if (!found)
|
||||
return theGUID;
|
||||
} // PartTypes::IDToGUID()
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include "support.h"
|
||||
|
||||
#ifndef __PARTITION_TYPES
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
const char* name, int toDisplay = 1);
|
||||
void ShowTypes(void);
|
||||
int Valid(uint16_t);
|
||||
char* GUIDToName(struct GUIDData typeCode, char typeName[]);
|
||||
string GUIDToName(struct GUIDData typeCode);
|
||||
struct GUIDData IDToGUID(uint16_t ID);
|
||||
uint16_t GUIDToID(struct GUIDData);
|
||||
};
|
||||
|
||||
37
sgdisk.cc
37
sgdisk.cc
@@ -13,6 +13,7 @@
|
||||
#include <string>
|
||||
#include <popt.h>
|
||||
#include <errno.h>
|
||||
#include <iostream>
|
||||
#include "mbr.h"
|
||||
#include "gpt.h"
|
||||
#include "support.h"
|
||||
@@ -87,7 +88,7 @@ int main(int argc, char *argv[]) {
|
||||
pretend = 1;
|
||||
break;
|
||||
case 'V':
|
||||
printf("GPT fdisk (sgdisk) version %s\n\n", GPTFDISK_VERSION);
|
||||
cout << "GPT fdisk (sgdisk) version " << GPTFDISK_VERSION << "\n\n";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -102,7 +103,7 @@ int main(int argc, char *argv[]) {
|
||||
if (device != NULL) {
|
||||
theGPT.JustLooking(); // reset as necessary
|
||||
theGPT.BeQuiet(); // Tell called functions to be less verbose & interactive
|
||||
if (theGPT.LoadPartitions(device)) {
|
||||
if (theGPT.LoadPartitions((string) device)) {
|
||||
if ((theGPT.WhichWasUsed() == use_mbr) || (theGPT.WhichWasUsed() == use_bsd))
|
||||
saveNonGPT = 0; // flag so we don't overwrite unless directed to do so
|
||||
while ((opt = poptGetNextOpt(poptCon)) > 0) {
|
||||
@@ -117,11 +118,11 @@ int main(int argc, char *argv[]) {
|
||||
case 'c':
|
||||
theGPT.JustLooking(0);
|
||||
partNum = (int) GetInt(partName, 1) - 1;
|
||||
if (theGPT.SetName(partNum, (char*) GetString(partName, 2).c_str())) {
|
||||
if (theGPT.SetName(partNum, GetString(partName, 2))) {
|
||||
saveData = 1;
|
||||
} else {
|
||||
fprintf(stderr, "Unable set set partition %d's name to '%s'!\n",
|
||||
partNum + 1, GetString(partName, 2).c_str());
|
||||
cerr << "Unable set set partition " << partNum + 1
|
||||
<< "'s name to '" << GetString(partName, 2) << "'!\n";
|
||||
neverSaveData = 1;
|
||||
} // if/else
|
||||
free(partName);
|
||||
@@ -129,7 +130,7 @@ int main(int argc, char *argv[]) {
|
||||
case 'd':
|
||||
theGPT.JustLooking(0);
|
||||
if (theGPT.DeletePartition(deletePartNum - 1) == 0) {
|
||||
fprintf(stderr, "Error %d deleting partition!\n", errno);
|
||||
cerr << "Error " << errno << " deleting partition!\n";
|
||||
neverSaveData = 1;
|
||||
} else saveData = 1;
|
||||
break;
|
||||
@@ -139,10 +140,10 @@ int main(int argc, char *argv[]) {
|
||||
saveData = 1;
|
||||
break;
|
||||
case 'E':
|
||||
printf("%llu\n", (unsigned long long) theGPT.FindLastAvailable(theGPT.FindFirstInLargest()));
|
||||
cout << theGPT.FindLastAvailable(theGPT.FindFirstInLargest()) << "\n";
|
||||
break;
|
||||
case 'f':
|
||||
printf("%llu\n", (unsigned long long) theGPT.FindFirstInLargest());
|
||||
cout << theGPT.FindFirstInLargest() << "\n";
|
||||
break;
|
||||
case 'g':
|
||||
theGPT.JustLooking(0);
|
||||
@@ -153,12 +154,12 @@ int main(int argc, char *argv[]) {
|
||||
theGPT.ShowPartDetails(infoPartNum - 1);
|
||||
break;
|
||||
case 'l':
|
||||
if (theGPT.LoadGPTBackup(backupFile) == 1)
|
||||
if (theGPT.LoadGPTBackup((string) backupFile) == 1)
|
||||
saveData = 1;
|
||||
else {
|
||||
saveData = 0;
|
||||
neverSaveData = 1;
|
||||
fprintf(stderr, "Error loading backup file!\n");
|
||||
cerr << "Error loading backup file!\n";
|
||||
} // else
|
||||
free(backupFile);
|
||||
break;
|
||||
@@ -172,8 +173,8 @@ int main(int argc, char *argv[]) {
|
||||
if (theGPT.CreatePartition(partNum, startSector, endSector)) {
|
||||
saveData = 1;
|
||||
} else {
|
||||
fprintf(stderr, "Could not create partition %d from %llu to %llu!\n",
|
||||
partNum, startSector, endSector);
|
||||
cerr << "Could not create partition " << partNum << " from "
|
||||
<< startSector << " to " << endSector << "\n";
|
||||
neverSaveData = 1;
|
||||
} // if/else
|
||||
free(newPartInfo);
|
||||
@@ -208,8 +209,8 @@ int main(int argc, char *argv[]) {
|
||||
if (theGPT.ChangePartType(partNum, hexCode)) {
|
||||
saveData = 1;
|
||||
} else {
|
||||
fprintf(stderr, "Could not change partition %d's type code to %x!\n",
|
||||
partNum + 1, hexCode);
|
||||
cerr << "Could not change partition " << partNum + 1
|
||||
<< "'s type code to " << hex << hexCode << "!\n" << dec;
|
||||
neverSaveData = 1;
|
||||
} // if/else
|
||||
free(typeCode);
|
||||
@@ -228,18 +229,18 @@ int main(int argc, char *argv[]) {
|
||||
saveNonGPT = 0;
|
||||
break;
|
||||
default:
|
||||
printf("Unknown option (-%c)!\n", opt);
|
||||
cerr << "Unknown option (-" << opt << ")!\n";
|
||||
break;
|
||||
} // switch
|
||||
} // while
|
||||
if ((saveData) && (!neverSaveData) && (saveNonGPT) && (!pretend))
|
||||
theGPT.SaveGPTData(1);
|
||||
if (saveData && (!saveNonGPT)) {
|
||||
printf("Non-GPT disk; not saving changes. Use -g to override.\n");
|
||||
cout << "Non-GPT disk; not saving changes. Use -g to override.\n";
|
||||
retval = 3;
|
||||
} // if
|
||||
if (neverSaveData) {
|
||||
printf("Error encountered; not saving changes.\n");
|
||||
cerr << "Error encountered; not saving changes.\n";
|
||||
retval = 4;
|
||||
} // if
|
||||
} else { // if loaded OK
|
||||
@@ -267,8 +268,6 @@ uint64_t GetInt(char* argument, int itemNum) {
|
||||
endPos--;
|
||||
|
||||
sscanf(Info.substr(startPos, endPos - startPos + 1).c_str(), "%llu", &retval);
|
||||
/* printf("In GetInt(), startPos = %d, endPos = %d, retval = %llu\n", startPos,
|
||||
endPos, (unsigned long long) retval); */
|
||||
return retval;
|
||||
} // GetInt()
|
||||
|
||||
|
||||
155
support.cc
155
support.cc
@@ -10,11 +10,13 @@
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "support.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -33,26 +35,25 @@ using namespace std;
|
||||
// If user provides no input, def (default value) is returned.
|
||||
// (If def is outside of the low-high range, an explicit response
|
||||
// is required.)
|
||||
int GetNumber(int low, int high, int def, const char prompt[]) {
|
||||
int GetNumber(int low, int high, int def, const string & prompt) {
|
||||
int response, num;
|
||||
char line[255];
|
||||
char* junk;
|
||||
|
||||
if (low != high) { // bother only if low and high differ...
|
||||
response = low - 1; // force one loop by setting response outside range
|
||||
while ((response < low) || (response > high)) {
|
||||
printf("%s", prompt);
|
||||
junk = fgets(line, 255, stdin);
|
||||
cout << prompt;
|
||||
cin.getline(line, 255);
|
||||
num = sscanf(line, "%d", &response);
|
||||
if (num == 1) { // user provided a response
|
||||
if ((response < low) || (response > high))
|
||||
printf("Value out of range\n");
|
||||
cout << "Value out of range\n";
|
||||
} else { // user hit enter; return default
|
||||
response = def;
|
||||
} // if/else
|
||||
} // while
|
||||
} else { // low == high, so return this value
|
||||
printf("Using %d\n", low);
|
||||
cout << "Using " << low << "\n";
|
||||
response = low;
|
||||
} // else
|
||||
return (response);
|
||||
@@ -62,10 +63,10 @@ int GetNumber(int low, int high, int def, const char prompt[]) {
|
||||
char GetYN(void) {
|
||||
char line[255];
|
||||
char response = '\0';
|
||||
char* junk;
|
||||
char *junk;
|
||||
|
||||
while ((response != 'Y') && (response != 'N')) {
|
||||
printf("(Y/N): ");
|
||||
cout << "(Y/N): ";
|
||||
junk = fgets(line, 255, stdin);
|
||||
sscanf(line, "%c", &response);
|
||||
if (response == 'y') response = 'Y';
|
||||
@@ -81,18 +82,17 @@ char GetYN(void) {
|
||||
// If a "-" prefix is used, use the high value minus the user-
|
||||
// specified number of sectors (or KiB, MiB, etc.). Use the def
|
||||
//value as the default if the user just hits Enter
|
||||
uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, char prompt[]) {
|
||||
uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const string & prompt) {
|
||||
unsigned long long response;
|
||||
int num, plusFlag = 0;
|
||||
uint64_t mult = 1;
|
||||
char suffix;
|
||||
char line[255];
|
||||
char* junk;
|
||||
|
||||
response = low - 1; // Ensure one pass by setting a too-low initial value
|
||||
while ((response < low) || (response > high)) {
|
||||
printf("%s", prompt);
|
||||
junk = fgets(line, 255, stdin);
|
||||
cout << prompt;
|
||||
cin.getline(line, 255);
|
||||
|
||||
// Remove leading spaces, if present
|
||||
while (line[0] == ' ')
|
||||
@@ -164,65 +164,65 @@ uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, char prompt[])
|
||||
// Takes a size in bytes (in size) and converts this to a size in
|
||||
// SI units (KiB, MiB, GiB, TiB, or PiB), returned in C++ string
|
||||
// form
|
||||
char* BytesToSI(uint64_t size, char theValue[]) {
|
||||
char units[8];
|
||||
string BytesToSI(uint64_t size) {
|
||||
string units;
|
||||
char theValue[99];
|
||||
float sizeInSI;
|
||||
|
||||
if (theValue != NULL) {
|
||||
sizeInSI = (float) size;
|
||||
strcpy (units, " bytes");
|
||||
if (sizeInSI > 1024.0) {
|
||||
sizeInSI /= 1024.0;
|
||||
strcpy(units, " KiB");
|
||||
} // if
|
||||
if (sizeInSI > 1024.0) {
|
||||
sizeInSI /= 1024.0;
|
||||
strcpy(units, " MiB");
|
||||
} // if
|
||||
if (sizeInSI > 1024.0) {
|
||||
sizeInSI /= 1024.0;
|
||||
strcpy(units, " GiB");
|
||||
} // if
|
||||
if (sizeInSI > 1024.0) {
|
||||
sizeInSI /= 1024.0;
|
||||
strcpy(units, " TiB");
|
||||
} // if
|
||||
if (sizeInSI > 1024.0) {
|
||||
sizeInSI /= 1024.0;
|
||||
strcpy(units, " PiB");
|
||||
} // if
|
||||
if (strcmp(units, " bytes") == 0) { // in bytes, so no decimal point
|
||||
sprintf(theValue, "%1.0f%s", sizeInSI, units);
|
||||
} else {
|
||||
sprintf(theValue, "%1.1f%s", sizeInSI, units);
|
||||
} // if/else
|
||||
theValue[0] = '\0';
|
||||
sizeInSI = (float) size;
|
||||
units = " bytes";
|
||||
if (sizeInSI > 1024.0) {
|
||||
sizeInSI /= 1024.0;
|
||||
units = " KiB";
|
||||
} // if
|
||||
if (sizeInSI > 1024.0) {
|
||||
sizeInSI /= 1024.0;
|
||||
units = " MiB";
|
||||
} // if
|
||||
if (sizeInSI > 1024.0) {
|
||||
sizeInSI /= 1024.0;
|
||||
units = " GiB";
|
||||
} // if
|
||||
if (sizeInSI > 1024.0) {
|
||||
sizeInSI /= 1024.0;
|
||||
units = " TiB";
|
||||
} // if
|
||||
if (sizeInSI > 1024.0) {
|
||||
sizeInSI /= 1024.0;
|
||||
units = " PiB";
|
||||
} // if
|
||||
if (units == " bytes") { // in bytes, so no decimal point
|
||||
sprintf(theValue, "%1.0f%s", sizeInSI, units.c_str());
|
||||
} else {
|
||||
sprintf(theValue, "%1.1f%s", sizeInSI, units.c_str());
|
||||
} // if/else
|
||||
return theValue;
|
||||
} // BlocksToSI()
|
||||
|
||||
// Return a plain-text name for a partition type.
|
||||
// Convert a GUID to a string representation, suitable for display
|
||||
// to humans....
|
||||
char* GUIDToStr(struct GUIDData theGUID, char* theString) {
|
||||
string GUIDToStr(struct GUIDData theGUID) {
|
||||
unsigned long long blocks[11], block;
|
||||
char theString[40];
|
||||
|
||||
if (theString != NULL) {
|
||||
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]);
|
||||
} // if
|
||||
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()
|
||||
|
||||
@@ -234,10 +234,10 @@ GUIDData GetGUID(void) {
|
||||
char* junk;
|
||||
GUIDData theGUID;
|
||||
|
||||
printf("\nA GUID is entered in five segments of from two to six bytes, with\n"
|
||||
"dashes between segments.\n");
|
||||
printf("Enter the entire GUID, a four-byte hexadecimal number for the first segment, or\n"
|
||||
"'R' to generate the entire GUID randomly: ");
|
||||
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....
|
||||
@@ -280,17 +280,17 @@ GUIDData GetGUID(void) {
|
||||
// entry....
|
||||
if (entered == 0) {
|
||||
sscanf(temp, "%llx", &part1);
|
||||
printf("Enter a two-byte hexadecimal number for the second segment: ");
|
||||
cout << "Enter a two-byte hexadecimal number for the second segment: ";
|
||||
junk = fgets(temp, 255, stdin);
|
||||
sscanf(temp, "%llx", &part2);
|
||||
printf("Enter a two-byte hexadecimal number for the third segment: ");
|
||||
cout << "Enter a two-byte hexadecimal number for the third segment: ";
|
||||
junk = fgets(temp, 255, stdin);
|
||||
sscanf(temp, "%llx", &part3);
|
||||
theGUID.data1 = (part3 << 48) + (part2 << 32) + part1;
|
||||
printf("Enter a two-byte hexadecimal number for the fourth segment: ");
|
||||
cout << "Enter a two-byte hexadecimal number for the fourth segment: ";
|
||||
junk = fgets(temp, 255, stdin);
|
||||
sscanf(temp, "%llx", &part4);
|
||||
printf("Enter a six-byte hexadecimal number for the fifth segment: ");
|
||||
cout << "Enter a six-byte hexadecimal number for the fifth segment: ";
|
||||
junk = fgets(temp, 255, stdin);
|
||||
sscanf(temp, "%llx", &part5);
|
||||
theGUID.data2 = ((part4 & UINT64_C(0x000000000000FF00)) >> 8) +
|
||||
@@ -303,7 +303,7 @@ GUIDData GetGUID(void) {
|
||||
((part5 & UINT64_C(0x00000000000000FF)) << 56);
|
||||
entered = 1;
|
||||
} // if/else
|
||||
printf("New GUID: %s\n", GUIDToStr(theGUID, temp));
|
||||
cout << "New GUID: " << GUIDToStr(theGUID) << "\n";
|
||||
return theGUID;
|
||||
} // GetGUID()
|
||||
|
||||
@@ -324,17 +324,16 @@ int IsLittleEndian(void) {
|
||||
|
||||
// Reverse the byte order of theValue; numBytes is number of bytes
|
||||
void ReverseBytes(void* theValue, int numBytes) {
|
||||
char* origValue;
|
||||
char* tempValue;
|
||||
char* tempValue = NULL;
|
||||
int i;
|
||||
|
||||
origValue = (char*) theValue;
|
||||
tempValue = (char*) malloc(numBytes);
|
||||
for (i = 0; i < numBytes; i++)
|
||||
tempValue[i] = origValue[i];
|
||||
for (i = 0; i < numBytes; i++)
|
||||
origValue[i] = tempValue[numBytes - i - 1];
|
||||
free(tempValue);
|
||||
if (tempValue != NULL) {
|
||||
memcpy(tempValue, theValue, numBytes);
|
||||
for (i = 0; i < numBytes; i++)
|
||||
((char*) theValue)[i] = tempValue[numBytes - i - 1];
|
||||
free(tempValue);
|
||||
} // if
|
||||
} // ReverseBytes()
|
||||
|
||||
// Compute (2 ^ value). Given the return type, value must be 63 or less.
|
||||
|
||||
13
support.h
13
support.h
@@ -4,7 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
#ifndef __GPTSUPPORT
|
||||
#define __GPTSUPPORT
|
||||
@@ -35,6 +35,9 @@
|
||||
#define APM_SIGNATURE1 UINT64_C(0x00004D5000000000)
|
||||
#define APM_SIGNATURE2 UINT64_C(0x0000535400000000)
|
||||
|
||||
// Maximum line length ignored on some input functions
|
||||
#define MAX_IGNORED 999
|
||||
|
||||
/**************************
|
||||
* Some GPT constants.... *
|
||||
**************************/
|
||||
@@ -58,11 +61,11 @@ struct GUIDData {
|
||||
|
||||
static char theFile[255];
|
||||
|
||||
int GetNumber(int low, int high, int def, const char prompt[]);
|
||||
int GetNumber(int low, int high, int def, const string & prompt);
|
||||
char GetYN(void);
|
||||
uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, char prompt[]);
|
||||
char* BytesToSI(uint64_t size, char theValue[]);
|
||||
char* GUIDToStr(struct GUIDData theGUID, char* theString);
|
||||
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);
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user