Upgrade gptfdisk to cb4bf320748f701a0ed835d4a410f2960f1ce0bd am: 2d39d3e54a am: 3c6f74c5ba

Original change: https://android-review.googlesource.com/c/platform/external/gptfdisk/+/2490477

Change-Id: Ied093b396634aeffb8c656058025596b0cffd435
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index d0178f8..ec1c354 100644
--- a/Android.bp
+++ b/Android.bp
@@ -33,6 +33,7 @@
     name: "gptfdisk_default_flags",
     cflags: [
         "-Wno-unused-parameter",
+        "-Wno-macro-redefined",
         "-Wno-pragma-pack",
         "-Werror",
         "-fPIC",
diff --git a/METADATA b/METADATA
index e53a6a6..8dd14f1 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update gptfdisk
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "gptfdisk"
 description: "This package includes the source code for four related disk partitioning programs."
 third_party {
@@ -9,11 +13,11 @@
     type: GIT
     value: "https://git.code.sf.net/p/gptfdisk/code"
   }
-  version: "d292ff36a3b350115835c62462911c3d8721704f"
+  version: "cb4bf320748f701a0ed835d4a410f2960f1ce0bd"
   license_type: RESTRICTED
   last_upgrade_date {
-    year: 2020
-    month: 2
-    day: 10
+    year: 2023
+    month: 3
+    day: 15
   }
 }
diff --git a/Makefile b/Makefile
index 0d7309c..af9701c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,30 +1,160 @@
-CFLAGS+=-D_FILE_OFFSET_BITS=64
-#CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64 -D USE_UTF16
-CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64
+# Makefile for GPT fdisk
+
+# Copyright (c) 2022 by Rod Smith
+# This program is licensed under the terms of the GNU GPL, version 2,
+# or (at your option) any later version.
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This is a consolidated Makefile for Linux, FreeBSD, Solaris (untested),
+# macOS, and Windows (x86_64 and i686).
+
+# Builds for host OS by default; pass TARGET={target_os} to cross-compile,
+# where {target_os} is one of linux, freebsd, solaris, macos, win32, or win64.
+# Appropriate cross-compiler support must be installed, of course, and build
+# options below may need to be changed.
+
+# DETECTED_OS is used both to set certain options for the build
+# environment and to determine the default TARGET if it's not
+# otherwise specified.
+DETECTED_OS := $(shell uname -s)
+
+ifeq ($(origin TARGET),undefined)
+  $(info TARGET is not set; trying to determine target based on host OS....)
+  $(info Detected OS is $(DETECTED_OS))
+  ifeq ($(DETECTED_OS),Linux)
+    # Note: TARGET is set to "linux", but this is never tested, since it's
+    # the default.
+    TARGET=linux
+  else ifeq ($(DETECTED_OS),Darwin)
+    TARGET=macos
+  else ifeq ($(DETECTED_OS),MINGW64_NT-10.0-19042)
+    # Works for my MSYS2 installation, but seems awfully version-specific
+    # Also, uname may not exist in some Windows environments.
+    TARGET=windows
+  else ifeq ($(DETECTED_OS),FreeBSD)
+    TARGET=freebsd
+  else ifeq ($(DETECTED_OS),SunOS)
+    TARGET=solaris
+  endif
+endif
+
+# A second way to detect Windows....
+ifeq ($(origin TARGET),undefined)
+  ifeq ($(OS),Windows_NT)
+    TARGET=windows
+  endif
+endif
+
+# For Windows, we need to know the bit depth, too
+ifeq ($(TARGET),windows)
+  ARCH=$(shell uname -m)
+  $(info ARCH is $(ARCH))
+  ifeq ($(ARCH),x86_64)
+    TARGET=win64
+  else ifeq ($(ARCH),i686)
+    TARGET=win32
+  else
+    # In theory, there could be ARM versions, but we aren't set up for them yet;
+    # also, default to win64 in case uname doesn't exist on the system
+    TARGET=win64
+  endif
+endif
+
+$(info Build target is $(TARGET))
+
+# Default/Linux settings....
+STRIP?=strip
+#CXXFLAGS+=-O2 -Wall -D_FILE_OFFSET_BITS=64 -D USE_UTF16
+CXXFLAGS+=-O2 -Wall -D_FILE_OFFSET_BITS=64
 LDFLAGS+=
+LDLIBS+=-luuid #-licuio -licuuc
+FATBINFLAGS=
+THINBINFLAGS=
+SGDISK_LDLIBS=-lpopt
+CGDISK_LDLIBS=-lncursesw
 LIB_NAMES=crc32 support guid gptpart mbrpart basicmbr mbr gpt bsd parttypes attributes diskio diskio-unix
 MBR_LIBS=support diskio diskio-unix basicmbr mbrpart
+ALL=gdisk cgdisk sgdisk fixparts
+FN_EXTENSION=
+
+# Settings for non-Linux OSes....
+ifeq ($(TARGET),win64)
+  CXX=x86_64-w64-mingw32-g++
+  ifeq ($(DETECTED_OS),Linux)
+    STRIP=x86_64-w64-mingw32-strip
+  else
+    STRIP=strip
+  endif
+  CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -static -static-libgcc -static-libstdc++
+  #CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
+  LDFLAGS+=-static -static-libgcc -static-libstdc++
+  LDLIBS+=-lrpcrt4
+  SGDISK_LDLIBS=-lpopt -lintl -liconv
+  LIB_NAMES=guid gptpart bsd parttypes attributes crc32 mbrpart basicmbr mbr gpt support diskio diskio-windows
+  MBR_LIBS=support diskio diskio-windows basicmbr mbrpart
+  FN_EXTENSION=64.exe
+  ifeq ($(DETECTED_OS),Linux)
+    # Omit cgdisk when building under Linux for Windows because it doesn't
+    # work on my system
+    ALL=gdisk sgdisk fixparts
+  endif
+else ifeq ($(TARGET),win32)
+  CXX=i686-w64-mingw32-g++
+  ifeq ($(DETECTED_OS),Linux)
+    STRIP=i686-w64-mingw32-strip
+  else
+    STRIP=strip
+  endif
+  CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -static -static-libgcc -static-libstdc++
+  #CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include
+  LDFLAGS+=-static -static-libgcc -static-libstdc++
+  LDLIBS+=-lrpcrt4
+  SGDISK_LDLIBS=-lpopt -lintl -liconv
+  LIB_NAMES=guid gptpart bsd parttypes attributes crc32 mbrpart basicmbr mbr gpt support diskio diskio-windows
+  MBR_LIBS=support diskio diskio-windows basicmbr mbrpart
+  FN_EXTENSION=32.exe
+  ifeq ($(DETECTED_OS),Linux)
+    # Omit cgdisk when building for Windows under Linux because it doesn't
+    # work on my system
+    ALL=gdisk sgdisk fixparts
+  endif
+else ifeq ($(TARGET),freebsd)
+  CXX=clang++
+  CXXFLAGS+=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include
+  LDFLAGS+=-L/usr/local/lib
+  LDLIBS+=-luuid #-licuio
+else ifeq ($(TARGET),macos)
+  FATBINFLAGS=-arch x86_64 -arch arm64 -mmacosx-version-min=10.9
+  THINBINFLAGS=-arch x86_64 -mmacosx-version-min=10.9
+  CXXFLAGS=$(FATBINFLAGS) -O2 -Wall -D_FILE_OFFSET_BITS=64 -stdlib=libc++ -I/opt/local/include -I /usr/local/include -I/opt/local/include
+  LDLIBS= #-licucore
+  CGDISK_LDLIBS=/usr/local/Cellar/ncurses/6.2/lib/libncurses.dylib
+else ifeq ($(TARGET),solaris)
+  CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64 -I/usr/include/ncurses
+  LDFLAGS+=-L/lib -licuio -licuuc -luuid
+endif
+
+# More default settings, for all OSes....
 LIB_OBJS=$(LIB_NAMES:=.o)
 MBR_LIB_OBJS=$(MBR_LIBS:=.o)
 LIB_HEADERS=$(LIB_NAMES:=.h)
 DEPEND= makedepend $(CXXFLAGS)
+ALL_EXE=$(ALL:=$(FN_EXTENSION))
 
-all:	cgdisk gdisk sgdisk fixparts
+all:	$(ALL)
 
 gdisk:	$(LIB_OBJS) gdisk.o gpttext.o
-	$(CXX) $(LIB_OBJS) gdisk.o gpttext.o $(LDFLAGS) -luuid $(LDLIBS) -o gdisk
-#	$(CXX) $(LIB_OBJS) gdisk.o gpttext.o $(LDFLAGS) -licuio -licuuc -luuid -o gdisk
+	$(CXX) $(LIB_OBJS) gdisk.o gpttext.o $(LDFLAGS) $(LDLIBS) $(FATBINFLAGS) -o gdisk$(FN_EXTENSION)
 
 cgdisk: $(LIB_OBJS) cgdisk.o gptcurses.o
