diff --git a/Makefile b/Makefile
index b03f3bf88d0182c22297a0079adbf2cc3eca53cb..38650138ebdc16b579b271b597420afea8cd94e7 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ CXX=g++
 CFLAGS+=-D_FILE_OFFSET_BITS=64
 CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64
 LDFLAGS+=
-LIB_NAMES=crc32 support guid partnotes gptpart mbr gpt bsd parttypes attributes diskio diskio-unix
+LIB_NAMES=crc32 support guid partnotes gptpartnotes gptpart basicmbr mbr gpt bsd parttypes attributes diskio diskio-unix
 LIB_SRCS=$(NAMES:=.cc)
 LIB_OBJS=$(LIB_NAMES:=.o)
 LIB_HEADERS=$(LIB_NAMES:=.h)
@@ -31,3 +31,355 @@ $(OBJS):
 	$(CRITICAL_CXX_FLAGS) 
 
 # DO NOT DELETE
+
+attributes.o: /usr/include/stdint.h /usr/include/features.h
+attributes.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+attributes.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+attributes.o: /usr/include/bits/wchar.h /usr/include/stdio.h
+attributes.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+attributes.o: /usr/include/libio.h /usr/include/_G_config.h
+attributes.o: /usr/include/wchar.h /usr/include/bits/stdio_lim.h
+attributes.o: /usr/include/bits/sys_errlist.h attributes.h support.h
+attributes.o: /usr/include/stdlib.h /usr/include/sys/types.h
+attributes.o: /usr/include/time.h /usr/include/endian.h
+attributes.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+attributes.o: /usr/include/sys/select.h /usr/include/bits/select.h
+attributes.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+attributes.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
+attributes.o: /usr/include/alloca.h
+bsd.o: /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h
+bsd.o: /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h
+bsd.o: /usr/include/gnu/stubs-64.h /usr/include/bits/types.h
+bsd.o: /usr/include/bits/typesizes.h /usr/include/libio.h
+bsd.o: /usr/include/_G_config.h /usr/include/wchar.h
+bsd.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+bsd.o: /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h
+bsd.o: /usr/include/endian.h /usr/include/bits/endian.h
+bsd.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
+bsd.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+bsd.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
+bsd.o: /usr/include/bits/pthreadtypes.h /usr/include/alloca.h
+bsd.o: /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/fcntl.h
+bsd.o: /usr/include/bits/fcntl.h /usr/include/sys/stat.h
+bsd.o: /usr/include/bits/stat.h /usr/include/errno.h
+bsd.o: /usr/include/bits/errno.h /usr/include/linux/errno.h
+bsd.o: /usr/include/asm/errno.h /usr/include/asm-generic/errno.h
+bsd.o: /usr/include/asm-generic/errno-base.h support.h bsd.h gptpart.h
+bsd.o: parttypes.h guid.h /usr/include/uuid/uuid.h /usr/include/sys/time.h
+bsd.o: attributes.h diskio.h /usr/include/sys/ioctl.h
+bsd.o: /usr/include/bits/ioctls.h /usr/include/asm/ioctls.h
+bsd.o: /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h
+bsd.o: /usr/include/asm/ioctl.h /usr/include/asm-generic/ioctl.h
+bsd.o: /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h
+crc32.o: /usr/include/stdio.h /usr/include/features.h
+crc32.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+crc32.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+crc32.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+crc32.o: /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h
+crc32.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+crc32.o: /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h
+crc32.o: /usr/include/endian.h /usr/include/bits/endian.h
+crc32.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
+crc32.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+crc32.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
+crc32.o: /usr/include/bits/pthreadtypes.h /usr/include/alloca.h crc32.h
+crc32.o: /usr/include/stdint.h /usr/include/bits/wchar.h
+diskio.o: /usr/include/sys/ioctl.h /usr/include/features.h
+diskio.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+diskio.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+diskio.o: /usr/include/bits/ioctls.h /usr/include/asm/ioctls.h
+diskio.o: /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h
+diskio.o: /usr/include/asm/ioctl.h /usr/include/asm-generic/ioctl.h
+diskio.o: /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h
+diskio.o: /usr/include/stdint.h /usr/include/bits/wchar.h
+diskio.o: /usr/include/errno.h /usr/include/bits/errno.h
+diskio.o: /usr/include/linux/errno.h /usr/include/asm/errno.h
+diskio.o: /usr/include/asm-generic/errno.h
+diskio.o: /usr/include/asm-generic/errno-base.h /usr/include/fcntl.h
+diskio.o: /usr/include/bits/fcntl.h /usr/include/sys/types.h
+diskio.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+diskio.o: /usr/include/time.h /usr/include/endian.h
+diskio.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+diskio.o: /usr/include/sys/select.h /usr/include/bits/select.h
+diskio.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+diskio.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
+diskio.o: /usr/include/sys/stat.h /usr/include/bits/stat.h support.h
+diskio.o: /usr/include/stdlib.h /usr/include/alloca.h diskio.h parttypes.h
+diskio.o: guid.h /usr/include/uuid/uuid.h /usr/include/sys/time.h gpt.h
+diskio.o: gptpart.h attributes.h mbr.h partnotes.h bsd.h
+diskio-unix.o: /usr/include/sys/ioctl.h /usr/include/features.h
+diskio-unix.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+diskio-unix.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+diskio-unix.o: /usr/include/bits/ioctls.h /usr/include/asm/ioctls.h
+diskio-unix.o: /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h
+diskio-unix.o: /usr/include/asm/ioctl.h /usr/include/asm-generic/ioctl.h
+diskio-unix.o: /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h
+diskio-unix.o: /usr/include/string.h /usr/include/xlocale.h
+diskio-unix.o: /usr/include/stdint.h /usr/include/bits/wchar.h
+diskio-unix.o: /usr/include/errno.h /usr/include/bits/errno.h
+diskio-unix.o: /usr/include/linux/errno.h /usr/include/asm/errno.h
+diskio-unix.o: /usr/include/asm-generic/errno.h
+diskio-unix.o: /usr/include/asm-generic/errno-base.h /usr/include/fcntl.h
+diskio-unix.o: /usr/include/bits/fcntl.h /usr/include/sys/types.h
+diskio-unix.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+diskio-unix.o: /usr/include/time.h /usr/include/endian.h
+diskio-unix.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+diskio-unix.o: /usr/include/sys/select.h /usr/include/bits/select.h
+diskio-unix.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+diskio-unix.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
+diskio-unix.o: /usr/include/sys/stat.h /usr/include/bits/stat.h diskio.h
+diskio-unix.o: support.h /usr/include/stdlib.h /usr/include/alloca.h
+diskio-unix.o: parttypes.h guid.h /usr/include/uuid/uuid.h
+diskio-unix.o: /usr/include/sys/time.h
+diskio-windows.o: /usr/include/stdio.h /usr/include/features.h
+diskio-windows.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+diskio-windows.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+diskio-windows.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+diskio-windows.o: /usr/include/libio.h /usr/include/_G_config.h
+diskio-windows.o: /usr/include/wchar.h /usr/include/bits/stdio_lim.h
+diskio-windows.o: /usr/include/bits/sys_errlist.h /usr/include/stdint.h
+diskio-windows.o: /usr/include/bits/wchar.h /usr/include/errno.h
+diskio-windows.o: /usr/include/bits/errno.h /usr/include/linux/errno.h
+diskio-windows.o: /usr/include/asm/errno.h /usr/include/asm-generic/errno.h
+diskio-windows.o: /usr/include/asm-generic/errno-base.h /usr/include/fcntl.h
+diskio-windows.o: /usr/include/bits/fcntl.h /usr/include/sys/types.h
+diskio-windows.o: /usr/include/time.h /usr/include/endian.h
+diskio-windows.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+diskio-windows.o: /usr/include/sys/select.h /usr/include/bits/select.h
+diskio-windows.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+diskio-windows.o: /usr/include/sys/sysmacros.h
+diskio-windows.o: /usr/include/bits/pthreadtypes.h /usr/include/sys/stat.h
+diskio-windows.o: /usr/include/bits/stat.h support.h /usr/include/stdlib.h
+diskio-windows.o: /usr/include/alloca.h diskio.h /usr/include/sys/ioctl.h
+diskio-windows.o: /usr/include/bits/ioctls.h /usr/include/asm/ioctls.h
+diskio-windows.o: /usr/include/asm-generic/ioctls.h
+diskio-windows.o: /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h
+diskio-windows.o: /usr/include/asm-generic/ioctl.h
+diskio-windows.o: /usr/include/bits/ioctl-types.h
+diskio-windows.o: /usr/include/sys/ttydefaults.h parttypes.h guid.h
+diskio-windows.o: /usr/include/uuid/uuid.h /usr/include/sys/time.h
+gdisk.o: /usr/include/stdio.h /usr/include/features.h
+gdisk.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+gdisk.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+gdisk.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+gdisk.o: /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h
+gdisk.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+gdisk.o: /usr/include/string.h /usr/include/xlocale.h mbr.h
+gdisk.o: /usr/include/stdint.h /usr/include/bits/wchar.h
+gdisk.o: /usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h
+gdisk.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+gdisk.o: /usr/include/sys/select.h /usr/include/bits/select.h
+gdisk.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+gdisk.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
+gdisk.o: gptpart.h support.h /usr/include/stdlib.h /usr/include/alloca.h
+gdisk.o: parttypes.h guid.h /usr/include/uuid/uuid.h /usr/include/sys/time.h
+gdisk.o: attributes.h partnotes.h gpt.h bsd.h diskio.h
+gdisk.o: /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h
+gdisk.o: /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h
+gdisk.o: /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h
+gdisk.o: /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h
+gdisk.o: /usr/include/sys/ttydefaults.h gpttext.h
+gpt.o: /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h
+gpt.o: /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h
+gpt.o: /usr/include/gnu/stubs-64.h /usr/include/bits/types.h
+gpt.o: /usr/include/bits/typesizes.h /usr/include/libio.h
+gpt.o: /usr/include/_G_config.h /usr/include/wchar.h
+gpt.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+gpt.o: /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h
+gpt.o: /usr/include/endian.h /usr/include/bits/endian.h
+gpt.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
+gpt.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+gpt.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
+gpt.o: /usr/include/bits/pthreadtypes.h /usr/include/alloca.h
+gpt.o: /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/fcntl.h
+gpt.o: /usr/include/bits/fcntl.h /usr/include/string.h /usr/include/xlocale.h
+gpt.o: /usr/include/math.h /usr/include/bits/huge_val.h
+gpt.o: /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h
+gpt.o: /usr/include/bits/inf.h /usr/include/bits/nan.h
+gpt.o: /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h
+gpt.o: /usr/include/sys/stat.h /usr/include/bits/stat.h /usr/include/errno.h
+gpt.o: /usr/include/bits/errno.h /usr/include/linux/errno.h
+gpt.o: /usr/include/asm/errno.h /usr/include/asm-generic/errno.h
+gpt.o: /usr/include/asm-generic/errno-base.h crc32.h gpt.h gptpart.h
+gpt.o: support.h parttypes.h guid.h /usr/include/uuid/uuid.h
+gpt.o: /usr/include/sys/time.h attributes.h mbr.h partnotes.h diskio.h
+gpt.o: /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h
+gpt.o: /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h
+gpt.o: /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h
+gpt.o: /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h
+gpt.o: /usr/include/sys/ttydefaults.h bsd.h
+gptpart.o: /usr/include/string.h /usr/include/features.h
+gptpart.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+gptpart.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+gptpart.o: /usr/include/xlocale.h /usr/include/stdio.h
+gptpart.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+gptpart.o: /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h
+gptpart.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+gptpart.o: gptpart.h /usr/include/stdint.h /usr/include/bits/wchar.h
+gptpart.o: /usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h
+gptpart.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+gptpart.o: /usr/include/sys/select.h /usr/include/bits/select.h
+gptpart.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+gptpart.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
+gptpart.o: support.h /usr/include/stdlib.h /usr/include/alloca.h parttypes.h
+gptpart.o: guid.h /usr/include/uuid/uuid.h /usr/include/sys/time.h
+gptpart.o: attributes.h
+gpttext.o: /usr/include/string.h /usr/include/features.h
+gpttext.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+gpttext.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+gpttext.o: /usr/include/xlocale.h /usr/include/errno.h
+gpttext.o: /usr/include/bits/errno.h /usr/include/linux/errno.h
+gpttext.o: /usr/include/asm/errno.h /usr/include/asm-generic/errno.h
+gpttext.o: /usr/include/asm-generic/errno-base.h /usr/include/stdint.h
+gpttext.o: /usr/include/bits/wchar.h /usr/include/limits.h
+gpttext.o: /usr/include/bits/posix1_lim.h /usr/include/bits/local_lim.h
+gpttext.o: /usr/include/linux/limits.h /usr/include/bits/posix2_lim.h
+gpttext.o: attributes.h gpttext.h gpt.h /usr/include/sys/types.h
+gpttext.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+gpttext.o: /usr/include/time.h /usr/include/endian.h
+gpttext.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+gpttext.o: /usr/include/sys/select.h /usr/include/bits/select.h
+gpttext.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+gpttext.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
+gpttext.o: gptpart.h support.h /usr/include/stdlib.h /usr/include/alloca.h
+gpttext.o: parttypes.h guid.h /usr/include/uuid/uuid.h
+gpttext.o: /usr/include/sys/time.h mbr.h partnotes.h diskio.h
+gpttext.o: /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h
+gpttext.o: /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h
+gpttext.o: /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h
+gpttext.o: /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h
+gpttext.o: /usr/include/sys/ttydefaults.h bsd.h
+guid.o: /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h
+guid.o: /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h
+guid.o: /usr/include/gnu/stubs-64.h /usr/include/bits/types.h
+guid.o: /usr/include/bits/typesizes.h /usr/include/libio.h
+guid.o: /usr/include/_G_config.h /usr/include/wchar.h
+guid.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+guid.o: /usr/include/time.h guid.h /usr/include/stdint.h
+guid.o: /usr/include/bits/wchar.h /usr/include/uuid/uuid.h
+guid.o: /usr/include/sys/types.h /usr/include/endian.h
+guid.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+guid.o: /usr/include/sys/select.h /usr/include/bits/select.h
+guid.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+guid.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
+guid.o: /usr/include/sys/time.h support.h /usr/include/stdlib.h
+guid.o: /usr/include/alloca.h
+mbr.o: /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h
+mbr.o: /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h
+mbr.o: /usr/include/gnu/stubs-64.h /usr/include/bits/types.h
+mbr.o: /usr/include/bits/typesizes.h /usr/include/libio.h
+mbr.o: /usr/include/_G_config.h /usr/include/wchar.h
+mbr.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+mbr.o: /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h
+mbr.o: /usr/include/endian.h /usr/include/bits/endian.h
+mbr.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
+mbr.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+mbr.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
+mbr.o: /usr/include/bits/pthreadtypes.h /usr/include/alloca.h
+mbr.o: /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/fcntl.h
+mbr.o: /usr/include/bits/fcntl.h /usr/include/string.h /usr/include/xlocale.h
+mbr.o: /usr/include/sys/stat.h /usr/include/bits/stat.h /usr/include/errno.h
+mbr.o: /usr/include/bits/errno.h /usr/include/linux/errno.h
+mbr.o: /usr/include/asm/errno.h /usr/include/asm-generic/errno.h
+mbr.o: /usr/include/asm-generic/errno-base.h mbr.h gptpart.h support.h
+mbr.o: parttypes.h guid.h /usr/include/uuid/uuid.h /usr/include/sys/time.h
+mbr.o: attributes.h partnotes.h gpt.h bsd.h diskio.h /usr/include/sys/ioctl.h
+mbr.o: /usr/include/bits/ioctls.h /usr/include/asm/ioctls.h
+mbr.o: /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h
+mbr.o: /usr/include/asm/ioctl.h /usr/include/asm-generic/ioctl.h
+mbr.o: /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h
+partnotes.o: /usr/include/stdio.h /usr/include/features.h
+partnotes.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+partnotes.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+partnotes.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+partnotes.o: /usr/include/libio.h /usr/include/_G_config.h
+partnotes.o: /usr/include/wchar.h /usr/include/bits/stdio_lim.h
+partnotes.o: /usr/include/bits/sys_errlist.h partnotes.h gpt.h
+partnotes.o: /usr/include/stdint.h /usr/include/bits/wchar.h
+partnotes.o: /usr/include/sys/types.h /usr/include/time.h
+partnotes.o: /usr/include/endian.h /usr/include/bits/endian.h
+partnotes.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
+partnotes.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+partnotes.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
+partnotes.o: /usr/include/bits/pthreadtypes.h gptpart.h support.h
+partnotes.o: /usr/include/stdlib.h /usr/include/alloca.h parttypes.h guid.h
+partnotes.o: /usr/include/uuid/uuid.h /usr/include/sys/time.h attributes.h
+partnotes.o: mbr.h diskio.h /usr/include/sys/ioctl.h
+partnotes.o: /usr/include/bits/ioctls.h /usr/include/asm/ioctls.h
+partnotes.o: /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h
+partnotes.o: /usr/include/asm/ioctl.h /usr/include/asm-generic/ioctl.h
+partnotes.o: /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h
+partnotes.o: bsd.h
+parttypes.o: /usr/include/string.h /usr/include/features.h
+parttypes.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+parttypes.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+parttypes.o: /usr/include/xlocale.h /usr/include/stdint.h
+parttypes.o: /usr/include/bits/wchar.h /usr/include/stdio.h
+parttypes.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+parttypes.o: /usr/include/libio.h /usr/include/_G_config.h
+parttypes.o: /usr/include/wchar.h /usr/include/bits/stdio_lim.h
+parttypes.o: /usr/include/bits/sys_errlist.h parttypes.h
+parttypes.o: /usr/include/stdlib.h /usr/include/sys/types.h
+parttypes.o: /usr/include/time.h /usr/include/endian.h
+parttypes.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+parttypes.o: /usr/include/sys/select.h /usr/include/bits/select.h
+parttypes.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+parttypes.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
+parttypes.o: /usr/include/alloca.h support.h guid.h /usr/include/uuid/uuid.h
+parttypes.o: /usr/include/sys/time.h
+sgdisk.o: /usr/include/stdio.h /usr/include/features.h
+sgdisk.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+sgdisk.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+sgdisk.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+sgdisk.o: /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h
+sgdisk.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+sgdisk.o: /usr/include/popt.h /usr/include/errno.h /usr/include/bits/errno.h
+sgdisk.o: /usr/include/linux/errno.h /usr/include/asm/errno.h
+sgdisk.o: /usr/include/asm-generic/errno.h
+sgdisk.o: /usr/include/asm-generic/errno-base.h /usr/include/stdint.h
+sgdisk.o: /usr/include/bits/wchar.h mbr.h /usr/include/sys/types.h
+sgdisk.o: /usr/include/time.h /usr/include/endian.h
+sgdisk.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+sgdisk.o: /usr/include/sys/select.h /usr/include/bits/select.h
+sgdisk.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+sgdisk.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
+sgdisk.o: gptpart.h support.h /usr/include/stdlib.h /usr/include/alloca.h
+sgdisk.o: parttypes.h guid.h /usr/include/uuid/uuid.h /usr/include/sys/time.h
+sgdisk.o: attributes.h partnotes.h gpt.h bsd.h diskio.h
+sgdisk.o: /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h
+sgdisk.o: /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h
+sgdisk.o: /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h
+sgdisk.o: /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h
+sgdisk.o: /usr/include/sys/ttydefaults.h
+support.o: /usr/include/stdio.h /usr/include/features.h
+support.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+support.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+support.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+support.o: /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h
+support.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+support.o: /usr/include/stdint.h /usr/include/bits/wchar.h
+support.o: /usr/include/errno.h /usr/include/bits/errno.h
+support.o: /usr/include/linux/errno.h /usr/include/asm/errno.h
+support.o: /usr/include/asm-generic/errno.h
+support.o: /usr/include/asm-generic/errno-base.h /usr/include/fcntl.h
+support.o: /usr/include/bits/fcntl.h /usr/include/sys/types.h
+support.o: /usr/include/time.h /usr/include/endian.h
+support.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+support.o: /usr/include/sys/select.h /usr/include/bits/select.h
+support.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+support.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
+support.o: /usr/include/string.h /usr/include/xlocale.h
+support.o: /usr/include/sys/stat.h /usr/include/bits/stat.h support.h
+support.o: /usr/include/stdlib.h /usr/include/alloca.h
+testguid.o: guid.h /usr/include/stdint.h /usr/include/features.h
+testguid.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+testguid.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+testguid.o: /usr/include/bits/wchar.h /usr/include/uuid/uuid.h
+testguid.o: /usr/include/sys/types.h /usr/include/bits/types.h
+testguid.o: /usr/include/bits/typesizes.h /usr/include/time.h
+testguid.o: /usr/include/endian.h /usr/include/bits/endian.h
+testguid.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
+testguid.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+testguid.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
+testguid.o: /usr/include/bits/pthreadtypes.h /usr/include/sys/time.h
+testguid.o: parttypes.h /usr/include/stdlib.h /usr/include/alloca.h support.h
diff --git a/Makefile.mac b/Makefile.mac
index 99a6ea38ede146af4695f3947b24709a30a92cd3..9c55308f6628220232c301630f6692c7dd345313 100644
--- a/Makefile.mac
+++ b/Makefile.mac
@@ -2,7 +2,7 @@ CC=gcc
 CXX=g++
 CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g
 CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
