Early support for larger-than-512-byte sectors and even earlier support
for sgdisk program. (The latter is just proof-of-concept at this point; it doesn't do anything useful.)
This commit is contained in:
@@ -1,6 +1,13 @@
|
|||||||
0.5.3 (1/??/2009):
|
0.6.0 (1/??/2009):
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
- Added support for disks with other than 512-byte sectors.
|
||||||
|
|
||||||
|
- Created embryonic sgdisk program.
|
||||||
|
|
||||||
|
0.5.3 (1/4/2009):
|
||||||
|
-----------------
|
||||||
|
|
||||||
- Fixed bug in display of GUIDs when compiled with some versions of GCC.
|
- Fixed bug in display of GUIDs when compiled with some versions of GCC.
|
||||||
|
|
||||||
- Eliminated warnings caused by additional checks in latest versions of
|
- Eliminated warnings caused by additional checks in latest versions of
|
||||||
|
|||||||
3
Makefile
3
Makefile
@@ -15,6 +15,9 @@ DEPEND= makedepend $(CFLAGS)
|
|||||||
gdisk: $(LIB_OBJS) gdisk.o
|
gdisk: $(LIB_OBJS) gdisk.o
|
||||||
$(CXX) $(LIB_OBJS) gdisk.o -o gdisk
|
$(CXX) $(LIB_OBJS) gdisk.o -o gdisk
|
||||||
|
|
||||||
|
sgdisk: $(LIB_OBJS) sgdisk.o
|
||||||
|
$(CXX) $(LIB_OBJS) sgdisk.o -o sgdisk
|
||||||
|
|
||||||
wipegpt: $(LIB_OBJS) wipegpt.o
|
wipegpt: $(LIB_OBJS) wipegpt.o
|
||||||
$(CXX) $(LIB_OBJS) wipegpt.o -o wipegpt
|
$(CXX) $(LIB_OBJS) wipegpt.o -o wipegpt
|
||||||
|
|
||||||
|
|||||||
8
bsd.cc
8
bsd.cc
@@ -63,7 +63,7 @@ int BSDData::ReadBSDData(char* device, uint64_t startSector, uint64_t endSector)
|
|||||||
// Load the BSD disklabel data from an already-opened disk
|
// Load the BSD disklabel data from an already-opened disk
|
||||||
// file, starting with the specified sector number.
|
// file, starting with the specified sector number.
|
||||||
void BSDData::ReadBSDData(int fd, uint64_t startSector, uint64_t endSector) {
|
void BSDData::ReadBSDData(int fd, uint64_t startSector, uint64_t endSector) {
|
||||||
uint8_t buffer[2048]; // I/O buffer
|
uint8_t buffer[4096]; // I/O buffer
|
||||||
int i, err, foundSig = 0, bigEnd = 0;
|
int i, err, foundSig = 0, bigEnd = 0;
|
||||||
int relative = 0; // assume absolute partition sector numbering
|
int relative = 0; // assume absolute partition sector numbering
|
||||||
uint32_t realSig;
|
uint32_t realSig;
|
||||||
@@ -74,10 +74,10 @@ void BSDData::ReadBSDData(int fd, uint64_t startSector, uint64_t endSector) {
|
|||||||
labelFirstLBA = startSector;
|
labelFirstLBA = startSector;
|
||||||
labelLastLBA = endSector;
|
labelLastLBA = endSector;
|
||||||
|
|
||||||
// Read two sectors into memory; we'll extract data from
|
// Read eight sectors into memory; we'll extract data from
|
||||||
// this buffer. (Done to work around FreeBSD limitation)
|
// this buffer. (Done to work around FreeBSD limitation)
|
||||||
lseek64(fd, startSector * 512, SEEK_SET);
|
lseek64(fd, startSector * GetBlockSize(fd), SEEK_SET);
|
||||||
err = read(fd, buffer, 2048);
|
err = read(fd, buffer, 4096);
|
||||||
|
|
||||||
// Do some strangeness to support big-endian architectures...
|
// Do some strangeness to support big-endian architectures...
|
||||||
bigEnd = (IsLittleEndian() == 0);
|
bigEnd = (IsLittleEndian() == 0);
|
||||||
|
|||||||
5
gdisk.cc
5
gdisk.cc
@@ -4,7 +4,7 @@
|
|||||||
//
|
//
|
||||||
// by Rod Smith, project began February 2009
|
// by Rod Smith, project began February 2009
|
||||||
|
|
||||||
/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
|
/* This program is copyright (c) 2009, 2010 by Roderick W. Smith. It is distributed
|
||||||
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||||
|
|
||||||
//#include <iostream>
|
//#include <iostream>
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
#include "support.h"
|
#include "support.h"
|
||||||
|
|
||||||
// Function prototypes....
|
// Function prototypes....
|
||||||
// int ReadPartitions(char* filename, struct GPTData* theGPT);
|
|
||||||
void MainMenu(char* filename, struct GPTData* theGPT);
|
void MainMenu(char* filename, struct GPTData* theGPT);
|
||||||
void ShowCommands(void);
|
void ShowCommands(void);
|
||||||
void ExpertsMenu(char* filename, struct GPTData* theGPT);
|
void ExpertsMenu(char* filename, struct GPTData* theGPT);
|
||||||
@@ -29,7 +28,7 @@ int main(int argc, char* argv[]) {
|
|||||||
int doMore = 1;
|
int doMore = 1;
|
||||||
char* device = NULL;
|
char* device = NULL;
|
||||||
|
|
||||||
printf("GPT fdisk (gdisk) version 0.5.3\n\n");
|
printf("GPT fdisk (gdisk) version 0.5.4-pre1\n\n");
|
||||||
|
|
||||||
if (argc == 2) { // basic usage
|
if (argc == 2) { // basic usage
|
||||||
if (SizesOK()) {
|
if (SizesOK()) {
|
||||||
|
|||||||
99
gpt.cc
99
gpt.cc
@@ -49,6 +49,7 @@ GPTData::GPTData(void) {
|
|||||||
bsdFound = 0;
|
bsdFound = 0;
|
||||||
sectorAlignment = 8; // Align partitions on 4096-byte boundaries by default
|
sectorAlignment = 8; // Align partitions on 4096-byte boundaries by default
|
||||||
srand((unsigned int) time(NULL));
|
srand((unsigned int) time(NULL));
|
||||||
|
mainHeader.numParts = 0;
|
||||||
SetGPTSize(NUM_GPT_ENTRIES);
|
SetGPTSize(NUM_GPT_ENTRIES);
|
||||||
} // GPTData default constructor
|
} // GPTData default constructor
|
||||||
|
|
||||||
@@ -68,6 +69,7 @@ GPTData::GPTData(char* filename) {
|
|||||||
bsdFound = 0;
|
bsdFound = 0;
|
||||||
sectorAlignment = 8; // Align partitions on 4096-byte boundaries by default
|
sectorAlignment = 8; // Align partitions on 4096-byte boundaries by default
|
||||||
srand((unsigned int) time(NULL));
|
srand((unsigned int) time(NULL));
|
||||||
|
mainHeader.numParts = 0;
|
||||||
LoadPartitions(filename);
|
LoadPartitions(filename);
|
||||||
} // GPTData(char* filename) constructor
|
} // GPTData(char* filename) constructor
|
||||||
|
|
||||||
@@ -601,9 +603,9 @@ int GPTData::ForceLoadGPTData(int fd) {
|
|||||||
uint32_t newCRC, sizeOfParts;
|
uint32_t newCRC, sizeOfParts;
|
||||||
|
|
||||||
// Seek to and read the main GPT header
|
// Seek to and read the main GPT header
|
||||||
lseek64(fd, 512, SEEK_SET);
|
lseek64(fd, blockSize, SEEK_SET);
|
||||||
if (read(fd, &mainHeader, 512) != 512) { // read main GPT header
|
if (myRead(fd, (char*) &mainHeader, 512) != 512) { // read main GPT header
|
||||||
fprintf(stderr, "Warning! Error %d reading secondary GPT header!", errno);
|
fprintf(stderr, "Warning! Error %d reading main GPT header!\n", errno);
|
||||||
} // if
|
} // if
|
||||||
mainCrcOk = CheckHeaderCRC(&mainHeader);
|
mainCrcOk = CheckHeaderCRC(&mainHeader);
|
||||||
if (IsLittleEndian() == 0) // big-endian system; adjust header byte order....
|
if (IsLittleEndian() == 0) // big-endian system; adjust header byte order....
|
||||||
@@ -618,19 +620,19 @@ int GPTData::ForceLoadGPTData(int fd) {
|
|||||||
if (mainHeader.backupLBA < diskSize) {
|
if (mainHeader.backupLBA < diskSize) {
|
||||||
seekTo = mainHeader.backupLBA * blockSize;
|
seekTo = mainHeader.backupLBA * blockSize;
|
||||||
} else {
|
} else {
|
||||||
seekTo = (diskSize * blockSize) - UINT64_C(512);
|
seekTo = (diskSize * blockSize) - blockSize;
|
||||||
printf("Warning! Disk size is smaller than the main header indicates! Loading\n"
|
printf("Warning! Disk size is smaller than the main header indicates! Loading\n"
|
||||||
"secondary header from the last sector of the disk! You should use 'v' to\n"
|
"secondary header from the last sector of the disk! You should use 'v' to\n"
|
||||||
"verify disk integrity, and perhaps options on the experts' menu to repair\n"
|
"verify disk integrity, and perhaps options on the experts' menu to repair\n"
|
||||||
"the disk.\n");
|
"the disk.\n");
|
||||||
} // else
|
} // else
|
||||||
} else {
|
} else {
|
||||||
seekTo = (diskSize * blockSize) - UINT64_C(512);
|
seekTo = (diskSize * blockSize) - blockSize;
|
||||||
} // if/else (mainCrcOk)
|
} // if/else (mainCrcOk)
|
||||||
|
|
||||||
if (lseek64(fd, seekTo, SEEK_SET) != (off_t) -1) {
|
if (lseek64(fd, seekTo, SEEK_SET) != (off_t) -1) {
|
||||||
if (read(fd, &secondHeader, 512) != 512) { // read secondary GPT header
|
if (myRead(fd, (char*) &secondHeader, 512) != 512) { // read secondary GPT header
|
||||||
fprintf(stderr, "Warning! Error %d reading secondary GPT header!", errno);
|
fprintf(stderr, "Warning! Error %d reading secondary GPT header!\n", errno);
|
||||||
} // if
|
} // if
|
||||||
secondCrcOk = CheckHeaderCRC(&secondHeader);
|
secondCrcOk = CheckHeaderCRC(&secondHeader);
|
||||||
if (IsLittleEndian() == 0) // big-endian system; adjust header byte order....
|
if (IsLittleEndian() == 0) // big-endian system; adjust header byte order....
|
||||||
@@ -681,7 +683,7 @@ int GPTData::ForceLoadGPTData(int fd) {
|
|||||||
if ((lseek64(fd, seekTo, SEEK_SET) != (off_t) -1) && (secondCrcOk)) {
|
if ((lseek64(fd, seekTo, SEEK_SET) != (off_t) -1) && (secondCrcOk)) {
|
||||||
sizeOfParts = secondHeader.numParts * secondHeader.sizeOfPartitionEntries;
|
sizeOfParts = secondHeader.numParts * secondHeader.sizeOfPartitionEntries;
|
||||||
storage = (char*) malloc(sizeOfParts);
|
storage = (char*) malloc(sizeOfParts);
|
||||||
if (read(fd, storage, sizeOfParts) != sizeOfParts) {
|
if (myRead(fd, storage, sizeOfParts) != sizeOfParts) {
|
||||||
fprintf(stderr, "Warning! Error %d reading backup partition table!\n", errno);
|
fprintf(stderr, "Warning! Error %d reading backup partition table!\n", errno);
|
||||||
} // if
|
} // if
|
||||||
newCRC = chksum_crc32((unsigned char*) storage, sizeOfParts);
|
newCRC = chksum_crc32((unsigned char*) storage, sizeOfParts);
|
||||||
@@ -716,7 +718,7 @@ int GPTData::LoadMainTable(void) {
|
|||||||
// matches the stored value
|
// matches the stored value
|
||||||
lseek64(fd, mainHeader.partitionEntriesLBA * blockSize, SEEK_SET);
|
lseek64(fd, mainHeader.partitionEntriesLBA * blockSize, SEEK_SET);
|
||||||
sizeOfParts = mainHeader.numParts * mainHeader.sizeOfPartitionEntries;
|
sizeOfParts = mainHeader.numParts * mainHeader.sizeOfPartitionEntries;
|
||||||
if (read(fd, partitions, sizeOfParts) != sizeOfParts) {
|
if (myRead(fd, (char*) partitions, sizeOfParts) != sizeOfParts) {
|
||||||
fprintf(stderr, "Warning! Error %d when loading the main partition table!\n", errno);
|
fprintf(stderr, "Warning! Error %d when loading the main partition table!\n", errno);
|
||||||
} // if
|
} // if
|
||||||
newCRC = chksum_crc32((unsigned char*) partitions, sizeOfParts);
|
newCRC = chksum_crc32((unsigned char*) partitions, sizeOfParts);
|
||||||
@@ -740,7 +742,7 @@ void GPTData::LoadSecondTableAsMain(void) {
|
|||||||
if (lseek64(fd, seekTo, SEEK_SET) != (off_t) -1) {
|
if (lseek64(fd, seekTo, SEEK_SET) != (off_t) -1) {
|
||||||
SetGPTSize(secondHeader.numParts);
|
SetGPTSize(secondHeader.numParts);
|
||||||
sizeOfParts = secondHeader.numParts * secondHeader.sizeOfPartitionEntries;
|
sizeOfParts = secondHeader.numParts * secondHeader.sizeOfPartitionEntries;
|
||||||
if (read(fd, partitions, sizeOfParts) != sizeOfParts) {
|
if (myRead(fd, (char*) partitions, sizeOfParts) != sizeOfParts) {
|
||||||
fprintf(stderr, "Warning! Read error %d! Misbehavior now likely!\n", errno);
|
fprintf(stderr, "Warning! Read error %d! Misbehavior now likely!\n", errno);
|
||||||
} // if
|
} // if
|
||||||
newCRC = chksum_crc32((unsigned char*) partitions, sizeOfParts);
|
newCRC = chksum_crc32((unsigned char*) partitions, sizeOfParts);
|
||||||
@@ -852,15 +854,21 @@ int GPTData::SaveGPTData(void) {
|
|||||||
protectiveMBR.WriteMBRData(fd);
|
protectiveMBR.WriteMBRData(fd);
|
||||||
|
|
||||||
// Now write the main GPT header...
|
// Now write the main GPT header...
|
||||||
if (allOK)
|
if (allOK) {
|
||||||
if (write(fd, &mainHeader, 512) == -1)
|
if (lseek64(fd, blockSize, SEEK_SET) != (off_t) -1) {
|
||||||
allOK = 0;
|
if (myWrite(fd, (char*) &mainHeader, 512) == -1)
|
||||||
|
allOK = 0;
|
||||||
|
} else allOK = 0; // if (lseek64()...)
|
||||||
|
} // if (allOK)
|
||||||
|
|
||||||
// Now write the main partition tables...
|
// Now write the main partition tables...
|
||||||
if (allOK) {
|
if (allOK) {
|
||||||
if (write(fd, partitions, GPT_SIZE * numParts) == -1)
|
offset = mainHeader.partitionEntriesLBA * blockSize;
|
||||||
|
if (lseek64(fd, offset, SEEK_SET) != (off_t) - 1) {
|
||||||
|
if (myWrite(fd, (char*) partitions, GPT_SIZE * numParts) == -1)
|
||||||
allOK = 0;
|
allOK = 0;
|
||||||
} // if
|
} else allOK = 0; // if (lseek64()...)
|
||||||
|
} // if (allOK)
|
||||||
|
|
||||||
// Now seek to near the end to write the secondary GPT....
|
// Now seek to near the end to write the secondary GPT....
|
||||||
if (allOK) {
|
if (allOK) {
|
||||||
@@ -872,14 +880,19 @@ int GPTData::SaveGPTData(void) {
|
|||||||
} // if
|
} // if
|
||||||
|
|
||||||
// Now write the secondary partition tables....
|
// Now write the secondary partition tables....
|
||||||
if (allOK)
|
if (allOK) {
|
||||||
if (write(fd, partitions, GPT_SIZE * numParts) == -1)
|
if (myWrite(fd, (char*) partitions, GPT_SIZE * numParts) == -1)
|
||||||
allOK = 0;
|
allOK = 0;
|
||||||
|
} // if (allOK)
|
||||||
|
|
||||||
// Now write the secondary GPT header...
|
// Now write the secondary GPT header...
|
||||||
if (allOK)
|
if (allOK) {
|
||||||
if (write(fd, &secondHeader, 512) == -1)
|
offset = mainHeader.backupLBA * blockSize;
|
||||||
allOK = 0;
|
if (lseek64(fd, offset, SEEK_SET) != (off_t) - 1) {
|
||||||
|
if (myWrite(fd, (char*) &secondHeader, 512) == -1)
|
||||||
|
allOK = 0;
|
||||||
|
} else allOK = 0; // if (lseek64()...)
|
||||||
|
} // if (allOK)
|
||||||
|
|
||||||
// re-read the partition table
|
// re-read the partition table
|
||||||
if (allOK) {
|
if (allOK) {
|
||||||
@@ -944,17 +957,17 @@ int GPTData::SaveGPTBackup(char* filename) {
|
|||||||
|
|
||||||
// Now write the main GPT header...
|
// Now write the main GPT header...
|
||||||
if (allOK)
|
if (allOK)
|
||||||
if (write(fd, &mainHeader, 512) == -1)
|
if (myWrite(fd, (char*) &mainHeader, 512) == -1)
|
||||||
allOK = 0;
|
allOK = 0;
|
||||||
|
|
||||||
// Now write the secondary GPT header...
|
// Now write the secondary GPT header...
|
||||||
if (allOK)
|
if (allOK)
|
||||||
if (write(fd, &secondHeader, 512) == -1)
|
if (myWrite(fd, (char*) &secondHeader, 512) == -1)
|
||||||
allOK = 0;
|
allOK = 0;
|
||||||
|
|
||||||
// Now write the main partition tables...
|
// Now write the main partition tables...
|
||||||
if (allOK) {
|
if (allOK) {
|
||||||
if (write(fd, partitions, GPT_SIZE * numParts) == -1)
|
if (myWrite(fd, (char*) partitions, GPT_SIZE * numParts) == -1)
|
||||||
allOK = 0;
|
allOK = 0;
|
||||||
} // if
|
} // if
|
||||||
|
|
||||||
@@ -997,7 +1010,7 @@ int GPTData::LoadGPTBackup(char* filename) {
|
|||||||
|
|
||||||
// Load the main GPT header, check its vaility, and set the GPT
|
// Load the main GPT header, check its vaility, and set the GPT
|
||||||
// size based on the data
|
// size based on the data
|
||||||
if (read(fd, &mainHeader, 512)) {
|
if (myRead(fd, (char*) &mainHeader, 512)) {
|
||||||
fprintf(stderr, "Warning! Read error %d; strange behavior now likely!\n", errno);
|
fprintf(stderr, "Warning! Read error %d; strange behavior now likely!\n", errno);
|
||||||
} // if
|
} // if
|
||||||
mainCrcOk = CheckHeaderCRC(&mainHeader);
|
mainCrcOk = CheckHeaderCRC(&mainHeader);
|
||||||
@@ -1009,7 +1022,7 @@ int GPTData::LoadGPTBackup(char* filename) {
|
|||||||
|
|
||||||
// Load the backup GPT header in much the same way as the main
|
// Load the backup GPT header in much the same way as the main
|
||||||
// GPT header....
|
// GPT header....
|
||||||
if (read(fd, &secondHeader, 512) != 512) {
|
if (myRead(fd, (char*) &secondHeader, 512) != 512) {
|
||||||
fprintf(stderr, "Warning! Read error %d; strange behavior now likely!\n", errno);
|
fprintf(stderr, "Warning! Read error %d; strange behavior now likely!\n", errno);
|
||||||
} // if
|
} // if
|
||||||
secondCrcOk = CheckHeaderCRC(&secondHeader);
|
secondCrcOk = CheckHeaderCRC(&secondHeader);
|
||||||
@@ -1045,7 +1058,7 @@ int GPTData::LoadGPTBackup(char* filename) {
|
|||||||
// Load main partition table, and record whether its CRC
|
// Load main partition table, and record whether its CRC
|
||||||
// matches the stored value
|
// matches the stored value
|
||||||
sizeOfParts = numParts * sizeOfEntries;
|
sizeOfParts = numParts * sizeOfEntries;
|
||||||
if (read(fd, partitions, sizeOfParts) != sizeOfParts) {
|
if (myRead(fd, (char*) partitions, sizeOfParts) != sizeOfParts) {
|
||||||
fprintf(stderr, "Warning! Read error %d; strange behavior now likely!\n", errno);
|
fprintf(stderr, "Warning! Read error %d; strange behavior now likely!\n", errno);
|
||||||
} // if
|
} // if
|
||||||
|
|
||||||
@@ -1109,6 +1122,7 @@ void GPTData::DisplayGPTData(void) {
|
|||||||
BytesToSI(diskSize * blockSize, sizeInSI);
|
BytesToSI(diskSize * blockSize, sizeInSI);
|
||||||
printf("Disk %s: %llu sectors, %s\n", device,
|
printf("Disk %s: %llu sectors, %s\n", device,
|
||||||
(unsigned long long) diskSize, sizeInSI);
|
(unsigned long long) diskSize, sizeInSI);
|
||||||
|
printf("Logical sector size: %d bytes\n", blockSize);
|
||||||
printf("Disk identifier (GUID): %s\n", GUIDToStr(mainHeader.diskGUID, tempStr));
|
printf("Disk identifier (GUID): %s\n", GUIDToStr(mainHeader.diskGUID, tempStr));
|
||||||
printf("Partition table holds up to %lu entries\n", (unsigned long) mainHeader.numParts);
|
printf("Partition table holds up to %lu entries\n", (unsigned long) mainHeader.numParts);
|
||||||
printf("First usable sector is %llu, last usable sector is %llu\n",
|
printf("First usable sector is %llu, last usable sector is %llu\n",
|
||||||
@@ -1302,8 +1316,9 @@ void GPTData::SetAttributes(uint32_t partNum) {
|
|||||||
// If prompt == 0, don't ask user about proceeding and do NOT wipe out
|
// If prompt == 0, don't ask user about proceeding and do NOT wipe out
|
||||||
// MBR. (Set prompt == 0 when doing a GPT-to-MBR conversion.)
|
// MBR. (Set prompt == 0 when doing a GPT-to-MBR conversion.)
|
||||||
int GPTData::DestroyGPT(int prompt) {
|
int GPTData::DestroyGPT(int prompt) {
|
||||||
int fd, i, sum;
|
int fd, i, sum, tableSize;
|
||||||
char blankSector[512], goOn = 'Y', blank = 'N';
|
char blankSector[512], goOn = 'Y', blank = 'N';
|
||||||
|
char* emptyTable;
|
||||||
|
|
||||||
for (i = 0; i < 512; i++) {
|
for (i = 0; i < 512; i++) {
|
||||||
blankSector[i] = '\0';
|
blankSector[i] = '\0';
|
||||||
@@ -1326,24 +1341,24 @@ int GPTData::DestroyGPT(int prompt) {
|
|||||||
} // if
|
} // if
|
||||||
#endif
|
#endif
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
lseek64(fd, mainHeader.currentLBA * 512, SEEK_SET); // seek to GPT header
|
lseek64(fd, mainHeader.currentLBA * blockSize, SEEK_SET); // seek to GPT header
|
||||||
if (write(fd, blankSector, 512) != 512) { // blank it out
|
if (myWrite(fd, blankSector, 512) != 512) { // blank it out
|
||||||
fprintf(stderr, "Warning! GPT main header not overwritten! Error is %d\n", errno);
|
fprintf(stderr, "Warning! GPT main header not overwritten! Error is %d\n", errno);
|
||||||
} // if
|
} // if
|
||||||
lseek64(fd, mainHeader.partitionEntriesLBA * 512, SEEK_SET); // seek to partition table
|
lseek64(fd, mainHeader.partitionEntriesLBA * blockSize, SEEK_SET); // seek to partition table
|
||||||
sum = 0;
|
tableSize = mainHeader.numParts * mainHeader.sizeOfPartitionEntries;
|
||||||
for (i = 0; i < GetBlocksInPartTable(); i++)
|
emptyTable = (char*) malloc(tableSize);
|
||||||
sum += write(fd, blankSector, 512);
|
for (i = 0; i < tableSize; i++)
|
||||||
if (sum != 512 * GetBlocksInPartTable())
|
emptyTable[i] = (char) 0;
|
||||||
|
sum = myWrite(fd, emptyTable, tableSize);
|
||||||
|
if (sum != tableSize)
|
||||||
fprintf(stderr, "Warning! GPT main partition table not overwritten! Error is %d\n", errno);
|
fprintf(stderr, "Warning! GPT main partition table not overwritten! Error is %d\n", errno);
|
||||||
lseek64(fd, secondHeader.partitionEntriesLBA * 512, SEEK_SET); // seek to partition table
|
lseek64(fd, secondHeader.partitionEntriesLBA * blockSize, SEEK_SET); // seek to partition table
|
||||||
sum = 0;
|
sum = myWrite(fd, emptyTable, tableSize);
|
||||||
for (i = 0; i < GetBlocksInPartTable(); i++)
|
if (sum != tableSize)
|
||||||
sum += write(fd, blankSector, 512);
|
|
||||||
if (sum != 512 * GetBlocksInPartTable())
|
|
||||||
fprintf(stderr, "Warning! GPT backup partition table not overwritten! Error is %d\n", errno);
|
fprintf(stderr, "Warning! GPT backup partition table not overwritten! Error is %d\n", errno);
|
||||||
lseek64(fd, secondHeader.currentLBA * 512, SEEK_SET); // seek to GPT header
|
lseek64(fd, secondHeader.currentLBA * blockSize, SEEK_SET); // seek to GPT header
|
||||||
if (write(fd, blankSector, 512) != 512) { // blank it out
|
if (myWrite(fd, blankSector, 512) != 512) { // blank it out
|
||||||
fprintf(stderr, "Warning! GPT backup header not overwritten! Error is %d\n", errno);
|
fprintf(stderr, "Warning! GPT backup header not overwritten! Error is %d\n", errno);
|
||||||
} // if
|
} // if
|
||||||
if (prompt) {
|
if (prompt) {
|
||||||
@@ -1357,7 +1372,7 @@ int GPTData::DestroyGPT(int prompt) {
|
|||||||
// structures).
|
// structures).
|
||||||
if (blank == 'Y') {
|
if (blank == 'Y') {
|
||||||
lseek64(fd, 0, SEEK_SET);
|
lseek64(fd, 0, SEEK_SET);
|
||||||
if (write(fd, blankSector, 512) != 512) { // blank it out
|
if (myWrite(fd, blankSector, 512) != 512) { // blank it out
|
||||||
fprintf(stderr, "Warning! MBR not overwritten! Error is %d!\n", errno);
|
fprintf(stderr, "Warning! MBR not overwritten! Error is %d!\n", errno);
|
||||||
} // if
|
} // if
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
2
gpt.h
2
gpt.h
@@ -145,8 +145,6 @@ public:
|
|||||||
uint64_t GetSecondHeaderLBA(void) {return secondHeader.currentLBA;}
|
uint64_t GetSecondHeaderLBA(void) {return secondHeader.currentLBA;}
|
||||||
uint64_t GetMainPartsLBA(void) {return mainHeader.partitionEntriesLBA;}
|
uint64_t GetMainPartsLBA(void) {return mainHeader.partitionEntriesLBA;}
|
||||||
uint64_t GetSecondPartsLBA(void) {return secondHeader.partitionEntriesLBA;}
|
uint64_t GetSecondPartsLBA(void) {return secondHeader.partitionEntriesLBA;}
|
||||||
uint64_t GetBlocksInPartTable(void) {return (mainHeader.numParts *
|
|
||||||
mainHeader.sizeOfPartitionEntries) / blockSize;}
|
|
||||||
uint32_t CountParts(void);
|
uint32_t CountParts(void);
|
||||||
int GetAlignment(void) {return sectorAlignment;}
|
int GetAlignment(void) {return sectorAlignment;}
|
||||||
|
|
||||||
|
|||||||
6
mbr.cc
6
mbr.cc
@@ -98,7 +98,7 @@ void MBRData::ReadMBRData(int fd, int checkBlockSize) {
|
|||||||
EmptyMBR(0);
|
EmptyMBR(0);
|
||||||
|
|
||||||
err = lseek64(fd, 0, SEEK_SET);
|
err = lseek64(fd, 0, SEEK_SET);
|
||||||
err = read(fd, &tempMBR, 512);
|
err = myRead(fd, (char*) &tempMBR, 512);
|
||||||
for (i = 0; i < 440; i++)
|
for (i = 0; i < 440; i++)
|
||||||
code[i] = tempMBR.code[i];
|
code[i] = tempMBR.code[i];
|
||||||
diskSignature = tempMBR.diskSignature;
|
diskSignature = tempMBR.diskSignature;
|
||||||
@@ -202,7 +202,7 @@ int MBRData::ReadLogicalPart(int fd, uint32_t extendedStart,
|
|||||||
fprintf(stderr, "Unable to seek to %lu! Aborting!\n", (unsigned long) offset);
|
fprintf(stderr, "Unable to seek to %lu! Aborting!\n", (unsigned long) offset);
|
||||||
partNum = -1;
|
partNum = -1;
|
||||||
}
|
}
|
||||||
if (read(fd, &ebr, 512) != 512) { // Load the data....
|
if (myRead(fd, (char*) &ebr, 512) != 512) { // Load the data....
|
||||||
fprintf(stderr, "Error seeking to or reading logical partition data from %lu!\nAborting!\n",
|
fprintf(stderr, "Error seeking to or reading logical partition data from %lu!\nAborting!\n",
|
||||||
(unsigned long) offset);
|
(unsigned long) offset);
|
||||||
partNum = -1;
|
partNum = -1;
|
||||||
@@ -289,7 +289,7 @@ void MBRData::WriteMBRData(int fd) {
|
|||||||
|
|
||||||
// Now write that data structure...
|
// Now write that data structure...
|
||||||
lseek64(fd, 0, SEEK_SET);
|
lseek64(fd, 0, SEEK_SET);
|
||||||
if (write(fd, &tempMBR, 512) != 512) {
|
if (myWrite(fd, (char*) &tempMBR, 512) != 512) {
|
||||||
fprintf(stderr, "Warning! Error %d when saving MBR!\n", errno);
|
fprintf(stderr, "Warning! Error %d when saving MBR!\n", errno);
|
||||||
} // if
|
} // if
|
||||||
|
|
||||||
|
|||||||
464
sgdisk.cc
Normal file
464
sgdisk.cc
Normal file
@@ -0,0 +1,464 @@
|
|||||||
|
// sgdisk.cc
|
||||||
|
// Program modelled after Linux sfdisk, but it manipulates GPT partitions
|
||||||
|
// rather than MBR partitions. This is effectively a new user interface
|
||||||
|
// to my gdisk program.
|
||||||
|
//
|
||||||
|
// by Rod Smith, project began February 2009
|
||||||
|
|
||||||
|
/* This program is copyright (c) 2009, 2010 by Roderick W. Smith. It is distributed
|
||||||
|
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||||
|
|
||||||
|
//#include <iostream>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include "mbr.h"
|
||||||
|
#include "gpt.h"
|
||||||
|
#include "support.h"
|
||||||
|
|
||||||
|
#define MAX_OPTIONS 50
|
||||||
|
|
||||||
|
// Function prototypes....
|
||||||
|
/* void MainMenu(char* filename, struct GPTData* theGPT);
|
||||||
|
void ShowCommands(void);
|
||||||
|
void ExpertsMenu(char* filename, struct GPTData* theGPT);
|
||||||
|
void ShowExpertCommands(void);
|
||||||
|
void RecoveryMenu(char* filename, struct GPTData* theGPT);
|
||||||
|
void ShowRecoveryCommands(void); */
|
||||||
|
|
||||||
|
enum Commands { NONE, LIST, VERIFY };
|
||||||
|
|
||||||
|
struct Options {
|
||||||
|
Commands theCommand;
|
||||||
|
char* theArgument;
|
||||||
|
}; // struct Options
|
||||||
|
|
||||||
|
int verbose_flag;
|
||||||
|
|
||||||
|
static struct option long_options[] =
|
||||||
|
{
|
||||||
|
{"verify", no_argument, NULL, 'v'},
|
||||||
|
{"list", no_argument, NULL, 'l'},
|
||||||
|
{0, 0, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
int ParseOptions(int argc, char* argv[], Options* theOptions, char** device);
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
GPTData theGPT;
|
||||||
|
int doMore = 1, opt, i, numOptions = 0;
|
||||||
|
char* device = NULL;
|
||||||
|
Options theOptions[MAX_OPTIONS];
|
||||||
|
|
||||||
|
printf("GPT fdisk (sgdisk) version 0.5.4-pre1\n\n");
|
||||||
|
numOptions = ParseOptions(argc, argv, theOptions, &device);
|
||||||
|
|
||||||
|
if (device != NULL) {
|
||||||
|
if (theGPT.LoadPartitions(device)) {
|
||||||
|
for (i = 0; i < numOptions; i++) {
|
||||||
|
switch (theOptions[i].theCommand) {
|
||||||
|
case LIST:
|
||||||
|
theGPT.JustLooking();
|
||||||
|
theGPT.DisplayGPTData();
|
||||||
|
break;
|
||||||
|
case VERIFY:
|
||||||
|
theGPT.JustLooking();
|
||||||
|
theGPT.Verify();
|
||||||
|
break;
|
||||||
|
case NONE:
|
||||||
|
printf("Usage: %s {-lv} device\n", argv[0]);
|
||||||
|
break;
|
||||||
|
} // switch
|
||||||
|
} // for
|
||||||
|
} // if loaded OK
|
||||||
|
} // if (device != NULL)
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} // main
|
||||||
|
|
||||||
|
// Parse command-line options. Returns the number of arguments retrieved
|
||||||
|
int ParseOptions(int argc, char* argv[], Options* theOptions, char** device) {
|
||||||
|
int opt, i, numOptions = 0;
|
||||||
|
int verbose_flag;
|
||||||
|
|
||||||
|
// Use getopt() to extract commands and their arguments
|
||||||
|
/* getopt_long stores the option index here. */
|
||||||
|
int option_index = 0;
|
||||||
|
|
||||||
|
// c = getopt_long (argc, argv, "abc:d:f:",
|
||||||
|
// long_options, &option_index);
|
||||||
|
|
||||||
|
while (((opt = getopt_long(argc, argv, "vl", long_options, &option_index)) != -1)
|
||||||
|
&& (numOptions < MAX_OPTIONS)) {
|
||||||
|
printf("opt is %c, option_index is %d\n", opt, option_index);
|
||||||
|
switch (opt) {
|
||||||
|
case 'l':
|
||||||
|
printf("Entering list option, numOptions = %d!\n", numOptions);
|
||||||
|
theOptions[numOptions].theCommand = LIST;
|
||||||
|
theOptions[numOptions++].theArgument = NULL;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
theOptions[numOptions].theCommand = VERIFY;
|
||||||
|
theOptions[numOptions++].theArgument = NULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Default switch; opt is %c\n", opt);
|
||||||
|
break;
|
||||||
|
// abort();
|
||||||
|
} // switch
|
||||||
|
} // while
|
||||||
|
|
||||||
|
// Find non-option arguments. If the user types a legal command, there
|
||||||
|
// will be only one of these: The device filename....
|
||||||
|
opt = 0;
|
||||||
|
printf("Searching for device filename; optind is %d\n", optind);
|
||||||
|
for (i = optind; i < argc; i++) {
|
||||||
|
*device = argv[i];
|
||||||
|
printf("Setting device to %s\n", argv[i]);
|
||||||
|
opt++;
|
||||||
|
} // for
|
||||||
|
if (opt > 1) {
|
||||||
|
fprintf(stderr, "Warning! Found stray unrecognized arguments! Program may misbehave!\n");
|
||||||
|
} // if
|
||||||
|
|
||||||
|
return numOptions;
|
||||||
|
} // ParseOptions()
|
||||||
|
|
||||||
|
/* // 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) {
|
||||||
|
char command, line[255], buFile[255];
|
||||||
|
char* junk;
|
||||||
|
int goOn = 1;
|
||||||
|
PartTypes typeHelper;
|
||||||
|
uint32_t temp1, temp2;
|
||||||
|
|
||||||
|
do {
|
||||||
|
printf("\nCommand (? for help): ");
|
||||||
|
junk = fgets(line, 255, stdin);
|
||||||
|
sscanf(line, "%c", &command);
|
||||||
|
switch (command) {
|
||||||
|
case 'b': case 'B':
|
||||||
|
printf("Enter backup filename to save: ");
|
||||||
|
junk = fgets(line, 255, stdin);
|
||||||
|
sscanf(line, "%s", (char*) &buFile);
|
||||||
|
theGPT->SaveGPTBackup(buFile);
|
||||||
|
break;
|
||||||
|
case 'c': case 'C':
|
||||||
|
if (theGPT->GetPartRange(&temp1, &temp2) > 0)
|
||||||
|
theGPT->SetName(theGPT->GetPartNum());
|
||||||
|
else
|
||||||
|
printf("No partitions\n");
|
||||||
|
break;
|
||||||
|
case 'd': case 'D':
|
||||||
|
theGPT->DeletePartition();
|
||||||
|
break;
|
||||||
|
case 'i': case 'I':
|
||||||
|
theGPT->ShowDetails();
|
||||||
|
break;
|
||||||
|
case 'l': case 'L':
|
||||||
|
typeHelper.ShowTypes();
|
||||||
|
break;
|
||||||
|
case 'n': case 'N':
|
||||||
|
theGPT->CreatePartition();
|
||||||
|
break;
|
||||||
|
case 'o': case 'O':
|
||||||
|
printf("This option deletes all partitions and creates a new "
|
||||||
|
"protective MBR.\nProceed? ");
|
||||||
|
if (GetYN() == 'Y') {
|
||||||
|
theGPT->ClearGPTData();
|
||||||
|
theGPT->MakeProtectiveMBR();
|
||||||
|
} // if
|
||||||
|
break;
|
||||||
|
case 'p': case 'P':
|
||||||
|
theGPT->DisplayGPTData();
|
||||||
|
break;
|
||||||
|
case 'q': case 'Q':
|
||||||
|
goOn = 0;
|
||||||
|
break;
|
||||||
|
case 'r': case 'R':
|
||||||
|
RecoveryMenu(filename, theGPT);
|
||||||
|
goOn = 0;
|
||||||
|
break;
|
||||||
|
case 's': case 'S':
|
||||||
|
theGPT->SortGPT();
|
||||||
|
printf("You may need to edit /etc/fstab and/or your boot loader configuration!\n");
|
||||||
|
break;
|
||||||
|
case 't': case 'T':
|
||||||
|
theGPT->ChangePartType();
|
||||||
|
break;
|
||||||
|
case 'v': case 'V':
|
||||||
|
if (theGPT->Verify() > 0) { // problems found
|
||||||
|
printf("You may be able to correct the problems by using options on the experts\n"
|
||||||
|
"menu (press 'x' at the command prompt). Good luck!\n");
|
||||||
|
} // if
|
||||||
|
break;
|
||||||
|
case 'w': case 'W':
|
||||||
|
if (theGPT->SaveGPTData() == 1)
|
||||||
|
goOn = 0;
|
||||||
|
break;
|
||||||
|
case 'x': case 'X':
|
||||||
|
ExpertsMenu(filename, theGPT);
|
||||||
|
goOn = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ShowCommands();
|
||||||
|
break;
|
||||||
|
} // switch
|
||||||
|
} while (goOn);
|
||||||
|
} // 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");
|
||||||
|
} // 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) {
|
||||||
|
char command, line[255], buFile[255];
|
||||||
|
char* junk;
|
||||||
|
PartTypes typeHelper;
|
||||||
|
uint32_t temp1;
|
||||||
|
int goOn = 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
printf("\nrecovery/transformation command (? for help): ");
|
||||||
|
junk = fgets(line, 255, stdin);
|
||||||
|
sscanf(line, "%c", &command);
|
||||||
|
switch (command) {
|
||||||
|
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? ");
|
||||||
|
if (GetYN() == 'Y')
|
||||||
|
theGPT->LoadSecondTableAsMain();
|
||||||
|
break;
|
||||||
|
case 'd': case 'D':
|
||||||
|
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? ");
|
||||||
|
if (GetYN() == 'Y')
|
||||||
|
theGPT->LoadMainTable();
|
||||||
|
break;
|
||||||
|
case 'f': case 'F':
|
||||||
|
printf("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");
|
||||||
|
theGPT->MakeProtectiveMBR();
|
||||||
|
} // if/else
|
||||||
|
} // if
|
||||||
|
break;
|
||||||
|
case 'g': case 'G':
|
||||||
|
temp1 = theGPT->XFormToMBR();
|
||||||
|
if (temp1 > 0) {
|
||||||
|
printf("Converted %d partitions. Finalize and exit? ", temp1);
|
||||||
|
if (GetYN() == 'Y') {
|
||||||
|
if (theGPT->DestroyGPT(0) > 0)
|
||||||
|
goOn = 0;
|
||||||
|
} else {
|
||||||
|
theGPT->MakeProtectiveMBR();
|
||||||
|
printf("Note: New protective MBR created.\n");
|
||||||
|
} // if/else
|
||||||
|
} // if
|
||||||
|
break;
|
||||||
|
case 'h': case 'H':
|
||||||
|
theGPT->MakeHybrid();
|
||||||
|
break;
|
||||||
|
case 'i': case 'I':
|
||||||
|
theGPT->ShowDetails();
|
||||||
|
break;
|
||||||
|
case 'l': case 'L':
|
||||||
|
printf("Enter backup filename to load: ");
|
||||||
|
junk = fgets(line, 255, stdin);
|
||||||
|
sscanf(line, "%s", (char*) &buFile);
|
||||||
|
theGPT->LoadGPTBackup(buFile);
|
||||||
|
break;
|
||||||
|
case 'm': case 'M':
|
||||||
|
MainMenu(filename, theGPT);
|
||||||
|
goOn = 0;
|
||||||
|
break;
|
||||||
|
case 'o': case 'O':
|
||||||
|
theGPT->DisplayMBRData();
|
||||||
|
break;
|
||||||
|
case 'p': case 'P':
|
||||||
|
theGPT->DisplayGPTData();
|
||||||
|
break;
|
||||||
|
case 'q': case 'Q':
|
||||||
|
goOn = 0;
|
||||||
|
break;
|
||||||
|
case 't': case 'T':
|
||||||
|
theGPT->XFormDisklabel();
|
||||||
|
break;
|
||||||
|
case 'v': case 'V':
|
||||||
|
theGPT->Verify();
|
||||||
|
break;
|
||||||
|
case 'w': case 'W':
|
||||||
|
if (theGPT->SaveGPTData() == 1) {
|
||||||
|
goOn = 0;
|
||||||
|
} // if
|
||||||
|
break;
|
||||||
|
case 'x': case 'X':
|
||||||
|
ExpertsMenu(filename, theGPT);
|
||||||
|
goOn = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ShowRecoveryCommands();
|
||||||
|
break;
|
||||||
|
} // switch
|
||||||
|
} while (goOn);
|
||||||
|
} // 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");
|
||||||
|
} // 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) {
|
||||||
|
char command, line[255];
|
||||||
|
char* junk;
|
||||||
|
PartTypes typeHelper;
|
||||||
|
uint32_t pn;
|
||||||
|
uint32_t temp1, temp2;
|
||||||
|
int goOn = 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
printf("\nExpert command (? for help): ");
|
||||||
|
junk = fgets(line, 255, stdin);
|
||||||
|
sscanf(line, "%c", &command);
|
||||||
|
switch (command) {
|
||||||
|
case 'a': case 'A':
|
||||||
|
if (theGPT->GetPartRange(&temp1, &temp2) > 0)
|
||||||
|
theGPT->SetAttributes(theGPT->GetPartNum());
|
||||||
|
else
|
||||||
|
printf("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");
|
||||||
|
theGPT->SetPartitionGUID(pn, GetGUID());
|
||||||
|
} else printf("No partitions\n");
|
||||||
|
break;
|
||||||
|
case 'd': case 'D':
|
||||||
|
printf("The number of logical sectors per physical sector is %d.\n",
|
||||||
|
theGPT->GetAlignment());
|
||||||
|
break;
|
||||||
|
case 'e': case 'E':
|
||||||
|
printf("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");
|
||||||
|
theGPT->SetDiskGUID(GetGUID());
|
||||||
|
break;
|
||||||
|
case 'i': case 'I':
|
||||||
|
theGPT->ShowDetails();
|
||||||
|
break;
|
||||||
|
case 'l': case 'L':
|
||||||
|
temp1 = GetNumber(1, 128, 8, "Enter the number of logical sectors in a physical sector on the\ndisk (1-128, default = 8): ");
|
||||||
|
theGPT->SetAlignment(temp1);
|
||||||
|
break;
|
||||||
|
case 'm': case 'M':
|
||||||
|
MainMenu(filename, theGPT);
|
||||||
|
goOn = 0;
|
||||||
|
break;
|
||||||
|
case 'n': case 'N':
|
||||||
|
theGPT->MakeProtectiveMBR();
|
||||||
|
break;
|
||||||
|
case 'o': case 'O':
|
||||||
|
theGPT->DisplayMBRData();
|
||||||
|
break;
|
||||||
|
case 'p': case 'P':
|
||||||
|
theGPT->DisplayGPTData();
|
||||||
|
break;
|
||||||
|
case 'q': case 'Q':
|
||||||
|
goOn = 0;
|
||||||
|
break;
|
||||||
|
case 'r': case 'R':
|
||||||
|
RecoveryMenu(filename, theGPT);
|
||||||
|
goOn = 0;
|
||||||
|
break;
|
||||||
|
case 's': case 'S':
|
||||||
|
theGPT->ResizePartitionTable();
|
||||||
|
break;
|
||||||
|
case 'v': case 'V':
|
||||||
|
theGPT->Verify();
|
||||||
|
break;
|
||||||
|
case 'w': case 'W':
|
||||||
|
if (theGPT->SaveGPTData() == 1) {
|
||||||
|
goOn = 0;
|
||||||
|
} // if
|
||||||
|
break;
|
||||||
|
case 'z': case 'Z':
|
||||||
|
if (theGPT->DestroyGPT() == 1) {
|
||||||
|
goOn = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ShowExpertCommands();
|
||||||
|
break;
|
||||||
|
} // switch
|
||||||
|
} while (goOn);
|
||||||
|
} // ExpertsMenu()
|
||||||
|
|
||||||
|
void ShowExpertCommands(void) {
|
||||||
|
printf("a\tset attributes\n");
|
||||||
|
printf("c\tchange partition GUID\n");
|
||||||
|
printf("d\tdisplay the number of logical sectors per physical sector\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("b\tset the number of logical sectors per physical sector\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");
|
||||||
|
} // ShowExpertCommands()
|
||||||
|
*/
|
||||||
88
support.cc
88
support.cc
@@ -223,10 +223,10 @@ int GetBlockSize(int fd) {
|
|||||||
} // if
|
} // if
|
||||||
} // if
|
} // if
|
||||||
|
|
||||||
if (result != 512) {
|
/* if (result != 512) {
|
||||||
printf("\aWARNING! Sector size is not 512 bytes! This program is likely to ");
|
printf("\aWARNING! Sector size is not 512 bytes! This program is likely to ");
|
||||||
printf("misbehave!\nProceed at your own risk!\n\n");
|
printf("misbehave!\nProceed at your own risk!\n\n");
|
||||||
} // if
|
} // if */
|
||||||
|
|
||||||
return (result);
|
return (result);
|
||||||
} // GetBlockSize()
|
} // GetBlockSize()
|
||||||
@@ -244,9 +244,12 @@ int FindAlignment(int fd) {
|
|||||||
err = -1;
|
err = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (err < 0) {
|
if (err < 0) { // ioctl didn't work; have to guess....
|
||||||
result = 8;
|
if (GetBlockSize(fd) == 512)
|
||||||
} else {
|
result = 8; // play it safe; align for 4096-byte sectors
|
||||||
|
else
|
||||||
|
result = 1; // unusual sector size; assume it's the real physical size
|
||||||
|
} else { // ioctl worked; compute alignment
|
||||||
result = physicalSectorSize / GetBlockSize(fd);
|
result = physicalSectorSize / GetBlockSize(fd);
|
||||||
} // if/else
|
} // if/else
|
||||||
return result;
|
return result;
|
||||||
@@ -501,7 +504,9 @@ uint64_t disksize(int fd, int *err) {
|
|||||||
else
|
else
|
||||||
sectors = (b >> 9);
|
sectors = (b >> 9);
|
||||||
} // if
|
} // if
|
||||||
|
// Unintuitively, the above returns values in 512-byte blocks, no
|
||||||
|
// matter what the underlying device's block size. Correct for this....
|
||||||
|
sectors /= (GetBlockSize(fd) / 512);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -517,7 +522,72 @@ uint64_t disksize(int fd, int *err) {
|
|||||||
sectors = bytes / UINT64_C(512);
|
sectors = bytes / UINT64_C(512);
|
||||||
} // if
|
} // if
|
||||||
} // if
|
} // if
|
||||||
// sectors = 25000000;
|
|
||||||
// printf("Returning bogus sector size: %d\n", sectors);
|
|
||||||
return sectors;
|
return sectors;
|
||||||
}
|
} // disksize()
|
||||||
|
|
||||||
|
// A variant on the standard read() function. Done to work around
|
||||||
|
// limitations in FreeBSD concerning the matching of the sector
|
||||||
|
// size with the number of bytes read
|
||||||
|
int myRead(int fd, char* buffer, int numBytes) {
|
||||||
|
int blockSize = 512, i, numBlocks, retval;
|
||||||
|
char* tempSpace;
|
||||||
|
|
||||||
|
// Compute required space and allocate memory
|
||||||
|
blockSize = GetBlockSize(fd);
|
||||||
|
if (numBytes <= blockSize) {
|
||||||
|
numBlocks = 1;
|
||||||
|
tempSpace = (char*) malloc(blockSize);
|
||||||
|
} else {
|
||||||
|
numBlocks = numBytes / blockSize;
|
||||||
|
if ((numBytes % blockSize) != 0) numBlocks++;
|
||||||
|
tempSpace = (char*) malloc(numBlocks * blockSize);
|
||||||
|
} // if/else
|
||||||
|
|
||||||
|
// Read the data into temporary space, then copy it to buffer
|
||||||
|
retval = read(fd, tempSpace, numBlocks * blockSize);
|
||||||
|
for (i = 0; i < numBytes; i++) {
|
||||||
|
buffer[i] = tempSpace[i];
|
||||||
|
} // for
|
||||||
|
|
||||||
|
// Adjust the return value, if necessary....
|
||||||
|
if (((numBlocks * blockSize) != numBytes) && (retval > 0))
|
||||||
|
retval = numBytes;
|
||||||
|
|
||||||
|
free(tempSpace);
|
||||||
|
return retval;
|
||||||
|
} // myRead()
|
||||||
|
|
||||||
|
// A variant on the standard write() function. Done to work around
|
||||||
|
// limitations in FreeBSD concerning the matching of the sector
|
||||||
|
// size with the number of bytes read
|
||||||
|
int myWrite(int fd, char* buffer, int numBytes) {
|
||||||
|
int blockSize = 512, i, numBlocks, retval;
|
||||||
|
char* tempSpace;
|
||||||
|
|
||||||
|
// Compute required space and allocate memory
|
||||||
|
blockSize = GetBlockSize(fd);
|
||||||
|
if (numBytes <= blockSize) {
|
||||||
|
numBlocks = 1;
|
||||||
|
tempSpace = (char*) malloc(blockSize);
|
||||||
|
} else {
|
||||||
|
numBlocks = numBytes / blockSize;
|
||||||
|
if ((numBytes % blockSize) != 0) numBlocks++;
|
||||||
|
tempSpace = (char*) malloc(numBlocks * blockSize);
|
||||||
|
} // if/else
|
||||||
|
|
||||||
|
// Copy the data to my own buffer, then write it
|
||||||
|
for (i = 0; i < numBytes; i++) {
|
||||||
|
tempSpace[i] = buffer[i];
|
||||||
|
} // for
|
||||||
|
for (i = numBytes; i < numBlocks * blockSize; i++) {
|
||||||
|
tempSpace[i] = 0;
|
||||||
|
} // for
|
||||||
|
retval = write(fd, tempSpace, numBlocks * blockSize);
|
||||||
|
|
||||||
|
// Adjust the return value, if necessary....
|
||||||
|
if (((numBlocks * blockSize) != numBytes) && (retval > 0))
|
||||||
|
retval = numBytes;
|
||||||
|
|
||||||
|
free(tempSpace);
|
||||||
|
return retval;
|
||||||
|
} // myRead()
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ int IsLittleEndian(void); // Returns 1 if CPU is little-endian, 0 if it's big-en
|
|||||||
void ReverseBytes(void* theValue, int numBytes); // Reverses byte-order of theValue
|
void ReverseBytes(void* theValue, int numBytes); // Reverses byte-order of theValue
|
||||||
uint64_t PowerOf2(int value);
|
uint64_t PowerOf2(int value);
|
||||||
int OpenForWrite(char* deviceFilename);
|
int OpenForWrite(char* deviceFilename);
|
||||||
|
int myRead(int fd, char* buffer, int numBytes);
|
||||||
|
int myWrite(int fd, char* buffer, int numBytes);
|
||||||
void DiskSync(int fd); // resync disk caches to use new partitions
|
void DiskSync(int fd); // resync disk caches to use new partitions
|
||||||
|
|
||||||
uint64_t disksize(int fd, int* err);
|
uint64_t disksize(int fd, int* err);
|
||||||
|
|||||||
Reference in New Issue
Block a user