Revisions for 0.6.10 release
This commit is contained in:
22
NEWS
22
NEWS
@@ -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):
|
||||
------------------
|
||||
|
||||
163
attributes.cc
163
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()
|
||||
|
||||
22
attributes.h
22
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
|
||||
|
||||
18
current.spec
18
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
|
||||
|
||||
11
gdisk.8
11
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.
|
||||
|
||||
53
gpt.cc
53
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 *
|
||||
|
||||
9
gpt.h
9
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....
|
||||
|
||||
@@ -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()
|
||||
|
||||
25
sgdisk.8
25
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
|
||||
|
||||
92
sgdisk.cc
92
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;
|
||||
|
||||
41
support.cc
41
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;
|
||||
// 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()
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user