-LIB_NAMES=crc32 support guid partnotes gptpart mbr gpt bsd parttypes attributes diskio diskio-unix
+LIB_NAMES=crc32 support guid partnotes gptpartnotes gptpart basicmbr mbr gpt bsd parttypes attributes diskio diskio-unix
 LIB_SRCS=$(NAMES:=.cc)
 LIB_OBJS=$(LIB_NAMES:=.o)
 LIB_HEADERS=$(LIB_NAMES:=.h)
diff --git a/Makefile.mingw b/Makefile.mingw
index 07e2de787986df0711a73c21497b0846f3100354..9f3a9a36839c143f4670815d3ac82cd257455cef 100644
--- a/Makefile.mingw
+++ b/Makefile.mingw
@@ -1,10 +1,10 @@
-CC=/usr/bin/i586-mingw32msvc-gcc
-CXX=/usr/bin/i586-mingw32msvc-g++
-STRIP=/usr/bin/i586-mingw32msvc-strip
+CC=/usr/bin/i686-pc-mingw32-gcc
+CXX=/usr/bin/i686-pc-mingw32-g++
+STRIP=/usr/bin/i686-pc-mingw32-strip
 CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g
 CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -g
 #CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
-LIB_NAMES=guid gptpart partnotes bsd parttypes attributes crc32 mbr gpt support diskio diskio-windows
+LIB_NAMES=guid gptpart bsd parttypes partnotes gptpartnotes attributes crc32 basicmbr mbr gpt support diskio diskio-windows
 LIB_SRCS=$(NAMES:=.cc)
 LIB_OBJS=$(LIB_NAMES:=.o)
 LIB_HEADERS=$(LIB_NAMES:=.h)
@@ -12,8 +12,8 @@ DEPEND= makedepend $(CFLAGS)
 
 all:	gdisk
 
-gdisk:	$(LIB_OBJS) gpttext.o gdisk.o
-	$(CXX) $(LIB_OBJS) gpttext.o gdisk.o -luuid -o gdisk.exe
+gdisk:	$(LIB_OBJS) gdisk.o gpttext.o
+	$(CXX) $(LIB_OBJS) gdisk.o gpttext.o -luuid -static-libgcc -o gdisk.exe
 
 sgdisk: $(LIB_OBJS) sgdisk.o
 	$(CXX) $(LIB_OBJS) sgdisk.o -lpopt -o sgdisk.exe
