aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS22
-rw-r--r--attributes.cc163
-rw-r--r--attributes.h22
-rw-r--r--current.spec18
-rw-r--r--gdisk.811
-rw-r--r--gpt.cc53
-rw-r--r--gpt.h9
-rw-r--r--gpttext.cc1
-rw-r--r--sgdisk.825
-rw-r--r--sgdisk.cc92
-rw-r--r--support.cc43
-rw-r--r--support.h5
12 files changed, 354 insertions, 110 deletions
diff --git a/NEWS b/NEWS
index 26c666b..777bb8e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,8 +1,22 @@
-0.6.10 (??/??/2010):
---------------------
+0.6.10 (8/22/2010):
+-------------------
+
+- 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).
-- 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):
------------------
diff --git a/attributes.cc b/attributes.cc
index 527dc87..c9c1d23 100644
--- a/attributes.cc
+++ b/attributes.cc
@@ -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()
diff --git a/attributes.h b/attributes.h
index ab8cb14..34cf258 100644
--- a/attributes.h
+++ b/attributes.h
@@ -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
diff --git a/current.spec b/current.spec
index 600c21b..009de63 100644
--- a/current.spec
+++ b/current.spec
@@ -1,11 +1,11 @@
Summary: An fdisk-like partitioning tool for GPT disks
Name: gdisk
-Version: 0.6.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
diff --git a/gdisk.8 b/gdisk.8
index e11df37..76600fc 100644
--- a/gdisk.8
+++ b/gdisk.8
@@ -1,6 +1,6 @@
.\" Copyright 2010 Roderick W. Smith (rodsmith@rodsbooks.com)
.\" May be distributed under the GNU General Public License
-.TH "GDISK" "8" "0.6.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.
diff --git a/gpt.cc b/gpt.cc
index 9bebb12..7dcbc86 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -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 *
diff --git a/gpt.h b/gpt.h
index 4ead25a..4f0ccf7 100644
--- a/gpt.h
+++ b/gpt.h
@@ -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....
diff --git a/gpttext.cc b/gpttext.cc
index fe64be0..c37e01e 100644
--- a/gpttext.cc
+++ b/gpttext.cc
@@ -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()
diff --git a/sgdisk.8 b/sgdisk.8
index 1855bcd..ecb37d3 100644
--- a/sgdisk.8
+++ b/sgdisk.8
@@ -1,6 +1,6 @@
.\" Copyright 2010 Roderick W. Smith (rodsmith@rodsbooks.com)
.\" May be distributed under the GNU General Public License
-.TH "SGDISK" "8" "0.6.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
diff --git a/sgdisk.cc b/sgdisk.cc
index 537639d..3927d26 100644
--- a/sgdisk.cc
+++ b/sgdisk.cc
@@ -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;
diff --git a/support.cc b/support.cc
index 11c6200..1711209 100644
--- a/support.cc
+++ b/support.cc
@@ -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;
-
- if (value < 64) {
- for (i = 0; i < value; i++) {
- retval *= 2;
- } // for
- } else retval = 0;
+// 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;
+
+ 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() \ No newline at end of file
diff --git a/support.h b/support.h
index 8e29f7a..be55294 100644
--- a/support.h
+++ b/support.h
@@ -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