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
(gdisk: 'u' on experts' menu; sgdisk: -R or --replicate option)
- Enable disk-wipe (-z and -Z) and verification (-v) operations in
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):
------------------

View File

@@ -8,36 +8,38 @@
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include "attributes.h"
#include "support.h"
using namespace std;
// Constructor. Its main task is to initialize the attribute name
// data.
Attributes::Attributes(void) {
int i;
ostringstream temp;
string Attributes::atNames[NUM_ATR];
Attributes::staticInit Attributes::staticInitializer;
Attributes::staticInit::staticInit (void) {
ostringstream temp;
// Most bits are undefined, so start by giving them an
// appropriate name
for (i = 1; i < NUM_ATR; i++) {
for (int i = 0; i < NUM_ATR; i++) {
temp.str("");
temp << "Undefined bit #" << i;
atNames[i] = temp.str();
Attributes::atNames[i] = temp.str();
} // for
// Now reset those names that are defined....
atNames[0] = "system partition"; // required for computer to operate
atNames[1] = "hide from EFI";
atNames[2] = "legacy BIOS bootable";
atNames[60] = "read-only";
atNames[62] = "hidden";
atNames[63] = "do not automount";
} // Attributes constructor
Attributes::atNames[0] = "system partition"; // required for computer to operate
Attributes::atNames[1] = "hide from EFI";
Attributes::atNames[2] = "legacy BIOS bootable";
Attributes::atNames[60] = "read-only";
Attributes::atNames[62] = "hidden";
Attributes::atNames[63] = "do not automount";
} // Attributes::staticInit::staticInit
// Destructor.
Attributes::~Attributes(void) {
@@ -45,7 +47,8 @@ Attributes::~Attributes(void) {
// Display current attributes to user
void Attributes::DisplayAttributes(void) {
int i;
uint32_t i;
int numSet = 0;
cout << "Attribute value is ";
cout.setf(ios::uppercase);
@@ -53,37 +56,137 @@ void Attributes::DisplayAttributes(void) {
cout.width(16);
cout << hex << attributes << dec << ". Set fields are:\n";
for (i = 0; i < NUM_ATR; i++) {
if (((attributes >> i) % 2) == 1) { // bit is set
if (atNames[NUM_ATR - i - 1].substr(0, 9) != "Undefined")
cout << atNames[NUM_ATR - i - 1] << "\n";
if ((UINT64_C(1) << i) & attributes) {
cout << i << " (" << Attributes::GetAttributeName(i) << ")" << "\n";
numSet++;
} // if
} // for
cout.fill(' ');
if (numSet == 0)
cout << " No fields set\n";
cout << "\n";
} // Attributes::DisplayAttributes()
// Prompt user for attribute changes
void Attributes::ChangeAttributes(void) {
int response, i;
int response;
uint64_t bitValue;
cout << "Known attributes are:\n";
for (i = 0; i < NUM_ATR; i++) {
if (atNames[i].substr(0, 9) != "Undefined")
cout << i << " - " << atNames[i] << "\n";
} // for
ListAttributes();
cout << "\n";
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) {
bitValue = PowerOf2(uint32_t (NUM_ATR - response - 1)); // Find the integer value of the bit
if ((bitValue & attributes) == bitValue) { // bit is set
attributes -= bitValue; // so unset it
cout << "Have disabled the '" << atNames[response] << "' attribute.\n";
bitValue = UINT64_C(1) << response; // Find the integer value of the bit
if (bitValue & attributes) { // bit is set
attributes &= ~bitValue; // so unset it
cout << "Have disabled the '" << atNames[response] << "' attribute.\n";
} else { // bit is not set
attributes += bitValue; // so set it
attributes |= bitValue; // so set it
cout << "Have enabled the '" << atNames[response] << "' attribute.\n";
} // if/else
} // if
} while (response != 64);
} // 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. */
#include <stdint.h>
//#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "support.h"
#include <string>
#ifndef __GPT_ATTRIBUTES
#define __GPT_ATTRIBUTES
@@ -16,16 +13,27 @@
using namespace std;
class Attributes {
private:
class staticInit {public: staticInit (void);};
static string atNames[NUM_ATR];
static Attributes::staticInit staticInitializer;
protected:
uint64_t attributes;
string atNames[NUM_ATR];
public:
Attributes(void);
Attributes(const uint64_t a = 0) {SetAttributes (a);}
~Attributes(void);
void SetAttributes(uint64_t a) {attributes = a;}
void SetAttributes(const uint64_t a) {attributes = a;}
uint64_t GetAttributes(void) {return attributes;}
void DisplayAttributes(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
#endif

View File

@@ -1,11 +1,11 @@
Summary: An fdisk-like partitioning tool for GPT disks
Name: gdisk
Version: 0.6.9
Version: 0.6.10
Release: 1%{?dist}
License: GPLv2
URL: http://www.rodsbooks.com/gdisk
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)
%description
@@ -23,9 +23,9 @@ CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_CXX_FLAGS" make
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/sbin
install -Dp -m0755 gdisk $RPM_BUILD_ROOT/sbin
install -Dp -m0755 sgdisk $RPM_BUILD_ROOT/sbin
mkdir -p $RPM_BUILD_ROOT/usr/sbin
install -Dp -m0755 gdisk $RPM_BUILD_ROOT/usr/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 sgdisk.8 $RPM_BUILD_ROOT/%{_mandir}/man8/sgdisk.8
@@ -35,10 +35,10 @@ rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root -)
%doc NEWS COPYING README
/sbin/gdisk
/sbin/sgdisk
/usr/sbin/gdisk
/usr/sbin/sgdisk
%doc %{_mandir}/man8*
%changelog
* Sun Jul 4 2010 R Smith <rodsmith@rodsbooks.com> - 0.6.9
- Created spec file for 0.6.9 release
* Sun Aug 22 2010 R Smith <rodsmith@rodsbooks.com> - 0.6.10
- 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)
.\" 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"
gdisk \- Interactive GUID partition table (GPT) manipulator
.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
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
.B v
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;
case use_abort:
allOK = 0;
cerr << "Aborting because of invalid partition data!\n";
cerr << "Invalid partition data!\n";
break;
} // switch
@@ -1510,7 +1510,7 @@ int GPTData::PartsToMBR(PartNotes & notes) {
int mbrNum = 0, numConverted = 0;
struct PartInfo convInfo;
protectiveMBR.EmptyMBR();
protectiveMBR.EmptyMBR(0);
protectiveMBR.SetDiskSize(diskSize);
notes.Rewind();
while (notes.GetNextInfo(&convInfo) >= 0) {
@@ -2205,7 +2205,7 @@ uint32_t GPTData::ComputeAlignment(void) {
if (partitions[i].IsUsed()) {
found = 0;
while (!found) {
align = PowerOf2(exponent);
align = UINT64_C(1)<<exponent;
if ((partitions[i].GetFirstLBA() % align) == 0) {
found = 1;
} else {
@@ -2252,6 +2252,53 @@ void GPTData::ReversePartitionBytes() {
} // for
} // 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 *

9
gpt.h
View File

@@ -16,7 +16,7 @@
#ifndef __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-
// 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 GetPartLastLBA(uint32_t i) {return partitions[i].GetLastLBA();}
uint32_t CountParts(void);
bool ValidPartNum (const uint32_t partNum);
// Find information about free space
uint64_t FindFirstAvailable(uint64_t start = 0);
@@ -200,6 +201,12 @@ public:
// Endianness functions
void ReverseHeaderBytes(struct GPTHeader* header);
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
// Function prototypes....

View File

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

View File

@@ -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.9" "Roderick W. Smith" "GPT fdisk Manual"
.TH "SGDISK" "8" "0.6.10" "Roderick W. Smith" "GPT fdisk Manual"
.SH "NAME"
sgdisk \- Command\-line GUID partition table (GPT) manipulator for Linux and Unix
.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
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
.B \-b, \-\-backup=file
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.
.TP
.B E, \-\-end\-of\-largest
.B \-E, \-\-end\-of\-largest
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
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
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
.B \-s, \-\-sort
Sort partition entries. GPT partition numbers need not match the order of

View File

@@ -19,13 +19,12 @@
#include "gpt.h"
#include "support.h"
#include "parttypes.h"
#include "attributes.h"
using namespace std;
#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 CountColons(char* argument);
@@ -39,15 +38,18 @@ int main(int argc, char *argv[]) {
unsigned int hexCode;
uint32_t tableSize = 128;
uint64_t startSector, endSector;
char *attributeOperation = NULL;
char *device = NULL;
char *newPartInfo = NULL, *typeCode = NULL, *partName = NULL;
char *backupFile = NULL, *twoParts = NULL, *hybrids = NULL, *mbrParts;
char *partGUID = NULL, *diskGUID = NULL, *outDevice = NULL;
string cmd;
PartType typeHelper;
poptContext poptCon;
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"},
{"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"},
@@ -98,6 +100,11 @@ int main(int argc, char *argv[]) {
// with options that don't require a device filename....
while ((opt = poptGetNextOpt(poptCon)) > 0) {
switch (opt) {
case 'A':
cmd = GetString(attributeOperation, 1);
if (cmd == "list")
Attributes::ListAttributes();
break;
case 'L':
typeHelper.ShowAllTypes();
break;
@@ -125,6 +132,25 @@ int main(int argc, char *argv[]) {
saveNonGPT = 0; // flag so we don't overwrite unless directed to do so
while ((opt = poptGetNextOpt(poptCon)) > 0) {
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':
theGPT.SetAlignment(alignment);
break;
@@ -339,6 +365,31 @@ int main(int argc, char *argv[]) {
retval = 4;
} // if
} 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;
} // if/else loaded OK
} // if (device != NULL)
@@ -347,43 +398,6 @@ int main(int argc, char *argv[]) {
return retval;
} // 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
int BuildMBR(GPTData* theGPT, char* argument, int isHybrid) {
int numParts, allOK = 1, i;

View File

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