Skip to content

Commit

Permalink
Changes for GPT fdisk version 0.8.1
Browse files Browse the repository at this point in the history
  • Loading branch information
srs5694 committed Oct 1, 2011
1 parent d1b11e8 commit 23d8d54
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 542 deletions.
464 changes: 0 additions & 464 deletions Makefile

Large diffs are not rendered by default.

27 changes: 20 additions & 7 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
0.8.1 (?/??/2011):
0.8.1 (10/1/2011):
------------------

- Fixed bug that could cause FixParts to keep a partition's assignment
as logical when FixPart could not actually do so. This could happen
when there are no gaps between two logical partitions. Some partitioning
tools can create such configurations, but FixParts can't. Such
configurations are extremely rare. I've only encountered them when
logical partitions are out of order.

- Added code to detect infinite loops of logical partitions when reading
MBR data. When detected, the program now stops reading after the first
loop, so no duplicates appear in the partition list.

- Fixed bug in partition overlap detection in MBR code.

- Changed GPT reading code to use the size encoded in GPT headers to
determine how much of the header to use in computing a CRC, with the
restriction that the size be equal to or less than the disk's sector
size. This should work around problems with libefi in ZFS, which sets the
header size to 512 rather than the standard 92. A caveat: If the disk's
sector size is larger than the GPTHeader data structure size (512 bytes),
then the rest of the sector's contents are ignored and replaced with 0
values. This could produce false positives on CRC checks on disks with
over-512-byte sector sizes if the header sector is padded with something
other than 0 values.
header size to 512 rather than the more common 92. A caveat: If the
disk's sector size is larger than the GPTHeader data structure size (512
bytes), then the rest of the sector's contents are ignored and replaced
with 0 values. This could produce false positives on CRC checks on disks
with over-512-byte sector sizes if the header sector is padded with
something other than 0 values.

- Fixed bug in new (as of 0.8.0) check that main and backup partition
tables are identical on big-endian (PowerPC, etc.) hardware.
Expand Down
117 changes: 65 additions & 52 deletions basicmbr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ BasicMBRData::BasicMBRData(void) {
numSecspTrack = MAX_SECSPERTRACK;
myDisk = NULL;
canDeleteMyDisk = 0;
// memset(&EbrLocations, 0, MAX_MBR_PARTS * sizeof(uint32_t));
EmptyMBR();
} // BasicMBRData default constructor

