Version 0.6.14 release
diff --git a/NEWS b/NEWS
index a734b09..eabf53d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,25 @@
+0.6.14 (1/8/2011):
+------------------
+
+- Made small change to the way the start sector is interpreted if you use a
+ "+" specification, as in "+2G" to locate a partition 2 GiB into the
+ default range. This change makes adjustments for sector alignment less
+ likely.
+
+- Modified sgdisk's -n (--new) option to work with relative start and end
+ values (which the man page incorrectly stated it already did). Values of
+ 0 for the start and end sectors refer to the first and last available
+ sectors in the largest free block, and a partition number of 0 refers to
+ the first available partition.
+
+- Added ChromeOS GUID values to list of recognized partition type GUIDs.
+ 7F00 = ChromeOS kernel, 7501 = ChromeOS root, 7502 = ChromeOS reserved.
+ Untested on actual ChromeOS system.
+
+- Tweaked APM detection to look for APM signature even if an MBR
+ signature has already been found. Helps in diagnosis of cases
+ in which an MBR has overwritten an APM disk.
+
0.6.13 (10/12/2010):
--------------------
diff --git a/current.spec b/current.spec
index caa1a84..18b283b 100644
--- a/current.spec
+++ b/current.spec
@@ -1,11 +1,11 @@
Summary: An fdisk-like partitioning tool for GPT disks
Name: gdisk
-Version: 0.6.13
+Version: 0.6.14
Release: 1%{?dist}
License: GPLv2
URL: http://www.rodsbooks.com/gdisk
Group: Applications/System
-Source: http://www.rodsbooks.com/gdisk/gdisk-0.6.13.tgz
+Source: http://www.rodsbooks.com/gdisk/gdisk-0.6.14.tgz
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
%description
@@ -40,5 +40,5 @@
%doc %{_mandir}/man8*
%changelog
-* Tue Oct 12 2010 R Smith <rodsmith@rodsbooks.com> - 0.6.13
-- Created spec file for 0.6.13 release
+* Sat Jan 8 2011 R Smith <rodsmith@rodsbooks.com> - 0.6.14
+- Created spec file for 0.6.14 release
diff --git a/gdisk.8 b/gdisk.8
index fdb7277..7d5d2c6 100644
--- a/gdisk.8
+++ b/gdisk.8
@@ -1,6 +1,6 @@
.\" Copyright 2010 Roderick W. Smith (rodsmith@rodsbooks.com)
.\" May be distributed under the GNU General Public License
-.TH "GDISK" "8" "0.6.13" "Roderick W. Smith" "GPT fdisk Manual"
+.TH "GDISK" "8" "0.6.14" "Roderick W. Smith" "GPT fdisk Manual"
.SH "NAME"
gdisk \- Interactive GUID partition table (GPT) manipulator
.SH "SYNOPSIS"
@@ -560,7 +560,7 @@
usually bypasses the prompt entirely.
.SH "BUGS"
-As of March 2010 (version 0.6.6), \fBgdisk\fR
+As of January 2011 (version 0.6.14), \fBgdisk\fR
should be considered beta software. Known bugs and limitations include:
.TP
@@ -569,7 +569,8 @@
Linux versions for x86\-64 (64\-bit), x86 (32\-bit), and PowerPC (32\-bit) have been
tested, with the x86\-64 version having seen the most testing. Under FreeBSD,
32\-bit (x86) and 64\-bit (x86\-64) versions have been tested. Only 32\-bit
-versions for Mac OS X and Windows have been tested.
+versions for Mac OS X and Windows have been tested by the author, although
+I've heard of 64-bit versions being successfully compiled.
.TP
.B *
@@ -645,9 +646,9 @@
.PP
-The support for big\-endian CPUs (PowerPC, for example) is new, as of version
-0.3.5. I advise using caution on that platform, particularly with the more
-obscure features of the program.
+The support for big\-endian CPUs (PowerPC, for example) is new, as of
+version 0.3.5. I advise using caution on such CPUs, particularly with the
+more obscure features of the program.
.SH "AUTHORS"
Primary author: Roderick W. Smith (rodsmith@rodsbooks.com)
diff --git a/gpt.cc b/gpt.cc
index 2a2df8f..bcc053a 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -344,10 +344,9 @@
cout << UINT32_C(0x00010000) << dec << "\n";
} // if/else/if
- // If MBR bad, check for an Apple disk signature
- if ((protectiveMBR.GetValidity() == invalid) &&
- (((mainHeader.signature << 32) == APM_SIGNATURE1) ||
- (mainHeader.signature << 32) == APM_SIGNATURE2)) {
+ // Check for an Apple disk signature
+ if (((mainHeader.signature << 32) == APM_SIGNATURE1) ||
+ (mainHeader.signature << 32) == APM_SIGNATURE2) {
apmFound = 1; // Will display warning message later
} // if
cout.fill(' ');
diff --git a/gpt.h b/gpt.h
index e92b8b1..9d13750 100644
--- a/gpt.h
+++ b/gpt.h
@@ -16,7 +16,7 @@
#ifndef __GPTSTRUCTS
#define __GPTSTRUCTS
-#define GPTFDISK_VERSION "0.6.13"
+#define GPTFDISK_VERSION "0.6.14"
// Constants used by GPTData::PartsToMBR(). MBR_EMPTY must be the lowest-
// numbered value to refer to partition numbers. (Most will be 0 or positive,
@@ -180,6 +180,7 @@
bool ValidPartNum (const uint32_t partNum);
const GPTPart & operator[](uint32_t partNum) const;
const GUIDData & GetDiskGUID(void) const;
+ uint32_t GetBlockSize(void) {return blockSize;}
// Find information about free space
uint64_t FindFirstAvailable(uint64_t start = 0);
diff --git a/parttypes.cc b/parttypes.cc
index d8d8624..c6e2098 100644
--- a/parttypes.cc
+++ b/parttypes.cc
@@ -95,6 +95,16 @@
// An oddball IBM filesystem....
AddType(0x7501, "37AFFC90-EF7D-4E96-91C3-2D7AE055B174", "IBM GPFS"); // General Parallel File System (GPFS)
+ // ChromeOS-specific partition types...
+ // Values taken from vboot_reference/firmware/lib/cgptlib/include/gpt.h in
+ // ChromeOS source code, retrieved 12/23/2010. They're also at
+ // http://www.chromium.org/chromium-os/chromiumos-design-docs/disk-format.
+ // These have no MBR equivalents, AFAIK, so I'm using 0x7Fxx values, since they're close
+ // to the Linux values.
+ AddType(0x7f00, "FE3A2A5D-4F32-41A7-B725-ACCC3285A309", "ChromeOS kernel");
+ AddType(0x7f01, "3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC", "ChromeOS root");
+ AddType(0x7f02, "2E0A753D-9E48-43B0-8337-B15192CB1B5E", "ChromeOS reserved");
+
// Linux-specific partition types....
AddType(0x8200, "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F", "Linux swap"); // Linux swap (or Solaris)
AddType(0x8300, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Linux native
diff --git a/sgdisk.8 b/sgdisk.8
index 4b75053..1cd2b90 100644
--- a/sgdisk.8
+++ b/sgdisk.8
@@ -1,6 +1,6 @@
.\" Copyright 2010 Roderick W. Smith (rodsmith@rodsbooks.com)
.\" May be distributed under the GNU General Public License
-.TH "SGDISK" "8" "0.6.13" "Roderick W. Smith" "GPT fdisk Manual"
+.TH "SGDISK" "8" "0.6.14" "Roderick W. Smith" "GPT fdisk Manual"
.SH "NAME"
sgdisk \- Command\-line GUID partition table (GPT) manipulator for Linux and Unix
.SH "SYNOPSIS"
@@ -323,9 +323,10 @@
specified default range by preceding the number by a '+' or '\-' symbol, as
in \fI\fB+2G\fR\fR to specify a point 2GiB after the default start sector,
or \fI\fB\-200M\fR\fR to specify a point 200MiB before the last available
-sector. Pressing the Enter key with no input specifies the default value,
-which is the start of the largest available block for the start sector and
-the end of the same block for the end sector.
+sector. A start or end value of 0 specifies the default value, which is the
+start of the largest available block for the start sector and the end of
+the same block for the end sector. A partnum value of 0 causes the program
+to use the first available partition number.
.TP
.B \-N, \-\-largest\-new=num
@@ -334,7 +335,8 @@
result in a sector-moved warning, since the first available sector
(normally 34) doesn't fall on a 2048-sector boundary (the default for
alignment). You can use the \fI\-a\fR (\fI\-\-set\-alignment\fR) option to
-adjust the alignment, if desired.
+adjust the alignment, if desired. A num value of 0 causes the program to
+use the first available partition number.
.TP
.B \-o, \-\-clear
@@ -468,7 +470,7 @@
.B 4
An error prevented saving changes
.SH "BUGS"
-As of March 2010 (version 0.6.6), \fBsgdisk\fR
+As of January 2011 (version 0.6.14), \fBsgdisk\fR
should be considered beta software. Known bugs and limitations include:
.TP
@@ -551,9 +553,9 @@
.PP
-The support for big\-endian CPUs (PowerPC, for example) is new, as of version
-0.3.5. I advise using caution on that platform, particularly with the more
-obscure features of the program.
+The support for big\-endian CPUs (PowerPC, for example) is new, as of
+version 0.3.5. I advise using caution on such systems, particularly with
+the more obscure features of the program.
.SH "AUTHORS"
Primary author: Roderick W. Smith (rodsmith@rodsbooks.com)
diff --git a/sgdisk.cc b/sgdisk.cc
index fc56202..fb0e2c8 100644
--- a/sgdisk.cc
+++ b/sgdisk.cc
@@ -10,9 +10,10 @@
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
#include <stdio.h>
-#include <string>
#include <popt.h>
#include <errno.h>
+#include <stdint.h>
+#include <string>
#include <iostream>
#include <sstream>
#include "mbr.h"
@@ -30,6 +31,8 @@
int main(int argc, char *argv[]) {
GPTData theGPT;
+ uint32_t sSize;
+ uint64_t low, high;
int opt, numOptions = 0, saveData = 0, neverSaveData = 0;
int partNum = 0, deletePartNum = 0, infoPartNum = 0, bsdPartNum = 0, largestPartNum = 0;
int saveNonGPT = 1;
@@ -131,6 +134,7 @@
if (theGPT.LoadPartitions((string) device)) {
if ((theGPT.WhichWasUsed() == use_mbr) || (theGPT.WhichWasUsed() == use_bsd))
saveNonGPT = 0; // flag so we don't overwrite unless directed to do so
+ sSize = theGPT.GetBlockSize();
while ((opt = poptGetNextOpt(poptCon)) > 0) {
switch (opt) {
case 'A': {
@@ -254,12 +258,16 @@
case 'n':
theGPT.JustLooking(0);
partNum = (int) GetInt(newPartInfo, 1) - 1;
- startSector = GetInt(newPartInfo, 2);
- endSector = GetInt(newPartInfo, 3);
+ if (partNum < 0)
+ partNum = theGPT.FindFirstFreePart();
+ low = theGPT.FindFirstInLargest();
+ high = theGPT.FindLastInFree(low);
+ startSector = SIToInt(GetString(newPartInfo, 2), sSize, low, high, low);
+ endSector = SIToInt(GetString(newPartInfo, 3), sSize, startSector, high, high);
if (theGPT.CreatePartition(partNum, startSector, endSector)) {
saveData = 1;
} else {
- cerr << "Could not create partition " << partNum << " from "
+ cerr << "Could not create partition " << partNum + 1 << " from "
<< startSector << " to " << endSector << "\n";
neverSaveData = 1;
} // if/else
@@ -269,6 +277,8 @@
theGPT.JustLooking(0);
startSector = theGPT.FindFirstInLargest();
endSector = theGPT.FindLastInFree(startSector);
+ if (largestPartNum < 0)
+ largestPartNum = theGPT.FindFirstFreePart();
if (theGPT.CreatePartition(largestPartNum - 1, startSector, endSector)) {
saveData = 1;
} else {
diff --git a/support.cc b/support.cc
index 6211fdb..ee44566 100644
--- a/support.cc
+++ b/support.cc
@@ -85,98 +85,118 @@
// the user-specified number of sectors (or KiB, MiB, etc.). Use the
// def value as the default if the user just hits Enter. The sSize is
// the sector size of the device.
-uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, uint64_t sSize, const string & prompt) {
- uint64_t response, mult = 1, divide = 1;
- int plusFlag = 0;
- char suffix, line[255];
-
- if (sSize == 0) {
- sSize = SECTOR_SIZE;
- cerr << "Bug: Sector size invalid in GetSectorNum()!\n";
- } // if
+uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, uint64_t sSize,
+ const string & prompt) {
+ uint64_t response;
+ char line[255];
do {
cout << prompt;
cin.getline(line, 255);
-
- // Remove leading spaces, if present
- while (line[0] == ' ')
- strcpy(line, &line[1]);
-
- // If present, flag and remove leading plus sign
- if (line[0] == '+') {
- plusFlag = 1;
- strcpy(line, &line[1]);
- } // if
-
- // If present, flag and remove leading minus sign
- if (line[0] == '-') {
- plusFlag = -1;
- strcpy(line, &line[1]);
- } // if
-
- // Extract numeric response and, if present, suffix
- istringstream inString(line);
- inString >> response >> suffix;
-
- // If no response, use default (def)
- if (strlen(line) == 0) {
- response = def;
- suffix = ' ';
- plusFlag = 0;
- } // if
-
- // Set multiplier based on suffix
- switch (suffix) {
- case 'K':
- case 'k':
- mult = UINT64_C(1024) / sSize;
- divide = sSize / UINT64_C(1024);
- break;
- break;
- case 'M':
- case 'm':
- mult = UINT64_C(1048576) / sSize;
- divide = sSize / UINT64_C(1048576);
- break;
- case 'G':
- case 'g':
- mult = UINT64_C(1073741824) / sSize;
- break;
- case 'T':
- case 't':
- mult = UINT64_C(1099511627776) / sSize;
- break;
- case 'P':
- case 'p':
- mult = UINT64_C(1125899906842624) / sSize;
- break;
- default:
- mult = 1;
- } // switch
-
- // Adjust response based on multiplier and plus flag, if present
- if (mult > 1)
- response *= mult;
- else if (divide > 1)
- response /= divide;
- if (plusFlag == 1) {
- // Recompute response based on low part of range (if default = high
- // value, which should be the case when prompting for the end of a
- // range) or the defaut value (if default != high, which should be
- // the case for the first sector of a partition).
- if (def == high)
- response = response + low - UINT64_C(1);
- else
- response = response + def - UINT64_C(1);
- } // if
- if (plusFlag == -1) {
- response = high - response;
- } // if
+ response = SIToInt(line, sSize, low, high, def);
} while ((response < low) || (response > high));
return response;
} // GetSectorNum()
+// Convert an SI value (K, M, G, T, or P) to its equivalent in
+// number of sectors. If no units are appended, interprets as the number
+// of sectors; otherwise, interprets as number of specified units and
+// converts to sectors. For instance, with 512-byte sectors, "1K" converts
+// to 2. If value includes a "+", adds low and subtracts 1; if SIValue
+// inclues a "-", subtracts from high. If SIValue is empty, returns def.
+// Returns integral sector value.
+uint64_t SIToInt(string SIValue, uint64_t sSize, uint64_t low, uint64_t high, uint64_t def) {
+ int plusFlag = 0, badInput = 0;
+ uint64_t response = def, mult = 1, divide = 1;
+ char suffix;
+
+ if (sSize == 0) {
+ sSize = SECTOR_SIZE;
+ cerr << "Bug: Sector size invalid in SIToInt()!\n";
+ } // if
+
+ // Remove leading spaces, if present
+ while (SIValue[0] == ' ')
+ SIValue.erase(0, 1);
+
+ // If present, flag and remove leading plus sign
+ if (SIValue[0] == '+') {
+ plusFlag = 1;
+ SIValue.erase(0, 1);
+ } // if
+
+ // If present, flag and remove leading minus sign
+ if (SIValue[0] == '-') {
+ plusFlag = -1;
+ SIValue.erase(0, 1);
+ } // if
+
+ // Extract numeric response and, if present, suffix
+ istringstream inString(SIValue);
+ if (((inString.peek() < '0') || (inString.peek() > '9')) && (inString.peek() != -1))
+ badInput = 1;
+ inString >> response >> suffix;
+
+ // If no response, or if response == 0, use default (def)
+ if ((SIValue.length() == 0) || (response == 0)) {
+ response = def;
+ suffix = ' ';
+ plusFlag = 0;
+ } // if
+
+ // Set multiplier based on suffix
+ switch (suffix) {
+ case 'K':
+ case 'k':
+ mult = UINT64_C(1024) / sSize;
+ divide = sSize / UINT64_C(1024);
+ break;
+ case 'M':
+ case 'm':
+ mult = UINT64_C(1048576) / sSize;
+ divide = sSize / UINT64_C(1048576);
+ break;
+ case 'G':
+ case 'g':
+ mult = UINT64_C(1073741824) / sSize;
+ break;
+ case 'T':
+ case 't':
+ mult = UINT64_C(1099511627776) / sSize;
+ break;
+ case 'P':
+ case 'p':
+ mult = UINT64_C(1125899906842624) / sSize;
+ break;
+ default:
+ mult = 1;
+ } // switch
+
+ // Adjust response based on multiplier and plus flag, if present
+ if (mult > 1)
+ response *= mult;
+ else if (divide > 1)
+ response /= divide;
+ if (plusFlag == 1) {
+ // Recompute response based on low part of range (if default = high
+ // value, which should be the case when prompting for the end of a
+ // range) or the defaut value (if default != high, which should be
+ // the case for the first sector of a partition).
+ if (def == high)
+ response = response + low - UINT64_C(1);
+ else
+ response = response + def;
+ } // if
+ if (plusFlag == -1) {
+ response = high - response;
+ } // if
+
+ if (badInput)
+ response = high + UINT64_C(1);
+
+ return response;
+} // SIToInt()
+
// Takes a size and converts this to a size in SI units (KiB, MiB, GiB,
// TiB, or PiB), returned in C++ string form. The size is either in units
// of the sector size or, if that parameter is omitted, in bytes.
diff --git a/support.h b/support.h
index 3ae2d9f..6a4dcef 100644
--- a/support.h
+++ b/support.h
@@ -50,6 +50,7 @@
int GetNumber(int low, int high, int def, const string & prompt);
char GetYN(void);
uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, uint64_t sSize, const std::string& prompt);
+uint64_t SIToInt(string SIValue, uint64_t sSize, uint64_t low, uint64_t high, uint64_t def = 0);
string BytesToSI(uint64_t size, uint32_t sectorSize = 1);
unsigned char StrToHex(const string & input, unsigned int position);
int IsHex(const string & input); // Returns 1 if input can be hexadecimal number....