summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile16
-rw-r--r--Makefile.freebsd16
-rw-r--r--NEWS16
-rw-r--r--README22
-rw-r--r--basicmbr.cc4
-rw-r--r--cgdisk.84
-rw-r--r--cgdisk.cc1
-rw-r--r--current.spec8
-rw-r--r--fixparts.84
-rw-r--r--gdisk.84
-rw-r--r--gdisk.cc3
-rw-r--r--gpt.cc45
-rw-r--r--gptcurses.cc11
-rw-r--r--gptpart.cc203
-rw-r--r--gptpart.h2
-rw-r--r--gpttext.cc10
-rw-r--r--guid.cc7
-rw-r--r--guid.h2
-rw-r--r--parttypes.cc2
-rw-r--r--sgdisk.84
-rw-r--r--support.cc3
-rw-r--r--support.h4
22 files changed, 277 insertions, 114 deletions
diff --git a/Makefile b/Makefile
index 3364082..1ae018e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
CC=gcc
CXX=g++
CFLAGS+=-D_FILE_OFFSET_BITS=64
-CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64 -D USE_UTF16
-#CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64
+#CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64 -D USE_UTF16
+CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64
LDFLAGS+=
LIB_NAMES=crc32 support guid gptpart mbrpart basicmbr mbr gpt bsd parttypes attributes diskio diskio-unix
MBR_LIBS=support diskio diskio-unix basicmbr mbrpart
@@ -14,16 +14,16 @@ DEPEND= makedepend $(CXXFLAGS)
all: cgdisk gdisk sgdisk fixparts
gdisk: $(LIB_OBJS) gdisk.o gpttext.o
-# $(CXX) $(LIB_OBJS) gdisk.o gpttext.o $(LDFLAGS) -luuid -o gdisk
- $(CXX) $(LIB_OBJS) gdisk.o gpttext.o $(LDFLAGS) -licuio -licuuc -luuid -o gdisk
+ $(CXX) $(LIB_OBJS) gdisk.o gpttext.o $(LDFLAGS) -luuid -o gdisk
+# $(CXX) $(LIB_OBJS) gdisk.o gpttext.o $(LDFLAGS) -licuio -licuuc -luuid -o gdisk
cgdisk: $(LIB_OBJS) cgdisk.o gptcurses.o
-# $(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o $(LDFLAGS) -luuid -lncurses -o cgdisk
- $(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o $(LDFLAGS) -licuio -licuuc -luuid -lncurses -o cgdisk
+ $(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o $(LDFLAGS) -luuid -lncursesw -o cgdisk
+# $(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o $(LDFLAGS) -licuio -licuuc -luuid -lncurses -o cgdisk
sgdisk: $(LIB_OBJS) sgdisk.o gptcl.o
-# $(CXX) $(LIB_OBJS) sgdisk.o gptcl.o $(LDFLAGS) -luuid -lpopt -o sgdisk
- $(CXX) $(LIB_OBJS) sgdisk.o gptcl.o $(LDFLAGS) -licuio -licuuc -luuid -lpopt -o sgdisk
+ $(CXX) $(LIB_OBJS) sgdisk.o gptcl.o $(LDFLAGS) -luuid -lpopt -o sgdisk
+# $(CXX) $(LIB_OBJS) sgdisk.o gptcl.o $(LDFLAGS) -licuio -licuuc -luuid -lpopt -o sgdisk
fixparts: $(MBR_LIB_OBJS) fixparts.o
$(CXX) $(MBR_LIB_OBJS) fixparts.o $(LDFLAGS) -o fixparts
diff --git a/Makefile.freebsd b/Makefile.freebsd
index d36dc92..dace733 100644
--- a/Makefile.freebsd
+++ b/Makefile.freebsd
@@ -1,8 +1,8 @@
CC=gcc
CXX=g++
CFLAGS+=-D_FILE_OFFSET_BITS=64
-CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64 -D USE_UTF16 -I/usr/local/include
-#CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include
+#CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64 -D USE_UTF16 -I/usr/local/include
+CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include
LDFLAGS+=
LIB_NAMES=crc32 support guid gptpart mbrpart basicmbr mbr gpt bsd parttypes attributes diskio diskio-unix
MBR_LIBS=support diskio diskio-unix basicmbr mbrpart
@@ -14,16 +14,16 @@ DEPEND= makedepend $(CXXFLAGS)
all: gdisk cgdisk sgdisk fixparts
gdisk: $(LIB_OBJS) gdisk.o gpttext.o
- $(CXX) $(LIB_OBJS) gdisk.o gpttext.o -L/usr/local/lib $(LDFLAGS) -licuio -luuid -o gdisk
-# $(CXX) $(LIB_OBJS) gdisk.o gpttext.o -L/usr/local/lib $(LDFLAGS) -luuid -o gdisk
+# $(CXX) $(LIB_OBJS) gdisk.o gpttext.o -L/usr/local/lib $(LDFLAGS) -licuio -luuid -o gdisk
+ $(CXX) $(LIB_OBJS) gdisk.o gpttext.o -L/usr/local/lib $(LDFLAGS) -luuid -o gdisk
cgdisk: $(LIB_OBJS) cgdisk.o gptcurses.o
- $(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o -L/usr/local/lib $(LDFLAGS) -licuio -luuid -lncurses -o cgdisk
-# $(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o -L/usr/local/lib $(LDFLAGS) -luuid -lncurses -o cgdisk
+# $(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o -L/usr/local/lib $(LDFLAGS) -licuio -luuid -lncurses -o cgdisk
+ $(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o -L/usr/local/lib $(LDFLAGS) -luuid -lncurses -o cgdisk
sgdisk: $(LIB_OBJS) sgdisk.o gptcl.o
- $(CXX) $(LIB_OBJS) sgdisk.o gptcl.o -L/usr/local/lib $(LDFLAGS) -luuid -licuio -lpopt -o sgdisk
-# $(CXX) $(LIB_OBJS) sgdisk.o gptcl.o -L/usr/local/lib $(LDFLAGS) -luuid -lpopt -o sgdisk
+# $(CXX) $(LIB_OBJS) sgdisk.o gptcl.o -L/usr/local/lib $(LDFLAGS) -luuid -licuio -lpopt -o sgdisk
+ $(CXX) $(LIB_OBJS) sgdisk.o gptcl.o -L/usr/local/lib $(LDFLAGS) -luuid -lpopt -o sgdisk
fixparts: $(MBR_LIB_OBJS) fixparts.o
$(CXX) $(MBR_LIB_OBJS) fixparts.o -L/usr/local/lib $(LDFLAGS) -o fixparts
diff --git a/NEWS b/NEWS
index 42dc4ae..c71c4b0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,15 +1,15 @@
-0.8.9 (??/??/2014):
--------------------
+0.8.9 (2/17/2014):
+------------------
+
+- Removed dependency on libicu for UTF-16 support.
- Fixed spurious "0xEE partition doesn't start on sector 1" warning in
FixParts (and perhaps in other programs under some circumstances).
-- Added check for valid location of backup GPT data to GPT-destruction
- options ('z' in gdisk, -z and -Z options to sgdisk). If the backup
- GPT data structures aren't at the end of the disk, they aren't erased.
- This is done to avoid wiping out data mid-disk that might not be backup
- GPT data structures, which could otherwise occur if a RAID array was
- resized in certain ways.
+- Added GPT regeneration command to GPT-destruction options ('z' in gdisk,
+ -z and -Z options to sgdisk). This is done to avoid wiping out data
+ mid-disk that might not be backup GPT data structures, which could
+ otherwise occur if a RAID array was resized in certain ways.
- Added check for an oversized 0xEE protective partition. The program now
auto-repairs this condition on loading if the GPT data seem otherwise
diff --git a/README b/README
index 2fc1c45..a3c0e44 100644
--- a/README
+++ b/README
@@ -174,17 +174,17 @@ be used instead. In addition, note these requirements:
FreeBSD, the e2fsprogs-libuuid port must be installed.
* The ICU library (http://site.icu-project.org), which provides support for
- Unicode partition names, is recommended on all
- platforms except Windows. This library is normally installed in Linux and
- OS X, but you may need to install the development headers (libicu-dev or
- something similar in Linux; or the libicu36-dev Fink package in OS X). To
- compile without ICU support, you must modify the Makefile: Remove the
- "-D USE_UTF16" part from the CXXFLAGS line and remove references to
- -licuio, -licuuc, -licudata, and -licucore (details vary between
- platforms) from the compilation options. Suitable lines are present, but
- commented out, in the Makefile, Makefile.solaris, Makefile.freebsd files.
- Because of problems with ICU under OS X, the Makefile.mac file doesn't
- build against ICU by default.
+ Unicode partition names, is optional on all platforms except Windows, on
+ which it's not supported. Using this library was required to get proper
+ UTF-16 partition name support in GPT fdisk versions prior to 0.8.9, but
+ as of that version it should not longer be required. Nonetheless, you can
+ use it if you're having problems with the new UTF-16 support. This
+ library is normally installed in Linux and OS X, but you may need to
+ install the development headers (libicu-dev or something similar in
+ Linux; or the libicu36-dev Fink package in OS X). To compile with ICU
+ support, you must modify the Makefile: Look for commented-out lines that
+ refer to USE_UTF16, -licuuc, -licudata, or -licucore. Uncomment them and
+ comment out the equivalents that lack these lines.
* The cgdisk program requires the ncurses library and its development files
(headers). Most Linux distributions install ncurses by default, but you
diff --git a/basicmbr.cc b/basicmbr.cc
index 9e754d4..f7e1f6d 100644
--- a/basicmbr.cc
+++ b/basicmbr.cc
@@ -671,7 +671,7 @@ int BasicMBRData::LBAtoCHS(uint64_t lba, uint8_t * chs) {
done = 1;
} // if
// If LBA value is too large for CHS, max out CHS values....
- if ((!done) && (lba >= (numHeads * numSecspTrack * MAX_CYLINDERS))) {
+ if ((!done) && (lba >= ((uint64_t) numHeads * numSecspTrack * MAX_CYLINDERS))) {
chs[0] = 254;
chs[1] = chs[2] = 255;
done = 1;
@@ -1223,7 +1223,7 @@ void BasicMBRData::MaximizePrimaries() {
// Remove primary partitions in excess of 4, starting with the later ones,
// in terms of the array location....
void BasicMBRData::TrimPrimaries(void) {
- int numToDelete, i = MAX_MBR_PARTS;
+ int numToDelete, i = MAX_MBR_PARTS - 1;
numToDelete = NumPrimaries() - 4;
while ((numToDelete > 0) && (i >= 0)) {
diff --git a/cgdisk.8 b/cgdisk.8
index 05ef400..bb20d71 100644
--- a/cgdisk.8
+++ b/cgdisk.8
@@ -1,6 +1,6 @@
.\" Copyright 2011-2013 Roderick W. Smith (rodsmith@rodsbooks.com)
.\" May be distributed under the GNU General Public License
-.TH "CGDISK" "8" "0.8.8" "Roderick W. Smith" "GPT fdisk Manual"
+.TH "CGDISK" "8" "0.8.9" "Roderick W. Smith" "GPT fdisk Manual"
.SH "NAME"
cgdisk \- Curses-based GUID partition table (GPT) manipulator
.SH "SYNOPSIS"
@@ -276,7 +276,7 @@ Write data. Use this command to save your changes.
.SH "BUGS"
-As of October 2013 (version 0.8.8), \fBcgdisk\fR should be considered
+As of February 2014 (version 0.8.9), \fBcgdisk\fR should be considered
beta software. Although the underlying partition manipulation code is much
older, the \fBcgdisk\fR ncurses user interface is brand new with GPT fdisk
version 0.8.0. Known bugs and limitations include:
diff --git a/cgdisk.cc b/cgdisk.cc
index 7e967cc..f21f046 100644
--- a/cgdisk.cc
+++ b/cgdisk.cc
@@ -75,4 +75,5 @@ int main(int argc, char *argv[]) {
} else {
Report("Could not load partitions from '" + device + "'! Aborting!");
} // if/else
+ return 0;
} // main
diff --git a/current.spec b/current.spec
index 39fe6e1..8beaeaa 100644
--- a/current.spec
+++ b/current.spec
@@ -1,11 +1,11 @@
Summary: GPT partitioning and MBR repair software
Name: gptfdisk
-Version: 0.8.8
+Version: 0.8.9
Release: 1%{?dist}
License: GPLv2
URL: http://www.rodsbooks.com/gdisk
Group: Applications/System
-Source: http://www.rodsbooks.com/gdisk/gptfdisk-0.8.8.tar.gz
+Source: http://www.rodsbooks.com/gdisk/gptfdisk-0.8.9.tar.gz
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
%description
@@ -80,5 +80,5 @@ provides a few additional partition manipulation features.
%changelog
-* Mon Oct 14 2013 R Smith <rodsmith@rodsbooks.com> - 0.8.8
-- Created spec file for 0.8.8 release
+* Mon Feb 17 2014 R Smith <rodsmith@rodsbooks.com> - 0.8.9
+- Created spec file for 0.8.9 release
diff --git a/fixparts.8 b/fixparts.8
index 934be3c..b7b532d 100644
--- a/fixparts.8
+++ b/fixparts.8
@@ -1,6 +1,6 @@
.\" Copyright 2011-2013 Roderick W. Smith (rodsmith@rodsbooks.com)
.\" May be distributed under the GNU General Public License
-.TH "FIXPARTS" "8" "0.8.8" "Roderick W. Smith" "FixParts Manual"
+.TH "FIXPARTS" "8" "0.8.9" "Roderick W. Smith" "FixParts Manual"
.SH "NAME"
fixparts \- MBR partition table repair utility
.SH "SYNOPSIS"
@@ -202,7 +202,7 @@ see a summary of available options.
.PP
.SH "BUGS"
-As of October 2013 (version 0.8.8), \fBfixparts\fR
+As of February 2014 (version 0.8.9), \fBfixparts\fR
should be considered beta software. Known bugs and limitations include:
.TP
diff --git a/gdisk.8 b/gdisk.8
index a2c64bf..82066bb 100644
--- a/gdisk.8
+++ b/gdisk.8
@@ -1,6 +1,6 @@
.\" Copyright 2011-2013 Roderick W. Smith (rodsmith@rodsbooks.com)
.\" May be distributed under the GNU General Public License
-.TH "GDISK" "8" "0.8.8" "Roderick W. Smith" "GPT fdisk Manual"
+.TH "GDISK" "8" "0.8.9" "Roderick W. Smith" "GPT fdisk Manual"
.SH "NAME"
gdisk \- Interactive GUID partition table (GPT) manipulator
.SH "SYNOPSIS"
@@ -561,7 +561,7 @@ entering data. When only one option is possible, \fBgdisk\fR
usually bypasses the prompt entirely.
.SH "BUGS"
-As of October 2013 (version 0.8.8), \fBgdisk\fR
+As of February 2014 (version 0.8.9), \fBgdisk\fR
should be considered beta software. Known bugs and limitations include:
.TP
diff --git a/gdisk.cc b/gdisk.cc
index 8cd47a8..b3c6240 100644
--- a/gdisk.cc
+++ b/gdisk.cc
@@ -58,4 +58,5 @@ int main(int argc, char* argv[]) {
cerr << "Usage: " << argv[0] << " [-l] device_file\n";
break;
} // switch
-} // main \ No newline at end of file
+ return 1 ;
+} // main
diff --git a/gpt.cc b/gpt.cc
index d584397..fdffb25 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -1314,6 +1314,7 @@ int GPTData::DestroyGPT(void) {
uint8_t* emptyTable;
memset(blankSector, 0, sizeof(blankSector));
+ ClearGPTData();
if (myDisk.OpenForWrite()) {
if (!myDisk.Seek(mainHeader.currentLBA))
@@ -1327,8 +1328,8 @@ int GPTData::DestroyGPT(void) {
tableSize = numParts * mainHeader.sizeOfPartitionEntries;
emptyTable = new uint8_t[tableSize];
if (emptyTable == NULL) {
- cerr << "Could not allocate memory in GPTData::DestroyGPT()! Aborting operation!\n";
- return(0);
+ cerr << "Could not allocate memory in GPTData::DestroyGPT()! Terminating!\n";
+ exit(1);
} // if
memset(emptyTable, 0, tableSize);
if (allOK) {
@@ -1337,31 +1338,25 @@ int GPTData::DestroyGPT(void) {
cerr << "Warning! GPT main partition table not overwritten! Error is " << errno << "\n";
allOK = 0;
} // if write failed
- } // if
-
- if (secondHeader.currentLBA == (diskSize - UINT64_C(1))) {
- if (!myDisk.Seek(secondHeader.partitionEntriesLBA))
+ } // if
+ if (!myDisk.Seek(secondHeader.partitionEntriesLBA))
+ allOK = 0;
+ if (allOK) {
+ sum = myDisk.Write(emptyTable, tableSize);
+ if (sum != tableSize) {
+ cerr << "Warning! GPT backup partition table not overwritten! Error is "
+ << errno << "\n";
allOK = 0;
- if (allOK) {
- sum = myDisk.Write(emptyTable, tableSize);
- if (sum != tableSize) {
- cerr << "Warning! GPT backup partition table not overwritten! Error is "
- << errno << "\n";
- allOK = 0;
- } // if wrong size written
- } // if
- if (!myDisk.Seek(secondHeader.currentLBA))
+ } // if wrong size written
+ } // if
+ if (!myDisk.Seek(secondHeader.currentLBA))
+ allOK = 0;
+ if (allOK) {
+ if (myDisk.Write(blankSector, 512) != 512) { // blank it out
+ cerr << "Warning! GPT backup header not overwritten! Error is " << errno << "\n";
allOK = 0;
- if (allOK) {
- if (myDisk.Write(blankSector, 512) != 512) { // blank it out
- cerr << "Warning! GPT backup header not overwritten! Error is " << errno << "\n";
- allOK = 0;
- } // if
} // if
- } else {
- cout << "Note: The GPT second header is not at the end of the disk end; therefore,\n"
- << "it's not being erased.\n";
- }
+ } // if
myDisk.DiskSync();
myDisk.Close();
cout << "GPT data structures destroyed! You may now partition the disk using fdisk or\n"
@@ -2444,7 +2439,7 @@ int SizesOK(void) {
allOK = 0;
} // if
if (sizeof(PartType) != 16) {
- cerr << "PartType is " << sizeof(GUIDData) << " bytes, should be 16 bytes; aborting!\n";
+ cerr << "PartType is " << sizeof(PartType) << " bytes, should be 16 bytes; aborting!\n";
allOK = 0;
} // if
return (allOK);
diff --git a/gptcurses.cc b/gptcurses.cc
index 2ec8a40..6002077 100644
--- a/gptcurses.cc
+++ b/gptcurses.cc
@@ -39,6 +39,7 @@ GPTDataCurses::GPTDataCurses(void) {
if (numInstances > 0) {
refresh();
} else {
+ setlocale( LC_ALL , "" );
initscr();
cbreak();
noecho();
@@ -318,7 +319,7 @@ void GPTDataCurses::DeletePartition(int partNum) {
void GPTDataCurses::ShowInfo(int partNum) {
uint64_t size;
#ifdef USE_UTF16
- char temp[NAME_SIZE / 2 + 1];
+ char temp[NAME_SIZE + 1];
#endif
clear();
@@ -335,7 +336,7 @@ void GPTDataCurses::ShowInfo(int partNum) {
printw("Partition size: %lld sectors (%s)\n", size, BytesToIeee(size, blockSize).c_str());
printw("Attribute flags: %016x\n", partitions[partNum].GetAttributes().GetAttributes());
#ifdef USE_UTF16
- partitions[partNum].GetDescription().extract(0, NAME_SIZE / 2, temp, NAME_SIZE / 2);
+ partitions[partNum].GetDescription().extract(0, NAME_SIZE , temp, NAME_SIZE );
printw("Partition name: '%s'\n", temp);
#else
printw("Partition name: '%s'\n", partitions[partNum].GetDescription().c_str());
@@ -345,21 +346,21 @@ void GPTDataCurses::ShowInfo(int partNum) {
// Prompt for and change a partition's name....
void GPTDataCurses::ChangeName(int partNum) {
- char temp[NAME_SIZE / 2 + 1];
+ char temp[NAME_SIZE + 1];
if (ValidPartNum(partNum)) {
move(LINES - 4, 0);
clrtobot();
move(LINES - 4, 0);
#ifdef USE_UTF16
- partitions[partNum].GetDescription().extract(0, NAME_SIZE / 2, temp, NAME_SIZE / 2);
+ partitions[partNum].GetDescription().extract(0, NAME_SIZE , temp, NAME_SIZE );
printw("Current partition name is '%s'\n", temp);
#else
printw("Current partition name is '%s'\n", partitions[partNum].GetDescription().c_str());
#endif
printw("Enter new partition name, or <Enter> to use the current name:\n");
echo();
- getnstr(temp, NAME_SIZE / 2);
+ getnstr(temp, NAME_SIZE );
partitions[partNum].SetName((string) temp);
noecho();
} // if
diff --git a/gptpart.cc b/gptpart.cc
index 2d609d6..7c61569 100644
--- a/gptpart.cc
+++ b/gptpart.cc
@@ -35,7 +35,7 @@ GPTPart::GPTPart(void) {
firstLBA = 0;
lastLBA = 0;
attributes = 0;
- memset(name, 0, NAME_SIZE);
+ memset(name, 0, NAME_SIZE * sizeof(name[0]) );
} // Default constructor
GPTPart::~GPTPart(void) {
@@ -52,11 +52,13 @@ string GPTPart::GetTypeName(void) {
return partitionType.TypeName();
} // GPTPart::GetNameType()
+#ifdef USE_UTF16
// Return a Unicode description of the partition type (e.g., "Linux/Windows
// data" or "Linux swap").
UnicodeString GPTPart::GetUTypeName(void) {
return partitionType.UTypeName();
} // GPTPart::GetNameType()
+#endif
// Compute and return the partition's length (or 0 if the end is incorrectly
// set before the beginning).
@@ -74,18 +76,61 @@ UnicodeString GPTPart::GetDescription(void) {
return (UChar*) name;
} // GPTPart::GetDescription()
#else
-// Return partition's name field, converted to a C++ ASCII string
+// Return partition's name field, converted to a C++ UTF-8 string
string GPTPart::GetDescription(void) {
- string theName;
- int i = 0;
-
- theName = "";
- while ((i < NAME_SIZE) && (name[i] != '\0')) {
- theName += name[i];
- i+=2;
- } // while
- return theName;
-} // GPTPart::GetDescription() (Windows version)
+ // convert name to utf32 then to utf8
+ string utf8 ;
+ size_t pos = 0 ;
+ while ( ( pos < NAME_SIZE ) && ( name[ pos ] != 0 ) ) {
+ uint16_t cp = name[ pos ++ ] ;
+ if ( ! IsLittleEndian() ) ReverseBytes( & cp , 2 ) ;
+ // first to utf32
+ uint32_t uni ;
+ if ( cp < 0xd800 || cp > 0xdfff ) {
+ uni = cp ;
+ } // if
+ else if ( cp < 0xdc00 ) {
+ // lead surrogate
+ uni = ( (uint32_t)( cp & 0x3ff ) ) << 10 ;
+ if ( pos >= NAME_SIZE ) {
+ // missing trail surrogate, name[] is invalid
+ break ;
+ } // if
+ cp = name[ pos ++ ] ;
+ if ( cp < 0xdc00 || cp > 0xdfff ) {
+ // invalid trail surrogate, name[] is invalid
+ break ;
+ } // if
+ // trail surrogate
+ uni |= cp & 0x3ff ;
+ uni += 0x10000 ;
+ } // if
+ else {
+ // unexpected trail surrogate, name[] is invalid
+ break ;
+ } // if
+ // then to utf8
+ if ( uni < 0x80 ) {
+ utf8 += (char) uni ;
+ } // if
+ else if ( uni < 0x800 ) {
+ utf8 += (char) ( 0xc0 | ( uni >> 6 ) ) ;
+ utf8 += (char) ( 0x80 | ( uni & 0x3f ) ) ;
+ } // if
+ else if ( uni < 0x10000 ) {
+ utf8 += (char) ( 0xe0 | ( uni >> 12 ) ) ;
+ utf8 += (char) ( 0x80 | ( ( uni >> 6 ) & 0x3f ) ) ;
+ utf8 += (char) ( 0x80 | ( uni & 0x3f ) ) ;
+ } // if
+ else {
+ utf8 += (char) ( 0xf0 | ( uni >> 18 ) ) ;
+ utf8 += (char) ( 0xe0 | ( ( uni >> 12 ) & 0x3f ) ) ;
+ utf8 += (char) ( 0x80 | ( ( uni >> 6 ) & 0x3f ) ) ;
+ utf8 += (char) ( 0x80 | ( uni & 0x3f ) ) ;
+ } // if
+ }
+ return utf8 ;
+} // GPTPart::GetDescription(), UTF-8 version
#endif
// Return 1 if the partition is in use
@@ -97,7 +142,11 @@ int GPTPart::IsUsed(void) {
// name *IF* the current name is the generic one for the current partition
// type.
void GPTPart::SetType(PartType t) {
+#ifdef USE_UTF16
if (GetDescription() == partitionType.UTypeName()) {
+#else
+ if (GetDescription() == partitionType.TypeName()) {
+#endif
SetName(t.TypeName());
} // if
partitionType = t;
@@ -116,8 +165,8 @@ void GPTPart::SetName(const UnicodeString & theName) {
if (theName.isBogus()) {
cerr << "Bogus UTF-16 name found in GPTPart::SetName()! Name not changed!\n";
} else {
- memset(name, 0, NAME_SIZE);
- theName.extractBetween(0, NAME_SIZE / 2 - 1, (UChar*) name);
+ memset(name, 0, NAME_SIZE * sizeof(name[0]) );
+ theName.extractBetween(0, NAME_SIZE, (UChar*) name);
} // if/else
} // GPTPart::SetName()
@@ -128,16 +177,73 @@ void GPTPart::SetName(const UnicodeString & theName) {
// requires a UTF-16LE string. This function creates a simple-minded copy
// for this.
void GPTPart::SetName(const string & theName) {
- int i, length;
-
- if (theName.length() < (NAME_SIZE / 2))
- length = theName.length();
- else
- length = NAME_SIZE / 2;
- memset(name, 0, NAME_SIZE);
- for (i = 0; i < length; i++)
- name[i * 2] = theName[i];
-} // GPTPart::SetName(), ASCII version
+ // convert utf8 to utf32 then to utf16le
+ size_t len = theName.length() ;
+ size_t pos = 0 ;
+ for ( size_t i = 0 ; pos < NAME_SIZE && i < len ; ) {
+ uint32_t uni ;
+ uint8_t cp = theName[ i ++ ] ;
+ int todo ;
+ if ( cp < 0x80 ) {
+ uni = cp ;
+ todo = 0 ;
+ } // if
+ else if ( cp < 0xc0 || cp > 0xf7 ) {
+ // invalid byte, theName is broken
+ break ;
+ } // if
+ else if ( cp < 0xe0 ) {
+ uni = cp & 0x1f ;
+ todo = 1 ;
+ } // if
+ else if ( cp < 0xf0 ) {
+ uni = cp & 0x0f ;
+ todo = 2 ;
+ } // if
+ else {
+ uni = cp & 0x7 ;
+ todo = 3 ;
+ } // if
+ while ( todo > 0 ) {
+ if ( i >= len ) {
+ // missing continuation byte, theName is broken
+ goto break_converter ;
+ } // if
+ cp = theName[ i ++ ] ;
+ if ( cp > 0xbf || cp < 0x80 ) {
+ // invalid continuation byte, theName is broken
+ goto break_converter ;
+ } // if
+ uni <<= 6 ;
+ uni |= cp & 0x3f ;
+ todo -- ;
+ } // while
+ // then to utf16le
+ if ( uni < 0x10000 ) {
+ name[ pos ] = (uint16_t) uni ;
+ if ( ! IsLittleEndian() ) ReverseBytes( name + pos , 2 ) ;
+ pos ++ ;
+ } // if
+ else {
+ if ( pos > NAME_SIZE - 2 ) {
+ // not enough room for two surrogates, truncate
+ break ;
+ } // if
+ uni -= 0x10000 ;
+ name[ pos ] = (uint16_t)( uni >> 10 ) | 0xd800 ;
+ if ( ! IsLittleEndian() ) ReverseBytes( name + pos , 2 ) ;
+ pos ++ ;
+ name[ pos ] = (uint16_t)( uni & 0x3ff ) | 0xdc00 ;
+ if ( ! IsLittleEndian() ) ReverseBytes( name + pos , 2 ) ;
+ pos ++ ;
+ }
+ } // for
+ break_converter : ;
+ // finally fill with zeroes
+ while ( pos < NAME_SIZE ) {
+ name[ pos ++ ] = 0 ;
+ } // while
+} // GPTPart::SetName(), UTF-8 version
#endif
// Set the name for the partition based on the current GUID partition type
@@ -152,7 +258,7 @@ GPTPart & GPTPart::operator=(const GPTPart & orig) {
firstLBA = orig.firstLBA;
lastLBA = orig.lastLBA;
attributes = orig.attributes;
- memcpy(name, orig.name, NAME_SIZE);
+ memcpy(name, orig.name, NAME_SIZE * sizeof( name[ 0 ] ) );
return *this;
} // assignment operator
@@ -196,7 +302,44 @@ void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
GetDescription().extractBetween(0, 23, description);
cout << description << "\n";
#else
- cout << GetDescription().substr(0, 23) << "\n";
+ string desc = GetDescription() ;
+ size_t n = 0 ;
+ size_t i = 0 ;
+ size_t len = desc.length() ;
+ while ( n < 22 && i < len ) {
+ i ++ ;
+ if ( i >= len ) {
+ // short description
+ break ;
+ } // if
+ // skip continuation bytes
+ while ( i < len && ( ( desc[ i ] & 0xC0 ) == 0x80 ) ) {
+ // utf8 continuation byte
+ i ++ ;
+ } // while
+ n ++ ;
+ } // while
+ if ( i < len ) {
+ n = 0 ;
+ i = 0 ;
+ // description is long we will truncate it
+ while ( n < 19 && i < len ) {
+ i ++ ;
+ if ( i >= len ) {
+ // should not happen
+ break ;
+ } // if
+ // skip continuation bytes
+ while ( i < len && ( ( desc[ i ] & 0xC0 ) == 0x80 ) ) {
+ // utf8 continuation byte
+ i ++ ;
+ } // while
+ n ++ ;
+ } // while
+ } // for
+ cout << GetDescription().substr( 0 , i ) ;
+ if ( i < len ) cout << "..." ;
+ cout << "\n";
#endif
cout.fill(' ');
} // if
@@ -237,7 +380,7 @@ void GPTPart::BlankPartition(void) {
firstLBA = 0;
lastLBA = 0;
attributes = 0;
- memset(name, 0, NAME_SIZE);
+ memset(name, 0, NAME_SIZE * sizeof( name[0]) );
} // GPTPart::BlankPartition
// Returns 1 if the two partitions overlap, 0 if they don't
@@ -256,7 +399,7 @@ void GPTPart::ReversePartBytes(void) {
ReverseBytes(&firstLBA, 8);
ReverseBytes(&lastLBA, 8);
ReverseBytes(&attributes, 8);
- for (i = 0; i < NAME_SIZE; i += 2)
+ for (i = 0; i < NAME_SIZE; i ++ )
ReverseBytes(name + i, 2);
} // GPTPart::ReverseBytes()
@@ -271,7 +414,11 @@ void GPTPart::ChangeType(void) {
int changeName;
PartType tempType = (GUIDData) "00000000-0000-0000-0000-000000000000";
+#ifdef USE_UTF16
changeName = (GetDescription() == GetUTypeName());
+#else
+ changeName = (GetDescription() == GetTypeName());
+#endif
cout << "Current type is '" << GetTypeName() << "'\n";
do {
diff --git a/gptpart.h b/gptpart.h
index cdfce2a..67cba6b 100644
--- a/gptpart.h
+++ b/gptpart.h
@@ -45,7 +45,7 @@ class GPTPart {
uint64_t firstLBA;
uint64_t lastLBA;
Attributes attributes;
- unsigned char name[NAME_SIZE];
+ uint16_t name[NAME_SIZE];
public:
GPTPart(void);
~GPTPart(void);
diff --git a/gpttext.cc b/gpttext.cc
index f91b8e4..95ba850 100644
--- a/gpttext.cc
+++ b/gpttext.cc
@@ -309,7 +309,11 @@ int GPTDataTextUI::SetName(uint32_t partNum) {
if (IsUsedPartNum(partNum)) {
cout << "Enter name: ";
+#ifdef USE_UTF16
theName = ReadUString();
+#else
+ theName = ReadString();
+#endif
partitions[partNum].SetName(theName);
} else {
cerr << "Invalid partition number (" << partNum << ")\n";
@@ -412,7 +416,7 @@ void GPTDataTextUI::MakeHybrid(void) {
cout << "Type from one to three GPT partition numbers, separated by spaces, to be\n"
<< "added to the hybrid MBR, in sequence: ";
line = ReadString();
- numPartsToCvt = sscanf(line.c_str(), "%d %d %d", &partNums[0], &partNums[1], &partNums[2]);
+ numPartsToCvt = sscanf(line.c_str(), "%ud %ud %ud", &partNums[0], &partNums[1], &partNums[2]);
if (numPartsToCvt > 0) {
cout << "Place EFI GPT (0xEE) partition first in MBR (good for GRUB)? ";
@@ -854,7 +858,7 @@ void GPTDataTextUI::ShowExpertCommands(void) {
cout << "r\trecovery and transformation options (experts only)\n";
cout << "s\tresize partition table\n";
cout << "t\ttranspose two partition table entries\n";
- cout << "u\tReplicate partition table on new device\n";
+ cout << "u\treplicate partition table on new device\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";
@@ -894,6 +898,7 @@ int GetMBRTypeCode(int defType) {
return typeCode;
} // GetMBRTypeCode
+#ifdef USE_UTF16
// Note: ReadUString() is here rather than in support.cc so that the ICU
// libraries need not be linked to fixparts.
@@ -904,4 +909,5 @@ int GetMBRTypeCode(int defType) {
UnicodeString ReadUString(void) {
return ReadString().c_str();
} // ReadUString()
+#endif
diff --git a/guid.cc b/guid.cc
index 6abc16e..1e73ab7 100644
--- a/guid.cc
+++ b/guid.cc
@@ -24,8 +24,13 @@
using namespace std;
+bool GUIDData::firstInstance = 1;
+
GUIDData::GUIDData(void) {
- srand((unsigned int) time(0));
+ if (firstInstance) {
+ srand((unsigned int) time(0));
+ firstInstance = 0;
+ } // if
Zero();
} // constructor
diff --git a/guid.h b/guid.h
index 6eb6ebf..229d5bd 100644
--- a/guid.h
+++ b/guid.h
@@ -35,6 +35,8 @@ using namespace std;
// Note: This class's data size is critical. If data elements must be added,
// it will be necessary to modify various GPT classes to compensate.
class GUIDData {
+ private:
+ static bool firstInstance;
protected:
my_uuid_t uuidData;
string DeleteSpaces(string s);
diff --git a/parttypes.cc b/parttypes.cc
index e624e54..441508a 100644
--- a/parttypes.cc
+++ b/parttypes.cc
@@ -315,6 +315,7 @@ string PartType::TypeName(void) const {
return typeName;
} // PartType::TypeName()
+#ifdef USE_UTF16
// Return the Unicode description of the partition type (e.g., "Linux filesystem")
UnicodeString PartType::UTypeName(void) const {
AType* theItem = allTypes;
@@ -334,6 +335,7 @@ UnicodeString PartType::UTypeName(void) const {
} // if (!found)
return typeName;
} // PartType::TypeName()
+#endif
// Return the custom GPT fdisk 2-byte (16-bit) hex code for this GUID partition type
// Note that this function ignores entries for which the display variable
diff --git a/sgdisk.8 b/sgdisk.8
index 964fecc..4fb6507 100644
--- a/sgdisk.8
+++ b/sgdisk.8
@@ -1,6 +1,6 @@
.\" Copyright 2011-2013 Roderick W. Smith (rodsmith@rodsbooks.com)
.\" May be distributed under the GNU General Public License
-.TH "SGDISK" "8" "0.8.8" "Roderick W. Smith" "GPT fdisk Manual"
+.TH "SGDISK" "8" "0.8.9" "Roderick W. Smith" "GPT fdisk Manual"
.SH "NAME"
sgdisk \- Command\-line GUID partition table (GPT) manipulator for Linux and Unix
.SH "SYNOPSIS"
@@ -490,7 +490,7 @@ sgdisk, but may with gdisk)
Disk replication operation (-R) failed
.SH "BUGS"
-As of October 2013 (version 0.8.8), \fBsgdisk\fR
+As of February 2014 (version 0.8.9), \fBsgdisk\fR
should be considered beta software. Known bugs and limitations include:
.TP
diff --git a/support.cc b/support.cc
index d795440..dbcfa00 100644
--- a/support.cc
+++ b/support.cc
@@ -77,8 +77,11 @@ int GetNumber(int low, int high, int def, const string & prompt) {
char GetYN(void) {
char response;
string line;
+ bool again = 0 ;
do {
+ if ( again ) { cout << "Your option? " ; }
+ again = 1 ;
cout << "(Y/N): ";
line = ReadString();
response = toupper(line[0]);
diff --git a/support.h b/support.h
index 89ad8f1..9f00846 100644
--- a/support.h
+++ b/support.h
@@ -8,7 +8,7 @@
#ifndef __GPTSUPPORT
#define __GPTSUPPORT
-#define GPTFDISK_VERSION "0.8.8.4"
+#define GPTFDISK_VERSION "0.8.9"
#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__)
// Darwin (Mac OS) & FreeBSD: disk IOCTLs are different, and there is no lseek64
@@ -67,7 +67,7 @@
#define GPT_SIZE 128
#define HEADER_SIZE UINT32_C(92)
#define GPT_RESERVED 420
-#define NAME_SIZE 72
+#define NAME_SIZE 36 // GPT allows 36 UTF-16LE code units for a name in a 128 byte partition entry
using namespace std;