diff options
-rw-r--r-- | Makefile.freebsd | 4 | ||||
-rw-r--r-- | NEWS | 17 | ||||
-rw-r--r-- | README | 24 | ||||
-rw-r--r-- | README.Windows | 18 | ||||
-rw-r--r-- | attributes.cc | 2 | ||||
-rw-r--r-- | basicmbr.cc | 60 | ||||
-rw-r--r-- | basicmbr.h | 5 | ||||
-rw-r--r-- | current.spec | 8 | ||||
-rw-r--r-- | diskio-windows.cc | 7 | ||||
-rw-r--r-- | fixparts.8 | 4 | ||||
-rw-r--r-- | fixparts.cc | 106 | ||||
-rw-r--r-- | gdisk.8 | 26 | ||||
-rw-r--r-- | gpt.cc | 9 | ||||
-rw-r--r-- | gpt.h | 2 | ||||
-rw-r--r-- | gptpart.cc | 106 | ||||
-rw-r--r-- | gptpart.h | 8 | ||||
-rw-r--r-- | gpttext.cc | 57 | ||||
-rw-r--r-- | gpttext.h | 4 | ||||
-rw-r--r-- | guid.cc | 2 | ||||
-rw-r--r-- | mbr.cc | 10 | ||||
-rw-r--r-- | mbr.h | 1 | ||||
-rw-r--r-- | mbrpart.cc | 2 | ||||
-rw-r--r-- | parttypes.cc | 26 | ||||
-rw-r--r-- | parttypes.h | 7 | ||||
-rw-r--r-- | sgdisk.8 | 15 | ||||
-rw-r--r-- | sgdisk.cc | 5 | ||||
-rw-r--r-- | support.h | 2 |
27 files changed, 270 insertions, 267 deletions
diff --git a/Makefile.freebsd b/Makefile.freebsd index 92dcb0b..783dd7d 100644 --- a/Makefile.freebsd +++ b/Makefile.freebsd @@ -13,10 +13,10 @@ DEPEND= makedepend $(CXXFLAGS) all: gdisk sgdisk fixparts gdisk: $(LIB_OBJS) gdisk.o gpttext.o - $(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 sgdisk: $(LIB_OBJS) sgdisk.o - $(CXX) $(LIB_OBJS) sgdisk.o -L/usr/local/lib $(LDFLAGS) -luuid -lpopt -o sgdisk + $(CXX) $(LIB_OBJS) sgdisk.o -L/usr/local/lib $(LDFLAGS) -luuid -licuio -lpopt -o sgdisk fixparts: $(MBR_LIB_OBJS) fixparts.o $(CXX) $(MBR_LIB_OBJS) fixparts.o -L/usr/local/lib $(LDFLAGS) -o fixparts @@ -1,5 +1,18 @@ -0.7.1 (?/?/2011): ------------------ +0.7.1 (3/21/2011): +------------------ + +- Added support for proper UTF-16LE partition names rather than the + "shortcut" that properly encoded only ASCII names. This support works + only in Linux, FreeBSD, and OS X, though, at least for the moment. + Although it's possible to compile this support into Windows when using + Visual C++, it doesn't seem to work properly. Since using this feature + would require distributing the ICU libraries with the Windows binary, + thus bloating the binary package's size to no effect, I've disabled it in + my standard Windows build, at least for now. + +- Added check to fixparts to keep it from operating on devices that + lack an existing MBR signature. (In 0.7.0, it could write an empty + MBR data structure to a device on which it was mistakenly launched.) - Fixed bug that caused the protective MBR to not be written when restoring a backup of the GPT data. @@ -4,8 +4,8 @@ by Roderick W. Smith, rodsmith@rodsbooks.com Introduction ------------ -This binary archive includes the source code for three related disk -partitioning programs: +This package includes the source code for three related disk partitioning +programs: - gdisk -- This program is modeled after Linux fdisk, but it operates on GUID Partition Table (GPT) disks rather than the Master Boot Record (MBR) @@ -62,8 +62,7 @@ and sgdisk include: * A user interface that's familiar to long-time users of Linux fdisk (gdisk only) -* The MBR boot loader code is left alone (GNU Parted tends to - wipe it out with every change) +* The MBR boot loader code is left alone * The ability to create a hybrid MBR, which permits GPT-unaware OSes to access up to three GPT partitions on the disk @@ -95,7 +94,7 @@ that the OS sees. I've observed four causes of these symptoms, three of which FixParts can correct: -- Old GPT data -- If a disk is used as a GPT disk and then re-used as an +* Old GPT data -- If a disk is used as a GPT disk and then re-used as an MBR disk, the GPT data may be incompletely erased. This happens if the disk is repartitioned with fdisk or the Microsoft Windows installer, for instance. (Tools based on libparted correctly remove the old GPT data @@ -104,12 +103,12 @@ correct: data, this erasure occurs immediately, unlike other changes the program makes. -- Mis-sized extended partitions -- Some tools create an extended partition +* Mis-sized extended partitions -- Some tools create an extended partition that's too large, typically ending after the last sector of the disk. FixParts automatically corrects this problem (if you use the 'w' option to save the partition table). -- Primary partitions inside an extended partition -- Some utilities create +* Primary partitions inside an extended partition -- Some utilities create or move primary partitions to within the range covered by the extended partition. FixParts can usually correct this problem by turning the primary partition into a logical partition or by changing one or more @@ -117,7 +116,7 @@ correct: possible, though, at least not without deleting or resizing other partitions. -- Leftover RAID data -- If a disk is used in a RAID array and then re-used +* Leftover RAID data -- If a disk is used in a RAID array and then re-used as a non-RAID disk, some utilities can become confused and fail to see the disk. FixParts can NOT correct this problem. You must destroy the old RAID data, or possibly remove the dmraid package from the system, to fix @@ -130,7 +129,7 @@ omitting it), you can't create new partitions with the program. If you're used to partitioning disks, particularly with Linux fdisk, two unusual features of FixParts require elaboration: -- No extended partitions -- Internally, FixParts reads the partition table +* No extended partitions -- Internally, FixParts reads the partition table and discards data on any extended partition(s) it finds. When you save the partition table, the program generates a new extended partition. This design means that the program automatically corrects many problems @@ -139,7 +138,7 @@ features of FixParts require elaboration: it keeps track of the requirements and prevents you from creating illegal layouts, such as a primary between two logicals. -- Partition numbering -- In most Linux tools, partitions 1-4 are primaries +* Partition numbering -- In most Linux tools, partitions 1-4 are primaries and partitions 5 and up are logicals. Although a legal partition table loaded into FixParts will initially conform to this convention, some types of damaged table might not, and various changes you make can also @@ -162,8 +161,9 @@ used.) In addition, note these requirements: e2fsprogs-libuuid port must be installed. * The ICU library (http://site.icu-project.org) is required on all - platforms. This library is normally installed in Linux, but you may need - to install the development headers (libicu-dev or something similar). + platforms except Windows. This library is normally installed in Linux, + but you may need to install the development headers (libicu-dev or + something similar). * The sgdisk program also requires the popt library and its development files (headers). Most Linux distributions install popt by default, but diff --git a/README.Windows b/README.Windows index fa57484..3194838 100644 --- a/README.Windows +++ b/README.Windows @@ -88,10 +88,19 @@ for disks and partitions, not to the GUIDs used to identify partition type codes; those are standardized and are handled correctly by all versions of
GPT fdisk.
+The Windows binaries I've compiled do not support Unicode UTF-16LE GPT
+partition names. This feature was added to version 0.7.1 of the software
+for Linux, FreeBSD, and OS X, and with changes to some #ifndef lines in the
+source files, it can be compiled for Windows; however, it seems to do
+little good in Windows because of Command Prompt window and/or ICU library
+limitations. Thus, I've omitted this support in the interests of
+simplifying the binary distribution, since including it would mean
+distributing the ICU libraries.
+
Source Code and Compilation Issues
----------------------------------
-I have successfully compiled GPT fdisk using two different Windows
+I have successfully compiled GPT fdisk using three different Windows
compilers:
- MinGW (http://www.mingw.org), and in particular its Linux-hosted
@@ -109,8 +118,11 @@ compilers: all the *.cc files except diskio-unix.cc, sgdisk.cc, and whichever
program file you intend to NOT build (gdisk.cc or fixparts.cc).
-The MinGW compiler produces much larger executables than does the MS
-compiler. The resulting binaries seem to work equally well, but my testing
+- Microsoft Visual C++ 2010 Express -- This compiler works much like the
+ 2008 version, although I didn't need to add a third-party stdint.h file.
+
+The MinGW compiler produces much larger executables than do the MS
+compilers. The resulting binaries seem to work equally well, but my testing
has been minimal.
I've also attempted to compile the code with OpenWatcom 1.8, but this
diff --git a/attributes.cc b/attributes.cc index 0abed40..45de56e 100644 --- a/attributes.cc +++ b/attributes.cc @@ -223,4 +223,4 @@ bool Attributes::OperateOnAttributes(const uint32_t partNum, const string& attri ostream & operator<<(ostream & os, const Attributes & data) { os << data.GetAttributes(); return os; -} // operator<<()
\ No newline at end of file +} // operator<<() diff --git a/basicmbr.cc b/basicmbr.cc index 4f2fa34..12ec92b 100644 --- a/basicmbr.cc +++ b/basicmbr.cc @@ -874,7 +874,6 @@ int BasicMBRData::SpaceBeforeAllLogicals(void) { do { if ((partitions[i].GetStartLBA() > 0) && (partitions[i].GetInclusion() == LOGICAL)) { allOK = allOK && (SectorUsedAs(partitions[i].GetStartLBA() - 1) == EBR); -// allOK = allOK && IsFree(partitions[i].GetStartLBA() - 1); } // if i++; } while (allOK && (i < MAX_MBR_PARTS)); @@ -1080,37 +1079,12 @@ int BasicMBRData::SetInclusionwChecks(int num, int inclStatus) { // providing a function to do this deliberately at the user's command. // This function does nothing if the partition's length is 0. void BasicMBRData::RecomputeCHS(int partNum) { -// uint64_t firstLBA, lengthLBA; - partitions[partNum].RecomputeCHS(); -/* firstLBA = (uint64_t) partitions[partNum].firstLBA; - lengthLBA = (uint64_t) partitions[partNum].lengthLBA; - - if (lengthLBA > 0) { - LBAtoCHS(firstLBA, partitions[partNum].firstSector); - LBAtoCHS(firstLBA + lengthLBA - 1, partitions[partNum].lastSector); - } // if */ } // BasicMBRData::RecomputeCHS() -// Swap the contents of two partitions. -// Returns 1 if successful, 0 if either partition is out of range -// (that is, not a legal number; either or both can be empty). -// Note that if partNum1 = partNum2 and this number is in range, -// it will be considered successful. -int BasicMBRData::SwapPartitions(uint32_t partNum1, uint32_t partNum2) { - MBRPart temp; - int allOK = 1; - - if ((partNum1 < MAX_MBR_PARTS) && (partNum2 < MAX_MBR_PARTS)) { - if (partNum1 != partNum2) { - temp = partitions[partNum1]; - partitions[partNum1] = partitions[partNum2]; - partitions[partNum2] = temp; - } // if - } else allOK = 0; // partition numbers are valid - return allOK; -} // BasicMBRData::SwapPartitions() - +// Sorts the partitions starting with partition #start. This function +// does NOT pay attention to primary/logical assignment, which is +// critical when writing the partitions. void BasicMBRData::SortMBR(int start) { if ((start < MAX_MBR_PARTS) && (start >= 0)) sort(partitions + start, partitions + MAX_MBR_PARTS); @@ -1167,15 +1141,6 @@ void BasicMBRData::OmitOverlaps() { } // for (i...) } // BasicMBRData::OmitOverlaps() -/* // Omits all partitions; used as starting point in MakeItLegal() -void BasicMBRData::OmitAll(void) { - int i; - - for (i = 0; i < MAX_MBR_PARTS; i++) { - partitions[i].SetInclusion(NONE); - } // for -} // BasicMBRData::OmitAll() */ - // Convert as many partitions into logicals as possible, except for // the first partition, if possible. void BasicMBRData::MaximizeLogicals() { @@ -1206,8 +1171,8 @@ void BasicMBRData::MaximizePrimaries() { while ((num < 4) && (i < MAX_MBR_PARTS)) { if ((partitions[i].GetInclusion() == NONE) && (partitions[i].CanBePrimary())) { partitions[i].SetInclusion(PRIMARY); - num++; - UpdateCanBeLogical(); + num++; + UpdateCanBeLogical(); } // if i++; } // while @@ -1254,7 +1219,6 @@ void BasicMBRData::MakeLogicalsContiguous(void) { void BasicMBRData::MakeItLegal(void) { if (!IsLegal()) { DeleteOversizedParts(); -// OmitAll(); MaximizeLogicals(); MaximizePrimaries(); if (!AreLogicalsContiguous()) @@ -1406,6 +1370,7 @@ uint64_t BasicMBRData::FindLastInFree(uint64_t start) { nearestStart = diskSize - 1; else nearestStart = UINT32_MAX - 1; + for (i = 0; i < 4; i++) { if ((nearestStart > partitions[i].GetStartLBA()) && (partitions[i].GetStartLBA() > start)) { @@ -1449,19 +1414,6 @@ int BasicMBRData::SectorUsedAs(uint64_t sector, int topPartNum) { return usedAs; } // BasicMBRData::SectorUsedAs() -/* // Returns 1 if the specified sector is unallocated, 0 if it's -// allocated. -int BasicMBRData::IsFree(uint64_t sector, int topPartNum) { - int i, isFree = 1; - - for (i = 0; i < topPartNum; i++) { - if ((partitions[i].GetStartLBA() <= sector) && (partitions[i].GetLastLBA() >= sector) - && (partitions[i].GetInclusion() != NONE)) - isFree = 0; - } // for - return isFree; -} // BasicMBRData::IsFree() */ - /****************************************************** * * * Functions that extract data on specific partitions * @@ -123,9 +123,7 @@ public: void DeletePartition(int i); int SetInclusionwChecks(int num, int inclStatus); void RecomputeCHS(int partNum); - int SwapPartitions(uint32_t partNum1, uint32_t partNum2); void SortMBR(int start = 0); -// void QuickSortMBR(int start, int finish); int DeleteOversizedParts(); int DeleteExtendedParts(); void OmitOverlaps(void); @@ -153,7 +151,6 @@ public: // User interaction functions.... int DoMenu(const string& prompt = "\nMBR command (? for help): "); void ShowCommands(void); - -}; // struct BasicMBRData +}; // class BasicMBRData #endif diff --git a/current.spec b/current.spec index 3ae7f6c..b0fa691 100644 --- a/current.spec +++ b/current.spec @@ -1,11 +1,11 @@ Summary: GPT partitioning and MBR repair software Name: gptfdisk -Version: 0.7.0 +Version: 0.7.1 Release: 1%{?dist} License: GPLv2 URL: http://www.rodsbooks.com/gdisk Group: Applications/System -Source: http://www.rodsbooks.com/gdisk/gptfdisk-0.7.0.tgz +Source: http://www.rodsbooks.com/gdisk/gptfdisk-0.7.1.tgz BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) %description @@ -77,5 +77,5 @@ provides a few additional partition manipulation features. %changelog -* Fri Mar 11 2011 R Smith <rodsmith@rodsbooks.com> - 0.7.0 -- Created spec file for 0.7.0 release +* Mon Mar 21 2011 R Smith <rodsmith@rodsbooks.com> - 0.7.1 +- Created spec file for 0.7.1 release diff --git a/diskio-windows.cc b/diskio-windows.cc index b79884c..938d7ec 100644 --- a/diskio-windows.cc +++ b/diskio-windows.cc @@ -133,11 +133,12 @@ int DiskIO::GetBlockSize(void) { } // if if (isOpen) { - if (DeviceIoControl(fd, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &geom, sizeof(geom), &retBytes, NULL)) { + if (DeviceIoControl(fd, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, + &geom, sizeof(geom), &retBytes, NULL)) { blockSize = geom.Geometry.BytesPerSector; - } else { // was probably an ordinary file; set default value.... + } else { // was probably an ordinary file; set default value.... blockSize = SECTOR_SIZE; - } // if/else + } // if/else } // if (isOpen) return (blockSize); @@ -1,6 +1,6 @@ .\" Copyright 2011 Roderick W. Smith (rodsmith@rodsbooks.com) .\" May be distributed under the GNU General Public License -.TH "FIXPARTS" "8" "0.7.0" "Roderick W. Smith" "FixParts Manual" +.TH "FIXPARTS" "8" "0.7.1" "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 March 2011 (version 0.7.0), \fBfixparts\fR +As of March 2011 (version 0.7.1), \fBfixparts\fR should be considered beta software. Known bugs and limitations include: .TP diff --git a/fixparts.cc b/fixparts.cc index 8a7c7d0..318c65e 100644 --- a/fixparts.cc +++ b/fixparts.cc @@ -20,11 +20,14 @@ using namespace std; +void DoMBR(BasicMBRData & mbrTable); + int main(int argc, char* argv[]) { BasicMBRData mbrTable; string device; - int doItAgain; + cout << "FixParts " << GPTFDISK_VERSION << "\n"; + switch (argc) { case 1: cout << "Type device filename, or press <Enter> to exit: "; @@ -40,41 +43,72 @@ int main(int argc, char* argv[]) { exit(1); } // switch - cout << "FixParts " << GPTFDISK_VERSION << "\n"; cout << "\nLoading MBR data from " << device << "\n"; - if (mbrTable.ReadMBRData(device)) { - if (mbrTable.CheckForGPT() > 0) { - if ((mbrTable.GetValidity() == hybrid) || (mbrTable.GetValidity() == gpt)) { - cerr << "\nThis disk appears to be a GPT disk. Use GNU Parted or GPT fdisk on it!\n"; - cerr << "Exiting!\n\n"; - exit(1); - } else { - cout << "\nNOTICE: GPT signatures detected on the disk, but no 0xEE protective " - << "partition!\nThe GPT signatures are probably left over from a previous " - << "partition table.\nDo you want to delete them (if you answer 'Y', this " - << "will happen\nimmediately)? "; - if (GetYN() == 'Y') { - cout << "Erasing GPT data!\n"; - if (mbrTable.BlankGPTData() != 1) - cerr << "GPT signature erasure failed!\n"; - } // if - } // if/else - } // if - mbrTable.MakeItLegal(); - do { - doItAgain = 0; - if (mbrTable.DoMenu() > 0) { - cout << "\nFinal checks complete. About to write MBR data. THIS WILL OVERWRITE EXISTING\n" - << "PARTITIONS!!\n\nDo you want to proceed? "; - if (GetYN() == 'Y') { - mbrTable.WriteMBRData(); - mbrTable.DiskSync(); - doItAgain = 0; - } else { - doItAgain = 1; - } // else - } // if - } while (doItAgain); - } // if read OK + if (!mbrTable.ReadMBRData(device)) { + cerr << "\nUnable to read MBR data from '" << device << "'! Exiting!\n\n"; + exit(1); + } // if + + // This switch() statement weeds out disks with GPT signatures and non-MBR + // disks so we don't accidentally damage them.... + switch(mbrTable.GetValidity()) { + case hybrid: case gpt: + cerr << "\nThis disk appears to be a GPT disk. Use GNU Parted or GPT fdisk on it!\n"; + cerr << "Exiting!\n\n"; + exit(1); + break; + case invalid: + cerr << "\nCannot find valid MBR data on '" << device << "'! Exiting!\n\n"; + exit(1); + break; + case mbr: + DoMBR(mbrTable); + break; + default: + cerr << "\nCannot determine the validity of the disk on '" << device + << "'! Exiting!\n\n"; + exit(1); + break; + } // switch() return 0; } // main() + +// Do the bulk of the processing on actual MBR disks. First checks for old +// GPT data (note this is different from the earlier check; this one only +// looks for the GPT signatures in the main and backup GPT area, not for +// a protective partition in the MBR, which we know is NOT present, since +// if it were, this function would NOT be called!) and offers to destroy +// it, if found; then makes sure the partitions are in a consistent and +// legal state; then presents the MBR menu and, if it returns a "1" value +// (meaning the user opted to write changes), writes the table to disk. +void DoMBR(BasicMBRData & mbrTable) { + int doItAgain; + + if (mbrTable.CheckForGPT() > 0) { + cout << "\nNOTICE: GPT signatures detected on the disk, but no 0xEE protective " + << "partition!\nThe GPT signatures are probably left over from a previous " + << "partition table.\nDo you want to delete them (if you answer 'Y', this " + << "will happen\nimmediately)? "; + if (GetYN() == 'Y') { + cout << "Erasing GPT data!\n"; + if (mbrTable.BlankGPTData() != 1) + cerr << "GPT signature erasure failed!\n"; + } // if + } // if + + mbrTable.MakeItLegal(); + do { + doItAgain = 0; + if (mbrTable.DoMenu() > 0) { + cout << "\nFinal checks complete. About to write MBR data. THIS WILL OVERWRITE " + << "EXISTING\nPARTITIONS!!\n\nDo you want to proceed? "; + if (GetYN() == 'Y') { + mbrTable.WriteMBRData(); + mbrTable.DiskSync(); + doItAgain = 0; + } else { + doItAgain = 1; + } // else + } // if + } while (doItAgain); +} // DoMBR() @@ -1,6 +1,6 @@ .\" Copyright 2011 Roderick W. Smith (rodsmith@rodsbooks.com) .\" May be distributed under the GNU General Public License -.TH "GDISK" "8" "0.7.0" "Roderick W. Smith" "GPT fdisk Manual" +.TH "GDISK" "8" "0.7.1" "Roderick W. Smith" "GPT fdisk Manual" .SH "NAME" gdisk \- Interactive GUID partition table (GPT) manipulator .SH "SYNOPSIS" @@ -152,12 +152,12 @@ to encourage its use. .TP .B c Change the GPT name of a partition. This name is encoded as a UTF\-16 -string, but \fBgdisk\fR -supports only ASCII characters as names. For the most part, Linux ignores -the partition name, but it may be important in some OSes. GPT fdisk sets -a default name based on the partition type code. Note that the GPT partition -name is different from the filesystem name, which is encoded in the filesystem's -data structures. +string, but proper entry and display of anything beyond basic ASCII values +requires suitable locale and font support. For the most part, Linux ignores +the partition name, but it may be important in some OSes. GPT fdisk sets a +default name based on the partition type code. Note that the GPT partition +name is different from the filesystem name, which is encoded in the +filesystem's data structures. .TP .B d @@ -561,7 +561,7 @@ entering data. When only one option is possible, \fBgdisk\fR usually bypasses the prompt entirely. .SH "BUGS" -As of March 2011 (version 0.7.0), \fBgdisk\fR +As of March 2011 (version 0.7.1), \fBgdisk\fR should be considered beta software. Known bugs and limitations include: .TP @@ -590,10 +590,12 @@ alignment. .TP .B * -Only ASCII characters are supported in the partition name field. If an -existing partition uses non\-ASCII UTF\-16 characters, they're likely to be -corrupted in the 'i' and 'p' menu options' displays; however, they should be -preserved when loading and saving partitions. +In the Windows version, only ASCII characters are supported in the +partition name field. If an existing partition uses non\-ASCII UTF\-16 +characters, they're likely to be corrupted in the 'i' and 'p' menu options' +displays; however, they should be preserved when loading and saving +partitions. Binaries for Linux, FreeBSD, and OS X support full UTF-16 +partition names. .TP .B * @@ -1057,6 +1057,7 @@ int GPTData::SaveGPTBackup(const string & filename) { RecomputeCRCs(); protectiveMBR.WriteMBRData(&backupFile); + protectiveMBR.SetDisk(&myDisk); if (allOK) { // MBR write closed disk, so re-open and seek to end.... @@ -1768,12 +1769,16 @@ void GPTData::MoveSecondHeaderToEnd() { secondHeader.partitionEntriesLBA = secondHeader.lastUsableLBA + UINT64_C(1); } // GPTData::FixSecondHeaderLocation() +// Sets the partition's name to the specified UnicodeString without +// user interaction. +// Returns 1 on success, 0 on failure (invalid partition number). int GPTData::SetName(uint32_t partNum, const UnicodeString & theName) { int retval = 1; - if (!IsFreePartNum(partNum)) { + if (IsUsedPartNum(partNum)) partitions[partNum].SetName(theName); - } else retval = 0; + else + retval = 0; return retval; } // GPTData::SetName @@ -150,7 +150,7 @@ public: int SwapPartitions(uint32_t partNum1, uint32_t partNum2); int ClearGPTData(void); void MoveSecondHeaderToEnd(); - int SetName(uint32_t partNum, const UnicodeString & theName = ""); + int SetName(uint32_t partNum, const UnicodeString & theName); void SetDiskGUID(GUIDData newGUID); int SetPartitionGUID(uint32_t pn, GUIDData theGUID); void RandomizeGUIDs(void); @@ -4,7 +4,7 @@ // Description: Class to implement a SINGLE GPT partition // // -// Author: Rod Smith <rodsmith@rodsbooks.com>, (C) 2009 +// Author: Rod Smith <rodsmith@rodsbooks.com>, (C) 2009-2011 // // Copyright: See COPYING file that comes with this distribution // @@ -15,9 +15,14 @@ #define __STDC_LIMIT_MACROS #define __STDC_CONSTANT_MACROS +#ifndef _WIN32 +#include <unicode/ustdio.h> +#else +#define UnicodeString string +#endif + #include <string.h> #include <stdio.h> -#include <unicode/ustdio.h> #include <iostream> #include "gptpart.h" #include "attributes.h" @@ -51,10 +56,6 @@ string GPTPart::GetTypeName(void) { // data" or "Linux swap"). UnicodeString GPTPart::GetUTypeName(void) { return partitionType.UTypeName(); -/* UnicodeString temp; - - temp = temp.fromUTF8(partitionType.TypeName()); - return temp; */ } // GPTPart::GetNameType() // Compute and return the partition's length (or 0 if the end is incorrectly @@ -67,7 +68,13 @@ uint64_t GPTPart::GetLengthLBA(void) const { return length; } // GPTPart::GetLengthLBA() -/* // Return partition's name field, converted to a C++ ASCII string +#ifndef _WIN32 +// Return partition's name field, converted to a Unicode string +UnicodeString GPTPart::GetDescription(void) { + return (UChar*) name; +} // GPTPart::GetDescription() +#else +// Return partition's name field, converted to a C++ ASCII string string GPTPart::GetDescription(void) { string theName; int i; @@ -78,21 +85,8 @@ string GPTPart::GetDescription(void) { theName += name[i]; } // for return theName; -} // GPTPart::GetDescription() */ - -UnicodeString GPTPart::GetDescription(void) { - UnicodeString theName; - UChar *temp; - int i; - - theName = ""; - temp = (UChar*) name; - for (i = 0; i < NAME_SIZE / 2; i++) { - if (temp[i] != '\0') - theName += temp[i]; - } // for - return theName; -} // GPTPart::GetDescription() +} // GPTPart::GetDescription() (Windows version) +#endif // Return 1 if the partition is in use int GPTPart::IsUsed(void) { @@ -109,33 +103,40 @@ void GPTPart::SetType(PartType t) { partitionType = t; } // GPTPart::SetType() -// Set the name for a partition to theName, or prompt for a name if -// theName is empty, using a C++-style string as input. -void GPTPart::SetName(string theName) { - UnicodeString uString; - - uString = theName.c_str(); - SetName(uString); +#ifndef _WIN32 +// Set the name for a partition to theName, using a C++-style string as +// input. +void GPTPart::SetName(const string & theName) { + SetName((UnicodeString) theName.c_str()); } // GPTPart::SetName() -// Set the name for a partition to theName, or prompt for a name -// if theName is empty, using a Unicode string as input. -void GPTPart::SetName(UnicodeString theName) { - int i; - UChar temp[NAME_SIZE / 2]; - - if (theName == "") { // No name specified, so get one from the user - cout << "Enter name: "; - theName = ReadUString(); - } // if - - // Copy the C++-style string from newName into a form that the GPT - // table will accept.... - memset(temp, 0, NAME_SIZE); - for (i = 0; i < theName.length(); i++) - temp[i] = theName[i]; - memcpy(name, temp, NAME_SIZE); +// Set the name for a partition to theName, using a Unicode string as +// input. +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); + } // if/else } // GPTPart::SetName() +#else +// Set the name for a partition to theName. Note that theName is a +// standard C++-style ASCII string, although the GUID partition definition +// 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(), Windows version +#endif // Set the name for the partition based on the current GUID partition type // code's associated name @@ -189,13 +190,12 @@ void GPTPart::ShowSummary(int partNum, uint32_t blockSize) { cout.setf(ios::uppercase); cout << hex << partitionType.GetHexType() << " " << dec; cout.fill(' '); -// description = GetDescription(); - GetDescription().extractBetween(0, 24, description); +#ifndef _WIN32 + GetDescription().extractBetween(0, 23, description); cout << description << "\n"; -// for (i = 0; i < 23; i++) -// cout << (char) description.; -// cout << GetDescription().tempSubString(0, 23) << "\n"; -// cout << GetDescription().substr(0, 23) << "\n"; +#else + cout << GetDescription().substr(0, 23) << "\n"; +#endif cout.fill(' '); } // if } // GPTPart::ShowSummary() @@ -223,7 +223,7 @@ void GPTPart::ShowDetails(uint32_t blockSize) { cout << hex; cout << attributes << "\n"; cout << dec; - cout << "Partition name: " << GetDescription() << "\n"; + cout << "Partition name: '" << GetDescription() << "'\n"; cout.fill(' '); } // if } // GPTPart::ShowDetails() @@ -61,7 +61,6 @@ class GPTPart { uint64_t GetLengthLBA(void) const; Attributes GetAttributes(void) {return attributes;} void ShowAttributes(uint32_t partNum) {attributes.ShowAttributes(partNum);} -// string GetDescription(void); UnicodeString GetDescription(void); int IsUsed(void); @@ -74,9 +73,10 @@ class GPTPart { void SetLastLBA(uint64_t l) {lastLBA = l;} void SetAttributes(uint64_t a) {attributes = a;} void SetAttributes(void) {attributes.ChangeAttributes();} - void SetName(string theName); - void SetName(UnicodeString theName); -// void SetName(UChar *theName); + void SetName(const string & theName); +#ifndef _WIN32 + void SetName(const UnicodeString & theName); +#endif void SetDefaultDescription(void); // Additional functions @@ -1,5 +1,5 @@ /* - Copyright (C) <2010> <Roderick W. Smith> + Copyright (C) 2010-2011 <Roderick W. Smith> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,7 +29,6 @@ #include <cstdio> #include "attributes.h" #include "gpttext.h" -//#include "gptpartnotes.h" #include "support.h" using namespace std; @@ -295,15 +294,29 @@ void GPTDataTextUI::ChangeUniqueGuid(void) { // Partition attributes seem to be rarely used, but I want a way to // adjust them for completeness.... void GPTDataTextUI::SetAttributes(uint32_t partNum) { -// Attributes theAttr; - partitions[partNum].SetAttributes(); -/* theAttr = partitions[partNum].GetAttributes(); -// theAttr.SetAttributes(partitions[partNum].GetAttributes()); - theAttr.ChangeAttributes(); - partitions[partNum].SetAttributes(theAttr.GetAttributes()); */ } // GPTDataTextUI::SetAttributes() +// Prompts the user for a partition name and sets the partition's +// name. Returns 1 on success, 0 on failure (invalid partition +// number). (Note that the function skips prompting when an +// invalid partition number is detected.) +int GPTDataTextUI::SetName(uint32_t partNum) { + UnicodeString theName = ""; + int retval = 1; + + if (IsUsedPartNum(partNum)) { + cout << "Enter name: "; + theName = ReadUString(); + partitions[partNum].SetName(theName); + } else { + cerr << "Invalid partition number (" << partNum << ")\n"; + retval = 0; + } // if/else + + return retval; +} // GPTDataTextUI::SetName() + // Ask user for two partition numbers and swap them in the table. Note that // this just reorders table entries; it doesn't adjust partition layout on // the disk. @@ -477,13 +490,15 @@ int GPTDataTextUI::XFormToMBR(void) { return protectiveMBR.DoMenu(); } // GPTDataTextUI::XFormToMBR() -/********************************************************************* - * * - * The following doesn't really belong in the class, since it's MBR- * - * specific, but it's also user I/O-related, so I want to keep it in * - * this file.... * - * * - *********************************************************************/ +/******************************** + * * + * Non-class support functions. * + * * + ********************************/ + +// GetMBRTypeCode() doesn't really belong in the class, since it's MBR- +// specific, but it's also user I/O-related, so I want to keep it in +// this file.... // Get an MBR type code from the user and return it int GetMBRTypeCode(int defType) { @@ -505,3 +520,15 @@ int GetMBRTypeCode(int defType) { cout.fill(' '); return typeCode; } // GetMBRTypeCode + +// Note: ReadUString() is here rather than in support.cc so that the ICU +// libraries need not be linked to fixparts. + +// Reads a Unicode string from stdin, returning it as an ICU-style string. +// Note that the returned string will NOT include the carriage return +// entered by the user. Relies on the ICU constructor from a string +// encoded in the current codepage to work. +UnicodeString ReadUString(void) { + return ReadString().c_str(); +} // ReadUString() + @@ -1,6 +1,6 @@ /* <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> + Copyright (C) 2010-2011 Roderick W. Smith This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -47,6 +47,7 @@ class GPTDataTextUI : public GPTData { void ChangePartType(void); void ChangeUniqueGuid(void); void SetAttributes(uint32_t partNum); + int SetName(uint32_t partNum); int SwapPartitions(void); int DestroyGPTwPrompt(void); // Returns 1 if user proceeds void ShowDetails(void); @@ -55,5 +56,6 @@ class GPTDataTextUI : public GPTData { }; // class GPTDataTextUI int GetMBRTypeCode(int defType); +UnicodeString ReadUString(void); #endif // __GPTDATATEXT_H @@ -5,7 +5,7 @@ // Implements the GUIDData data structure and support methods // // -// Author: Rod Smith <rodsmith@rodsbooks.com>, (C) 2010 +// Author: Rod Smith <rodsmith@rodsbooks.com>, (C) 2010-2011 // // Copyright: See COPYING file that comes with this distribution // @@ -66,16 +66,6 @@ void MBRData::MakeProtectiveMBR(int clearBoot) { } // if/else partitions[0].SetInclusion(PRIMARY); - // Write CHS data. This maxes out the use of the disk, as much as - // possible -- even to the point of exceeding the capacity of sub-8GB - // disks. The EFI spec says to use 0xffffff as the ending value, - // although normal MBR disks max out at 0xfeffff. FWIW, both GNU Parted - // and Apple's Disk Utility use 0xfeffff, and the latter puts that - // value in for the FIRST sector, too! -/* LBAtoCHS(1, partitions[0].firstSector); - if (LBAtoCHS(partitions[0].lengthLBA, partitions[0].lastSector) == 0) - partitions[0].lastSector[0] = 0xFF; */ - state = gpt; } // MBRData::MakeProtectiveMBR() @@ -30,7 +30,6 @@ public: MBRData(void) {} MBRData(string deviceFilename) : BasicMBRData(deviceFilename) {} MBRData & operator=(const BasicMBRData & orig); -// MBRData & operator=(const MBRData & orig); // Functions to create, delete, or change partitions // Pass EmptyMBR 1 to clear the boot loader code, 0 to leave it intact @@ -346,4 +346,4 @@ void MBRPart::ShowData(int isGpt) { cout.width(2); cout.fill('0'); cout << hex << (int) partitionType << dec << "\n"; -} // MBRPart::ShowData()
\ No newline at end of file +} // MBRPart::ShowData() diff --git a/parttypes.cc b/parttypes.cc index 99de500..662a278 100644 --- a/parttypes.cc +++ b/parttypes.cc @@ -357,29 +357,3 @@ int PartType::Valid(uint16_t code) const { } // while return found; } // PartType::Valid() - -/******************************** - * * - * Non-class support functions. * - * * - ********************************/ - -// Note: ReadUString() is here rather than in support.cc so that the ICU -// libraries need not be linked to fixparts. - -// Reads a Unicode string from stdin, returning it as a ICU-style string. -// Note that the returned string will NOT include the carriage return -// entered by the user. -UnicodeString ReadUString(void) { - UnicodeString inString = "", oneWord; - - do { - cin >> oneWord; - if (inString.length() > 0) - inString += " "; - inString += oneWord; - } while (cin.peek() != '\n'); - cin.get(); // discard CR - return inString; -} // ReadUString() - diff --git a/parttypes.h b/parttypes.h index 77ed851..73c66e2 100644 --- a/parttypes.h +++ b/parttypes.h @@ -3,8 +3,11 @@ #include <stdint.h> #include <stdlib.h> -#include <unicode/unistr.h> +#ifndef _WIN32 #include <unicode/ustream.h> +#else +#define UnicodeString string +#endif #include <string> #include "support.h" #include "guid.h" @@ -61,6 +64,4 @@ public: int Valid(uint16_t code) const; }; -UnicodeString ReadUString(void); - #endif @@ -1,6 +1,6 @@ .\" Copyright 2011 Roderick W. Smith (rodsmith@rodsbooks.com) .\" May be distributed under the GNU General Public License -.TH "SGDISK" "8" "0.7.0" "Roderick W. Smith" "GPT fdisk Manual" +.TH "SGDISK" "8" "0.7.1" "Roderick W. Smith" "GPT fdisk Manual" .SH "NAME" sgdisk \- Command\-line GUID partition table (GPT) manipulator for Linux and Unix .SH "SYNOPSIS" @@ -182,8 +182,8 @@ will reflect GPT fdisk's first\-pass interpretation of the GPT. .TP .B \-c, \-\-change\-name=partnum:name Change the GPT name of a partition. This name is encoded as a UTF\-16 -string, but \fBsgdisk\fR -supports only ASCII characters as names. For the most part, Linux ignores +string, but proper entry and display of anything beyond basic ASCII values +requires suitable locale and font support. For the most part, Linux ignores the partition name, but it may be important in some OSes. GPT fdisk sets a default name based on the partition type code. If you want to set a name that includes a space, enclose it in quotation marks, as in @@ -470,7 +470,7 @@ Non\-GPT disk detected and no \fI\-g\fR option .B 4 An error prevented saving changes .SH "BUGS" -As of March 2011 (version 0.7.00), \fBsgdisk\fR +As of March 2011 (version 0.7.1), \fBsgdisk\fR should be considered beta software. Known bugs and limitations include: .TP @@ -496,13 +496,6 @@ alignment. .TP .B * -Only ASCII characters are supported in the partition name field. If an -existing partition uses non\-ASCII UTF\-16 characters, they're likely to be -corrupted in the 'i' and 'p' menu options' displays; however, they should be -preserved when loading and saving partitions. - -.TP -.B * The program can load only up to 128 partitions (4 primary partitions and 124 logical partitions) when converting from MBR format. This limit can be raised by changing the \fI#define MAX_MBR_PARTS\fR line in the @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) { char *newPartInfo = NULL, *typeCode = NULL, *partName = NULL; char *backupFile = NULL, *twoParts = NULL, *hybrids = NULL, *mbrParts; char *partGUID = NULL, *diskGUID = NULL, *outDevice = NULL; - string cmd, typeGUID; + string cmd, typeGUID, name; PartType typeHelper; poptContext poptCon; @@ -178,7 +178,8 @@ int main(int argc, char *argv[]) { case 'c': theGPT.JustLooking(0); partNum = (int) GetInt(partName, 1) - 1; - if (theGPT.SetName(partNum, (UnicodeString) GetString(partName, 2).c_str())) { + name = GetString(partName, 2); + if (theGPT.SetName(partNum, (UnicodeString) name.c_str())) { saveData = 1; } else { cerr << "Unable to set partition " << partNum + 1 @@ -8,7 +8,7 @@ #ifndef __GPTSUPPORT #define __GPTSUPPORT -#define GPTFDISK_VERSION "0.7.1-pre2" +#define GPTFDISK_VERSION "0.7.1" #if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__) // Darwin (Mac OS) only: disk IOCTLs are different, and there is no lseek64 |