Updates for version 0.4.2
New feature: Ability to edit disk images. Several small bug fixes and feature enhancements (see CHANGELOG).
This commit is contained in:
27
CHANGELOG
27
CHANGELOG
@@ -1,3 +1,30 @@
|
|||||||
|
0.4.2:
|
||||||
|
------
|
||||||
|
|
||||||
|
- Code cleanup.
|
||||||
|
|
||||||
|
- Fixed very small formatting bug in display of hex code when a match isn't
|
||||||
|
found when converting from an MBR/gdisk hex code to a GUID type code.
|
||||||
|
|
||||||
|
- Added the ability to work on disk image files (raw files for virtual
|
||||||
|
machines, backup images, etc.). The program assumes that all such disk
|
||||||
|
image files have 512-byte sectors.
|
||||||
|
|
||||||
|
- Added verification prompt to 'o' main-menu option to avoid accidental
|
||||||
|
erasures of all partitions.
|
||||||
|
|
||||||
|
- The "destroy GPT data structures" option ('z' on the experts' menu) now
|
||||||
|
also destroys all EFI GPT (0xEE) partitions in the MBR.
|
||||||
|
|
||||||
|
- Added an extra warning to the "destroy GPT data structures" option if an APM
|
||||||
|
or BSD disklabel was detected on the disk.
|
||||||
|
|
||||||
|
- Added a buffer flush after destroying GPT data structures, to get the OS
|
||||||
|
to read the new (empty or MBR-only) partition table.
|
||||||
|
|
||||||
|
- Fixed bug that allowed entry of nonexistent partition numbers when creating
|
||||||
|
a hybrid MBR.
|
||||||
|
|
||||||
0.4.1:
|
0.4.1:
|
||||||
------
|
------
|
||||||
|
|
||||||
|
|||||||
4
Makefile
4
Makefile
@@ -2,8 +2,8 @@ CC=gcc
|
|||||||
CXX=g++
|
CXX=g++
|
||||||
#CFLAGS=-O2 -fpack-struct
|
#CFLAGS=-O2 -fpack-struct
|
||||||
CFLAGS=-O2 -fpack-struct -D_FILE_OFFSET_BITS=64 -g
|
CFLAGS=-O2 -fpack-struct -D_FILE_OFFSET_BITS=64 -g
|
||||||
CXXFLAGS=-O2 -fpack-struct -D_FILE_OFFSET_BITS=64 -g
|
CXXFLAGS=-O2 -fpack-struct -Wuninitialized -Wreturn-type -D_FILE_OFFSET_BITS=64 -g
|
||||||
LIB_NAMES=support crc32 gptpart mbr gpt bsd parttypes attributes
|
LIB_NAMES=crc32 support gptpart mbr gpt bsd parttypes attributes
|
||||||
LIB_SRCS=$(NAMES:=.cc)
|
LIB_SRCS=$(NAMES:=.cc)
|
||||||
LIB_OBJS=$(LIB_NAMES:=.o)
|
LIB_OBJS=$(LIB_NAMES:=.o)
|
||||||
LIB_HEADERS=$(LIB_NAMES:=.h)
|
LIB_HEADERS=$(LIB_NAMES:=.h)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string.h>
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
|
|
||||||
#ifndef __GPT_ATTRIBUTES
|
#ifndef __GPT_ATTRIBUTES
|
||||||
|
|||||||
1
bsd.cc
1
bsd.cc
@@ -64,7 +64,6 @@ int BSDData::ReadBSDData(char* device, uint64_t startSector, uint64_t endSector)
|
|||||||
// 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[2048]; // I/O buffer
|
||||||
uint64_t startByte;
|
|
||||||
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;
|
||||||
|
|||||||
8
gdisk.8
8
gdisk.8
@@ -1,6 +1,6 @@
|
|||||||
.\" Copyright 2009 Roderick W. Smith (rodsmith@rodsbooks.com)
|
.\" Copyright 2009 Roderick W. Smith (rodsmith@rodsbooks.com)
|
||||||
.\" May be distributed under the GNU General Public License
|
.\" May be distributed under the GNU General Public License
|
||||||
.TH GDISK 8 "August 2009" "0.4.1" "GPT fdisk Manual"
|
.TH GDISK 8 "August 2009" "0.4.2" "GPT fdisk Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
gdisk \- GPT partition table manipulator for Linux and Unix
|
gdisk \- GPT partition table manipulator for Linux and Unix
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -425,7 +425,7 @@ menu provides unusually dangerous or obscure options. These are:
|
|||||||
Set attributes. GPT provides a 64-bit attributes field that can be used to
|
Set attributes. GPT provides a 64-bit attributes field that can be used to
|
||||||
set partition features.
|
set partition features.
|
||||||
.B gdisk
|
.B gdisk
|
||||||
supports four attributes:
|
supports four attributes:
|
||||||
.IR "system partition",
|
.IR "system partition",
|
||||||
.IR "read-only",
|
.IR "read-only",
|
||||||
.IR "hidden",
|
.IR "hidden",
|
||||||
@@ -548,7 +548,7 @@ the main menu.
|
|||||||
.TP
|
.TP
|
||||||
.B z
|
.B z
|
||||||
Destroy the GPT data structures and exit. Use this option if you want to
|
Destroy the GPT data structures and exit. Use this option if you want to
|
||||||
repartition a GPT disk using
|
repartition a GPT disk using
|
||||||
.B "fdisk"
|
.B "fdisk"
|
||||||
or some other GPT-unaware program.
|
or some other GPT-unaware program.
|
||||||
You'll be given the choice of preserving the existing MBR, in case it's a
|
You'll be given the choice of preserving the existing MBR, in case it's a
|
||||||
@@ -562,7 +562,7 @@ entering data. When only one option is possible,
|
|||||||
usually bypasses the prompt entirely.
|
usually bypasses the prompt entirely.
|
||||||
|
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
As of August of 2009 (version 0.4.1),
|
As of September 2009 (version 0.4.2),
|
||||||
.B gdisk
|
.B gdisk
|
||||||
should be considered beta software. Known bugs and limitations include:
|
should be considered beta software. Known bugs and limitations include:
|
||||||
|
|
||||||
|
|||||||
11
gdisk.cc
11
gdisk.cc
@@ -27,7 +27,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.4.1\n\n");
|
printf("GPT fdisk (gdisk) version 0.4.2\n\n");
|
||||||
|
|
||||||
if (argc == 2) { // basic usage
|
if (argc == 2) { // basic usage
|
||||||
if (SizesOK()) {
|
if (SizesOK()) {
|
||||||
@@ -90,9 +90,12 @@ int DoCommand(char* filename, struct GPTData* theGPT) {
|
|||||||
theGPT->CreatePartition();
|
theGPT->CreatePartition();
|
||||||
break;
|
break;
|
||||||
case 'o': case 'O':
|
case 'o': case 'O':
|
||||||
theGPT->ClearGPTData();
|
printf("This option deletes all partitions and creates a new "
|
||||||
theGPT->MakeProtectiveMBR();
|
"protective MBR.\nProceed? ");
|
||||||
// theGPT->BlankPartitions();
|
if (GetYN() == 'Y') {
|
||||||
|
theGPT->ClearGPTData();
|
||||||
|
theGPT->MakeProtectiveMBR();
|
||||||
|
} // if
|
||||||
break;
|
break;
|
||||||
case 'p': case 'P':
|
case 'p': case 'P':
|
||||||
theGPT->DisplayGPTData();
|
theGPT->DisplayGPTData();
|
||||||
|
|||||||
68
gpt.cc
68
gpt.cc
@@ -83,7 +83,7 @@ GPTData::~GPTData(void) {
|
|||||||
// do *NOT* recover from these problems. Returns the total number of
|
// do *NOT* recover from these problems. Returns the total number of
|
||||||
// problems identified.
|
// problems identified.
|
||||||
int GPTData::Verify(void) {
|
int GPTData::Verify(void) {
|
||||||
int problems = 0, numSegments, i, j;
|
int problems = 0, numSegments;
|
||||||
uint64_t totalFree, largestSegment;
|
uint64_t totalFree, largestSegment;
|
||||||
char tempStr[255], siTotal[255], siLargest[255];
|
char tempStr[255], siTotal[255], siLargest[255];
|
||||||
|
|
||||||
@@ -282,7 +282,7 @@ int GPTData::CheckHeaderValidity(void) {
|
|||||||
} // if/else/if
|
} // if/else/if
|
||||||
|
|
||||||
// If MBR bad, check for an Apple disk signature
|
// If MBR bad, check for an Apple disk signature
|
||||||
if ((protectiveMBR.GetValidity() == invalid) &&
|
if ((protectiveMBR.GetValidity() == invalid) &&
|
||||||
(((mainHeader.signature << 32) == APM_SIGNATURE1) ||
|
(((mainHeader.signature << 32) == APM_SIGNATURE1) ||
|
||||||
(mainHeader.signature << 32) == APM_SIGNATURE2)) {
|
(mainHeader.signature << 32) == APM_SIGNATURE2)) {
|
||||||
apmFound = 1; // Will display warning message later
|
apmFound = 1; // Will display warning message later
|
||||||
@@ -317,7 +317,7 @@ int GPTData::CheckHeaderCRC(struct GPTHeader* header) {
|
|||||||
// byte order on big-endian systems) if any changes have been made.
|
// byte order on big-endian systems) if any changes have been made.
|
||||||
void GPTData::RecomputeCRCs(void) {
|
void GPTData::RecomputeCRCs(void) {
|
||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
uint32_t trueNumParts, crcTemp;
|
uint32_t trueNumParts;
|
||||||
int littleEndian = 1;
|
int littleEndian = 1;
|
||||||
|
|
||||||
// Initialize CRC functions...
|
// Initialize CRC functions...
|
||||||
@@ -703,7 +703,7 @@ void GPTData::LoadSecondTableAsMain(void) {
|
|||||||
// Writes GPT (and protective MBR) to disk. Returns 1 on successful
|
// Writes GPT (and protective MBR) to disk. Returns 1 on successful
|
||||||
// write, 0 if there was a problem.
|
// write, 0 if there was a problem.
|
||||||
int GPTData::SaveGPTData(void) {
|
int GPTData::SaveGPTData(void) {
|
||||||
int allOK = 1, i, j;
|
int allOK = 1, i;
|
||||||
char answer, line[256];
|
char answer, line[256];
|
||||||
int fd;
|
int fd;
|
||||||
uint64_t secondTable;
|
uint64_t secondTable;
|
||||||
@@ -806,27 +806,7 @@ int GPTData::SaveGPTData(void) {
|
|||||||
|
|
||||||
// re-read the partition table
|
// re-read the partition table
|
||||||
if (allOK) {
|
if (allOK) {
|
||||||
sync();
|
DiskSync(fd);
|
||||||
#ifdef __APPLE__
|
|
||||||
printf("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 */
|
|
||||||
i = ioctl(fd, DKIOCSYNCHRONIZECACHE);
|
|
||||||
#else
|
|
||||||
#ifdef __FreeBSD__
|
|
||||||
sleep(2);
|
|
||||||
i = ioctl(fd, DIOCGFLUSH);
|
|
||||||
printf("Warning: The kernel may still provide disk access using old partition IDs.\n");
|
|
||||||
#else
|
|
||||||
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");
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
} // if
|
} // if
|
||||||
|
|
||||||
if (allOK) { // writes completed OK
|
if (allOK) { // writes completed OK
|
||||||
@@ -1035,7 +1015,7 @@ void GPTData::ShowGPTState(void) {
|
|||||||
|
|
||||||
// Display the basic GPT data
|
// Display the basic GPT data
|
||||||
void GPTData::DisplayGPTData(void) {
|
void GPTData::DisplayGPTData(void) {
|
||||||
int i, j;
|
int i;
|
||||||
char sizeInSI[255]; // String to hold size of disk in SI units
|
char sizeInSI[255]; // String to hold size of disk in SI units
|
||||||
char tempStr[255];
|
char tempStr[255];
|
||||||
uint64_t temp, totalFree;
|
uint64_t temp, totalFree;
|
||||||
@@ -1233,13 +1213,17 @@ void GPTData::SetAttributes(uint32_t partNum) {
|
|||||||
// This function destroys the on-disk GPT structures. Returns 1 if the
|
// This function destroys the on-disk GPT structures. Returns 1 if the
|
||||||
// user confirms destruction, 0 if the user aborts.
|
// user confirms destruction, 0 if the user aborts.
|
||||||
int GPTData::DestroyGPT(void) {
|
int GPTData::DestroyGPT(void) {
|
||||||
int fd, i, doMore;
|
int fd, i;
|
||||||
char blankSector[512], goOn;
|
char blankSector[512], goOn;
|
||||||
|
|
||||||
for (i = 0; i < 512; i++) {
|
for (i = 0; i < 512; i++) {
|
||||||
blankSector[i] = '\0';
|
blankSector[i] = '\0';
|
||||||
} // for
|
} // for
|
||||||
|
|
||||||
|
if ((apmFound) || (bsdFound)) {
|
||||||
|
printf("WARNING: APM or BSD disklabel structures detected! This operation could\n"
|
||||||
|
"damage any APM or BSD partitions on this disk!\n");
|
||||||
|
} // if APM or BSD
|
||||||
printf("\a\aAbout to wipe out GPT on %s. Proceed? ", device);
|
printf("\a\aAbout to wipe out GPT on %s. Proceed? ", device);
|
||||||
goOn = GetYN();
|
goOn = GetYN();
|
||||||
if (goOn == 'Y') {
|
if (goOn == 'Y') {
|
||||||
@@ -1265,7 +1249,16 @@ int GPTData::DestroyGPT(void) {
|
|||||||
if (GetYN() == 'Y') {
|
if (GetYN() == 'Y') {
|
||||||
lseek64(fd, 0, SEEK_SET);
|
lseek64(fd, 0, SEEK_SET);
|
||||||
write(fd, blankSector, 512); // blank it out
|
write(fd, blankSector, 512); // blank it out
|
||||||
} // if blank MBR
|
} else { // write current protective MBR, in case it's hybrid....
|
||||||
|
// find and delete 0xEE partitions in MBR
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
if (protectiveMBR.GetType(i) == (uint8_t) 0xEE) {
|
||||||
|
protectiveMBR.DeletePartition(i);
|
||||||
|
} // if
|
||||||
|
} // for
|
||||||
|
protectiveMBR.WriteMBRData(fd);
|
||||||
|
} // if/else
|
||||||
|
DiskSync(fd);
|
||||||
close(fd);
|
close(fd);
|
||||||
printf("GPT data structures destroyed! You may now partition the disk using fdisk or\n"
|
printf("GPT data structures destroyed! You may now partition the disk using fdisk or\n"
|
||||||
"other utilities. Program will now terminate.\n");
|
"other utilities. Program will now terminate.\n");
|
||||||
@@ -1376,7 +1369,6 @@ int GPTData::XFormPartitions(void) {
|
|||||||
int i, numToConvert;
|
int i, numToConvert;
|
||||||
uint8_t origType;
|
uint8_t origType;
|
||||||
struct newGUID;
|
struct newGUID;
|
||||||
char name[NAME_SIZE];
|
|
||||||
|
|
||||||
// Clear out old data & prepare basics....
|
// Clear out old data & prepare basics....
|
||||||
ClearGPTData();
|
ClearGPTData();
|
||||||
@@ -1391,7 +1383,7 @@ int GPTData::XFormPartitions(void) {
|
|||||||
origType = protectiveMBR.GetType(i);
|
origType = protectiveMBR.GetType(i);
|
||||||
// don't waste CPU time trying to convert extended, hybrid protective, or
|
// don't waste CPU time trying to convert extended, hybrid protective, or
|
||||||
// null (non-existent) partitions
|
// null (non-existent) partitions
|
||||||
if ((origType != 0x05) && (origType != 0x0f) && (origType != 0x85) &&
|
if ((origType != 0x05) && (origType != 0x0f) && (origType != 0x85) &&
|
||||||
(origType != 0x00) && (origType != 0xEE))
|
(origType != 0x00) && (origType != 0xEE))
|
||||||
partitions[i] = protectiveMBR.AsGPT(i);
|
partitions[i] = protectiveMBR.AsGPT(i);
|
||||||
} // for
|
} // for
|
||||||
@@ -1509,7 +1501,8 @@ void GPTData::MakeHybrid(void) {
|
|||||||
j = partNums[i] - 1;
|
j = partNums[i] - 1;
|
||||||
printf("\nCreating entry for partition #%d\n", j + 1);
|
printf("\nCreating entry for partition #%d\n", j + 1);
|
||||||
if ((j >= 0) && (j < mainHeader.numParts)) {
|
if ((j >= 0) && (j < mainHeader.numParts)) {
|
||||||
if (partitions[j].GetLastLBA() < UINT32_MAX) {
|
if ((partitions[j].GetLastLBA() < UINT32_MAX) &&
|
||||||
|
(partitions[j].GetLastLBA() > UINT64_C(0))) {
|
||||||
do {
|
do {
|
||||||
printf("Enter an MBR hex code (default %02X): ",
|
printf("Enter an MBR hex code (default %02X): ",
|
||||||
typeHelper.GUIDToID(partitions[j].GetType()) / 256);
|
typeHelper.GUIDToID(partitions[j].GetType()) / 256);
|
||||||
@@ -1529,7 +1522,8 @@ void GPTData::MakeHybrid(void) {
|
|||||||
(uint32_t) length, typeCode, bootable);
|
(uint32_t) length, typeCode, bootable);
|
||||||
protectiveMBR.SetHybrid();
|
protectiveMBR.SetHybrid();
|
||||||
} else { // partition out of range
|
} else { // partition out of range
|
||||||
printf("Partition %d ends beyond the 2TiB limit of MBR partitions; omitting it.\n",
|
printf("Partition %d ends beyond the 2TiB limit of MBR partitions or does not exist;\n"
|
||||||
|
"omitting it.\n",
|
||||||
j + 1);
|
j + 1);
|
||||||
} // if/else
|
} // if/else
|
||||||
} else {
|
} else {
|
||||||
@@ -1683,8 +1677,12 @@ void GPTData::SortGPT(void) {
|
|||||||
|
|
||||||
// Set up data structures for entirely new set of partitions on the
|
// Set up data structures for entirely new set of partitions on the
|
||||||
// specified device. Returns 1 if OK, 0 if there were problems.
|
// specified device. Returns 1 if OK, 0 if there were problems.
|
||||||
|
// Note that this function does NOT clear the protectiveMBR data
|
||||||
|
// structure, since it may hold the original MBR partitions if the
|
||||||
|
// program was launched on an MBR disk, and those may need to be
|
||||||
|
// converted to GPT format.
|
||||||
int GPTData::ClearGPTData(void) {
|
int GPTData::ClearGPTData(void) {
|
||||||
int goOn, i;
|
int goOn = 1, i;
|
||||||
|
|
||||||
// Set up the partition table....
|
// Set up the partition table....
|
||||||
free(partitions);
|
free(partitions);
|
||||||
@@ -1835,7 +1833,7 @@ uint64_t GPTData::FindFirstAvailable(uint64_t start) {
|
|||||||
// Finds the first available sector in the largest block of unallocated
|
// Finds the first available sector in the largest block of unallocated
|
||||||
// space on the disk. Returns 0 if there are no available blocks left
|
// space on the disk. Returns 0 if there are no available blocks left
|
||||||
uint64_t GPTData::FindFirstInLargest(void) {
|
uint64_t GPTData::FindFirstInLargest(void) {
|
||||||
uint64_t start, firstBlock, lastBlock, segmentSize, selectedSize = 0, selectedSegment;
|
uint64_t start, firstBlock, lastBlock, segmentSize, selectedSize = 0, selectedSegment = 0;
|
||||||
|
|
||||||
start = 0;
|
start = 0;
|
||||||
do {
|
do {
|
||||||
@@ -1937,7 +1935,7 @@ int GPTData::IsFree(uint64_t sector) {
|
|||||||
isFree = 0;
|
isFree = 0;
|
||||||
} // if
|
} // if
|
||||||
} // for
|
} // for
|
||||||
if ((sector < mainHeader.firstUsableLBA) ||
|
if ((sector < mainHeader.firstUsableLBA) ||
|
||||||
(sector > mainHeader.lastUsableLBA)) {
|
(sector > mainHeader.lastUsableLBA)) {
|
||||||
isFree = 0;
|
isFree = 0;
|
||||||
} // if
|
} // if
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ GPTPart & GPTPart::operator=(const GPTPart & orig) {
|
|||||||
attributes = orig.attributes;
|
attributes = orig.attributes;
|
||||||
for (i = 0; i < NAME_SIZE; i++)
|
for (i = 0; i < NAME_SIZE; i++)
|
||||||
name[i] = orig.name[i];
|
name[i] = orig.name[i];
|
||||||
|
return *this;
|
||||||
} // assignment operator
|
} // assignment operator
|
||||||
|
|
||||||
// Sets the unique GUID to a value of 0 or a random value,
|
// Sets the unique GUID to a value of 0 or a random value,
|
||||||
|
|||||||
43
mbr.cc
43
mbr.cc
@@ -179,11 +179,12 @@ void MBRData::ReadMBRData(int fd, int checkBlockSize) {
|
|||||||
|
|
||||||
// Find block size
|
// Find block size
|
||||||
if (checkBlockSize) {
|
if (checkBlockSize) {
|
||||||
if ((blockSize = GetBlockSize(fd)) == -1) {
|
blockSize = GetBlockSize(fd);
|
||||||
blockSize = SECTOR_SIZE;
|
// if ((blockSize = GetBlockSize(fd)) == -1) {
|
||||||
printf("Unable to determine sector size; assuming %lu bytes!\n",
|
// blockSize = SECTOR_SIZE;
|
||||||
(unsigned long) SECTOR_SIZE);
|
// printf("Unable to determine sector size; assuming %lu bytes!\n",
|
||||||
} // if
|
// (unsigned long) SECTOR_SIZE);
|
||||||
|
// } // if
|
||||||
} // if (checkBlockSize)
|
} // if (checkBlockSize)
|
||||||
|
|
||||||
// Load logical partition data, if any is found....
|
// Load logical partition data, if any is found....
|
||||||
@@ -291,6 +292,7 @@ void MBRData::WriteMBRData(int fd) {
|
|||||||
} // for i...
|
} // for i...
|
||||||
|
|
||||||
// Now write that data structure...
|
// Now write that data structure...
|
||||||
|
lseek64(fd, 0, SEEK_SET);
|
||||||
write(fd, &tempMBR, 512);
|
write(fd, &tempMBR, 512);
|
||||||
|
|
||||||
/* write(fd, code, 440);
|
/* write(fd, code, 440);
|
||||||
@@ -298,7 +300,7 @@ void MBRData::WriteMBRData(int fd) {
|
|||||||
write(fd, &nulls, 2);
|
write(fd, &nulls, 2);
|
||||||
write(fd, partitions, 64);
|
write(fd, partitions, 64);
|
||||||
write(fd, &MBRSignature, 2); */
|
write(fd, &MBRSignature, 2); */
|
||||||
|
|
||||||
// Reverse the byte order back, if necessary
|
// Reverse the byte order back, if necessary
|
||||||
if (IsLittleEndian() == 0) {
|
if (IsLittleEndian() == 0) {
|
||||||
ReverseBytes(&diskSignature, 4);
|
ReverseBytes(&diskSignature, 4);
|
||||||
@@ -496,6 +498,20 @@ int MBRData::MakeBiggestPart(int i, int type) {
|
|||||||
return found;
|
return found;
|
||||||
} // MBRData::MakeBiggestPart(int i)
|
} // MBRData::MakeBiggestPart(int i)
|
||||||
|
|
||||||
|
// Delete partition #i
|
||||||
|
void MBRData::DeletePartition(int i) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
partitions[i].firstLBA = UINT32_C(0);
|
||||||
|
partitions[i].lengthLBA = UINT32_C(0);
|
||||||
|
partitions[i].status = UINT8_C(0);
|
||||||
|
partitions[i].partitionType = UINT8_C(0);
|
||||||
|
for (j = 0; j < 3; j++) {
|
||||||
|
partitions[i].firstSector[j] = UINT8_C(0);
|
||||||
|
partitions[i].lastSector[j] = UINT8_C(0);
|
||||||
|
} // for j (CHS data blanking)
|
||||||
|
} // MBRData::DeletePartition()
|
||||||
|
|
||||||
// Delete a partition if one exists at the specified location.
|
// Delete a partition if one exists at the specified location.
|
||||||
// Returns 1 if a partition was deleted, 0 otherwise....
|
// Returns 1 if a partition was deleted, 0 otherwise....
|
||||||
// Used to help keep GPT & hybrid MBR partitions in sync....
|
// Used to help keep GPT & hybrid MBR partitions in sync....
|
||||||
@@ -509,14 +525,7 @@ int MBRData::DeleteByLocation(uint64_t start64, uint64_t length64) {
|
|||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
if ((partitions[i].firstLBA == start32) && (partitions[i].lengthLBA = length32) &&
|
if ((partitions[i].firstLBA == start32) && (partitions[i].lengthLBA = length32) &&
|
||||||
(partitions[i].partitionType != 0xEE)) {
|
(partitions[i].partitionType != 0xEE)) {
|
||||||
partitions[i].firstLBA = UINT32_C(0);
|
DeletePartition(i);
|
||||||
partitions[i].lengthLBA = UINT32_C(0);
|
|
||||||
partitions[i].status = UINT8_C(0);
|
|
||||||
partitions[i].partitionType = UINT8_C(0);
|
|
||||||
for (j = 0; j < 3; j++) {
|
|
||||||
partitions[i].firstSector[j] = UINT8_C(0);
|
|
||||||
partitions[i].lastSector[j] = UINT8_C(0);
|
|
||||||
} // for j (CHS data blanking)
|
|
||||||
OptimizeEESize();
|
OptimizeEESize();
|
||||||
deleted = 1;
|
deleted = 1;
|
||||||
} // if (match found)
|
} // if (match found)
|
||||||
@@ -594,7 +603,7 @@ void MBRData::ShowState(void) {
|
|||||||
// setup to begin with....
|
// setup to begin with....
|
||||||
void MBRData::MakePart(int num, uint32_t start, uint32_t length, int type,
|
void MBRData::MakePart(int num, uint32_t start, uint32_t length, int type,
|
||||||
int bootable) {
|
int bootable) {
|
||||||
|
|
||||||
partitions[num].status = (uint8_t) bootable * (uint8_t) 0x80;
|
partitions[num].status = (uint8_t) bootable * (uint8_t) 0x80;
|
||||||
partitions[num].firstSector[0] = UINT8_C(0);
|
partitions[num].firstSector[0] = UINT8_C(0);
|
||||||
partitions[num].firstSector[1] = UINT8_C(0);
|
partitions[num].firstSector[1] = UINT8_C(0);
|
||||||
@@ -657,7 +666,7 @@ uint32_t MBRData::FindLastInFree(uint32_t start) {
|
|||||||
|
|
||||||
// Finds the first free sector on the disk from start backward.
|
// Finds the first free sector on the disk from start backward.
|
||||||
uint32_t MBRData::FindFirstInFree(uint32_t start) {
|
uint32_t MBRData::FindFirstInFree(uint32_t start) {
|
||||||
uint32_t nearestStart, bestLastLBA, thisLastLBA;
|
uint32_t bestLastLBA, thisLastLBA;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
bestLastLBA = 1;
|
bestLastLBA = 1;
|
||||||
@@ -752,7 +761,7 @@ GPTPart MBRData::AsGPT(int i) {
|
|||||||
// partitions (Note similar protection is in GPTData::XFormPartitions(),
|
// partitions (Note similar protection is in GPTData::XFormPartitions(),
|
||||||
// but I want it here too in case I call this function in another
|
// but I want it here too in case I call this function in another
|
||||||
// context in the future....)
|
// context in the future....)
|
||||||
if ((origType != 0x05) && (origType != 0x0f) && (origType != 0x85) &&
|
if ((origType != 0x05) && (origType != 0x0f) && (origType != 0x85) &&
|
||||||
(origType != 0x00) && (origType != 0xEE)) {
|
(origType != 0x00) && (origType != 0xEE)) {
|
||||||
firstSector = (uint64_t) origPart->firstLBA;
|
firstSector = (uint64_t) origPart->firstLBA;
|
||||||
newPart.SetFirstLBA(firstSector);
|
newPart.SetFirstLBA(firstSector);
|
||||||
|
|||||||
1
mbr.h
1
mbr.h
@@ -105,6 +105,7 @@ public:
|
|||||||
void MakePart(int num, uint32_t startLBA, uint32_t lengthLBA, int type = 0x07,
|
void MakePart(int num, uint32_t startLBA, uint32_t lengthLBA, int type = 0x07,
|
||||||
int bootable = 0);
|
int bootable = 0);
|
||||||
int MakeBiggestPart(int i, int type); // Make partition filling most space
|
int MakeBiggestPart(int i, int type); // Make partition filling most space
|
||||||
|
void DeletePartition(int i);
|
||||||
int DeleteByLocation(uint64_t start64, uint64_t length64);
|
int DeleteByLocation(uint64_t start64, uint64_t length64);
|
||||||
void OptimizeEESize(void);
|
void OptimizeEESize(void);
|
||||||
void SetHybrid(void) {state = hybrid;} // Set hybrid flag
|
void SetHybrid(void) {state = hybrid;} // Set hybrid flag
|
||||||
|
|||||||
13
parttypes.cc
13
parttypes.cc
@@ -293,6 +293,14 @@ struct GUIDData PartTypes::IDToGUID(uint16_t ID) {
|
|||||||
int found = 0;
|
int found = 0;
|
||||||
struct GUIDData theGUID;
|
struct GUIDData theGUID;
|
||||||
|
|
||||||
|
// Start by assigning a default GUID for the return value. Done
|
||||||
|
// "raw" to avoid the necessity for a recursive call and the
|
||||||
|
// remote possibility of an infinite recursive loop that this
|
||||||
|
// approach would present....
|
||||||
|
theGUID.data1 = UINT64_C(0x4433B9E5EBD0A0A2);
|
||||||
|
theGUID.data2 = UINT64_C(0xC79926B7B668C087);
|
||||||
|
|
||||||
|
// Now search the type list for a match to the ID....
|
||||||
while ((theItem != NULL) && (!found)) {
|
while ((theItem != NULL) && (!found)) {
|
||||||
if (theItem->MBRType == ID) { // found it!
|
if (theItem->MBRType == ID) { // found it!
|
||||||
theGUID = theItem->GUIDType;
|
theGUID = theItem->GUIDType;
|
||||||
@@ -302,8 +310,7 @@ struct GUIDData PartTypes::IDToGUID(uint16_t ID) {
|
|||||||
} // if/else
|
} // if/else
|
||||||
} // while
|
} // while
|
||||||
if (!found) {
|
if (!found) {
|
||||||
theGUID = IDToGUID(0x0700); // assign a default type code
|
printf("Exact type match not found for type code %04X; assigning type code for\n'Linux/Windows data'\n",
|
||||||
printf("Exact type match not found for type code %lx; assigning type code for\n'Linux/Windows data'\n",
|
|
||||||
ID);
|
ID);
|
||||||
} // if (!found)
|
} // if (!found)
|
||||||
return theGUID;
|
return theGUID;
|
||||||
@@ -317,7 +324,7 @@ struct GUIDData PartTypes::IDToGUID(uint16_t ID) {
|
|||||||
uint16_t PartTypes::GUIDToID(struct GUIDData typeCode) {
|
uint16_t PartTypes::GUIDToID(struct GUIDData typeCode) {
|
||||||
AType* theItem = allTypes;
|
AType* theItem = allTypes;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
uint16_t theID;
|
uint16_t theID = 0xFFFF;
|
||||||
|
|
||||||
while ((theItem != NULL) && (!found)) {
|
while ((theItem != NULL) && (!found)) {
|
||||||
if ((theItem->GUIDType.data1 == typeCode.data1) &&
|
if ((theItem->GUIDType.data1 == typeCode.data1) &&
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string.h>
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
|
|
||||||
#ifndef __PARTITION_TYPES
|
#ifndef __PARTITION_TYPES
|
||||||
|
|||||||
125
support.cc
125
support.cc
@@ -15,6 +15,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@@ -184,8 +185,9 @@ char* BytesToSI(uint64_t size, char theValue[]) {
|
|||||||
return theValue;
|
return theValue;
|
||||||
} // BlocksToSI()
|
} // BlocksToSI()
|
||||||
|
|
||||||
// Returns block size of device pointed to by fd file descriptor, or -1
|
// Returns block size of device pointed to by fd file descriptor. If the ioctl
|
||||||
// if there's a problem
|
// returns an error condition, print a warning but return a value of SECTOR_SIZE
|
||||||
|
// (512)..
|
||||||
int GetBlockSize(int fd) {
|
int GetBlockSize(int fd) {
|
||||||
int err, result;
|
int err, result;
|
||||||
|
|
||||||
@@ -199,13 +201,21 @@ int GetBlockSize(int fd) {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (err == -1) {
|
||||||
|
result = SECTOR_SIZE;
|
||||||
|
// ENOTTY = inappropriate ioctl; probably being called on a disk image
|
||||||
|
// file, so don't display the warning message....
|
||||||
|
if (errno != ENOTTY) {
|
||||||
|
printf("\aError %d when determining sector size! Setting sector size to %d\n",
|
||||||
|
errno, SECTOR_SIZE);
|
||||||
|
} // 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
|
||||||
|
|
||||||
if (err == -1)
|
|
||||||
result = -1;
|
|
||||||
return (result);
|
return (result);
|
||||||
} // GetBlockSize()
|
} // GetBlockSize()
|
||||||
|
|
||||||
@@ -380,7 +390,37 @@ int OpenForWrite(char* deviceFilename) {
|
|||||||
fd = open(deviceFilename, O_WRONLY|O_SHLOCK);
|
fd = open(deviceFilename, O_WRONLY|O_SHLOCK);
|
||||||
} // if
|
} // if
|
||||||
#endif
|
#endif
|
||||||
} // MyOpen()
|
return fd;
|
||||||
|
} // OpenForWrite()
|
||||||
|
|
||||||
|
// Resync disk caches so the OS uses the new partition table. This code varies
|
||||||
|
// a lot from one OS to another.
|
||||||
|
void DiskSync(int fd) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sync();
|
||||||
|
#ifdef __APPLE__
|
||||||
|
printf("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 */
|
||||||
|
i = ioctl(fd, DKIOCSYNCHRONIZECACHE);
|
||||||
|
#else
|
||||||
|
#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");
|
||||||
|
#else
|
||||||
|
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");
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
} // DiskSync()
|
||||||
|
|
||||||
/**************************************************************************************
|
/**************************************************************************************
|
||||||
* *
|
* *
|
||||||
@@ -392,35 +432,62 @@ int OpenForWrite(char* deviceFilename) {
|
|||||||
// The disksize function is taken from the Linux fdisk code and modified
|
// The disksize function is taken from the Linux fdisk code and modified
|
||||||
// to work around a problem returning a uint64_t value on Mac OS.
|
// to work around a problem returning a uint64_t value on Mac OS.
|
||||||
uint64_t disksize(int fd, int *err) {
|
uint64_t disksize(int fd, int *err) {
|
||||||
long sz; // Do not delete; needed for Linux
|
long sz; // Do not delete; needed for Linux
|
||||||
long long b; // Do not delete; needed for Linux
|
long long b; // Do not delete; needed for Linux
|
||||||
uint64_t sectors;
|
uint64_t sectors = 0, bytes = 0; // size in sectors & bytes
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
// Note to self: I recall testing a simplified version of
|
// Note to self: I recall testing a simplified version of
|
||||||
// this code, similar to what's in the __APPLE__ block,
|
// this code, similar to what's in the __APPLE__ block,
|
||||||
// on Linux, but I had some problems. IIRC, it ran OK on 32-bit
|
// on Linux, but I had some problems. IIRC, it ran OK on 32-bit
|
||||||
// systems but not on 64-bit. Keep this in mind in case of
|
// systems but not on 64-bit. Keep this in mind in case of
|
||||||
// 32/64-bit issues on MacOS....
|
// 32/64-bit issues on MacOS....
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
*err = ioctl(fd, DKIOCGETBLOCKCOUNT, §ors);
|
*err = ioctl(fd, DKIOCGETBLOCKCOUNT, §ors);
|
||||||
#else
|
#else
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
*err = ioctl(fd, DIOCGMEDIASIZE, &sz);
|
*err = ioctl(fd, DIOCGMEDIASIZE, &sz);
|
||||||
b = GetBlockSize(fd);
|
b = GetBlockSize(fd);
|
||||||
sectors = sz / b;
|
sectors = sz / b;
|
||||||
#else
|
#else
|
||||||
*err = ioctl(fd, BLKGETSIZE, &sz);
|
*err = ioctl(fd, BLKGETSIZE, &sz);
|
||||||
if (*err) {
|
if (*err) {
|
||||||
sz = 0;
|
sectors = sz = 0;
|
||||||
if (errno != EFBIG)
|
} // if
|
||||||
return sz;
|
if ((errno == EFBIG) || (!*err)) {
|
||||||
}
|
*err = ioctl(fd, BLKGETSIZE64, &b);
|
||||||
*err = ioctl(fd, BLKGETSIZE64, &b);
|
if (*err || b == 0 || b == sz)
|
||||||
if (*err || b == 0 || b == sz)
|
sectors = sz;
|
||||||
sectors = sz;
|
else
|
||||||
else
|
sectors = (b >> 9);
|
||||||
sectors = (b >> 9);
|
} // if
|
||||||
|
|
||||||
|
// if (*err) {
|
||||||
|
// sz = 0;
|
||||||
|
// if (errno != EFBIG)
|
||||||
|
// return sz;
|
||||||
|
// }
|
||||||
|
// *err = ioctl(fd, BLKGETSIZE64, &b);
|
||||||
|
// if (*err || b == 0 || b == sz)
|
||||||
|
// sectors = sz;
|
||||||
|
// else
|
||||||
|
// sectors = (b >> 9);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
return sectors;
|
|
||||||
|
// The above methods have failed (or it's a bum filename reference),
|
||||||
|
// so let's assume it's a regular file (a QEMU image, dd backup, or
|
||||||
|
// what have you) and see what stat() gives us....
|
||||||
|
if (sectors == 0) {
|
||||||
|
if (fstat(fd, &st) == 0) {
|
||||||
|
bytes = (uint64_t) st.st_size;
|
||||||
|
if ((bytes % UINT64_C(512)) != 0)
|
||||||
|
fprintf(stderr, "Warning: File size is not a multiple of 512 bytes!"
|
||||||
|
" Misbehavior is likely!\n\a");
|
||||||
|
sectors = bytes / UINT64_C(512);
|
||||||
|
} // if
|
||||||
|
} // if
|
||||||
|
// printf("In disksize(), sectors is %lld.\n", sectors);
|
||||||
|
return sectors;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef __GPTSUPPORT
|
#ifndef __GPTSUPPORT
|
||||||
#define __GPTSUPPORT
|
#define __GPTSUPPORT
|
||||||
@@ -62,6 +62,7 @@ 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);
|
||||||
|
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