diff --git a/NEWS b/NEWS
index eabf53d802fa3287a6d103cf1e01fcb3f18840a7..e90d99bca73bd351b1f6f57c3a7a7095bf288082 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,26 @@
+0.6.15 (?/?/2011):
+------------------
+
+- Enhanced disk replication features ('u' on the experts' menu in gdisk; -R
+  or --replicate in sgdisk). It's now possible to replicate the partition
+  table from a larger to a smaller disk, so long as all the partitions fit
+  on the smaller disk. In sgdisk, the secondary GPT data are moved
+  automatically if disk sizes don't match. In gdisk, the secondary GPT data
+  are moved automatically if the target disk is smaller than the source
+  disk; if the target disk is larger than the source disk, the user is
+  given the option of making this adjustment.
+
+- Fixed --load-backup (-l) option to sgdisk, which was broken.
+
+- Changed largest drive that's not given a minimum 4 KiB alignment even
+  when smaller alignment is detected on the disk to 300 GB.
+
+- Fixed bug that preventing a partition table backup ('u' on the
+  experts' menu) by hitting the Enter key for the device filename.
+
+- Implemented a number of code cleanups provided by an anonymous
+  contributor.
+
 0.6.14 (1/8/2011):
 ------------------
 
diff --git a/attributes.cc b/attributes.cc
index 07f909ae84158b07c4daa2078aba107d6499db05..0abed40d78c9189f22fe5723faf113123fe1fa0f 100644
--- a/attributes.cc
+++ b/attributes.cc
@@ -1,8 +1,9 @@
 // attributes.cc
 // Class to manage partition attribute codes. These are binary bit fields,
-// of which only three are currently (2/2009) documented on Wikipedia.
+// of which only four are currently (2/2011) documented on Wikipedia, and
+// two others found from other sources.
 
-/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
+/* 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. */
 
 #define __STDC_LIMIT_MACROS
diff --git a/attributes.h b/attributes.h
index 0ae4487dbf804b54312d47283e4fd40ecc21b9dd..f6c66ff48712215a7b5d2cb89ae9049514307d31 100644
--- a/attributes.h
+++ b/attributes.h
@@ -1,4 +1,4 @@
-/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
+/* 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>
diff --git a/diskio-unix.cc b/diskio-unix.cc
index b20f1614234d9279e8dcd2688a6532640bd1bcc1..d65a6447542d71653ce388f426b13f507c2e9816 100644
--- a/diskio-unix.cc
+++ b/diskio-unix.cc
@@ -348,7 +348,7 @@ uint64_t DiskIO::DiskSize(int *err) {
       if (*err) {
          sectors = sz = 0;
       } // if
-      if ((errno == EFBIG) || (!*err)) {
+      if ((!*err) || (errno == EFBIG)) {
          *err = ioctl(fd, BLKGETSIZE64, &b);
          if (*err || b == 0 || b == sz)
             sectors = sz;
diff --git a/diskio.h b/diskio.h
index 9c709c53f58aa6c294f5f10be0fe5b3676a726ba..d9f0d38d91d71ce883e1126d718391da39086220 100644
--- a/diskio.h
+++ b/diskio.h
@@ -69,7 +69,7 @@ class DiskIO {
       int GetBlockSize(void);
       int IsOpen(void) {return isOpen;}
       int IsOpenForWrite(void) {return openForWrite;}
-      string GetName(void) {return realFilename;}
+      string GetName(void) const {return realFilename;}
 
       uint64_t DiskSize(int* err);
 }; // struct GPTPart
diff --git a/gdisk.8 b/gdisk.8
index 7d5d2c62ea0301cd68daba48c2fadc9df510303b..272677ce49c130fb52bf27600207e28de23bf14c 100644
--- a/gdisk.8
+++ b/gdisk.8
@@ -471,10 +471,11 @@ physical sectors (such as some Western Digital models introduced in
 December of 2009) and some RAID configurations 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
-2048\-sector (1MiB) boundaries by default, which optimizes performance
-for both of these disk types. On pre\-partitioned disks, GPT fdisk
-attempts to identify the alignment value used on that disk. In either
-case, it can be changed by using this option.
+2048\-sector (1MiB) boundaries by default, which optimizes performance for
+both 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.
 
 .TP 
 .B m
@@ -663,6 +664,8 @@ Contributors:
 
 * Dwight Schauer (dschauer@ti.com)
 
+* Florian Zumbiehl (florz@florz.de)
+
 
 .SH "SEE ALSO"
 \fBcfdisk (8)\fR,
diff --git a/gdisk.cc b/gdisk.cc
index f47ec5ea9d4cc729a7e5f5e6074c2646f4c8a39e..f78643114f1b576723f5b57776981a57e33fd2cc 100644
--- a/gdisk.cc
+++ b/gdisk.cc
@@ -4,7 +4,7 @@
 //
 // by Rod Smith, project began February 2009
 
-/* This program is copyright (c) 2009, 2010 by Roderick W. Smith. It is distributed
+/* 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 <stdio.h>
@@ -29,8 +29,8 @@ void WinWarning(void);
 
 int main(int argc, char* argv[]) {
    GPTDataTextUI theGPT;
-   int doMore = 1, i;
-   char *device = NULL, *junk;
+   size_t i;
+   char *device = NULL;
 
    cout << "GPT fdisk (gdisk) version " << GPTFDISK_VERSION << "\n\n";
 
@@ -42,25 +42,21 @@ int main(int argc, char* argv[]) {
          WinWarning();
          cout << "Type device filename, or press <Enter> to exit: ";
          device = new char[255];
-         junk = fgets(device, 255, stdin);
-         if (device[0] != '\n') {
-            i = (int) strlen(device);
-            if (i > 0)
-               if (device[i - 1] == '\n')
-                  device[i - 1] = '\0';
-            doMore = theGPT.LoadPartitions(device);
-            if (doMore) {
-               MainMenu(device, &theGPT);
-            } // if (doMore)
+         if (!fgets(device, 255, stdin)) {
+            cerr << "Critical error! Failed fgets() in main()!\n";
+            exit(1);
          } // if
+         i = strlen(device);
+         if (i && device[i - 1] == '\n')
+            device[i - 1] = '\0';
+         if (*device && theGPT.LoadPartitions(device))
+            MainMenu(device, &theGPT);
          delete[] device;
          break;
       case 2: // basic usage
          WinWarning();
-         doMore = theGPT.LoadPartitions(argv[1]);
-         if (doMore) {
+         if (theGPT.LoadPartitions(argv[1]))
             MainMenu(argv[1], &theGPT);
-         } // if (doMore)
          break;
       case 3: // usage with "-l" option
          if (strcmp(argv[1], "-l") == 0) {
@@ -72,8 +68,8 @@ int main(int argc, char* argv[]) {
          } // if/elseif/else
          if (device != NULL) {
             theGPT.JustLooking();
-            doMore = theGPT.LoadPartitions((string) device);
-            if (doMore) theGPT.DisplayGPTData();
+            if (theGPT.LoadPartitions((string) device))
+               theGPT.DisplayGPTData();
          } // if
          break;
       default:
@@ -85,23 +81,27 @@ int main(int argc, char* argv[]) {
 // Accept a command and execute it. Returns only when the user
 // wants to exit (such as after a 'w' or 'q' command).
 void MainMenu(string filename, GPTDataTextUI* theGPT) {
-   char command, line[255], buFile[255];
-   char* junk;
+   char line[255], buFile[255];
    int goOn = 1;
    PartType typeHelper;
    uint32_t temp1, temp2;
 
    do {
       cout << "\nCommand (? for help): ";
-      junk = fgets(line, 255, stdin);
-      sscanf(line, "%c", &command);
-      switch (command) {
+      if (!fgets(line, 255, stdin)) {
+         cerr << "Critical error! Failed fgets() in MainMenu()!\n";
+         exit(1);
+      } // if
+      switch (*line) {
          case '\n':
             break;
          case 'b': case 'B':
             cout << "Enter backup filename to save: ";
-            junk = fgets(line, 255, stdin);
-            sscanf(line, "%s", (char*) &buFile);
+            if (!fgets(line, 255, stdin)) {
+               exit(1);
+               cerr << "Critical error! Failed fgets() in MainMenu()!\n";
+            } // if
+            sscanf(line, "%s", buFile);
             theGPT->SaveGPTBackup(buFile);
             break;
          case 'c': case 'C':
@@ -187,16 +187,17 @@ void ShowCommands(void) {
 // Accept a recovery & transformation menu command. Returns only when the user
 // issues an exit command, such as 'w' or 'q'.
 void RecoveryMenu(string filename, GPTDataTextUI* theGPT) {
-   char command, line[255], buFile[255];
-   char* junk;
+   char line[255], buFile[255];
    uint32_t temp1, numParts;
    int goOn = 1;
 
    do {
       cout << "\nRecovery/transformation command (? for help): ";
-      junk = fgets(line, 255, stdin);
-      sscanf(line, "%c", &command);
-      switch (command) {
+      if (!fgets(line, 255, stdin)) {
+         cerr << "Critical error! Failed fgets() in RecoveryMenu()!\n";
+         exit(1);
+      } // if
+      switch (*line) {
          case '\n':
             break;
          case 'b': case 'B':
@@ -251,8 +252,11 @@ void RecoveryMenu(string filename, GPTDataTextUI* theGPT) {
             break;
          case 'l': case 'L':
             cout << "Enter backup filename to load: ";
-            junk = fgets(line, 255, stdin);
-            sscanf(line, "%s", (char*) &buFile);
+            if (!fgets(line, 255, stdin)) {
+               cerr << "Critical error! Failed fgets() in RecoveryMenu()!\n";
+               exit(1);
+            } // if
+            sscanf(line, "%s", buFile);
             theGPT->LoadGPTBackup(buFile);
             break;
          case 'm': case 'M':
@@ -314,19 +318,22 @@ void ShowRecoveryCommands(void) {
 // Accept an experts' menu command. Returns only after the user
 // selects an exit command, such as 'w' or 'q'.
 void ExpertsMenu(string filename, GPTDataTextUI* theGPT) {
-   char command, line[255], *device;
-   char* junk;
+   GPTData secondDevice;
+   char line[255], *device;
    uint32_t pn, temp1, temp2;
-   int goOn = 1, i;
+   int goOn = 1;
+   size_t i;
    char guidStr[255];
    GUIDData aGUID;
    ostringstream prompt;
 
    do {
       cout << "\nExpert command (? for help): ";
-      junk = fgets(line, 255, stdin);
-      sscanf(line, "%c", &command);
-      switch (command) {
+      if (!fgets(line, 255, stdin)) {
+         cerr << "Critical error! Failed fgets() in ExpertsMenu()!\n";
+         exit(1);
+      } // if
+      switch (*line) {
          case '\n':
             break;
          case 'a': case 'A':
@@ -339,7 +346,10 @@ void ExpertsMenu(string filename, GPTDataTextUI* theGPT) {
             if (theGPT->GetPartRange(&temp1, &temp2) > 0) {
                pn = theGPT->GetPartNum();
                cout << "Enter the partition's new unique GUID ('R' to randomize): ";
-               junk = fgets(guidStr, 255, stdin);
+               if (!fgets(guidStr, 255, stdin)) {
+                  cerr << "Critical error! Failed fgets() in ExpertsMenu()!\n";
+                  exit(1);
+               } // if
                if ((strlen(guidStr) >= 33) || (guidStr[0] == 'R') || (guidStr[0] == 'r')) {
                   theGPT->SetPartitionGUID(pn, (GUIDData) guidStr);
                   cout << "New GUID is " << theGPT->operator[](pn).GetUniqueGUID() << "\n";
@@ -361,7 +371,10 @@ void ExpertsMenu(string filename, GPTDataTextUI* theGPT) {
             break;
          case 'g': case 'G':
             cout << "Enter the disk's unique GUID ('R' to randomize): ";
-            junk = fgets(guidStr, 255, stdin);
+            if (!fgets(guidStr, 255, stdin)) {
+               cerr << "Critical error! Failed fgets() in ExpertsMenu()!\n";
+               exit(1);
+            } // if
             if ((strlen(guidStr) >= 33) || (guidStr[0] == 'R') || (guidStr[0] == 'r')) {
                theGPT->SetDiskGUID((GUIDData) guidStr);
                cout << "The new disk GUID is " << theGPT->GetDiskGUID() << "\n";
@@ -395,8 +408,8 @@ void ExpertsMenu(string filename, GPTDataTextUI* theGPT) {
             theGPT->DisplayGPTData();
             break;
          case 'q': case 'Q':
-	         goOn = 0;
-	         break;
+            goOn = 0;
+            break;
          case 'r': case 'R':
             RecoveryMenu(filename, theGPT);
             goOn = 0;
@@ -404,21 +417,24 @@ void ExpertsMenu(string filename, GPTDataTextUI* theGPT) {
          case 's': case 'S':
             theGPT->ResizePartitionTable();
             break;
-	      case 't': case 'T':
-	         theGPT->SwapPartitions();
-	         break;
+         case 't': case 'T':
+            theGPT->SwapPartitions();
+            break;
          case 'u': case 'U':
             cout << "Type device filename, or press <Enter> to exit: ";
             device = new char[255];
-            junk = fgets(device, 255, stdin);
-            if (device[0] != '\n') {
-               i = (int) strlen(device);
-               if (i > 0)
-                  if (device[i - 1] == '\n')
-                     device[i - 1] = '\0';
+            if (!fgets(device, 255, stdin)) {
+               cerr << "Critical error! Failed fgets() in ExpertsMenu()!\n";
+               exit(1);
+            } // if
+            i = strlen(device);
+            if (i && device[i - 1] == '\n')
+               device[i - 1] = '\0';
+            if (*device && strlen(device) > 0) {
+               secondDevice = *theGPT;
+               secondDevice.SetFile(device);
+               secondDevice.SaveGPTData(0);
             } // if
-            if (strlen(device) > 0)
-               theGPT->SaveGPTData(0, device);
             delete[] device;
             break;
          case 'v': case 'V':
diff --git a/gpt.cc b/gpt.cc
index bcc053a9784489c49cbd7afe29080ed86581f844..309a038fb8264080dec82347ec1260f05cf01362 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -3,7 +3,7 @@
 
 /* By Rod Smith, initial coding January to February, 2009 */
 
-/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
+/* 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. */
 
 #define __STDC_LIMIT_MACROS
@@ -96,6 +96,45 @@ GPTData::~GPTData(void) {
    delete[] partitions;
 } // GPTData destructor
 
+// Assignment operator
+GPTData & GPTData::operator=(const GPTData & orig) {
+   uint32_t i;
+
+   mainHeader = orig.mainHeader;
+   numParts = orig.numParts;
+   secondHeader = orig.secondHeader;
+   protectiveMBR = orig.protectiveMBR;
+   device = orig.device;
+   blockSize = orig.blockSize;
+   diskSize = orig.diskSize;
+   state = orig.state;
+   justLooking = orig.justLooking;
+   mainCrcOk = orig.mainCrcOk;
+   secondCrcOk = orig.secondCrcOk;
+   mainPartsCrcOk = orig.mainPartsCrcOk;
+   secondPartsCrcOk = orig.secondPartsCrcOk;
+   apmFound = orig.apmFound;
+   bsdFound = orig.bsdFound;
+   sectorAlignment = orig.sectorAlignment;
+   beQuiet = orig.beQuiet;
+   whichWasUsed = orig.whichWasUsed;
+
+   myDisk.OpenForRead(orig.myDisk.GetName());
+
+   delete[] partitions;
+   partitions = new GPTPart [numParts * sizeof (GPTPart)];
+   if (partitions != NULL) {
+      for (i = 0; i < numParts; i++) {
+         partitions[i] = orig.partitions[i];
+      }
+   } else {
+      numParts = 0;
+      cerr << "Error! Could not allocate memory for partitions in GPTData::operator=()!\n"
+           << "Continuing, but strange problems may occur!\n";
+   } // if/else
+   return *this;
+} // GPTData::operator=()
+
 /*********************************************************************
  *                                                                   *
  * Begin functions that verify data, or that adjust the verification *
@@ -107,7 +146,7 @@ GPTData::~GPTData(void) {
 // do *NOT* recover from these problems. Returns the total number of
 // problems identified.
 int GPTData::Verify(void) {
-   int problems = 0;
+   int problems = 0, alignProbs = 0;
    uint32_t i, numSegments;
    uint64_t totalFree, largestSegment;
 
@@ -210,11 +249,11 @@ int GPTData::Verify(void) {
 
    // Now check for a few other miscellaneous problems...
    // Check that the disk size will hold the data...
-   if (mainHeader.backupLBA > diskSize) {
+   if (mainHeader.backupLBA >= diskSize) {
       problems++;
       cout << "\nProblem: Disk is too small to hold all the data!\n"
            << "(Disk size is " << diskSize << " sectors, needs to be "
-           << mainHeader.backupLBA << " sectors.)\n"
+           << mainHeader.backupLBA + UINT64_C(1) << " sectors.)\n"
            << "The 'e' option on the experts' menu may fix this problem.\n";
    } // if
 
@@ -240,14 +279,18 @@ int GPTData::Verify(void) {
          cout << "\nCaution: Partition " << i + 1 << " doesn't begin on a "
               << sectorAlignment << "-sector boundary. This may\nresult "
               << "in degraded performance on some modern (2009 and later) hard disks.\n";
+         alignProbs++;
       } // if
    } // for
+   if (alignProbs > 0)
+      cout << "\nConsult http://www.ibm.com/developerworks/linux/library/l-4kb-sector-disks/\n"
+      << "for information on disk alignment.\n";
 
    // Now compute available space, but only if no problems found, since
    // problems could affect the results
    if (problems == 0) {
       totalFree = FindFreeBlocks(&numSegments, &largestSegment);
-      cout << "No problems found. " << totalFree << " free sectors ("
+      cout << "\nNo problems found. " << totalFree << " free sectors ("
            << BytesToSI(totalFree, blockSize) << ") available in "
            << numSegments << "\nsegments, the largest of which is "
            << largestSegment << " (" << BytesToSI(largestSegment, blockSize)
@@ -563,6 +606,24 @@ int GPTData::FindInsanePartitions(void) {
  *                                                                *
  ******************************************************************/
 
+// Change the filename associated with the GPT. Used for duplicating
+// the partition table to a new disk and saving backups.
+// Returns 1 on success, 0 on failure.
+int GPTData::SetFile(const string & deviceFilename) {
+   int err, allOK = 1;
+
+   device = deviceFilename;
+   if (allOK && myDisk.OpenForRead(deviceFilename)) {
+      // store disk information....
+      diskSize = myDisk.DiskSize(&err);
+      blockSize = (uint32_t) myDisk.GetBlockSize();
+   } // if
+   protectiveMBR.SetDisk(&myDisk);
+   protectiveMBR.SetDiskSize(diskSize);
+   protectiveMBR.SetBlockSize(blockSize);
+   return allOK;
+} // GPTData::SetFile()
+
 // Scan for partition data. This function loads the MBR data (regular MBR or
 // protective MBR) and loads BSD disklabel data (which is probably invalid).
 // It also looks for APM data, forces a load of GPT data, and summarizes
@@ -869,20 +930,15 @@ int GPTData::CheckTable(struct GPTHeader *header) {
    return newCrcOk;
 } // GPTData::CheckTable()
 
-// Writes GPT (and protective MBR) to disk. Returns 1 on successful
+// Writes GPT (and protective MBR) to disk. If quiet==1, 
+// Returns 1 on successful
 // write, 0 if there was a problem.
-int GPTData::SaveGPTData(int quiet, string filename) {
+int GPTData::SaveGPTData(int quiet) {
    int allOK = 1, littleEndian;
    char answer;
 
    littleEndian = IsLittleEndian();
 
-   if (filename == "")
-      filename = device;
-   if (filename == "") {
-      cerr << "Device not defined.\n";
-   } // if
-
    // First do some final sanity checks....
 
    // This test should only fail on read-only disks....
@@ -891,30 +947,34 @@ int GPTData::SaveGPTData(int quiet, string filename) {
       allOK = 0;
    } // if
 
+   // Check that disk is really big enough to handle the second header...
+   if (mainHeader.backupLBA >= diskSize) {
+      cerr << "Caution! Secondary header was placed beyond the disk's limits! Moving the\n"
+           << "header, but other problems may occur!\n";
+      MoveSecondHeaderToEnd();
+   } // if
+
    // Is there enough space to hold the GPT headers and partition tables,
    // given the partition sizes?
    if (CheckGPTSize() > 0) {
       allOK = 0;
    } // if
 
-   // Check that disk is really big enough to handle this...
-   if (mainHeader.backupLBA > diskSize) {
-      cerr << "Error! Disk is too small! The 'e' option on the experts' menu might fix the\n"
-           << "problem (or it might not). Aborting!\n(Disk size is "
-           << diskSize << " sectors, needs to be " << mainHeader.backupLBA << " sectors.)\n";
-      allOK = 0;
-   } // if
    // Check that second header is properly placed. Warn and ask if this should
    // be corrected if the test fails....
-   if ((mainHeader.backupLBA < (diskSize - UINT64_C(1))) && (quiet == 0)) {
-      cout << "Warning! Secondary header is placed too early on the disk! Do you want to\n"
-           << "correct this problem? ";
-      if (GetYN() == 'Y') {
+   if (mainHeader.backupLBA < (diskSize - UINT64_C(1))) {
+      if (quiet == 0) {
+         cout << "Warning! Secondary header is placed too early on the disk! Do you want to\n"
+              << "correct this problem? ";
+         if (GetYN() == 'Y') {
+            MoveSecondHeaderToEnd();
+            cout << "Have moved second header and partition table to correct location.\n";
+         } else {
+            cout << "Have not corrected the problem. Strange problems may occur in the future!\n";
+         } // if correction requested
+      } else { // Go ahead and do correction automatically
          MoveSecondHeaderToEnd();
-         cout << "Have moved second header and partition table to correct location.\n";
-      } else {
-         cout << "Have not corrected the problem. Strange problems may occur in the future!\n";
-      } // if correction requested
+      } // if/else quiet
    } // if
 
    // Check for overlapping or insane partitions....
@@ -942,7 +1002,7 @@ int GPTData::SaveGPTData(int quiet, string filename) {
 
    // Do it!
    if (allOK) {
-      if (myDisk.OpenForWrite(filename)) {
+      if (myDisk.OpenForWrite()) {
          // As per UEFI specs, write the secondary table and GPT first....
          allOK = SavePartitionTable(myDisk, secondHeader.partitionEntriesLBA);
          if (!allOK)
@@ -975,7 +1035,7 @@ int GPTData::SaveGPTData(int quiet, string filename) {
 
          myDisk.Close();
       } else {
-         cerr << "Unable to open device " << filename << " for writing! Errno is "
+         cerr << "Unable to open device " << myDisk.GetName() << " for writing! Errno is "
               << errno << "! Aborting write!\n";
          allOK = 0;
       } // if/else
@@ -1513,24 +1573,24 @@ int GPTData::PartsToMBR(PartNotes * notes) {
       notes->MakeItLegal();
    notes->Rewind();
    while (notes->GetNextInfo(&convInfo) >= 0) {
-      if ((convInfo.gptPartNum >= 0) && (convInfo.type == PRIMARY)) {
-         numConverted += OnePartToMBR((uint32_t) convInfo.gptPartNum, mbrNum);
+      if ((convInfo.origPartNum >= 0) && (convInfo.type == PRIMARY)) {
+         numConverted += OnePartToMBR((uint32_t) convInfo.origPartNum, mbrNum);
          if (convInfo.hexCode != 0)
             protectiveMBR.SetPartType(mbrNum, convInfo.hexCode);
          if (convInfo.active)
             protectiveMBR.SetPartBootable(mbrNum);
          mbrNum++;
       } // if
-      if (convInfo.gptPartNum == MBR_EFI_GPT)
+      if (convInfo.origPartNum == MBR_EFI_GPT)
          mbrNum++;
    } // for
    // Now go through and set sizes for MBR_EFI_GPT partitions....
    notes->Rewind();
    mbrNum = 0;
    while (notes->GetNextInfo(&convInfo) >= 0) {
-      if ((convInfo.gptPartNum >= 0) && (convInfo.type == PRIMARY))
+      if ((convInfo.origPartNum >= 0) && (convInfo.type == PRIMARY))
          mbrNum++;
-      if (convInfo.gptPartNum == MBR_EFI_GPT) {
+      if (convInfo.origPartNum == MBR_EFI_GPT) {
          if (protectiveMBR.FindFirstAvailable() == UINT32_C(1)) {
             protectiveMBR.MakePart(mbrNum, 1, protectiveMBR.FindLastInFree(1), convInfo.hexCode);
             protectiveMBR.SetHybrid();
@@ -1803,11 +1863,22 @@ int GPTData::ClearGPTData(void) {
 } // GPTData::ClearGPTData()
 
 // Set the location of the second GPT header data to the end of the disk.
+// If the disk size has actually changed, this also adjusts the protective
+// entry in the MBR, since it's probably no longer correct.
 // Used internally and called by the 'e' option on the recovery &
 // transformation menu, to help users of RAID arrays who add disk space
-// to their arrays.
+// to their arrays or to adjust data structures in restore operations
+// involving unequal-sized disks.
 void GPTData::MoveSecondHeaderToEnd() {
    mainHeader.backupLBA = secondHeader.currentLBA = diskSize - UINT64_C(1);
+   if (mainHeader.lastUsableLBA != diskSize - mainHeader.firstUsableLBA) {
+      if (protectiveMBR.GetValidity() == hybrid) {
+         protectiveMBR.OptimizeEESize();
+         RecomputeCHS();
+      } // if
+      if (protectiveMBR.GetValidity() == gpt)
+         MakeProtectiveMBR();
+   } // if
    mainHeader.lastUsableLBA = secondHeader.lastUsableLBA = diskSize - mainHeader.firstUsableLBA;
    secondHeader.partitionEntriesLBA = secondHeader.lastUsableLBA + UINT64_C(1);
 } // GPTData::FixSecondHeaderLocation()
diff --git a/gpt.h b/gpt.h
index 9d137509960c5dc0e006e7aa9a048ca831ab892c..3e0e20631ee576c574cddd5088a8b80b529f570c 100644
--- a/gpt.h
+++ b/gpt.h
@@ -1,7 +1,7 @@
 /* gpt.h -- GPT and data structure definitions, types, and
    functions */
 
-/* This program is copyright (c) 2009, 2010 by Roderick W. Smith. It is distributed
+/* 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>
@@ -11,12 +11,12 @@
 #include "mbr.h"
 #include "bsd.h"
 #include "gptpart.h"
-#include "partnotes.h"
+#include "gptpartnotes.h"
 
 #ifndef __GPTSTRUCTS
 #define __GPTSTRUCTS
 
-#define GPTFDISK_VERSION "0.6.14"
+#define GPTFDISK_VERSION "0.6.15-pre1"
 
 // Constants used by GPTData::PartsToMBR(). MBR_EMPTY must be the lowest-
 // numbered value to refer to partition numbers. (Most will be 0 or positive,
@@ -29,9 +29,9 @@
 #define MAX_ALIGNMENT 65536
 #define MIN_AF_ALIGNMENT 8
 
-// Below constant corresponds to a ~596GiB (640MB) disk, since WD has
-// introduced a smaller Advanced Format drive
-#define SMALLEST_ADVANCED_FORMAT UINT64_C(1250263728)
+// Below constant corresponds to a ~279GiB (300GB) disk, since the
+// smallest Advanced Format drive I know of is 320GB in size
+#define SMALLEST_ADVANCED_FORMAT UINT64_C(585937500)
 
 using namespace std;
 
@@ -103,6 +103,7 @@ public:
    GPTData(void);
    GPTData(string deviceFilename);
    virtual ~GPTData(void);
+   GPTData & operator=(const GPTData & orig);
 
    // Verify (or update) data integrity
    int Verify(void);
@@ -118,6 +119,7 @@ public:
    int FindInsanePartitions(void);
 
    // Load or save data from/to disk
+   int SetFile(const string & deviceFilename);
    int LoadMBR(const string & f) {return protectiveMBR.ReadMBRData(f);}
    int WriteProtectiveMBR(void) {return protectiveMBR.WriteMBRData(&myDisk);}
    void PartitionScan(void);
@@ -125,7 +127,7 @@ public:
    int ForceLoadGPTData(void);
    int LoadMainTable(void);
    int LoadSecondTableAsMain(void);
-   int SaveGPTData(int quiet = 0, string filename = "");
+   int SaveGPTData(int quiet = 0);
    int SaveGPTBackup(const string & filename);
    int LoadGPTBackup(const string & filename);
    int SaveMBR(void);
diff --git a/gptpart.cc b/gptpart.cc
index 2af5db72aa3834c3f0d9f9e84aa050c7e8524981..63e453d1db6f933a0fe43d6883ae7d0140315d2c 100644
--- a/gptpart.cc
+++ b/gptpart.cc
@@ -24,16 +24,12 @@
 using namespace std;
 
 GPTPart::GPTPart(void) {
-   int i;
-
    partitionType.Zero();
    uniqueGUID.Zero();
    firstLBA = 0;
    lastLBA = 0;
    attributes = 0;
-
-   for (i = 0; i < NAME_SIZE; i++)
-      name[i] = '\0';
+   memset(name, 0, NAME_SIZE);
 } // Default constructor
 
 GPTPart::~GPTPart(void) {
@@ -94,35 +90,32 @@ void GPTPart::SetType(PartType t) {
 // string. This function creates a simple-minded copy for this.
 void GPTPart::SetName(const string & theName) {
    char newName[NAME_SIZE];
-   char *junk;
-   int i;
+   size_t i;
 
-   // Blank out new name string, just to be on the safe side....
-   for (i = 0; i < NAME_SIZE; i++)
-      newName[i] = '\0';
+   // Blank out new name string, so that it will terminate in a null
+   // when data are copied to it....
+   memset(newName, 0, NAME_SIZE);
 
    if (theName == "") { // No name specified, so get one from the user
       cout << "Enter name: ";
-      junk = fgets(newName, NAME_SIZE / 2, stdin);
+      if (!fgets(newName, NAME_SIZE / 2 + 1, stdin)) {
+         cerr << "Critical error! Failed fgets() in GPTPart::SetName()!\n";
+         exit(1);
+      }
 
       // Input is likely to include a newline, so remove it....
-      i = (int) strlen(newName);
-      if ((i > 0) && (i <= NAME_SIZE))
-         if (newName[i - 1] == '\n')
-            newName[i - 1] = '\0';
+      i = strlen(newName);
+      if (i && newName[i - 1] == '\n')
+         newName[i - 1] = '\0';
    } else {
       strcpy(newName, theName.substr(0, NAME_SIZE / 2).c_str());
    } // if
 
    // Copy the C-style ASCII string from newName into a form that the GPT
    // table will accept....
-   for (i = 0; i < NAME_SIZE; i++) {
-      if ((i % 2) == 0) {
-         name[i] = newName[(i / 2)];
-      } else {
-         name[i] = '\0';
-      } // if/else
-   } // for
+   memset(name, 0, NAME_SIZE);
+   for (i = 0; i < NAME_SIZE / 2; i++)
+      name[i * 2] = newName[i];
 } // GPTPart::SetName()
 
 // Set the name for the partition based on the current GUID partition type
@@ -132,22 +125,19 @@ void GPTPart::SetDefaultDescription(void) {
 } // GPTPart::SetDefaultDescription()
 
 GPTPart & GPTPart::operator=(const GPTPart & orig) {
-   int i;
-
    partitionType = orig.partitionType;
    uniqueGUID = orig.uniqueGUID;
    firstLBA = orig.firstLBA;
    lastLBA = orig.lastLBA;
    attributes = orig.attributes;
-   for (i = 0; i < NAME_SIZE; i++)
-      name[i] = orig.name[i];
+   memcpy(name, orig.name, NAME_SIZE);
    return *this;
 } // assignment operator
 
 // Display summary information; does nothing if the partition is empty.
 void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
    string sizeInSI;
-   int i;
+   size_t i;
 
    if (firstLBA != 0) {
       sizeInSI = BytesToSI(lastLBA - firstLBA + 1, blockSize);
@@ -159,7 +149,7 @@ void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
       cout.width(14);
       cout << lastLBA  << "   ";
       cout << BytesToSI(lastLBA - firstLBA + 1, blockSize) << "  ";
-      for (i = 0; i < 10 - (int) sizeInSI.length(); i++)
+      for (i = 0; i < 10 - sizeInSI.length(); i++)
          cout << " ";
       cout.fill('0');
       cout.width(4);
@@ -201,30 +191,21 @@ void GPTPart::ShowDetails(uint32_t blockSize) {
 
 // Blank (delete) a single partition
 void GPTPart::BlankPartition(void) {
-   int j;
-
    uniqueGUID.Zero();
    partitionType.Zero();
    firstLBA = 0;
    lastLBA = 0;
    attributes = 0;
-   for (j = 0; j < NAME_SIZE; j++)
-      name[j] = '\0';
+   memset(name, 0, NAME_SIZE);
 } // GPTPart::BlankPartition
 
 // Returns 1 if the two partitions overlap, 0 if they don't
 int GPTPart::DoTheyOverlap(const GPTPart & other) {
-   int theyDo = 0;
-
    // Don't bother checking unless these are defined (both start and end points
    // are 0 for undefined partitions, so just check the start points)
-   if ((firstLBA != 0) && (other.firstLBA != 0)) {
-      if ((firstLBA < other.lastLBA) && (lastLBA >= other.firstLBA))
-         theyDo = 1;
-      if ((other.firstLBA < lastLBA) && (other.lastLBA >= firstLBA))
-         theyDo = 1;
-   } // if
-   return (theyDo);
+//   cout << "Entering GPTPart::DoTheyOverlap()\n";
+   return firstLBA && other.firstLBA &&
+          (firstLBA <= other.lastLBA) != (lastLBA < other.firstLBA);
 } // GPTPart::DoTheyOverlap()
 
 // Reverse the bytes of integral data types; used on big-endian systems.
@@ -242,17 +223,18 @@ void GPTPart::ReversePartBytes(void) {
 // name is the generic one for the partition type.
 void GPTPart::ChangeType(void) {
    char line[255];
-   char* junk;
-   unsigned int changeName = 0;
+   int changeName;
    PartType tempType = (GUIDData) "00000000-0000-0000-0000-000000000000";
 
-   if (GetDescription() == GetTypeName())
-      changeName = UINT16_C(1);
+   changeName = (GetDescription() == GetTypeName());
 
    cout << "Current type is '" << GetTypeName() << "'\n";
    do {
       cout << "Hex code or GUID (L to show codes, Enter = 0700): ";
-      junk = fgets(line, 255, stdin);
+      if (!fgets(line, sizeof(line), stdin)) {
+         cerr << "Critical error! Failed fgets() in GPTPart::ChangeType()!\n";
+         exit(1);
+      } // if
       if ((line[0] == 'L') || (line[0] == 'l')) {
          partitionType.ShowAllTypes();
       } else {
diff --git a/gpttext.cc b/gpttext.cc
index 0bc0ae24706213ea792197deb9121317be0ecdb3..91391e2813c8d900b85e8464567784ce1ac2aad9 100644
--- a/gpttext.cc
+++ b/gpttext.cc
@@ -29,7 +29,7 @@
 #include <cstdio>
 #include "attributes.h"
 #include "gpttext.h"
-#include "partnotes.h"
+#include "gptpartnotes.h"
 #include "support.h"
 
 using namespace std;
@@ -353,7 +353,6 @@ void GPTDataTextUI::ShowDetails(void) {
 void GPTDataTextUI::MakeHybrid(void) {
    uint32_t partNums[3];
    char line[255];
-   char* junk;
    int numPartsToCvt, i, j, mbrNum, bootable = 0;
    unsigned int hexCode = 0;
    struct PartInfo *newNote;
@@ -368,7 +367,10 @@ void GPTDataTextUI::MakeHybrid(void) {
    // hybrid MBR....
    cout << "Type from one to three GPT partition numbers, separated by spaces, to be\n"
         << "added to the hybrid MBR, in sequence: ";
-   junk = fgets(line, 255, stdin);
+   if (!fgets(line, 255, stdin)) {
+      cerr << "Critical error! Failed fgets() in GPTDataTextUI::MakeHybrid()!\n";
+      exit(1);
+   } // if
    numPartsToCvt = sscanf(line, "%d %d %d", &partNums[0], &partNums[1], &partNums[2]);
 
    if (numPartsToCvt > 0) {
@@ -378,7 +380,7 @@ void GPTDataTextUI::MakeHybrid(void) {
 
    for (i = 0; i < numPartsToCvt; i++) {
       newNote = new struct PartInfo;
-      j = newNote->gptPartNum = partNums[i] - 1;
+      j = newNote->origPartNum = partNums[i] - 1;
       if (partitions[j].IsUsed()) {
          mbrNum = i + (eeFirst == 'Y');
          cout << "\nCreating entry for GPT partition #" << j + 1
@@ -404,7 +406,7 @@ void GPTDataTextUI::MakeHybrid(void) {
       // If this location (covering the main GPT data structures) is omitted,
       // Linux won't find any partitions on the disk.
       newNote = new struct PartInfo;
-      newNote->gptPartNum = MBR_EFI_GPT;
+      newNote->origPartNum = MBR_EFI_GPT;
       newNote->firstLBA = 1;
       newNote->active = 0;
       newNote->hexCode = 0xEE;
@@ -427,13 +429,16 @@ void GPTDataTextUI::MakeHybrid(void) {
                cout << "Enter an MBR hex code (EE is EFI GPT, but may confuse MacOS): ";
                // Comment on above: Mac OS treats disks with more than one
                // 0xEE MBR partition as MBR disks, not as GPT disks.
-               junk = fgets(line, 255, stdin);
+               if (!fgets(line, 255, stdin)) {
+                  cerr << "Critical error! Failed fgets() in GPTDataTextUI::MakeHybrid()\n";
+                  exit(1);
+               } // if
                sscanf(line, "%x", &hexCode);
                if (line[0] == '\n')
                   hexCode = 0x00;
             } // while
             newNote = new struct PartInfo;
-            newNote->gptPartNum = MBR_EFI_GPT;
+            newNote->origPartNum = MBR_EFI_GPT;
             newNote->active = 0;
             newNote->hexCode = hexCode;
             newNote->type = PRIMARY;
@@ -452,7 +457,7 @@ void GPTDataTextUI::MakeHybrid(void) {
 // possible, but gives the user the option to override this suggestion.
 // Returns the number of partitions assigned (0 if problems or if the
 // user aborts)
-int GPTDataTextUI::AssignPrimaryOrLogical(PartNotes & notes) {
+int GPTDataTextUI::AssignPrimaryOrLogical(GptPartNotes& notes) {
    int i, partNum, allOK = 1, changesWanted = 1, countedParts, numPrimary = 0, numLogical = 0;
    int newNumParts; // size of GPT table
 
@@ -527,7 +532,7 @@ int GPTDataTextUI::AssignPrimaryOrLogical(PartNotes & notes) {
 int GPTDataTextUI::XFormToMBR(void) {
    int numToConvert, numReallyConverted = 0;
    int origNumParts;
-   PartNotes notes;
+   GptPartNotes notes;
    GPTPart *tempGptParts;
    uint32_t i;
 
@@ -576,7 +581,6 @@ int GPTDataTextUI::XFormToMBR(void) {
 // Get an MBR type code from the user and return it
 int GetMBRTypeCode(int defType) {
    char line[255];
-   char* junk;
    int typeCode;
 
    cout.setf(ios::uppercase);
@@ -585,7 +589,10 @@ int GetMBRTypeCode(int defType) {
       cout << "Enter an MBR hex code (default " << hex;
       cout.width(2);
       cout << defType << "): " << dec;
-      junk = fgets(line, 255, stdin);
+      if (!fgets(line, 255, stdin)) {
+         cerr << "Critical error! Failed fgets() in GetMBRTypeCode()\n";
+         exit(1);
+      } // if
       if (line[0] == '\n')
          typeCode = defType;
       else
diff --git a/gpttext.h b/gpttext.h
index 6d91a135a27d31ffa0e78b8b9bef51dbb6a891af..642791bbacf4c5091ee3cb447e27722086b21773 100644
--- a/gpttext.h
+++ b/gpttext.h
@@ -50,7 +50,7 @@ class GPTDataTextUI : public GPTData {
       int DestroyGPTwPrompt(void); // Returns 1 if user proceeds
       void ShowDetails(void);
       void MakeHybrid(void);
-      int AssignPrimaryOrLogical(PartNotes& notes);
+      int AssignPrimaryOrLogical(GptPartNotes& notes);
       int XFormToMBR(void); // convert GPT to MBR, wiping GPT afterwards. Returns 1 if successful
 }; // class GPTDataTextUI
 
diff --git a/guid.cc b/guid.cc
index 7b4b378591081f7e5c459090ca4c99c9fd19c7b5..bfbc7d44d186be32fcdf2c2f48a6422065b403e9 100644
--- a/guid.cc
+++ b/guid.cc
@@ -16,6 +16,7 @@
 
 #include <stdio.h>
 #include <time.h>
+#include <string.h>
 #include <string>
 #include <iostream>
 #include "guid.h"
@@ -29,10 +30,7 @@ GUIDData::GUIDData(void) {
 } // constructor
 
 GUIDData::GUIDData(const GUIDData & orig) {
-   int i;
-
-   for (i = 0; i < 16; i++)
-      uuidData[i] = orig.uuidData[i];
+   memcpy(uuidData, orig.uuidData, sizeof(uuidData));
 } // copy constructor
 
 GUIDData::GUIDData(const char * orig) {
@@ -43,10 +41,7 @@ GUIDData::~GUIDData(void) {
 } // destructor
 
 GUIDData & GUIDData::operator=(const GUIDData & orig) {
-   int i;
-
-   for (i = 0; i < 16; i++)
-      uuidData[i] = orig.uuidData[i];
+   memcpy(uuidData, orig.uuidData, sizeof(uuidData));
    return *this;
 } // GUIDData::operator=(const GUIDData & orig)
 
@@ -123,11 +118,7 @@ GUIDData & GUIDData::operator=(const char * orig) {
 
 // Erase the contents of the GUID
 void GUIDData::Zero(void) {
-   int i;
-
-   for (i = 0; i < 16; i++) {
-      uuidData[i] = 0;
-   } // for
+   memset(uuidData, 0, sizeof(uuidData));
 } // GUIDData::Zero()
 
 // Set a completely random GUID value....
@@ -151,14 +142,7 @@ void GUIDData::Randomize(void) {
 
 // Equality operator; returns 1 if the GUIDs are equal, 0 if they're unequal
 int GUIDData::operator==(const GUIDData & orig) const {
-   int retval = 1; // assume they're equal
-   int i;
-
-   for (i = 0; i < 16; i++)
-      if (uuidData[i] != orig.uuidData[i])
-         retval = 0;
-
-   return retval;
+   return !memcmp(uuidData, orig.uuidData, sizeof(uuidData));
 } // GUIDData::operator==
 
 // Inequality operator; returns 1 if the GUIDs are unequal, 0 if they're equal
diff --git a/guid.h b/guid.h
index 224302cb09a7d49e936d44c178f86d7f35aabc47..d22ec8672f0346d46d9d106b4cc0a2d0879fe314 100644
--- a/guid.h
+++ b/guid.h
@@ -22,7 +22,7 @@
 #ifdef _WIN32
 typedef unsigned char my_uuid_t[16];
 #else
-#include </usr/include/uuid/uuid.h>
+#include <uuid/uuid.h>
 typedef uuid_t my_uuid_t;
 #endif
 
diff --git a/mbr.cc b/mbr.cc
index 1d840cc2747bf33becd5a7378b642ded253b9dcf..415aaf6072b769f0632170f5ace4d4f33c818aaa 100644
--- a/mbr.cc
+++ b/mbr.cc
@@ -19,8 +19,6 @@
 #include <errno.h>
 #include <iostream>
 #include "mbr.h"
-#include "partnotes.h"
-#include "support.h"
 
 using namespace std;
 
@@ -30,548 +28,11 @@ using namespace std;
  *                                      *
  ****************************************/
 
-MBRData::MBRData(void) {
-   blockSize = SECTOR_SIZE;
-   diskSize = 0;
-   device = "";
-   state = invalid;
-   srand((unsigned int) time(NULL));
-   numHeads = MAX_HEADS;
-   numSecspTrack = MAX_SECSPERTRACK;
-   myDisk = NULL;
-   canDeleteMyDisk = 0;
-   EmptyMBR();
-} // MBRData default constructor
-
-MBRData::MBRData(string filename) {
-   blockSize = SECTOR_SIZE;
-   diskSize = 0;
-   device = filename;
-   state = invalid;
-   numHeads = MAX_HEADS;
-   numSecspTrack = MAX_SECSPERTRACK;
-   myDisk = NULL;
-   canDeleteMyDisk = 0;
-
-   srand((unsigned int) time(NULL));
-   // Try to read the specified partition table, but if it fails....
-   if (!ReadMBRData(filename)) {
-      EmptyMBR();
-      device = "";
-   } // if
-} // MBRData(string filename) constructor
-
-// Free space used by myDisk only if that's OK -- sometimes it will be
-// copied from an outside source, in which case that source should handle
-// it!
-MBRData::~MBRData(void) {
-   if (canDeleteMyDisk)
-      delete myDisk;
-} // MBRData destructor
-
-/**********************
- *                    *
- * Disk I/O functions *
- *                    *
- **********************/
-
-// 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 MBRData::ReadMBRData(const string & deviceFilename) {
-   int allOK = 1;
-
-   if (myDisk == NULL) {
-      myDisk = new DiskIO;
-      canDeleteMyDisk = 1;
-   } // if
-   if (myDisk->OpenForRead(deviceFilename)) {
-      allOK = ReadMBRData(myDisk);
-   } else {
-      allOK = 0;
-   } // if
-
-   if (allOK)
-      device = deviceFilename;
-
-   return allOK;
-} // MBRData::ReadMBRData(const string & deviceFilename)
-
-// Read data from MBR. If checkBlockSize == 1 (the default), the block
-// size is checked; otherwise it's set to the default (512 bytes).
-// Note that any extended partition(s) present will be explicitly stored
-// in the partitions[] array, along with their contained partitions; the
-// extended container partition(s) should be ignored by other functions.
-int MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
-   int allOK = 1, i, j, logicalNum;
-   int err = 1;
-   TempMBR tempMBR;
-
-   if ((myDisk != NULL) && (canDeleteMyDisk)) {
-      delete myDisk;
-      canDeleteMyDisk = 0;
-   } // if
-
-   myDisk = theDisk;
-
-   // Empty existing MBR data, including the logical partitions...
-   EmptyMBR(0);
-
-   if (myDisk->Seek(0))
-     if (myDisk->Read(&tempMBR, 512))
-        err = 0;
-   if (err) {
-      cerr << "Problem reading disk in MBRData::ReadMBRData()!\n";
-   } else {
-      for (i = 0; i < 440; i++)
-         code[i] = tempMBR.code[i];
-      diskSignature = tempMBR.diskSignature;
-      nulls = tempMBR.nulls;
-      for (i = 0; i < 4; i++) {
-         partitions[i].status = tempMBR.partitions[i].status;
-         partitions[i].partitionType = tempMBR.partitions[i].partitionType;
-         partitions[i].firstLBA = tempMBR.partitions[i].firstLBA;
-         partitions[i].lengthLBA = tempMBR.partitions[i].lengthLBA;
-         for (j = 0; j < 3; j++) {
-            partitions[i].firstSector[j] = tempMBR.partitions[i].firstSector[j];
-            partitions[i].lastSector[j] = tempMBR.partitions[i].lastSector[j];
-         } // for j... (reading parts of CHS geometry)
-      } // for i... (reading all four partitions)
-      MBRSignature = tempMBR.MBRSignature;
-
-      // Reverse the byte order, if necessary
-      if (IsLittleEndian() == 0) {
-         ReverseBytes(&diskSignature, 4);
-         ReverseBytes(&nulls, 2);
-         ReverseBytes(&MBRSignature, 2);
-         for (i = 0; i < 4; i++) {
-            ReverseBytes(&partitions[i].firstLBA, 4);
-            ReverseBytes(&partitions[i].lengthLBA, 4);
-         } // for
-      } // if
-
-      if (MBRSignature != MBR_SIGNATURE) {
-         allOK = 0;
-         state = invalid;
-      } // if
-
-      // Find disk size
-      diskSize = myDisk->DiskSize(&err);
-
-      // Find block size
-      if (checkBlockSize) {
-         blockSize = myDisk->GetBlockSize();
-      } // if (checkBlockSize)
-
-      // Load logical partition data, if any is found....
-      if (allOK) {
-         for (i = 0; i < 4; i++) {
-            if ((partitions[i].partitionType == 0x05) || (partitions[i].partitionType == 0x0f)
-               || (partitions[i].partitionType == 0x85)) {
-               // Found it, so call a recursive algorithm to load everything from them....
-               logicalNum = ReadLogicalPart(partitions[i].firstLBA, UINT32_C(0), 4);
-               if ((logicalNum < 0) || (logicalNum >= MAX_MBR_PARTS)) {
-                  allOK = 0;
-                  cerr << "Error reading logical partitions! List may be truncated!\n";
-               } // if maxLogicals valid
-            } // if primary partition is extended
-         } // for primary partition loop
-         if (allOK) { // Loaded logicals OK
-            state = mbr;
-         } else {
-            state = invalid;
-         } // if
-      } // if
-
-      // Check to see if it's in GPT format....
-      if (allOK) {
-         for (i = 0; i < 4; i++) {
-            if (partitions[i].partitionType == UINT8_C(0xEE)) {
-               state = gpt;
-            } // if
-         } // for
-      } // if
-
-      // If there's an EFI GPT partition, look for other partition types,
-      // to flag as hybrid
-      if (state == gpt) {
-         for (i = 0 ; i < 4; i++) {
-            if ((partitions[i].partitionType != UINT8_C(0xEE)) &&
-               (partitions[i].partitionType != UINT8_C(0x00)))
-               state = hybrid;
-         } // for
-      } // if (hybrid detection code)
-   } // no initial error
-   return allOK;
-} // MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize)
-
-// This is a recursive function to read all the logical partitions, following the
-// logical partition linked list from the disk and storing the basic data in the
-// partitions[] array. Returns last index to partitions[] used, or -1 if there was
-// a problem.
-// Parameters:
-// extendedStart = LBA of the start of the extended partition
-// diskOffset = LBA offset WITHIN the extended partition of the one to be read
-// partNum = location in partitions[] array to store retrieved data
-int MBRData::ReadLogicalPart(uint32_t extendedStart, uint32_t diskOffset, int partNum) {
-   struct TempMBR ebr;
-   uint64_t offset;
-
-   // Check for a valid partition number. Note that partitions MAY be read into
-   // the area normally used by primary partitions, although the only calling
-   // function as of GPT fdisk version 0.5.0 doesn't do so.
-   if ((partNum < MAX_MBR_PARTS) && (partNum >= 0)) {
-      offset = (uint64_t) (extendedStart + diskOffset);
-      if (myDisk->Seek(offset) == 0) { // seek to EBR record
-         cerr << "Unable to seek to " << offset << "! Aborting!\n";
-         partNum = -1;
-      }
-      if (myDisk->Read(&ebr, 512) != 512) { // Load the data....
-         cerr << "Error seeking to or reading logical partition data from " << offset
-              << "!\nAborting!\n";
-         partNum = -1;
-      } else if (IsLittleEndian() != 1) { // Reverse byte ordering of some data....
-         ReverseBytes(&ebr.MBRSignature, 2);
-         ReverseBytes(&ebr.partitions[0].firstLBA, 4);
-         ReverseBytes(&ebr.partitions[0].lengthLBA, 4);
-         ReverseBytes(&ebr.partitions[1].firstLBA, 4);
-         ReverseBytes(&ebr.partitions[1].lengthLBA, 4);
-      } // if/else/if
-
-      if (ebr.MBRSignature != MBR_SIGNATURE) {
-         partNum = -1;
-         cerr << "MBR signature in logical partition invalid; read 0x";
-         cerr.fill('0');
-         cerr.width(4);
-         cerr.setf(ios::uppercase);
-         cerr << hex << ebr.MBRSignature << ", but should be 0x";
-         cerr.width(4);
-         cerr << MBR_SIGNATURE << dec << "\n";
-         cerr.fill(' ');
-      } // if
-
-      // Copy over the basic data....
-      partitions[partNum].status = ebr.partitions[0].status;
-      partitions[partNum].firstLBA = ebr.partitions[0].firstLBA + diskOffset + extendedStart;
-      partitions[partNum].lengthLBA = ebr.partitions[0].lengthLBA;
-      partitions[partNum].partitionType = ebr.partitions[0].partitionType;
-
-      // Find the next partition (if there is one) and recurse....
-      if ((ebr.partitions[1].firstLBA != UINT32_C(0)) && (partNum >= 4) &&
-          (partNum < (MAX_MBR_PARTS - 1))) {
-         partNum = ReadLogicalPart(extendedStart, ebr.partitions[1].firstLBA,
-                                   partNum + 1);
-      } else {
-         partNum++;
-      } // if another partition
-   } // Not enough space for all the logicals (or previous error encountered)
-   return (partNum);
-} // MBRData::ReadLogicalPart()
-
-// Write the MBR data to the default defined device. This writes both the
-// MBR itself and any defined logical partitions, provided there's an
-// MBR extended partition.
-int MBRData::WriteMBRData(void) {
-   int allOK = 1;
-
-   if (myDisk != NULL) {
-      if (myDisk->OpenForWrite() != 0) {
-         allOK = WriteMBRData(myDisk);
-      } else {
-         allOK = 0;
-      } // if/else
-      myDisk->Close();
-   } else allOK = 0;
-   return allOK;
-} // MBRData::WriteMBRData(void)
-
-// Save the MBR data to a file. This writes both the
-// MBR itself and any defined logical partitions, provided there's an
-// MBR extended partition.
-int MBRData::WriteMBRData(DiskIO *theDisk) {
-   int i, j, partNum, allOK, moreLogicals = 0;
-   uint32_t extFirstLBA = 0;
-   uint64_t writeEbrTo; // 64-bit because we support extended in 2-4TiB range
-   TempMBR tempMBR;
-
-   // First write the main MBR data structure....
-   for (i = 0; i < 440; i++)
-      tempMBR.code[i] = code[i];
-   tempMBR.diskSignature = diskSignature;
-   tempMBR.nulls = nulls;
-   tempMBR.MBRSignature = MBRSignature;
-   for (i = 0; i < 4; i++) {
-      tempMBR.partitions[i].status = partitions[i].status;
-      tempMBR.partitions[i].partitionType = partitions[i].partitionType;
-      tempMBR.partitions[i].firstLBA = partitions[i].firstLBA;
-      tempMBR.partitions[i].lengthLBA = partitions[i].lengthLBA;
-      for (j = 0; j < 3; j++) {
-         tempMBR.partitions[i].firstSector[j] = partitions[i].firstSector[j];
-         tempMBR.partitions[i].lastSector[j] = partitions[i].lastSector[j];
-      } // for j...
-      if (partitions[i].partitionType == 0x0f) {
-         extFirstLBA = partitions[i].firstLBA;
-         moreLogicals = 1;
-      } // if
-   } // for i...
-   allOK = WriteMBRData(tempMBR, theDisk, 0);
-
-   // Set up tempMBR with some constant data for logical partitions...
-   tempMBR.diskSignature = 0;
-   for (i = 2; i < 4; i++) {
-      tempMBR.partitions[i].firstLBA = tempMBR.partitions[i].lengthLBA = 0;
-      tempMBR.partitions[i].partitionType = 0x00;
-      for (j = 0; j < 3; j++) {
-         tempMBR.partitions[i].firstSector[j] = 0;
-         tempMBR.partitions[i].lastSector[j] = 0;
-      } // for j
-   } // for i
-
-   partNum = 4;
-   writeEbrTo = (uint64_t) extFirstLBA;
-   // If extended partition is present, write logicals...
-   while (allOK && moreLogicals && (partNum < MAX_MBR_PARTS)) {
-      tempMBR.partitions[0] = partitions[partNum];
-      tempMBR.partitions[0].firstLBA = 1; // partition starts on sector after EBR
-      // tempMBR.partitions[1] points to next EBR or terminates EBR linked list...
-      if ((partNum < MAX_MBR_PARTS - 1) && (partitions[partNum + 1].firstLBA > 0)) {
-         tempMBR.partitions[1].partitionType = 0x0f;
-         tempMBR.partitions[1].firstLBA = partitions[partNum + 1].firstLBA - 1;
-         tempMBR.partitions[1].lengthLBA = partitions[partNum + 1].lengthLBA + 1;
-         LBAtoCHS((uint64_t) tempMBR.partitions[1].firstLBA,
-                  (uint8_t *) &tempMBR.partitions[1].firstSector);
-         LBAtoCHS(tempMBR.partitions[1].lengthLBA - extFirstLBA,
-                  (uint8_t *) &tempMBR.partitions[1].lastSector);
-      } else {
-         tempMBR.partitions[1].partitionType = 0x00;
-         tempMBR.partitions[1].firstLBA = 0;
-         tempMBR.partitions[1].lengthLBA = 0;
-         moreLogicals = 0;
-      } // if/else
-      allOK = WriteMBRData(tempMBR, theDisk, writeEbrTo);
-      partNum++;
-      writeEbrTo = (uint64_t) tempMBR.partitions[1].firstLBA + (uint64_t) extFirstLBA;
-   } // while
-   return allOK;
-} // MBRData::WriteMBRData(DiskIO *theDisk)
-
-int MBRData::WriteMBRData(const string & deviceFilename) {
-   device = deviceFilename;
-   return WriteMBRData();
-} // MBRData::WriteMBRData(const string & deviceFilename)
-
-// Write a single MBR record to the specified sector. Used by the like-named
-// function to write both the MBR and multiple EBR (for logical partition)
-// records.
-// Returns 1 on success, 0 on failure
-int MBRData::WriteMBRData(struct TempMBR & mbr, DiskIO *theDisk, uint64_t sector) {
-   int i, allOK;
-
-   // Reverse the byte order, if necessary
-   if (IsLittleEndian() == 0) {
-      ReverseBytes(&mbr.diskSignature, 4);
-      ReverseBytes(&mbr.nulls, 2);
-      ReverseBytes(&mbr.MBRSignature, 2);
-      for (i = 0; i < 4; i++) {
-         ReverseBytes(&mbr.partitions[i].firstLBA, 4);
-         ReverseBytes(&mbr.partitions[i].lengthLBA, 4);
-      } // for
-   } // if
-
-   // Now write the data structure...
-   allOK = theDisk->OpenForWrite();
-   if (allOK && theDisk->Seek(sector)) {
-      if (theDisk->Write(&mbr, 512) != 512) {
-         allOK = 0;
-         cerr << "Error " << errno << " when saving MBR!\n";
-      } // if
-   } else {
-      allOK = 0;
-      cerr << "Error " << errno << " when seeking to MBR to write it!\n";
-   } // if/else
-   theDisk->Close();
-
-   // Reverse the byte order back, if necessary
-   if (IsLittleEndian() == 0) {
-      ReverseBytes(&mbr.diskSignature, 4);
-      ReverseBytes(&mbr.nulls, 2);
-      ReverseBytes(&mbr.MBRSignature, 2);
-      for (i = 0; i < 4; i++) {
-         ReverseBytes(&mbr.partitions[i].firstLBA, 4);
-         ReverseBytes(&mbr.partitions[i].lengthLBA, 4);
-      } // for
-   }// if
-   return allOK;
-} // MBRData::WriteMBRData(uint64_t sector)
-
-/********************************************
- *                                          *
- * Functions that display data for the user *
- *                                          *
- ********************************************/
-
-// Show the MBR data to the user, up to the specified maximum number
-// of partitions....
-void MBRData::DisplayMBRData(int maxParts) {
-   int i;
-   char bootCode;
-
-   if (maxParts > MAX_MBR_PARTS)
-      maxParts = MAX_MBR_PARTS;
-   cout << "MBR disk identifier: 0x";
-   cout.width(8);
-   cout.fill('0');
-   cout.setf(ios::uppercase);
-   cout << hex << diskSignature << dec << "\n";
-   cout << "MBR partitions:\n";
-   cout << "Number\t Boot\t Start (sector)\t Length (sectors)\tType\n";
-   for (i = 0; i < maxParts; i++) {
-      if (partitions[i].lengthLBA != 0) {
-         if (partitions[i].status && 0x80) // it's bootable
-            bootCode = '*';
-         else
-            bootCode = ' ';
-         cout.fill(' ');
-         cout.width(4);
-         cout << i + 1 << "\t   " << bootCode << "\t";
-         cout.width(13);
-         cout << partitions[i].firstLBA << "\t";
-         cout.width(15);
-         cout << partitions[i].lengthLBA << " \t0x";
-         cout.width(2);
-         cout.fill('0');
-         cout << hex << (int) partitions[i].partitionType << dec << "\n";
-      } // if
-      cout.fill(' ');
-   } // for
-   cout << "\nDisk size is " << diskSize << " sectors ("
-        << BytesToSI(diskSize, blockSize) << ")\n";
-} // MBRData::DisplayMBRData()
-
-// Displays the state, as a word, on stdout. Used for debugging & to
-// tell the user about the MBR state when the program launches....
-void MBRData::ShowState(void) {
-   switch (state) {
-      case invalid:
-         cout << "  MBR: not present\n";
-         break;
-      case gpt:
-         cout << "  MBR: protective\n";
-         break;
-      case hybrid:
-         cout << "  MBR: hybrid\n";
-         break;
-      case mbr:
-         cout << "  MBR: MBR only\n";
-         break;
-      default:
-         cout << "\a  MBR: unknown -- bug!\n";
-         break;
-   } // switch
-} // MBRData::ShowState()
-
-/*********************************************************************
- *                                                                   *
- * Functions that set or get disk metadata (CHS geometry, disk size, *
- * etc.)                                                             *
- *                                                                   *
- *********************************************************************/
-
-// Sets the CHS geometry. CHS geometry is used by LBAtoCHS() function.
-// Note that this only sets the heads and sectors; the number of
-// cylinders is determined by these values and the disk size.
-void MBRData::SetCHSGeom(uint32_t h, uint32_t s) {
-   if ((h <= MAX_HEADS) && (s <= MAX_SECSPERTRACK)) {
-      numHeads = h;
-      numSecspTrack = s;
-   } else {
-      cout << "Warning! Attempt to set invalid CHS geometry!\n";
-   } // if/else
-} // MBRData::SetCHSGeom()
-
-// Converts 64-bit LBA value to MBR-style CHS value. Returns 1 if conversion
-// was within the range that can be expressed by CHS (including 0, for an
-// empty partition), 0 if the value is outside that range, and -1 if chs is
-// invalid.
-int MBRData::LBAtoCHS(uint64_t lba, uint8_t * chs) {
-   uint64_t cylinder, head, sector; // all numbered from 0
-   uint64_t remainder;
-   int retval = 1;
-   int done = 0;
-
-   if (chs != NULL) {
-      // Special case: In case of 0 LBA value, zero out CHS values....
-      if (lba == 0) {
-         chs[0] = chs[1] = chs[2] = UINT8_C(0);
-         done = 1;
-      } // if
-      // If LBA value is too large for CHS, max out CHS values....
-      if ((!done) && (lba >= (numHeads * numSecspTrack * MAX_CYLINDERS))) {
-         chs[0] = 254;
-         chs[1] = chs[2] = 255;
-         done = 1;
-         retval = 0;
-      } // if
-      // If neither of the above applies, compute CHS values....
-      if (!done) {
-         cylinder = lba / (uint64_t) (numHeads * numSecspTrack);
-         remainder = lba - (cylinder * numHeads * numSecspTrack);
-         head = remainder / numSecspTrack;
-         remainder -= head * numSecspTrack;
-         sector = remainder;
-         if (head < numHeads)
-            chs[0] = (uint8_t) head;
-         else
-            retval = 0;
-         if (sector < numSecspTrack) {
-            chs[1] = (uint8_t) ((sector + 1) + (cylinder >> 8) * 64);
-            chs[2] = (uint8_t) (cylinder & UINT64_C(0xFF));
-         } else {
-            retval = 0;
-         } // if/else
-      } // if value is expressible and non-0
-   } else { // Invalid (NULL) chs pointer
-      retval = -1;
-   } // if CHS pointer valid
-   return (retval);
-} // MBRData::LBAtoCHS()
-
-// Look for problems -- overlapping partitions, etc.
-int MBRData::Verify(void) {
-   int i, j, theyOverlap, numProbs = 0, numEE = 0;
-   uint32_t firstLBA1, firstLBA2, lastLBA1, lastLBA2;
-
-   for (i = 0; i < MAX_MBR_PARTS; i++) {
-      for (j = i + 1; j < MAX_MBR_PARTS; j++) {
-         theyOverlap = 0;
-         firstLBA1 = partitions[i].firstLBA;
-         firstLBA2 = partitions[j].firstLBA;
-         if ((firstLBA1 != 0) && (firstLBA2 != 0)) {
-            lastLBA1 = partitions[i].firstLBA + partitions[i].lengthLBA - 1;
-            lastLBA2 = partitions[j].firstLBA + partitions[j].lengthLBA - 1;
-            if ((firstLBA1 < lastLBA2) && (lastLBA1 >= firstLBA2))
-               theyOverlap = 1;
-            if ((firstLBA2 < lastLBA1) && (lastLBA2 >= firstLBA1))
-               theyOverlap = 1;
-         } // if
-         if (theyOverlap) {
-            numProbs++;
-            cout << "\nProblem: MBR partitions " << i + 1 << " and " << j + 1
-                 << " overlap!\n";
-         } // if
-      } // for (j...)
-      if (partitions[i].partitionType == 0xEE) {
-         numEE++;
-         if (partitions[i].firstLBA != 1)
-            cout << "\nWarning: 0xEE partition doesn't start on sector 1. This can cause problems\n"
-                 << "in some OSes.\n";
-      } // if
-   } // for (i...)
-   if (numEE > 1)
-      cout << "\nCaution: More than one 0xEE MBR partition found. This can cause problems\n"
-           << "in some OSes.\n";
-
-   return numProbs;
-} // MBRData::Verify()
+// Assignment operator -- copy entire set of MBR data.
+MBRData & MBRData::operator=(const MBRData & orig) {
+   BasicMBRData::operator=(orig);
+   return *this;
+} // MBRData::operator=() */
 
 /*****************************************************
  *                                                   *
@@ -579,45 +40,6 @@ int MBRData::Verify(void) {
  *                                                   *
  *****************************************************/
 
-// Empty all data. Meant mainly for calling by constructors, but it's also
-// used by the hybrid MBR functions in the GPTData class.
-void MBRData::EmptyMBR(int clearBootloader) {
-   int i;
-
-   // Zero out the boot loader section, the disk signature, and the
-   // 2-byte nulls area only if requested to do so. (This is the
-   // default.)
-   if (clearBootloader == 1) {
-      EmptyBootloader();
-   } // if
-
-   // Blank out the partitions
-   for (i = 0; i < MAX_MBR_PARTS; i++) {
-      partitions[i].status = UINT8_C(0);
-      partitions[i].firstSector[0] = UINT8_C(0);
-      partitions[i].firstSector[1] = UINT8_C(0);
-      partitions[i].firstSector[2] = UINT8_C(0);
-      partitions[i].partitionType = UINT8_C(0);
-      partitions[i].lastSector[0] = UINT8_C(0);
-      partitions[i].lastSector[1] = UINT8_C(0);
-      partitions[i].lastSector[2] = UINT8_C(0);
-      partitions[i].firstLBA = UINT32_C(0);
-      partitions[i].lengthLBA = UINT32_C(0);
-   } // for
-   MBRSignature = MBR_SIGNATURE;
-} // MBRData::EmptyMBR()
-
-// Blank out the boot loader area. Done with the initial MBR-to-GPT
-// conversion, since MBR boot loaders don't understand GPT, and so
-// need to be replaced....
-void MBRData::EmptyBootloader(void) {
-   int i;
-
-   for (i = 0; i < 440; i++)
-      code[i] = 0;
-   nulls = 0;
-} // MBRData::EmptyBootloader
-
 // Create a protective MBR. Clears the boot loader area if clearBoot > 0.
 void MBRData::MakeProtectiveMBR(int clearBoot) {
 
@@ -651,134 +73,6 @@ void MBRData::MakeProtectiveMBR(int clearBoot) {
    state = gpt;
 } // MBRData::MakeProtectiveMBR()
 
-// Create a partition of the specified number, starting LBA, and
-// length. This function does *NO* error checking, so it's possible
-// to seriously screw up a partition table using this function!
-// Note: This function should NOT be used to create the 0xEE partition
-// in a conventional GPT configuration, since that partition has
-// specific size requirements that this function won't handle. It may
-// be used for creating the 0xEE partition(s) in a hybrid MBR, though,
-// since those toss the rulebook away anyhow....
-void MBRData::MakePart(int num, uint32_t start, uint32_t length, int type, int bootable) {
-   if ((num >= 0) && (num < MAX_MBR_PARTS)) {
-      partitions[num].firstSector[0] = UINT8_C(0);
-      partitions[num].firstSector[1] = UINT8_C(0);
-      partitions[num].firstSector[2] = UINT8_C(0);
-      partitions[num].partitionType = (uint8_t) type;
-      partitions[num].lastSector[0] = UINT8_C(0);
-      partitions[num].lastSector[1] = UINT8_C(0);
-      partitions[num].lastSector[2] = UINT8_C(0);
-      partitions[num].firstLBA = start;
-      partitions[num].lengthLBA = length;
-      // If this is a "real" partition, set its CHS geometry
-      if (length > 0) {
-         LBAtoCHS((uint64_t) start, partitions[num].firstSector);
-         LBAtoCHS((uint64_t) (start + length - 1), partitions[num].lastSector);
-      } // if (length > 0)
-      SetPartBootable(num, bootable);
-   } // if valid partition number
-} // MBRData::MakePart()
-
-// Set the partition's type code.
-// Returns 1 if successful, 0 if not (invalid partition number)
-int MBRData::SetPartType(int num, int type) {
-   int allOK = 1;
-
-   if ((num >= 0) && (num < MAX_MBR_PARTS)) {
-      if (partitions[num].lengthLBA != UINT32_C(0)) {
-         partitions[num].partitionType = (uint8_t) type;
-      } else allOK = 0;
-   } else allOK = 0;
-   return allOK;
-} // MBRData::SetPartType()
-
-// Set (or remove) the partition's bootable flag. Setting it is the
-// default; pass 0 as bootable to remove the flag.
-// Returns 1 if successful, 0 if not (invalid partition number)
-int MBRData::SetPartBootable(int num, int bootable) {
-   int allOK = 1;
-
-   if ((num >= 0) && (num < MAX_MBR_PARTS)) {
-      if (partitions[num].lengthLBA != UINT32_C(0)) {
-         if (bootable == 0)
-            partitions[num].status = UINT8_C(0);
-         else
-            partitions[num].status = UINT8_C(0x80);
-      } else allOK = 0;
-   } else allOK = 0;
-   return allOK;
-} // MBRData::SetPartBootable()
-
-// Create a partition that fills the most available space. Returns
-// 1 if partition was created, 0 otherwise. Intended for use in
-// creating hybrid MBRs.
-int MBRData::MakeBiggestPart(int i, int type) {
-   uint32_t start = UINT32_C(1); // starting point for each search
-   uint32_t firstBlock; // first block in a segment
-   uint32_t lastBlock; // last block in a segment
-   uint32_t segmentSize; // size of segment in blocks
-   uint32_t selectedSegment = UINT32_C(0); // location of largest segment
-   uint32_t selectedSize = UINT32_C(0); // size of largest segment in blocks
-   int found = 0;
-
-   do {
-      firstBlock = FindFirstAvailable(start);
-      if (firstBlock != UINT32_C(0)) { // something's free...
-         lastBlock = FindLastInFree(firstBlock);
-         segmentSize = lastBlock - firstBlock + UINT32_C(1);
-         if (segmentSize > selectedSize) {
-            selectedSize = segmentSize;
-            selectedSegment = firstBlock;
-         } // if
-         start = lastBlock + 1;
-      } // if
-   } while (firstBlock != 0);
-   if ((selectedSize > UINT32_C(0)) && ((uint64_t) selectedSize < diskSize)) {
-      found = 1;
-      MakePart(i, selectedSegment, selectedSize, type, 0);
-   } else {
-      found = 0;
-   } // if/else
-   return found;
-} // MBRData::MakeBiggestPart(int i)
-
-// Delete partition #i
-void MBRData::DeletePartition(int i) {
-   int j;
-
-   partitions[i].firstLBA = UINT32_C(0);
-   partitions[i].lengthLBA = UINT32_C(0);
-   partitions[i].status = UINT8_C(0);
-   partitions[i].partitionType = UINT8_C(0);
-   for (j = 0; j < 3; j++) {
-      partitions[i].firstSector[j] = UINT8_C(0);
-      partitions[i].lastSector[j] = UINT8_C(0);
-   } // for j (CHS data blanking)
-} // MBRData::DeletePartition()
-
-// Delete a partition if one exists at the specified location.
-// Returns 1 if a partition was deleted, 0 otherwise....
-// Used to help keep GPT & hybrid MBR partitions in sync....
-int MBRData::DeleteByLocation(uint64_t start64, uint64_t length64) {
-   uint32_t start32, length32;
-   int i, deleted = 0;
-
-   if ((start64 < UINT32_MAX) && (length64 < UINT32_MAX)) {
-      start32 = (uint32_t) start64;
-      length32 = (uint32_t) length64;
-      for (i = 0; i < MAX_MBR_PARTS; i++) {
-         if ((partitions[i].firstLBA == start32) && (partitions[i].lengthLBA == length32) &&
-             (partitions[i].partitionType != 0xEE)) {
-            DeletePartition(i);
-            if (state == hybrid)
-               OptimizeEESize();
-            deleted = 1;
-         } // if (match found)
-      } // for i (partition scan)
-   } // if (hybrid & GPT partition < 2TiB)
-   return deleted;
-} // MBRData::DeleteByLocation()
-
 // Optimizes the size of the 0xEE (EFI GPT) partition
 void MBRData::OptimizeEESize(void) {
    int i, typeFlag = 0;
@@ -798,168 +92,43 @@ void MBRData::OptimizeEESize(void) {
          if (IsFree(after)) {
             partitions[i].lengthLBA = FindLastInFree(after) - partitions[i].firstLBA + 1;
          } // if free space after
+         if (after > diskSize) {
+            if (diskSize < UINT32_MAX) { // If the disk is under 2TiB
+               partitions[0].lengthLBA = (uint32_t) diskSize - partitions[i].firstLBA;
+            } else { // disk is too big to represent, so fake it...
+               partitions[0].lengthLBA = UINT32_MAX - partitions[i].firstLBA;
+            } // if/else
+         } // if protective partition is too big
+         RecomputeCHS(i);
       } // if partition is 0xEE
    } // for partition loop
    if (typeFlag == 0) { // No non-hybrid partitions found
-      MakeProtectiveMBR(); // ensure it's a fully compliant hybrid MBR.
+      MakeProtectiveMBR(); // ensure it's a fully compliant protective MBR.
    } // if
 } // MBRData::OptimizeEESize()
 
-// Recomputes the CHS values for the specified partition and adjusts the value.
-// Note that this will create a technically incorrect CHS value for EFI GPT (0xEE)
-// protective partitions, but this is required by some buggy BIOSes, so I'm
-// providing a function to do this deliberately at the user's command.
-// This function does nothing if the partition's length is 0.
-void MBRData::RecomputeCHS(int partNum) {
-   uint64_t firstLBA, lengthLBA;
-
-   firstLBA = (uint64_t) partitions[partNum].firstLBA;
-   lengthLBA = (uint64_t) partitions[partNum].lengthLBA;
-
-   if (lengthLBA > 0) {
-      LBAtoCHS(firstLBA, partitions[partNum].firstSector);
-      LBAtoCHS(firstLBA + lengthLBA - 1, partitions[partNum].lastSector);
-   } // if
-} // MBRData::RecomputeCHS()
-
-// Creates an MBR extended partition holding logical partitions that
-// correspond to the list of GPT partitions in theList. The extended
-// partition is placed in position #4 (counting from 1) in the MBR.
-// The logical partition data are copied to the partitions[] array in
-// positions 4 and up (counting from 0). Neither the MBR nor the EBR
-// entries are written to disk; that is left for the WriteMBRData()
-// function.
-// Returns number of converted partitions
-int MBRData::CreateLogicals(PartNotes * notes) {
-   uint64_t extEndLBA = 0, extStartLBA = UINT64_MAX;
-   int i = 4, numLogicals = 0;
-   struct PartInfo aPart;
-
-   // Find bounds of the extended partition....
-   notes->Rewind();
-   while (notes->GetNextInfo(&aPart) >= 0) {
-      if (aPart.type == LOGICAL) {
-         if (extStartLBA > aPart.firstLBA)
-            extStartLBA = aPart.firstLBA;
-         if (extEndLBA < aPart.lastLBA)
-            extEndLBA = aPart.lastLBA;
-         numLogicals++;
-      } // if
-   } // while
-   extStartLBA--;
-
-   if ((extStartLBA < UINT32_MAX) && ((extEndLBA - extStartLBA + 1) < UINT32_MAX)) {
-      notes->Rewind();
-      i = 4;
-      while ((notes->GetNextInfo(&aPart) >= 0) && (i < MAX_MBR_PARTS)) {
-         if (aPart.type == LOGICAL) {
-            partitions[i].partitionType = aPart.hexCode;
-            partitions[i].firstLBA = (uint32_t) (aPart.firstLBA - extStartLBA);
-            partitions[i].lengthLBA = (uint32_t) (aPart.lastLBA - aPart.firstLBA + 1);
-            LBAtoCHS(UINT64_C(1), (uint8_t *) &partitions[i].firstSector);
-            LBAtoCHS(partitions[i].lengthLBA, (uint8_t *) &partitions[i].lastSector);
-            partitions[i].status = aPart.active * 0x80;
-            i++;
-         } // if
-      } // while
-      MakePart(3, (uint32_t) extStartLBA, (uint32_t) (extEndLBA - extStartLBA + 1), 0x0f, 0);
-   } else {
-      if (numLogicals > 0) {
-         cerr << "Unable to create logical partitions; they exceed the 2 TiB limit!\n";
-//         cout << "extStartLBA = " << extStartLBA << ", extEndLBA = " << extEndLBA << "\n";
-      }
-   } // if/else
-   return (i - 4);
-} // MBRData::CreateLogicals()
-
-/****************************************
- *                                      *
- * Functions to find data on free space *
- *                                      *
- ****************************************/
-
-// Finds the first free space on the disk from start onward; returns 0
-// if none available....
-uint32_t MBRData::FindFirstAvailable(uint32_t start) {
-   uint32_t first;
-   uint32_t i;
-   int firstMoved;
-
-   first = start;
-
-   // ...now search through all partitions; if first is within an
-   // existing partition, move it to the next sector after that
-   // partition and repeat. If first was moved, set firstMoved
-   // flag; repeat until firstMoved is not set, so as to catch
-   // cases where partitions are out of sequential order....
-   do {
-      firstMoved = 0;
-      for (i = 0; i < 4; i++) {
-         // Check if it's in the existing partition
-         if ((first >= partitions[i].firstLBA) &&
-             (first < (partitions[i].firstLBA + partitions[i].lengthLBA))) {
-            first = partitions[i].firstLBA + partitions[i].lengthLBA;
-            firstMoved = 1;
-         } // if
-      } // for
-   } while (firstMoved == 1);
-   if (first >= diskSize)
-      first = 0;
-   return (first);
-} // MBRData::FindFirstAvailable()
-
-// Finds the last free sector on the disk from start forward.
-uint32_t MBRData::FindLastInFree(uint32_t start) {
-   uint32_t nearestStart;
-   uint32_t i;
-
-   if ((diskSize <= UINT32_MAX) && (diskSize > 0))
-      nearestStart = (uint32_t) diskSize - 1;
-   else
-      nearestStart = UINT32_MAX - 1;
-   for (i = 0; i < 4; i++) {
-      if ((nearestStart > partitions[i].firstLBA) &&
-          (partitions[i].firstLBA > start)) {
-         nearestStart = partitions[i].firstLBA - 1;
-      } // if
-   } // for
-   return (nearestStart);
-} // MBRData::FindLastInFree()
-
-// Finds the first free sector on the disk from start backward.
-uint32_t MBRData::FindFirstInFree(uint32_t start) {
-   uint32_t bestLastLBA, thisLastLBA;
-   int i;
-
-   bestLastLBA = 1;
-   for (i = 0; i < 4; i++) {
-      thisLastLBA = partitions[i].firstLBA + partitions[i].lengthLBA;
-      if (thisLastLBA > 0)
-         thisLastLBA--;
-      if ((thisLastLBA > bestLastLBA) && (thisLastLBA < start))
-         bestLastLBA = thisLastLBA + 1;
-   } // for
-   return (bestLastLBA);
-} // MBRData::FindFirstInFree()
-
-// Returns 1 if the specified sector is unallocated, 0 if it's
-// allocated.
-int MBRData::IsFree(uint32_t sector) {
-   int i, isFree = 1;
-   uint32_t first, last;
+// Delete a partition if one exists at the specified location.
+// Returns 1 if a partition was deleted, 0 otherwise....
+// Used to help keep GPT & hybrid MBR partitions in sync....
+int MBRData::DeleteByLocation(uint64_t start64, uint64_t length64) {
+   uint32_t start32, length32;
+   int i, deleted = 0;
 
-   for (i = 0; i < 4; i++) {
-      first = partitions[i].firstLBA;
-      // Note: Weird two-line thing to avoid subtracting 1 from a 0 value
-      // for an unsigned int....
-      last = first + partitions[i].lengthLBA;
-      if (last > 0)
-         last--;
-      if ((first <= sector) && (last >= sector))
-         isFree = 0;
-   } // for
-   return isFree;
-} // MBRData::IsFree()
+   if ((start64 < UINT32_MAX) && (length64 < UINT32_MAX)) {
+      start32 = (uint32_t) start64;
+      length32 = (uint32_t) length64;
+      for (i = 0; i < MAX_MBR_PARTS; i++) {
+         if ((partitions[i].firstLBA == start32) && (partitions[i].lengthLBA == length32) &&
+            (partitions[i].partitionType != 0xEE)) {
+            DeletePartition(i);
+         if (state == hybrid)
+            OptimizeEESize();
+         deleted = 1;
+         } // if (match found)
+      } // for i (partition scan)
+   } // if (hybrid & GPT partition < 2TiB)
+   return deleted;
+} // MBRData::DeleteByLocation()
 
 /******************************************************
  *                                                    *
@@ -967,54 +136,6 @@ int MBRData::IsFree(uint32_t sector) {
  *                                                    *
  ******************************************************/
 
-uint8_t MBRData::GetStatus(int i) {
-   MBRRecord* thePart;
-   uint8_t retval;
-
-   thePart = GetPartition(i);
-   if (thePart != NULL)
-      retval = thePart->status;
-   else
-      retval = UINT8_C(0);
-   return retval;
-} // MBRData::GetStatus()
-
-uint8_t MBRData::GetType(int i) {
-   MBRRecord* thePart;
-   uint8_t retval;
-
-   thePart = GetPartition(i);
-   if (thePart != NULL)
-      retval = thePart->partitionType;
-   else
-      retval = UINT8_C(0);
-   return retval;
-} // MBRData::GetType()
-
-uint32_t MBRData::GetFirstSector(int i) {
-   MBRRecord* thePart;
-   uint32_t retval;
-
-   thePart = GetPartition(i);
-   if (thePart != NULL) {
-      retval = thePart->firstLBA;
-   } else
-      retval = UINT32_C(0);
-      return retval;
-} // MBRData::GetFirstSector()
-
-uint32_t MBRData::GetLength(int i) {
-   MBRRecord* thePart;
-   uint32_t retval;
-
-   thePart = GetPartition(i);
-   if (thePart != NULL) {
-      retval = thePart->lengthLBA;
-   } else
-      retval = UINT32_C(0);
-      return retval;
-} // MBRData::GetLength()
-
 // Return the MBR data as a GPT partition....
 GPTPart MBRData::AsGPT(int i) {
    MBRRecord* origPart;
@@ -1047,18 +168,3 @@ GPTPart MBRData::AsGPT(int i) {
    return newPart;
 } // MBRData::AsGPT()
 
-/***********************
- *                     *
- * Protected functions *
- *                     *
- ***********************/
-
-// Return a pointer to a primary or logical partition, or NULL if
-// the partition is out of range....
-struct MBRRecord* MBRData::GetPartition(int i) {
-   MBRRecord* thePart = NULL;
-
-   if ((i >= 0) && (i < MAX_MBR_PARTS))
-      thePart = &partitions[i];
-   return thePart;
-} // GetPartition()
diff --git a/mbr.h b/mbr.h
index 85b1841826c89337b6d0fff8e617e30378f6d305..35dfddc882173b2e14953746fa4d542656fdccab 100644
--- a/mbr.h
+++ b/mbr.h
@@ -6,23 +6,16 @@
 #include <stdint.h>
 #include <sys/types.h>
 #include "gptpart.h"
-#include "partnotes.h"
+//#include "partnotes.h"
 #include "diskio.h"
+#include "basicmbr.h"
 
 #ifndef __MBRSTRUCTS
 #define __MBRSTRUCTS
 
-#define MBR_SIGNATURE UINT16_C(0xAA55)
-#define MAX_HEADS 255        /* numbered 0 - 254 */
-#define MAX_SECSPERTRACK 63  /* numbered 1 - 63 */
-#define MAX_CYLINDERS 1024   /* numbered 0 - 1023 */
-
-// Maximum number of MBR partitions
-#define MAX_MBR_PARTS 128
-
 using namespace std;
 
-class PartNotes;
+// class PartNotes;
 
 /****************************************
  *                                      *
@@ -30,115 +23,22 @@ class PartNotes;
  *                                      *
  ****************************************/
 
-// 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.
-// On read or write of MBR entries, firstLBA is an absolute disk sector.
-// On read of logical entries, it's relative to the EBR record for that
-// partition. When writing EBR records, it's relative to the extended
-// partition's start.
-#pragma pack(1)
-struct MBRRecord {
-   uint8_t status;
-   uint8_t firstSector[3];
-   uint8_t partitionType;
-   uint8_t lastSector[3];
-   uint32_t firstLBA; // see above
-   uint32_t lengthLBA;
-}; // struct MBRRecord
-
-// A 512-byte data structure into which the MBR can be loaded in one
-// go. Also used when loading logical partitions.
-#pragma pack(1)
-struct TempMBR {
-   uint8_t code[440];
-   uint32_t diskSignature;
-   uint16_t nulls;
-   struct MBRRecord partitions[4];
-   uint16_t MBRSignature;
-}; // struct TempMBR
-
-// Possible states of the MBR
-enum MBRValidity {invalid, gpt, hybrid, mbr};
-
 // Full data in tweaked MBR format
-class MBRData {
+class MBRData : public BasicMBRData {
 protected:
-   uint8_t code[440];
-   uint32_t diskSignature;
-   uint16_t nulls;
-   // MAX_MBR_PARTS defaults to 128. This array holds both the primary and
-   // the logical partitions, to simplify data retrieval for GPT conversions.
-   struct MBRRecord partitions[MAX_MBR_PARTS];
-   uint16_t MBRSignature;
-
-   // Above are basic MBR data; now add more stuff....
-   uint32_t blockSize; // block size (usually 512)
-   uint64_t diskSize; // size in blocks
-   uint64_t numHeads; // number of heads, in CHS scheme
-   uint64_t numSecspTrack; // number of sectors per track, in CHS scheme
-   DiskIO* myDisk;
-   int canDeleteMyDisk;
-   string device;
-   MBRValidity state;
-   struct MBRRecord* GetPartition(int i); // Return primary or logical partition
+   int foo;
 public:
-   MBRData(void);
-   MBRData(string deviceFilename);
-   ~MBRData(void);
-
-   // File I/O functions...
-   int ReadMBRData(const string & deviceFilename);
-   int ReadMBRData(DiskIO * theDisk, int checkBlockSize = 1);
-   // ReadLogicalPart() returns last partition # read to logicals[] array,
-   // or -1 if there was a problem....
-   int ReadLogicalPart(uint32_t extendedStart, uint32_t diskOffset,
-                       int partNum);
-   int WriteMBRData(void);
-   int WriteMBRData(DiskIO *theDisk);
-   int WriteMBRData(const string & deviceFilename);
-   int WriteMBRData(struct TempMBR & mbr, DiskIO *theDisk, uint64_t sector);
-   void SetDisk(DiskIO *theDisk) {myDisk = theDisk; canDeleteMyDisk = 0;}
-
-   // Display data for user...
-   void DisplayMBRData(int maxParts = 4);
-   void ShowState(void);
-
-   // Functions that set or get disk metadata (size, CHS geometry, etc.)
-   void SetDiskSize(uint64_t ds) {diskSize = ds;}
-   MBRValidity GetValidity(void) {return state;}
-   void SetHybrid(void) {state = hybrid;} // Set hybrid flag
-   void SetCHSGeom(uint32_t h, uint32_t s);
-   int LBAtoCHS(uint64_t lba, uint8_t * chs); // Convert LBA to CHS
-   int Verify(void);
+   MBRData(void) {}
+   MBRData(string deviceFilename) : BasicMBRData(deviceFilename) {}
+   MBRData & operator=(const MBRData & orig);
 
    // Functions to create, delete, or change partitions
    // Pass EmptyMBR 1 to clear the boot loader code, 0 to leave it intact
-   void EmptyMBR(int clearBootloader = 1);
-   void EmptyBootloader(void);
    void MakeProtectiveMBR(int clearBoot = 0);
-   void MakePart(int num, uint32_t startLBA, uint32_t lengthLBA, int type = 0x07,
-                 int bootable = 0);
-   int SetPartType(int num, int type);
-   int SetPartBootable(int num, int bootable = 1);
-   int MakeBiggestPart(int i, int type); // Make partition filling most space
-   void DeletePartition(int i);
-   int DeleteByLocation(uint64_t start64, uint64_t length64);
    void OptimizeEESize(void);
-   void RecomputeCHS(int partNum);
-   int CreateLogicals(PartNotes * notes);
-
-   // Functions to find information on free space....
-   uint32_t FindFirstAvailable(uint32_t start = 1);
-   uint32_t FindLastInFree(uint32_t start);
-   uint32_t FindFirstInFree(uint32_t start);
-   int IsFree(uint32_t sector);
+   int DeleteByLocation(uint64_t start64, uint64_t length64);
 
    // Functions to extract data on specific partitions....
-   uint8_t GetStatus(int i);
-   uint8_t GetType(int i);
-   uint32_t GetFirstSector(int i);
-   uint32_t GetLength(int i);
    GPTPart AsGPT(int i);
 }; // struct MBRData
 
diff --git a/partnotes.cc b/partnotes.cc
index 70196f763d6ea4086066c99d51842e92b7fc8088..a35f9c7376c55f5cb9e40006f5b03c974ef3ff61 100644
--- a/partnotes.cc
+++ b/partnotes.cc
@@ -29,21 +29,16 @@ PartNotes::PartNotes() {
    notes = NULL;
    currentNote = NULL;
    currentIndex = 0;
-   gptParts = NULL;
-   gptTableSize = 0;
+   origTableSize = 0;
    blockSize = 512;
    dummyNote.active = 0;
-   dummyNote.gptPartNum = MBR_EMPTY;
+   dummyNote.origPartNum = MBR_EMPTY;
    dummyNote.hexCode = 0xEE;
    dummyNote.next = NULL;
    dummyNote.spaceBefore = 0;
    dummyNote.type = WILL_NOT_CONVERT;
 } // PartNotes constructor
 
-PartNotes::PartNotes(GPTPart *parts, GPTData *gpt, int num, int s) {
-   PassPartitions(parts, gpt, num, s);
-} // PartNotes constructor passing partition information
-
 // Destructor. Note that we do NOT delete the gptParts array, since we just
 // store a pointer to an array that's allocated by the calling function.
 PartNotes::~PartNotes() {
@@ -71,59 +66,6 @@ void PartNotes::DeleteNotes(void) {
  *                                                                       *
  *************************************************************************/
 
-// Creates the notes linked list with as many entries as there are
-// in-use GPT partitions. Note that the parts array must be pre-sorted!
-// If not, this function will reject the partition table.
-// Returns the number of partitions -- normally identical to num,
-// unless there were problems, in which case it returns 0.
-int PartNotes::PassPartitions(GPTPart *parts, GPTData *gpt, int num, int s) {
-   int i;
-   struct PartInfo *tempNote = NULL, *lastNote = NULL;
-
-   if ((parts != NULL) && (num > 0)) {
-      blockSize = s;
-      gptParts = parts;
-      gptTableSize = num;
-      if (notes != NULL)
-         DeleteNotes();
-      for (i = 0; i < num; i++) {
-         if (gptParts[i].IsUsed()){
-            tempNote = new struct PartInfo;
-            tempNote->next = NULL;
-            tempNote->firstLBA = gptParts[i].GetFirstLBA();
-            tempNote->lastLBA = gptParts[i].GetLastLBA();
-            if (gpt->IsFree(gptParts[i].GetFirstLBA() - 1)) {
-               tempNote->spaceBefore = 1;
-               tempNote->type = LOGICAL;
-            } else {
-               tempNote->spaceBefore = 0;
-               tempNote->type = PRIMARY;
-            } // if/else
-            tempNote->gptPartNum = i;
-            tempNote->active = 0;
-            if (lastNote == NULL) {
-               lastNote = tempNote;
-               notes = tempNote;
-            } else {
-               lastNote->next = tempNote;
-               lastNote = tempNote;
-            } // if/else
-         } // if GPT partition in use
-      } // for
-      if (!IsSorted()) {
-         DeleteNotes();
-         gptParts = NULL;
-         gptTableSize = 0;
-         cerr << "The partition table must be sorted before calling PartNotes::PassPartitions()!\n";
-      } // if
-   } else {
-      notes = NULL;
-      gptParts = NULL;
-      gptTableSize = 0;
-   } // if/else
-   return gptTableSize;
-} // PartNotes::PassPartitions
-
 // Add a single partition to the end of the linked list.
 // Returns 1 on success, 0 on failures.
 int PartNotes::AddToEnd(struct PartInfo *newOne) {
@@ -344,10 +286,10 @@ uint8_t PartNotes::GetMbrHexType(int partNum) {
    } // if/else
 } // PartNotes::GetMBRHexType()
 
-// Return the GPT partition number associated with this note, -1 if
-// the notes list is empty, or the GPT partition number of the last
+// Return the original partition number associated with this note, -1 if
+// the notes list is empty, or the original partition number of the last
 // partition if partNum is too high.
-int PartNotes::GetGptNum(int partNum) {
+int PartNotes::GetOrigNum(int partNum) {
    int count = 0;
    struct PartInfo *theNote;
 
@@ -355,11 +297,11 @@ int PartNotes::GetGptNum(int partNum) {
    if (theNote != NULL) {
       while ((count++ < partNum) && (theNote->next != NULL))
          theNote = theNote->next;
-      return theNote->gptPartNum;
+      return theNote->origPartNum;
    } else {
       return -1;
    } // if/else
-} // PartNotes::GetGptNum()
+} // PartNotes::GetOrigNum()
 
 // Return whether or not the partition is flagged as active (bootable)
 int PartNotes::GetActiveStatus(int partNum) {
@@ -417,23 +359,6 @@ int PartNotes::FindExtended(int &start) {
    return length;
 } // PartNotes::FindExtended()
 
-// Returns 1 if the GPT partition table is sorted, 0 if not (or if the
-// pointer is NULL)
-int PartNotes::IsSorted(void) {
-   int i, sorted = 1;
-   uint64_t lastStartLBA = 0;
-
-   if (gptParts == NULL) {
-      sorted = 0;
-   } else {
-      for (i = 0; i < gptTableSize; i++) {
-         if (lastStartLBA > gptParts[i].GetFirstLBA())
-            sorted = 0;
-      } // for
-   } // if/else
-   return sorted;
-} // PartNotes::IsSorted()
-
 // Returns 1 if the set as a whole makes a legal MBR partition table
 // (possibly with logicals), 0 if not
 int PartNotes::IsLegal(void) {
@@ -557,7 +482,7 @@ void PartNotes::TrimSmallestExtended() {
       } // for
 
       // Find the smallest extended partition....
-      shortestNum = gptTableSize + 1;
+      shortestNum = origTableSize + 1;
       for (i = 0; i < numExtended; i++) {
          if (extendeds[i].numLogicals < shortestNum) {
             shortestNum = extendeds[i].numLogicals;
@@ -593,57 +518,8 @@ void PartNotes::TrimSmallestExtended() {
 
 // Display summary information for the user
 void PartNotes::ShowSummary(void) {
-   int j;
-   string sizeInSI;
-   struct PartInfo *theNote;
-
-   if ((gptParts != NULL) && (notes != NULL)) {
-      theNote = notes;
-      cout << "Sorted GPT partitions and their current conversion status:\n";
-      cout << "                                      Can Be\n";
-      cout << "Number    Boot    Size       Status   Logical   Code   GPT Name\n";
-      while (theNote != NULL) {
-         if (gptParts[theNote->gptPartNum].IsUsed()) {
-            cout.fill(' ');
-            cout.width(4);
-            cout << theNote->gptPartNum + 1 << "    ";
-            if (theNote->active)
-               cout << "   *    ";
-            else
-               cout << "        ";
-            sizeInSI = BytesToSI((gptParts[theNote->gptPartNum].GetLastLBA() -
-                                 gptParts[theNote->gptPartNum].GetFirstLBA() + 1), blockSize);
-            cout << " " << sizeInSI;
-            for (j = 0; j < 12 - (int) sizeInSI.length(); j++)
-               cout << " ";
-            switch (theNote->type) {
-               case PRIMARY:
-                  cout << "primary     ";
-                  break;
-               case LOGICAL:
-                  cout << "logical     ";
-                  break;
-               case WILL_NOT_CONVERT:
-                  cout << "OMITTED     ";
-                  break;
-               default:
-                  cout << "**ERROR**   ";
-                  break;
-            } // switch
-            if (theNote->spaceBefore)
-               cout << "Y       ";
-            else
-               cout << "-       ";
-            cout.fill('0');
-            cout.width(2);
-            cout.setf(ios::uppercase);
-            cout << hex << (int) theNote->hexCode << "    " << dec;
-            cout.fill(' ');
-            cout << gptParts[theNote->gptPartNum].GetDescription().substr(0, 25) << "\n";
-         } // if
-         theNote = theNote->next;
-      } // for
-   } // if
+   cerr << "Program is calling PartNotes::ShowSummary(); this is a virtual base function,\n"
+        << "and should never be called.\n";
 } // PartNotes::ShowSummary()
 
 // Interact with the user to create a change in the specified
@@ -654,7 +530,6 @@ void PartNotes::ShowSummary(void) {
 int PartNotes::MakeChange(int partNum) {
    int allOK = 1;
    int type = 0;
-   char *junk;
    char line[255], command;
 
    if (notes != NULL) {
@@ -676,7 +551,10 @@ int PartNotes::MakeChange(int partNum) {
       } // switch
       cout << " t - change MBR type code\n";
       cout << "Action: ";
-      junk = fgets(line, 255, stdin);
+      if (!fgets(line, 255, stdin)) {
+         cerr << "Critical error! Failed fgets() in PartNotes::MakeChange()!\n";
+         exit(1);
+      } // if
       sscanf(line, "%c", &command);
       switch (command) {
          case 'a': case 'A':
@@ -694,7 +572,10 @@ int PartNotes::MakeChange(int partNum) {
          case 't': case 'T':
             while (type == 0) {
                cout << "Enter a 2-byte hexadecimal MBR type code: ";
-               junk = fgets(line, 255, stdin);
+               if (!fgets(line, 255, stdin)) {
+                  cerr << "Critical error! Failed fgets() in PartNotes::MakeChange()\n";
+                  exit(1);
+               } // if
                sscanf(line, "%x", &type);
             } // while
             SetMbrHexType(partNum, (uint8_t) type);
@@ -711,7 +592,7 @@ int PartNotes::MakeChange(int partNum) {
 // Returns 1 unless there's a dire bug.
 int PartNotes::ChangeType(int partNum, int newType) {
    int origType, allOK = 1;
-   char *junk, line[255];
+   char line[255];
 
    if ((notes != NULL) && IsLegal()) {
       origType = GetType(partNum);
@@ -733,7 +614,10 @@ int PartNotes::ChangeType(int partNum, int newType) {
               << "another\norder, such as deleting partitions before changing others' "
               << "types.\n";
          cout << "\nReverting change.\nPress <Enter> to continue: ";
-         junk = fgets(line, 255, stdin);
+         if (!fgets(line, 255, stdin)) {
+            cerr << "Critical error! Failed fgets() in PartNotes::ChangeType()\n";
+            exit(1);
+         } // if
          SetType(partNum, origType);
       } // if
    } else allOK = 0; // if
diff --git a/partnotes.h b/partnotes.h
index 735e1df11ff0f3eb4b7f878dda3c07fcdd0f544a..750b75f25b0485dfe7ce1a075fae2ee55448ac57 100644
--- a/partnotes.h
+++ b/partnotes.h
@@ -1,6 +1,6 @@
 /*
     partnotes.h -- Class that takes notes on GPT partitions for purpose of MBR conversion
-    Copyright (C) 2010 Roderick W. Smith
+    Copyright (C) 2010-2011 Roderick W. Smith
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -21,8 +21,8 @@
 #ifndef __PARTNOTES_H
 #define __PARTNOTES_H
 
-#include "gpt.h"
-#include "gptpart.h"
+#include <stdint.h>
+#include <sys/types.h>
 
 using namespace std;
 
@@ -33,7 +33,7 @@ using namespace std;
 // Data structure used in GPT-to-MBR conversions; holds pointer to GPT
 // partition number, start and end sectors, and a few MBR-specific details
 struct PartInfo {
-   int gptPartNum;
+   int origPartNum;
    int spaceBefore; // boolean; if 1, can theoretically become a logical part.
    int active; // boolean
    int type; // WILL_NOT_CONVERT, PRIMARY, or LOGICAL
@@ -54,22 +54,21 @@ class PartNotes {
       struct PartInfo *notes;
       struct PartInfo *currentNote;
       int currentIndex;
-      GPTPart *gptParts;
-      int gptTableSize;
       int blockSize;
+      int origTableSize;
 
       void DeleteNotes(void);
+
    public:
       PartNotes();
-      PartNotes(GPTPart *parts, GPTData *gpt, int num, int blockSize);
       ~PartNotes();
 
       // Add partition notes (little or no error checking)
-      int PassPartitions(GPTPart *parts, GPTData *gpt, int num, int blockSize);
+//      int PassPartitions(GPTPart *parts, GPTData *gpt, int num, int blockSize);
       int AddToEnd(struct PartInfo* newOne);
       int AddToStart(struct PartInfo* newOne);
       void SetType(int partNum, int type); // type is PRIMARY, LOGICAL, or WILL_NOT_CONVERT
-      void SetMbrHexType(int i, uint8_t type);
+      void SetMbrHexType(int partNum, uint8_t type);
       void ToggleActiveStatus(int partNum);
 
       // Retrieve data or metadata
@@ -81,12 +80,11 @@ class PartNotes {
       int GetNumLogical();
       int GetType(int partNum);
       uint8_t GetMbrHexType(int i);
-      int GetGptNum(int partNum);
+      int GetOrigNum(int partNum);
       int GetActiveStatus(int partNum);
       int CanBeLogical(int partNum); // returns boolean
       int FindExtended(int &start);
-      int IsSorted(void);
-      int IsLegal(void); // returns boolean
+      int IsLegal(void); // returns Boolean
 
       // Manipulate data or metadata
       void RemoveDuplicates(void);
@@ -94,7 +92,7 @@ class PartNotes {
       void TrimSmallestExtended(void);
 
       // Interact with users, possibly changing data with error handling
-      void ShowSummary(void);
+      virtual void ShowSummary(void);
       int MakeChange(int partNum);
       int ChangeType(int partNum, int newType);
 };
diff --git a/parttypes.cc b/parttypes.cc
index c6e2098e91f2fd513c644f24caef6e6735a174b4..fce2d46de178356cdcf9fee7bdcc1ffc81a835c3 100644
--- a/parttypes.cc
+++ b/parttypes.cc
@@ -2,7 +2,7 @@
 // Class to manage partition type codes -- a slight variant on MBR type
 // codes, GUID type codes, and associated names.
 
-/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
+/* 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. */
 
 #define __STDC_LIMIT_MACROS
@@ -163,7 +163,7 @@ void PartType::AddAllTypes(void) {
    AddType(0xc002, "E2A1E728-32E3-11D6-A682-7B03A0000000", "HP-UX service");
 
    // EFI system and related partitions
-   AddType(0xef00, "C12A7328-F81F-11D2-BA4B-00A0C93EC93B", "EFI System"); // Parted marks Linux boot partitions as this
+   AddType(0xef00, "C12A7328-F81F-11D2-BA4B-00A0C93EC93B", "EFI System"); // Parted identifies these as having the "boot flag" set
    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"); // Boot loader
 
diff --git a/sgdisk.8 b/sgdisk.8
index 1cd2b90d750826df87257ac74b45cd0db36f4a4e..0b0b57cebcd5aff3a298099aa367c25d8e4fdb22 100644
--- a/sgdisk.8
+++ b/sgdisk.8
@@ -570,6 +570,8 @@ Contributors:
 
 * Dwight Schauer (dschauer@ti.com)
 
+* Florian Zumbiehl (florz@florz.de)
+
 
 .SH "SEE ALSO"
 \fBcfdisk (8)\fR,
diff --git a/sgdisk.cc b/sgdisk.cc
index fb0e2c862f255b8ea79564b21c19412388c0e728..f9b0a72a7ed546337da5638cc9b91eec3b79440c 100644
--- a/sgdisk.cc
+++ b/sgdisk.cc
@@ -6,7 +6,7 @@
 //
 // by Rod Smith, project began February 2009; sgdisk begun January 2010.
 
-/* This program is copyright (c) 2009, 2010 by Roderick W. Smith. It is distributed
+/* 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 <stdio.h>
@@ -20,6 +20,7 @@
 #include "gpt.h"
 #include "support.h"
 #include "parttypes.h"
+#include "gptpartnotes.h"
 #include "attributes.h"
 
 using namespace std;
@@ -30,7 +31,7 @@ int BuildMBR(GPTData& theGPT, char* argument, int isHybrid);
 int CountColons(char* argument);
 
 int main(int argc, char *argv[]) {
-   GPTData theGPT;
+   GPTData theGPT, secondDevice;
    uint32_t sSize;
    uint64_t low, high;
    int opt, numOptions = 0, saveData = 0, neverSaveData = 0;
@@ -231,9 +232,10 @@ int main(int argc, char *argv[]) {
                   theGPT.ShowPartDetails(infoPartNum - 1);
                   break;
                case 'l':
-                  if (theGPT.LoadGPTBackup((string) backupFile) == 1)
+                  if (theGPT.LoadGPTBackup((string) backupFile) == 1) {
+                     theGPT.JustLooking(0);
                      saveData = 1;
-                  else {
+                  } else {
                      saveData = 0;
                      neverSaveData = 1;
                      cerr << "Error loading backup file!\n";
@@ -309,8 +311,11 @@ int main(int argc, char *argv[]) {
                   } else saveData = 1;
                   break;
                case 'R':
-                  theGPT.JustLooking(0);
-                  theGPT.SaveGPTData(1, outDevice);
+                  secondDevice = theGPT;
+                  secondDevice.SetFile(outDevice);
+                  secondDevice.JustLooking(0);
+//                  secondDevice.FixupMBR();
+                  secondDevice.SaveGPTData(1);
                   break;
                case 's':
                   theGPT.JustLooking(0);
@@ -424,7 +429,7 @@ int main(int argc, char *argv[]) {
 // Create a hybrid or regular MBR from GPT data structures
 int BuildMBR(GPTData & theGPT, char* argument, int isHybrid) {
    int numParts, allOK = 1, i;
-   PartNotes notes;
+   GptPartNotes notes;
    struct PartInfo *newNote;
 
    if ((&theGPT != NULL) && (argument != NULL)) {
@@ -432,17 +437,17 @@ int BuildMBR(GPTData & theGPT, char* argument, int isHybrid) {
       if (numParts <= (4 - isHybrid)) {
          for (i = 0; i < numParts; i++) {
             newNote = new struct PartInfo;
-            newNote->gptPartNum = GetInt(argument, i + 1) - 1;
+            newNote->origPartNum = GetInt(argument, i + 1) - 1;
             newNote->active = 0;
             newNote->hexCode = 0; // code to compute it from default
             newNote->type = PRIMARY;
-            newNote->firstLBA = theGPT[newNote->gptPartNum].GetFirstLBA();
-            newNote->lastLBA = theGPT[newNote->gptPartNum].GetLastLBA();
+            newNote->firstLBA = theGPT[newNote->origPartNum].GetFirstLBA();
+            newNote->lastLBA = theGPT[newNote->origPartNum].GetLastLBA();
             notes.AddToEnd(newNote);
          } // for
          if (isHybrid) {
             newNote = new struct PartInfo;
-            newNote->gptPartNum = MBR_EFI_GPT;
+            newNote->origPartNum = MBR_EFI_GPT;
             newNote->active = 0;
             newNote->hexCode = 0xEE;
             newNote->type = PRIMARY;
diff --git a/support.cc b/support.cc
index ee445661bea66ebca11b6d16d84e6207776dda2a..bd0b28b4c24cc75e5442cf6f9c69a5c1f73d7c70 100644
--- a/support.cc
+++ b/support.cc
@@ -63,11 +63,13 @@ int GetNumber(int low, int high, int def, const string & prompt) {
 char GetYN(void) {
    char line[255];
    char response;
-   char *junk;
 
    do {
       cout << "(Y/N): ";
-      junk = fgets(line, 255, stdin);
+      if (!fgets(line, 255, stdin)) {
+         cerr << "Critical error! Failed fgets() in GetYN()\n";
+         exit(1);
+      } // if
       sscanf(line, "%c", &response);
       if (response == 'y')
          response = 'Y';
@@ -306,32 +308,23 @@ void ReverseBytes(void* theValue, int numBytes) {
 
 // Extract integer data from argument string, which should be colon-delimited
 uint64_t GetInt(const string & argument, int itemNum) {
-   int startPos = -1, endPos = -1;
-   uint64_t retval = 0;
+   uint64_t retval;
 
-   while (itemNum-- > 0) {
-      startPos = endPos + 1;
-      endPos = (int) argument.find(':', startPos);
-   }
-   if (endPos == (int) string::npos)
-      endPos = (int) argument.length();
-   endPos--;
-
-   istringstream inString(argument.substr(startPos, endPos - startPos + 1));
+   istringstream inString(GetString(argument, itemNum));
    inString >> retval;
    return retval;
 } // GetInt()
 
 // Extract string data from argument string, which should be colon-delimited
 string GetString(const string & argument, int itemNum) {
-   int startPos = -1, endPos = -1;
+   size_t startPos = -1, endPos = -1;
 
    while (itemNum-- > 0) {
       startPos = endPos + 1;
-      endPos = (int) argument.find(':', startPos);
+      endPos = argument.find(':', startPos);
    }
-   if (endPos == (int) string::npos)
-      endPos = (int) argument.length();
+   if (endPos == string::npos)
+      endPos = argument.length();
    endPos--;
 
    return argument.substr(startPos, endPos - startPos + 1);