Version 0.6.4
This commit is contained in:
47
CHANGELOG
47
CHANGELOG
@@ -1,6 +1,51 @@
|
||||
0.6.4 (??/??/2010):
|
||||
0.6.4 (2/19/2010):
|
||||
-------------------
|
||||
|
||||
- Added -m (--gpttombr) option to sgdisk, enabling conversion of GPT
|
||||
disks to MBR format, with a limit of four partitions total, and of course
|
||||
without overcoming the 2TiB limit.
|
||||
|
||||
- Added -h (--hybrid) option to sgdisk, enabling creation of hybrid
|
||||
MBRs. Fewer options are available in sgdisk than in gdisk, though,
|
||||
in order to keep the user interface manageable.
|
||||
|
||||
- Fixed off-by-one bug in specification of partition when using the
|
||||
-T (--transform-bsd) option in sgdisk.
|
||||
|
||||
- Changed the code to create a new MBR unique disk signature whenever a new
|
||||
protective MBR is generated (when doing an MBR-to-GPT conversion, when
|
||||
using the 'n' option on the experts' menu, or when using the 'o' option
|
||||
on the main menu, for example). Previous versions attempted to preserve
|
||||
the existing MBR disk signature in most cases, but this resulted in
|
||||
values of 0x00000000 whenever an empty disk was partitioned, and often in
|
||||
other cases, too. Better to risk changing this value too often than to
|
||||
leave multiple disks with 0x00000000 values, I think.
|
||||
|
||||
- Added transpose ('t' on experts' menu in gdisk; or -r or --transpose in
|
||||
sgdisk) command to enable fine-tuning partition order without doing a
|
||||
full sort.
|
||||
|
||||
- Added code to clear the MBR boot loader when doing an MBR-to-GPT
|
||||
conversion. (This was already done in full-disk BSD-to-GPT conversions.)
|
||||
This is done because I've seen a few problem reports that make me think
|
||||
some MBR boot loaders freak out and hang the system when they encounter
|
||||
GPT disks, and/or they attempt to load a second-stage boot loader stored
|
||||
in what is now GPT territory, causing a system hang. Since MBR boot
|
||||
loaders don't work on GPT disks anyhow (even GRUB needs to be
|
||||
reinstalled), this new wiping behavior shouldn't cause any problems, and
|
||||
may prevent a few.
|
||||
|
||||
- Fixed bug in Windows version that prevented saving backup files.
|
||||
|
||||
- Fixed bug that caused second and subsequent partition numbers in
|
||||
prompts in hybrid MBR conversion procedure to be displayed in
|
||||
hexadecimal.
|
||||
|
||||
- Fixed very obscure potential bug in hybrid MBR/GPT synchronization when
|
||||
deleting partitions; code wasn't matching partition lengths correctly,
|
||||
which would only affect partitions that start at the same point but have
|
||||
different lengths in MBR vs. GPT.
|
||||
|
||||
- Fixed bug in the -E option to sgdisk; it was actually returning the
|
||||
last free sector, not the last free sector in the largest free block.
|
||||
|
||||
|
||||
4
Makefile
4
Makefile
@@ -10,8 +10,8 @@ DEPEND= makedepend $(CFLAGS)
|
||||
|
||||
all: gdisk sgdisk
|
||||
|
||||
gdisk: $(LIB_OBJS) gdisk.o
|
||||
$(CXX) $(LIB_OBJS) gdisk.o -L/opt/local/lib -L/usr/local/lib -luuid -o gdisk
|
||||
gdisk: $(LIB_OBJS) gdisk.o gpttext.o
|
||||
$(CXX) $(LIB_OBJS) gdisk.o gpttext.o -L/opt/local/lib -L/usr/local/lib -luuid -o gdisk
|
||||
|
||||
sgdisk: $(LIB_OBJS) sgdisk.o
|
||||
$(CXX) $(LIB_OBJS) sgdisk.o -L/opt/local/lib -L/usr/local/lib -luuid -lpopt -o sgdisk
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
CC=/usr/bin/i586-mingw32msvc-gcc
|
||||
CXX=/usr/bin/i586-mingw32msvc-g++
|
||||
STRIP=/usr/bin/i586-mingw32msvc-strip
|
||||
CC=/usr/bin/i686-pc-mingw32-gcc
|
||||
CXX=/usr/bin/i686-pc-mingw32-g++
|
||||
STRIP=/usr/bin/i686-pc-mingw32-strip
|
||||
CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g
|
||||
CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -g
|
||||
#CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
|
||||
|
||||
@@ -90,16 +90,28 @@ use a version for another platform, or use a different partitioning tool
|
||||
altogether.
|
||||
|
||||
I compiled gdisk.exe using MinGW (http://www.mingw.org), and in particular
|
||||
its Linux-hosted cross-compiler. I have not tested the compilability of the
|
||||
source code under more mainstream Windows compilers, or even on the
|
||||
Windows-hosted MinGW variant. MinGW was designed for porting Unix
|
||||
applications to Windows, so it's entirely possible that it will work where
|
||||
other compilers won't.
|
||||
its Linux-hosted cross-compiler. Under Ubuntu Linux, the Makefile.mingw
|
||||
file enables compilation of the software via MinGW. (Type "make -f
|
||||
Makefile.mingw" to compile the software.) If you try to compile using
|
||||
another compiler or even using MinGW under Windows or another Linux
|
||||
variety, you may need to adjust the Makefile.mingw options.
|
||||
|
||||
Under Ubuntu Linux, the Makefile.mingw file enables compilation of the
|
||||
software. (Type "make -f Makefile.mingw" to compile the software.) If you
|
||||
try to compile using another compiler or even using MinGW under Windows or
|
||||
another Linux variety, you may need to adjust the Makefile.mingw options.
|
||||
I've also attempted to compile the code with OpenWatcom 1.8 and Microsoft
|
||||
Visual C++ 2008 Express. My OpenWatcom attempts failed, mostly because the
|
||||
compiler can't yet handle iostream output on standard C++ strings.
|
||||
OpenWatcom also seems to have incorrectly set the value of UINT32_MAX as if
|
||||
uint32_t values were 64-bit integers. This alone won't cause the compile to
|
||||
fail, but it would create bugs.
|
||||
|
||||
My attemps with Visual C++ were much more successful; after tracking down
|
||||
and installing a stdint.h file (I used the one from
|
||||
http://msinttypes.googlecode.com/svn/trunk/stdint.h) and making a few other
|
||||
minor changes, the code compiled fine, and seems to run properly, although
|
||||
I've not tested it extensively. I created native projects for both
|
||||
OpenWatcom and Visual C++, ignoring the Makefile approach, but I'm not
|
||||
including the relevant project files in the source tarball, since they're
|
||||
easy enough to regenerate -- just include all the *.h files and all the
|
||||
*.cc files except diskio-unix.cc and sgdisk.cc, then build.
|
||||
|
||||
If you modify GPT fdisk to get it to compile under another compiler, I
|
||||
welcome submission of patches.
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "attributes.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -20,13 +21,13 @@ using namespace std;
|
||||
// data.
|
||||
Attributes::Attributes(void) {
|
||||
int i;
|
||||
char temp[ATR_NAME_SIZE];
|
||||
ostringstream temp;
|
||||
|
||||
// Most bits are undefined, so start by giving them an
|
||||
// appropriate name
|
||||
for (i = 1; i < NUM_ATR; i++) {
|
||||
sprintf(temp, "Undefined bit #%d", i);
|
||||
atNames[i] = temp;
|
||||
temp << "Undefined bit #" << i;
|
||||
atNames[i] = temp.str();
|
||||
} // for
|
||||
|
||||
// Now reset those names that are defined....
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
//#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "support.h"
|
||||
|
||||
12
bsd.cc
12
bsd.cc
@@ -10,7 +10,7 @@
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
//#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
@@ -37,7 +37,8 @@ BSDData::BSDData(void) {
|
||||
} // default constructor
|
||||
|
||||
BSDData::~BSDData(void) {
|
||||
delete[] partitions;
|
||||
if (partitions != NULL)
|
||||
delete[] partitions;
|
||||
} // destructor
|
||||
|
||||
// Read BSD disklabel data from the specified device filename. This function
|
||||
@@ -64,9 +65,10 @@ int BSDData::ReadBSDData(const string & device, uint64_t startSector, uint64_t e
|
||||
// Load the BSD disklabel data from an already-opened disk
|
||||
// file, starting with the specified sector number.
|
||||
int BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSector) {
|
||||
uint8_t buffer[4096]; // I/O buffer
|
||||
int i, foundSig = 0, bigEnd = 0, allOK = 1;
|
||||
int allOK = 1;
|
||||
int i, foundSig = 0, bigEnd = 0;
|
||||
int relative = 0; // assume absolute partition sector numbering
|
||||
uint8_t buffer[4096]; // I/O buffer
|
||||
uint32_t realSig;
|
||||
uint32_t* temp32;
|
||||
uint16_t* temp16;
|
||||
@@ -158,7 +160,7 @@ int BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSect
|
||||
// detected above, apply a correction to all partition start sectors....
|
||||
if (relative) {
|
||||
for (i = 0; i < numParts; i++) {
|
||||
partitions[i].firstLBA += startSector;
|
||||
partitions[i].firstLBA += (uint32_t) startSector;
|
||||
} // for
|
||||
} // if
|
||||
} // if signatures OK
|
||||
|
||||
5
bsd.h
5
bsd.h
@@ -55,6 +55,9 @@ struct BSDRecord { // the partition table
|
||||
};
|
||||
|
||||
// Full data in tweaked BSD format
|
||||
// For some reason this has to be packed or MS Visual C++'s debugger complains
|
||||
// about memory errors whenever a BSDData variable is destroyed.
|
||||
#pragma pack (8)
|
||||
class BSDData {
|
||||
protected:
|
||||
// We only need a few items from the main BSD disklabel data structure....
|
||||
@@ -62,7 +65,7 @@ class BSDData {
|
||||
uint32_t sectorSize; // # of bytes per sector
|
||||
uint32_t signature2; // the magic number (again)
|
||||
uint16_t numParts; // number of partitions in table
|
||||
BSDRecord* partitions; // partition array
|
||||
struct BSDRecord* partitions; // partition array
|
||||
|
||||
// Above are basic BSD disklabel data; now add more stuff....
|
||||
uint64_t labelFirstLBA; // first sector of BSD disklabel (partition or disk)
|
||||
|
||||
@@ -97,7 +97,8 @@ int DiskIO::OpenForWrite(void) {
|
||||
// so the file can be re-opened without specifying the filename.
|
||||
void DiskIO::Close(void) {
|
||||
if (isOpen)
|
||||
close(fd);
|
||||
if (close(fd) < 0)
|
||||
cerr << "Warning! Problem closing file!\n";
|
||||
isOpen = 0;
|
||||
openForWrite = 0;
|
||||
} // DiskIO::Close()
|
||||
@@ -117,7 +118,7 @@ int DiskIO::GetBlockSize(void) {
|
||||
#ifdef __APPLE__
|
||||
err = ioctl(fd, DKIOCGETBLOCKSIZE, &blockSize);
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
||||
err = ioctl(fd, DIOCGSECTORSIZE, &blockSize);
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
@@ -161,7 +162,7 @@ void DiskIO::DiskSync(void) {
|
||||
i = ioctl(fd, DKIOCSYNCHRONIZECACHE);
|
||||
platformFound++;
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
||||
sleep(2);
|
||||
i = ioctl(fd, DIOCGFLUSH);
|
||||
cout << "Warning: The kernel may continue to use old or deleted partitions.\n"
|
||||
@@ -295,8 +296,6 @@ int DiskIO::Write(void* buffer, int numBytes) {
|
||||
// greatly since then to enable FreeBSD and MacOS support, as well as to
|
||||
// return correct values for disk image files.
|
||||
uint64_t DiskIO::DiskSize(int *err) {
|
||||
long sz; // Do not delete; needed for Linux
|
||||
long long b; // Do not delete; needed for Linux
|
||||
uint64_t sectors = 0; // size in sectors
|
||||
off_t bytes = 0; // size in bytes
|
||||
struct stat64 st;
|
||||
@@ -317,13 +316,15 @@ uint64_t DiskIO::DiskSize(int *err) {
|
||||
*err = ioctl(fd, DKIOCGETBLOCKCOUNT, §ors);
|
||||
platformFound++;
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
||||
*err = ioctl(fd, DIOCGMEDIASIZE, &bytes);
|
||||
b = GetBlockSize();
|
||||
long long b = GetBlockSize();
|
||||
sectors = bytes / b;
|
||||
platformFound++;
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
long sz;
|
||||
long long b;
|
||||
*err = ioctl(fd, BLKGETSIZE, &sz);
|
||||
if (*err) {
|
||||
sectors = sz = 0;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <winioctl.h>
|
||||
#define fstat64 fstat
|
||||
#define stat64 stat
|
||||
//#define S_IRGRP 0
|
||||
#define S_IRGRP 0
|
||||
#define S_IROTH 0
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
@@ -93,6 +93,14 @@ int DiskIO::OpenForWrite(void) {
|
||||
fd = CreateFile(realFilename.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
// Preceding call can fail when creating backup files; if so, try
|
||||
// again with different option...
|
||||
if (fd == INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(fd);
|
||||
fd = CreateFile(realFilename.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
} // if
|
||||
if (fd == INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(fd);
|
||||
isOpen = 0;
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#else
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
2
diskio.h
2
diskio.h
@@ -25,7 +25,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#if defined (__FreeBSD__) || defined (__APPLE__)
|
||||
#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__)
|
||||
#define fstat64 fstat
|
||||
#define stat64 stat
|
||||
#endif
|
||||
|
||||
10
gdisk.8
10
gdisk.8
@@ -1,6 +1,6 @@
|
||||
.\" Copyright 2009 Roderick W. Smith (rodsmith@rodsbooks.com)
|
||||
.\" May be distributed under the GNU General Public License
|
||||
.TH "GDISK" "8" "0.6.3" "Roderick W. Smith" "GPT fdisk Manual"
|
||||
.TH "GDISK" "8" "0.6.4" "Roderick W. Smith" "GPT fdisk Manual"
|
||||
.SH "NAME"
|
||||
gdisk \- Interactive GUID partition table (GPT) manipulator
|
||||
.SH "SYNOPSIS"
|
||||
@@ -497,6 +497,14 @@ seem to work, and can sometimes be useful in converting MBR disks. Larger
|
||||
sizes also work fine. OSes may impose their own limits on the number of
|
||||
partitions, though.
|
||||
|
||||
.TP
|
||||
.B t
|
||||
Swap two partitions' entries in the partition table. One partition may be
|
||||
empty. For instance, if partitions 1\-4 are defined, transposing 1 and 5
|
||||
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 v
|
||||
Verify disk. This option is identical to the 'v' option in the main menu.
|
||||
|
||||
36
gdisk.cc
36
gdisk.cc
@@ -9,24 +9,24 @@
|
||||
|
||||
//#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
//#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "mbr.h"
|
||||
#include "gpt.h"
|
||||
#include "gpttext.h"
|
||||
#include "support.h"
|
||||
|
||||
// Function prototypes....
|
||||
void MainMenu(string filename, struct GPTData* theGPT);
|
||||
void MainMenu(string filename, GPTDataTextUI* theGPT);
|
||||
void ShowCommands(void);
|
||||
void ExpertsMenu(string filename, struct GPTData* theGPT);
|
||||
void ExpertsMenu(string filename, GPTDataTextUI* theGPT);
|
||||
void ShowExpertCommands(void);
|
||||
void RecoveryMenu(string filename, struct GPTData* theGPT);
|
||||
void RecoveryMenu(string filename, GPTDataTextUI* theGPT);
|
||||
void ShowRecoveryCommands(void);
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
GPTData theGPT;
|
||||
GPTDataTextUI theGPT;
|
||||
int doMore = 1;
|
||||
char* device = NULL;
|
||||
|
||||
@@ -72,7 +72,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Accept a command and execute it. Returns only when the user
|
||||
// wants to exit (such as after a 'w' or 'q' command).
|
||||
void MainMenu(string filename, struct GPTData* theGPT) {
|
||||
void MainMenu(string filename, GPTDataTextUI* theGPT) {
|
||||
char command, line[255], buFile[255];
|
||||
char* junk;
|
||||
int goOn = 1;
|
||||
@@ -174,7 +174,7 @@ void ShowCommands(void) {
|
||||
|
||||
// Accept a recovery & transformation menu command. Returns only when the user
|
||||
// issues an exit command, such as 'w' or 'q'.
|
||||
void RecoveryMenu(string filename, struct GPTData* theGPT) {
|
||||
void RecoveryMenu(string filename, GPTDataTextUI* theGPT) {
|
||||
char command, line[255], buFile[255];
|
||||
char* junk;
|
||||
uint32_t temp1;
|
||||
@@ -221,10 +221,11 @@ void RecoveryMenu(string filename, struct GPTData* theGPT) {
|
||||
if (temp1 > 0) {
|
||||
cout << "Converted " << temp1 << " partitions. Finalize and exit? ";
|
||||
if (GetYN() == 'Y') {
|
||||
if (theGPT->DestroyGPT(0) > 0)
|
||||
if (theGPT->DestroyGPT() > 0)
|
||||
goOn = 0;
|
||||
} else {
|
||||
theGPT->MakeProtectiveMBR();
|
||||
theGPT->WriteProtectiveMBR();
|
||||
cout << "Note: New protective MBR created.\n";
|
||||
} // if/else
|
||||
} // if
|
||||
@@ -299,11 +300,10 @@ void ShowRecoveryCommands(void) {
|
||||
|
||||
// Accept an experts' menu command. Returns only after the user
|
||||
// selects an exit command, such as 'w' or 'q'.
|
||||
void ExpertsMenu(string filename, struct GPTData* theGPT) {
|
||||
void ExpertsMenu(string filename, GPTDataTextUI* theGPT) {
|
||||
char command, line[255];
|
||||
char* junk;
|
||||
uint32_t pn;
|
||||
uint32_t temp1, temp2;
|
||||
uint32_t pn, temp1, temp2;
|
||||
int goOn = 1;
|
||||
GUIDData aGUID;
|
||||
|
||||
@@ -359,10 +359,10 @@ void ExpertsMenu(string filename, struct GPTData* theGPT) {
|
||||
break;
|
||||
case 'p': case 'P':
|
||||
theGPT->DisplayGPTData();
|
||||
break;
|
||||
break;
|
||||
case 'q': case 'Q':
|
||||
goOn = 0;
|
||||
break;
|
||||
goOn = 0;
|
||||
break;
|
||||
case 'r': case 'R':
|
||||
RecoveryMenu(filename, theGPT);
|
||||
goOn = 0;
|
||||
@@ -370,6 +370,9 @@ void ExpertsMenu(string filename, struct GPTData* theGPT) {
|
||||
case 's': case 'S':
|
||||
theGPT->ResizePartitionTable();
|
||||
break;
|
||||
case 't': case 'T':
|
||||
theGPT->SwapPartitions();
|
||||
break;
|
||||
case 'v': case 'V':
|
||||
theGPT->Verify();
|
||||
break;
|
||||
@@ -379,7 +382,7 @@ void ExpertsMenu(string filename, struct GPTData* theGPT) {
|
||||
} // if
|
||||
break;
|
||||
case 'z': case 'Z':
|
||||
if (theGPT->DestroyGPT() == 1) {
|
||||
if (theGPT->DestroyGPTwPrompt() == 1) {
|
||||
goOn = 0;
|
||||
}
|
||||
break;
|
||||
@@ -405,6 +408,7 @@ void ShowExpertCommands(void) {
|
||||
cout << "q\tquit without saving changes\n";
|
||||
cout << "r\trecovery and transformation options (experts only)\n";
|
||||
cout << "s\tresize partition table\n";
|
||||
cout << "t\ttranspose two partition table entries\n";
|
||||
cout << "v\tverify disk\n";
|
||||
cout << "w\twrite table to disk and exit\n";
|
||||
cout << "z\tzap (destroy) GPT data structures and exit\n";
|
||||
|
||||
40
gpt.h
40
gpt.h
@@ -15,7 +15,13 @@
|
||||
#ifndef __GPTSTRUCTS
|
||||
#define __GPTSTRUCTS
|
||||
|
||||
#define GPTFDISK_VERSION "0.6.4-pre1"
|
||||
#define GPTFDISK_VERSION "0.6.4"
|
||||
|
||||
// Constants used by GPTData::PartsToMBR(). MBR_EMPTY must be the lowest-
|
||||
// numbered value to refer to partition numbers. (Most will be 0 or positive,
|
||||
// of course.)
|
||||
#define MBR_EFI_GPT -1
|
||||
#define MBR_EMPTY -2
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -83,7 +89,7 @@ public:
|
||||
// Basic necessary functions....
|
||||
GPTData(void);
|
||||
GPTData(string deviceFilename);
|
||||
~GPTData(void);
|
||||
virtual ~GPTData(void);
|
||||
|
||||
// Verify (or update) data integrity
|
||||
int Verify(void);
|
||||
@@ -98,6 +104,7 @@ public:
|
||||
|
||||
// Load or save data from/to disk
|
||||
int LoadMBR(const string & f) {return protectiveMBR.ReadMBRData(f);}
|
||||
int WriteProtectiveMBR(void) {return protectiveMBR.WriteMBRData(&myDisk);}
|
||||
void PartitionScan(void);
|
||||
int LoadPartitions(const string & deviceFilename);
|
||||
int ForceLoadGPTData(void);
|
||||
@@ -106,32 +113,24 @@ public:
|
||||
int SaveGPTData(int quiet = 0);
|
||||
int SaveGPTBackup(const string & filename);
|
||||
int LoadGPTBackup(const string & filename);
|
||||
int SaveMBR(void);
|
||||
int DestroyGPT(void);
|
||||
int DestroyMBR(void);
|
||||
|
||||
// Display data....
|
||||
void ShowAPMState(void);
|
||||
void ShowGPTState(void);
|
||||
void DisplayGPTData(void);
|
||||
void DisplayMBRData(void) {protectiveMBR.DisplayMBRData();}
|
||||
void ShowDetails(void);
|
||||
void ShowPartDetails(uint32_t partNum);
|
||||
|
||||
// Request information from the user (& possibly do something with it)
|
||||
uint32_t GetPartNum(void);
|
||||
void ResizePartitionTable(void);
|
||||
void CreatePartition(void);
|
||||
void DeletePartition(void);
|
||||
void ChangePartType(void);
|
||||
void SetAttributes(uint32_t partNum);
|
||||
int DestroyGPT(int prompt = 1); // Returns 1 if user proceeds
|
||||
|
||||
// Convert between GPT and other formats (may require user interaction)
|
||||
WhichToUse UseWhichPartitions(void);
|
||||
int XFormPartitions(void);
|
||||
int XFormDisklabel(int OnGptPart = -1);
|
||||
int XFormDisklabel(BSDData* disklabel, uint32_t startPart);
|
||||
// Convert between GPT and other formats
|
||||
virtual WhichToUse UseWhichPartitions(void);
|
||||
void XFormPartitions(void);
|
||||
virtual int XFormDisklabel(uint32_t partNum);
|
||||
int XFormDisklabel(BSDData* disklabel);
|
||||
int OnePartToMBR(uint32_t gptPart, int mbrPart); // add one partition to MBR. Returns 1 if successful
|
||||
int XFormToMBR(void); // convert GPT to MBR, wiping GPT afterwards. Returns 1 if successful
|
||||
void MakeHybrid(void);
|
||||
int PartsToMBR(const int *gptParts, const int *mbrTypes);
|
||||
|
||||
// Adjust GPT structures WITHOUT user interaction...
|
||||
int SetGPTSize(uint32_t numEntries);
|
||||
@@ -139,6 +138,8 @@ public:
|
||||
int DeletePartition(uint32_t partNum);
|
||||
uint32_t CreatePartition(uint32_t partNum, uint64_t startSector, uint64_t endSector);
|
||||
void SortGPT(void);
|
||||
void QuickSortGPT(int start, int finish);
|
||||
int SwapPartitions(uint32_t partNum1, uint32_t partNum2);
|
||||
int ClearGPTData(void);
|
||||
void MoveSecondHeaderToEnd();
|
||||
int SetName(uint32_t partNum, const string & theName = "");
|
||||
@@ -150,6 +151,7 @@ public:
|
||||
|
||||
// Return data about the GPT structures....
|
||||
int GetPartRange(uint32_t* low, uint32_t* high);
|
||||
int FindFirstFreePart(void);
|
||||
uint32_t GetNumParts(void) {return mainHeader.numParts;}
|
||||
uint64_t GetMainHeaderLBA(void) {return mainHeader.currentLBA;}
|
||||
uint64_t GetSecondHeaderLBA(void) {return secondHeader.currentLBA;}
|
||||
|
||||
39
gptpart.cc
39
gptpart.cc
@@ -66,6 +66,11 @@ string GPTPart::GetDescription(void) {
|
||||
return theName;
|
||||
} // GPTPart::GetDescription()
|
||||
|
||||
// Return 1 if the partition is in use
|
||||
int GPTPart::IsUsed(void) {
|
||||
return (firstLBA != UINT64_C(0));
|
||||
} // GPTPart::IsUsed()
|
||||
|
||||
// Set the type code to the specified one. Also changes the partition
|
||||
// name *IF* the current name is the generic one for the current partition
|
||||
// type.
|
||||
@@ -139,6 +144,7 @@ void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
|
||||
|
||||
if (firstLBA != 0) {
|
||||
sizeInSI = BytesToSI(blockSize * (lastLBA - firstLBA + 1));
|
||||
cout.fill(' ');
|
||||
cout.width(4);
|
||||
cout << partNum + 1 << " ";
|
||||
cout.width(14);
|
||||
@@ -256,36 +262,3 @@ void GPTPart::ChangeType(void) {
|
||||
SetDefaultDescription();
|
||||
} // if
|
||||
} // GPTPart::ChangeType()
|
||||
|
||||
/***********************************
|
||||
* Non-class but related functions *
|
||||
***********************************/
|
||||
|
||||
// Recursive quick sort algorithm for GPT partitions. Note that if there
|
||||
// are any empties in the specified range, they'll be sorted to the
|
||||
// start, resulting in a sorted set of partitions that begins with
|
||||
// partition 2, 3, or higher.
|
||||
void QuickSortGPT(GPTPart* partitions, int start, int finish) {
|
||||
uint64_t starterValue; // starting location of median partition
|
||||
int left, right;
|
||||
GPTPart temp;
|
||||
|
||||
left = start;
|
||||
right = finish;
|
||||
starterValue = partitions[(start + finish) / 2].GetFirstLBA();
|
||||
do {
|
||||
while (partitions[left].GetFirstLBA() < starterValue)
|
||||
left++;
|
||||
while (partitions[right].GetFirstLBA() > starterValue)
|
||||
right--;
|
||||
if (left <= right) {
|
||||
temp = partitions[left];
|
||||
partitions[left] = partitions[right];
|
||||
partitions[right] = temp;
|
||||
left++;
|
||||
right--;
|
||||
} // if
|
||||
} while (left <= right);
|
||||
if (start < right) QuickSortGPT(partitions, start, right);
|
||||
if (finish > left) QuickSortGPT(partitions, left, finish);
|
||||
} // QuickSortGPT()
|
||||
|
||||
@@ -59,6 +59,7 @@ class GPTPart {
|
||||
uint64_t GetLengthLBA(void);
|
||||
uint64_t GetAttributes(void) {return attributes;}
|
||||
string GetDescription(void);
|
||||
int IsUsed(void);
|
||||
|
||||
// Simple data assignment:
|
||||
void SetType(PartType t);
|
||||
@@ -83,7 +84,4 @@ class GPTPart {
|
||||
void ChangeType(void); // Change the type code
|
||||
}; // struct GPTPart
|
||||
|
||||
// A support function that doesn't quite belong in the class....
|
||||
void QuickSortGPT(GPTPart* partitions, int start, int finish);
|
||||
|
||||
#endif
|
||||
|
||||
58
mbr.cc
58
mbr.cc
@@ -10,7 +10,7 @@
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
//#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
@@ -273,7 +273,7 @@ int MBRData::WriteMBRData(void) {
|
||||
int allOK = 1;
|
||||
|
||||
if (myDisk != NULL) {
|
||||
if (myDisk->OpenForWrite(device) != 0) {
|
||||
if (myDisk->OpenForWrite() != 0) {
|
||||
allOK = WriteMBRData(myDisk);
|
||||
} else {
|
||||
allOK = 0;
|
||||
@@ -493,10 +493,7 @@ void MBRData::EmptyMBR(int clearBootloader) {
|
||||
// 2-byte nulls area only if requested to do so. (This is the
|
||||
// default.)
|
||||
if (clearBootloader == 1) {
|
||||
for (i = 0; i < 440; i++)
|
||||
code[i] = 0;
|
||||
diskSignature = (uint32_t) rand();
|
||||
nulls = 0;
|
||||
EmptyBootloader();
|
||||
} // if
|
||||
|
||||
// Blank out the partitions
|
||||
@@ -515,6 +512,17 @@ void MBRData::EmptyMBR(int clearBootloader) {
|
||||
MBRSignature = MBR_SIGNATURE;
|
||||
} // MBRData::EmptyMBR()
|
||||
|
||||
// Blank out the boot loader area. Done with the initial MBR-to-GPT
|
||||
// conversion, since MBR boot loaders don't understand GPT, and so
|
||||
// need to be replaced....
|
||||
void MBRData::EmptyBootloader(void) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 440; i++)
|
||||
code[i] = 0;
|
||||
nulls = 0;
|
||||
} // MBRData::EmptyBootloader
|
||||
|
||||
// Create a protective MBR. Clears the boot loader area if clearBoot > 0.
|
||||
void MBRData::MakeProtectiveMBR(int clearBoot) {
|
||||
|
||||
@@ -523,6 +531,7 @@ void MBRData::MakeProtectiveMBR(int clearBoot) {
|
||||
// Initialize variables
|
||||
nulls = 0;
|
||||
MBRSignature = MBR_SIGNATURE;
|
||||
diskSignature = (uint32_t) rand();
|
||||
|
||||
partitions[0].status = UINT8_C(0); // Flag the protective part. as unbootable
|
||||
|
||||
@@ -561,7 +570,7 @@ void MBRData::MakeProtectiveMBR(int clearBoot) {
|
||||
void MBRData::MakePart(int num, uint32_t start, uint32_t length, int type,
|
||||
int bootable) {
|
||||
if ((num >= 0) && (num < MAX_MBR_PARTS)) {
|
||||
partitions[num].status = (uint8_t) bootable * (uint8_t) 0x80;
|
||||
// partitions[num].status = (uint8_t) bootable * (uint8_t) 0x80;
|
||||
partitions[num].firstSector[0] = UINT8_C(0);
|
||||
partitions[num].firstSector[1] = UINT8_C(0);
|
||||
partitions[num].firstSector[2] = UINT8_C(0);
|
||||
@@ -576,9 +585,40 @@ void MBRData::MakePart(int num, uint32_t start, uint32_t length, int type,
|
||||
LBAtoCHS((uint64_t) start, partitions[num].firstSector);
|
||||
LBAtoCHS((uint64_t) (start + length - 1), partitions[num].lastSector);
|
||||
} // if (length > 0)
|
||||
SetPartBootable(num, bootable);
|
||||
} // if valid partition number
|
||||
} // MBRData::MakePart()
|
||||
|
||||
// Set the partition's type code.
|
||||
// Returns 1 if successful, 0 if not (invalid partition number)
|
||||
int MBRData::SetPartType(int num, int type) {
|
||||
int allOK = 1;
|
||||
|
||||
if ((num >= 0) && (num < MAX_MBR_PARTS)) {
|
||||
if (partitions[num].lengthLBA != UINT32_C(0)) {
|
||||
partitions[num].partitionType = (uint8_t) type;
|
||||
} else allOK = 0;
|
||||
} else allOK = 0;
|
||||
return allOK;
|
||||
} // MBRData::SetPartType()
|
||||
|
||||
// Set (or remove) the partition's bootable flag. Setting it is the
|
||||
// default; pass 0 as bootable to remove the flag.
|
||||
// Returns 1 if successful, 0 if not (invalid partition number)
|
||||
int MBRData::SetPartBootable(int num, int bootable) {
|
||||
int allOK = 1;
|
||||
|
||||
if ((num >= 0) && (num < MAX_MBR_PARTS)) {
|
||||
if (partitions[num].lengthLBA != UINT32_C(0)) {
|
||||
if (bootable == 0)
|
||||
partitions[num].status = UINT8_C(0);
|
||||
else
|
||||
partitions[num].status = UINT8_C(0x80);
|
||||
} else allOK = 0;
|
||||
} else allOK = 0;
|
||||
return allOK;
|
||||
} // MBRData::SetPartBootable()
|
||||
|
||||
// Create a partition that fills the most available space. Returns
|
||||
// 1 if partition was created, 0 otherwise. Intended for use in
|
||||
// creating hybrid MBRs.
|
||||
@@ -637,7 +677,7 @@ int MBRData::DeleteByLocation(uint64_t start64, uint64_t length64) {
|
||||
start32 = (uint32_t) start64;
|
||||
length32 = (uint32_t) length64;
|
||||
for (i = 0; i < MAX_MBR_PARTS; i++) {
|
||||
if ((partitions[i].firstLBA == start32) && (partitions[i].lengthLBA = length32) &&
|
||||
if ((partitions[i].firstLBA == start32) && (partitions[i].lengthLBA == length32) &&
|
||||
(partitions[i].partitionType != 0xEE)) {
|
||||
DeletePartition(i);
|
||||
if (state == hybrid)
|
||||
@@ -717,7 +757,7 @@ uint32_t MBRData::FindLastInFree(uint32_t start) {
|
||||
uint32_t i;
|
||||
|
||||
if ((diskSize <= UINT32_MAX) && (diskSize > 0))
|
||||
nearestStart = diskSize - 1;
|
||||
nearestStart = (uint32_t) diskSize - 1;
|
||||
else
|
||||
nearestStart = UINT32_MAX - 1;
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
||||
3
mbr.h
3
mbr.h
@@ -105,9 +105,12 @@ public:
|
||||
// Functions to create, delete, or change partitions
|
||||
// Pass EmptyMBR 1 to clear the boot loader code, 0 to leave it intact
|
||||
void EmptyMBR(int clearBootloader = 1);
|
||||
void EmptyBootloader(void);
|
||||
void MakeProtectiveMBR(int clearBoot = 0);
|
||||
void MakePart(int num, uint32_t startLBA, uint32_t lengthLBA, int type = 0x07,
|
||||
int bootable = 0);
|
||||
int SetPartType(int num, int type);
|
||||
int SetPartBootable(int num, int bootable = 1);
|
||||
int MakeBiggestPart(int i, int type); // Make partition filling most space
|
||||
void DeletePartition(int i);
|
||||
int DeleteByLocation(uint64_t start64, uint64_t length64);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
//#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include "support.h"
|
||||
|
||||
76
sgdisk.8
76
sgdisk.8
@@ -1,6 +1,6 @@
|
||||
.\" Copyright 2009 Roderick W. Smith (rodsmith@rodsbooks.com)
|
||||
.\" May be distributed under the GNU General Public License
|
||||
.TH "SGDISK" "8" "0.6.3" "Roderick W. Smith" "GPT fdisk Manual"
|
||||
.TH "SGDISK" "8" "0.6.4" "Roderick W. Smith" "GPT fdisk Manual"
|
||||
.SH "NAME"
|
||||
sgdisk \- Command\-line GUID partition table (GPT) manipulator for Linux and Unix
|
||||
.SH "SYNOPSIS"
|
||||
@@ -60,14 +60,15 @@ attempt to convert the MBR or disklabel into GPT form. (BSD disklabels are
|
||||
likely to have unusable first and/or final partitions because they overlap
|
||||
with the GPT data structures, though.) GPT fdisk can identify, but not use
|
||||
data in, Apple Partition Map (APM) disks, which are used on 680x0\- and
|
||||
PowerPC\-based Macintoshes. If you specify any option that results in changes
|
||||
to an MBR or BSD disklabel, \fBsgdisk\fR ignores those changes unless the
|
||||
\fI\-g\fR (\fI\-\-mbrtogpt\fR) or \fI\-z\fR (\fI\-\-zap\fR) option is used.
|
||||
If you use the \fI\-g\fR option, \fBsgdisk\fR replaces the MBR or disklabel
|
||||
with a GPT. \fIThis action is potentially dangerous!\fR Your system may become
|
||||
unbootable, and partition type codes may become corrupted if the disk uses
|
||||
unrecognized type codes. Boot problems are particularly likely if you're
|
||||
multi\-booting with any GPT\-unaware OS.
|
||||
PowerPC\-based Macintoshes. If you specify any option that results in
|
||||
changes to an MBR or BSD disklabel, \fBsgdisk\fR ignores those changes
|
||||
unless the \fI\-g\fR (\fI\-\-mbrtogpt\fR), \fI\-z\fR (\fI\-\-zap\fR), or
|
||||
\fI\-Z\fR (\fI\-\-zap\-all\fR) option is used. If you use the \fI\-g\fR
|
||||
option, \fBsgdisk\fR replaces the MBR or disklabel with a GPT. \fIThis
|
||||
action is potentially dangerous!\fR Your system may become unbootable, and
|
||||
partition type codes may become corrupted if the disk uses unrecognized
|
||||
type codes. Boot problems are particularly likely if you're multi\-booting
|
||||
with any GPT\-unaware OS.
|
||||
|
||||
The MBR\-to\-GPT conversion will leave at least one gap in the partition
|
||||
numbering if the original MBR used logical partitions. These gaps are
|
||||
@@ -210,6 +211,17 @@ Convert an MBR or BSD disklabel disk to a GPT disk. As a safety measure, use of
|
||||
this option is required on MBR or BSD disklabel disks if you intend to save your
|
||||
changes, in order to prevent accidentally damaging such disks.
|
||||
|
||||
.TP
|
||||
.B \-h, \-\-hybrid
|
||||
Create a hybrid MBR. This option takes from one to three partition numbers,
|
||||
separated by colons, as arguments. The created hybrid MBR places an EFI GPT
|
||||
(type 0xEE) partition first in the table, followed by the partition(s) you
|
||||
specify. Their type codes are based on the GPT fdisk type codes divided by
|
||||
0x0100, which is usually correct for Windows partitions. If the
|
||||
active/bootable flag should be set, you must do so in another program, such
|
||||
as \fBfdisk\fR. The \fBgdisk\fR program offers additional hybrid MBR
|
||||
creation options.
|
||||
|
||||
.TP
|
||||
.B \-i, \-\-info=partnum
|
||||
Show detailed partition information. The summary information produced by
|
||||
@@ -241,6 +253,17 @@ adds code numbers sequentially, such as 0xa500 for a FreeBSD disklabel,
|
||||
these two\-byte codes are unique to \fBgdisk\fR and \fBsgdisk\fR. This
|
||||
option does not require you to specify a valid disk device filename.
|
||||
|
||||
.TP
|
||||
.B \-m, \-\-gpttombr
|
||||
Convert disk from GPT to MBR form. This option takes from one to four
|
||||
partition numbers, separated by colons, as arguments. Their type codes are
|
||||
based on the GPT fdisk type codes divided by 0x0100. If the active/bootable
|
||||
flag should be set, you must do so in another program, such as \fBfdisk\fR.
|
||||
The \fBgdisk\fR program offers additional MBR conversion options. It is not
|
||||
possible to convert more than four partitions from GPT to MBR form or to
|
||||
convert partitions that start above the 2TiB mark or that are larger than
|
||||
2TiB.
|
||||
|
||||
.TP
|
||||
.B \-n, \-\-new=partnum:start:end
|
||||
Create a new partition. You enter a partition
|
||||
@@ -274,6 +297,15 @@ Pretend to make specified changes. In\-memory GPT data structures are
|
||||
altered according to other parameters, but changes are not written
|
||||
to disk.
|
||||
|
||||
.TP
|
||||
.B \-r, \-\-transpose
|
||||
Swap two partitions' entries in the partition table. One or both partitions
|
||||
may be empty, although swapping two empty partitions is pointless. For
|
||||
instance, if partitions 1\-4 are defined, transposing 1 and 5 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 \-s, \-\-sort
|
||||
Sort partition entries. GPT partition numbers need not match the order of
|
||||
@@ -317,14 +349,22 @@ specifying a device filename.
|
||||
|
||||
.TP
|
||||
.B \-z, \-\-zap
|
||||
Zap (destroy) the GPT data structures and exit. Use this option if you want to
|
||||
repartition a GPT disk using \fBfdisk\fR or some other GPT\-unaware program.
|
||||
You'll be given the choice of preserving the existing MBR, in case it's a
|
||||
hybrid MBR with salvageable partitions or if you've already created new MBR
|
||||
partitions and want to erase the remnants of your GPT partitions. \fIIf you've
|
||||
already created new MBR partitions, it's conceivable that this option will
|
||||
damage the first and/or last MBR partitions!\fR Such an event is unlikely, but
|
||||
could occur if your new MBR partitions overlap the old GPT data structures.
|
||||
Zap (destroy) the GPT data structures and then exit. Use this option if you
|
||||
want to repartition a GPT disk using \fBfdisk\fR or some other GPT\-unaware
|
||||
program. This option destroys only the GPT data structures; it leaves the
|
||||
MBR intact. This makes it useful for wiping out GPT data structures after a
|
||||
disk has been repartitioned for MBR using a GPT-unaware utility; however,
|
||||
there's a risk that it will damage boot loaders or even the start of the
|
||||
first or end of the last MBR partition. If you use it on a valid GPT disk,
|
||||
the MBR will be left with an inappropriate EFI GPT (0xEE) partition
|
||||
definition, which you can delete using another utility.
|
||||
|
||||
.TP
|
||||
.B \-Z, \-\-zap\-all
|
||||
Zap (destroy) the GPT and MBR data structures and then exit. This option
|
||||
works much like \fI\-z\fR, but as it wipes the MBR as well as the GPT, it's
|
||||
more suitable if you want to repartition a disk after using this option,
|
||||
and completely unsuitable if you've already repartitioned the disk.
|
||||
|
||||
.TP
|
||||
.B \-?, \-\-help
|
||||
@@ -353,7 +393,7 @@ Non\-GPT disk detected and no \fI\-g\fR option
|
||||
.B 4
|
||||
An error prevented saving changes
|
||||
.SH "BUGS"
|
||||
As of January 2010 (version 0.6.0), \fBsgdisk\fR
|
||||
As of February 2010 (version 0.6.4), \fBsgdisk\fR
|
||||
should be considered beta software. Known bugs and limitations include:
|
||||
|
||||
.TP
|
||||
|
||||
97
sgdisk.cc
97
sgdisk.cc
@@ -25,6 +25,8 @@ using namespace std;
|
||||
|
||||
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);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
GPTData theGPT;
|
||||
@@ -35,8 +37,8 @@ int main(int argc, char *argv[]) {
|
||||
uint32_t tableSize = 128;
|
||||
uint64_t startSector, endSector;
|
||||
char *device = NULL;
|
||||
char *newPartInfo = NULL, *typeCode = NULL, *partName;
|
||||
char *backupFile = NULL;
|
||||
char *newPartInfo = NULL, *typeCode = NULL, *partName = NULL;
|
||||
char *backupFile = NULL, *twoParts = NULL, *hybrids = NULL, *mbrParts;
|
||||
PartType typeHelper;
|
||||
|
||||
poptContext poptCon;
|
||||
@@ -50,20 +52,24 @@ int main(int argc, char *argv[]) {
|
||||
{"end-of-largest", 'E', POPT_ARG_NONE, NULL, 'E', "show end of largest free block", ""},
|
||||
{"first-in-largest", 'f', POPT_ARG_NONE, NULL, 'f', "show start of the largest free block", ""},
|
||||
{"mbrtogpt", 'g', POPT_ARG_NONE, NULL, 'g', "convert MBR to GPT", ""},
|
||||
{"hybrid", 'h', POPT_ARG_STRING, &hybrids, 'h', "create hybrid MBR", "partnum[:partnum...]"},
|
||||
{"info", 'i', POPT_ARG_INT, &infoPartNum, 'i', "show detailed information on partition", "partnum"},
|
||||
{"load-backup", 'l', POPT_ARG_STRING, &backupFile, 'l', "load GPT backup from file", "file"},
|
||||
{"list-types", 'L', POPT_ARG_NONE, NULL, 'L', "list known partition types", ""},
|
||||
{"gpttombr", 'm', POPT_ARG_STRING, &mbrParts, 'm', "convert GPT to MBR", "partnum[:partnum...]"},
|
||||
{"new", 'n', POPT_ARG_STRING, &newPartInfo, 'n', "create new partition", "partnum:start:end"},
|
||||
{"clear", 'o', POPT_ARG_NONE, NULL, 'o', "clear partition table", ""},
|
||||
{"print", 'p', POPT_ARG_NONE, NULL, 'p', "print partition table", ""},
|
||||
{"pretend", 'P', POPT_ARG_NONE, NULL, 'P', "make changes in memory, but don't write them", ""},
|
||||
{"transpose", 'r', POPT_ARG_STRING, &twoParts, 'r', "transpose two partitions", "partnum:partnum"},
|
||||
{"sort", 's', POPT_ARG_NONE, NULL, 's', "sort partition table entries", ""},
|
||||
{"resize-table", 'S', POPT_ARG_INT, &tableSize, 'S', "resize partition table", "numparts"},
|
||||
{"typecode", 't', POPT_ARG_STRING, &typeCode, 't', "change partition type code", "partnum:hexcode"},
|
||||
{"transform-bsd", 'T', POPT_ARG_INT, &bsdPartNum, 'T', "transform BSD disklabel partition to GPT", "partnum"},
|
||||
{"verify", 'v', POPT_ARG_NONE, NULL, 'v', "check partition table integrity", ""},
|
||||
{"version", 'V', POPT_ARG_NONE, NULL, 'V', "display version information", ""},
|
||||
{"zap", 'z', POPT_ARG_NONE, NULL, 'z', "zap (destroy) GPT data structures", ""},
|
||||
{"zap", 'z', POPT_ARG_NONE, NULL, 'z', "zap (destroy) GPT (but not MBR) data structures", ""},
|
||||
{"zap-all", 'Z', POPT_ARG_NONE, NULL, 'Z', "zap (destroy) GPT and MBR data structures", ""},
|
||||
POPT_AUTOHELP { NULL, 0, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
@@ -150,6 +156,11 @@ int main(int argc, char *argv[]) {
|
||||
saveData = 1;
|
||||
saveNonGPT = 1;
|
||||
break;
|
||||
case 'h':
|
||||
theGPT.JustLooking(0);
|
||||
if (BuildMBR(&theGPT, hybrids, 1) == 1)
|
||||
saveData = 1;
|
||||
break;
|
||||
case 'i':
|
||||
theGPT.ShowPartDetails(infoPartNum - 1);
|
||||
break;
|
||||
@@ -165,6 +176,19 @@ int main(int argc, char *argv[]) {
|
||||
break;
|
||||
case 'L':
|
||||
break;
|
||||
case 'm':
|
||||
theGPT.JustLooking(0);
|
||||
if (BuildMBR(&theGPT, mbrParts, 0) == 1) {
|
||||
if (!pretend) {
|
||||
if (theGPT.SaveMBR())
|
||||
theGPT.DestroyGPT();
|
||||
else
|
||||
cerr << "Problem saving MBR!\n";
|
||||
} // if
|
||||
saveNonGPT = 0;
|
||||
saveData = 0;
|
||||
} // if
|
||||
break;
|
||||
case 'n':
|
||||
theGPT.JustLooking(0);
|
||||
partNum = (int) GetInt(newPartInfo, 1) - 1;
|
||||
@@ -190,6 +214,16 @@ int main(int argc, char *argv[]) {
|
||||
case 'P':
|
||||
pretend = 1;
|
||||
break;
|
||||
case 'r':
|
||||
theGPT.JustLooking(0);
|
||||
uint64_t p1, p2;
|
||||
p1 = GetInt(twoParts, 1) - 1;
|
||||
p2 = GetInt(twoParts, 2) - 1;
|
||||
if (theGPT.SwapPartitions((uint32_t) p1, (uint32_t) p2) == 0) {
|
||||
neverSaveData = 1;
|
||||
cerr << "Cannot swap partitions " << p1 + 1 << " and " << p2 + 1 << "\n";
|
||||
} else saveData = 1;
|
||||
break;
|
||||
case 's':
|
||||
theGPT.JustLooking(0);
|
||||
theGPT.SortGPT();
|
||||
@@ -217,16 +251,26 @@ int main(int argc, char *argv[]) {
|
||||
break;
|
||||
case 'T':
|
||||
theGPT.JustLooking(0);
|
||||
theGPT.XFormDisklabel(bsdPartNum);
|
||||
theGPT.XFormDisklabel(bsdPartNum - 1);
|
||||
saveData = 1;
|
||||
break;
|
||||
case 'v':
|
||||
theGPT.Verify();
|
||||
break;
|
||||
case 'z':
|
||||
if (!pretend)
|
||||
theGPT.DestroyGPT(-1);
|
||||
if (!pretend) {
|
||||
theGPT.DestroyGPT();
|
||||
} // if
|
||||
saveNonGPT = 0;
|
||||
saveData = 0;
|
||||
break;
|
||||
case 'Z':
|
||||
if (!pretend) {
|
||||
theGPT.DestroyGPT();
|
||||
theGPT.DestroyMBR();
|
||||
} // if
|
||||
saveNonGPT = 0;
|
||||
saveData = 0;
|
||||
break;
|
||||
default:
|
||||
cerr << "Unknown option (-" << opt << ")!\n";
|
||||
@@ -287,3 +331,44 @@ string GetString(char* argument, int itemNum) {
|
||||
|
||||
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;
|
||||
int gptParts[4], mbrTypes[4];
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
gptParts[i] = MBR_EMPTY;
|
||||
mbrTypes[i] = 0; // All 0s flags to use default type
|
||||
} // for
|
||||
if ((theGPT != NULL) && (argument != NULL) && ((isHybrid == 0) || (isHybrid == 1))) {
|
||||
numParts = CountColons(argument) + 1;
|
||||
if (numParts <= (4 - isHybrid)) {
|
||||
if (isHybrid) {
|
||||
gptParts[0] = MBR_EFI_GPT;
|
||||
mbrTypes[0] = 0xEE;
|
||||
} // if
|
||||
for (i = 0; i < numParts; i++) {
|
||||
gptParts[i + isHybrid] = GetInt(argument, i + 1) - 1;
|
||||
} // for
|
||||
if (theGPT->PartsToMBR(gptParts, mbrTypes) != numParts)
|
||||
allOK = 0;
|
||||
} else allOK = 0;
|
||||
} else allOK = 0;
|
||||
if (!allOK)
|
||||
cerr << "Problem creating MBR!\n";
|
||||
return allOK;
|
||||
} // BuildMBR()
|
||||
|
||||
// Returns the number of colons in argument string
|
||||
int CountColons(char* argument) {
|
||||
int num = 0, i = 0;
|
||||
|
||||
if (argument != NULL) {
|
||||
while (argument[i] != '\0') {
|
||||
if (argument[i++] == ':')
|
||||
num++;
|
||||
} // while
|
||||
} // if
|
||||
return num;
|
||||
} // CountColons()
|
||||
|
||||
12
support.cc
12
support.cc
@@ -17,6 +17,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "support.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -166,10 +167,9 @@ uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const string &
|
||||
// form
|
||||
string BytesToSI(uint64_t size) {
|
||||
string units;
|
||||
char theValue[99];
|
||||
ostringstream theValue;
|
||||
float sizeInSI;
|
||||
|
||||
theValue[0] = '\0';
|
||||
sizeInSI = (float) size;
|
||||
units = " bytes";
|
||||
if (sizeInSI > 1024.0) {
|
||||
@@ -192,12 +192,14 @@ string BytesToSI(uint64_t size) {
|
||||
sizeInSI /= 1024.0;
|
||||
units = " PiB";
|
||||
} // if
|
||||
theValue.setf(ios::fixed);
|
||||
if (units == " bytes") { // in bytes, so no decimal point
|
||||
sprintf(theValue, "%1.0f%s", sizeInSI, units.c_str());
|
||||
theValue.precision(0);
|
||||
} else {
|
||||
sprintf(theValue, "%1.1f%s", sizeInSI, units.c_str());
|
||||
theValue.precision(1);
|
||||
} // if/else
|
||||
return theValue;
|
||||
theValue << sizeInSI << units;
|
||||
return theValue.str();
|
||||
} // BlocksToSI()
|
||||
|
||||
// Converts two consecutive characters in the input string into a
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
//#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
|
||||
#ifndef __GPTSUPPORT
|
||||
#define __GPTSUPPORT
|
||||
|
||||
#if defined (__FreeBSD__) || defined (__APPLE__)
|
||||
#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__)
|
||||
// Darwin (Mac OS) only: disk IOCTLs are different, and there is no lseek64
|
||||
// This used to use __DARWIN_UNIX03 rather than __APPLE__, but __APPLE__
|
||||
// is more general. If the code fails to work on older versions of OS X/
|
||||
|
||||
Reference in New Issue
Block a user