Revisions for 0.6.10 release

This commit is contained in:
srs5694
2010-08-22 22:44:42 -04:00
parent f9312b0ca9
commit 9ddc14bb9b
12 changed files with 353 additions and 109 deletions

22
NEWS
View File

@@ -1,8 +1,22 @@
0.6.10 (??/??/2010): 0.6.10 (8/22/2010):
-------------------- -------------------
- Added ability to save partition table from one device to another - Enable disk-wipe (-z and -Z) and verification (-v) operations in
(gdisk: 'u' on experts' menu; sgdisk: -R or --replicate option) sgdisk even if the disk is badly damaged.
- Added support for setting attributes in sgdisk (-A/--attributes option)
in sgdisk.
- Fixed bug that created backwards attribute field values (bit #2 was
entered as bit #61, etc.).
- Fixed bug that caused creation of hybrid MBR to wipe out the MBR's boot
code.
- Added ability to save partition table from one device to another (gdisk:
'u' on experts' menu; sgdisk: -R or --replicate option).
- Fixed inaccessible -C/--recompute-chs option in sgdisk.
0.6.9 (7/4/2010): 0.6.9 (7/4/2010):
------------------ ------------------

View File

@@ -8,36 +8,38 @@
#define __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS #define __STDC_CONSTANT_MACROS
#include <string.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include "attributes.h" #include "attributes.h"
#include "support.h"
using namespace std; using namespace std;
// Constructor. Its main task is to initialize the attribute name string Attributes::atNames[NUM_ATR];
// data. Attributes::staticInit Attributes::staticInitializer;
Attributes::Attributes(void) {
int i;
ostringstream temp;
Attributes::staticInit::staticInit (void) {
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 (i = 1; i < NUM_ATR; i++) { for (int i = 0; i < NUM_ATR; i++) {
temp.str("");
temp << "Undefined bit #" << i; temp << "Undefined bit #" << i;
atNames[i] = temp.str(); Attributes::atNames[i] = temp.str();
} // for } // for
// Now reset those names that are defined.... // Now reset those names that are defined....
atNames[0] = "system partition"; // required for computer to operate Attributes::atNames[0] = "system partition"; // required for computer to operate
atNames[1] = "hide from EFI"; Attributes::atNames[1] = "hide from EFI";
atNames[2] = "legacy BIOS bootable"; Attributes::atNames[2] = "legacy BIOS bootable";
atNames[60] = "read-only"; Attributes::atNames[60] = "read-only";
atNames[62] = "hidden"; Attributes::atNames[62] = "hidden";
atNames[63] = "do not automount"; Attributes::atNames[63] = "do not automount";
} // Attributes constructor } // Attributes::staticInit::staticInit
// Destructor. // Destructor.
Attributes::~Attributes(void) { Attributes::~Attributes(void) {
@@ -45,7 +47,8 @@ Attributes::~Attributes(void) {
// Display current attributes to user // Display current attributes to user
void Attributes::DisplayAttributes(void) { void Attributes::DisplayAttributes(void) {
int i; uint32_t i;
int numSet = 0;
cout << "Attribute value is "; cout << "Attribute value is ";
cout.setf(ios::uppercase); cout.setf(ios::uppercase);
@@ -53,37 +56,137 @@ void Attributes::DisplayAttributes(void) {
cout.width(16); cout.width(16);
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 (((attributes >> i) % 2) == 1) { // bit is set if ((UINT64_C(1) << i) & attributes) {
if (atNames[NUM_ATR - i - 1].substr(0, 9) != "Undefined") cout << i << " (" << Attributes::GetAttributeName(i) << ")" << "\n";
cout << atNames[NUM_ATR - i - 1] << "\n"; numSet++;
} // if } // if
} // for } // for
cout.fill(' '); cout.fill(' ');
if (numSet == 0)
cout << " No fields set\n";
cout << "\n";
} // Attributes::DisplayAttributes() } // Attributes::DisplayAttributes()
// Prompt user for attribute changes // Prompt user for attribute changes
void Attributes::ChangeAttributes(void) { void Attributes::ChangeAttributes(void) {
int response, i; int response;
uint64_t bitValue; uint64_t bitValue;
cout << "Known attributes are:\n"; cout << "Known attributes are:\n";
for (i = 0; i < NUM_ATR; i++) { ListAttributes();
if (atNames[i].substr(0, 9) != "Undefined") cout << "\n";
cout << i << " - " << atNames[i] << "\n";
} // for
do { do {
response = GetNumber(0, 64, -1, (string) "Toggle which attribute field (0-63, 64 to exit): "); DisplayAttributes();
response = GetNumber(0, NUM_ATR, -1, "Toggle which attribute field (0-63, 64 to exit): ");
if (response != 64) { if (response != 64) {
bitValue = PowerOf2(uint32_t (NUM_ATR - response - 1)); // Find the integer value of the bit bitValue = UINT64_C(1) << response; // Find the integer value of the bit
if ((bitValue & attributes) == bitValue) { // bit is set if (bitValue & attributes) { // bit is set
attributes -= bitValue; // so unset it attributes &= ~bitValue; // so unset it
cout << "Have disabled the '" << atNames[response] << "' attribute.\n"; cout << "Have disabled the '" << atNames[response] << "' attribute.\n";
} else { // bit is not set } else { // bit is not set
attributes += bitValue; // so set it attributes |= bitValue; // so set it
cout << "Have enabled the '" << atNames[response] << "' attribute.\n"; cout << "Have enabled the '" << atNames[response] << "' attribute.\n";
} // if/else } // if/else
} // if } // if
} while (response != 64); } while (response != 64);
} // Attributes::ChangeAttributes() } // Attributes::ChangeAttributes()
// Display all defined attributes on the screen (omits undefined bits).
void Attributes::ListAttributes(void) {
uint32_t bitNum;
string tempAttr;
for (bitNum = 0; bitNum < NUM_ATR; bitNum++) {
tempAttr = GetAttributeName(bitNum);
if (tempAttr.substr(0, 15) != "Undefined bit #" )
cout << bitNum << ": " << Attributes::GetAttributeName(bitNum) << "\n";
} // for
} // 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
// returns true upon success, false upon failure
bool Attributes::OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits) {
// attribute access opcode
typedef enum {
ao_or, ao_nand, ao_xor, ao_assignall, // operate on all attributes (bitmask)
ao_unknown, // must be after bitmask operators and before bitnum operators
ao_set, ao_clear, ao_toggle, ao_get // operate on a single attribute (bitnum)
} attribute_opcode_t; // typedef enum
// translate attribute operator into an attribute opcode
attribute_opcode_t attributeOpcode = ao_unknown; { // opcode is not known yet
if (attributeOperator == "or") attributeOpcode = ao_or;
else if (attributeOperator == "nand") attributeOpcode = ao_nand;
else if (attributeOperator == "xor") attributeOpcode = ao_xor;
else if (attributeOperator == "=") attributeOpcode = ao_assignall;
else if (attributeOperator == "set") attributeOpcode = ao_set;
else if (attributeOperator == "clear") attributeOpcode = ao_clear;
else if (attributeOperator == "toggle") attributeOpcode = ao_toggle;
else if (attributeOperator == "get") attributeOpcode = ao_get;
else {
cerr << "Unknown attributes operator: " << attributeOperator << endl;
return false;
} // else
} // attributeOpcode
// get bit mask if operating on entire attribute set
uint64_t attributeBitMask; { if (attributeOpcode < ao_unknown) {
if (1 != sscanf (attributeBits.c_str(), "%qx", (long long unsigned int*) &attributeBitMask)) {
cerr << "Could not convert hex attribute mask" << endl;
return false;
} // if
}} // attributeBitMask, if
// get bit number and calculate bit mask if operating on a single attribute
int bitNum; { if (attributeOpcode > ao_unknown) {
if (1 != sscanf (attributeBits.c_str(), "%d", &bitNum)) {
cerr << "Could not convert bit number" << endl;
return false;
} // if
const uint64_t one = 1;
attributeBitMask = one << bitNum;
}} // bitNum, if
switch (attributeOpcode) {
// assign all attributes at once
case ao_assignall: attributes = attributeBitMask; break;
// set individual attribute(s)
case ao_set:
case ao_or: attributes |= attributeBitMask; break;
// clear individual attribute(s)
case ao_clear:
case ao_nand: attributes &= ~attributeBitMask; break;
// toggle individual attribute(s)
case ao_toggle:
case ao_xor: attributes ^= attributeBitMask; break;
// display a single attribute
case ao_get: {
cout << partNum+1 << ":" << bitNum << ":" <<
bool (attributeBitMask & attributes) << endl;
break;
} // case ao_get
default: break; // will never get here
} // switch
return true;
} // Attributes::OperateOnAttributes()

View File

@@ -2,10 +2,7 @@
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 <string>
#include <stdlib.h>
#include <string.h>
#include "support.h"
#ifndef __GPT_ATTRIBUTES #ifndef __GPT_ATTRIBUTES
#define __GPT_ATTRIBUTES #define __GPT_ATTRIBUTES
@@ -16,16 +13,27 @@
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:
uint64_t attributes; uint64_t attributes;
string atNames[NUM_ATR];
public: public:
Attributes(void); Attributes(const uint64_t a = 0) {SetAttributes (a);}
~Attributes(void); ~Attributes(void);
void SetAttributes(uint64_t a) {attributes = a;} void SetAttributes(const uint64_t a) {attributes = a;}
uint64_t GetAttributes(void) {return attributes;} uint64_t GetAttributes(void) {return attributes;}
void DisplayAttributes(void); void DisplayAttributes(void);
void ChangeAttributes(void); void ChangeAttributes(void);
void ShowAttributes(const uint32_t partNum);
bool OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits);
static const string& GetAttributeName(const uint32_t bitNum) {return atNames [bitNum];}
static void ListAttributes(void);
}; // class Attributes }; // class Attributes
#endif #endif

View File

@@ -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.9 Version: 0.6.10
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.9.tgz Source: http://www.rodsbooks.com/gdisk/gdisk-0.6.10.tgz
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
%description %description
@@ -23,9 +23,9 @@ CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_CXX_FLAGS" make
%install %install
rm -rf $RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/sbin mkdir -p $RPM_BUILD_ROOT/usr/sbin
install -Dp -m0755 gdisk $RPM_BUILD_ROOT/sbin install -Dp -m0755 gdisk $RPM_BUILD_ROOT/usr/sbin
install -Dp -m0755 sgdisk $RPM_BUILD_ROOT/sbin install -Dp -m0755 sgdisk $RPM_BUILD_ROOT/usr/sbin
install -Dp -m0644 gdisk.8 $RPM_BUILD_ROOT/%{_mandir}/man8/gdisk.8 install -Dp -m0644 gdisk.8 $RPM_BUILD_ROOT/%{_mandir}/man8/gdisk.8
install -Dp -m0644 sgdisk.8 $RPM_BUILD_ROOT/%{_mandir}/man8/sgdisk.8 install -Dp -m0644 sgdisk.8 $RPM_BUILD_ROOT/%{_mandir}/man8/sgdisk.8
@@ -35,10 +35,10 @@ rm -rf $RPM_BUILD_ROOT
%files %files
%defattr(-,root,root -) %defattr(-,root,root -)
%doc NEWS COPYING README %doc NEWS COPYING README
/sbin/gdisk /usr/sbin/gdisk
/sbin/sgdisk /usr/sbin/sgdisk
%doc %{_mandir}/man8* %doc %{_mandir}/man8*
%changelog %changelog
* Sun Jul 4 2010 R Smith <rodsmith@rodsbooks.com> - 0.6.9 * Sun Aug 22 2010 R Smith <rodsmith@rodsbooks.com> - 0.6.10
- Created spec file for 0.6.9 release - Created spec file for 0.6.10 release

11
gdisk.8
View File

@@ -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.9" "Roderick W. Smith" "GPT fdisk Manual" .TH "GDISK" "8" "0.6.10" "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"
@@ -524,6 +524,15 @@ results in a table with partitions numbered from 2\-5. Transposing
partitions in this way has no effect on their disk space allocation; it partitions in this way has no effect on their disk space allocation; it
only alters their order in the partition table. only alters their order in the partition table.
.TP
.B u
Replicate the current device's partition table on another device. You will
be prompted to type the new device's filename. After the write operation
completes, you can continue editing the original device's partition table.
Note that the replicated partition table is an exact copy, including all
GUIDs; if the device should have its own unique GUIDs, you should use the
\fBf\fR option on the new disk.
.TP .TP
.B v .B v
Verify disk. This option is identical to the 'v' option in the main menu. Verify disk. This option is identical to the 'v' option in the main menu.

53
gpt.cc
View File

@@ -645,7 +645,7 @@ int GPTData::LoadPartitions(const string & deviceFilename) {
break; break;
case use_abort: case use_abort:
allOK = 0; allOK = 0;
cerr << "Aborting because of invalid partition data!\n"; cerr << "Invalid partition data!\n";
break; break;
} // switch } // switch
@@ -1510,7 +1510,7 @@ int GPTData::PartsToMBR(PartNotes & notes) {
int mbrNum = 0, numConverted = 0; int mbrNum = 0, numConverted = 0;
struct PartInfo convInfo; struct PartInfo convInfo;
protectiveMBR.EmptyMBR(); protectiveMBR.EmptyMBR(0);
protectiveMBR.SetDiskSize(diskSize); protectiveMBR.SetDiskSize(diskSize);
notes.Rewind(); notes.Rewind();
while (notes.GetNextInfo(&convInfo) >= 0) { while (notes.GetNextInfo(&convInfo) >= 0) {
@@ -2205,7 +2205,7 @@ uint32_t GPTData::ComputeAlignment(void) {
if (partitions[i].IsUsed()) { if (partitions[i].IsUsed()) {
found = 0; found = 0;
while (!found) { while (!found) {
align = PowerOf2(exponent); align = UINT64_C(1)<<exponent;
if ((partitions[i].GetFirstLBA() % align) == 0) { if ((partitions[i].GetFirstLBA() % align) == 0) {
found = 1; found = 1;
} else { } else {
@@ -2252,6 +2252,53 @@ void GPTData::ReversePartitionBytes() {
} // for } // for
} // GPTData::ReversePartitionBytes() } // GPTData::ReversePartitionBytes()
// Validate partition number
bool GPTData::ValidPartNum (const uint32_t partNum) {
if (partNum >= numParts) {
cerr << "Partition number out of range: " << (signed) partNum << endl;
return false;
} // if
return true;
} // GPTData::ValidPartNum
// Manage attributes for a partition, based on commands passed to this function.
// (Function is non-interactive.)
// Returns 1 if a modification command succeeded, 0 if the command should not have
// modified data, and -1 if a modification command failed.
int GPTData::ManageAttributes(int partNum, const string & command, const string & bits) {
int retval = 0;
Attributes theAttr;
if (command == "show") {
ShowAttributes(partNum);
} else if (command == "get") {
GetAttribute(partNum, bits);
} else {
theAttr = partitions[partNum].GetAttributes();
if (theAttr.OperateOnAttributes(partNum, command, bits)) {
partitions[partNum].SetAttributes(theAttr.GetAttributes());
retval = 1;
} else {
retval = -1;
} // if/else
} // if/elseif/else
return retval;
} // GPTData::ManageAttributes()
// Show all attributes for a specified partition....
void GPTData::ShowAttributes(const uint32_t partNum) {
Attributes theAttr (partitions[partNum].GetAttributes());
theAttr.ShowAttributes(partNum);
} // GPTData::ShowAttributes
// Show whether a single attribute bit is set (terse output)...
void GPTData::GetAttribute(const uint32_t partNum, const string& attributeBits) {
Attributes theAttr (partitions[partNum].GetAttributes());
theAttr.OperateOnAttributes(partNum, "get", attributeBits);
} // GPTData::GetAttribute
/****************************************** /******************************************
* * * *
* Additional non-class support functions * * Additional non-class support functions *

9
gpt.h
View File

@@ -16,7 +16,7 @@
#ifndef __GPTSTRUCTS #ifndef __GPTSTRUCTS
#define __GPTSTRUCTS #define __GPTSTRUCTS
#define GPTFDISK_VERSION "0.6.10-pre1" #define GPTFDISK_VERSION "0.6.10"
// 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,
@@ -179,6 +179,7 @@ public:
uint64_t GetPartFirstLBA(uint32_t i) {return partitions[i].GetFirstLBA();} uint64_t GetPartFirstLBA(uint32_t i) {return partitions[i].GetFirstLBA();}
uint64_t GetPartLastLBA(uint32_t i) {return partitions[i].GetLastLBA();} uint64_t GetPartLastLBA(uint32_t i) {return partitions[i].GetLastLBA();}
uint32_t CountParts(void); uint32_t CountParts(void);
bool ValidPartNum (const uint32_t partNum);
// Find information about free space // Find information about free space
uint64_t FindFirstAvailable(uint64_t start = 0); uint64_t FindFirstAvailable(uint64_t start = 0);
@@ -200,6 +201,12 @@ public:
// Endianness functions // Endianness functions
void ReverseHeaderBytes(struct GPTHeader* header); void ReverseHeaderBytes(struct GPTHeader* header);
void ReversePartitionBytes(); // for endianness void ReversePartitionBytes(); // for endianness
// Attributes functions
int ManageAttributes(int partNum, const string & command, const string & bits);
void ShowAttributes(const uint32_t partNum);
void GetAttribute(const uint32_t partNum, const string& attributeBits);
}; // class GPTData }; // class GPTData
// Function prototypes.... // Function prototypes....

View File

@@ -266,7 +266,6 @@ void GPTDataTextUI::SetAttributes(uint32_t partNum) {
Attributes theAttr; Attributes theAttr;
theAttr.SetAttributes(partitions[partNum].GetAttributes()); theAttr.SetAttributes(partitions[partNum].GetAttributes());
theAttr.DisplayAttributes();
theAttr.ChangeAttributes(); theAttr.ChangeAttributes();
partitions[partNum].SetAttributes(theAttr.GetAttributes()); partitions[partNum].SetAttributes(theAttr.GetAttributes());
} // GPTDataTextUI::SetAttributes() } // GPTDataTextUI::SetAttributes()

View File

@@ -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.9" "Roderick W. Smith" "GPT fdisk Manual" .TH "SGDISK" "8" "0.6.10" "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"
@@ -153,6 +153,20 @@ freshly formatted disks. This alignment value is necessary to obtain optimum
performance with Western Digital Advanced Format and similar drives with larger performance with Western Digital Advanced Format and similar drives with larger
physical than logical sector sizes and with some types of RAID arrays. physical than logical sector sizes and with some types of RAID arrays.
.TP
.B \-A, \-\-attributes=list|[partnum:show|or|nand|xor|=|set|clear|toggle|get[:bitnum|hexbitmask]]
View or set partition attributes. Use \fIlist\fR to see defined (known)
attribute values. Omit the partition number (and even the device filename)
when using this option. The others require a partition number. The
\fIshow\fR and \fIget\fR options show the current attribute settings
(all attributes or for a particular bit, respectively). The \fIor\fR,
\fInand\fR, \fIxor\fR, \fI\=\fR, \fIset\fR, \fIclear\fR, and
\fItoggle\fR options enable you to change the attribute bit value. The
\fIset\fR, \fIclear\fR, \fItoggle\fR, and \fIget\fR options work on a
bit number; the others work on a hexadecimal bit mask. For example, type
\fBsgdisk -A 4:set:2 /dev/sdc\fR to set the bit 2 attribute (legacy BIOS
bootable) on partition 4 on \fI/dev/sdc\fR.
.TP .TP
.B \-b, \-\-backup=file .B \-b, \-\-backup=file
Save partition data to a backup file. You can back up your current Save partition data to a backup file. You can back up your current
@@ -210,7 +224,7 @@ that follows the backup GPT data structures. This command moves the backup
GPT data structures to the end of the disk, where they belong. GPT data structures to the end of the disk, where they belong.
.TP .TP
.B E, \-\-end\-of\-largest .B \-E, \-\-end\-of\-largest
Displays the sector number of the end of the largest available block of Displays the sector number of the end of the largest available block of
sectors on the disk. A script may store this value and pass it back as sectors on the disk. A script may store this value and pass it back as
part of \fI\-n\fR's option to create a partition. If no unallocated part of \fI\-n\fR's option to create a partition. If no unallocated
@@ -339,6 +353,13 @@ table with partitions numbered from 2\-5. Transposing partitions in this
way has no effect on their disk space allocation; it only alters their way has no effect on their disk space allocation; it only alters their
order in the partition table. order in the partition table.
.TP
.B \-R, \-\-replicate=second_device_filename
Replicate the main device's partition table on the specified second device.
Note that the replicated partition table is an exact copy, including all
GUIDs; if the device should have its own unique GUIDs, you should use the
\-G option on the new disk.
.TP .TP
.B \-s, \-\-sort .B \-s, \-\-sort
Sort partition entries. GPT partition numbers need not match the order of Sort partition entries. GPT partition numbers need not match the order of

View File

@@ -19,13 +19,12 @@
#include "gpt.h" #include "gpt.h"
#include "support.h" #include "support.h"
#include "parttypes.h" #include "parttypes.h"
#include "attributes.h"
using namespace std; using namespace std;
#define MAX_OPTIONS 50 #define MAX_OPTIONS 50
uint64_t GetInt(char* Info, int itemNum);
string GetString(char* Info, int itemNum);
int BuildMBR(GPTData* theGPT, char* argument, int isHybrid); int BuildMBR(GPTData* theGPT, char* argument, int isHybrid);
int CountColons(char* argument); int CountColons(char* argument);
@@ -39,15 +38,18 @@ int main(int argc, char *argv[]) {
unsigned int hexCode; unsigned int hexCode;
uint32_t tableSize = 128; uint32_t tableSize = 128;
uint64_t startSector, endSector; uint64_t startSector, endSector;
char *attributeOperation = NULL;
char *device = NULL; char *device = NULL;
char *newPartInfo = NULL, *typeCode = NULL, *partName = NULL; char *newPartInfo = NULL, *typeCode = NULL, *partName = NULL;
char *backupFile = NULL, *twoParts = NULL, *hybrids = NULL, *mbrParts; char *backupFile = NULL, *twoParts = NULL, *hybrids = NULL, *mbrParts;
char *partGUID = NULL, *diskGUID = NULL, *outDevice = NULL; char *partGUID = NULL, *diskGUID = NULL, *outDevice = NULL;
string cmd;
PartType typeHelper; PartType typeHelper;
poptContext poptCon; poptContext poptCon;
struct poptOption theOptions[] = struct poptOption theOptions[] =
{ {
{"attributes", 'A', POPT_ARG_STRING, &attributeOperation, 'A', "operate on partition attributes", "list|[partnum:show|or|nand|xor|=|set|clear|toggle|get[:bitnum|hexbitmask]]"},
{"set-alignment", 'a', POPT_ARG_INT, &alignment, 'a', "set sector alignment", "value"}, {"set-alignment", 'a', POPT_ARG_INT, &alignment, 'a', "set sector alignment", "value"},
{"backup", 'b', POPT_ARG_STRING, &backupFile, 'b', "backup GPT to file", "file"}, {"backup", 'b', POPT_ARG_STRING, &backupFile, 'b', "backup GPT to file", "file"},
{"change-name", 'c', POPT_ARG_STRING, &partName, 'c', "change partition's name", "partnum:name"}, {"change-name", 'c', POPT_ARG_STRING, &partName, 'c', "change partition's name", "partnum:name"},
@@ -98,6 +100,11 @@ int main(int argc, char *argv[]) {
// with options that don't require a device filename.... // with options that don't require a device filename....
while ((opt = poptGetNextOpt(poptCon)) > 0) { while ((opt = poptGetNextOpt(poptCon)) > 0) {
switch (opt) { switch (opt) {
case 'A':
cmd = GetString(attributeOperation, 1);
if (cmd == "list")
Attributes::ListAttributes();
break;
case 'L': case 'L':
typeHelper.ShowAllTypes(); typeHelper.ShowAllTypes();
break; break;
@@ -125,6 +132,25 @@ int main(int argc, char *argv[]) {
saveNonGPT = 0; // flag so we don't overwrite unless directed to do so saveNonGPT = 0; // flag so we don't overwrite unless directed to do so
while ((opt = poptGetNextOpt(poptCon)) > 0) { while ((opt = poptGetNextOpt(poptCon)) > 0) {
switch (opt) { switch (opt) {
case 'A': {
if (cmd != "list") {
partNum = (int) GetInt(attributeOperation, 1) - 1;
switch (theGPT.ManageAttributes(partNum, GetString(attributeOperation, 2),
GetString(attributeOperation, 3))) {
case -1:
saveData = 0;
neverSaveData = 1;
break;
case 1:
theGPT.JustLooking(0);
saveData = 1;
break;
default:
break;
} // switch
} // if
break;
} // case 'A':
case 'a': case 'a':
theGPT.SetAlignment(alignment); theGPT.SetAlignment(alignment);
break; break;
@@ -339,6 +365,31 @@ int main(int argc, char *argv[]) {
retval = 4; retval = 4;
} // if } // if
} else { // if loaded OK } else { // if loaded OK
poptResetContext(poptCon);
// Do a few types of operations even if there are problems....
while ((opt = poptGetNextOpt(poptCon)) > 0) {
switch (opt) {
case 'v':
cout << "Verification may miss some problems!\n";
theGPT.Verify();
break;
case 'z':
if (!pretend) {
theGPT.DestroyGPT();
} // if
saveNonGPT = 0;
saveData = 0;
break;
case 'Z':
if (!pretend) {
theGPT.DestroyGPT();
theGPT.DestroyMBR();
} // if
saveNonGPT = 0;
saveData = 0;
break;
} // switch
} // while
retval = 2; retval = 2;
} // if/else loaded OK } // if/else loaded OK
} // if (device != NULL) } // if (device != NULL)
@@ -347,43 +398,6 @@ int main(int argc, char *argv[]) {
return retval; return retval;
} // main } // main
// Extract integer data from argument string, which should be colon-delimited
uint64_t GetInt(char* argument, int itemNum) {
int startPos = -1, endPos = -1;
uint64_t retval = 0;
string Info;
Info = argument;
while (itemNum-- > 0) {
startPos = endPos + 1;
endPos = Info.find(':', startPos);
}
if (endPos == (int) string::npos)
endPos = Info.length();
endPos--;
istringstream inString(Info.substr(startPos, endPos - startPos + 1));
inString >> retval;
return retval;
} // GetInt()
// Extract string data from argument string, which should be colon-delimited
string GetString(char* argument, int itemNum) {
int startPos = -1, endPos = -1;
string Info;
Info = argument;
while (itemNum-- > 0) {
startPos = endPos + 1;
endPos = Info.find(':', startPos);
}
if (endPos == (int) string::npos)
endPos = Info.length();
endPos--;
return Info.substr(startPos, endPos - startPos + 1);
} // GetString()
// Create a hybrid or regular MBR from GPT data structures // Create a hybrid or regular MBR from GPT data structures
int BuildMBR(GPTData* theGPT, char* argument, int isHybrid) { int BuildMBR(GPTData* theGPT, char* argument, int isHybrid) {
int numParts, allOK = 1, i; int numParts, allOK = 1, i;

View File

@@ -244,16 +244,35 @@ void ReverseBytes(void* theValue, int numBytes) {
} // if } // if
} // ReverseBytes() } // ReverseBytes()
// Compute (2 ^ value). Given the return type, value must be 63 or less. // Extract integer data from argument string, which should be colon-delimited
// Used in some bit-fiddling functions uint64_t GetInt(const string & argument, int itemNum) {
uint64_t PowerOf2(uint32_t value) { int startPos = -1, endPos = -1;
uint64_t retval = 1; uint64_t retval = 0;
uint32_t i;
if (value < 64) { while (itemNum-- > 0) {
for (i = 0; i < value; i++) { startPos = endPos + 1;
retval *= 2; endPos = argument.find(':', startPos);
} // for }
} else retval = 0; if (endPos == (int) string::npos)
endPos = argument.length();
endPos--;
istringstream inString(argument.substr(startPos, endPos - startPos + 1));
inString >> retval;
return retval; return retval;
} // PowerOf2() } // GetInt()
// Extract string data from argument string, which should be colon-delimited
string GetString(const string & argument, int itemNum) {
int startPos = -1, endPos = -1;
while (itemNum-- > 0) {
startPos = endPos + 1;
endPos = argument.find(':', startPos);
}
if (endPos == (int) string::npos)
endPos = argument.length();
endPos--;
return argument.substr(startPos, endPos - startPos + 1);
} // GetString()

View File

@@ -55,6 +55,9 @@ string BytesToSI(uint64_t size);
unsigned char StrToHex(const string & input, unsigned int position); unsigned char StrToHex(const string & input, unsigned int position);
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
uint64_t PowerOf2(uint32_t value);
// Extract colon-separated fields from a string....
uint64_t GetInt(const string & argument, int itemNum);
string GetString(const string & Info, int itemNum);
#endif #endif