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
|
- 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.
|
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
|
all: gdisk sgdisk
|
||||||
|
|
||||||
gdisk: $(LIB_OBJS) gdisk.o
|
gdisk: $(LIB_OBJS) gdisk.o gpttext.o
|
||||||
$(CXX) $(LIB_OBJS) gdisk.o -L/opt/local/lib -L/usr/local/lib -luuid -o gdisk
|
$(CXX) $(LIB_OBJS) gdisk.o gpttext.o -L/opt/local/lib -L/usr/local/lib -luuid -o gdisk
|
||||||
|
|
||||||
sgdisk: $(LIB_OBJS) sgdisk.o
|
sgdisk: $(LIB_OBJS) sgdisk.o
|
||||||
$(CXX) $(LIB_OBJS) sgdisk.o -L/opt/local/lib -L/usr/local/lib -luuid -lpopt -o sgdisk
|
$(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
|
CC=/usr/bin/i686-pc-mingw32-gcc
|
||||||
CXX=/usr/bin/i586-mingw32msvc-g++
|
CXX=/usr/bin/i686-pc-mingw32-g++
|
||||||
STRIP=/usr/bin/i586-mingw32msvc-strip
|
STRIP=/usr/bin/i686-pc-mingw32-strip
|
||||||
CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g
|
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 -g
|
||||||
#CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -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.
|
altogether.
|
||||||
|
|
||||||
I compiled gdisk.exe using MinGW (http://www.mingw.org), and in particular
|
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
|
its Linux-hosted cross-compiler. Under Ubuntu Linux, the Makefile.mingw
|
||||||
source code under more mainstream Windows compilers, or even on the
|
file enables compilation of the software via MinGW. (Type "make -f
|
||||||
Windows-hosted MinGW variant. MinGW was designed for porting Unix
|
Makefile.mingw" to compile the software.) If you try to compile using
|
||||||
applications to Windows, so it's entirely possible that it will work where
|
another compiler or even using MinGW under Windows or another Linux
|
||||||
other compilers won't.
|
variety, you may need to adjust the Makefile.mingw options.
|
||||||
|
|
||||||
Under Ubuntu Linux, the Makefile.mingw file enables compilation of the
|
I've also attempted to compile the code with OpenWatcom 1.8 and Microsoft
|
||||||
software. (Type "make -f Makefile.mingw" to compile the software.) If you
|
Visual C++ 2008 Express. My OpenWatcom attempts failed, mostly because the
|
||||||
try to compile using another compiler or even using MinGW under Windows or
|
compiler can't yet handle iostream output on standard C++ strings.
|
||||||
another Linux variety, you may need to adjust the Makefile.mingw options.
|
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
|
If you modify GPT fdisk to get it to compile under another compiler, I
|
||||||
welcome submission of patches.
|
welcome submission of patches.
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
#include "attributes.h"
|
#include "attributes.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -20,13 +21,13 @@ using namespace std;
|
|||||||
// data.
|
// data.
|
||||||
Attributes::Attributes(void) {
|
Attributes::Attributes(void) {
|
||||||
int i;
|
int i;
|
||||||
char temp[ATR_NAME_SIZE];
|
ostringstream temp;
|
||||||
|
|
||||||
// Most bits are undefined, so start by giving them an
|
// Most bits are undefined, so start by giving them an
|
||||||
// appropriate name
|
// appropriate name
|
||||||
for (i = 1; i < NUM_ATR; i++) {
|
for (i = 1; i < NUM_ATR; i++) {
|
||||||
sprintf(temp, "Undefined bit #%d", i);
|
temp << "Undefined bit #" << i;
|
||||||
atNames[i] = temp;
|
atNames[i] = temp.str();
|
||||||
} // for
|
} // for
|
||||||
|
|
||||||
// Now reset those names that are defined....
|
// 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. */
|
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
//#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
|
|||||||
12
bsd.cc
12
bsd.cc
@@ -10,7 +10,7 @@
|
|||||||
#define __STDC_CONSTANT_MACROS
|
#define __STDC_CONSTANT_MACROS
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
//#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -37,7 +37,8 @@ BSDData::BSDData(void) {
|
|||||||
} // default constructor
|
} // default constructor
|
||||||
|
|
||||||
BSDData::~BSDData(void) {
|
BSDData::~BSDData(void) {
|
||||||
delete[] partitions;
|
if (partitions != NULL)
|
||||||
|
delete[] partitions;
|
||||||
} // destructor
|
} // destructor
|
||||||
|
|
||||||
// Read BSD disklabel data from the specified device filename. This function
|
// 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
|
// Load the BSD disklabel data from an already-opened disk
|
||||||
// file, starting with the specified sector number.
|
// file, starting with the specified sector number.
|
||||||
int BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSector) {
|
int BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSector) {
|
||||||
uint8_t buffer[4096]; // I/O buffer
|
int allOK = 1;
|
||||||
int i, foundSig = 0, bigEnd = 0, allOK = 1;
|
int i, foundSig = 0, bigEnd = 0;
|
||||||
int relative = 0; // assume absolute partition sector numbering
|
int relative = 0; // assume absolute partition sector numbering
|
||||||
|
uint8_t buffer[4096]; // I/O buffer
|
||||||
uint32_t realSig;
|
uint32_t realSig;
|
||||||
uint32_t* temp32;
|
uint32_t* temp32;
|
||||||
uint16_t* temp16;
|
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....
|
// detected above, apply a correction to all partition start sectors....
|
||||||
if (relative) {
|
if (relative) {
|
||||||
for (i = 0; i < numParts; i++) {
|
for (i = 0; i < numParts; i++) {
|
||||||
partitions[i].firstLBA += startSector;
|
partitions[i].firstLBA += (uint32_t) startSector;
|
||||||
} // for
|
} // for
|
||||||
} // if
|
} // if
|
||||||
} // if signatures OK
|
} // if signatures OK
|
||||||
|
|||||||
5
bsd.h
5
bsd.h
@@ -55,6 +55,9 @@ struct BSDRecord { // the partition table
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Full data in tweaked BSD format
|
// 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 {
|
class BSDData {
|
||||||
protected:
|
protected:
|
||||||
// We only need a few items from the main BSD disklabel data structure....
|
// 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 sectorSize; // # of bytes per sector
|
||||||
uint32_t signature2; // the magic number (again)
|
uint32_t signature2; // the magic number (again)
|
||||||
uint16_t numParts; // number of partitions in table
|
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....
|
// Above are basic BSD disklabel data; now add more stuff....
|
||||||
uint64_t labelFirstLBA; // first sector of BSD disklabel (partition or disk)
|
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.
|
// so the file can be re-opened without specifying the filename.
|
||||||
void DiskIO::Close(void) {
|
void DiskIO::Close(void) {
|
||||||
if (isOpen)
|
if (isOpen)
|
||||||
close(fd);
|
if (close(fd) < 0)
|
||||||
|
cerr << "Warning! Problem closing file!\n";
|
||||||
isOpen = 0;
|
isOpen = 0;
|
||||||
openForWrite = 0;
|
openForWrite = 0;
|
||||||
} // DiskIO::Close()
|
} // DiskIO::Close()
|
||||||
@@ -117,7 +118,7 @@ int DiskIO::GetBlockSize(void) {
|
|||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
err = ioctl(fd, DKIOCGETBLOCKSIZE, &blockSize);
|
err = ioctl(fd, DKIOCGETBLOCKSIZE, &blockSize);
|
||||||
#endif
|
#endif
|
||||||
#ifdef __FreeBSD__
|
#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
||||||
err = ioctl(fd, DIOCGSECTORSIZE, &blockSize);
|
err = ioctl(fd, DIOCGSECTORSIZE, &blockSize);
|
||||||
#endif
|
#endif
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
@@ -161,7 +162,7 @@ void DiskIO::DiskSync(void) {
|
|||||||
i = ioctl(fd, DKIOCSYNCHRONIZECACHE);
|
i = ioctl(fd, DKIOCSYNCHRONIZECACHE);
|
||||||
platformFound++;
|
platformFound++;
|
||||||
#endif
|
#endif
|
||||||
#ifdef __FreeBSD__
|
#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
||||||
sleep(2);
|
sleep(2);
|
||||||
i = ioctl(fd, DIOCGFLUSH);
|
i = ioctl(fd, DIOCGFLUSH);
|
||||||
cout << "Warning: The kernel may continue to use old or deleted partitions.\n"
|
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
|
// greatly since then to enable FreeBSD and MacOS support, as well as to
|
||||||
// return correct values for disk image files.
|
// return correct values for disk image files.
|
||||||
uint64_t DiskIO::DiskSize(int *err) {
|
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
|
uint64_t sectors = 0; // size in sectors
|
||||||
off_t bytes = 0; // size in bytes
|
off_t bytes = 0; // size in bytes
|
||||||
struct stat64 st;
|
struct stat64 st;
|
||||||
@@ -317,13 +316,15 @@ uint64_t DiskIO::DiskSize(int *err) {
|
|||||||
*err = ioctl(fd, DKIOCGETBLOCKCOUNT, §ors);
|
*err = ioctl(fd, DKIOCGETBLOCKCOUNT, §ors);
|
||||||
platformFound++;
|
platformFound++;
|
||||||
#endif
|
#endif
|
||||||
#ifdef __FreeBSD__
|
#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
||||||
*err = ioctl(fd, DIOCGMEDIASIZE, &bytes);
|
*err = ioctl(fd, DIOCGMEDIASIZE, &bytes);
|
||||||
b = GetBlockSize();
|
long long b = GetBlockSize();
|
||||||
sectors = bytes / b;
|
sectors = bytes / b;
|
||||||
platformFound++;
|
platformFound++;
|
||||||
#endif
|
#endif
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
long sz;
|
||||||
|
long long b;
|
||||||
*err = ioctl(fd, BLKGETSIZE, &sz);
|
*err = ioctl(fd, BLKGETSIZE, &sz);
|
||||||
if (*err) {
|
if (*err) {
|
||||||
sectors = sz = 0;
|
sectors = sz = 0;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
#include <winioctl.h>
|
#include <winioctl.h>
|
||||||
#define fstat64 fstat
|
#define fstat64 fstat
|
||||||
#define stat64 stat
|
#define stat64 stat
|
||||||
//#define S_IRGRP 0
|
#define S_IRGRP 0
|
||||||
#define S_IROTH 0
|
#define S_IROTH 0
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -93,6 +93,14 @@ int DiskIO::OpenForWrite(void) {
|
|||||||
fd = CreateFile(realFilename.c_str(), GENERIC_READ | GENERIC_WRITE,
|
fd = CreateFile(realFilename.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
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) {
|
if (fd == INVALID_HANDLE_VALUE) {
|
||||||
CloseHandle(fd);
|
CloseHandle(fd);
|
||||||
isOpen = 0;
|
isOpen = 0;
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
#else
|
#else
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#endif
|
#endif
|
||||||
#include <stdio.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|||||||
2
diskio.h
2
diskio.h
@@ -25,7 +25,7 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (__FreeBSD__) || defined (__APPLE__)
|
#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__)
|
||||||
#define fstat64 fstat
|
#define fstat64 fstat
|
||||||
#define stat64 stat
|
#define stat64 stat
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
10
gdisk.8
10
gdisk.8
@@ -1,6 +1,6 @@
|
|||||||
.\" Copyright 2009 Roderick W. Smith (rodsmith@rodsbooks.com)
|
.\" Copyright 2009 Roderick W. Smith (rodsmith@rodsbooks.com)
|
||||||
.\" May be distributed under the GNU General Public License
|
.\" May be distributed under the GNU General Public License
|
||||||
.TH "GDISK" "8" "0.6.3" "Roderick W. Smith" "GPT fdisk Manual"
|
.TH "GDISK" "8" "0.6.4" "Roderick W. Smith" "GPT fdisk Manual"
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
gdisk \- Interactive GUID partition table (GPT) manipulator
|
gdisk \- Interactive GUID partition table (GPT) manipulator
|
||||||
.SH "SYNOPSIS"
|
.SH "SYNOPSIS"
|
||||||
@@ -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
|
sizes also work fine. OSes may impose their own limits on the number of
|
||||||
partitions, though.
|
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
|
.TP
|
||||||
.B v
|
.B v
|
||||||
Verify disk. This option is identical to the 'v' option in the main menu.
|
Verify disk. This option is identical to the 'v' option in the main menu.
|
||||||
|
|||||||
36
gdisk.cc
36
gdisk.cc
@@ -9,24 +9,24 @@
|
|||||||
|
|
||||||
//#include <iostream>
|
//#include <iostream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <getopt.h>
|
//#include <getopt.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "mbr.h"
|
#include "mbr.h"
|
||||||
#include "gpt.h"
|
#include "gpttext.h"
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
|
|
||||||
// Function prototypes....
|
// Function prototypes....
|
||||||
void MainMenu(string filename, struct GPTData* theGPT);
|
void MainMenu(string filename, GPTDataTextUI* theGPT);
|
||||||
void ShowCommands(void);
|
void ShowCommands(void);
|
||||||
void ExpertsMenu(string filename, struct GPTData* theGPT);
|
void ExpertsMenu(string filename, GPTDataTextUI* theGPT);
|
||||||
void ShowExpertCommands(void);
|
void ShowExpertCommands(void);
|
||||||
void RecoveryMenu(string filename, struct GPTData* theGPT);
|
void RecoveryMenu(string filename, GPTDataTextUI* theGPT);
|
||||||
void ShowRecoveryCommands(void);
|
void ShowRecoveryCommands(void);
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
GPTData theGPT;
|
GPTDataTextUI theGPT;
|
||||||
int doMore = 1;
|
int doMore = 1;
|
||||||
char* device = NULL;
|
char* device = NULL;
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
// Accept a command and execute it. Returns only when the user
|
// Accept a command and execute it. Returns only when the user
|
||||||
// wants to exit (such as after a 'w' or 'q' command).
|
// 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 command, line[255], buFile[255];
|
||||||
char* junk;
|
char* junk;
|
||||||
int goOn = 1;
|
int goOn = 1;
|
||||||
@@ -174,7 +174,7 @@ void ShowCommands(void) {
|
|||||||
|
|
||||||
// Accept a recovery & transformation menu command. Returns only when the user
|
// Accept a recovery & transformation menu command. Returns only when the user
|
||||||
// issues an exit command, such as 'w' or 'q'.
|
// 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 command, line[255], buFile[255];
|
||||||
char* junk;
|
char* junk;
|
||||||
uint32_t temp1;
|
uint32_t temp1;
|
||||||
@@ -221,10 +221,11 @@ void RecoveryMenu(string filename, struct GPTData* theGPT) {
|
|||||||
if (temp1 > 0) {
|
if (temp1 > 0) {
|
||||||
cout << "Converted " << temp1 << " partitions. Finalize and exit? ";
|
cout << "Converted " << temp1 << " partitions. Finalize and exit? ";
|
||||||
if (GetYN() == 'Y') {
|
if (GetYN() == 'Y') {
|
||||||
if (theGPT->DestroyGPT(0) > 0)
|
if (theGPT->DestroyGPT() > 0)
|
||||||
goOn = 0;
|
goOn = 0;
|
||||||
} else {
|
} else {
|
||||||
theGPT->MakeProtectiveMBR();
|
theGPT->MakeProtectiveMBR();
|
||||||
|
theGPT->WriteProtectiveMBR();
|
||||||
cout << "Note: New protective MBR created.\n";
|
cout << "Note: New protective MBR created.\n";
|
||||||
} // if/else
|
} // if/else
|
||||||
} // if
|
} // if
|
||||||
@@ -299,11 +300,10 @@ void ShowRecoveryCommands(void) {
|
|||||||
|
|
||||||
// Accept an experts' menu command. Returns only after the user
|
// Accept an experts' menu command. Returns only after the user
|
||||||
// selects an exit command, such as 'w' or 'q'.
|
// 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 command, line[255];
|
||||||
char* junk;
|
char* junk;
|
||||||
uint32_t pn;
|
uint32_t pn, temp1, temp2;
|
||||||
uint32_t temp1, temp2;
|
|
||||||
int goOn = 1;
|
int goOn = 1;
|
||||||
GUIDData aGUID;
|
GUIDData aGUID;
|
||||||
|
|
||||||
@@ -359,10 +359,10 @@ void ExpertsMenu(string filename, struct GPTData* theGPT) {
|
|||||||
break;
|
break;
|
||||||
case 'p': case 'P':
|
case 'p': case 'P':
|
||||||
theGPT->DisplayGPTData();
|
theGPT->DisplayGPTData();
|
||||||
break;
|
break;
|
||||||
case 'q': case 'Q':
|
case 'q': case 'Q':
|
||||||
goOn = 0;
|
goOn = 0;
|
||||||
break;
|
break;
|
||||||
case 'r': case 'R':
|
case 'r': case 'R':
|
||||||
RecoveryMenu(filename, theGPT);
|
RecoveryMenu(filename, theGPT);
|
||||||
goOn = 0;
|
goOn = 0;
|
||||||
@@ -370,6 +370,9 @@ void ExpertsMenu(string filename, struct GPTData* theGPT) {
|
|||||||
case 's': case 'S':
|
case 's': case 'S':
|
||||||
theGPT->ResizePartitionTable();
|
theGPT->ResizePartitionTable();
|
||||||
break;
|
break;
|
||||||
|
case 't': case 'T':
|
||||||
|
theGPT->SwapPartitions();
|
||||||
|
break;
|
||||||
case 'v': case 'V':
|
case 'v': case 'V':
|
||||||
theGPT->Verify();
|
theGPT->Verify();
|
||||||
break;
|
break;
|
||||||
@@ -379,7 +382,7 @@ void ExpertsMenu(string filename, struct GPTData* theGPT) {
|
|||||||
} // if
|
} // if
|
||||||
break;
|
break;
|
||||||
case 'z': case 'Z':
|
case 'z': case 'Z':
|
||||||
if (theGPT->DestroyGPT() == 1) {
|
if (theGPT->DestroyGPTwPrompt() == 1) {
|
||||||
goOn = 0;
|
goOn = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -405,6 +408,7 @@ void ShowExpertCommands(void) {
|
|||||||
cout << "q\tquit without saving changes\n";
|
cout << "q\tquit without saving changes\n";
|
||||||
cout << "r\trecovery and transformation options (experts only)\n";
|
cout << "r\trecovery and transformation options (experts only)\n";
|
||||||
cout << "s\tresize partition table\n";
|
cout << "s\tresize partition table\n";
|
||||||
|
cout << "t\ttranspose two partition table entries\n";
|
||||||
cout << "v\tverify disk\n";
|
cout << "v\tverify disk\n";
|
||||||
cout << "w\twrite table to disk and exit\n";
|
cout << "w\twrite table to disk and exit\n";
|
||||||
cout << "z\tzap (destroy) GPT data structures 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
|
#ifndef __GPTSTRUCTS
|
||||||
#define __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;
|
using namespace std;
|
||||||
|
|
||||||
@@ -83,7 +89,7 @@ public:
|
|||||||
// Basic necessary functions....
|
// Basic necessary functions....
|
||||||
GPTData(void);
|
GPTData(void);
|
||||||
GPTData(string deviceFilename);
|
GPTData(string deviceFilename);
|
||||||
~GPTData(void);
|
virtual ~GPTData(void);
|
||||||
|
|
||||||
// Verify (or update) data integrity
|
// Verify (or update) data integrity
|
||||||
int Verify(void);
|
int Verify(void);
|
||||||
@@ -98,6 +104,7 @@ public:
|
|||||||
|
|
||||||
// Load or save data from/to disk
|
// Load or save data from/to disk
|
||||||
int LoadMBR(const string & f) {return protectiveMBR.ReadMBRData(f);}
|
int LoadMBR(const string & f) {return protectiveMBR.ReadMBRData(f);}
|
||||||
|
int WriteProtectiveMBR(void) {return protectiveMBR.WriteMBRData(&myDisk);}
|
||||||
void PartitionScan(void);
|
void PartitionScan(void);
|
||||||
int LoadPartitions(const string & deviceFilename);
|
int LoadPartitions(const string & deviceFilename);
|
||||||
int ForceLoadGPTData(void);
|
int ForceLoadGPTData(void);
|
||||||
@@ -106,32 +113,24 @@ public:
|
|||||||
int SaveGPTData(int quiet = 0);
|
int SaveGPTData(int quiet = 0);
|
||||||
int SaveGPTBackup(const string & filename);
|
int SaveGPTBackup(const string & filename);
|
||||||
int LoadGPTBackup(const string & filename);
|
int LoadGPTBackup(const string & filename);
|
||||||
|
int SaveMBR(void);
|
||||||
|
int DestroyGPT(void);
|
||||||
|
int DestroyMBR(void);
|
||||||
|
|
||||||
// Display data....
|
// Display data....
|
||||||
void ShowAPMState(void);
|
void ShowAPMState(void);
|
||||||
void ShowGPTState(void);
|
void ShowGPTState(void);
|
||||||
void DisplayGPTData(void);
|
void DisplayGPTData(void);
|
||||||
void DisplayMBRData(void) {protectiveMBR.DisplayMBRData();}
|
void DisplayMBRData(void) {protectiveMBR.DisplayMBRData();}
|
||||||
void ShowDetails(void);
|
|
||||||
void ShowPartDetails(uint32_t partNum);
|
void ShowPartDetails(uint32_t partNum);
|
||||||
|
|
||||||
// Request information from the user (& possibly do something with it)
|
// Convert between GPT and other formats
|
||||||
uint32_t GetPartNum(void);
|
virtual WhichToUse UseWhichPartitions(void);
|
||||||
void ResizePartitionTable(void);
|
void XFormPartitions(void);
|
||||||
void CreatePartition(void);
|
virtual int XFormDisklabel(uint32_t partNum);
|
||||||
void DeletePartition(void);
|
int XFormDisklabel(BSDData* disklabel);
|
||||||
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);
|
|
||||||
int OnePartToMBR(uint32_t gptPart, int mbrPart); // add one partition to MBR. Returns 1 if successful
|
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
|
int PartsToMBR(const int *gptParts, const int *mbrTypes);
|
||||||
void MakeHybrid(void);
|
|
||||||
|
|
||||||
// Adjust GPT structures WITHOUT user interaction...
|
// Adjust GPT structures WITHOUT user interaction...
|
||||||
int SetGPTSize(uint32_t numEntries);
|
int SetGPTSize(uint32_t numEntries);
|
||||||
@@ -139,6 +138,8 @@ public:
|
|||||||
int DeletePartition(uint32_t partNum);
|
int DeletePartition(uint32_t partNum);
|
||||||
uint32_t CreatePartition(uint32_t partNum, uint64_t startSector, uint64_t endSector);
|
uint32_t CreatePartition(uint32_t partNum, uint64_t startSector, uint64_t endSector);
|
||||||
void SortGPT(void);
|
void SortGPT(void);
|
||||||
|
void QuickSortGPT(int start, int finish);
|
||||||
|
int SwapPartitions(uint32_t partNum1, uint32_t partNum2);
|
||||||
int ClearGPTData(void);
|
int ClearGPTData(void);
|
||||||
void MoveSecondHeaderToEnd();
|
void MoveSecondHeaderToEnd();
|
||||||
int SetName(uint32_t partNum, const string & theName = "");
|
int SetName(uint32_t partNum, const string & theName = "");
|
||||||
@@ -150,6 +151,7 @@ public:
|
|||||||
|
|
||||||
// Return data about the GPT structures....
|
// Return data about the GPT structures....
|
||||||
int GetPartRange(uint32_t* low, uint32_t* high);
|
int GetPartRange(uint32_t* low, uint32_t* high);
|
||||||
|
int FindFirstFreePart(void);
|
||||||
uint32_t GetNumParts(void) {return mainHeader.numParts;}
|
uint32_t GetNumParts(void) {return mainHeader.numParts;}
|
||||||
uint64_t GetMainHeaderLBA(void) {return mainHeader.currentLBA;}
|
uint64_t GetMainHeaderLBA(void) {return mainHeader.currentLBA;}
|
||||||
uint64_t GetSecondHeaderLBA(void) {return secondHeader.currentLBA;}
|
uint64_t GetSecondHeaderLBA(void) {return secondHeader.currentLBA;}
|
||||||
|
|||||||
39
gptpart.cc
39
gptpart.cc
@@ -66,6 +66,11 @@ string GPTPart::GetDescription(void) {
|
|||||||
return theName;
|
return theName;
|
||||||
} // GPTPart::GetDescription()
|
} // 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
|
// 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
|
// name *IF* the current name is the generic one for the current partition
|
||||||
// type.
|
// type.
|
||||||
@@ -139,6 +144,7 @@ void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
|
|||||||
|
|
||||||
if (firstLBA != 0) {
|
if (firstLBA != 0) {
|
||||||
sizeInSI = BytesToSI(blockSize * (lastLBA - firstLBA + 1));
|
sizeInSI = BytesToSI(blockSize * (lastLBA - firstLBA + 1));
|
||||||
|
cout.fill(' ');
|
||||||
cout.width(4);
|
cout.width(4);
|
||||||
cout << partNum + 1 << " ";
|
cout << partNum + 1 << " ";
|
||||||
cout.width(14);
|
cout.width(14);
|
||||||
@@ -256,36 +262,3 @@ void GPTPart::ChangeType(void) {
|
|||||||
SetDefaultDescription();
|
SetDefaultDescription();
|
||||||
} // if
|
} // if
|
||||||
} // GPTPart::ChangeType()
|
} // 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 GetLengthLBA(void);
|
||||||
uint64_t GetAttributes(void) {return attributes;}
|
uint64_t GetAttributes(void) {return attributes;}
|
||||||
string GetDescription(void);
|
string GetDescription(void);
|
||||||
|
int IsUsed(void);
|
||||||
|
|
||||||
// Simple data assignment:
|
// Simple data assignment:
|
||||||
void SetType(PartType t);
|
void SetType(PartType t);
|
||||||
@@ -83,7 +84,4 @@ class GPTPart {
|
|||||||
void ChangeType(void); // Change the type code
|
void ChangeType(void); // Change the type code
|
||||||
}; // struct GPTPart
|
}; // struct GPTPart
|
||||||
|
|
||||||
// A support function that doesn't quite belong in the class....
|
|
||||||
void QuickSortGPT(GPTPart* partitions, int start, int finish);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
58
mbr.cc
58
mbr.cc
@@ -10,7 +10,7 @@
|
|||||||
#define __STDC_CONSTANT_MACROS
|
#define __STDC_CONSTANT_MACROS
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
//#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -273,7 +273,7 @@ int MBRData::WriteMBRData(void) {
|
|||||||
int allOK = 1;
|
int allOK = 1;
|
||||||
|
|
||||||
if (myDisk != NULL) {
|
if (myDisk != NULL) {
|
||||||
if (myDisk->OpenForWrite(device) != 0) {
|
if (myDisk->OpenForWrite() != 0) {
|
||||||
allOK = WriteMBRData(myDisk);
|
allOK = WriteMBRData(myDisk);
|
||||||
} else {
|
} else {
|
||||||
allOK = 0;
|
allOK = 0;
|
||||||
@@ -493,10 +493,7 @@ void MBRData::EmptyMBR(int clearBootloader) {
|
|||||||
// 2-byte nulls area only if requested to do so. (This is the
|
// 2-byte nulls area only if requested to do so. (This is the
|
||||||
// default.)
|
// default.)
|
||||||
if (clearBootloader == 1) {
|
if (clearBootloader == 1) {
|
||||||
for (i = 0; i < 440; i++)
|
EmptyBootloader();
|
||||||
code[i] = 0;
|
|
||||||
diskSignature = (uint32_t) rand();
|
|
||||||
nulls = 0;
|
|
||||||
} // if
|
} // if
|
||||||
|
|
||||||
// Blank out the partitions
|
// Blank out the partitions
|
||||||
@@ -515,6 +512,17 @@ void MBRData::EmptyMBR(int clearBootloader) {
|
|||||||
MBRSignature = MBR_SIGNATURE;
|
MBRSignature = MBR_SIGNATURE;
|
||||||
} // MBRData::EmptyMBR()
|
} // 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.
|
// Create a protective MBR. Clears the boot loader area if clearBoot > 0.
|
||||||
void MBRData::MakeProtectiveMBR(int clearBoot) {
|
void MBRData::MakeProtectiveMBR(int clearBoot) {
|
||||||
|
|
||||||
@@ -523,6 +531,7 @@ void MBRData::MakeProtectiveMBR(int clearBoot) {
|
|||||||
// Initialize variables
|
// Initialize variables
|
||||||
nulls = 0;
|
nulls = 0;
|
||||||
MBRSignature = MBR_SIGNATURE;
|
MBRSignature = MBR_SIGNATURE;
|
||||||
|
diskSignature = (uint32_t) rand();
|
||||||
|
|
||||||
partitions[0].status = UINT8_C(0); // Flag the protective part. as unbootable
|
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,
|
void MBRData::MakePart(int num, uint32_t start, uint32_t length, int type,
|
||||||
int bootable) {
|
int bootable) {
|
||||||
if ((num >= 0) && (num < MAX_MBR_PARTS)) {
|
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[0] = UINT8_C(0);
|
||||||
partitions[num].firstSector[1] = UINT8_C(0);
|
partitions[num].firstSector[1] = UINT8_C(0);
|
||||||
partitions[num].firstSector[2] = 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, partitions[num].firstSector);
|
||||||
LBAtoCHS((uint64_t) (start + length - 1), partitions[num].lastSector);
|
LBAtoCHS((uint64_t) (start + length - 1), partitions[num].lastSector);
|
||||||
} // if (length > 0)
|
} // if (length > 0)
|
||||||
|
SetPartBootable(num, bootable);
|
||||||
} // if valid partition number
|
} // if valid partition number
|
||||||
} // MBRData::MakePart()
|
} // 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
|
// Create a partition that fills the most available space. Returns
|
||||||
// 1 if partition was created, 0 otherwise. Intended for use in
|
// 1 if partition was created, 0 otherwise. Intended for use in
|
||||||
// creating hybrid MBRs.
|
// creating hybrid MBRs.
|
||||||
@@ -637,7 +677,7 @@ int MBRData::DeleteByLocation(uint64_t start64, uint64_t length64) {
|
|||||||
start32 = (uint32_t) start64;
|
start32 = (uint32_t) start64;
|
||||||
length32 = (uint32_t) length64;
|
length32 = (uint32_t) length64;
|
||||||
for (i = 0; i < MAX_MBR_PARTS; i++) {
|
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)) {
|
(partitions[i].partitionType != 0xEE)) {
|
||||||
DeletePartition(i);
|
DeletePartition(i);
|
||||||
if (state == hybrid)
|
if (state == hybrid)
|
||||||
@@ -717,7 +757,7 @@ uint32_t MBRData::FindLastInFree(uint32_t start) {
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
if ((diskSize <= UINT32_MAX) && (diskSize > 0))
|
if ((diskSize <= UINT32_MAX) && (diskSize > 0))
|
||||||
nearestStart = diskSize - 1;
|
nearestStart = (uint32_t) diskSize - 1;
|
||||||
else
|
else
|
||||||
nearestStart = UINT32_MAX - 1;
|
nearestStart = UINT32_MAX - 1;
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
|
|||||||
3
mbr.h
3
mbr.h
@@ -105,9 +105,12 @@ public:
|
|||||||
// Functions to create, delete, or change partitions
|
// Functions to create, delete, or change partitions
|
||||||
// Pass EmptyMBR 1 to clear the boot loader code, 0 to leave it intact
|
// Pass EmptyMBR 1 to clear the boot loader code, 0 to leave it intact
|
||||||
void EmptyMBR(int clearBootloader = 1);
|
void EmptyMBR(int clearBootloader = 1);
|
||||||
|
void EmptyBootloader(void);
|
||||||
void MakeProtectiveMBR(int clearBoot = 0);
|
void MakeProtectiveMBR(int clearBoot = 0);
|
||||||
void MakePart(int num, uint32_t startLBA, uint32_t lengthLBA, int type = 0x07,
|
void MakePart(int num, uint32_t startLBA, uint32_t lengthLBA, int type = 0x07,
|
||||||
int bootable = 0);
|
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
|
int MakeBiggestPart(int i, int type); // Make partition filling most space
|
||||||
void DeletePartition(int i);
|
void DeletePartition(int i);
|
||||||
int DeleteByLocation(uint64_t start64, uint64_t length64);
|
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. */
|
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
//#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
|
|||||||
76
sgdisk.8
76
sgdisk.8
@@ -1,6 +1,6 @@
|
|||||||
.\" Copyright 2009 Roderick W. Smith (rodsmith@rodsbooks.com)
|
.\" Copyright 2009 Roderick W. Smith (rodsmith@rodsbooks.com)
|
||||||
.\" May be distributed under the GNU General Public License
|
.\" May be distributed under the GNU General Public License
|
||||||
.TH "SGDISK" "8" "0.6.3" "Roderick W. Smith" "GPT fdisk Manual"
|
.TH "SGDISK" "8" "0.6.4" "Roderick W. Smith" "GPT fdisk Manual"
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
sgdisk \- Command\-line GUID partition table (GPT) manipulator for Linux and Unix
|
sgdisk \- Command\-line GUID partition table (GPT) manipulator for Linux and Unix
|
||||||
.SH "SYNOPSIS"
|
.SH "SYNOPSIS"
|
||||||
@@ -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
|
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
|
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
|
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
|
PowerPC\-based Macintoshes. If you specify any option that results in
|
||||||
to an MBR or BSD disklabel, \fBsgdisk\fR ignores those changes unless the
|
changes to an MBR or BSD disklabel, \fBsgdisk\fR ignores those changes
|
||||||
\fI\-g\fR (\fI\-\-mbrtogpt\fR) or \fI\-z\fR (\fI\-\-zap\fR) option is used.
|
unless the \fI\-g\fR (\fI\-\-mbrtogpt\fR), \fI\-z\fR (\fI\-\-zap\fR), or
|
||||||
If you use the \fI\-g\fR option, \fBsgdisk\fR replaces the MBR or disklabel
|
\fI\-Z\fR (\fI\-\-zap\-all\fR) option is used. If you use the \fI\-g\fR
|
||||||
with a GPT. \fIThis action is potentially dangerous!\fR Your system may become
|
option, \fBsgdisk\fR replaces the MBR or disklabel with a GPT. \fIThis
|
||||||
unbootable, and partition type codes may become corrupted if the disk uses
|
action is potentially dangerous!\fR Your system may become unbootable, and
|
||||||
unrecognized type codes. Boot problems are particularly likely if you're
|
partition type codes may become corrupted if the disk uses unrecognized
|
||||||
multi\-booting with any GPT\-unaware OS.
|
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
|
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
|
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
|
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.
|
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
|
.TP
|
||||||
.B \-i, \-\-info=partnum
|
.B \-i, \-\-info=partnum
|
||||||
Show detailed partition information. The summary information produced by
|
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
|
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.
|
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
|
.TP
|
||||||
.B \-n, \-\-new=partnum:start:end
|
.B \-n, \-\-new=partnum:start:end
|
||||||
Create a new partition. You enter a partition
|
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
|
altered according to other parameters, but changes are not written
|
||||||
to disk.
|
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
|
.TP
|
||||||
.B \-s, \-\-sort
|
.B \-s, \-\-sort
|
||||||
Sort partition entries. GPT partition numbers need not match the order of
|
Sort partition entries. GPT partition numbers need not match the order of
|
||||||
@@ -317,14 +349,22 @@ specifying a device filename.
|
|||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-z, \-\-zap
|
.B \-z, \-\-zap
|
||||||
Zap (destroy) the GPT data structures and exit. Use this option if you want to
|
Zap (destroy) the GPT data structures and then exit. Use this option if you
|
||||||
repartition a GPT disk using \fBfdisk\fR or some other GPT\-unaware program.
|
want to repartition a GPT disk using \fBfdisk\fR or some other GPT\-unaware
|
||||||
You'll be given the choice of preserving the existing MBR, in case it's a
|
program. This option destroys only the GPT data structures; it leaves the
|
||||||
hybrid MBR with salvageable partitions or if you've already created new MBR
|
MBR intact. This makes it useful for wiping out GPT data structures after a
|
||||||
partitions and want to erase the remnants of your GPT partitions. \fIIf you've
|
disk has been repartitioned for MBR using a GPT-unaware utility; however,
|
||||||
already created new MBR partitions, it's conceivable that this option will
|
there's a risk that it will damage boot loaders or even the start of the
|
||||||
damage the first and/or last MBR partitions!\fR Such an event is unlikely, but
|
first or end of the last MBR partition. If you use it on a valid GPT disk,
|
||||||
could occur if your new MBR partitions overlap the old GPT data structures.
|
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
|
.TP
|
||||||
.B \-?, \-\-help
|
.B \-?, \-\-help
|
||||||
@@ -353,7 +393,7 @@ Non\-GPT disk detected and no \fI\-g\fR option
|
|||||||
.B 4
|
.B 4
|
||||||
An error prevented saving changes
|
An error prevented saving changes
|
||||||
.SH "BUGS"
|
.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:
|
should be considered beta software. Known bugs and limitations include:
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
97
sgdisk.cc
97
sgdisk.cc
@@ -25,6 +25,8 @@ using namespace std;
|
|||||||
|
|
||||||
uint64_t GetInt(char* Info, int itemNum);
|
uint64_t GetInt(char* Info, int itemNum);
|
||||||
string GetString(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[]) {
|
int main(int argc, char *argv[]) {
|
||||||
GPTData theGPT;
|
GPTData theGPT;
|
||||||
@@ -35,8 +37,8 @@ int main(int argc, char *argv[]) {
|
|||||||
uint32_t tableSize = 128;
|
uint32_t tableSize = 128;
|
||||||
uint64_t startSector, endSector;
|
uint64_t startSector, endSector;
|
||||||
char *device = NULL;
|
char *device = NULL;
|
||||||
char *newPartInfo = NULL, *typeCode = NULL, *partName;
|
char *newPartInfo = NULL, *typeCode = NULL, *partName = NULL;
|
||||||
char *backupFile = NULL;
|
char *backupFile = NULL, *twoParts = NULL, *hybrids = NULL, *mbrParts;
|
||||||
PartType typeHelper;
|
PartType typeHelper;
|
||||||
|
|
||||||
poptContext poptCon;
|
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", ""},
|
{"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", ""},
|
{"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", ""},
|
{"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"},
|
{"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"},
|
{"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", ""},
|
{"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"},
|
{"new", 'n', POPT_ARG_STRING, &newPartInfo, 'n', "create new partition", "partnum:start:end"},
|
||||||
{"clear", 'o', POPT_ARG_NONE, NULL, 'o', "clear partition table", ""},
|
{"clear", 'o', POPT_ARG_NONE, NULL, 'o', "clear partition table", ""},
|
||||||
{"print", 'p', POPT_ARG_NONE, NULL, 'p', "print 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", ""},
|
{"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", ""},
|
{"sort", 's', POPT_ARG_NONE, NULL, 's', "sort partition table entries", ""},
|
||||||
{"resize-table", 'S', POPT_ARG_INT, &tableSize, 'S', "resize partition table", "numparts"},
|
{"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"},
|
{"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"},
|
{"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", ""},
|
{"verify", 'v', POPT_ARG_NONE, NULL, 'v', "check partition table integrity", ""},
|
||||||
{"version", 'V', POPT_ARG_NONE, NULL, 'V', "display version information", ""},
|
{"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 }
|
POPT_AUTOHELP { NULL, 0, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -150,6 +156,11 @@ int main(int argc, char *argv[]) {
|
|||||||
saveData = 1;
|
saveData = 1;
|
||||||
saveNonGPT = 1;
|
saveNonGPT = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'h':
|
||||||
|
theGPT.JustLooking(0);
|
||||||
|
if (BuildMBR(&theGPT, hybrids, 1) == 1)
|
||||||
|
saveData = 1;
|
||||||
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
theGPT.ShowPartDetails(infoPartNum - 1);
|
theGPT.ShowPartDetails(infoPartNum - 1);
|
||||||
break;
|
break;
|
||||||
@@ -165,6 +176,19 @@ int main(int argc, char *argv[]) {
|
|||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
break;
|
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':
|
case 'n':
|
||||||
theGPT.JustLooking(0);
|
theGPT.JustLooking(0);
|
||||||
partNum = (int) GetInt(newPartInfo, 1) - 1;
|
partNum = (int) GetInt(newPartInfo, 1) - 1;
|
||||||
@@ -190,6 +214,16 @@ int main(int argc, char *argv[]) {
|
|||||||
case 'P':
|
case 'P':
|
||||||
pretend = 1;
|
pretend = 1;
|
||||||
break;
|
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':
|
case 's':
|
||||||
theGPT.JustLooking(0);
|
theGPT.JustLooking(0);
|
||||||
theGPT.SortGPT();
|
theGPT.SortGPT();
|
||||||
@@ -217,16 +251,26 @@ int main(int argc, char *argv[]) {
|
|||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
theGPT.JustLooking(0);
|
theGPT.JustLooking(0);
|
||||||
theGPT.XFormDisklabel(bsdPartNum);
|
theGPT.XFormDisklabel(bsdPartNum - 1);
|
||||||
saveData = 1;
|
saveData = 1;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
theGPT.Verify();
|
theGPT.Verify();
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
if (!pretend)
|
if (!pretend) {
|
||||||
theGPT.DestroyGPT(-1);
|
theGPT.DestroyGPT();
|
||||||
|
} // if
|
||||||
saveNonGPT = 0;
|
saveNonGPT = 0;
|
||||||
|
saveData = 0;
|
||||||
|
break;
|
||||||
|
case 'Z':
|
||||||
|
if (!pretend) {
|
||||||
|
theGPT.DestroyGPT();
|
||||||
|
theGPT.DestroyMBR();
|
||||||
|
} // if
|
||||||
|
saveNonGPT = 0;
|
||||||
|
saveData = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cerr << "Unknown option (-" << opt << ")!\n";
|
cerr << "Unknown option (-" << opt << ")!\n";
|
||||||
@@ -287,3 +331,44 @@ string GetString(char* argument, int itemNum) {
|
|||||||
|
|
||||||
return Info.substr(startPos, endPos - startPos + 1);
|
return Info.substr(startPos, endPos - startPos + 1);
|
||||||
} // GetString()
|
} // 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 <sys/stat.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@@ -166,10 +167,9 @@ uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const string &
|
|||||||
// form
|
// form
|
||||||
string BytesToSI(uint64_t size) {
|
string BytesToSI(uint64_t size) {
|
||||||
string units;
|
string units;
|
||||||
char theValue[99];
|
ostringstream theValue;
|
||||||
float sizeInSI;
|
float sizeInSI;
|
||||||
|
|
||||||
theValue[0] = '\0';
|
|
||||||
sizeInSI = (float) size;
|
sizeInSI = (float) size;
|
||||||
units = " bytes";
|
units = " bytes";
|
||||||
if (sizeInSI > 1024.0) {
|
if (sizeInSI > 1024.0) {
|
||||||
@@ -192,12 +192,14 @@ string BytesToSI(uint64_t size) {
|
|||||||
sizeInSI /= 1024.0;
|
sizeInSI /= 1024.0;
|
||||||
units = " PiB";
|
units = " PiB";
|
||||||
} // if
|
} // if
|
||||||
|
theValue.setf(ios::fixed);
|
||||||
if (units == " bytes") { // in bytes, so no decimal point
|
if (units == " bytes") { // in bytes, so no decimal point
|
||||||
sprintf(theValue, "%1.0f%s", sizeInSI, units.c_str());
|
theValue.precision(0);
|
||||||
} else {
|
} else {
|
||||||
sprintf(theValue, "%1.1f%s", sizeInSI, units.c_str());
|
theValue.precision(1);
|
||||||
} // if/else
|
} // if/else
|
||||||
return theValue;
|
theValue << sizeInSI << units;
|
||||||
|
return theValue.str();
|
||||||
} // BlocksToSI()
|
} // BlocksToSI()
|
||||||
|
|
||||||
// Converts two consecutive characters in the input string into a
|
// 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. */
|
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
//#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#ifndef __GPTSUPPORT
|
#ifndef __GPTSUPPORT
|
||||||
#define __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
|
// Darwin (Mac OS) only: disk IOCTLs are different, and there is no lseek64
|
||||||
// This used to use __DARWIN_UNIX03 rather than __APPLE__, but __APPLE__
|
// 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/
|
// is more general. If the code fails to work on older versions of OS X/
|
||||||
|
|||||||
Reference in New Issue
Block a user