Expand All @@ -51,7 +52,8 @@ BasicMBRData::BasicMBRData(string filename) {
numSecspTrack = MAX_SECSPERTRACK;
myDisk = NULL;
canDeleteMyDisk = 0;

// memset(&EbrLocations, 0, MAX_MBR_PARTS * sizeof(uint32_t));

// Try to read the specified partition table, but if it fails....
if (!ReadMBRData(filename)) {
EmptyMBR();
Expand Down Expand Up @@ -134,7 +136,7 @@ int BasicMBRData::ReadMBRData(const string & deviceFilename) {
// in the partitions[] array; these partitions must be re-created when
// the partition table is saved in MBR format.
int BasicMBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
int allOK = 1, i, logicalNum = 0;
int allOK = 1, i, logicalNum = 3;
int err = 1;
TempMBR tempMBR;

Expand Down Expand Up @@ -194,10 +196,9 @@ int BasicMBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
for (i = 0; i < 4; i++) {
if ((partitions[i].GetType() == 0x05) || (partitions[i].GetType() == 0x0f)
|| (partitions[i].GetType() == 0x85)) {
// Found it, so call a recursive algorithm to load everything from them....
logicalNum = ReadLogicalPart(partitions[i].GetStartLBA(), UINT32_C(0), 4);
if ((logicalNum < 0) || (logicalNum >= MAX_MBR_PARTS)) {
allOK = 0;
// Found it, so call a function to load everything from them....
logicalNum = ReadLogicalParts(partitions[i].GetStartLBA(), abs(logicalNum) + 1);
if (logicalNum < 0) {
cerr << "Error reading logical partitions! List may be truncated!\n";
} // if maxLogicals valid
DeletePartition(i);
Expand Down Expand Up @@ -226,7 +227,7 @@ int BasicMBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
if ((partitions[i].GetType() != UINT8_C(0xEE)) &&
(partitions[i].GetType() != UINT8_C(0x00)))
state = hybrid;
if (logicalNum > 0)
if (logicalNum != 3)
cerr << "Warning! MBR Logical partitions found on a hybrid MBR disk! This is an\n"
<< "EXTREMELY dangerous configuration!\n\a";
} // for
Expand All @@ -235,32 +236,40 @@ int BasicMBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
return allOK;
} // BasicMBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize)

// This is a recursive function to read all the logical partitions, following the
// This is a function to read all the logical partitions, following the
// logical partition linked list from the disk and storing the basic data in the
// partitions[] array. Returns last index to partitions[] used, or -1 if there was
// a problem.
// partitions[] array. Returns last index to partitions[] used, or -1 times the
// that index if there was a problem. (Some problems can leave valid logical
// partition data.)
// Parameters:
// extendedStart = LBA of the start of the extended partition
// diskOffset = LBA offset WITHIN the extended partition of the one to be read
// partNum = location in partitions[] array to store retrieved data
int BasicMBRData::ReadLogicalPart(uint64_t extendedStart, uint64_t diskOffset, int partNum) {
// partNum = number of first partition in extended partition (normally 4).
int BasicMBRData::ReadLogicalParts(uint64_t extendedStart, int partNum) {
struct TempMBR ebr;
int i, another = 1, allOK = 1;
uint8_t ebrType;
uint64_t offset;

// Check for a valid partition number. Note that partitions MAY be read into
// the area normally used by primary partitions, although the only calling
// functions as of GPT fdisk version 0.7.0 don't do so.
if ((partNum < MAX_MBR_PARTS) && (partNum >= 0)) {
offset = (uint64_t) (extendedStart + diskOffset);
uint64_t EbrLocations[MAX_MBR_PARTS];

offset = extendedStart;
memset(&EbrLocations, 0, MAX_MBR_PARTS * sizeof(uint64_t));
while (another && (partNum < MAX_MBR_PARTS) && (partNum >= 0) && (allOK > 0)) {
for (i = 0; i < MAX_MBR_PARTS; i++) {
if (EbrLocations[i] == offset) { // already read this one; infinite logical partition loop!
cerr << "Logical partition infinite loop detected! This is being corrected.\n";
allOK = -1;
partNum -= 1;
} // if
} // for
EbrLocations[partNum] = offset;
if (myDisk->Seek(offset) == 0) { // seek to EBR record
cerr << "Unable to seek to " << offset << "! Aborting!\n";
partNum = -1;
allOK = -1;
}
if (myDisk->Read(&ebr, 512) != 512) { // Load the data....
cerr << "Error seeking to or reading logical partition data from " << offset
<< "!\nAborting!\n";
partNum = -1;
<< "!\nSome logical partitions may be missing!\n";
allOK = -1;
} else if (IsLittleEndian() != 1) { // Reverse byte ordering of some data....
ReverseBytes(&ebr.MBRSignature, 2);
ReverseBytes(&ebr.partitions[0].firstLBA, 4);
Expand All @@ -270,8 +279,8 @@ int BasicMBRData::ReadLogicalPart(uint64_t extendedStart, uint64_t diskOffset, i
} // if/else/if

if (ebr.MBRSignature != MBR_SIGNATURE) {
partNum = -1;
cerr << "MBR signature in logical partition invalid; read 0x";
allOK = -1;
cerr << "EBR signature for logical partition invalid; read 0x";
cerr.fill('0');
cerr.width(4);
cerr.setf(ios::uppercase);
Expand All @@ -281,31 +290,32 @@ int BasicMBRData::ReadLogicalPart(uint64_t extendedStart, uint64_t diskOffset, i
cerr.fill(' ');
} // if

// Sometimes an EBR points directly to another EBR, rather than defining
// a logical partition and then pointing to another EBR. Thus, we recurse
// directly if this is detected, else extract partition data and then
// recurse on the second entry in the EBR...
ebrType = ebr.partitions[0].partitionType;
if ((ebrType == 0x05) || (ebrType == 0x0f) || (ebrType == 0x85)) {
partNum = ReadLogicalPart(extendedStart, ebr.partitions[0].firstLBA, partNum);
} else {
// Copy over the basic data....
partitions[partNum] = ebr.partitions[0];
// Adjust the start LBA, since it's encoded strangely....
partitions[partNum].SetStartLBA(ebr.partitions[0].firstLBA + diskOffset + extendedStart);
partitions[partNum].SetInclusion(LOGICAL);

// Find the next partition (if there is one) and recurse....
if ((ebr.partitions[1].firstLBA != UINT32_C(0)) && (partNum >= 4) &&
(partNum < (MAX_MBR_PARTS - 1))) {
partNum = ReadLogicalPart(extendedStart, ebr.partitions[1].firstLBA,
partNum + 1);
if ((partNum >= 0) && (partNum < MAX_MBR_PARTS) && (allOK > 0)) {
// Sometimes an EBR points directly to another EBR, rather than defining
// a logical partition and then pointing to another EBR. Thus, we skip
// the logical partition when this is the case....
ebrType = ebr.partitions[0].partitionType;
if ((ebrType == 0x05) || (ebrType == 0x0f) || (ebrType == 0x85)) {
cout << "EBR describes a logical partition!\n";
offset = extendedStart + ebr.partitions[0].firstLBA;
} else {
partNum++;
} // if another partition
} // if/else
} // Not enough space for all the logicals (or previous error encountered)
return (partNum);
// Copy over the basic data....
partitions[partNum] = ebr.partitions[0];
// Adjust the start LBA, since it's encoded strangely....
partitions[partNum].SetStartLBA(ebr.partitions[0].firstLBA + offset);
partitions[partNum].SetInclusion(LOGICAL);

// Find the next partition (if there is one)
if ((ebr.partitions[1].firstLBA != UINT32_C(0)) && (partNum < (MAX_MBR_PARTS - 1))) {
offset = extendedStart + ebr.partitions[1].firstLBA;
partNum++;
} else {
another = 0;
} // if another partition
} // if/else
} // if
} // while()
return (partNum * allOK);
} // BasicMBRData::ReadLogicalPart()

// Write the MBR data to the default defined device. This writes both the
Expand Down Expand Up @@ -365,7 +375,7 @@ int BasicMBRData::WriteMBRData(DiskIO *theDisk) {
partNum = FindNextInUse(4);
writeEbrTo = (uint64_t) extFirstLBA;
// Write logicals...
while (allOK && moreLogicals && (partNum < MAX_MBR_PARTS)) {
while (allOK && moreLogicals && (partNum < MAX_MBR_PARTS) && (partNum >= 0)) {
partitions[partNum].StoreInStruct(&tempMBR.partitions[0]);
tempMBR.partitions[0].firstLBA = 1;
// tempMBR.partitions[1] points to next EBR or terminates EBR linked list...
Expand Down Expand Up @@ -698,7 +708,7 @@ int BasicMBRData::FindOverlaps(void) {

for (i = 0; i < MAX_MBR_PARTS; i++) {
for (j = i + 1; j < MAX_MBR_PARTS; j++) {
if ((partitions[i].GetInclusion() != NONE) &&
if ((partitions[i].GetInclusion() != NONE) && (partitions[j].GetInclusion() != NONE) &&
(partitions[i].DoTheyOverlap(partitions[j]))) {
numProbs++;
cout << "\nProblem: MBR partitions " << i + 1 << " and " << j + 1
Expand Down Expand Up @@ -1411,7 +1421,10 @@ uint64_t BasicMBRData::FindFirstInFree(uint64_t start) {
return (bestLastLBA);
} // BasicMBRData::FindFirstInFree()

// Returns NONE (unused), PRIMARY, LOGICAL, EBR (for EBR or MBR), or INVALID
// Returns NONE (unused), PRIMARY, LOGICAL, EBR (for EBR or MBR), or INVALID.
// Note: If the sector immediately before a logical partition is in use by
// another partition, this function returns PRIMARY or LOGICAL for that
// sector, rather than EBR.
int BasicMBRData::SectorUsedAs(uint64_t sector, int topPartNum) {
int i = 0, usedAs = NONE;

Expand All @@ -1425,7 +1438,7 @@ int BasicMBRData::SectorUsedAs(uint64_t sector, int topPartNum) {
if (sector >= diskSize)
usedAs = INVALID;
i++;
} while ((i < topPartNum) && (usedAs == NONE));
} while ((i < topPartNum) && ((usedAs == NONE) || (usedAs == EBR)));
return usedAs;
} // BasicMBRData::SectorUsedAs()

Expand Down
5 changes: 1 addition & 4 deletions basicmbr.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,7 @@ class BasicMBRData {
// File I/O functions...
int ReadMBRData(const string & deviceFilename);
int ReadMBRData(DiskIO * theDisk, int checkBlockSize = 1);
// ReadLogicalPart() returns last partition # read to logicals[] array,
// or -1 if there was a problem....
int ReadLogicalPart(uint64_t extendedStart, uint64_t diskOffset,
int partNum);
int ReadLogicalParts(uint64_t extendedStart, int partNum);
int WriteMBRData(void);
int WriteMBRData(DiskIO *theDisk);
int WriteMBRData(const string & deviceFilename);
Expand Down
4 changes: 2 additions & 2 deletions cgdisk.8
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.\" Copyright 2011 Roderick W. Smith ([email protected])
.\" May be distributed under the GNU General Public License
.TH "CGDISK" "8" "0.8.0" "Roderick W. Smith" "GPT fdisk Manual"
.TH "CGDISK" "8" "0.8.1" "Roderick W. Smith" "GPT fdisk Manual"
.SH "NAME"
cgdisk \- Curses-based GUID partition table (GPT) manipulator
.SH "SYNOPSIS"
Expand Down Expand Up @@ -268,7 +268,7 @@ Write data. Use this command to save your changes.

.SH "BUGS"

As of September 2011 (version 0.8.0), \fBcgdisk\fR should be considered
As of September 2011 (version 0.8.1), \fBcgdisk\fR should be considered
beta software. Although the underlying partition manipulation code is much
older, the \fBcgdisk\fR ncurses user interface is brand new with GPT fdisk
version 0.8.0. Known bugs and limitations include:
Expand Down
8 changes: 4 additions & 4 deletions current.spec
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
Summary: GPT partitioning and MBR repair software
Name: gptfdisk
Version: 0.8.0
Version: 0.8.1
Release: 1%{?dist}
License: GPLv2
URL: http://www.rodsbooks.com/gdisk
Group: Applications/System
Source: http://www.rodsbooks.com/gdisk/gptfdisk-0.8.0.tar.gz
Source: http://www.rodsbooks.com/gdisk/gptfdisk-0.8.1.tar.gz
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)

%description
Expand Down Expand Up @@ -80,5 +80,5 @@ provides a few additional partition manipulation features.


%changelog
* Sat Sep 10 2011 R Smith <[email protected]> - 0.8.0
- Created spec file for 0.8.0 release
* Sat Oct 1 2011 R Smith <[email protected]> - 0.8.1
- Created spec file for 0.8.1 release
4 changes: 2 additions & 2 deletions fixparts.8
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.\" Copyright 2011 Roderick W. Smith ([email protected])
.\" May be distributed under the GNU General Public License
.TH "FIXPARTS" "8" "0.8.0" "Roderick W. Smith" "FixParts Manual"
.TH "FIXPARTS" "8" "0.8.1" "Roderick W. Smith" "FixParts Manual"
.SH "NAME"
fixparts \- MBR partition table repair utility
.SH "SYNOPSIS"
Expand Down Expand Up @@ -202,7 +202,7 @@ see a summary of available options.
.PP

.SH "BUGS"
As of September 2011 (version 0.8.0), \fBfixparts\fR
As of September 2011 (version 0.8.1), \fBfixparts\fR
should be considered beta software. Known bugs and limitations include:

.TP
Expand Down
4 changes: 2 additions & 2 deletions gdisk.8
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.\" Copyright 2011 Roderick W. Smith ([email protected])
.\" May be distributed under the GNU General Public License
.TH "GDISK" "8" "0.8.0" "Roderick W. Smith" "GPT fdisk Manual"
.TH "GDISK" "8" "0.8.1" "Roderick W. Smith" "GPT fdisk Manual"
.SH "NAME"
gdisk \- Interactive GUID partition table (GPT) manipulator
.SH "SYNOPSIS"
Expand Down Expand Up @@ -561,7 +561,7 @@ entering data. When only one option is possible, \fBgdisk\fR
usually bypasses the prompt entirely.

.SH "BUGS"
As of September 2011 (version 0.8.0), \fBgdisk\fR
As of September 2011 (version 0.8.1), \fBgdisk\fR
should be considered beta software. Known bugs and limitations include:

.TP
Expand Down
3 changes: 1 addition & 2 deletions gpt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -766,8 +766,7 @@ int GPTData::ForceLoadGPTData(void) {
// Return valid headers code: 0 = both headers bad; 1 = main header
// good, backup bad; 2 = backup header good, main header bad;
// 3 = both headers good. Note these codes refer to valid GPT
// signatures and version numbers; more subtle problems will elude
// this check!
// signatures, version numbers, and CRCs.
validHeaders = CheckHeaderValidity();

// Read partitions (from primary array)
Expand Down
4 changes: 2 additions & 2 deletions sgdisk.8
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.\" Copyright 2011 Roderick W. Smith ([email protected])
.\" May be distributed under the GNU General Public License
.TH "SGDISK" "8" "0.8.0" "Roderick W. Smith" "GPT fdisk Manual"
.TH "SGDISK" "8" "0.8.1" "Roderick W. Smith" "GPT fdisk Manual"
.SH "NAME"
sgdisk \- Command\-line GUID partition table (GPT) manipulator for Linux and Unix
.SH "SYNOPSIS"
Expand Down Expand Up @@ -485,7 +485,7 @@ An error prevented saving changes
Disk replication operation (-R) failed

.SH "BUGS"
As of September 2011 (version 0.8.0), \fBsgdisk\fR
As of October 2011 (version 0.8.1), \fBsgdisk\fR
should be considered beta software. Known bugs and limitations include:

.TP
Expand Down
2 changes: 1 addition & 1 deletion support.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#ifndef __GPTSUPPORT
#define __GPTSUPPORT

#define GPTFDISK_VERSION "0.8.0.1"
#define GPTFDISK_VERSION "0.8.1"

#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__)
// Darwin (Mac OS) & FreeBSD: disk IOCTLs are different, and there is no lseek64
Expand Down

0 comments on commit 23d8d54

Please sign in to comment.