-	$(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o $(LDFLAGS) -luuid -lncursesw $(LDLIBS) -o cgdisk
-#	$(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o $(LDFLAGS) -licuio -licuuc -luuid -lncurses -o cgdisk
+	$(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o $(LDFLAGS) $(LDLIBS) $(CGDISK_LDLIBS) -o cgdisk$(FN_EXTENSION)
 
 sgdisk: $(LIB_OBJS) sgdisk.o gptcl.o
-	$(CXX) $(LIB_OBJS) sgdisk.o gptcl.o $(LDFLAGS) -luuid -lpopt $(LDLIBS) -o sgdisk
-#	$(CXX) $(LIB_OBJS) sgdisk.o gptcl.o $(LDFLAGS) -licuio -licuuc -luuid -lpopt -o sgdisk
+	$(CXX) $(LIB_OBJS) sgdisk.o gptcl.o $(LDFLAGS) $(LDLIBS) $(SGDISK_LDLIBS) $(THINBINFLAGS) -o sgdisk$(FN_EXTENSION)
 
 fixparts: $(MBR_LIB_OBJS) fixparts.o
-	$(CXX) $(MBR_LIB_OBJS) fixparts.o $(LDFLAGS) $(LDLIBS) -o fixparts
+	$(CXX) $(MBR_LIB_OBJS) fixparts.o $(LDFLAGS) $(FATBINFLAGS) -o fixparts$(FN_EXTENSION)
 
 test:
 	./gdisk_test.sh
@@ -33,7 +163,10 @@
 	lint $(SRCS)
 
 clean:	#no pre-reqs
-	rm -f core *.o *~ gdisk sgdisk cgdisk fixparts
+	rm -f core *.o *~ $(ALL_EXE)
+
+strip:	#no pre-reqs
+	$(STRIP) $(ALL_EXE)
 
 # what are the source dependencies
 depend: $(SRCS)
diff --git a/Makefile.freebsd b/Makefile.freebsd
index dace733..7223f2d 100644
--- a/Makefile.freebsd
+++ b/Makefile.freebsd
@@ -1,9 +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 
-LDFLAGS+=
+CXX=clang++
+#CXXFLAGS+=-O2 -Wall -D_FILE_OFFSET_BITS=64 -D USE_UTF16 -I/usr/local/include
+CXXFLAGS+=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include 
+LDFLAGS+=-L/usr/local/lib
+LDLIBS+=-luuid #-licuio
 LIB_NAMES=crc32 support guid gptpart mbrpart basicmbr mbr gpt bsd parttypes attributes diskio diskio-unix
 MBR_LIBS=support diskio diskio-unix basicmbr mbrpart
 LIB_OBJS=$(LIB_NAMES:=.o)
@@ -14,25 +13,22 @@
 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 $(LDFLAGS) $(LDLIBS) -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 $(LDFLAGS) $(LDLIBS) -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 $(LDFLAGS) $(LDLIBS) -lpopt -o sgdisk
 
 fixparts: $(MBR_LIB_OBJS) fixparts.o
-	$(CXX) $(MBR_LIB_OBJS) fixparts.o -L/usr/local/lib $(LDFLAGS) -o fixparts
+	$(CXX) $(MBR_LIB_OBJS) fixparts.o $(LDFLAGS) -o fixparts
 
 lint:	#no pre-reqs
 	lint $(SRCS)
 
 clean:	#no pre-reqs
-	rm -f core *.o *~ gdisk sgdisk
+	rm -f core *.o *~ gdisk cgdisk sgdisk fixparts
 
 # what are the source dependencies
 depend: $(SRCS)
diff --git a/Makefile.linux b/Makefile.linux
new file mode 100644
index 0000000..0d7309c
--- /dev/null
+++ b/Makefile.linux
@@ -0,0 +1,46 @@
+CFLAGS+=-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
+LIB_OBJS=$(LIB_NAMES:=.o)
+MBR_LIB_OBJS=$(MBR_LIBS:=.o)
+LIB_HEADERS=$(LIB_NAMES:=.h)
+DEPEND= makedepend $(CXXFLAGS)
+
+all:	cgdisk gdisk sgdisk fixparts
+
+gdisk:	$(LIB_OBJS) gdisk.o gpttext.o
+	$(CXX) $(LIB_OBJS) gdisk.o gpttext.o $(LDFLAGS) -luuid $(LDLIBS) -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 -lncursesw $(LDLIBS) -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 $(LDLIBS) -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) $(LDLIBS) -o fixparts
+
+test:
+	./gdisk_test.sh
+
+lint:	#no pre-reqs
+	lint $(SRCS)
+
+clean:	#no pre-reqs
+	rm -f core *.o *~ gdisk sgdisk cgdisk fixparts
+
+# what are the source dependencies
+depend: $(SRCS)
+	$(DEPEND) $(SRCS)
+
+$(OBJS):
+	$(CRITICAL_CXX_FLAGS) 
+
+# makedepend dependencies below -- type "makedepend *.cc" to regenerate....
+# DO NOT DELETE
diff --git a/Makefile.mac b/Makefile.mac
index 27f95b7..91a281c 100644
--- a/Makefile.mac
+++ b/Makefile.mac
@@ -1,10 +1,11 @@
-CC=gcc
-CXX=clang++
-FATBINFLAGS=-arch x86_64 -arch i386 -mmacosx-version-min=10.4
-THINBINFLAGS=-arch x86_64 -mmacosx-version-min=10.4
-CFLAGS=$(FATBINFLAGS) -O2 -D_FILE_OFFSET_BITS=64 -g
-#CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -D USE_UTF16 -I/opt/local/include -I/usr/local/include -I/opt/local/include -g
-CXXFLAGS=$(FATBINFLAGS) -O2 -Wall -D_FILE_OFFSET_BITS=64 -I/opt/local/include -I /usr/local/include -I/opt/local/include -g
+CXX=c++
+# FATBINFLAGS=-arch x86_64 -arch i386 -mmacosx-version-min=10.9
+FATBINFLAGS=-arch x86_64 -arch arm64 -mmacosx-version-min=10.9
+THINBINFLAGS=-arch x86_64 -mmacosx-version-min=10.9
+#CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -D USE_UTF16 -I/opt/local/include -I/usr/local/include -I/opt/local/include
+CXXFLAGS=$(FATBINFLAGS) -O2 -Wall -D_FILE_OFFSET_BITS=64 -stdlib=libc++ -I/opt/local/include -I /usr/local/include -I/opt/local/include
+LDFLAGS+=
+LDLIBS+= #-licucore
 LIB_NAMES=crc32 support guid gptpart mbrpart basicmbr mbr gpt bsd parttypes attributes diskio diskio-unix
 MBR_LIBS=support diskio diskio-unix basicmbr mbrpart
 #LIB_SRCS=$(NAMES:=.cc)
@@ -16,24 +17,17 @@
 all:	gdisk sgdisk cgdisk fixparts
 
 gdisk:	$(LIB_OBJS) gpttext.o gdisk.o
-	$(CXX) $(LIB_OBJS) gpttext.o gdisk.o $(FATBINFLAGS) -o gdisk
-#	$(CXX) $(LIB_OBJS) -L/usr/lib -licucore gpttext.o gdisk.o -o gdisk
+	$(CXX) $(LIB_OBJS) gpttext.o gdisk.o $(FATBINFLAGS) $(LDFLAGS) $(LDLIBS) -o gdisk
 
 cgdisk: $(LIB_OBJS) cgdisk.o gptcurses.o
-	$(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o /usr/lib/libncurses.dylib $(LDFLAGS) $(FATBINFLAGS) -o cgdisk
-#	$(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o $(LDFLAGS) -licucore -lncurses -o cgdisk
+	$(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o $(LDFLAGS) $(LDLIBS) /usr/local/Cellar/ncurses/6.2/lib/libncurses.dylib -o cgdisk
 
 sgdisk: $(LIB_OBJS) gptcl.o sgdisk.o
-#	$(CXX) $(LIB_OBJS) gptcl.o sgdisk.o /opt/local/lib/libiconv.a /opt/local/lib/libintl.a /opt/local/lib/libpopt.a $(FATBINFLAGS) -o sgdisk
-	$(CXX) $(LIB_OBJS) gptcl.o sgdisk.o -L/usr/local/lib -lpopt $(THINBINFLAGS) -o sgdisk
-#	$(CXX) $(LIB_OBJS) gptcl.o sgdisk.o -L/sw/lib -licucore -lpopt -o sgdisk
+	$(CXX) $(LIB_OBJS) gptcl.o sgdisk.o $(LDFLAGS) -L/usr/local/lib $(LDLIBS) -lpopt $(THINBINFLAGS) -o sgdisk
 
 fixparts: $(MBR_LIB_OBJS) fixparts.o
 	$(CXX) $(MBR_LIB_OBJS) fixparts.o $(LDFLAGS) $(FATBINFLAGS) -o fixparts
 
-testguid:	$(LIB_OBJS) testguid.o
-	$(CXX) $(LIB_OBJS) testguid.o -o testguid
-
 lint:	#no pre-reqs
 	lint $(SRCS)
 
diff --git a/Makefile.mingw b/Makefile.mingw
index acfff64..2ed228a 100644
--- a/Makefile.mingw
+++ b/Makefile.mingw
@@ -1,9 +1,9 @@
-CC=/usr/bin/i686-w64-mingw32-gcc
-CXX=/usr/bin/i686-w64-mingw32-g++
-STRIP=/usr/bin/i686-w64-mingw32-strip
-CFLAGS=-O2 -Wall -static -static-libgcc -static-libstdc++  -D_FILE_OFFSET_BITS=64 -g
-CXXFLAGS=-O2 -Wall -static -static-libgcc -static-libstdc++ -D_FILE_OFFSET_BITS=64 -g
-#CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
+CXX=i686-w64-mingw32-g++
+STRIP=i686-w64-mingw32-strip
+CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -static -static-libgcc -static-libstdc++
+#CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include
+LDFLAGS+=-static -static-libgcc -static-libstdc++
+LDLIBS+=-lrpcrt4
 LIB_NAMES=guid gptpart bsd parttypes attributes crc32 mbrpart basicmbr mbr gpt support diskio diskio-windows
 MBR_LIBS=support diskio diskio-windows basicmbr mbrpart
 LIB_SRCS=$(NAMES:=.cc)
@@ -12,25 +12,28 @@
 LIB_HEADERS=$(LIB_NAMES:=.h)
 DEPEND= makedepend $(CFLAGS)
 
-all:	gdisk fixparts
+all:	gdisk sgdisk fixparts
 
 gdisk:	$(LIB_OBJS) gdisk.o gpttext.o
-	$(CXX) $(CXXFLAGS) $(LIB_OBJS) gdisk.o gpttext.o -lrpcrt4 -static-libgcc -o gdisk32.exe
+	$(CXX) $(LIB_OBJS) gdisk.o gpttext.o $(LDFLAGS) $(LDLIBS) -o gdisk32.exe
 
-sgdisk: $(LIB_OBJS) sgdisk.o
-	$(CXX) $(CXXFLAGS) $(LIB_OBJS) sgdisk.o -lpopt -static-libgcc -o sgdisk32.exe
+cgdisk: $(LIB_OBJS) cgdisk.o gptcurses.o
+	$(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o $(LDFLAGS) $(LDLIBS) -lncursesw -o cgdisk32.exe
+
+sgdisk: $(LIB_OBJS) sgdisk.o gptcl.o
+	$(CXX) $(LIB_OBJS) sgdisk.o gptcl.o $(LDFLAGS) $(LDLIBS) -lpopt -lintl -liconv -o sgdisk32.exe
 
 fixparts: $(MBR_LIB_OBJS) fixparts.o
-	$(CXX) $(CXXFLAGS) $(MBR_LIB_OBJS) fixparts.o $(LDFLAGS) -static-libgcc -o fixparts32.exe
+	$(CXX) $(MBR_LIB_OBJS) fixparts.o $(LDFLAGS) -o fixparts32.exe
 
 lint:	#no pre-reqs
 	lint $(SRCS)
 
 clean:	#no pre-reqs
-	rm -f core *.o *~ gdisk.exe sgdisk.exe
+	rm -f core *.o *~ gdisk32.exe cgdisk32.exe sgdisk32.exe fixparts32.exe
 
 strip:	#no pre-reqs
-	$(STRIP) gdisk32.exe fixparts32.exe
+	$(STRIP) gdisk32.exe cgdisk32.exe sgdisk32.exe fixparts32.exe
 
 # what are the source dependencies
 depend: $(SRCS)
diff --git a/Makefile.mingw64 b/Makefile.mingw64
index 7e4b32b..3070a42 100644
--- a/Makefile.mingw64
+++ b/Makefile.mingw64
@@ -1,9 +1,9 @@
-CC=/usr/bin/x86_64-w64-mingw32-gcc
-CXX=/usr/bin/x86_64-w64-mingw32-g++
-STRIP=/usr/bin/x86_64-w64-mingw32-strip
-CFLAGS=-O2 -Wall -static -static-libgcc -static-libstdc++  -D_FILE_OFFSET_BITS=64 -g
-CXXFLAGS=-O2 -Wall -static -static-libgcc -static-libstdc++ -D_FILE_OFFSET_BITS=64 -g
+CXX=x86_64-w64-mingw32-g++
+STRIP=x86_64-w64-mingw32-strip
+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
+LDFLAGS+=-static -static-libgcc -static-libstdc++
+LDLIBS+=-lrpcrt4
 LIB_NAMES=guid gptpart bsd parttypes attributes crc32 mbrpart basicmbr mbr gpt support diskio diskio-windows
 MBR_LIBS=support diskio diskio-windows basicmbr mbrpart
 LIB_SRCS=$(NAMES:=.cc)
@@ -12,25 +12,29 @@
 LIB_HEADERS=$(LIB_NAMES:=.h)
 DEPEND= makedepend $(CFLAGS)
 
-all:	gdisk fixparts
+# Note: cgdisk is buildable in Windows, but not in Ubuntu 20.04 or 22.04
+all:	gdisk sgdisk fixparts
 
 gdisk:	$(LIB_OBJS) gdisk.o gpttext.o
-	$(CXX) $(CXXFLAGS) $(LIB_OBJS) gdisk.o gpttext.o -lrpcrt4 -static-libgcc -o gdisk64.exe
+	$(CXX) $(LIB_OBJS) gdisk.o gpttext.o $(LDFLAGS) $(LDLIBS) -o gdisk64.exe
 
-sgdisk: $(LIB_OBJS) sgdisk.o
-	$(CXX) $(CXXFLAGS) $(LIB_OBJS) sgdisk.o -lpopt -static-libgcc -o sgdisk64.exe
+cgdisk: $(LIB_OBJS) cgdisk.o gptcurses.o
+	$(CXX) $(LIB_OBJS) cgdisk.o gptcurses.o $(LDFLAGS) $(LDLIBS) -lncursesw -o cgdisk64.exe
+
+sgdisk: $(LIB_OBJS) sgdisk.o gptcl.o
+	$(CXX) $(LIB_OBJS) sgdisk.o gptcl.o $(LDFLAGS) $(LDLIBS) -lpopt -lintl -liconv -o sgdisk64.exe
 
 fixparts: $(MBR_LIB_OBJS) fixparts.o
-	$(CXX) $(CXXFLAGS) $(MBR_LIB_OBJS) fixparts.o $(LDFLAGS) -static-libgcc -o fixparts64.exe
+	$(CXX) $(MBR_LIB_OBJS) fixparts.o $(LDFLAGS) -o fixparts64.exe
 
 lint:	#no pre-reqs
 	lint $(SRCS)
 
 clean:	#no pre-reqs
-	rm -f core *.o *~ gdisk64.exe sgdisk64.exe
+	rm -f core *.o *~ gdisk64.exe cgdisk64.exe sgdisk64.exe fixparts64.exe
 
 strip:	#no pre-reqs
-	$(STRIP) gdisk64.exe fixparts64.exe
+	$(STRIP) gdisk64.exe cgdisk64.exe sgdisk64.exe fixparts64.exe
 
 # what are the source dependencies
 depend: $(SRCS)
diff --git a/NEWS b/NEWS
index ff54c6c..29d99e3 100644
--- a/NEWS
+++ b/NEWS
@@ -1,12 +1,176 @@
-1.0.5 (?/?/2020):
+1.0.10 (?/??/2023):
+-------------------
+
+- Fixed problem that caused sgdisk to crash with errors about being unable
+  to read the disk's partition table when compiled with the latest popt
+  (commit 740, which is pre-release as I type; presumably version 1.19 and
+  later once released).
+
+- Updated guid.cc to deal with minor change in libuuid.
+
+- Fixed potential NULL derefernce bug in sgdisk. Thanks to Damian Kurek
+  for this fix.
+
+- The partition number of "0" can now be used to reference newly-created
+  partitions when the --largest-new=0 option to sgdisk is used. Thanks to
+  David Joaquín Shourabi Porcel for this improvement.
+
+- Make explicit casts in gptcurses.cc to eliminate compiler warnings about
+  mis-matched types in printw() statements.
+
+- Minor code cleanup based on valgrind analysis.
+
+- In previous versions, rEFInd accepted only integer values for partition
+  start points, end points, and sizes, and it interpreted decimal values
+  incorrectly. That is, if you typed "+9.5G" as the partition end point,
+  you'd end up with something just 9 sectors in size. This version now
+  truncates decimal numbers to their integral values, so you'd get a 9 GiB
+  partition instead.
+
+1.0.9 (4/14/2022):
+------------------
+
+- Removed stray debugging code that caused "partNum is {x}" to be printed
+  when changing a partition's name with sgdisk (-c/--change-name).
+
+- Added support for aligning partitions' end points, as well as their start
+  points. This support affects the default partition size when using 'n' in
+  gdisk; it affects the default partition size in cgdisk; and it's activated
+  by the new '-I' option in sgdisk. See the programs' respective man pages
+  for details. This feature is intended to help with LUKS2 encryption, which
+  reacts badly to partitions that are not sized as exact multiples of the
+  encryption block size.
+
+- Added check for too-small disks (most likely to be an issue when trying
+  to use a too-small disk image); program now aborts if this happens.
+
+- Added the ability to build sgdisk and cgdisk for Windows.
+
+- Added new type codes:
+  * FreeBSD nandfs (0xa506)
+  * Apple APFS Pre-Boot (0xaf0b)
+  * Apple APFS Recovery (0xaf0c)
+  * ChromeOS firmware (0x7f03)
+  * ChromeOS mini-OS (0x7f04)
+  * ChromeOS hibernate (0x7f05)
+  * U-Boot boot loader (0xb000)
+  * 27 (!) codes for Fuchsia (0xf100 to 0xf11a)
+
+- Fixed build problems with recent versions of ncurses.
+
+- Fixed bug that caused cgdisk to report incorrect partition attributes.
+
+- Consolidated Makefiles for Linux, FreeBSD, Solaris, macOS, and Windows
+  (32- and 64-bit). The old OS-specific Makefiles remain in case the new
+  consolidated Makefile has problems, but the old ones are deprecated.
+  (The Solaris support in the new Makefile is untested.)
+
+1.0.8 (6/9/2021):
 -----------------
 
+- Fixed double byte swap operation on writes of partition name data on
+  big-endian systems; this is in addition to the double byte swap fix on
+  reading partition label data fixed in 1.0.7. (Thanks to Erik Larsson for
+  both fixes.)
+
+- Added feature to gdisk and sgdisk to enable swapping the byte order of
+  partition names, so as to correct disks already affected by the preceding
+  bug. This option is 'b' on the experts' menu in gdisk and
+  -b/--byte-swap-name in sgdisk. This seems advanced/obscure enough that I
+  don't want to clutter cgdisk's menu with this option, so I haven't added
+  it there.
+
+- Added type code for the Barebox boot loader (0xbb00;
+  4778ED65-BF42-45FA-9C5B-287A1DC4AAB1).
+
+- Trivial code cleanup.
+
+1.0.7 (3/10/2021):
+------------------
+
+- Fixed bug that caused spurious warnings about the partition table
+  header claiming an invalid size of partition entries when reading
+  some MBR disks.
+
+- Added ARM64 as an architecture for the Mac builds of gdisk and fixparts.
+  The official GPT fdisk binaries of these files for macOS are now
+  "universal" x86-64/ARM64 binaries, so they will run natively on the new M1
+  (ARM64) Macs. The sgdisk and cgdisk binaries, though, remain built only
+  for x86-64, because they rely on libraries that are not easily built in
+  "universal" form.
+
+- Fixed double byte swap operation on partition label data on big-endian
+  CPUs. This resulted in partition names becoming gibberish on such CPUs.
+
+- Added three new type codes:
+  - 0x0701 - Microsoft Storage Replica
+  - 0x0702 - ArcaOS Type 1
+  - 0x8401 - Storage Performance Development Kit (SPDK) block device
+
+1.0.6 (1/13/2021):
+------------------
+
+- Fixed bug that could cause segfault if GPT header claimed partition
+  entries are oversized. See:
+  https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-0256
+
+- Fixed bug that could cause a crash if a badly-formatted MBR disk was
+  read. See:
+  https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-0308
+
+- Renamed the partition type "Freedesktop $BOOT" to "XBOOTLDR partition".
+
+- Added several more Freedesktop partition table type codes (0x8312 through
+  0x831C).
+
+- Fixed type code definition in diskio-unix.cc that prevented 32-bit builds
+  from correctly handling disks over 4 TiB in size.
+
+- Minor tweaks to get the software to compile on FreeBSD; that seems to have
+  fallen into disrepair.
+
+1.0.5 (2/17/2020):
+------------------
+
 - Fixed typos and minor formatting issues in man pages
 
 - Changed number of columns in type code output ("sgdisk -L" and equivalents
   in gdisk and cgdisk) from 3 to 2, since some descriptions are long enough
   that they're ambiguous with three columns.
 
+- Makefile change: Add $(LDLIBS) support to enable clean static builds (for
+  libintl).
+
+- You can now put the 0xEE partition last in a hybrid MBR using sgdisk.
+  (Previously, this was possible with gdisk but not with sgdisk.) See the
+  sgdisk man page for details.
+
+- Added numerous type codes for Container Linux, Veracrypt, and
+  Freedesktop.org's Discoverable Partitions Specification
+
+- Partition type name searches are now case-insensitive.
+
+- It's now possible to quit out of partition type name searches by typing
+  "q".
+
+- When changing a partition type code, the default is now the current
+  type code, not a platform-specific type code.
+
+- The UEFI GPT fdisk project
+  (https://sourceforge.net/projects/uefigptfdisk/) hasn't been updated since
+  2016, and is now broken; binaries don't compile with modern GCC
+  toolchains, and even when dropping back to Ubuntu 14.04, which worked for
+  GPT fdisk 1.0.4, the resulting binary hangs on launch. Therefore, I'm
+  dropping support for the EFI build of gdisk, at least unless and until
+  UEFI GPT fdisk is fixed.
+
+- Apple no longer supports building i386 or "fat" binaries in XCode (or if
+  they do, they're making it hard), so I've removed that support. GPT fdisk
+  macOS binaries are now x86-64 only. Similarly, building now seems to
+  require macOS 10.9 or later, so that's now the minimum macOS version. I've
+  also re-built my Mac build environment and tweaked Makefile.mac
+  appropriately.
+
 1.0.4 (7/5/2018):
 -----------------
 
diff --git a/README b/README
index f1a091d..157abb8 100644
--- a/README
+++ b/README
@@ -161,15 +161,15 @@
 Installing
 ----------
 
-To compile GPT fdisk, you must have appropriate development tools
-installed, most notably the GNU Compiler Collection (GCC) and its g++
-compiler for C++. I've also tested compilation with Clang, which seems to
-work; however, I've not done extensive testing of the resulting binaries,
-beyond checking a few basics. Under Windows, Microsoft Visual C++ 2008 can
-be used instead. In addition, note these requirements:
+To compile GPT fdisk, you must have appropriate development tools installed,
+most notably the GNU Compiler Collection (GCC) and its g++ compiler for C++.
+I've also tested compilation with Clang, which seems to work; however, I've
+not done extensive testing of the resulting binaries, beyond checking a few
+basics. See the README.Windows files for additional notes on compiling the
+software for Windows. In addition, note these requirements:
 
-* On Linux, FreeBSD, OS X, and Solaris, libuuid must be installed. This is
-  the standard for Linux and OS X, although you may need to install a
+* On Linux, FreeBSD, macOS, and Solaris, libuuid must be installed. This is
+  the standard for Linux and macOS, although you may need to install a
   package called uuid-dev or something similar to get the headers. On
   FreeBSD, the e2fsprogs-libuuid port must be installed.
 
@@ -177,11 +177,11 @@
   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
+  as of that version it should no 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
+  library is normally installed in Linux and macOS, 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
+  Linux; or the libicu36-dev Fink package in macOS). 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.
@@ -189,56 +189,70 @@
 * The cgdisk program requires the ncurses library and its development files
   (headers). Most Linux distributions install ncurses by default, but you
   may need to install a package called libncurses5-dev, ncurses-devel, or
-  something similar to obtain the header files. These files were installed
-  already on my Mac OS X development system; however, they may have been
-  installed as dependencies of other programs I've installed. If you're
-  having problems installing ncurses, you can compile gdisk and/or sgdisk
-  without cgdisk by specifying only the targets you want to compile to
-  make.
+  something similar to obtain the header files. On my macOS development
+  system, I installed the nurses Homebrew ("brew") package; however, other
+  Unix-style software repositories are available and may work for you (see
+  the next item). If you're having problems installing ncurses, you can
+  compile gdisk and/or sgdisk without cgdisk by specifying only the targets
+  you want to compile to make.
 
 * The sgdisk program requires the popt library and its development files
   (headers). Most Linux distributions install popt by default, but you may
   need to install a package called popt-dev, popt-devel, or something
-  similar to obtain the header files. Mac OS users can find a version of
+  similar to obtain the header files. MacOS users can find a version of
   popt for Mac OS from Darwin Ports (http://popt.darwinports.com), MacPorts
   (https://trac.macports.org/browser/trunk/dports/devel/popt/Portfile), Fink
   (http://www.finkproject.org), or brew (http://macappstore.org/popt/); 
   however, you'll first need to install the relevant environment
-  (instructions exist on the relevant projects' pages). Alternatively, you
-  can compile gdisk and/or cgdisk alone, without sgdisk; gdisk doesn't
-  require popt.
+  (instructions exist on the relevant projects' pages). When I re-built my
+  Mac build environment in February of 2020, I found that brew was, by far,
+  the easiest of these to install. Some of the others seem to have been
+  abandoned, but I didn't investigate thoroughly. I'm leaving the references
+  in case they might be useful in the future. Instead of installing one of
+  These ports, you can compile gdisk and/or cgdisk alone, without sgdisk;
+  gdisk and cgdisk don't require popt.
 
 When all the necessary development tools and libraries are installed, you
 can uncompress the package and type "make" at the command prompt in the
-resulting directory. (You may need to type "make -f Makefile.mac" on Mac OS
-X, "make -f Makefile.freebsd" on FreeBSD, "make -f Makefile.solaris" on
-Solaris, or "make -f Makefile.mingw" to compile using MinGW for Windows.)
-You may also need to add header (include) directories or library
-directories by setting the CXXFLAGS environment variable or by editing the
-Makefile. The result should be program files called gdisk, cgdisk, sgdisk,
-and fixparts. Typing "make gdisk", "make cgdisk", "make sgdisk", or "make
-fixparts" will compile only the requested programs. You can use these
-programs in place or copy the files to a suitable directory, such as
-/usr/local/sbin. You can copy the man pages (gdisk.8, cgdisk.8, sgdisk.8,
-and fixparts.8) to /usr/local/man/man8 to make them available.
+resulting directory. (Beginning with version 1.0.9, GPT fdisk provides a
+consolidated Makefile for all supported OSes. Earlier versions used
+OS-specific Makefiles, such as Makefile.mac and Makefile.freebsd, which are
+still provided, but are deprecated.) You must use GNU make (gmake on
+FreeBSD) with this Makefile. You may also need to add header (include)
+directories or library directories by setting the CXXFLAGS environment
+variable or by editing the Makefile. The result should be program files
+called gdisk, cgdisk, sgdisk, and fixparts (or variants with "32.exe" or
+"64.exe" added for Windows binaries). Typing "make gdisk", "make cgdisk",
+"make sgdisk", or "make fixparts" will compile only the requested programs.
+You can use these programs in place or copy the files to a suitable
+directory, such as /usr/local/sbin. You can copy the man pages (gdisk.8,
+cgdisk.8, sgdisk.8, and fixparts.8) to /usr/local/man/man8 to make them
+available.
+
+Cross-compiling is possible, but is not well-tested, except for compiling
+Windows binaries on Linux. (See README.Windows for details.) To
+cross-compile, specify the TARGET environment variable when launching make,
+as in "TARGET=win64 make" to compile for 64-bit (x86-64, X64, AMD64) Windows
+on a non-Windows platform. Supported TARGET values are linux, freebsd,
+solaris, macos, win32, and win64.
 
 Caveats
 -------
 
-THIS SOFTWARE IS BETA SOFTWARE! IF IT WIPES OUT YOUR HARD DISK OR EATS YOUR
-CAT, DON'T BLAME ME! To date, I've tested the software on several USB flash
-drives, physical hard disks, and virtual disks in the QEMU and VirtualBox
-environments. Many others have now used the software on their computers, as
-well. I believe all data-corruption bugs to be squashed, but I know full well
-that the odds of my missing something are high. This is particularly true for
-large (over-2TiB) drives; my only direct testing with such disks is with
-virtual QEMU and VirtualBox disks. I've received user reports of success with
-RAID arrays over 2TiB in size, though.
+DISK PARTITIONING SOFTWARE IS DANGEROUS! Although the GPT fdisk project has
+existed since 2009, I do not claim it is entirely bug-free; in fact a glance
+at the revision history shows recent bug fixes. I believe all
+data-corruption bugs to be squashed, but I know full well that the odds of
+my missing something are high. This is particularly true for large
+(over-2TiB) drives and use in exotic environments.
 
 My main development platform is a system running the 64-bit version of
 Ubuntu Linux. I've also tested on several other 32- and 64-bit Linux
-distributions, Intel-based Mac OS X 10.6 and several later versions, 64-bit
-FreeBSD 7.1, and Windows 7 and 10.
+distributions, Intel-based macOS 10 and 11, 64-bit FreeBSD 7.1, and Windows
+7 and 10. Other environments qualify as "exotic," and even macOS and Windows
+are borderline exotic in this context, since I use Linux almost exclusively,
+and my impression is that GPT fdisk is far more commonly used on Linux than
+in other OSes.
 
 Redistribution
 --------------
@@ -266,7 +280,7 @@
 
 - Justin Maggard (justin.maggard@netgear.com)
 
-- Dwight Schauer (dschauer@ti.com)
+- Dwight Schauer (das@teegra.net)
 
 - Florian Zumbiehl (florz@florz.de)
 
diff --git a/README.Windows b/README.Windows
index 3f49023..d13bce3 100644
--- a/README.Windows
+++ b/README.Windows
@@ -28,12 +28,8 @@
 

 The Windows version of GPT fdisk was added with version 0.6.2 of the

 package. The Windows binary package includes the gdisk.exe interactive

-text-mode program file but no equivalent to the sgdisk program that's

-available with Linux, FreeBSD, and OS X builds. In theory, an sgdisk.exe

-for Windows could be built if the popt library were installed. I've not

-attempted to do this myself, though. If you care to try, check

-http://gnuwin32.sourceforge.net/packages/popt.htm for information on popt

-for Windows.

+text-mode program file as well as the sgdisk program that's available

+with Linux, FreeBSD, and OS X builds.

 

 Beginning with version 0.8.10, I'm distributing both 32-bit and 64-bit

 binaries, which include the strings "32" or "64" in their names. The 32-bit

@@ -47,10 +43,11 @@
 software. Windows seems to be unfazed by most such problems, but I've not

 done an extensive survey of Windows partitioning tools on this score.

 

-To install the programs, copy the gdisk32.exe and fixparts32.exe (or

-gdisk64.exe and fixparts64.exe) program files to any directory on your

-path, such as C:\Windows. Alternatively, you can change to the program's

-directory or type its complete path whenever you use it.

+To install the programs, copy the gdisk32.exe, cgdisk32.exe, sgdisk32.exe

+and fixparts32.exe (or gdisk64.exe, cgdisk64.exe, sgdisk64.exe and

+fixparts64.exe) program files to any directory on your path, such as

+C:\Windows. Alternatively, you can change to the program's directory or type

+its complete path whenever you use it.

 

 To use the programs, first launch a Command Prompt as the Administrator. To

 do this, locate the Command Prompt program icon, right-click it, and select

@@ -74,17 +71,18 @@
 table on the first physical disk. Change the number at the end of the

 device name to change the disk edited.

 

-If you pass the "-l" option to gdisk.exe in addition to the disk

-identifier, the program displays the current partition table information

-and then exits. This use entails no risk to MBR disks, since the program

-never writes data back to the disk when used in this way.

+If you pass the "-l" option to gdisk64.exe in addition to the disk

+identifier, the program displays the current partition table information and

+then exits. (Alternatively, you can pass "-p" to sgdisk64.exe.) This use

+entails no risk to MBR disks, since the program never writes data back to

+the disk when used in this way.

 

-As noted above, editing the first disk with GPT fdisk is usually a Bad

-Idea. An exception would be if your system uses an Extensible Firmware

-Interface (EFI) and already boots from a GPT disk. It's safer to edit

-non-boot disks, which usually have numbers of 1 and above, but only if you

-run a version of Windows with GPT support. For more information on Windows'

-support of GPT, see Microsoft's Web page on the topic:

+As noted above, editing the first disk with GPT fdisk is a Bad Idea on older

+BIOS-based computers. Newer computers typically use an Extensible Firmware

+Interface (EFI) and boot from GPT disks. It's safer to edit non-boot disks,

+which usually have numbers of 1 and above, but only if you run a version of

+Windows with GPT support. For more information on Windows' support of GPT,

+see Microsoft's Web page on the topic:

 

 http://www.microsoft.com/whdc/device/storage/GPT_FAQ.mspx

 

@@ -103,34 +101,92 @@
 I have successfully compiled GPT fdisk using three different Windows

 compilers:

 

-- MinGW (http://www.mingw.org), and in particular its Linux-hosted

-  cross-compiler -- Under Ubuntu Linux, the Makefile.mingw and

-  Makefile.mingw64 files enable compilation of the software via MinGW.

-  (Type "make -f Makefile.mingw" to compile 32-bit binaries, and "make -f

-  Makefile.mingw64" to compile 64-bit binaries.) If you try to compile

-  using another compiler or even using MinGW under Windows or another Linux

-  variety, you may need to adjust the Makefile.mingw options.

+- MinGW (https://www.mingw-w64.org/), using either a Linux-hosted

+  cross-compiler or under Windows using the original MinGW or MSYS2

+  (https://www.msys2.org). This is my only GPT fdisk development environment

+  for Windows in 2022.

 

 - Microsoft Visual C++ 2008 Express

   (http://www.microsoft.com/express/Windows/) -- This compiler requires a

   third-party stdint.h file (I used the one from

-  http://msinttypes.googlecode.com/svn/trunk/stdint.h), but it otherwise

-  works fine. A project is easily created by adding all the *.h files and

-  all the *.cc files except diskio-unix.cc, sgdisk.cc, and whichever

-  program file you intend to NOT build (gdisk.cc or fixparts.cc).

+  http://web.archive.org/web/20130317001712/http://msinttypes.googlecode.com/svn/trunk/stdint.h),

+  but it otherwise worked fine the last time I tried it. A project is easily

+  created by adding all the *.h files and all the *.cc files except

+  diskio-unix.cc, sgdisk.cc, and whichever program file you intend to NOT

+  build (gdisk.cc or fixparts.cc).

 

 - 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

-attempt failed, mostly because the compiler can't yet handle iostream

-output on standard C++ strings. OpenWatcom also seems to have incorrectly

-set the value of UINT32_MAX as if uint32_t values were 64-bit integers.

-This alone won't cause the compile to fail, but it would create bugs.

+Although I used Microsoft Visual C++ in the past, I haven't tried using

+these compilers recently and so I can't promise they would work today (in

+2022).

 

 If you modify GPT fdisk to get it to compile under another compiler, I

 welcome submission of patches.

+

+The following instructions focus on use of MinGW to compile GPT fdisk for

+Windows.

+

+My primary development environment is Ubuntu Linux, using the MinGW

+cross-compiler. This system can compile the gdisk and fixparts binaries with

+no need for additional libraries; after installing MinGW (via the

+g++-mingw-w64 package in Ubuntu, or the equivalent in another distribution),

+you can type "TARGET=win32 make" to compile 32-bit binaries, and

+"TARGET=win64 make" to compile 64-bit binaries. This will attempt to build

+gdisk, sgdisk, and fixparts; but the sgdisk build will fail until you

+install the popt libraries, as described shortly. You can build the other

+binaries by specifying them, as in "TARGET=win64 make gdisk" to build the

+64-bit gdisk binary alone.

+

+If you use Windows, your best bet is likely to be to install the MSYS2

+package (https://www.msys2.org). This package provides MinGW and a package

+management system based on pacman (used by Arch Linux) for installing

+additional libraries. To install the libraries needed to compile sgdisk and

+cgdisk, type "pacman -S mingw-w64-x86_64-popt mingw-w64-x86_64-gettext

+mingw-w64-x86_64-ncurses" if you want to compile 64-bit binaries; change

+'x86_64' to 'i686' for 32-bit packages. This command will install the popt

+library needed by sgdisk and the ncurses library needed by cgdisk, along

+with gettext, which is needed by popt. With these libraries installed, you

+should be able to compile all four Linux programs -- gdisk, cgdisk, sgdisk,

+and fixparts. Typing "make" alone in the MSYS2 shell should build all four

+programs for the host architecture (x86-64 or i686); to compile for the

+other architecture, you must specify it with a "TARGET=" specification, as

+under Linux. (The Makefile does not currently support ARM64 targets for

+Windows.)

+

+If you want to compile sgdisk for Windows under Linux, you can do so;

+however, you must copy the relevant header and library files from a Windows

+installation to Linux. Specifically, you must copy:

+

+    Windows File                   Linux Directory

+    ------------                   ---------------

+    /mingw64/include/popt.h        /usr/x86_64-w64-mingw32/include/

+    /mingw64/lib/libpopt.a         /usr/x86_64-w64-mingw32/lib/

+    /mingw64/lib/libintl.a         /usr/x86_64-w64-mingw32/lib/

+    /mingw64/lib/libiconv.a        /usr/x86_64-w64-mingw32/lib/

+

+For 32-bit binaries, change /mingw64 to /mingw32 on the Windows source and

+x86_64-w64-mingw32 to i686-w64-mingw32 on the Linux destination.

+

+In theory, you should be able to do something similar to compile cgdisk. The

+relevant files are:

+

+    Windows File                            Linux Directory

+    ------------                            ---------------

+    /mingw64/include/ncursesw/curses.h      /usr/x86_64-w64-mingw32/include/ncursesw/

+    /mingw64/include/ncursesw/ncurses.h     /usr/x86_64-w64-mingw32/include/ncursesw/

+    /mingw64/include/ncursesw/ncurses_dll.h /usr/x86_64-w64-mingw32/include/ncursesw/

+    /mingw64/include/ncursesw/unctrl.h      /usr/x86_64-w64-mingw32/include/ncursesw/

+    /mingw64/lib/libncurses.a               /usr/x86_64-w64-mingw32/lib/

+

+In practice, this has not worked for me; the compilation fails with a

+complaint about an undefined reference to 'nanosleep'. My guess is that the

+ncurses version installed in Windows is too new to work with the MinGW

+libraries in Ubuntu (20.04 or 22.04). It's conceivable it would work with

+another distribution, though.

+

+The Makefile is configured to create statically-linked binaries so as to

+simplify installation of the binaries. If you want smaller binaries, you can

+remove the various static options from the Makefile. You can also strip the

+binaries ("make strip") to remove unused code.

diff --git a/attributes.cc b/attributes.cc
index bbd5aad..f3cd585 100644
--- a/attributes.cc
+++ b/attributes.cc
@@ -7,9 +7,7 @@
   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 
 #define __STDC_LIMIT_MACROS
-#ifndef __STDC_CONSTANT_MACROS
 #define __STDC_CONSTANT_MACROS
-#endif
 
 #include <stdint.h>
 #include <stdio.h>
diff --git a/attributes.h b/attributes.h
index f6c66ff..5eb57e3 100644
--- a/attributes.h
+++ b/attributes.h
@@ -1,20 +1,18 @@
 /* This program is copyright (c) 2009-2011 by Roderick W. Smith. It is distributed
   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 
-#include <stdint.h>
-#include <string>
-
 #ifndef __GPT_ATTRIBUTES
 #define __GPT_ATTRIBUTES
 
+#include <stdint.h>
+#include <string>
+
 #define NUM_ATR 64 /* # of attributes -- 64, since it's a 64-bit field */
 #define ATR_NAME_SIZE 25 /* maximum size of attribute names */
 
-using namespace std;
-
 class Attributes {
 protected:
-   static string atNames[NUM_ATR];
+   static std::string atNames[NUM_ATR];
    static int numAttrs;
    void Setup(void);
    uint64_t attributes;
@@ -30,12 +28,12 @@
    void ShowAttributes(const uint32_t partNum);
 
    void ChangeAttributes(void);
-   bool OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits);
+   bool OperateOnAttributes(const uint32_t partNum, const std::string& attributeOperator, const std::string& attributeBits);
 
-   static const string& GetAttributeName(const uint32_t bitNum) {return atNames [bitNum];}
+   static const std::string& GetAttributeName(const uint32_t bitNum) {return atNames [bitNum];}
    static void ListAttributes(void);
 }; // class Attributes
 
-ostream & operator<<(ostream & os, const Attributes & data);
+std::ostream & operator<<(std::ostream & os, const Attributes & data);
 
 #endif
diff --git a/basicmbr.cc b/basicmbr.cc
index e9ac5c5..e09b0e9 100644
--- a/basicmbr.cc
+++ b/basicmbr.cc
@@ -7,9 +7,7 @@
   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 
 #define __STDC_LIMIT_MACROS
-#ifndef __STDC_CONSTANT_MACROS
 #define __STDC_CONSTANT_MACROS
-#endif
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -142,7 +140,7 @@
 // Read data from MBR. Returns 1 if read was successful (even if the
 // data isn't a valid MBR), 0 if the read failed.
 int BasicMBRData::ReadMBRData(const string & deviceFilename) {
-   int allOK = 1;
+   int allOK;
 
    if (myDisk == NULL) {
       myDisk = new DiskIO;
@@ -292,8 +290,8 @@
          if (EbrLocations[i] == offset) { // already read this one; infinite logical partition loop!
             cerr << "Logical partition infinite loop detected! This is being corrected.\n";
             allOK = -1;
-            if(partNum > 0) //don't go negative
-                partNum -= 1;
+            if (partNum > 0) //don't go negative
+               partNum -= 1;
          } // if
       } // for
       EbrLocations[partNum] = offset;
@@ -357,7 +355,7 @@
 // MBR itself and any defined logical partitions, provided there's an
 // MBR extended partition.
 int BasicMBRData::WriteMBRData(void) {
-   int allOK = 1;
+   int allOK;
 
    if (myDisk != NULL) {
       if (myDisk->OpenForWrite() != 0) {
@@ -374,7 +372,7 @@
 // Save the MBR data to a file. This writes both the
 // MBR itself and any defined logical partitions.
 int BasicMBRData::WriteMBRData(DiskIO *theDisk) {
-   int i, j, partNum, next, allOK = 1, moreLogicals = 0;
+   int i, j, partNum, next, allOK, moreLogicals = 0;
    uint64_t extFirstLBA = 0;
    uint64_t writeEbrTo; // 64-bit because we support extended in 2-4TiB range
    TempMBR tempMBR;
@@ -950,7 +948,7 @@
 // primary status. Also does NOT consider partition order; there
 // can be gaps and it will still be considered legal.
 int BasicMBRData::IsLegal(void) {
-   int allOK = 1;
+   int allOK;
 
    allOK = (FindOverlaps() == 0);
    allOK = (allOK && (NumPrimaries() <= 4));
@@ -1057,7 +1055,7 @@
 // Set the partition's type code.
 // Returns 1 if successful, 0 if not (invalid partition number)
 int BasicMBRData::SetPartType(int num, int type) {
-   int allOK = 1;
+   int allOK;
 
    if ((num >= 0) && (num < MAX_MBR_PARTS)) {
       if (partitions[num].GetLengthLBA() != UINT32_C(0)) {
@@ -1310,7 +1308,7 @@
 // entries (primary space).
 // Returns the number of partitions moved.
 int BasicMBRData::RemoveLogicalsFromFirstFour(void) {
-   int i, j = 4, numMoved = 0, swapped = 0;
+   int i, j, numMoved = 0, swapped = 0;
    MBRPart temp;
 
    for (i = 0; i < 4; i++) {
diff --git a/basicmbr.h b/basicmbr.h
index 504e039..696f826 100644
--- a/basicmbr.h
+++ b/basicmbr.h
@@ -3,21 +3,19 @@
 /* This program is copyright (c) 2009-2013 by Roderick W. Smith. It is distributed
   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 
+#ifndef __BASICMBRSTRUCTS
+#define __BASICMBRSTRUCTS
+
 #include <stdint.h>
 #include <sys/types.h>
 #include "diskio.h"
 #include "mbrpart.h"
 
-#ifndef __BASICMBRSTRUCTS
-#define __BASICMBRSTRUCTS
-
 #define MBR_SIGNATURE UINT16_C(0xAA55)
 
 // Maximum number of MBR partitions
 #define MAX_MBR_PARTS 128
 
-using namespace std;
-
 /****************************************
  *                                      *
  * MBRData class and related structures *
@@ -57,23 +55,23 @@
    uint32_t numSecspTrack; // number of sectors per track, in CHS scheme
    DiskIO* myDisk;
    int canDeleteMyDisk;
-   string device;
+   std::string device;
    MBRValidity state;
    MBRPart* GetPartition(int i); // Return primary or logical partition
 public:
    BasicMBRData(void);
-   BasicMBRData(string deviceFilename);
+   BasicMBRData(std::string deviceFilename);
    BasicMBRData(const BasicMBRData &);
    ~BasicMBRData(void);
    BasicMBRData & operator=(const BasicMBRData & orig);
 
    // File I/O functions...
-   int ReadMBRData(const string & deviceFilename);
+   int ReadMBRData(const std::string & deviceFilename);
    int ReadMBRData(DiskIO * theDisk, int checkBlockSize = 1);
    int ReadLogicalParts(uint64_t extendedStart, int partNum);
    int WriteMBRData(void);
    int WriteMBRData(DiskIO *theDisk);
-   int WriteMBRData(const string & deviceFilename);
+   int WriteMBRData(const std::string & deviceFilename);
    int WriteMBRData(struct TempMBR & mbr, DiskIO *theDisk, uint64_t sector);
    void DiskSync(void) {myDisk->DiskSync();}
    void SetDisk(DiskIO *theDisk);
@@ -147,7 +145,7 @@
    uint64_t GetLength(int i);
 
    // User interaction functions....
-   int DoMenu(const string& prompt = "\nMBR command (? for help): ");
+   int DoMenu(const std::string& prompt = "\nMBR command (? for help): ");
    void ShowCommands(void);
 }; // class BasicMBRData
 
diff --git a/bsd.cc b/bsd.cc
index 59557c2..1ef7c81 100644
--- a/bsd.cc
+++ b/bsd.cc
@@ -7,9 +7,7 @@
   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 
 #define __STDC_LIMIT_MACROS
-#ifndef __STDC_CONSTANT_MACROS
 #define __STDC_CONSTANT_MACROS
-#endif
 
 #include <stdio.h>
 //#include <unistd.h>
@@ -46,7 +44,7 @@
 // just opens the device file and then calls an overloaded function to do
 // the bulk of the work. Returns 1 on success, 0 on failure.
 int BSDData::ReadBSDData(const string & device, uint64_t startSector, uint64_t endSector) {
-   int allOK = 1;
+   int allOK;
    DiskIO myDisk;
 
    if (device != "") {
@@ -66,7 +64,7 @@
 // Load the BSD disklabel data from an already-opened disk
 // file, starting with the specified sector number.
 int BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSector) {
-   int allOK = 1;
+   int allOK;
    int i, foundSig = 0, bigEnd = 0;
    int relative = 0; // assume absolute partition sector numbering
    uint8_t buffer[4096]; // I/O buffer
diff --git a/bsd.h b/bsd.h
index cbd3588..e042b7b 100644
--- a/bsd.h
+++ b/bsd.h
@@ -3,14 +3,14 @@
 /* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 
+#ifndef __BSD_STRUCTS
+#define __BSD_STRUCTS
+
 #include <stdint.h>
 #include <sys/types.h>
 #include "gptpart.h"
 #include "diskio.h"
 
-#ifndef __BSD_STRUCTS
-#define __BSD_STRUCTS
-
 #define BSD_SIGNATURE UINT32_C(0x82564557)  /* BSD disklabel signature ("magic") */
 
 // BSD disklabels can start at offsets of 64 or the sector size -- at least,
@@ -30,9 +30,6 @@
 // memory errors will occur.
 #define MAX_BSD_PARTS 64
 
-
-using namespace std;
-
 /****************************************
  *                                      *
  * BSDData class and related structures *
@@ -75,7 +72,7 @@
    public:
       BSDData(void);
       ~BSDData(void);
-      int ReadBSDData(const string & deviceFilename, uint64_t startSector, uint64_t endSector);
+      int ReadBSDData(const std::string & deviceFilename, uint64_t startSector, uint64_t endSector);
       int ReadBSDData(DiskIO *myDisk, uint64_t startSector, uint64_t endSector);
       void ReverseMetaBytes(void);
       void DisplayBSDData(void);
diff --git a/cgdisk.8 b/cgdisk.8
index 3dbddff..bc83d4b 100644
--- a/cgdisk.8
+++ b/cgdisk.8
@@ -1,6 +1,6 @@
-.\" Copyright 2011-2018 Roderick W. Smith (rodsmith@rodsbooks.com)
+.\" Copyright 2011-2022 Roderick W. Smith (rodsmith@rodsbooks.com)
 .\" May be distributed under the GNU General Public License
-.TH "CGDISK" "8" "1.0.4" "Roderick W. Smith" "GPT fdisk Manual"
+.TH "CGDISK" "8" "1.0.9" "Roderick W. Smith" "GPT fdisk Manual"
 .SH "NAME"
 cgdisk \- Curses-based GUID partition table (GPT) manipulator
 .SH "SYNOPSIS"
@@ -25,7 +25,7 @@
 
 For information on MBR vs. GPT, as well as GPT terminology and structure,
 see the extended GPT fdisk documentation at
-\fIhttp://www.rodsbooks.com/gdisk/\fR or consult Wikipedia.
+\fIhttps://www.rodsbooks.com/gdisk/\fR or consult Wikipedia.
 
 The \fBcgdisk\fR program employs a user interface similar to that of Linux's
 \fBcfdisk\fR, but \fBcgdisk\fR modifies GPT partitions. It also has the
@@ -172,7 +172,7 @@
 
 Available options are as described below. (Note that \fBcgdisk\fR provides
 a much more limited set of options than its sibling \fBgdisk\fR. If you
-need to perform partition table recovery, hybrid MBR modifcation, or other
+need to perform partition table recovery, hybrid MBR modification, or other
 advanced operations, you should consult the \fBgdisk\fR documentation.)
 
 .TP 
@@ -186,8 +186,13 @@
 performance for all of these disk types. On pre\-partitioned disks, GPT
 fdisk attempts to identify the alignment value used on that disk, but will
 set 8-sector alignment on disks larger than 300 GB even if lesser alignment
-values are detected. In either case, it can be changed by using this
-option.
+values are detected. In either case, it can be changed by using this option.
+The alignment value also affects the default end sector value when creating
+a new partition; it will be aligned to one less than a multiple of the
+alignment value, when possible. This should keep partitions a multiple of
+the alignment value in size. Some disk encryption tools require partitions
+to be sized to some value, typically 4096 bytes, so the default alignment of
+1 MiB works well for them.
 
 .TP 
 .B Backup
@@ -263,9 +268,9 @@
 have one and \fBcgdisk\fR doesn't know it. If you don't know the type code
 for your partition, you can type \fBL\fR to see a list of known type codes.
 The type code list may optionally be filtered by a search string; for
-instance, entering \fI\fBLinux\fR\fR shows only partition type codes with
+instance, entering \fI\fBlinux\fR\fR shows only partition type codes with
 descriptions that include the string \fILinux\fR. This search is performed
-case\-sensitively.
+case\-insensitively.
 
 .TP 
 .B Verify
@@ -369,7 +374,7 @@
 
 * Justin Maggard (justin.maggard@netgear.com)
 
-* Dwight Schauer (dschauer@gmail.com)
+* Dwight Schauer (das@teegra.net)
 
 * Florian Zumbiehl (florz@florz.de)
 
@@ -384,11 +389,11 @@
 .BR sgdisk (8),
 .BR fixparts (8).
 
-\fIhttp://en.wikipedia.org/wiki/GUID_Partition_Table\fR
+\fIhttps://en.wikipedia.org/wiki/GUID_Partition_Table\fR
 
-\fIhttp://developer.apple.com/technotes/tn2006/tn2166.html\fR
+\fIhttps://developer.apple.com/technotes/tn2006/tn2166.html\fR
 
-\fIhttp://www.rodsbooks.com/gdisk/\fR
+\fIhttps://www.rodsbooks.com/gdisk/\fR
 
 .SH "AVAILABILITY"
 The \fBcgdisk\fR command is part of the \fIGPT fdisk\fR package and is
diff --git a/current.spec b/current.spec
index e61a0ae..a912894 100644
--- a/current.spec
+++ b/current.spec
@@ -1,12 +1,12 @@
 Summary: GPT partitioning and MBR repair software
 Name: gptfdisk
-Version: 1.0.4
+Version: 1.0.9
 
 Release: 1%{?dist}
 License: GPLv2
 URL: http://www.rodsbooks.com/gdisk
 Group: Applications/System
-Source: http://www.rodsbooks.com/gdisk/gptfdisk-1.0.4.tar.gz
+Source: http://www.rodsbooks.com/gdisk/gptfdisk-1.0.9.tar.gz
 BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
 
 %description
@@ -81,5 +81,5 @@
 
 
 %changelog
-* Thu Jul 5 2018 R Smith <rodsmith@rodsbooks.com> - 1.0.4
-- Created spec file for 1.0.4 release
+* Thu Apr 14 2022 R Smith <rodsmith@rodsbooks.com> - 1.0.9
+- Created spec file for 1.0.9 release
diff --git a/diskio-unix.cc b/diskio-unix.cc
index 6d3e5b1..0897c56 100644
--- a/diskio-unix.cc
+++ b/diskio-unix.cc
@@ -13,9 +13,7 @@
 // under the terms of the GNU GPL version 2, as detailed in the COPYING file.
 
 #define __STDC_LIMIT_MACROS
-#ifndef __STDC_CONSTANT_MACROS
 #define __STDC_CONSTANT_MACROS
-#endif
 
 #include <sys/ioctl.h>
 #include <string.h>
@@ -39,6 +37,14 @@
 
 using namespace std;
 
+#if defined(__APPLE__) || defined(__linux__)
+#define off64_t off_t
+#define stat64 stat
+#define fstat64 fstat
+#define lstat64 lstat
+#define lseek64 lseek
+#endif
+
 // Returns the official "real" name for a shortened version of same.
 // Trivial here; more important in Windows
 void DiskIO::MakeRealName(void) {
@@ -374,7 +380,7 @@
 // size with the number of bytes read.
 // Returns the number of bytes written.
 int DiskIO::Write(void* buffer, int numBytes) {
-   int blockSize = 512, i, numBlocks, retval = 0;
+   int blockSize, i, numBlocks, retval = 0;
    char* tempSpace;
 
    // If disk isn't open, try to open it....
@@ -426,7 +432,7 @@
 // return correct values for disk image files.
 uint64_t DiskIO::DiskSize(int *err) {
    uint64_t sectors = 0; // size in sectors
-   off_t bytes = 0; // size in bytes
+   off64_t bytes = 0; // size in bytes
    struct stat64 st;
    int platformFound = 0;
 #ifdef __sun__
diff --git a/diskio.cc b/diskio.cc
index 7a89d09..556138e 100644
--- a/diskio.cc
+++ b/diskio.cc
@@ -13,9 +13,7 @@
 // under the terms of the GNU GPL version 2, as detailed in the COPYING file.
 
 #define __STDC_LIMIT_MACROS
-#ifndef __STDC_CONSTANT_MACROS
 #define __STDC_CONSTANT_MACROS
-#endif
 
 #ifdef _WIN32
 #include <windows.h>
diff --git a/diskio.h b/diskio.h
index 8521b8e..dec56ad 100644
--- a/diskio.h
+++ b/diskio.h
@@ -37,8 +37,6 @@
 #include "support.h"
 //#include "parttypes.h"
 
-using namespace std;
-
 /***************************************
  *                                     *
  * DiskIO class and related structures *
@@ -47,9 +45,9 @@
 
 class DiskIO {
    protected:
-      string userFilename;
-      string realFilename;
-      string modelName;
+      std::string userFilename;
+      std::string realFilename;
+      std::string modelName;
       int isOpen;
       int openForWrite;
 #ifdef _WIN32
@@ -70,9 +68,9 @@
 #ifdef ENABLE_HEAP_DISKIO
       int OpenForRead(const unsigned char* data, size_t size);
 #endif
-      int OpenForRead(const string & filename);
+      int OpenForRead(const std::string & filename);
       int OpenForRead(void);
-      int OpenForWrite(const string & filename);
+      int OpenForWrite(const std::string & filename);
       int OpenForWrite(void);
       void Close();
       int Seek(uint64_t sector);
@@ -81,12 +79,12 @@
       int DiskSync(void); // resync disk caches to use new partitions
       int GetBlockSize(void);
       int GetPhysBlockSize(void);
-      string GetModel(void) {return modelName;}
+      std::string GetModel(void) {return modelName;}
       uint32_t GetNumHeads(void);
       uint32_t GetNumSecsPerTrack(void);
       int IsOpen(void) {return isOpen;}
       int IsOpenForWrite(void) {return openForWrite;}
-      string GetName(void) const {return realFilename;}
+      std::string GetName(void) const {return realFilename;}
 
       uint64_t DiskSize(int* err);
 }; // class DiskIO
diff --git a/fixparts.8 b/fixparts.8
index 9857b24..25d05ad 100644
--- a/fixparts.8
+++ b/fixparts.8
@@ -1,6 +1,6 @@
-.\" Copyright 2011-2018 Roderick W. Smith (rodsmith@rodsbooks.com)
+.\" Copyright 2011-2022 Roderick W. Smith (rodsmith@rodsbooks.com)
 .\" May be distributed under the GNU General Public License
-.TH "FIXPARTS" "8" "1.0.4" "Roderick W. Smith" "FixParts Manual"
+.TH "FIXPARTS" "8" "1.0.9" "Roderick W. Smith" "FixParts Manual"
 .SH "NAME"
 fixparts \- MBR partition table repair utility
 .SH "SYNOPSIS"
@@ -258,7 +258,7 @@
 
 * Justin Maggard (justin.maggard@netgear.com)
 
-* Dwight Schauer (dschauer@gmail.com)
+* Dwight Schauer (das@teegra.net)
 
 * Florian Zumbiehl (florz@florz.de)
 
@@ -273,9 +273,9 @@
 .BR gdisk (8),
 .BR sgdisk (8).
 
-\fIhttp://en.wikipedia.org/wiki/Master_boot_record\fR
+\fIhttps://en.wikipedia.org/wiki/Master_boot_record\fR
 
-\fIhttp://www.rodsbooks.com/fixparts/\fR
+\fIhttps://www.rodsbooks.com/fixparts/\fR
 
 .SH "AVAILABILITY"
 The \fBfixparts\fR command is part of the \fIGPT fdisk\fR package and is
diff --git a/gdisk.8 b/gdisk.8
index dfdaa2c..8c9929b 100644
--- a/gdisk.8
+++ b/gdisk.8
@@ -1,6 +1,6 @@
-.\" Copyright 2011-2018 Roderick W. Smith (rodsmith@rodsbooks.com)
+.\" Copyright 2011-2022 Roderick W. Smith (rodsmith@rodsbooks.com)
 .\" May be distributed under the GNU General Public License
-.TH "GDISK" "8" "1.0.4" "Roderick W. Smith" "GPT fdisk Manual"
+.TH "GDISK" "8" "1.0.9" "Roderick W. Smith" "GPT fdisk Manual"
 .SH "NAME"
 gdisk \- Interactive GUID partition table (GPT) manipulator
 .SH "SYNOPSIS"
@@ -27,7 +27,7 @@
 main and backup data, as well as between the GPT headers and the partition
 tables. For information on MBR vs. GPT, as well as GPT terminology and
 structure, see the extended \fBgdisk\fR documentation at
-\fIhttp://www.rodsbooks.com/gdisk/\fR or consult Wikipedia.
+\fIhttps://www.rodsbooks.com/gdisk/\fR or consult Wikipedia.
 
 The \fBgdisk\fR program employs a user interface similar to that of Linux's
 \fBfdisk\fR, but \fBgdisk\fR modifies GPT partitions. It also has the
@@ -191,9 +191,9 @@
 such as 0xa500 for a FreeBSD disklabel, 0xa501 for FreeBSD boot, 0xa502 for
 FreeBSD swap, and so on. Note that these two\-byte codes are unique to
 \fBgdisk\fR. The type code list may optionally be filtered by a search
-string; for instance, entering \fI\fBLinux\fR\fR shows only partition type
+string; for instance, entering \fI\fBlinux\fR\fR shows only partition type
 codes with descriptions that include the string \fILinux\fR. This search is
-performed case\-sensitively.
+performed case\-insensitively.
 
 .TP 
 .B n
@@ -210,7 +210,8 @@
 before the last available sector. Pressing the Enter key with no input
 specifies the default value, which is the start of the largest available
 block for the start sector and the end of the same block for the end
-sector.
+sector. Default start and end points may be adjusted to optimize partition
+alignment.
 
 .TP 
 .B o
@@ -420,6 +421,14 @@
 ignore these attributes.
 
 .TP 
+.B b
+Swap the byte order for the name of the specified partition. Some
+partitioning tools, including GPT fdisk 1.0.7 and earlier, can write the
+partition name in the wrong byte order on big-endian computers, such as the
+IBM s390 mainframes and PowerPC-based Macs. This feature corrects this
+problem.
+
+.TP 
 .B c
 Change partition GUID. You can enter a custom unique GUID for a partition
 using this option. (Note this refers to the GUID that uniquely identifies a
@@ -483,13 +492,18 @@
 physical sectors (such as modern Advanced Format drives), some RAID
 configurations, and many SSD devices, can suffer performance problems if
 partitions are not aligned properly for their internal data structures. On
-new disks, GPT fdisk attempts to align partitions on 1 MiB boundaries
-(2048\-sectors on disks with 512-byte sectors) by default, which optimizes
+new disks, GPT fdisk attempts to align partitions on 1 MiB boundaries (2048
+sectors on disks with 512-byte sectors) by default, which optimizes
 performance for all of these disk types. On pre\-partitioned disks, GPT
 fdisk attempts to identify the alignment value used on that disk, but will
 set 8-sector alignment on disks larger than 300 GB even if lesser alignment
-values are detected. In either case, it can be changed by using this
-option.
+values are detected. In either case, it can be changed by using this option.
+The alignment value also affects the default end sector value when creating
+a new partition; it will be aligned to one less than a multiple of the
+alignment value, if possible. This should keep partitions a multiple of the
+alignment value in size. Some disk encryption tools require partitions to be
+sized to some value, typically 4096 bytes, so the default alignment of 1 MiB
+works well for them.
 
 .TP 
 .B m
@@ -673,7 +687,7 @@
 
 * Justin Maggard (justin.maggard@netgear.com)
 
-* Dwight Schauer (dschauer@gmail.com)
+* Dwight Schauer (das@teegra.net)
 
 * Florian Zumbiehl (florz@florz.de)
 
@@ -688,11 +702,11 @@
 .BR sgdisk (8),
 .BR fixparts (8).
 
-\fIhttp://en.wikipedia.org/wiki/GUID_Partition_Table\fR
+\fIhttps://en.wikipedia.org/wiki/GUID_Partition_Table\fR
 
-\fIhttp://developer.apple.com/technotes/tn2006/tn2166.html\fR
+\fIhttps://developer.apple.com/technotes/tn2006/tn2166.html\fR
 
-\fIhttp://www.rodsbooks.com/gdisk/\fR
+\fIhttps://www.rodsbooks.com/gdisk/\fR
 
 .SH "AVAILABILITY"
 The \fBgdisk\fR command is part of the \fIGPT fdisk\fR package and is
diff --git a/gdisk.cc b/gdisk.cc
index 5f85498..c9443bd 100644
--- a/gdisk.cc
+++ b/gdisk.cc
@@ -11,6 +11,8 @@
 #include <iostream>
 #include "gpttext.h"
 
+using namespace std;
+
 int main(int argc, char* argv[]) {
    GPTDataTextUI theGPT;
    string device = "";
diff --git a/gpt.cc b/gpt.cc
index 8ab6975..e8e0878 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -3,13 +3,11 @@
 
 /* By Rod Smith, initial coding January to February, 2009 */
 
-/* This program is copyright (c) 2009-2018 by Roderick W. Smith. It is distributed
+/* This program is copyright (c) 2009-2022 by Roderick W. Smith. It is distributed
   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 
 #define __STDC_LIMIT_MACROS
-#ifndef __STDC_CONSTANT_MACROS
 #define __STDC_CONSTANT_MACROS
-#endif
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -82,6 +80,8 @@
    beQuiet = 0;
    whichWasUsed = use_new;
    mainHeader.numParts = 0;
+   mainHeader.firstUsableLBA = 0;
+   mainHeader.lastUsableLBA = 0;
    numParts = 0;
    SetGPTSize(NUM_GPT_ENTRIES);
    // Initialize CRC functions...
@@ -145,6 +145,7 @@
    beQuiet = 0;
    whichWasUsed = use_new;
    mainHeader.numParts = 0;
+   mainHeader.lastUsableLBA = 0;
    numParts = 0;
    // Initialize CRC functions...
    chksum_crc32gentab();
@@ -412,6 +413,11 @@
               << "in degraded performance on some modern (2009 and later) hard disks.\n";
          alignProbs++;
       } // if
+      if ((partitions[i].IsUsed()) && ((partitions[i].GetLastLBA() + 1) % testAlignment) != 0) {
+         cout << "\nCaution: Partition " << i + 1 << " doesn't end on a "
+              << testAlignment << "-sector boundary. This may\nresult "
+              << "in problems with some disk encryption tools.\n";
+      } // if
    } // for
    if (alignProbs > 0)
       cout << "\nConsult http://www.ibm.com/developerworks/linux/library/l-4kb-sector-disks/\n"
@@ -584,7 +590,7 @@
 // byte order and then undoes that reversal.)
 void GPTData::RecomputeCRCs(void) {
    uint32_t crc, hSize;
-   int littleEndian = 1;
+   int littleEndian;
 
    // If the header size is bigger than the GPT header data structure, reset it;
    // otherwise, set both header sizes to whatever the main one is....
@@ -888,8 +894,16 @@
             break;
       } // switch
 
-      if (allOK)
+      if (allOK) {
          CheckGPTSize();
+         // Below is unlikely to happen on real disks, but could happen if
+         // the user is manipulating a truncated image file....
+         if (diskSize <= GetTableSizeInSectors() * 2 + 3) {
+             allOK = 0;
+             cout << "Disk is too small to hold GPT data (" << diskSize
+                  << " sectors)! Aborting!\n";
+         }
+      }
       myDisk.Close();
       ComputeAlignment();
    } else {
@@ -1048,6 +1062,22 @@
    } // if
    *crcOk = CheckHeaderCRC(&tempHeader);
 
+   if (tempHeader.sizeOfPartitionEntries != sizeof(GPTPart)) {
+      // Print the below warning only if the CRC is OK -- but correct the
+      // problem either way. The warning is printed only on a valid CRC
+      // because otherwise this warning will display inappropriately when
+      // reading MBR disks. If the CRC is invalid, then a warning about
+      // that will be shown later, so the user will still know that
+      // something is wrong.
+      if (*crcOk) {
+         cerr << "Warning: Partition table header claims that the size of partition table\n";
+         cerr << "entries is " << tempHeader.sizeOfPartitionEntries << " bytes, but this program ";
+         cerr << " supports only " << sizeof(GPTPart) << "-byte entries.\n";
+         cerr << "Adjusting accordingly, but partition table may be garbage.\n";
+      }
+      tempHeader.sizeOfPartitionEntries = sizeof(GPTPart);
+   }
+
    if (allOK && (numParts != tempHeader.numParts) && *crcOk) {
       allOK = SetGPTSize(tempHeader.numParts, 0);
    }
@@ -2135,7 +2165,6 @@
       // Check to see that every sector between the earlier one and the
       // requested one is clear, and that it's not too early....
       if (earlier >= mainHeader.firstUsableLBA) {
-         sectorOK = 1;
          testSector = earlier;
          do {
             sectorOK = IsFree(testSector++);
@@ -2148,7 +2177,6 @@
 
       // If couldn't move the sector earlier, try to move it later instead....
       if ((sectorOK != 1) && (later <= mainHeader.lastUsableLBA)) {
-         sectorOK = 1;
          testSector = later;
          do {
             sectorOK = IsFree(testSector--);
@@ -2327,18 +2355,28 @@
 } // GPTData::FindLastAvailable()
 
 // Find the last available block in the free space pointed to by start.
-uint64_t GPTData::FindLastInFree(uint64_t start) {
-   uint64_t nearestStart;
+// If align == true, returns the last sector that's aligned on the
+// system alignment value (unless that's less than the start value);
+// if align == false, returns the last available block regardless of
+// alignment. (The align variable is set to false by default.)
+uint64_t GPTData::FindLastInFree(uint64_t start, bool align) {
+   uint64_t nearestEnd, endPlus;
    uint32_t i;
 
-   nearestStart = mainHeader.lastUsableLBA;
+   nearestEnd = mainHeader.lastUsableLBA;
    for (i = 0; i < numParts; i++) {
-      if ((nearestStart > partitions[i].GetFirstLBA()) &&
+      if ((nearestEnd > partitions[i].GetFirstLBA()) &&
           (partitions[i].GetFirstLBA() > start)) {
-         nearestStart = partitions[i].GetFirstLBA() - 1;
+         nearestEnd = partitions[i].GetFirstLBA() - 1;
       } // if
    } // for
-   return (nearestStart);
+   if (align) {
+       endPlus = nearestEnd + 1;
+       if (Align(&endPlus) && IsFree(endPlus - 1) && (endPlus > start)) {
+           nearestEnd = endPlus - 1;
+       } // if
+   } // if
+   return (nearestEnd);
 } // GPTData::FindLastInFree()
 
 // Finds the total number of free blocks, the number of segments in which
@@ -2415,7 +2453,10 @@
  ***********************************************************/
 
 // Set partition alignment value; partitions will begin on multiples of
-// the specified value
+// the specified value, and the default end values will be set so that
+// partition sizes are multiples of this value in cgdisk and gdisk, too.
+// (In sgdisk, end-alignment is done only if the '-I' command-line option
+// is used.)
 void GPTData::SetAlignment(uint32_t n) {
    if (n > 0) {
       sectorAlignment = n;
@@ -2445,7 +2486,7 @@
 // is used on big disks (as safety for Advanced Format drives).
 // Returns the computed alignment value.
 uint32_t GPTData::ComputeAlignment(void) {
-   uint32_t i = 0, found, exponent = 31;
+   uint32_t i = 0, found, exponent;
    uint32_t align = DEFAULT_ALIGNMENT;
 
    if (blockSize > 0)
diff --git a/gpt.h b/gpt.h
index 0712a1f..6e1e0bb 100644
--- a/gpt.h
+++ b/gpt.h
@@ -1,9 +1,12 @@
 /* gpt.h -- GPT and data structure definitions, types, and
    functions */
 
-/* This program is copyright (c) 2009-2011 by Roderick W. Smith. It is distributed
+/* This program is copyright (c) 2009-2022 by Roderick W. Smith. It is distributed
   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 
+#ifndef __GPTSTRUCTS
+#define __GPTSTRUCTS
+
 #include <stdint.h>
 #include <sys/types.h>
 #include "gptpart.h"
@@ -12,9 +15,6 @@
 #include "bsd.h"
 #include "gptpart.h"
 
-#ifndef __GPTSTRUCTS
-#define __GPTSTRUCTS
-
 // Default values for sector alignment
 #define DEFAULT_ALIGNMENT 2048
 #define MAX_ALIGNMENT 65536
@@ -24,8 +24,6 @@
 // smallest Advanced Format drive I know of is 320GB in size
 #define SMALLEST_ADVANCED_FORMAT UINT64_C(585937500)
 
-using namespace std;
-
 /****************************************
  *                                      *
  * GPTData class and related structures *
@@ -67,7 +65,7 @@
    uint32_t numParts; // # of partitions the table can hold
    struct GPTHeader secondHeader;
    MBRData protectiveMBR;
-   string device; // device filename
+   std::string device; // device filename
    DiskIO myDisk;
    uint32_t blockSize; // device logical block size
    uint32_t physBlockSize; // device physical block size (or 0 if it can't be determined)
@@ -93,7 +91,7 @@
    // Basic necessary functions....
    GPTData(void);
    GPTData(const GPTData &);
-   GPTData(string deviceFilename);
+   GPTData(std::string deviceFilename);
    virtual ~GPTData(void);
    GPTData & operator=(const GPTData & orig);
 
@@ -111,19 +109,19 @@
    int FindInsanePartitions(void);
 
    // Load or save data from/to disk
-   int SetDisk(const string & deviceFilename);
+   int SetDisk(const std::string & deviceFilename);
    int SetDisk(const DiskIO & disk);
    DiskIO* GetDisk(void) {return &myDisk;}
-   int LoadMBR(const string & f) {return protectiveMBR.ReadMBRData(f);}
+   int LoadMBR(const std::string & f) {return protectiveMBR.ReadMBRData(f);}
    int WriteProtectiveMBR(void) {return protectiveMBR.WriteMBRData(&myDisk);}
    void PartitionScan(void);
-   int LoadPartitions(const string & deviceFilename);
+   int LoadPartitions(const std::string & deviceFilename);
    int ForceLoadGPTData(void);
    int LoadMainTable(void);
    int LoadSecondTableAsMain(void);
    int SaveGPTData(int quiet = 0);
-   int SaveGPTBackup(const string & filename);
-   int LoadGPTBackup(const string & filename);
+   int SaveGPTBackup(const std::string & filename);
+   int LoadGPTBackup(const std::string & filename);
    int SaveMBR(void);
    int DestroyGPT(void);
    int DestroyMBR(void);
@@ -186,7 +184,7 @@
    uint64_t FindFirstUsedLBA(void);
    uint64_t FindFirstInLargest(void);
    uint64_t FindLastAvailable();
-   uint64_t FindLastInFree(uint64_t start);
+   uint64_t FindLastInFree(uint64_t start, bool align = false);
    uint64_t FindFreeBlocks(uint32_t *numSegments, uint64_t *largestSegment);
    int IsFree(uint64_t sector, uint32_t *partNum = NULL);
    int IsFreePartNum(uint32_t partNum);
@@ -205,9 +203,9 @@
    void ReversePartitionBytes(); // for endianness
 
    // Attributes functions
-   int ManageAttributes(int partNum, const string & command, const string & bits);
+   int ManageAttributes(int partNum, const std::string & command, const std::string & bits);
    void ShowAttributes(const uint32_t partNum);
-   void GetAttribute(const uint32_t partNum, const string& attributeBits);
+   void GetAttribute(const uint32_t partNum, const std::string& attributeBits);
 
 }; // class GPTData
 
diff --git a/gptcl.cc b/gptcl.cc
index cb1701d..8162868 100644
--- a/gptcl.cc
+++ b/gptcl.cc
@@ -1,7 +1,7 @@
 /*
     Implementation of GPTData class derivative with popt-based command
     line processing
-    Copyright (C) 2010-2014 Roderick W. Smith
+    Copyright (C) 2010-2022 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
@@ -25,10 +25,13 @@
 #include <errno.h>
 #include "gptcl.h"
 
+using namespace std;
+
 GPTDataCL::GPTDataCL(void) {
    attributeOperation = backupFile = partName = hybrids = newPartInfo = NULL;
    mbrParts = twoParts = outDevice = typeCode = partGUID = diskGUID = NULL;
    alignment = DEFAULT_ALIGNMENT;
+   alignEnd = false;
    deletePartNum = infoPartNum = largestPartNum = bsdPartNum = 0;
    tableSize = GPT_SIZE;
 } // GPTDataCL constructor
@@ -63,6 +66,7 @@
    GPTData secondDevice;
    int opt, numOptions = 0, saveData = 0, neverSaveData = 0;
    int partNum = 0, newPartNum = -1, saveNonGPT = 1, retval = 0, pretend = 0;
+   int byteSwapPartNum = 0;
    uint64_t low, high, startSector, endSector, sSize, mainTableLBA;
    uint64_t temp; // temporary variable; free to use in any case
    char *device;
@@ -75,6 +79,7 @@
           "list|[partnum:show|or|nand|xor|=|set|clear|toggle|get[:bitnum|hexbitmask]]"},
       {"set-alignment", 'a', POPT_ARG_INT, &alignment, 'a', "set sector alignment", "value"},
       {"backup", 'b', POPT_ARG_STRING, &backupFile, 'b', "backup GPT to file", "file"},
+      {"byte-swap-name", 'B',  POPT_ARG_INT, &byteSwapPartNum, 'B', "byte-swap partition's name", "partnum"},
       {"change-name", 'c', POPT_ARG_STRING, &partName, 'c', "change partition's name", "partnum:name"},
       {"recompute-chs", 'C', POPT_ARG_NONE, NULL, 'C', "recompute CHS values in protective/hybrid MBR", ""},
       {"delete", 'd', POPT_ARG_INT, &deletePartNum, 'd', "delete a partition", "partnum"},
@@ -87,6 +92,7 @@
       {"randomize-guids", 'G', POPT_ARG_NONE, NULL, 'G', "randomize disk and partition GUIDs", ""},
       {"hybrid", 'h', POPT_ARG_STRING, &hybrids, 'h', "create hybrid MBR", "partnum[:partnum...][:EE]"},
       {"info", 'i', POPT_ARG_INT, &infoPartNum, 'i', "show detailed information on partition", "partnum"},
+      {"align-end", 'I', POPT_ARG_NONE, NULL, 'I', "align partition end points", ""},
       {"move-main-table", 'j', POPT_ARG_INT, &mainTableLBA, 'j', "adjust the location of the main partition table", "sector"},
       {"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", ""},
@@ -149,9 +155,10 @@
 
    // Assume first non-option argument is the device filename....
    device = (char*) poptGetArg(poptCon);
-   poptResetContext(poptCon);
 
    if (device != NULL) {
+      device = strdup(device);
+      poptResetContext(poptCon);
       JustLooking(); // reset as necessary
       BeQuiet(); // Tell called functions to be less verbose & interactive
       if (LoadPartitions((string) device)) {
@@ -190,17 +197,24 @@
                case 'a':
                   SetAlignment(alignment);
                   break;
+               case 'B':
+                  if (IsUsedPartNum(byteSwapPartNum - 1)) {
+                     partitions[byteSwapPartNum - 1].ReverseNameBytes();
+                     cout << "Changed partition " << byteSwapPartNum << "'s name to "
+                          << partitions[byteSwapPartNum - 1].GetDescription() << "\n";
+                     JustLooking(0);
+                     saveData = 1;
+                  }
+                  break;
                case 'b':
                   SaveGPTBackup(backupFile);
                   free(backupFile);
                   break;
                case 'c':
-                  cout << "Setting name!\n";
                   JustLooking(0);
                   partNum = (int) GetInt(partName, 1) - 1;
                   if (partNum < 0)
                      partNum = newPartNum;
-                  cout << "partNum is " << partNum << "\n";
                   if ((partNum >= 0) && (partNum < (int) GetNumParts())) {
                      name = GetString(partName, 2);
                      if (SetName(partNum, (UnicodeString) name.c_str())) {
@@ -262,6 +276,9 @@
                case 'i':
                   ShowPartDetails(infoPartNum - 1);
                   break;
+               case 'I':
+                  alignEnd = true;
+                  break;
                case 'j':
                    if (MoveMainTable(mainTableLBA)) {
                        JustLooking(0);
@@ -297,9 +314,9 @@
                      newPartNum = FindFirstFreePart();
                   low = FindFirstInLargest();
                   Align(&low);
-                  high = FindLastInFree(low);
-                  startSector = IeeeToInt(GetString(newPartInfo, 2), sSize, low, high, low);
-                  endSector = IeeeToInt(GetString(newPartInfo, 3), sSize, startSector, high, high);
+                  high = FindLastInFree(low, alignEnd);
+                  startSector = IeeeToInt(GetString(newPartInfo, 2), sSize, low, high, sectorAlignment, low);
+                  endSector = IeeeToInt(GetString(newPartInfo, 3), sSize, startSector, high, sectorAlignment, high);
                   if (CreatePartition(newPartNum, startSector, endSector)) {
                      saveData = 1;
                   } else {
@@ -313,9 +330,11 @@
                   JustLooking(0);
                   startSector = FindFirstInLargest();
                   Align(&startSector);
-                  endSector = FindLastInFree(startSector);
-                  if (largestPartNum <= 0)
+                  endSector = FindLastInFree(startSector, alignEnd);
+                  if (largestPartNum <= 0) {
                      largestPartNum = FindFirstFreePart() + 1;
+                     newPartNum = largestPartNum - 1;
+                  }
                   if (CreatePartition(largestPartNum - 1, startSector, endSector)) {
                      saveData = 1;
                   } else {
@@ -379,7 +398,7 @@
                         typeRaw[partNum] = StrToHex(raw, 0);
                      }
                      typeHelper = GetString(typeCode, 2);
-                     if ((typeHelper != (GUIDData) "00000000-0000-0000-0000-000000000000") &&
+                     if ((typeHelper != PartType::unusedPartType) &&
                          (ChangePartType(partNum, typeHelper))) {
                         saveData = 1;
                         } else {
@@ -486,6 +505,7 @@
          cerr << "Error encountered; not saving changes.\n";
          retval = 4;
       } // if
+      free(device);
    } // if (device != NULL)
    poptFreeContext(poptCon);
    return retval;
@@ -494,7 +514,7 @@
 // Create a hybrid or regular MBR from GPT data structures
 int GPTDataCL::BuildMBR(char* argument, int isHybrid) {
    int numParts, allOK = 1, i, origPartNum;
-   int eeLast, mbrNum = 0;
+   int eeLast = 0, mbrNum = 0;
    MBRPart newPart;
    BasicMBRData newMBR;
 
diff --git a/gptcl.h b/gptcl.h
index d8fa9ff..b937430 100644
--- a/gptcl.h
+++ b/gptcl.h
@@ -1,7 +1,7 @@
 /*
     Implementation of GPTData class derivative with popt-based command
     line processing
-    Copyright (C) 2010-2013 Roderick W. Smith
+    Copyright (C) 2010-2022 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
@@ -26,8 +26,6 @@
 #include <popt.h>
 #include <map>
 
-using namespace std;
-
 class GPTDataCL : public GPTData {
    protected:
       // Following are variables associated with popt parameters....
@@ -35,6 +33,7 @@
       char *newPartInfo, *mbrParts, *twoParts, *outDevice, *typeCode;
       char *partGUID, *diskGUID;
       int alignment, deletePartNum, infoPartNum, largestPartNum, bsdPartNum;
+      bool alignEnd;
       uint32_t tableSize;
       poptContext poptCon;
       std::map<int, char> typeRaw;
@@ -42,14 +41,14 @@
       int BuildMBR(char* argument, int isHybrid);
    public:
       GPTDataCL(void);
-      GPTDataCL(string filename);
+      GPTDataCL(std::string filename);
       ~GPTDataCL(void);
-      void LoadBackupFile(string backupFile, int &saveData, int &neverSaveData);
+      void LoadBackupFile(std::string backupFile, int &saveData, int &neverSaveData);
       int DoOptions(int argc, char* argv[]);
 }; // class GPTDataCL
 
 int CountColons(char* argument);
-uint64_t GetInt(const string & argument, int itemNum);
-string GetString(string argument, int itemNum);
+uint64_t GetInt(const std::string & argument, int itemNum);
+std::string GetString(std::string argument, int itemNum);
 
 #endif
diff --git a/gptcurses.cc b/gptcurses.cc
index 4ebfde1..64cc514 100644
--- a/gptcurses.cc
+++ b/gptcurses.cc
@@ -1,7 +1,7 @@
 /*
  *    Implementation of GPTData class derivative with curses-based text-mode
  *    interaction
- *    Copyright (C) 2011-2018 Roderick W. Smith
+ *    Copyright (C) 2011-2022 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
@@ -23,7 +23,11 @@
 #include <iostream>
 #include <string>
 #include <sstream>
+#if defined (__APPLE__) || (__FreeBSD__)
 #include <ncurses.h>
+#else
+#include <ncursesw/ncurses.h>
+#endif
 #include "gptcurses.h"
 #include "support.h"
 
@@ -86,7 +90,7 @@
 // unpartitioned space on the disk.
 // Returns the number of Spaces created.
 int GPTDataCurses::MakeSpacesFromParts(void) {
-   uint i;
+   uint32_t i;
    Space *tempSpace;
 
    EmptySpaces();
@@ -235,22 +239,22 @@
       ClearLine(lineNum);
       if (space->partNum == -1) { // space is empty
          move(lineNum, 12);
-         printw(BytesToIeee((space->lastLBA - space->firstLBA + 1), blockSize).c_str());
+         printw("%s", BytesToIeee((space->lastLBA - space->firstLBA + 1), blockSize).c_str());
          move(lineNum, 24);
          printw("free space");
       } else { // space holds a partition
          move(lineNum, 3);
          printw("%d", space->partNum + 1);
          move(lineNum, 12);
-         printw(BytesToIeee((space->lastLBA - space->firstLBA + 1), blockSize).c_str());
+         printw("%s", BytesToIeee((space->lastLBA - space->firstLBA + 1), blockSize).c_str());
          move(lineNum, 24);
-         printw(space->origPart->GetTypeName().c_str());
+         printw("%s", space->origPart->GetTypeName().c_str());
          move(lineNum, 50);
          #ifdef USE_UTF16
          space->origPart->GetDescription().extract(0, 39, temp, 39);
          printw(temp);
          #else
-         printw(space->origPart->GetDescription().c_str());
+         printw("%s", space->origPart->GetDescription().c_str());
          #endif
       } // if/else
    } // if
@@ -267,10 +271,10 @@
 
    move(lineNum++, 0);
    theLine = "Part. #     Size        Partition Type            Partition Name";
-   printw(theLine.c_str());
+   printw("%s", theLine.c_str());
    move(lineNum++, 0);
    theLine = "----------------------------------------------------------------";
-   printw(theLine.c_str());
+   printw("%s", theLine.c_str());
    numToShow = LINES - RESERVED_TOP - RESERVED_BOTTOM;
    pageNum = selected / numToShow;
    for (i = pageNum * numToShow; i <= (pageNum + 1) * numToShow - 1; i++) {
@@ -329,13 +333,13 @@
    printw("Partition GUID code: %s (%s)\n", partitions[partNum].GetType().AsString().c_str(),
           partitions[partNum].GetTypeName().c_str());
    printw("Partition unique GUID: %s\n", partitions[partNum].GetUniqueGUID().AsString().c_str());
-   printw("First sector: %lld (at %s)\n", partitions[partNum].GetFirstLBA(),
+   printw("First sector: %llu (at %s)\n", (long long unsigned int) partitions[partNum].GetFirstLBA(),
           BytesToIeee(partitions[partNum].GetFirstLBA(), blockSize).c_str());
-   printw("Last sector: %lld (at %s)\n", partitions[partNum].GetLastLBA(),
+   printw("Last sector: %llu (at %s)\n", (long long unsigned int) partitions[partNum].GetLastLBA(),
           BytesToIeee(partitions[partNum].GetLastLBA(), blockSize).c_str());
    size = partitions[partNum].GetLastLBA() - partitions[partNum].GetFirstLBA() + 1;
-   printw("Partition size: %lld sectors (%s)\n", size, BytesToIeee(size, blockSize).c_str());
-   printw("Attribute flags: %016x\n", partitions[partNum].GetAttributes().GetAttributes());
+   printw("Partition size: %llu sectors (%s)\n", (long long unsigned int) size, BytesToIeee(size, blockSize).c_str());
+   printw("Attribute flags: %016llx\n", (long long unsigned int) partitions[partNum].GetAttributes().GetAttributes());
    #ifdef USE_UTF16
    partitions[partNum].GetDescription().extract(0, NAME_SIZE , temp, NAME_SIZE );
    printw("Partition name: '%s'\n", temp);
@@ -426,34 +430,43 @@
 
 // Create a new partition in the space pointed to by currentSpace.
 void GPTDataCurses::MakeNewPart(void) {
-   uint64_t size, newFirstLBA = 0, newLastLBA = 0;
+   uint64_t size, newFirstLBA = 0, newLastLBA = 0, lastAligned;
    int partNum;
    char inLine[80];
 
    move(LINES - 4, 0);
    clrtobot();
+   lastAligned = currentSpace->lastLBA + 1;
+   Align(&lastAligned);
+   lastAligned--;
+   // Discard end-alignment attempt if it's giving us an invalid end point....
+   if (!IsFree(lastAligned))
+       lastAligned = currentSpace->lastLBA;
    while ((newFirstLBA < currentSpace->firstLBA) || (newFirstLBA > currentSpace->lastLBA)) {
-      newFirstLBA = currentSpace->firstLBA;
       move(LINES - 4, 0);
       clrtoeol();
       newFirstLBA = currentSpace->firstLBA;
       Align(&newFirstLBA);
-      printw("First sector (%lld-%lld, default = %lld): ", newFirstLBA, currentSpace->lastLBA, newFirstLBA);
+      printw("First sector (%llu-%llu, default = %llu): ", (long long unsigned int) newFirstLBA,
+             (long long unsigned int) currentSpace->lastLBA, (long long unsigned int) newFirstLBA);
       echo();
       getnstr(inLine, 79);
       noecho();
-      newFirstLBA = IeeeToInt(inLine, blockSize, currentSpace->firstLBA, currentSpace->lastLBA, newFirstLBA);
+      newFirstLBA = IeeeToInt(inLine, blockSize, currentSpace->firstLBA, currentSpace->lastLBA, sectorAlignment, newFirstLBA);
       Align(&newFirstLBA);
    } // while
-   size = currentSpace->lastLBA - newFirstLBA + 1;
+   if (newFirstLBA > lastAligned)
+      size = currentSpace->lastLBA - newFirstLBA + 1;
+   else
+      size = lastAligned - newFirstLBA + 1;
    while ((newLastLBA > currentSpace->lastLBA) || (newLastLBA < newFirstLBA)) {
       move(LINES - 3, 0);
       clrtoeol();
-      printw("Size in sectors or {KMGTP} (default = %lld): ", size);
+      printw("Size in sectors or {KMGTP} (default = %llu): ", (long long unsigned int) size);
       echo();
       getnstr(inLine, 79);
       noecho();
-      newLastLBA = newFirstLBA + IeeeToInt(inLine, blockSize, 1, size, size) - 1;
+      newLastLBA = newFirstLBA + IeeeToInt(inLine, blockSize, 1, size, sectorAlignment, size) - 1;
    } // while
    partNum = FindFirstFreePart();
    if (CreatePartition(partNum, newFirstLBA, newLastLBA)) { // created OK; set type code & name....
@@ -596,7 +609,7 @@
 // Show user's options. Refers to currentSpace to determine which options to show.
 // Highlights the option with the key selectedKey; or a default if that's invalid.
 void GPTDataCurses::DisplayOptions(char selectedKey) {
-   uint i, j = 0, firstLine, numPerLine;
+   uint64_t i, j = 0, firstLine, numPerLine;
    string optionName, optionDesc = "";
 
    if (currentSpace != NULL) {
@@ -633,7 +646,7 @@
          } // if/else
       } // for
       move(LINES - 1, (COLS - optionDesc.length()) / 2);
-      printw(optionDesc.c_str());
+      printw("%s", optionDesc.c_str());
       currentKey = selectedKey;
    } // if
 } // GPTDataCurses::DisplayOptions()
@@ -745,11 +758,11 @@
 
    clear();
    move(0, (COLS - title.length()) / 2);
-   printw(title.c_str());
+   printw("%s", title.c_str());
    move(2, (COLS - drive.length()) / 2);
-   printw(drive.c_str());
+   printw("%s", drive.c_str());
    move(3, (COLS - size.str().length()) / 2);
-   printw(size.str().c_str());
+   printw("%s", size.str().c_str());
    DisplayParts(currentSpaceNum);
 } // DrawMenu
 
@@ -799,7 +812,7 @@
 void Report(string theText) {
    clear();
    move(0, 0);
-   printw(theText.c_str());
+   printw("%s", theText.c_str());
    move(LINES - 2, (COLS - 29) / 2);
    printw("Press any key to continue....");
    cbreak();
diff --git a/gptcurses.h b/gptcurses.h
index f153de2..8d2ecaf 100644
--- a/gptcurses.h
+++ b/gptcurses.h
@@ -19,20 +19,18 @@
  *
  */
 
+#ifndef __GPT_CURSES
+#define __GPT_CURSES
+
 #include <iostream>
 #include <string>
 #include "gptpart.h"
 #include "gpt.h"
 
-#ifndef __GPT_CURSES
-#define __GPT_CURSES
-
-using namespace std;
-
 struct MenuItem {
    int key; // Keyboard shortcut
-   string name; // Item name; 8 characters
-   string desc; // Description
+   std::string name; // Item name; 8 characters
+   std::string desc; // Description
 };
 
 static struct MenuItem menuMain[] = {
@@ -81,7 +79,7 @@
    Space *lastSpace;
    Space *currentSpace;
    int currentSpaceNum;
-   string whichOptions;
+   std::string whichOptions;
    char currentKey;
    int numSpaces;
    int displayType;
@@ -130,7 +128,7 @@
 void ClearLine(int lineNum);
 void ClearBottom(void);
 void PromptToContinue(void);
-void Report(string theText);
+void Report(std::string theText);
 void ShowTypes(void);
 
 #endif
diff --git a/gptpart.cc b/gptpart.cc
index 1583bca..5fe7b5a 100644
--- a/gptpart.cc
+++ b/gptpart.cc
@@ -13,21 +13,18 @@
 // under the terms of the GNU GPL version 2, as detailed in the COPYING file.
 
 #define __STDC_LIMIT_MACROS
-#ifndef __STDC_CONSTANT_MACROS
 #define __STDC_CONSTANT_MACROS
-#endif
-
-#ifdef USE_UTF16
-#include <unicode/ustdio.h>
-#else
-#define UnicodeString string
-#endif
 
 #include <string.h>
 #include <stdio.h>
 #include <iostream>
 #include "gptpart.h"
 #include "attributes.h"
+#ifdef USE_UTF16
+#include <unicode/ustdio.h>
+#else
+#define UnicodeString std::string
+#endif
 
 using namespace std;
 
@@ -94,7 +91,6 @@
    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 ) {
@@ -245,7 +241,6 @@
       // then to utf16le
       if ( uni < 0x10000 ) {
          name[ pos ] = (uint16_t) uni ;
-         if ( ! IsLittleEndian() ) ReverseBytes( name + pos , 2 ) ;
          pos ++ ;
       } // if
       else {
@@ -255,10 +250,8 @@
          } // 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
@@ -418,14 +411,18 @@
 // Reverse the bytes of integral data types and of the UTF-16LE name;
 // used on big-endian systems.
 void GPTPart::ReversePartBytes(void) {
-   int i;
-
    ReverseBytes(&firstLBA, 8);
    ReverseBytes(&lastLBA, 8);
    ReverseBytes(&attributes, 8);
+   ReverseNameBytes();
+} // GPTPart::ReversePartBytes()
+
+void GPTPart::ReverseNameBytes(void) {
+   int i;
+
    for (i = 0; i < NAME_SIZE; i ++ )
       ReverseBytes(name + i, 2);
-} // GPTPart::ReverseBytes()
+} // GPTPart::ReverseNameBytes()
 
 /****************************************
  * Functions requiring user interaction *
@@ -436,7 +433,7 @@
 void GPTPart::ChangeType(void) {
    string line;
    int changeName;
-   PartType tempType = (GUIDData) "00000000-0000-0000-0000-000000000000";
+   PartType tempType = PartType::unusedPartType;
 
 #ifdef USE_UTF16
    changeName = (GetDescription() == GetUTypeName());
@@ -444,19 +441,19 @@
    changeName = (GetDescription() == GetTypeName());
 #endif
 
-   cout << "Current type is '" << GetTypeName() << "'\n";
+   cout << "Current type is " << hex << GetHexType() << dec << " (" << GetTypeName() << ")\n";
    do {
-      cout << "Hex code or GUID (L to show codes, Enter = " << hex << DEFAULT_GPT_TYPE << dec << "): ";
+      cout << "Hex code or GUID (L to show codes, Enter = " << hex << GetHexType() << dec << "): ";
       line = ReadString();
       if ((line[0] == 'L') || (line[0] == 'l')) {
          partitionType.ShowAllTypes();
       } else {
          if (line.length() == 0)
-            tempType = DEFAULT_GPT_TYPE;
+            tempType = GetHexType();
          else
             tempType = line;
       } // if/else
-   } while (tempType == (GUIDData) "00000000-0000-0000-0000-000000000000");
+   } while (tempType == PartType::unusedPartType);
    partitionType = tempType;
    cout << "Changed type of partition to '" << partitionType.TypeName() << "'\n";
    if (changeName) {
diff --git a/gptpart.h b/gptpart.h
index fac514e..ede8139 100644
--- a/gptpart.h
+++ b/gptpart.h
@@ -23,8 +23,6 @@
 #include "guid.h"
 #include "attributes.h"
 
-using namespace std;
-
 // Values returned by GPTPart::IsSizedForMBR()
 #define MBR_SIZED_GOOD 0 /* Whole partition under 2^32 sectors */
 #define MBR_SIZED_IFFY 1 /* Partition starts under 2^32 & is less than 2^32, but ends over 2^32 */
@@ -59,7 +57,7 @@
       // Simple data retrieval:
       PartType & GetType(void) {return partitionType;}
       uint16_t GetHexType(void) const;
-      string GetTypeName(void);
+      std::string GetTypeName(void);
       UnicodeString GetUTypeName(void);
       const GUIDData GetUniqueGUID(void) const {return uniqueGUID;}
       uint64_t GetFirstLBA(void) const {return firstLBA;}
@@ -80,7 +78,7 @@
       void SetLastLBA(uint64_t l) {lastLBA = l;}
       void SetAttributes(uint64_t a) {attributes = a;}
       void SetAttributes(void) {attributes.ChangeAttributes();}
-      void SetName(const string & theName);
+      void SetName(const std::string & theName);
 #ifdef USE_UTF16
       void SetName(const UnicodeString & theName);
 #endif
@@ -94,6 +92,7 @@
       void BlankPartition(void); // empty partition of data
       int DoTheyOverlap(const GPTPart & other); // returns 1 if there's overlap
       void ReversePartBytes(void); // reverse byte order of all integer fields
+      void ReverseNameBytes(void); // reverse byte order of partition's name field
 
       // Functions requiring user interaction
       void ChangeType(void); // Change the type code
diff --git a/gpttext.cc b/gpttext.cc
index ea34444..170a169 100644
--- a/gpttext.cc
+++ b/gpttext.cc
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2010-2018  <Roderick W. Smith>
+    Copyright (C) 2010-2022  <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
@@ -199,7 +199,7 @@
 
 // Interactively create a partition
 void GPTDataTextUI::CreatePartition(void) {
-   uint64_t firstBlock, firstInLargest, lastBlock, sector, origSector;
+   uint64_t firstBlock, firstInLargest, lastBlock, sector, origSector, lastAligned;
    uint32_t firstFreePart = 0;
    ostringstream prompt1, prompt2, prompt3;
    int partNum;
@@ -229,7 +229,7 @@
       prompt2 << "First sector (" << firstBlock << "-" << lastBlock << ", default = "
               << firstInLargest << ") or {+-}size{KMGTP}: ";
       do {
-         sector = GetSectorNum(firstBlock, lastBlock, firstInLargest, blockSize, prompt2.str());
+         sector = GetSectorNum(firstBlock, lastBlock, firstInLargest, prompt2.str());
       } while (IsFree(sector) == 0);
       origSector = sector;
       if (Align(&sector)) {
@@ -239,19 +239,19 @@
          if (!beQuiet)
             cout << "Use 'l' on the experts' menu to adjust alignment\n";
       } // if
-      //      Align(&sector); // Align sector to correct multiple
       firstBlock = sector;
 
       // Get last block for new partitions...
-      lastBlock = FindLastInFree(firstBlock);
+      lastBlock = FindLastInFree(firstBlock, false);
+      lastAligned = FindLastInFree(firstBlock, true);
       prompt3 << "Last sector (" << firstBlock << "-" << lastBlock << ", default = "
-            << lastBlock << ") or {+-}size{KMGTP}: ";
+              << lastAligned << ") or {+-}size{KMGTP}: ";
       do {
-         sector = GetSectorNum(firstBlock, lastBlock, lastBlock, blockSize, prompt3.str());
+         sector = GetSectorNum(firstBlock, lastBlock, lastAligned, prompt3.str());
       } while (IsFree(sector) == 0);
       lastBlock = sector;
 
-      firstFreePart = GPTData::CreatePartition(partNum, firstBlock, lastBlock);
+      GPTData::CreatePartition(partNum, firstBlock, lastBlock);
       partitions[partNum].ChangeType();
       partitions[partNum].SetDefaultDescription();
    } else {
@@ -341,6 +341,22 @@
    return retval;
 } // GPTDataTextUI::SetName()
 
+// Enable the user to byte-swap the name of the partition. Used to correct
+// partition names damaged by incorrect byte order, as could be created by
+// GPT fdisk 1.0.7 and earlier on big-endian systems, and perhaps other tools.
+void GPTDataTextUI::ReverseName(uint32_t partNum) {
+   int swapBytes;
+
+   cout << "Current name is: " << partitions[partNum].GetDescription() << "\n";
+   partitions[partNum].ReverseNameBytes();
+   cout << "Byte-swapped name is: " << partitions[partNum].GetDescription() << "\n";
+   cout << "Do you want to byte-swap the name? ";
+   swapBytes = (GetYN() == 'Y');
+   // Already swapped for display, so undo if necessary....
+   if (!swapBytes)
+      partitions[partNum].ReverseNameBytes();
+} // GPTDataTextUI::ReverseName()
+
 // 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.
@@ -532,6 +548,28 @@
    return protectiveMBR.DoMenu();
 } // GPTDataTextUI::XFormToMBR()
 
+// Obtains a sector number, between low and high, from the
+// user, accepting values prefixed by "+" to add sectors to low,
+// or the same with "K", "M", "G", "T", or "P" as suffixes to add
+// kibibytes, mebibytes, gibibytes, tebibytes, or pebibytes,
+// respectively. If a "-" prefix is used, use the high value minus
+// the user-specified number of sectors (or KiB, MiB, etc.). Use the
+// def value as the default if the user just hits Enter.
+uint64_t GPTDataTextUI::GetSectorNum(uint64_t low, uint64_t high, uint64_t def,
+                                     const string & prompt) {
+   uint64_t response;
+   char line[255];
+
+   do {
+      cout << prompt;
+      cin.getline(line, 255);
+      if (!cin.good())
+         exit(5);
+      response = IeeeToInt(line, blockSize, low, high, sectorAlignment, def);
+   } while ((response < low) || (response > high));
+   return response;
+} // GPTDataTextUI::GetSectorNum()
+
 /******************************************************
  *                                                    *
  * Display informational messages for the user....    *
@@ -799,6 +837,9 @@
             else
                cout << "No partitions\n";
             break;
+         case 'b': case 'B':
+            ReverseName(GetPartNum());
+            break;
          case 'c': case 'C':
             ChangeUniqueGuid();
             break;
@@ -896,6 +937,7 @@
 
 void GPTDataTextUI::ShowExpertCommands(void) {
    cout << "a\tset attributes\n";
+   cout << "b\tbyte-swap a partition's name\n";
    cout << "c\tchange partition GUID\n";
    cout << "d\tdisplay the sector alignment value\n";
    cout << "e\trelocate backup data structures to the end of the disk\n";
diff --git a/gpttext.h b/gpttext.h
index afe4651..32e2f88 100644
--- a/gpttext.h
+++ b/gpttext.h
@@ -1,6 +1,6 @@
 /*
     Implementation of GPTData class derivative with basic text-mode interaction
-    Copyright (C) 2010-2018 Roderick W. Smith
+    Copyright (C) 2010-2022 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
@@ -23,13 +23,11 @@
 
 #include "gpt.h"
 
-using namespace std;
-
 class GPTDataTextUI : public GPTData {
    protected:
    public:
       GPTDataTextUI(void);
-      GPTDataTextUI(string filename);
+      GPTDataTextUI(std::string filename);
       ~GPTDataTextUI(void);
 
       // This one needs to be explicitly defined, even though it does nothing new....
@@ -49,21 +47,23 @@
       void ChangeUniqueGuid(void);
       void SetAttributes(uint32_t partNum);
       int SetName(uint32_t partNum);
+      void ReverseName(uint32_t partNum);
       int SwapPartitions(void);
       int DestroyGPTwPrompt(void); // Returns 1 if user proceeds
       void ShowDetails(void);
       void MakeHybrid(void);
       int XFormToMBR(void); // convert GPT to MBR, wiping GPT afterwards. Returns 1 if successful
+      uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const std::string & prompt);
 
       // An informational function....
       void WarnAboutIffyMBRPart(int partNum);
 
       // Main menu functions
-      void MainMenu(string filename);
+      void MainMenu(std::string filename);
       void ShowCommands(void);
-      void ExpertsMenu(string filename);
+      void ExpertsMenu(std::string filename);
       void ShowExpertCommands(void);
-      void RecoveryMenu(string filename);
+      void RecoveryMenu(std::string filename);
       void ShowRecoveryCommands(void);
 }; // class GPTDataTextUI
 
diff --git a/guid.cc b/guid.cc
index e3e495c..d3e4fd5 100644
--- a/guid.cc
+++ b/guid.cc
@@ -12,9 +12,7 @@
 //
 
 #define __STDC_LIMIT_MACROS
-#ifndef __STDC_CONSTANT_MACROS
 #define __STDC_CONSTANT_MACROS
-#endif
 
 #include <stdio.h>
 #include <time.h>
@@ -143,7 +141,7 @@
 void GUIDData::Randomize(void) {
    int i, uuidGenerated = 0;
 
-#ifdef _UUID_UUID_H
+#if defined (_UUID_UUID_H) || defined (_UL_LIBUUID_UUID_H)
    uuid_generate(uuidData);
    ReverseBytes(&uuidData[0], 4);
    ReverseBytes(&uuidData[4], 2);
diff --git a/guid.h b/guid.h
index 229d5bd..515a75d 100644
--- a/guid.h
+++ b/guid.h
@@ -30,8 +30,6 @@
 typedef uuid_t my_uuid_t;
 #endif
 
-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 {
@@ -39,17 +37,17 @@
       static bool firstInstance;
    protected:
       my_uuid_t uuidData;
-      string DeleteSpaces(string s);
+      std::string DeleteSpaces(std::string s);
    public:
       GUIDData(void);
       GUIDData(const GUIDData & orig);
-      GUIDData(const string & orig);
+      GUIDData(const std::string & orig);
       GUIDData(const char * orig);
       ~GUIDData(void);
 
       // Data assignment operators....
       GUIDData & operator=(const GUIDData & orig);
-      GUIDData & operator=(const string & orig);
+      GUIDData & operator=(const std::string & orig);
       GUIDData & operator=(const char * orig);
       void Zero(void);
       void Randomize(void);
@@ -59,9 +57,9 @@
       int operator!=(const GUIDData & orig) const;
 
       // Data retrieval....
-      string AsString(void) const;
+      std::string AsString(void) const;
 }; // class GUIDData
 
-ostream & operator<<(ostream & os, const GUIDData & data);
+std::ostream & operator<<(std::ostream & os, const GUIDData & data);
 
 #endif
diff --git a/mbr.cc b/mbr.cc
index a01fe90..c3483a0 100644
--- a/mbr.cc
+++ b/mbr.cc
@@ -7,9 +7,7 @@
   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 
 #define __STDC_LIMIT_MACROS
-#ifndef __STDC_CONSTANT_MACROS
 #define __STDC_CONSTANT_MACROS
-#endif
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/mbr.h b/mbr.h
index bbb84ef..3eea775 100644
--- a/mbr.h
+++ b/mbr.h
@@ -3,6 +3,9 @@
 /* This program is copyright (c) 2009-2013 by Roderick W. Smith. It is distributed
   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 
+#ifndef __MBRSTRUCTS
+#define __MBRSTRUCTS
+
 #include <stdint.h>
 #include <sys/types.h>
 #include "gptpart.h"
@@ -10,11 +13,6 @@
 #include "diskio.h"
 #include "basicmbr.h"
 
-#ifndef __MBRSTRUCTS
-#define __MBRSTRUCTS
-
-using namespace std;
-
 /****************************************
  *                                      *
  * MBRData class and related structures *
@@ -26,7 +24,7 @@
 protected:
 public:
    MBRData(void) {}
-   MBRData(string deviceFilename) : BasicMBRData(deviceFilename) {}
+   MBRData(std::string deviceFilename) : BasicMBRData(deviceFilename) {}
    MBRData & operator=(const BasicMBRData & orig);
    ~MBRData(void);
 
diff --git a/mbrpart.cc b/mbrpart.cc
index c805d75..0ca5814 100644
--- a/mbrpart.cc
+++ b/mbrpart.cc
@@ -18,9 +18,7 @@
 */
 
 #define __STDC_LIMIT_MACROS
-#ifndef __STDC_CONSTANT_MACROS
 #define __STDC_CONSTANT_MACROS
-#endif
 
 #include <stddef.h>
 #include <stdint.h>
diff --git a/mbrpart.h b/mbrpart.h
index 0de365f..6c7b21a 100644
--- a/mbrpart.h
+++ b/mbrpart.h
@@ -32,8 +32,6 @@
 #define EBR 4     /* sector is used as an EBR or MBR */
 #define INVALID 8 /* sector number is too large for disk */
 
-using namespace std;
-
 // Data for a single MBR partition record
 // Note that firstSector and lastSector are in CHS addressing, which
 // splits the bits up in a weird way.
diff --git a/parttypes.cc b/parttypes.cc
index cbc40ba..b2f5a35 100644
--- a/parttypes.cc
+++ b/parttypes.cc
@@ -6,9 +6,7 @@
   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 
 #define __STDC_LIMIT_MACROS
-#ifndef __STDC_CONSTANT_MACROS
 #define __STDC_CONSTANT_MACROS
-#endif
 
 #include <string.h>
 #include <stdint.h>
@@ -21,6 +19,7 @@
 int PartType::numInstances = 0;
 AType* PartType::allTypes = NULL;
 AType* PartType::lastType = NULL;
+const PartType PartType::unusedPartType = (GUIDData) "00000000-0000-0000-0000-000000000000";
 
 #define SCREEN_WIDTH 80
 #define NUM_COLUMNS 2
@@ -84,6 +83,8 @@
    AddType(0x0400, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Microsoft basic data", 0); // FAT-16 < 32M
    AddType(0x0600, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Microsoft basic data", 0); // FAT-16
    AddType(0x0700, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Microsoft basic data", 1); // NTFS (or HPFS)
+   AddType(0x0701, "558D43C5-A1AC-43C0-AAC8-D1472B2923D1", "Microsoft Storage Replica", 1);
+   AddType(0x0702, "90B6FF38-B98F-4358-A21F-48F35B4A8AD3", "ArcaOS Type 1", 1);
    AddType(0x0b00, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Microsoft basic data", 0); // FAT-32
    AddType(0x0c00, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Microsoft basic data", 0); // FAT-32 LBA
    AddType(0x0c01, "E3C9E316-0B5C-4DB8-817D-F92DF00215AE", "Microsoft reserved");
@@ -126,6 +127,9 @@
    AddType(0x7f00, "FE3A2A5D-4F32-41A7-B725-ACCC3285A309", "ChromeOS kernel");
    AddType(0x7f01, "3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC", "ChromeOS root");
    AddType(0x7f02, "2E0A753D-9E48-43B0-8337-B15192CB1B5E", "ChromeOS reserved");
+   AddType(0x7f03, "CAB6E88E-ABF3-4102-A07A-D4BB9BE3C1D3", "ChromeOS firmware");
+   AddType(0x7f04, "09845860-705F-4BB5-B16C-8A8A099CAF52", "ChromeOS mini-OS");
+   AddType(0x7f05, "3F0F8318-F146-4E6B-8222-C28C8F02E0D5", "ChromeOS hibernate");
 
    // Linux-specific partition types....
    AddType(0x8200, "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F", "Linux swap"); // Linux swap (or Solaris on MBR)
@@ -149,9 +153,29 @@
    AddType(0x830F, "86ED10D5-B607-45BB-8957-D350F23D0571", "Linux IA-64 root verity");
    AddType(0x8310, "4D21B016-B534-45C2-A9FB-5C16E091FD2D", "Linux /var"); // Linux /var (auto-mounted by systemd)
    AddType(0x8311, "7EC6F557-3BC5-4ACA-B293-16EF5DF639D1", "Linux /var/tmp"); // Linux /var/tmp (auto-mounted by systemd)
+   // https://systemd.io/HOME_DIRECTORY/
+   AddType(0x8312, "773F91EF-66D4-49B5-BD83-D683BF40AD16", "Linux user's home"); // used by systemd-homed
+   AddType(0x8313, "75250D76-8CC6-458E-BD66-BD47CC81A812", "Linux x86 /usr "); // Linux /usr on x86 (auto-mounted by systemd)
+   AddType(0x8314, "8484680C-9521-48C6-9C11-B0720656F69E", "Linux x86-64 /usr"); // Linux /usr on x86-64 (auto-mounted by systemd)
+   AddType(0x8315, "7D0359A3-02B3-4F0A-865C-654403E70625", "Linux ARM32 /usr"); // Linux /usr on 32-bit ARM (auto-mounted by systemd)
+   AddType(0x8316, "B0E01050-EE5F-4390-949A-9101B17104E9", "Linux ARM64 /usr"); // Linux /usr on 64-bit ARM (auto-mounted by systemd)
+   AddType(0x8317, "4301D2A6-4E3B-4B2A-BB94-9E0B2C4225EA", "Linux IA-64 /usr"); // Linux /usr on Itanium (auto-mounted by systemd)
+   AddType(0x8318, "8F461B0D-14EE-4E81-9AA9-049B6FB97ABD", "Linux x86 /usr verity");
+   AddType(0x8319, "77FF5F63-E7B6-4633-ACF4-1565B864C0E6", "Linux x86-64 /usr verity");
+   AddType(0x831A, "C215D751-7BCD-4649-BE90-6627490A4C05", "Linux ARM32 /usr verity");
+   AddType(0x831B, "6E11A4E7-FBCA-4DED-B9E9-E1A512BB664E", "Linux ARM64 /usr verity");
+   AddType(0x831C, "6A491E03-3BE7-4545-8E38-83320E0EA880", "Linux IA-64 /usr verity");
 
    // Used by Intel Rapid Start technology
    AddType(0x8400, "D3BFE2DE-3DAF-11DF-BA40-E3A556D89593", "Intel Rapid Start");
+   // This is another Intel-associated technology, so I'm keeping it close to the previous one....
+   AddType(0x8401, "7C5222BD-8F5D-4087-9C00-BF9843C7B58C", "SPDK block device");
+
+   // Type codes for Container Linux (formerly CoreOS; https://coreos.com)
+   AddType(0x8500, "5DFBF5F4-2848-4BAC-AA5E-0D9A20B745A6", "Container Linux /usr");
+   AddType(0x8501, "3884DD41-8582-4404-B9A8-E9B84F2DF50E", "Container Linux resizable rootfs");
+   AddType(0x8502, "C95DC21A-DF0E-4340-8D7B-26CBFA9A03E0", "Container Linux /OEM customizations");
+   AddType(0x8503, "BE9067B9-EA49-4F15-B4F6-F36F8C9E1818", "Container Linux root on RAID");
 
    // Another Linux type code....
    AddType(0x8e00, "E6D6D379-F507-44C2-A23C-238F2A3DF928", "Linux LVM");
@@ -237,6 +261,7 @@
    AddType(0xa503, "516E7CB6-6ECF-11D6-8FF8-00022D09712B", "FreeBSD UFS");
    AddType(0xa504, "516E7CBA-6ECF-11D6-8FF8-00022D09712B", "FreeBSD ZFS");
    AddType(0xa505, "516E7CB8-6ECF-11D6-8FF8-00022D09712B", "FreeBSD Vinum/RAID");
+   AddType(0xa506, "74BA7DD9-A689-11E1-BD04-00E081286ACF", "FreeBSD nandfs");
 
    // Midnight BSD partition types....
    AddType(0xa580, "85D5E45A-237C-11E1-B4B3-E89A8F7FC3A7", "Midnight BSD data");
@@ -275,10 +300,19 @@
    AddType(0xaf08, "FA709C7E-65B1-4593-BFD5-E71D61DE9B02", "Apple SoftRAID Volume");
    AddType(0xaf09, "BBBA6DF5-F46F-4A89-8F59-8765B2727503", "Apple SoftRAID Cache");
    AddType(0xaf0a, "7C3457EF-0000-11AA-AA11-00306543ECAC", "Apple APFS");
+   AddType(0xaf0b, "69646961-6700-11AA-AA11-00306543ECAC", "Apple APFS Pre-Boot");
+   AddType(0xaf0c, "52637672-7900-11AA-AA11-00306543ECAC", "Apple APFS Recovery");
+
+   // U-Boot boot loader; see https://lists.denx.de/pipermail/u-boot/2020-November/432928.html
+   // and https://source.denx.de/u-boot/u-boot/-/blob/v2021.07/include/part_efi.h#L59-61
+   AddType(0xb000, "3DE21764-95BD-54BD-A5C3-4ABE786F38A8", "U-Boot boot loader");
 
    // QNX Power-Safe (QNX6)
    AddType(0xb300, "CEF5A9AD-73BC-4601-89F3-CDEEEEE321A1", "QNX6 Power-Safe");
 
+   // Barebox boot loader; see https://barebox.org/doc/latest/user/state.html?highlight=guid#sd-emmc-and-ata
+   AddType(0xbb00, "4778ED65-BF42-45FA-9C5B-287A1DC4AAB1", "Barebox boot loader");
+
    // Acronis Secure Zone
    AddType(0xbc00, "0311FC50-01CA-4725-AD77-9ADBB20ACE98", "Acronis Secure Zone");
 
@@ -306,8 +340,11 @@
    AddType(0xe100, "7412F7D5-A156-4B13-81DC-867174929325", "ONIE boot");
    AddType(0xe101, "D4E6E2CD-4469-46F3-B5CB-1BFF57AFC149", "ONIE config");
 
-   // See http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec
-   AddType(0xea00, "BC13C2FF-59E6-4262-A352-B275FD6F7172", "Freedesktop $BOOT");
+   // Veracrypt (https://www.veracrypt.fr/en/Home.html) encrypted partition
+   AddType(0xe900, "8C8F8EFF-AC95-4770-814A-21994F2DBC8F", "Veracrypt data");
+
+   // See https://systemd.io/BOOT_LOADER_SPECIFICATION/
+   AddType(0xea00, "BC13C2FF-59E6-4262-A352-B275FD6F7172", "XBOOTLDR partition");
 
    // Type code for Haiku; uses BeOS MBR code as hex code base
    AddType(0xeb00, "42465331-3BA3-10F1-802A-4861696B7521", "Haiku BFS");
@@ -321,6 +358,35 @@
    AddType(0xef01, "024DEE41-33E7-11D3-9D69-0008C781F39F", "MBR partition scheme"); // Used to nest MBR in GPT
    AddType(0xef02, "21686148-6449-6E6F-744E-656564454649", "BIOS boot partition"); // Used by GRUB
 
+   // Fuscia OS codes; see https://cs.opensource.google/fuchsia/fuchsia/+/main:zircon/system/public/zircon/hw/gpt.h
+   AddType(0xf100, "FE8A2634-5E2E-46BA-99E3-3A192091A350", "Fuchsia boot loader (slot A/B/R)");
+   AddType(0xf101, "D9FD4535-106C-4CEC-8D37-DFC020CA87CB", "Fuchsia durable mutable encrypted system data");
+   AddType(0xf102, "A409E16B-78AA-4ACC-995C-302352621A41", "Fuchsia durable mutable boot loader");
+   AddType(0xf103, "F95D940E-CABA-4578-9B93-BB6C90F29D3E", "Fuchsia factory ro system data");
+   AddType(0xf104, "10B8DBAA-D2BF-42A9-98C6-A7C5DB3701E7", "Fuchsia factory ro bootloader data");
+   AddType(0xf105, "49FD7CB8-DF15-4E73-B9D9-992070127F0F", "Fuchsia Volume Manager");
+   AddType(0xf106, "421A8BFC-85D9-4D85-ACDA-B64EEC0133E9", "Fuchsia verified boot metadata (slot A/B/R)");
+   AddType(0xf107, "9B37FFF6-2E58-466A-983A-F7926D0B04E0", "Fuchsia Zircon boot image (slot A/B/R)");
+   AddType(0xf108, "C12A7328-F81F-11D2-BA4B-00A0C93EC93B", "Fuchsia ESP");
+   AddType(0xf109, "606B000B-B7C7-4653-A7D5-B737332C899D", "Fuchsia System");
+   AddType(0xf10a, "08185F0C-892D-428A-A789-DBEEC8F55E6A", "Fuchsia Data");
+   AddType(0xf10b, "48435546-4953-2041-494E-5354414C4C52", "Fuchsia Install");
+   AddType(0xf10c, "2967380E-134C-4CBB-B6DA-17E7CE1CA45D", "Fuchsia Blob");
+   AddType(0xf10d, "41D0E340-57E3-954E-8C1E-17ECAC44CFF5", "Fuchsia FVM");
+   AddType(0xf10e, "DE30CC86-1F4A-4A31-93C4-66F147D33E05", "Fuchsia Zircon boot image (slot A)");
+   AddType(0xf10f, "23CC04DF-C278-4CE7-8471-897D1A4BCDF7", "Fuchsia Zircon boot image (slot B)");
+   AddType(0xf110, "A0E5CF57-2DEF-46BE-A80C-A2067C37CD49", "Fuchsia Zircon boot image (slot R)");
+   AddType(0xf111, "4E5E989E-4C86-11E8-A15B-480FCF35F8E6", "Fuchsia sys-config");
+   AddType(0xf112, "5A3A90BE-4C86-11E8-A15B-480FCF35F8E6", "Fuchsia factory-config");
+   AddType(0xf113, "5ECE94FE-4C86-11E8-A15B-480FCF35F8E6", "Fuchsia bootloader");
+   AddType(0xf114, "8B94D043-30BE-4871-9DFA-D69556E8C1F3", "Fuchsia guid-test");
+   AddType(0xf115, "A13B4D9A-EC5F-11E8-97D8-6C3BE52705BF", "Fuchsia verified boot metadata (A)");
+   AddType(0xf116, "A288ABF2-EC5F-11E8-97D8-6C3BE52705BF", "Fuchsia verified boot metadata (B)");
+   AddType(0xf117, "6A2460C3-CD11-4E8B-80A8-12CCE268ED0A", "Fuchsia verified boot metadata (R)");
+   AddType(0xf118, "1D75395D-F2C6-476B-A8B7-45CC1C97B476", "Fuchsia misc");
+   AddType(0xf119, "900B0FC5-90CD-4D4F-84F9-9F8ED579DB88", "Fuchsia emmc-boot1");
+   AddType(0xf11a, "B2B2E8D1-7C10-4EBC-A2D0-4614568260AD", "Fuchsia emmc-boot2");
+
    // Ceph type codes; see https://github.com/ceph/ceph/blob/9bcc42a3e6b08521694b5c0228b2c6ed7b3d312e/src/ceph-disk#L76-L81
    // and Wikipedia
    AddType(0xf800, "4FBD7E29-9D25-41B8-AFD0-062C0CEFF05D", "Ceph OSD"); // Ceph Object Storage Daemon
@@ -523,10 +589,10 @@
    cout.unsetf(ios::uppercase);
    if (maxLines > 0) {
       cout << "Type search string, or <Enter> to show all codes: ";
-      matchString = ReadString();
+      matchString = ToLower(ReadString());
    } // if
    while (thisType != NULL) {
-      found = thisType->name.find(matchString);
+      found = ToLower(thisType->name).find(matchString);
       if ((thisType->display == 1) && (found != string::npos)) { // show it
          cout.fill('0');
          cout.width(4);
@@ -538,8 +604,10 @@
             if (thisType->next) {
                cout << "\n";
                if ((maxLines > 0) && (lineCount++ % maxLines) == 0) {
-                  cout << "Press the <Enter> key to see more codes: ";
+                  cout << "Press the <Enter> key to see more codes, q to quit: ";
                   getline(cin, line);
+                  if ((line[0] =='q') || (line[0] =='Q'))
+                     break;
                } // if reached screen line limit
             } // if there's another entry following this one
          } else {
diff --git a/parttypes.h b/parttypes.h
index c108a17..4e1d968 100644
--- a/parttypes.h
+++ b/parttypes.h
@@ -1,21 +1,19 @@
 /* This program is copyright (c) 2009-2018 by Roderick W. Smith. It is distributed
   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 
-#include <stdint.h>
-#include <stdlib.h>
-#ifdef USE_UTF16
-#include <unicode/ustream.h>
-#else
-#define UnicodeString string
-#endif
-#include <string>
-#include "support.h"
-#include "guid.h"
-
 #ifndef __PARTITION_TYPES
 #define __PARTITION_TYPES
 
-using namespace std;
+#include <stdint.h>
+#include <stdlib.h>
+#include <string>
+#include "support.h"
+#include "guid.h"
+#ifdef USE_UTF16
+#include <unicode/ustream.h>
+#else
+#define UnicodeString std::string
+#endif
 
 // A partition type
 struct AType {
@@ -24,7 +22,7 @@
    // codes required by GPT
    uint16_t MBRType;
    GUIDData GUIDType;
-   string name;
+   std::string name;
    int display; // 1 to show to users as available type, 0 not to
    AType* next;
 }; // struct AType
@@ -36,6 +34,9 @@
    static AType* lastType; // Pointer to last entry in the list
    void AddAllTypes(void);
 public:
+   // PartType with GUID "00000000-0000-0000-0000-000000000000"
+   static const PartType unusedPartType;
+
    PartType(void);
    PartType(const PartType & orig);
    PartType(const GUIDData & orig);
@@ -45,7 +46,7 @@
    int AddType(uint16_t mbrType, const char * guidData, const char * name, int toDisplay = 1);
 
    // New assignment operators....
-   PartType & operator=(const string & orig);
+   PartType & operator=(const std::string & orig);
    PartType & operator=(const char * orig);
 
    // Assignment operators based on base class....
@@ -55,7 +56,7 @@
    PartType & operator=(uint16_t ID); // Use MBR type code times 0x0100 to assign GUID
 
    // Retrieve transformed GUID data based on type code matches
-   string TypeName(void) const;
+   std::string TypeName(void) const;
    UnicodeString UTypeName(void) const;
    uint16_t GetHexType() const;
 
diff --git a/sgdisk.8 b/sgdisk.8
index d5a71a0..fa53b29 100644
--- a/sgdisk.8
+++ b/sgdisk.8
@@ -1,6 +1,6 @@
-.\" Copyright 2011-2018 Roderick W. Smith (rodsmith@rodsbooks.com)
+.\" Copyright 2011-2022 Roderick W. Smith (rodsmith@rodsbooks.com)
 .\" May be distributed under the GNU General Public License
-.TH "SGDISK" "8" "1.0.4" "Roderick W. Smith" "GPT fdisk Manual"
+.TH "SGDISK" "8" "1.0.9" "Roderick W. Smith" "GPT fdisk Manual"
 .SH "NAME"
 sgdisk \- Command\-line GUID partition table (GPT) manipulator for Linux and Unix
 .SH "SYNOPSIS"
@@ -23,7 +23,7 @@
 main and backup data, as well as between the GPT headers and the partition
 tables. For information on MBR vs. GPT, as well as GPT terminology and
 structure, see the extended \fBgdisk\fR documentation at
-\fIhttp://www.rodsbooks.com/gdisk/\fR or consult Wikipedia.
+\fIhttps://www.rodsbooks.com/gdisk/\fR or consult Wikipedia.
 
 The \fBsgdisk\fR program employs a user interface that's based entirely on
 the command line, making it suitable for use in scripts or by experts who
@@ -154,7 +154,10 @@
 on disks with 512-byte sectors) on freshly formatted disks. This alignment
 value is necessary to obtain optimum performance with Western Digital
 Advanced Format and similar drives with larger physical than logical sector
-sizes, with some types of RAID arrays, and with SSD devices.
+sizes, with some types of RAID arrays, and with SSD devices. When the
+\fI\-I\fR option is used, this same alignment value is used to determine
+partition end points; but partitions end at one less than a multiple of this
+value, to keep the partition length a multiple of this value.
 
 .TP
 .B \-A, \-\-attributes=list|[partnum:show|or|nand|xor|=|set|clear|toggle|get[:bitnum|hexbitmask]]
@@ -167,7 +170,7 @@
 \fItoggle\fR options enable you to change the attribute bit value. The
 \fIset\fR, \fIclear\fR, \fItoggle\fR, and \fIget\fR options work on a
 bit number; the others work on a hexadecimal bit mask. For example, type 
-\fBsgdisk -A 4:set:2 /dev/sdc\fR to set the bit 2 attribute (legacy BIOS
+\fBsgdisk \-A 4:set:2 /dev/sdc\fR to set the bit 2 attribute (legacy BIOS
 bootable) on partition 4 on \fI/dev/sdc\fR.
 
 .TP 
@@ -183,6 +186,14 @@
 will reflect GPT fdisk's first\-pass interpretation of the GPT.
 
 .TP 
+.B \-B, \-\-byte\-swap\-name=partnum
+Swap the byte order for the name of the specified partition. Some
+partitioning tools, including GPT fdisk 1.0.7 and earlier, can write the
+partition name in the wrong byte order on big-endian computers, such as the
+IBM s390 mainframes and PowerPC-based Macs. This feature corrects this
+problem.
+
+.TP 
 .B \-c, \-\-change\-name=partnum:name
 Change the GPT name of a partition. This name is encoded as a UTF\-16
 string, but proper entry and display of anything beyond basic ASCII values
@@ -272,7 +283,7 @@
 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
 Show detailed partition information. The summary information produced by
 the \fI\-p\fR command necessarily omits many details, such as the partition's
@@ -281,6 +292,18 @@
 displays this information for a single partition.
 
 .TP
+.B \-I, \-\-align\-end
+When possible, align the end points of partitions to one less than a
+multiple of the alignment value. When both start and end points are aligned,
+partitions should be multiples of the alignment value in size, which is
+necessary for some partition encryption tools to function correctly. This
+option applies to all partitions created \fBafter\fR this option on the
+command line. Note that this alignment is not always possible; for instance,
+if the free space at the end of a disk is less than the alignment value,
+with the current final partition being aligned, and if \fBsgdisk\fR is asked
+to create a partition in that space, then it will \fBnot\fR be end\-aligned.
+
+.TP
 .B \-j, \-\-adjust\-main\-table=sector
 Adjust the location of the main partition table. This value is normally 2,
 but it may need to be increased in some cases, such as when a
@@ -339,22 +362,26 @@
 start of the largest available block for the start sector and the end of
 the same block for the end sector. A partnum value of 0 causes the program
 to use the first available partition number. Subsequent uses of the
-\fI\-A\fR, \fI\-c\fR, \fI\-t\fR, and \fI\-u\fR options may also use
+\fI\-A\fR (\fI\-\-attributes\fR), \fI\-c\fR (\fI\-\-change\-name\fR), \fI\-t\fR
+(\fI\-\-typecode\fR), and \fI\-u\fR (\fI\-\-partition\-guid\fR) options may also use
 \fI0\fR to refer to the same partition.
 
 .TP
 .B \-N, \-\-largest\-new=num
 Create a new partition that fills the largest available block of space on
 the disk. You can use the \fI\-a\fR (\fI\-\-set\-alignment\fR) option to
-adjust the alignment, if desired. A num value of 0 causes the program to
-use the first available partition number.
+adjust the alignment, if desired. A num value of 0 causes the program to use
+the first available partition number. Subsequent uses of the \fI\-A\fR
+(\fI\-\-attributes\fR), \fI\-c\fR (\fI\-\-change\-name\fR), \fI\-t\fR
+(\fI\-\-typecode\fR), and \fI\-u\fR (\fI\-\-partition\-guid\fR) options may
+also use \fI0\fR to refer to the same partition.
 
 .TP 
 .B \-o, \-\-clear
 Clear out all partition data. This includes GPT header data, all partition
 definitions, and the protective MBR. Note that this operation will, like
 most other operations, fail on a damaged disk. If you want to prepare a
-disk you know to be damaged for GPT use, you should first wipe it with -Z
+disk you know to be damaged for GPT use, you should first wipe it with \-Z
 and then partition it normally. This option will work even if the
 disk's original partition table is bad; however, most other options on the
 same command line will be ignored.
@@ -504,7 +531,7 @@
 
 .TP
 .B 8
-Disk replication operation (-R) failed
+Disk replication operation (\-R) failed
 
 .SH "BUGS"
 Known bugs and limitations include:
@@ -593,7 +620,7 @@
 
 * Justin Maggard (justin.maggard@netgear.com)
 
-* Dwight Schauer (dschauer@gmail.com)
+* Dwight Schauer (das@teegra.net)
 
 * Florian Zumbiehl (florz@florz.de)
 
@@ -608,11 +635,11 @@
 .BR sfdisk (8),
 .BR fixparts (8).
 
-\fIhttp://en.wikipedia.org/wiki/GUID_Partition_Table\fR
+\fIhttps://en.wikipedia.org/wiki/GUID_Partition_Table\fR
 
-\fIhttp://developer.apple.com/technotes/tn2006/tn2166.html\fR
+\fIhttps://developer.apple.com/technotes/tn2006/tn2166.html\fR
 
-\fIhttp://www.rodsbooks.com/gdisk/\fR
+\fIhttps://www.rodsbooks.com/gdisk/\fR
 
 .SH "AVAILABILITY"
 The \fBsgdisk\fR command is part of the \fIGPT fdisk\fR package and is
diff --git a/support.cc b/support.cc
index 92bfd77..3cbabf7 100644
--- a/support.cc
+++ b/support.cc
@@ -3,14 +3,14 @@
 // Primarily by Rod Smith, February 2009, but with a few functions
 // copied from other sources (see attributions below).
 
-/* This program is copyright (c) 2009-2018 by Roderick W. Smith. It is distributed
+/* This program is copyright (c) 2009-2022 by Roderick W. Smith. It is distributed
   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 
 #define __STDC_LIMIT_MACROS
-#ifndef __STDC_CONSTANT_MACROS
 #define __STDC_CONSTANT_MACROS
-#endif
+#define __STDC_FORMAT_MACROS
 
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <errno.h>
@@ -18,8 +18,9 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <string>
+#include <cctype>
+#include <algorithm>
 #include <iostream>
-#include <inttypes.h>
 #include <sstream>
 #include "support.h"
 
@@ -81,7 +82,7 @@
          cin.getline(line, 255);
          if (!cin.good())
             exit(5);
-         num = sscanf(line, "%" SCNu64, &response);
+         num = sscanf(line, "%" PRIu64, &response);
          if (num == 1) { // user provided a response
             if ((response < low) || (response > high))
                cout << "Value out of range\n";
@@ -112,48 +113,27 @@
    return response;
 } // GetYN(void)
 
-// Obtains a sector number, between low and high, from the
-// user, accepting values prefixed by "+" to add sectors to low,
-// or the same with "K", "M", "G", "T", or "P" as suffixes to add
-// kilobytes, megabytes, gigabytes, terabytes, or petabytes,
-// respectively. If a "-" prefix is used, use the high value minus
-// the user-specified number of sectors (or KiB, MiB, etc.). Use the
-// def value as the default if the user just hits Enter. The sSize is
-// the sector size of the device.
-uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, uint64_t sSize,
-                      const string & prompt) {
-   uint64_t response;
-   char line[255];
-
-   do {
-      cout << prompt;
-      cin.getline(line, 255);
-      if (!cin.good())
-         exit(5);
-      response = IeeeToInt(line, sSize, low, high, def);
-   } while ((response < low) || (response > high));
-   return response;
-} // GetSectorNum()
-
 // Convert an IEEE-1541-2002 value (K, M, G, T, P, or E) to its equivalent in
 // number of sectors. If no units are appended, interprets as the number
 // of sectors; otherwise, interprets as number of specified units and
 // converts to sectors. For instance, with 512-byte sectors, "1K" converts
-// to 2. If value includes a "+", adds low and subtracts 1; if SIValue
+// to 2. If value includes a "+", adds low and subtracts 1; if inValue
 // inclues a "-", subtracts from high. If IeeeValue is empty, returns def.
 // Returns final sector value. In case inValue is invalid, returns 0 (a
 // sector value that's always in use on GPT and therefore invalid); and if
 // inValue works out to something outside the range low-high, returns the
 // computed value; the calling function is responsible for checking the
 // validity of this value.
+// If inValue contains a decimal number (e.g., "9.5G"), quietly truncate it
+// (to "9G" in this example).
 // NOTE: There's a difference in how GCC and VC++ treat oversized values
 // (say, "999999999999999999999") read via the ">>" operator; GCC turns
 // them into the maximum value for the type, whereas VC++ turns them into
 // 0 values. The result is that IeeeToInt() returns UINT64_MAX when
 // compiled with GCC (and so the value is rejected), whereas when VC++
 // is used, the default value is returned.
-uint64_t IeeeToInt(string inValue, uint64_t sSize, uint64_t low, uint64_t high, uint64_t def) {
-   uint64_t response = def, bytesPerUnit = 1, mult = 1, divide = 1;
+uint64_t IeeeToInt(string inValue, uint64_t sSize, uint64_t low, uint64_t high, uint32_t sectorAlignment, uint64_t def) {
+   uint64_t response = def, bytesPerUnit, mult = 1, divide = 1;
    size_t foundAt = 0;
    char suffix = ' ', plusFlag = ' ';
    string suffixes = "KMGTPE";
@@ -180,6 +160,15 @@
       badInput = 1;
    inString >> response >> suffix;
    suffix = toupper(suffix);
+   foundAt = suffixes.find(suffix);
+   // If suffix is invalid, try to find a valid one. Done because users
+   // sometimes enter decimal numbers; when they do, suffix becomes
+   // '.', and we need to truncate the number and find the real suffix.
+   while (foundAt > (suffixes.length() - 1) && inString.peek() != -1) {
+      inString >> suffix;
+      foundAt = suffixes.find(suffix);
+      suffix = toupper(suffix);
+   }
 
    // If no response, or if response == 0, use default (def)
    if ((inValue.length() == 0) || (response == 0)) {
@@ -189,7 +178,6 @@
    } // if
 
    // Find multiplication and division factors for the suffix
-   foundAt = suffixes.find(suffix);
    if (foundAt != string::npos) {
       bytesPerUnit = UINT64_C(1) << (10 * (foundAt + 1));
       mult = bytesPerUnit / sSize;
@@ -207,11 +195,12 @@
    } // if/elseif
 
    if (plusFlag == '+') {
-      // Recompute response based on low part of range (if default == high
-      // value, which should be the case when prompting for the end of a
-      // range) or the defaut value (if default != high, which should be
-      // the case for the first sector of a partition).
-      if (def == high) {
+      // Recompute response based on low part of range (if default is within
+      // sectorAlignment sectors of high, which should be the case when
+      // prompting for the end of a range) or the defaut value (if default is
+      // further away from the high value, which should be the case for the
+      // first sector of a partition).
+      if ((high - def) < sectorAlignment) {
          if (response > 0)
             response--;
          if (response > (UINT64_MAX - low))
@@ -361,3 +350,11 @@
       exit(0);
    #endif
 } // WinWarning()
+
+// Returns the input string in lower case
+string ToLower(const string& input) {
+   string lower = input; // allocate correct size through copy
+
+   transform(input.begin(), input.end(), lower.begin(), ::tolower);
+   return lower;
+} // ToLower()
diff --git a/support.h b/support.h
index 8f976da..4a9f414 100644
--- a/support.h
+++ b/support.h
@@ -1,14 +1,14 @@
-/* This program is copyright (c) 2009-2018 by Roderick W. Smith. It is distributed
+/* This program is copyright (c) 2009-2022 by Roderick W. Smith. It is distributed
   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 
+#ifndef __GPTSUPPORT
+#define __GPTSUPPORT
+
 #include <stdint.h>
 #include <stdlib.h>
 #include <string>
 
-#ifndef __GPTSUPPORT
-#define __GPTSUPPORT
-
-#define GPTFDISK_VERSION "1.0.4"
+#define GPTFDISK_VERSION "1.0.9.2"
 
 #if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__)
 // Darwin (Mac OS) & FreeBSD: disk IOCTLs are different, and there is no lseek64
@@ -69,18 +69,16 @@
 #define GPT_RESERVED 420
 #define NAME_SIZE 36 // GPT allows 36 UTF-16LE code units for a name in a 128 byte partition entry
 
-using namespace std;
-
-string ReadString(void);
-uint64_t GetNumber(uint64_t low, uint64_t high, uint64_t def, const string & prompt);
+std::string ReadString(void);
+uint64_t GetNumber(uint64_t low, uint64_t high, uint64_t def, const std::string & prompt);
 char GetYN(void);
-uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, uint64_t sSize, const std::string& prompt);
-uint64_t IeeeToInt(string IeeeValue, uint64_t sSize, uint64_t low, uint64_t high, uint64_t def = 0);
-string BytesToIeee(uint64_t size, uint32_t sectorSize);
-unsigned char StrToHex(const string & input, unsigned int position);
-int IsHex(string input); // Returns 1 if input can be hexadecimal number....
+uint64_t IeeeToInt(std::string IeeeValue, uint64_t sSize, uint64_t low, uint64_t high, uint32_t sectorAlignment, uint64_t def = 0);
+std::string BytesToIeee(uint64_t size, uint32_t sectorSize);
+unsigned char StrToHex(const std::string & input, unsigned int position);
+int IsHex(std::string input); // Returns 1 if input can be hexadecimal number....
 int IsLittleEndian(void); // Returns 1 if CPU is little-endian, 0 if it's big-endian
 void ReverseBytes(void* theValue, int numBytes); // Reverses byte-order of theValue
 void WinWarning(void);
+std::string ToLower(const std::string& input);
 
 #endif