Version 0.6.12 release; mostly changes in support for disks with other
than 512-byte sectors.
This commit is contained in:
23
NEWS
23
NEWS
@@ -1,3 +1,26 @@
|
|||||||
|
0.6.12 (10/7/2010):
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
- Adjusted alignment code to use 1 MiB alignment by default for drives with
|
||||||
|
other than 512-byte sector sizes. (Previous versions increased this --
|
||||||
|
for instance, to 4 MiB for drives with 2048-byte logical sector size.)
|
||||||
|
|
||||||
|
- Entry of non-hexadecimal value for partition type code now causes
|
||||||
|
re-prompting for a new value, fixing a recently-introduced minor bug.
|
||||||
|
|
||||||
|
- Fixed bug in sector entry using K/M/G/T/P suffixes on disks with
|
||||||
|
other-than-512-byte sector numbers.
|
||||||
|
|
||||||
|
- Added "P" (PiB, pebibyte) suffix to suffixes accepted in entering
|
||||||
|
partition sizes.
|
||||||
|
|
||||||
|
- Fixed bug that caused sgdisk to segfault if fed the (invalid)
|
||||||
|
"-A show" parameter. Now it terminates with a complaint about an invalid
|
||||||
|
partition number 0.
|
||||||
|
|
||||||
|
- Removed warning when running on big-endian hardware, since this
|
||||||
|
support has been present for quite a while with no bug reports.
|
||||||
|
|
||||||
0.6.11 (9/25/2010):
|
0.6.11 (9/25/2010):
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,33 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
string Attributes::atNames[NUM_ATR];
|
string Attributes::atNames[NUM_ATR];
|
||||||
Attributes::staticInit Attributes::staticInitializer;
|
int Attributes::numAttrs = 0;
|
||||||
|
//Attributes::staticInit Attributes::staticInitializer;
|
||||||
|
|
||||||
Attributes::staticInit::staticInit (void) {
|
// Default constructor
|
||||||
|
Attributes::Attributes(void) {
|
||||||
|
numAttrs++;
|
||||||
|
if (numAttrs == 1)
|
||||||
|
Setup();
|
||||||
|
attributes = 0;
|
||||||
|
} // constructor
|
||||||
|
|
||||||
|
// Alternate constructor
|
||||||
|
Attributes::Attributes(const uint64_t a) {
|
||||||
|
numAttrs++;
|
||||||
|
if (numAttrs == 1)
|
||||||
|
Setup();
|
||||||
|
attributes = a;
|
||||||
|
} // alternate constructor
|
||||||
|
|
||||||
|
// Destructor.
|
||||||
|
Attributes::~Attributes(void) {
|
||||||
|
numAttrs--;
|
||||||
|
} // Attributes destructor
|
||||||
|
|
||||||
|
void Attributes::Setup(void) {
|
||||||
ostringstream temp;
|
ostringstream temp;
|
||||||
|
|
||||||
// Most bits are undefined, so start by giving them an
|
// Most bits are undefined, so start by giving them an
|
||||||
// appropriate name
|
// appropriate name
|
||||||
for (int i = 0; i < NUM_ATR; i++) {
|
for (int i = 0; i < NUM_ATR; i++) {
|
||||||
@@ -33,17 +55,13 @@ Attributes::staticInit::staticInit (void) {
|
|||||||
} // for
|
} // for
|
||||||
|
|
||||||
// Now reset those names that are defined....
|
// Now reset those names that are defined....
|
||||||
Attributes::atNames[0] = "system partition"; // required for computer to operate
|
atNames[0] = "system partition"; // required for computer to operate
|
||||||
Attributes::atNames[1] = "hide from EFI";
|
atNames[1] = "hide from EFI";
|
||||||
Attributes::atNames[2] = "legacy BIOS bootable";
|
atNames[2] = "legacy BIOS bootable";
|
||||||
Attributes::atNames[60] = "read-only";
|
atNames[60] = "read-only";
|
||||||
Attributes::atNames[62] = "hidden";
|
atNames[62] = "hidden";
|
||||||
Attributes::atNames[63] = "do not automount";
|
atNames[63] = "do not automount";
|
||||||
} // Attributes::staticInit::staticInit
|
} // Attributes::Setup()
|
||||||
|
|
||||||
// Destructor.
|
|
||||||
Attributes::~Attributes(void) {
|
|
||||||
} // Attributes destructor
|
|
||||||
|
|
||||||
// Display current attributes to user
|
// Display current attributes to user
|
||||||
void Attributes::DisplayAttributes(void) {
|
void Attributes::DisplayAttributes(void) {
|
||||||
@@ -57,7 +75,7 @@ void Attributes::DisplayAttributes(void) {
|
|||||||
cout << hex << attributes << dec << ". Set fields are:\n";
|
cout << hex << attributes << dec << ". Set fields are:\n";
|
||||||
for (i = 0; i < NUM_ATR; i++) {
|
for (i = 0; i < NUM_ATR; i++) {
|
||||||
if ((UINT64_C(1) << i) & attributes) {
|
if ((UINT64_C(1) << i) & attributes) {
|
||||||
cout << i << " (" << Attributes::GetAttributeName(i) << ")" << "\n";
|
cout << i << " (" << GetAttributeName(i) << ")" << "\n";
|
||||||
numSet++;
|
numSet++;
|
||||||
} // if
|
} // if
|
||||||
} // for
|
} // for
|
||||||
@@ -67,6 +85,21 @@ void Attributes::DisplayAttributes(void) {
|
|||||||
cout << "\n";
|
cout << "\n";
|
||||||
} // Attributes::DisplayAttributes()
|
} // Attributes::DisplayAttributes()
|
||||||
|
|
||||||
|
// Display attributes for a partition. Note that partNum is just passed for
|
||||||
|
// immediate display; it's not used to access a particular partition.
|
||||||
|
void Attributes::ShowAttributes(const uint32_t partNum) {
|
||||||
|
uint32_t bitNum;
|
||||||
|
bool bitset;
|
||||||
|
|
||||||
|
for (bitNum = 0; bitNum < 64; bitNum++) {
|
||||||
|
bitset = (UINT64_C(1) << bitNum) & attributes;
|
||||||
|
if (bitset) {
|
||||||
|
cout << partNum+1 << ":" << bitNum << ":" << bitset
|
||||||
|
<< " (" << GetAttributeName(bitNum) << ")" << endl;
|
||||||
|
} // if
|
||||||
|
} // for
|
||||||
|
} // Attributes::ShowAttributes
|
||||||
|
|
||||||
// Prompt user for attribute changes
|
// Prompt user for attribute changes
|
||||||
void Attributes::ChangeAttributes(void) {
|
void Attributes::ChangeAttributes(void) {
|
||||||
int response;
|
int response;
|
||||||
@@ -78,7 +111,8 @@ void Attributes::ChangeAttributes(void) {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
DisplayAttributes();
|
DisplayAttributes();
|
||||||
response = GetNumber(0, NUM_ATR, -1, "Toggle which attribute field (0-63, 64 to exit): ");
|
response = GetNumber(0, NUM_ATR, 64,
|
||||||
|
"Toggle which attribute field (0-63, 64 or <Enter> to exit): ");
|
||||||
if (response != 64) {
|
if (response != 64) {
|
||||||
bitValue = UINT64_C(1) << response; // Find the integer value of the bit
|
bitValue = UINT64_C(1) << response; // Find the integer value of the bit
|
||||||
if (bitValue & attributes) { // bit is set
|
if (bitValue & attributes) { // bit is set
|
||||||
@@ -104,19 +138,6 @@ void Attributes::ListAttributes(void) {
|
|||||||
} // for
|
} // for
|
||||||
} // Attributes::ListAttributes
|
} // Attributes::ListAttributes
|
||||||
|
|
||||||
void Attributes::ShowAttributes(const uint32_t partNum) {
|
|
||||||
uint32_t bitNum;
|
|
||||||
bool bitset;
|
|
||||||
|
|
||||||
for (bitNum = 0; bitNum < 64; bitNum++) {
|
|
||||||
bitset = (UINT64_C(1) << bitNum) & attributes;
|
|
||||||
if (bitset) {
|
|
||||||
cout << partNum+1 << ":" << bitNum << ":" << bitset
|
|
||||||
<< " (" << Attributes::GetAttributeName(bitNum) << ")" << endl;
|
|
||||||
} // if
|
|
||||||
} // for
|
|
||||||
} // Attributes::ShowAttributes
|
|
||||||
|
|
||||||
// multifaceted attributes access
|
// multifaceted attributes access
|
||||||
// returns true upon success, false upon failure
|
// returns true upon success, false upon failure
|
||||||
bool Attributes::OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits) {
|
bool Attributes::OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits) {
|
||||||
@@ -190,3 +211,15 @@ bool Attributes::OperateOnAttributes(const uint32_t partNum, const string& attri
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
} // Attributes::OperateOnAttributes()
|
} // Attributes::OperateOnAttributes()
|
||||||
|
|
||||||
|
/*******************************
|
||||||
|
* *
|
||||||
|
* Non-class support functions *
|
||||||
|
* *
|
||||||
|
*******************************/
|
||||||
|
|
||||||
|
// Display attributes
|
||||||
|
ostream & operator<<(ostream & os, const Attributes & data) {
|
||||||
|
os << data.GetAttributes();
|
||||||
|
return os;
|
||||||
|
} // operator<<()
|
||||||
22
attributes.h
22
attributes.h
@@ -13,27 +13,29 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
class Attributes {
|
class Attributes {
|
||||||
|
|
||||||
private:
|
|
||||||
class staticInit {public: staticInit (void);};
|
|
||||||
static string atNames[NUM_ATR];
|
|
||||||
static Attributes::staticInit staticInitializer;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static string atNames[NUM_ATR];
|
||||||
|
static int numAttrs;
|
||||||
|
void Setup(void);
|
||||||
uint64_t attributes;
|
uint64_t attributes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Attributes(const uint64_t a = 0) {SetAttributes (a);}
|
Attributes(void);
|
||||||
|
Attributes(const uint64_t a);
|
||||||
~Attributes(void);
|
~Attributes(void);
|
||||||
void SetAttributes(const uint64_t a) {attributes = a;}
|
void operator=(uint64_t a) {attributes = a;}
|
||||||
uint64_t GetAttributes(void) {return attributes;}
|
|
||||||
|
uint64_t GetAttributes(void) const {return attributes;}
|
||||||
void DisplayAttributes(void);
|
void DisplayAttributes(void);
|
||||||
void ChangeAttributes(void);
|
|
||||||
void ShowAttributes(const uint32_t partNum);
|
void ShowAttributes(const uint32_t partNum);
|
||||||
|
|
||||||
|
void ChangeAttributes(void);
|
||||||
bool OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits);
|
bool OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits);
|
||||||
|
|
||||||
static const string& GetAttributeName(const uint32_t bitNum) {return atNames [bitNum];}
|
static const string& GetAttributeName(const uint32_t bitNum) {return atNames [bitNum];}
|
||||||
static void ListAttributes(void);
|
static void ListAttributes(void);
|
||||||
}; // class Attributes
|
}; // class Attributes
|
||||||
|
|
||||||
|
ostream & operator<<(ostream & os, const Attributes & data);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
Summary: An fdisk-like partitioning tool for GPT disks
|
Summary: An fdisk-like partitioning tool for GPT disks
|
||||||
Name: gdisk
|
Name: gdisk
|
||||||
Version: 0.6.11
|
Version: 0.6.12
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
License: GPLv2
|
License: GPLv2
|
||||||
URL: http://www.rodsbooks.com/gdisk
|
URL: http://www.rodsbooks.com/gdisk
|
||||||
Group: Applications/System
|
Group: Applications/System
|
||||||
Source: http://www.rodsbooks.com/gdisk/gdisk-0.6.11.tgz
|
Source: http://www.rodsbooks.com/gdisk/gdisk-0.6.12.tgz
|
||||||
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
|
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
|
||||||
|
|
||||||
%description
|
%description
|
||||||
@@ -40,5 +40,5 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
%doc %{_mandir}/man8*
|
%doc %{_mandir}/man8*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Sat Sep 25 2010 R Smith <rodsmith@rodsbooks.com> - 0.6.11
|
* Thu Oct 7 2010 R Smith <rodsmith@rodsbooks.com> - 0.6.12
|
||||||
- Created spec file for 0.6.11 release
|
- Created spec file for 0.6.12 release
|
||||||
|
|||||||
21
gdisk.8
21
gdisk.8
@@ -1,6 +1,6 @@
|
|||||||
.\" Copyright 2010 Roderick W. Smith (rodsmith@rodsbooks.com)
|
.\" Copyright 2010 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" "0.6.11" "Roderick W. Smith" "GPT fdisk Manual"
|
.TH "GDISK" "8" "0.6.12" "Roderick W. Smith" "GPT fdisk Manual"
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
gdisk \- Interactive GUID partition table (GPT) manipulator
|
gdisk \- Interactive GUID partition table (GPT) manipulator
|
||||||
.SH "SYNOPSIS"
|
.SH "SYNOPSIS"
|
||||||
@@ -197,15 +197,16 @@ Create a new partition. This command is modelled after the equivalent
|
|||||||
\fBfdisk\fR option, although some differences exist. You enter a partition
|
\fBfdisk\fR option, although some differences exist. You enter a partition
|
||||||
number, starting sector, and an ending sector. Both start and end sectors
|
number, starting sector, and an ending sector. Both start and end sectors
|
||||||
can be specified in absolute terms as sector numbers or as positions
|
can be specified in absolute terms as sector numbers or as positions
|
||||||
measured in kilobytes (K), megabytes (M), gigabytes (G), or terabytes (T);
|
measured in kibibytes (K), mebibytes (M), gibibytes (G), tebibytes (T), or
|
||||||
for instance, \fI\fB40M\fR\fR specifies a position 40MiB from the start of
|
pebibytes (P); for instance, \fI\fB40M\fR\fR specifies a position 40MiB
|
||||||
the disk. You can specify locations relative to the start or end of the
|
from the start of the disk. You can specify locations relative to the start
|
||||||
specified default range by preceding the number by a '+' or '\-' symbol, as
|
or end of the specified default range by preceding the number by a '+' or
|
||||||
in \fI\fB+2G\fR\fR to specify a point 2GiB after the default start sector,
|
'\-' symbol, as in \fI\fB+2G\fR\fR to specify a point 2GiB after the
|
||||||
or \fI\fB\-200M\fR\fR to specify a point 200MiB before the last available
|
default start sector, or \fI\fB\-200M\fR\fR to specify a point 200MiB
|
||||||
sector. Pressing the Enter key with no input specifies the default value,
|
before the last available sector. Pressing the Enter key with no input
|
||||||
which is the start of the largest available block for the start sector and
|
specifies the default value, which is the start of the largest available
|
||||||
the end of the same block for the end sector.
|
block for the start sector and the end of the same block for the end
|
||||||
|
sector.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B o
|
.B o
|
||||||
|
|||||||
76
gpt.cc
76
gpt.cc
@@ -58,7 +58,7 @@ GPTData::GPTData(void) {
|
|||||||
secondPartsCrcOk = 0;
|
secondPartsCrcOk = 0;
|
||||||
apmFound = 0;
|
apmFound = 0;
|
||||||
bsdFound = 0;
|
bsdFound = 0;
|
||||||
sectorAlignment = 8; // Align partitions on 4096-byte boundaries by default
|
sectorAlignment = MIN_AF_ALIGNMENT; // Align partitions on 4096-byte boundaries by default
|
||||||
beQuiet = 0;
|
beQuiet = 0;
|
||||||
whichWasUsed = use_new;
|
whichWasUsed = use_new;
|
||||||
srand((unsigned int) time(NULL));
|
srand((unsigned int) time(NULL));
|
||||||
@@ -81,7 +81,7 @@ GPTData::GPTData(string filename) {
|
|||||||
secondPartsCrcOk = 0;
|
secondPartsCrcOk = 0;
|
||||||
apmFound = 0;
|
apmFound = 0;
|
||||||
bsdFound = 0;
|
bsdFound = 0;
|
||||||
sectorAlignment = 8; // Align partitions on 4096-byte boundaries by default
|
sectorAlignment = MIN_AF_ALIGNMENT; // Align partitions on 4096-byte boundaries by default
|
||||||
beQuiet = 0;
|
beQuiet = 0;
|
||||||
whichWasUsed = use_new;
|
whichWasUsed = use_new;
|
||||||
srand((unsigned int) time(NULL));
|
srand((unsigned int) time(NULL));
|
||||||
@@ -248,9 +248,9 @@ int GPTData::Verify(void) {
|
|||||||
if (problems == 0) {
|
if (problems == 0) {
|
||||||
totalFree = FindFreeBlocks(&numSegments, &largestSegment);
|
totalFree = FindFreeBlocks(&numSegments, &largestSegment);
|
||||||
cout << "No problems found. " << totalFree << " free sectors ("
|
cout << "No problems found. " << totalFree << " free sectors ("
|
||||||
<< BytesToSI(totalFree * (uint64_t) blockSize) << ") available in "
|
<< BytesToSI(totalFree, blockSize) << ") available in "
|
||||||
<< numSegments << "\nsegments, the largest of which is "
|
<< numSegments << "\nsegments, the largest of which is "
|
||||||
<< largestSegment << " (" << BytesToSI(largestSegment * (uint64_t) blockSize)
|
<< largestSegment << " (" << BytesToSI(largestSegment, blockSize)
|
||||||
<< ") in size.\n";
|
<< ") in size.\n";
|
||||||
} else {
|
} else {
|
||||||
cout << "\nIdentified " << problems << " problems!\n";
|
cout << "\nIdentified " << problems << " problems!\n";
|
||||||
@@ -551,7 +551,7 @@ int GPTData::FindInsanePartitions(void) {
|
|||||||
} // if
|
} // if
|
||||||
if (partitions[i].GetLastLBA() >= diskSize) {
|
if (partitions[i].GetLastLBA() >= diskSize) {
|
||||||
problems++;
|
problems++;
|
||||||
cout << "\nProblem: partition " << i + 1<< " is too big for the disk.\n";
|
cout << "\nProblem: partition " << i + 1 << " is too big for the disk.\n";
|
||||||
} // if
|
} // if
|
||||||
} // for
|
} // for
|
||||||
return problems;
|
return problems;
|
||||||
@@ -876,11 +876,10 @@ int GPTData::SaveGPTData(int quiet, string filename) {
|
|||||||
int allOK = 1, littleEndian;
|
int allOK = 1, littleEndian;
|
||||||
char answer;
|
char answer;
|
||||||
|
|
||||||
if (filename == "")
|
|
||||||
filename = device;
|
|
||||||
|
|
||||||
littleEndian = IsLittleEndian();
|
littleEndian = IsLittleEndian();
|
||||||
|
|
||||||
|
if (filename == "")
|
||||||
|
filename = device;
|
||||||
if (filename == "") {
|
if (filename == "") {
|
||||||
cerr << "Device not defined.\n";
|
cerr << "Device not defined.\n";
|
||||||
} // if
|
} // if
|
||||||
@@ -1113,16 +1112,12 @@ int GPTData::LoadGPTBackup(const string & filename) {
|
|||||||
if ((val = CheckHeaderValidity()) > 0) {
|
if ((val = CheckHeaderValidity()) > 0) {
|
||||||
if (val == 2) { // only backup header seems to be good
|
if (val == 2) { // only backup header seems to be good
|
||||||
SetGPTSize(secondHeader.numParts);
|
SetGPTSize(secondHeader.numParts);
|
||||||
// numParts = secondHeader.numParts;
|
|
||||||
sizeOfEntries = secondHeader.sizeOfPartitionEntries;
|
sizeOfEntries = secondHeader.sizeOfPartitionEntries;
|
||||||
} else { // main header is OK
|
} else { // main header is OK
|
||||||
SetGPTSize(mainHeader.numParts);
|
SetGPTSize(mainHeader.numParts);
|
||||||
// numParts = mainHeader.numParts;
|
|
||||||
sizeOfEntries = mainHeader.sizeOfPartitionEntries;
|
sizeOfEntries = mainHeader.sizeOfPartitionEntries;
|
||||||
} // if/else
|
} // if/else
|
||||||
|
|
||||||
// SetGPTSize(numParts);
|
|
||||||
|
|
||||||
if (secondHeader.currentLBA != diskSize - UINT64_C(1)) {
|
if (secondHeader.currentLBA != diskSize - UINT64_C(1)) {
|
||||||
cout << "Warning! Current disk size doesn't match that of the backup!\n"
|
cout << "Warning! Current disk size doesn't match that of the backup!\n"
|
||||||
<< "Adjusting sizes to match, but subsequent problems are possible!\n";
|
<< "Adjusting sizes to match, but subsequent problems are possible!\n";
|
||||||
@@ -1266,7 +1261,7 @@ void GPTData::DisplayGPTData(void) {
|
|||||||
uint64_t temp, totalFree;
|
uint64_t temp, totalFree;
|
||||||
|
|
||||||
cout << "Disk " << device << ": " << diskSize << " sectors, "
|
cout << "Disk " << device << ": " << diskSize << " sectors, "
|
||||||
<< BytesToSI(diskSize * blockSize) << "\n";
|
<< BytesToSI(diskSize, blockSize) << "\n";
|
||||||
cout << "Logical sector size: " << blockSize << " bytes\n";
|
cout << "Logical sector size: " << blockSize << " bytes\n";
|
||||||
cout << "Disk identifier (GUID): " << mainHeader.diskGUID << "\n";
|
cout << "Disk identifier (GUID): " << mainHeader.diskGUID << "\n";
|
||||||
cout << "Partition table holds up to " << numParts << " entries\n";
|
cout << "Partition table holds up to " << numParts << " entries\n";
|
||||||
@@ -1275,7 +1270,7 @@ void GPTData::DisplayGPTData(void) {
|
|||||||
totalFree = FindFreeBlocks(&i, &temp);
|
totalFree = FindFreeBlocks(&i, &temp);
|
||||||
cout << "Partitions will be aligned on " << sectorAlignment << "-sector boundaries\n";
|
cout << "Partitions will be aligned on " << sectorAlignment << "-sector boundaries\n";
|
||||||
cout << "Total free space is " << totalFree << " sectors ("
|
cout << "Total free space is " << totalFree << " sectors ("
|
||||||
<< BytesToSI(totalFree * (uint64_t) blockSize) << ")\n";
|
<< BytesToSI(totalFree, blockSize) << ")\n";
|
||||||
cout << "\nNumber Start (sector) End (sector) Size Code Name\n";
|
cout << "\nNumber Start (sector) End (sector) Size Code Name\n";
|
||||||
for (i = 0; i < numParts; i++) {
|
for (i = 0; i < numParts; i++) {
|
||||||
partitions[i].ShowSummary(i, blockSize);
|
partitions[i].ShowSummary(i, blockSize);
|
||||||
@@ -1284,7 +1279,7 @@ void GPTData::DisplayGPTData(void) {
|
|||||||
|
|
||||||
// Show detailed information on the specified partition
|
// Show detailed information on the specified partition
|
||||||
void GPTData::ShowPartDetails(uint32_t partNum) {
|
void GPTData::ShowPartDetails(uint32_t partNum) {
|
||||||
if (partitions[partNum].GetFirstLBA() != 0) {
|
if (!IsFreePartNum(partNum)) {
|
||||||
partitions[partNum].ShowDetails(blockSize);
|
partitions[partNum].ShowDetails(blockSize);
|
||||||
} else {
|
} else {
|
||||||
cout << "Partition #" << partNum + 1 << " does not exist.";
|
cout << "Partition #" << partNum + 1 << " does not exist.";
|
||||||
@@ -1780,7 +1775,10 @@ int GPTData::ClearGPTData(void) {
|
|||||||
for (i = 0; i < GPT_RESERVED; i++) {
|
for (i = 0; i < GPT_RESERVED; i++) {
|
||||||
mainHeader.reserved2[i] = '\0';
|
mainHeader.reserved2[i] = '\0';
|
||||||
} // for
|
} // for
|
||||||
sectorAlignment = DEFAULT_ALIGNMENT;
|
if (blockSize > 0)
|
||||||
|
sectorAlignment = DEFAULT_ALIGNMENT * SECTOR_SIZE / blockSize;
|
||||||
|
else
|
||||||
|
sectorAlignment = DEFAULT_ALIGNMENT;
|
||||||
|
|
||||||
// Now some semi-static items (computed based on end of disk)
|
// Now some semi-static items (computed based on end of disk)
|
||||||
mainHeader.backupLBA = diskSize - UINT64_C(1);
|
mainHeader.backupLBA = diskSize - UINT64_C(1);
|
||||||
@@ -2174,31 +2172,37 @@ int GPTData::IsFreePartNum(uint32_t partNum) {
|
|||||||
// Set partition alignment value; partitions will begin on multiples of
|
// Set partition alignment value; partitions will begin on multiples of
|
||||||
// the specified value
|
// the specified value
|
||||||
void GPTData::SetAlignment(uint32_t n) {
|
void GPTData::SetAlignment(uint32_t n) {
|
||||||
sectorAlignment = n;
|
if (n > 0)
|
||||||
|
sectorAlignment = n;
|
||||||
|
else
|
||||||
|
cerr << "Attempt to set partition alignment to 0!\n";
|
||||||
} // GPTData::SetAlignment()
|
} // GPTData::SetAlignment()
|
||||||
|
|
||||||
// Compute sector alignment based on the current partitions (if any). Each
|
// Compute sector alignment based on the current partitions (if any). Each
|
||||||
// partition's starting LBA is examined, and if it's divisible by a power-of-2
|
// partition's starting LBA is examined, and if it's divisible by a power-of-2
|
||||||
// value less than or equal to the DEFAULT_ALIGNMENT value, but not by the
|
// value less than or equal to the DEFAULT_ALIGNMENT value (adjusted for the
|
||||||
// previously-located alignment value, then the alignment value is adjusted
|
// sector size), but not by the previously-located alignment value, then the
|
||||||
// down. If the computed alignment is less than 8 and the disk is bigger than
|
// alignment value is adjusted down. If the computed alignment is less than 8
|
||||||
// SMALLEST_ADVANCED_FORMAT, resets it to 8. This is a safety measure for WD
|
// and the disk is bigger than SMALLEST_ADVANCED_FORMAT, resets it to 8. This
|
||||||
// Advanced Format and similar drives. If no partitions are defined, the
|
// is a safety measure for WD Advanced Format and similar drives. If no partitions
|
||||||
// alignment value is set to DEFAULT_ALIGNMENT (2048). The result is that new
|
// are defined, the alignment value is set to DEFAULT_ALIGNMENT (2048) (or an
|
||||||
|
// adjustment of that based on the current sector size). The result is that new
|
||||||
// drives are aligned to 2048-sector multiples but the program won't complain
|
// drives are aligned to 2048-sector multiples but the program won't complain
|
||||||
// about other alignments on existing disks unless a smaller-than-8 alignment
|
// about other alignments on existing disks unless a smaller-than-8 alignment
|
||||||
// is used on small disks (as safety for WD Advanced Format drives).
|
// is used on big disks (as safety for WD Advanced Format drives).
|
||||||
// Returns the computed alignment value.
|
// Returns the computed alignment value.
|
||||||
uint32_t GPTData::ComputeAlignment(void) {
|
uint32_t GPTData::ComputeAlignment(void) {
|
||||||
uint32_t i = 0, found, exponent = 31;
|
uint32_t i = 0, found, exponent = 31;
|
||||||
uint32_t align = DEFAULT_ALIGNMENT;
|
uint32_t align = DEFAULT_ALIGNMENT;
|
||||||
|
|
||||||
exponent = (uint32_t) log2(DEFAULT_ALIGNMENT);
|
if (blockSize > 0)
|
||||||
|
align = DEFAULT_ALIGNMENT * SECTOR_SIZE / blockSize;
|
||||||
|
exponent = (uint32_t) log2(align);
|
||||||
for (i = 0; i < numParts; i++) {
|
for (i = 0; i < numParts; i++) {
|
||||||
if (partitions[i].IsUsed()) {
|
if (partitions[i].IsUsed()) {
|
||||||
found = 0;
|
found = 0;
|
||||||
while (!found) {
|
while (!found) {
|
||||||
align = UINT64_C(1)<<exponent;
|
align = UINT64_C(1) << exponent;
|
||||||
if ((partitions[i].GetFirstLBA() % align) == 0) {
|
if ((partitions[i].GetFirstLBA() % align) == 0) {
|
||||||
found = 1;
|
found = 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -2207,9 +2211,9 @@ uint32_t GPTData::ComputeAlignment(void) {
|
|||||||
} // while
|
} // while
|
||||||
} // if
|
} // if
|
||||||
} // for
|
} // for
|
||||||
if ((align < 8) && (diskSize >= SMALLEST_ADVANCED_FORMAT))
|
if ((align < MIN_AF_ALIGNMENT) && (diskSize >= SMALLEST_ADVANCED_FORMAT))
|
||||||
align = 8;
|
align = MIN_AF_ALIGNMENT;
|
||||||
SetAlignment(align);
|
sectorAlignment = align;
|
||||||
return align;
|
return align;
|
||||||
} // GPTData::ComputeAlignment()
|
} // GPTData::ComputeAlignment()
|
||||||
|
|
||||||
@@ -2296,14 +2300,12 @@ int GPTData::ManageAttributes(int partNum, const string & command, const string
|
|||||||
|
|
||||||
// Show all attributes for a specified partition....
|
// Show all attributes for a specified partition....
|
||||||
void GPTData::ShowAttributes(const uint32_t partNum) {
|
void GPTData::ShowAttributes(const uint32_t partNum) {
|
||||||
Attributes theAttr (partitions[partNum].GetAttributes());
|
partitions[partNum].ShowAttributes(partNum);
|
||||||
theAttr.ShowAttributes(partNum);
|
|
||||||
} // GPTData::ShowAttributes
|
} // GPTData::ShowAttributes
|
||||||
|
|
||||||
// Show whether a single attribute bit is set (terse output)...
|
// Show whether a single attribute bit is set (terse output)...
|
||||||
void GPTData::GetAttribute(const uint32_t partNum, const string& attributeBits) {
|
void GPTData::GetAttribute(const uint32_t partNum, const string& attributeBits) {
|
||||||
Attributes theAttr (partitions[partNum].GetAttributes());
|
partitions[partNum].GetAttributes().OperateOnAttributes(partNum, "get", attributeBits);
|
||||||
theAttr.OperateOnAttributes(partNum, "get", attributeBits);
|
|
||||||
} // GPTData::GetAttribute
|
} // GPTData::GetAttribute
|
||||||
|
|
||||||
|
|
||||||
@@ -2361,10 +2363,10 @@ int SizesOK(void) {
|
|||||||
allOK = 0;
|
allOK = 0;
|
||||||
} // if
|
} // if
|
||||||
// Determine endianness; warn user if running on big-endian (PowerPC, etc.) hardware
|
// Determine endianness; warn user if running on big-endian (PowerPC, etc.) hardware
|
||||||
if (IsLittleEndian() == 0) {
|
// if (IsLittleEndian() == 0) {
|
||||||
cerr << "\aRunning on big-endian hardware. Big-endian support is new and poorly"
|
// cerr << "\aRunning on big-endian hardware. Big-endian support is new and poorly"
|
||||||
" tested!\n";
|
// " tested!\n";
|
||||||
} // if
|
// } // if
|
||||||
return (allOK);
|
return (allOK);
|
||||||
} // SizesOK()
|
} // SizesOK()
|
||||||
|
|
||||||
|
|||||||
11
gpt.h
11
gpt.h
@@ -16,7 +16,7 @@
|
|||||||
#ifndef __GPTSTRUCTS
|
#ifndef __GPTSTRUCTS
|
||||||
#define __GPTSTRUCTS
|
#define __GPTSTRUCTS
|
||||||
|
|
||||||
#define GPTFDISK_VERSION "0.6.11"
|
#define GPTFDISK_VERSION "0.6.12"
|
||||||
|
|
||||||
// Constants used by GPTData::PartsToMBR(). MBR_EMPTY must be the lowest-
|
// Constants used by GPTData::PartsToMBR(). MBR_EMPTY must be the lowest-
|
||||||
// numbered value to refer to partition numbers. (Most will be 0 or positive,
|
// numbered value to refer to partition numbers. (Most will be 0 or positive,
|
||||||
@@ -27,11 +27,10 @@
|
|||||||
// Default values for sector alignment
|
// Default values for sector alignment
|
||||||
#define DEFAULT_ALIGNMENT 2048
|
#define DEFAULT_ALIGNMENT 2048
|
||||||
#define MAX_ALIGNMENT 65536
|
#define MAX_ALIGNMENT 65536
|
||||||
|
#define MIN_AF_ALIGNMENT 8
|
||||||
|
|
||||||
// Below constant corresponds to an 800GB disk -- a somewhat arbitrary
|
// Below constant corresponds to a ~596GiB (640MB) disk, since WD has
|
||||||
// cutoff
|
// introduced a smaller Advanced Format drive
|
||||||
//#define SMALLEST_ADVANCED_FORMAT UINT64_C(1677721600)
|
|
||||||
// Now ~596GiB (640MB), since WD has introduced a smaller Advanced Format drive
|
|
||||||
#define SMALLEST_ADVANCED_FORMAT UINT64_C(1250263728)
|
#define SMALLEST_ADVANCED_FORMAT UINT64_C(1250263728)
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -90,7 +89,7 @@ protected:
|
|||||||
int secondPartsCrcOk;
|
int secondPartsCrcOk;
|
||||||
int apmFound; // set to 1 if APM detected
|
int apmFound; // set to 1 if APM detected
|
||||||
int bsdFound; // set to 1 if BSD disklabel detected in MBR
|
int bsdFound; // set to 1 if BSD disklabel detected in MBR
|
||||||
uint32_t sectorAlignment; // Start & end partitions at multiples of sectorAlignment
|
uint32_t sectorAlignment; // Start partitions at multiples of sectorAlignment
|
||||||
int beQuiet;
|
int beQuiet;
|
||||||
WhichToUse whichWasUsed;
|
WhichToUse whichWasUsed;
|
||||||
|
|
||||||
|
|||||||
10
gptpart.cc
10
gptpart.cc
@@ -150,7 +150,7 @@ void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (firstLBA != 0) {
|
if (firstLBA != 0) {
|
||||||
sizeInSI = BytesToSI(blockSize * (lastLBA - firstLBA + 1));
|
sizeInSI = BytesToSI(lastLBA - firstLBA + 1, blockSize);
|
||||||
cout.fill(' ');
|
cout.fill(' ');
|
||||||
cout.width(4);
|
cout.width(4);
|
||||||
cout << partNum + 1 << " ";
|
cout << partNum + 1 << " ";
|
||||||
@@ -158,7 +158,7 @@ void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
|
|||||||
cout << firstLBA << " ";
|
cout << firstLBA << " ";
|
||||||
cout.width(14);
|
cout.width(14);
|
||||||
cout << lastLBA << " ";
|
cout << lastLBA << " ";
|
||||||
cout << BytesToSI(blockSize * (lastLBA - firstLBA + 1)) << " ";
|
cout << BytesToSI(lastLBA - firstLBA + 1, blockSize) << " ";
|
||||||
for (i = 0; i < 10 - (int) sizeInSI.length(); i++)
|
for (i = 0; i < 10 - (int) sizeInSI.length(); i++)
|
||||||
cout << " ";
|
cout << " ";
|
||||||
cout.fill('0');
|
cout.fill('0');
|
||||||
@@ -182,12 +182,12 @@ void GPTPart::ShowDetails(uint32_t blockSize) {
|
|||||||
cout << "Partition unique GUID: " << uniqueGUID << "\n";
|
cout << "Partition unique GUID: " << uniqueGUID << "\n";
|
||||||
|
|
||||||
cout << "First sector: " << firstLBA << " (at "
|
cout << "First sector: " << firstLBA << " (at "
|
||||||
<< BytesToSI(firstLBA * blockSize) << ")\n";
|
<< BytesToSI(firstLBA, blockSize) << ")\n";
|
||||||
cout << "Last sector: " << lastLBA << " (at "
|
cout << "Last sector: " << lastLBA << " (at "
|
||||||
<< BytesToSI(lastLBA * blockSize) << ")\n";
|
<< BytesToSI(lastLBA, blockSize) << ")\n";
|
||||||
size = (lastLBA - firstLBA + 1);
|
size = (lastLBA - firstLBA + 1);
|
||||||
cout << "Partition size: " << size << " sectors ("
|
cout << "Partition size: " << size << " sectors ("
|
||||||
<< BytesToSI(size * ((uint64_t) blockSize)) << ")\n";
|
<< BytesToSI(size, blockSize) << ")\n";
|
||||||
cout << "Attribute flags: ";
|
cout << "Attribute flags: ";
|
||||||
cout.fill('0');
|
cout.fill('0');
|
||||||
cout.width(16);
|
cout.width(16);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "support.h"
|
#include "support.h"
|
||||||
#include "parttypes.h"
|
#include "parttypes.h"
|
||||||
#include "guid.h"
|
#include "guid.h"
|
||||||
|
#include "attributes.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -43,7 +44,8 @@ class GPTPart {
|
|||||||
GUIDData uniqueGUID;
|
GUIDData uniqueGUID;
|
||||||
uint64_t firstLBA;
|
uint64_t firstLBA;
|
||||||
uint64_t lastLBA;
|
uint64_t lastLBA;
|
||||||
uint64_t attributes;
|
Attributes attributes;
|
||||||
|
// uint64_t attributes;
|
||||||
unsigned char name[NAME_SIZE];
|
unsigned char name[NAME_SIZE];
|
||||||
public:
|
public:
|
||||||
GPTPart(void);
|
GPTPart(void);
|
||||||
@@ -57,7 +59,8 @@ class GPTPart {
|
|||||||
uint64_t GetFirstLBA(void) const {return firstLBA;}
|
uint64_t GetFirstLBA(void) const {return firstLBA;}
|
||||||
uint64_t GetLastLBA(void) const {return lastLBA;}
|
uint64_t GetLastLBA(void) const {return lastLBA;}
|
||||||
uint64_t GetLengthLBA(void);
|
uint64_t GetLengthLBA(void);
|
||||||
uint64_t GetAttributes(void) {return attributes;}
|
Attributes GetAttributes(void) {return attributes;}
|
||||||
|
void ShowAttributes(uint32_t partNum) {attributes.ShowAttributes(partNum);}
|
||||||
string GetDescription(void);
|
string GetDescription(void);
|
||||||
int IsUsed(void);
|
int IsUsed(void);
|
||||||
|
|
||||||
@@ -69,6 +72,7 @@ class GPTPart {
|
|||||||
void SetFirstLBA(uint64_t f) {firstLBA = f;}
|
void SetFirstLBA(uint64_t f) {firstLBA = f;}
|
||||||
void SetLastLBA(uint64_t l) {lastLBA = l;}
|
void SetLastLBA(uint64_t l) {lastLBA = l;}
|
||||||
void SetAttributes(uint64_t a) {attributes = a;}
|
void SetAttributes(uint64_t a) {attributes = a;}
|
||||||
|
void SetAttributes(void) {attributes.ChangeAttributes();}
|
||||||
void SetName(const string & n);
|
void SetName(const string & n);
|
||||||
void SetDefaultDescription(void);
|
void SetDefaultDescription(void);
|
||||||
|
|
||||||
|
|||||||
16
gpttext.cc
16
gpttext.cc
@@ -207,9 +207,9 @@ void GPTDataTextUI::CreatePartition(void) {
|
|||||||
|
|
||||||
// Get first block for new partition...
|
// Get first block for new partition...
|
||||||
prompt2 << "First sector (" << firstBlock << "-" << lastBlock << ", default = "
|
prompt2 << "First sector (" << firstBlock << "-" << lastBlock << ", default = "
|
||||||
<< firstInLargest << ") or {+-}size{KMGT}: ";
|
<< firstInLargest << ") or {+-}size{KMGTP}: ";
|
||||||
do {
|
do {
|
||||||
sector = GetSectorNum(firstBlock, lastBlock, firstInLargest, prompt2.str());
|
sector = GetSectorNum(firstBlock, lastBlock, firstInLargest, blockSize, prompt2.str());
|
||||||
} while (IsFree(sector) == 0);
|
} while (IsFree(sector) == 0);
|
||||||
origSector = sector;
|
origSector = sector;
|
||||||
if (Align(§or)) {
|
if (Align(§or)) {
|
||||||
@@ -225,9 +225,9 @@ void GPTDataTextUI::CreatePartition(void) {
|
|||||||
// Get last block for new partitions...
|
// Get last block for new partitions...
|
||||||
lastBlock = FindLastInFree(firstBlock);
|
lastBlock = FindLastInFree(firstBlock);
|
||||||
prompt3 << "Last sector (" << firstBlock << "-" << lastBlock << ", default = "
|
prompt3 << "Last sector (" << firstBlock << "-" << lastBlock << ", default = "
|
||||||
<< lastBlock << ") or {+-}size{KMGT}: ";
|
<< lastBlock << ") or {+-}size{KMGTP}: ";
|
||||||
do {
|
do {
|
||||||
sector = GetSectorNum(firstBlock, lastBlock, lastBlock, prompt3.str());
|
sector = GetSectorNum(firstBlock, lastBlock, lastBlock, blockSize, prompt3.str());
|
||||||
} while (IsFree(sector) == 0);
|
} while (IsFree(sector) == 0);
|
||||||
lastBlock = sector;
|
lastBlock = sector;
|
||||||
|
|
||||||
@@ -271,11 +271,13 @@ void GPTDataTextUI::ChangePartType(void) {
|
|||||||
// Partition attributes seem to be rarely used, but I want a way to
|
// Partition attributes seem to be rarely used, but I want a way to
|
||||||
// adjust them for completeness....
|
// adjust them for completeness....
|
||||||
void GPTDataTextUI::SetAttributes(uint32_t partNum) {
|
void GPTDataTextUI::SetAttributes(uint32_t partNum) {
|
||||||
Attributes theAttr;
|
// Attributes theAttr;
|
||||||
|
|
||||||
theAttr.SetAttributes(partitions[partNum].GetAttributes());
|
partitions[partNum].SetAttributes();
|
||||||
|
/* theAttr = partitions[partNum].GetAttributes();
|
||||||
|
// theAttr.SetAttributes(partitions[partNum].GetAttributes());
|
||||||
theAttr.ChangeAttributes();
|
theAttr.ChangeAttributes();
|
||||||
partitions[partNum].SetAttributes(theAttr.GetAttributes());
|
partitions[partNum].SetAttributes(theAttr.GetAttributes()); */
|
||||||
} // GPTDataTextUI::SetAttributes()
|
} // GPTDataTextUI::SetAttributes()
|
||||||
|
|
||||||
// Ask user for two partition numbers and swap them in the table. Note that
|
// Ask user for two partition numbers and swap them in the table. Note that
|
||||||
|
|||||||
2
guid.cc
2
guid.cc
@@ -202,7 +202,7 @@ string GUIDData::DeleteSpaces(string s) {
|
|||||||
|
|
||||||
// Display a GUID as a string....
|
// Display a GUID as a string....
|
||||||
ostream & operator<<(ostream & os, const GUIDData & data) {
|
ostream & operator<<(ostream & os, const GUIDData & data) {
|
||||||
string asString;
|
// string asString;
|
||||||
|
|
||||||
os << data.AsString();
|
os << data.AsString();
|
||||||
return os;
|
return os;
|
||||||
|
|||||||
2
mbr.cc
2
mbr.cc
@@ -444,7 +444,7 @@ void MBRData::DisplayMBRData(int maxParts) {
|
|||||||
cout.fill(' ');
|
cout.fill(' ');
|
||||||
} // for
|
} // for
|
||||||
cout << "\nDisk size is " << diskSize << " sectors ("
|
cout << "\nDisk size is " << diskSize << " sectors ("
|
||||||
<< BytesToSI(diskSize * (uint64_t) blockSize) << ")\n";
|
<< BytesToSI(diskSize, blockSize) << ")\n";
|
||||||
} // MBRData::DisplayMBRData()
|
} // MBRData::DisplayMBRData()
|
||||||
|
|
||||||
// Displays the state, as a word, on stdout. Used for debugging & to
|
// Displays the state, as a word, on stdout. Used for debugging & to
|
||||||
|
|||||||
@@ -600,8 +600,8 @@ void PartNotes::ShowSummary(void) {
|
|||||||
cout << " * ";
|
cout << " * ";
|
||||||
else
|
else
|
||||||
cout << " ";
|
cout << " ";
|
||||||
sizeInSI = BytesToSI(blockSize * (gptParts[theNote->gptPartNum].GetLastLBA() -
|
sizeInSI = BytesToSI((gptParts[theNote->gptPartNum].GetLastLBA() -
|
||||||
gptParts[theNote->gptPartNum].GetFirstLBA() + 1));
|
gptParts[theNote->gptPartNum].GetFirstLBA() + 1), blockSize);
|
||||||
cout << " " << sizeInSI;
|
cout << " " << sizeInSI;
|
||||||
for (j = 0; j < 12 - (int) sizeInSI.length(); j++)
|
for (j = 0; j < 12 - (int) sizeInSI.length(); j++)
|
||||||
cout << " ";
|
cout << " ";
|
||||||
|
|||||||
@@ -192,13 +192,16 @@ int PartType::AddType(uint16_t mbrType, const char * guidData, const char * name
|
|||||||
|
|
||||||
// Assignment operator by string. If the original string is short,
|
// Assignment operator by string. If the original string is short,
|
||||||
// interpret it as a gdisk hex code; if it's longer, interpret it as
|
// interpret it as a gdisk hex code; if it's longer, interpret it as
|
||||||
// a direct entry of a GUID value....
|
// a direct entry of a GUID value. If a short string isn't a hex
|
||||||
|
// number, do nothing.
|
||||||
PartType & PartType::operator=(const string & orig) {
|
PartType & PartType::operator=(const string & orig) {
|
||||||
uint32_t hexCode;
|
uint32_t hexCode;
|
||||||
|
|
||||||
if (orig.length() < 32) {
|
if (orig.length() < 32) {
|
||||||
sscanf(orig.c_str(), "%x", &hexCode);
|
if (IsHex(orig)) {
|
||||||
*this = hexCode;
|
sscanf(orig.c_str(), "%x", &hexCode);
|
||||||
|
*this = hexCode;
|
||||||
|
} // if
|
||||||
} else {
|
} else {
|
||||||
GUIDData::operator=(orig);
|
GUIDData::operator=(orig);
|
||||||
} // if/else hexCode or GUID
|
} // if/else hexCode or GUID
|
||||||
|
|||||||
14
sgdisk.8
14
sgdisk.8
@@ -1,6 +1,6 @@
|
|||||||
.\" Copyright 2010 Roderick W. Smith (rodsmith@rodsbooks.com)
|
.\" Copyright 2010 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 "SGDISK" "8" "0.6.11" "Roderick W. Smith" "GPT fdisk Manual"
|
.TH "SGDISK" "8" "0.6.12" "Roderick W. Smith" "GPT fdisk Manual"
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
sgdisk \- Command\-line GUID partition table (GPT) manipulator for Linux and Unix
|
sgdisk \- Command\-line GUID partition table (GPT) manipulator for Linux and Unix
|
||||||
.SH "SYNOPSIS"
|
.SH "SYNOPSIS"
|
||||||
@@ -314,12 +314,12 @@ convert partitions that start above the 2TiB mark or that are larger than
|
|||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-n, \-\-new=partnum:start:end
|
.B \-n, \-\-new=partnum:start:end
|
||||||
Create a new partition. You enter a partition
|
Create a new partition. You enter a partition number, starting sector, and
|
||||||
number, starting sector, and an ending sector. Both start and end sectors
|
an ending sector. Both start and end sectors can be specified in absolute
|
||||||
can be specified in absolute terms as sector numbers or as positions
|
terms as sector numbers or as positions measured in kibibytes (K),
|
||||||
measured in kilobytes (K), megabytes (M), gigabytes (G), or terabytes (T);
|
mebibytes (M), gibibytes (G), tebibytes (T), or pebibytes (P); for
|
||||||
for instance, \fI\fB40M\fR\fR specifies a position 40MiB from the start of
|
instance, \fI\fB40M\fR\fR specifies a position 40MiB from the start of the
|
||||||
the disk. You can specify locations relative to the start or end of the
|
disk. You can specify locations relative to the start or end of the
|
||||||
specified default range by preceding the number by a '+' or '\-' symbol, as
|
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,
|
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
|
or \fI\fB\-200M\fR\fR to specify a point 200MiB before the last available
|
||||||
|
|||||||
34
sgdisk.cc
34
sgdisk.cc
@@ -136,20 +136,26 @@ int main(int argc, char *argv[]) {
|
|||||||
case 'A': {
|
case 'A': {
|
||||||
if (cmd != "list") {
|
if (cmd != "list") {
|
||||||
partNum = (int) GetInt(attributeOperation, 1) - 1;
|
partNum = (int) GetInt(attributeOperation, 1) - 1;
|
||||||
switch (theGPT.ManageAttributes(partNum, GetString(attributeOperation, 2),
|
if ((partNum >= 0) && (partNum < (int) theGPT.GetNumParts())) {
|
||||||
GetString(attributeOperation, 3))) {
|
switch (theGPT.ManageAttributes(partNum, GetString(attributeOperation, 2),
|
||||||
case -1:
|
GetString(attributeOperation, 3))) {
|
||||||
saveData = 0;
|
case -1:
|
||||||
neverSaveData = 1;
|
saveData = 0;
|
||||||
break;
|
neverSaveData = 1;
|
||||||
case 1:
|
break;
|
||||||
theGPT.JustLooking(0);
|
case 1:
|
||||||
saveData = 1;
|
theGPT.JustLooking(0);
|
||||||
break;
|
saveData = 1;
|
||||||
default:
|
break;
|
||||||
break;
|
default:
|
||||||
} // switch
|
break;
|
||||||
} // if
|
} // switch
|
||||||
|
} else {
|
||||||
|
cerr << "Error: Invalid partition number " << partNum + 1 << "\n";
|
||||||
|
saveData = 0;
|
||||||
|
neverSaveData = 1;
|
||||||
|
} // if/else reasonable partition #
|
||||||
|
} // if (cmd != "list")
|
||||||
break;
|
break;
|
||||||
} // case 'A':
|
} // case 'A':
|
||||||
case 'a':
|
case 'a':
|
||||||
|
|||||||
100
support.cc
100
support.cc
@@ -41,8 +41,7 @@ int GetNumber(int low, int high, int def, const string & prompt) {
|
|||||||
char line[255];
|
char line[255];
|
||||||
|
|
||||||
if (low != high) { // bother only if low and high differ...
|
if (low != high) { // bother only if low and high differ...
|
||||||
response = low - 1; // force one loop by setting response outside range
|
do {
|
||||||
while ((response < low) || (response > high)) {
|
|
||||||
cout << prompt;
|
cout << prompt;
|
||||||
cin.getline(line, 255);
|
cin.getline(line, 255);
|
||||||
num = sscanf(line, "%d", &response);
|
num = sscanf(line, "%d", &response);
|
||||||
@@ -52,7 +51,7 @@ int GetNumber(int low, int high, int def, const string & prompt) {
|
|||||||
} else { // user hit enter; return default
|
} else { // user hit enter; return default
|
||||||
response = def;
|
response = def;
|
||||||
} // if/else
|
} // if/else
|
||||||
} // while
|
} while ((response < low) || (response > high));
|
||||||
} else { // low == high, so return this value
|
} else { // low == high, so return this value
|
||||||
cout << "Using " << low << "\n";
|
cout << "Using " << low << "\n";
|
||||||
response = low;
|
response = low;
|
||||||
@@ -63,33 +62,40 @@ int GetNumber(int low, int high, int def, const string & prompt) {
|
|||||||
// Gets a Y/N response (and converts lowercase to uppercase)
|
// Gets a Y/N response (and converts lowercase to uppercase)
|
||||||
char GetYN(void) {
|
char GetYN(void) {
|
||||||
char line[255];
|
char line[255];
|
||||||
char response = '\0';
|
char response;
|
||||||
char *junk;
|
char *junk;
|
||||||
|
|
||||||
while ((response != 'Y') && (response != 'N')) {
|
do {
|
||||||
cout << "(Y/N): ";
|
cout << "(Y/N): ";
|
||||||
junk = fgets(line, 255, stdin);
|
junk = fgets(line, 255, stdin);
|
||||||
sscanf(line, "%c", &response);
|
sscanf(line, "%c", &response);
|
||||||
if (response == 'y') response = 'Y';
|
if (response == 'y')
|
||||||
if (response == 'n') response = 'N';
|
response = 'Y';
|
||||||
} // while
|
if (response == 'n')
|
||||||
|
response = 'N';
|
||||||
|
} while ((response != 'Y') && (response != 'N'));
|
||||||
return response;
|
return response;
|
||||||
} // GetYN(void)
|
} // GetYN(void)
|
||||||
|
|
||||||
// Obtains a sector number, between low and high, from the
|
// Obtains a sector number, between low and high, from the
|
||||||
// user, accepting values prefixed by "+" to add sectors to low,
|
// user, accepting values prefixed by "+" to add sectors to low,
|
||||||
// or the same with "K", "M", "G", or "T" as suffixes to add
|
// or the same with "K", "M", "G", "T", or "P" as suffixes to add
|
||||||
// kilobytes, megabytes, gigabytes, or terabytes, respectively.
|
// kilobytes, megabytes, gigabytes, terabytes, or petabytes,
|
||||||
// If a "-" prefix is used, use the high value minus the user-
|
// respectively. If a "-" prefix is used, use the high value minus
|
||||||
// specified number of sectors (or KiB, MiB, etc.). Use the def
|
// the user-specified number of sectors (or KiB, MiB, etc.). Use the
|
||||||
//value as the default if the user just hits Enter
|
// def value as the default if the user just hits Enter. The sSize is
|
||||||
uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const string & prompt) {
|
// the sector size of the device.
|
||||||
uint64_t response, mult = 1;
|
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;
|
int plusFlag = 0;
|
||||||
char suffix, line[255];
|
char suffix, line[255];
|
||||||
|
|
||||||
response = low - 1; // Ensure one pass by setting a too-low initial value
|
if (sSize == 0) {
|
||||||
while ((response < low) || (response > high)) {
|
sSize = SECTOR_SIZE;
|
||||||
|
cerr << "Bug: Sector size invalid in GetSectorNum()!\n";
|
||||||
|
} // if
|
||||||
|
|
||||||
|
do {
|
||||||
cout << prompt;
|
cout << prompt;
|
||||||
cin.getline(line, 255);
|
cin.getline(line, 255);
|
||||||
|
|
||||||
@@ -124,26 +130,36 @@ uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const string &
|
|||||||
switch (suffix) {
|
switch (suffix) {
|
||||||
case 'K':
|
case 'K':
|
||||||
case 'k':
|
case 'k':
|
||||||
mult = (uint64_t) 1024 / SECTOR_SIZE;
|
mult = UINT64_C(1024) / sSize;
|
||||||
|
divide = sSize / UINT64_C(1024);
|
||||||
|
break;
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
case 'm':
|
case 'm':
|
||||||
mult = (uint64_t) 1048576 / SECTOR_SIZE;
|
mult = UINT64_C(1048576) / sSize;
|
||||||
|
divide = sSize / UINT64_C(1048576);
|
||||||
break;
|
break;
|
||||||
case 'G':
|
case 'G':
|
||||||
case 'g':
|
case 'g':
|
||||||
mult = (uint64_t) 1073741824 / SECTOR_SIZE;
|
mult = UINT64_C(1073741824) / sSize;
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
case 't':
|
case 't':
|
||||||
mult = ((uint64_t) 1073741824 * (uint64_t) 1024) / (uint64_t) SECTOR_SIZE;
|
mult = UINT64_C(1099511627776) / sSize;
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
case 'p':
|
||||||
|
mult = UINT64_C(1125899906842624) / sSize;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mult = 1;
|
mult = 1;
|
||||||
} // switch
|
} // switch
|
||||||
|
|
||||||
// Adjust response based on multiplier and plus flag, if present
|
// Adjust response based on multiplier and plus flag, if present
|
||||||
response *= mult;
|
if (mult > 1)
|
||||||
|
response *= mult;
|
||||||
|
else if (divide > 1)
|
||||||
|
response /= divide;
|
||||||
if (plusFlag == 1) {
|
if (plusFlag == 1) {
|
||||||
// Recompute response based on low part of range (if default = high
|
// Recompute response based on low part of range (if default = high
|
||||||
// value, which should be the case when prompting for the end of a
|
// value, which should be the case when prompting for the end of a
|
||||||
@@ -157,19 +173,20 @@ uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const string &
|
|||||||
if (plusFlag == -1) {
|
if (plusFlag == -1) {
|
||||||
response = high - response;
|
response = high - response;
|
||||||
} // if
|
} // if
|
||||||
} // while
|
} while ((response < low) || (response > high));
|
||||||
return response;
|
return response;
|
||||||
} // GetSectorNum()
|
} // GetSectorNum()
|
||||||
|
|
||||||
// Takes a size in bytes (in size) and converts this to a size in
|
// Takes a size and converts this to a size in SI units (KiB, MiB, GiB,
|
||||||
// SI units (KiB, MiB, GiB, TiB, or PiB), returned in C++ string
|
// TiB, or PiB), returned in C++ string form. The size is either in units
|
||||||
// form
|
// of the sector size or, if that parameter is omitted, in bytes.
|
||||||
string BytesToSI(uint64_t size) {
|
// (sectorSize defaults to 1).
|
||||||
|
string BytesToSI(uint64_t size, uint32_t sectorSize) {
|
||||||
string units;
|
string units;
|
||||||
ostringstream theValue;
|
ostringstream theValue;
|
||||||
float sizeInSI;
|
float sizeInSI;
|
||||||
|
|
||||||
sizeInSI = (float) size;
|
sizeInSI = (float) size * (float) sectorSize;
|
||||||
units = " bytes";
|
units = " bytes";
|
||||||
if (sizeInSI > 1024.0) {
|
if (sizeInSI > 1024.0) {
|
||||||
sizeInSI /= 1024.0;
|
sizeInSI /= 1024.0;
|
||||||
@@ -215,6 +232,29 @@ unsigned char StrToHex(const string & input, unsigned int position) {
|
|||||||
return retval;
|
return retval;
|
||||||
} // StrToHex()
|
} // StrToHex()
|
||||||
|
|
||||||
|
// Returns 1 if input can be interpreted as a hexadecimal number --
|
||||||
|
// all characters must be spaces, digits, or letters A-F (upper- or
|
||||||
|
// lower-case), with at least one valid hexadecimal digit; otherwise
|
||||||
|
// returns 0.
|
||||||
|
int IsHex(const string & input) {
|
||||||
|
int isHex = 1, foundHex = 0, i;
|
||||||
|
|
||||||
|
for (i = 0; i < (int) input.length(); i++) {
|
||||||
|
if ((input[i] < '0') || (input[i] > '9')) {
|
||||||
|
if ((input[i] < 'A') || (input[i] > 'F')) {
|
||||||
|
if ((input[i] < 'a') || (input[i] > 'f')) {
|
||||||
|
if ((input[i] != ' ') && (input[i] != '\n')) {
|
||||||
|
isHex = 0;
|
||||||
|
}
|
||||||
|
} else foundHex = 1;
|
||||||
|
} else foundHex = 1;
|
||||||
|
} else foundHex = 1;
|
||||||
|
} // for
|
||||||
|
if (!foundHex)
|
||||||
|
isHex = 0;
|
||||||
|
return isHex;
|
||||||
|
} // IsHex()
|
||||||
|
|
||||||
// Return 1 if the CPU architecture is little endian, 0 if it's big endian....
|
// Return 1 if the CPU architecture is little endian, 0 if it's big endian....
|
||||||
int IsLittleEndian(void) {
|
int IsLittleEndian(void) {
|
||||||
int littleE = 1; // assume little-endian (Intel-style)
|
int littleE = 1; // assume little-endian (Intel-style)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
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 <stdint.h>
|
#include <stdint.h>
|
||||||
//#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -50,9 +49,10 @@ using namespace std;
|
|||||||
|
|
||||||
int GetNumber(int low, int high, int def, const string & prompt);
|
int GetNumber(int low, int high, int def, const string & prompt);
|
||||||
char GetYN(void);
|
char GetYN(void);
|
||||||
uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const string & prompt);
|
uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, uint64_t sSize, const std::string& prompt);
|
||||||
string BytesToSI(uint64_t size);
|
string BytesToSI(uint64_t size, uint32_t sectorSize = 1);
|
||||||
unsigned char StrToHex(const string & input, unsigned int position);
|
unsigned char StrToHex(const string & input, unsigned int position);
|
||||||
|
int IsHex(const string & input); // Returns 1 if input can be hexadecimal number....
|
||||||
int IsLittleEndian(void); // Returns 1 if CPU is little-endian, 0 if it's big-endian
|
int IsLittleEndian(void); // Returns 1 if CPU is little-endian, 0 if it's big-endian
|
||||||
void ReverseBytes(void* theValue, int numBytes); // Reverses byte-order of theValue
|
void ReverseBytes(void* theValue, int numBytes); // Reverses byte-order of theValue
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user