Misc. bug fixes & restructuring.

This commit is contained in:
srs5694
2011-03-01 22:03:54 -05:00
parent f2efa7defc
commit 64cbd17106
25 changed files with 742 additions and 1413 deletions

354
Makefile
View File

@@ -3,7 +3,7 @@ CXX=g++
CFLAGS+=-D_FILE_OFFSET_BITS=64 CFLAGS+=-D_FILE_OFFSET_BITS=64
CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64 CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64
LDFLAGS+= 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_SRCS=$(NAMES:=.cc)
LIB_OBJS=$(LIB_NAMES:=.o) LIB_OBJS=$(LIB_NAMES:=.o)
LIB_HEADERS=$(LIB_NAMES:=.h) LIB_HEADERS=$(LIB_NAMES:=.h)
@@ -31,3 +31,355 @@ $(OBJS):
$(CRITICAL_CXX_FLAGS) $(CRITICAL_CXX_FLAGS)
# DO NOT DELETE # 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

View File

@@ -2,7 +2,7 @@ CC=gcc
CXX=g++ CXX=g++
CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -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 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_SRCS=$(NAMES:=.cc)
LIB_OBJS=$(LIB_NAMES:=.o) LIB_OBJS=$(LIB_NAMES:=.o)
LIB_HEADERS=$(LIB_NAMES:=.h) LIB_HEADERS=$(LIB_NAMES:=.h)

View File

@@ -1,10 +1,10 @@
CC=/usr/bin/i586-mingw32msvc-gcc CC=/usr/bin/i686-pc-mingw32-gcc
CXX=/usr/bin/i586-mingw32msvc-g++ CXX=/usr/bin/i686-pc-mingw32-g++
STRIP=/usr/bin/i586-mingw32msvc-strip STRIP=/usr/bin/i686-pc-mingw32-strip
CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g
CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -g CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -g
#CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g #CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
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_SRCS=$(NAMES:=.cc)
LIB_OBJS=$(LIB_NAMES:=.o) LIB_OBJS=$(LIB_NAMES:=.o)
LIB_HEADERS=$(LIB_NAMES:=.h) LIB_HEADERS=$(LIB_NAMES:=.h)
@@ -12,8 +12,8 @@ DEPEND= makedepend $(CFLAGS)
all: gdisk all: gdisk
gdisk: $(LIB_OBJS) gpttext.o gdisk.o gdisk: $(LIB_OBJS) gdisk.o gpttext.o
$(CXX) $(LIB_OBJS) gpttext.o gdisk.o -luuid -o gdisk.exe $(CXX) $(LIB_OBJS) gdisk.o gpttext.o -luuid -static-libgcc -o gdisk.exe
sgdisk: $(LIB_OBJS) sgdisk.o sgdisk: $(LIB_OBJS) sgdisk.o
$(CXX) $(LIB_OBJS) sgdisk.o -lpopt -o sgdisk.exe $(CXX) $(LIB_OBJS) sgdisk.o -lpopt -o sgdisk.exe

23
NEWS
View File

@@ -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): 0.6.14 (1/8/2011):
------------------ ------------------

View File

@@ -1,8 +1,9 @@
// attributes.cc // attributes.cc
// Class to manage partition attribute codes. These are binary bit fields, // 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. */ under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
#define __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS

View File

@@ -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. */ under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
#include <stdint.h> #include <stdint.h>

View File

@@ -348,7 +348,7 @@ uint64_t DiskIO::DiskSize(int *err) {
if (*err) { if (*err) {
sectors = sz = 0; sectors = sz = 0;
} // if } // if
if ((errno == EFBIG) || (!*err)) { if ((!*err) || (errno == EFBIG)) {
*err = ioctl(fd, BLKGETSIZE64, &b); *err = ioctl(fd, BLKGETSIZE64, &b);
if (*err || b == 0 || b == sz) if (*err || b == 0 || b == sz)
sectors = sz; sectors = sz;

View File

@@ -69,7 +69,7 @@ class DiskIO {
int GetBlockSize(void); int GetBlockSize(void);
int IsOpen(void) {return isOpen;} int IsOpen(void) {return isOpen;}
int IsOpenForWrite(void) {return openForWrite;} int IsOpenForWrite(void) {return openForWrite;}
string GetName(void) {return realFilename;} string GetName(void) const {return realFilename;}
uint64_t DiskSize(int* err); uint64_t DiskSize(int* err);
}; // struct GPTPart }; // struct GPTPart

11
gdisk.8
View File

@@ -471,10 +471,11 @@ physical sectors (such as some Western Digital models introduced in
December of 2009) and some RAID configurations can suffer performance December of 2009) and some RAID configurations can suffer performance
problems if partitions are not aligned properly for their internal data problems if partitions are not aligned properly for their internal data
structures. On new disks, GPT fdisk attempts to align partitions on structures. On new disks, GPT fdisk attempts to align partitions on
2048\-sector (1MiB) boundaries by default, which optimizes performance 2048\-sector (1MiB) boundaries by default, which optimizes performance for
for both of these disk types. On pre\-partitioned disks, GPT fdisk both of these disk types. On pre\-partitioned disks, GPT fdisk attempts to
attempts to identify the alignment value used on that disk. In either identify the alignment value used on that disk, but will set 8-sector
case, it can be changed by using this option. 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 .TP
.B m .B m
@@ -663,6 +664,8 @@ Contributors:
* Dwight Schauer (dschauer@ti.com) * Dwight Schauer (dschauer@ti.com)
* Florian Zumbiehl (florz@florz.de)
.SH "SEE ALSO" .SH "SEE ALSO"
\fBcfdisk (8)\fR, \fBcfdisk (8)\fR,

122
gdisk.cc
View File

@@ -4,7 +4,7 @@
// //
// by Rod Smith, project began February 2009 // 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. */ under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
#include <stdio.h> #include <stdio.h>
@@ -29,8 +29,8 @@ void WinWarning(void);
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
GPTDataTextUI theGPT; GPTDataTextUI theGPT;
int doMore = 1, i; size_t i;
char *device = NULL, *junk; char *device = NULL;
cout << "GPT fdisk (gdisk) version " << GPTFDISK_VERSION << "\n\n"; cout << "GPT fdisk (gdisk) version " << GPTFDISK_VERSION << "\n\n";
@@ -42,25 +42,21 @@ int main(int argc, char* argv[]) {
WinWarning(); WinWarning();
cout << "Type device filename, or press <Enter> to exit: "; cout << "Type device filename, or press <Enter> to exit: ";
device = new char[255]; device = new char[255];
junk = fgets(device, 255, stdin); if (!fgets(device, 255, stdin)) {
if (device[0] != '\n') { cerr << "Critical error! Failed fgets() in main()!\n";
i = (int) strlen(device); exit(1);
if (i > 0)
if (device[i - 1] == '\n')
device[i - 1] = '\0';
doMore = theGPT.LoadPartitions(device);
if (doMore) {
MainMenu(device, &theGPT);
} // if (doMore)
} // if } // if
i = strlen(device);
if (i && device[i - 1] == '\n')
device[i - 1] = '\0';
if (*device && theGPT.LoadPartitions(device))
MainMenu(device, &theGPT);
delete[] device; delete[] device;
break; break;
case 2: // basic usage case 2: // basic usage
WinWarning(); WinWarning();
doMore = theGPT.LoadPartitions(argv[1]); if (theGPT.LoadPartitions(argv[1]))
if (doMore) {
MainMenu(argv[1], &theGPT); MainMenu(argv[1], &theGPT);
} // if (doMore)
break; break;
case 3: // usage with "-l" option case 3: // usage with "-l" option
if (strcmp(argv[1], "-l") == 0) { if (strcmp(argv[1], "-l") == 0) {
@@ -72,8 +68,8 @@ int main(int argc, char* argv[]) {
} // if/elseif/else } // if/elseif/else
if (device != NULL) { if (device != NULL) {
theGPT.JustLooking(); theGPT.JustLooking();
doMore = theGPT.LoadPartitions((string) device); if (theGPT.LoadPartitions((string) device))
if (doMore) theGPT.DisplayGPTData(); theGPT.DisplayGPTData();
} // if } // if
break; break;
default: default:
@@ -85,23 +81,27 @@ int main(int argc, char* argv[]) {
// Accept a command and execute it. Returns only when the user // Accept a command and execute it. Returns only when the user
// wants to exit (such as after a 'w' or 'q' command). // wants to exit (such as after a 'w' or 'q' command).
void MainMenu(string filename, GPTDataTextUI* theGPT) { void MainMenu(string filename, GPTDataTextUI* theGPT) {
char command, line[255], buFile[255]; char line[255], buFile[255];
char* junk;
int goOn = 1; int goOn = 1;
PartType typeHelper; PartType typeHelper;
uint32_t temp1, temp2; uint32_t temp1, temp2;
do { do {
cout << "\nCommand (? for help): "; cout << "\nCommand (? for help): ";
junk = fgets(line, 255, stdin); if (!fgets(line, 255, stdin)) {
sscanf(line, "%c", &command); cerr << "Critical error! Failed fgets() in MainMenu()!\n";
switch (command) { exit(1);
} // if
switch (*line) {
case '\n': case '\n':
break; break;
case 'b': case 'B': case 'b': case 'B':
cout << "Enter backup filename to save: "; cout << "Enter backup filename to save: ";
junk = fgets(line, 255, stdin); if (!fgets(line, 255, stdin)) {
sscanf(line, "%s", (char*) &buFile); exit(1);
cerr << "Critical error! Failed fgets() in MainMenu()!\n";
} // if
sscanf(line, "%s", buFile);
theGPT->SaveGPTBackup(buFile); theGPT->SaveGPTBackup(buFile);
break; break;
case 'c': case 'C': case 'c': case 'C':
@@ -187,16 +187,17 @@ void ShowCommands(void) {
// Accept a recovery & transformation menu command. Returns only when the user // Accept a recovery & transformation menu command. Returns only when the user
// issues an exit command, such as 'w' or 'q'. // issues an exit command, such as 'w' or 'q'.
void RecoveryMenu(string filename, GPTDataTextUI* theGPT) { void RecoveryMenu(string filename, GPTDataTextUI* theGPT) {
char command, line[255], buFile[255]; char line[255], buFile[255];
char* junk;
uint32_t temp1, numParts; uint32_t temp1, numParts;
int goOn = 1; int goOn = 1;
do { do {
cout << "\nRecovery/transformation command (? for help): "; cout << "\nRecovery/transformation command (? for help): ";
junk = fgets(line, 255, stdin); if (!fgets(line, 255, stdin)) {
sscanf(line, "%c", &command); cerr << "Critical error! Failed fgets() in RecoveryMenu()!\n";
switch (command) { exit(1);
} // if
switch (*line) {
case '\n': case '\n':
break; break;
case 'b': case 'B': case 'b': case 'B':
@@ -251,8 +252,11 @@ void RecoveryMenu(string filename, GPTDataTextUI* theGPT) {
break; break;
case 'l': case 'L': case 'l': case 'L':
cout << "Enter backup filename to load: "; cout << "Enter backup filename to load: ";
junk = fgets(line, 255, stdin); if (!fgets(line, 255, stdin)) {
sscanf(line, "%s", (char*) &buFile); cerr << "Critical error! Failed fgets() in RecoveryMenu()!\n";
exit(1);
} // if
sscanf(line, "%s", buFile);
theGPT->LoadGPTBackup(buFile); theGPT->LoadGPTBackup(buFile);
break; break;
case 'm': case 'M': case 'm': case 'M':
@@ -314,19 +318,22 @@ void ShowRecoveryCommands(void) {
// Accept an experts' menu command. Returns only after the user // Accept an experts' menu command. Returns only after the user
// selects an exit command, such as 'w' or 'q'. // selects an exit command, such as 'w' or 'q'.
void ExpertsMenu(string filename, GPTDataTextUI* theGPT) { void ExpertsMenu(string filename, GPTDataTextUI* theGPT) {
char command, line[255], *device; GPTData secondDevice;
char* junk; char line[255], *device;
uint32_t pn, temp1, temp2; uint32_t pn, temp1, temp2;
int goOn = 1, i; int goOn = 1;
size_t i;
char guidStr[255]; char guidStr[255];
GUIDData aGUID; GUIDData aGUID;
ostringstream prompt; ostringstream prompt;
do { do {
cout << "\nExpert command (? for help): "; cout << "\nExpert command (? for help): ";
junk = fgets(line, 255, stdin); if (!fgets(line, 255, stdin)) {
sscanf(line, "%c", &command); cerr << "Critical error! Failed fgets() in ExpertsMenu()!\n";
switch (command) { exit(1);
} // if
switch (*line) {
case '\n': case '\n':
break; break;
case 'a': case 'A': case 'a': case 'A':
@@ -339,7 +346,10 @@ void ExpertsMenu(string filename, GPTDataTextUI* theGPT) {
if (theGPT->GetPartRange(&temp1, &temp2) > 0) { if (theGPT->GetPartRange(&temp1, &temp2) > 0) {
pn = theGPT->GetPartNum(); pn = theGPT->GetPartNum();
cout << "Enter the partition's new unique GUID ('R' to randomize): "; 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')) { if ((strlen(guidStr) >= 33) || (guidStr[0] == 'R') || (guidStr[0] == 'r')) {
theGPT->SetPartitionGUID(pn, (GUIDData) guidStr); theGPT->SetPartitionGUID(pn, (GUIDData) guidStr);
cout << "New GUID is " << theGPT->operator[](pn).GetUniqueGUID() << "\n"; cout << "New GUID is " << theGPT->operator[](pn).GetUniqueGUID() << "\n";
@@ -361,7 +371,10 @@ void ExpertsMenu(string filename, GPTDataTextUI* theGPT) {
break; break;
case 'g': case 'G': case 'g': case 'G':
cout << "Enter the disk's unique GUID ('R' to randomize): "; 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')) { if ((strlen(guidStr) >= 33) || (guidStr[0] == 'R') || (guidStr[0] == 'r')) {
theGPT->SetDiskGUID((GUIDData) guidStr); theGPT->SetDiskGUID((GUIDData) guidStr);
cout << "The new disk GUID is " << theGPT->GetDiskGUID() << "\n"; cout << "The new disk GUID is " << theGPT->GetDiskGUID() << "\n";
@@ -395,8 +408,8 @@ void ExpertsMenu(string filename, GPTDataTextUI* theGPT) {
theGPT->DisplayGPTData(); theGPT->DisplayGPTData();
break; break;
case 'q': case 'Q': case 'q': case 'Q':
goOn = 0; goOn = 0;
break; break;
case 'r': case 'R': case 'r': case 'R':
RecoveryMenu(filename, theGPT); RecoveryMenu(filename, theGPT);
goOn = 0; goOn = 0;
@@ -404,21 +417,24 @@ void ExpertsMenu(string filename, GPTDataTextUI* theGPT) {
case 's': case 'S': case 's': case 'S':
theGPT->ResizePartitionTable(); theGPT->ResizePartitionTable();
break; break;
case 't': case 'T': case 't': case 'T':
theGPT->SwapPartitions(); theGPT->SwapPartitions();
break; break;
case 'u': case 'U': case 'u': case 'U':
cout << "Type device filename, or press <Enter> to exit: "; cout << "Type device filename, or press <Enter> to exit: ";
device = new char[255]; device = new char[255];
junk = fgets(device, 255, stdin); if (!fgets(device, 255, stdin)) {
if (device[0] != '\n') { cerr << "Critical error! Failed fgets() in ExpertsMenu()!\n";
i = (int) strlen(device); exit(1);
if (i > 0) } // if
if (device[i - 1] == '\n') i = strlen(device);
device[i - 1] = '\0'; 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
if (strlen(device) > 0)
theGPT->SaveGPTData(0, device);
delete[] device; delete[] device;
break; break;
case 'v': case 'V': case 'v': case 'V':

143
gpt.cc
View File

@@ -3,7 +3,7 @@
/* By Rod Smith, initial coding January to February, 2009 */ /* 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. */ under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
#define __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS
@@ -96,6 +96,45 @@ GPTData::~GPTData(void) {
delete[] partitions; delete[] partitions;
} // GPTData destructor } // 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 * * 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 // do *NOT* recover from these problems. Returns the total number of
// problems identified. // problems identified.
int GPTData::Verify(void) { int GPTData::Verify(void) {
int problems = 0; int problems = 0, alignProbs = 0;
uint32_t i, numSegments; uint32_t i, numSegments;
uint64_t totalFree, largestSegment; uint64_t totalFree, largestSegment;
@@ -210,11 +249,11 @@ int GPTData::Verify(void) {
// Now check for a few other miscellaneous problems... // Now check for a few other miscellaneous problems...
// Check that the disk size will hold the data... // Check that the disk size will hold the data...
if (mainHeader.backupLBA > diskSize) { if (mainHeader.backupLBA >= diskSize) {
problems++; problems++;
cout << "\nProblem: Disk is too small to hold all the data!\n" cout << "\nProblem: Disk is too small to hold all the data!\n"
<< "(Disk size is " << diskSize << " sectors, needs to be " << "(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"; << "The 'e' option on the experts' menu may fix this problem.\n";
} // if } // if
@@ -240,14 +279,18 @@ int GPTData::Verify(void) {
cout << "\nCaution: Partition " << i + 1 << " doesn't begin on a " cout << "\nCaution: Partition " << i + 1 << " doesn't begin on a "
<< sectorAlignment << "-sector boundary. This may\nresult " << sectorAlignment << "-sector boundary. This may\nresult "
<< "in degraded performance on some modern (2009 and later) hard disks.\n"; << "in degraded performance on some modern (2009 and later) hard disks.\n";
alignProbs++;
} // if } // if
} // for } // 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 // Now compute available space, but only if no problems found, since
// problems could affect the results // problems could affect the results
if (problems == 0) { if (problems == 0) {
totalFree = FindFreeBlocks(&numSegments, &largestSegment); totalFree = FindFreeBlocks(&numSegments, &largestSegment);
cout << "No problems found. " << totalFree << " free sectors (" cout << "\nNo problems found. " << totalFree << " free sectors ("
<< BytesToSI(totalFree, blockSize) << ") available in " << BytesToSI(totalFree, blockSize) << ") available in "
<< numSegments << "\nsegments, the largest of which is " << numSegments << "\nsegments, the largest of which is "
<< largestSegment << " (" << BytesToSI(largestSegment, blockSize) << 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 // Scan for partition data. This function loads the MBR data (regular MBR or
// protective MBR) and loads BSD disklabel data (which is probably invalid). // 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 // 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; return newCrcOk;
} // GPTData::CheckTable() } // 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. // write, 0 if there was a problem.
int GPTData::SaveGPTData(int quiet, string filename) { int GPTData::SaveGPTData(int quiet) {
int allOK = 1, littleEndian; int allOK = 1, littleEndian;
char answer; char answer;
littleEndian = IsLittleEndian(); littleEndian = IsLittleEndian();
if (filename == "")
filename = device;
if (filename == "") {
cerr << "Device not defined.\n";
} // if
// First do some final sanity checks.... // First do some final sanity checks....
// This test should only fail on read-only disks.... // This test should only fail on read-only disks....
@@ -891,30 +947,34 @@ int GPTData::SaveGPTData(int quiet, string filename) {
allOK = 0; allOK = 0;
} // if } // 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, // Is there enough space to hold the GPT headers and partition tables,
// given the partition sizes? // given the partition sizes?
if (CheckGPTSize() > 0) { if (CheckGPTSize() > 0) {
allOK = 0; allOK = 0;
} // if } // 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 // Check that second header is properly placed. Warn and ask if this should
// be corrected if the test fails.... // be corrected if the test fails....
if ((mainHeader.backupLBA < (diskSize - UINT64_C(1))) && (quiet == 0)) { if (mainHeader.backupLBA < (diskSize - UINT64_C(1))) {
cout << "Warning! Secondary header is placed too early on the disk! Do you want to\n" if (quiet == 0) {
<< "correct this problem? "; cout << "Warning! Secondary header is placed too early on the disk! Do you want to\n"
if (GetYN() == 'Y') { << "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(); MoveSecondHeaderToEnd();
cout << "Have moved second header and partition table to correct location.\n"; } // if/else quiet
} else {
cout << "Have not corrected the problem. Strange problems may occur in the future!\n";
} // if correction requested
} // if } // if
// Check for overlapping or insane partitions.... // Check for overlapping or insane partitions....
@@ -942,7 +1002,7 @@ int GPTData::SaveGPTData(int quiet, string filename) {
// Do it! // Do it!
if (allOK) { if (allOK) {
if (myDisk.OpenForWrite(filename)) { if (myDisk.OpenForWrite()) {
// As per UEFI specs, write the secondary table and GPT first.... // As per UEFI specs, write the secondary table and GPT first....
allOK = SavePartitionTable(myDisk, secondHeader.partitionEntriesLBA); allOK = SavePartitionTable(myDisk, secondHeader.partitionEntriesLBA);
if (!allOK) if (!allOK)
@@ -975,7 +1035,7 @@ int GPTData::SaveGPTData(int quiet, string filename) {
myDisk.Close(); myDisk.Close();
} else { } 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"; << errno << "! Aborting write!\n";
allOK = 0; allOK = 0;
} // if/else } // if/else
@@ -1513,24 +1573,24 @@ int GPTData::PartsToMBR(PartNotes * notes) {
notes->MakeItLegal(); notes->MakeItLegal();
notes->Rewind(); notes->Rewind();
while (notes->GetNextInfo(&convInfo) >= 0) { while (notes->GetNextInfo(&convInfo) >= 0) {
if ((convInfo.gptPartNum >= 0) && (convInfo.type == PRIMARY)) { if ((convInfo.origPartNum >= 0) && (convInfo.type == PRIMARY)) {
numConverted += OnePartToMBR((uint32_t) convInfo.gptPartNum, mbrNum); numConverted += OnePartToMBR((uint32_t) convInfo.origPartNum, mbrNum);
if (convInfo.hexCode != 0) if (convInfo.hexCode != 0)
protectiveMBR.SetPartType(mbrNum, convInfo.hexCode); protectiveMBR.SetPartType(mbrNum, convInfo.hexCode);
if (convInfo.active) if (convInfo.active)
protectiveMBR.SetPartBootable(mbrNum); protectiveMBR.SetPartBootable(mbrNum);
mbrNum++; mbrNum++;
} // if } // if
if (convInfo.gptPartNum == MBR_EFI_GPT) if (convInfo.origPartNum == MBR_EFI_GPT)
mbrNum++; mbrNum++;
} // for } // for
// Now go through and set sizes for MBR_EFI_GPT partitions.... // Now go through and set sizes for MBR_EFI_GPT partitions....
notes->Rewind(); notes->Rewind();
mbrNum = 0; mbrNum = 0;
while (notes->GetNextInfo(&convInfo) >= 0) { while (notes->GetNextInfo(&convInfo) >= 0) {
if ((convInfo.gptPartNum >= 0) && (convInfo.type == PRIMARY)) if ((convInfo.origPartNum >= 0) && (convInfo.type == PRIMARY))
mbrNum++; mbrNum++;
if (convInfo.gptPartNum == MBR_EFI_GPT) { if (convInfo.origPartNum == MBR_EFI_GPT) {
if (protectiveMBR.FindFirstAvailable() == UINT32_C(1)) { if (protectiveMBR.FindFirstAvailable() == UINT32_C(1)) {
protectiveMBR.MakePart(mbrNum, 1, protectiveMBR.FindLastInFree(1), convInfo.hexCode); protectiveMBR.MakePart(mbrNum, 1, protectiveMBR.FindLastInFree(1), convInfo.hexCode);
protectiveMBR.SetHybrid(); protectiveMBR.SetHybrid();
@@ -1803,11 +1863,22 @@ int GPTData::ClearGPTData(void) {
} // GPTData::ClearGPTData() } // GPTData::ClearGPTData()
// Set the location of the second GPT header data to the end of the disk. // 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 & // Used internally and called by the 'e' option on the recovery &
// transformation menu, to help users of RAID arrays who add disk space // 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() { void GPTData::MoveSecondHeaderToEnd() {
mainHeader.backupLBA = secondHeader.currentLBA = diskSize - UINT64_C(1); 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; mainHeader.lastUsableLBA = secondHeader.lastUsableLBA = diskSize - mainHeader.firstUsableLBA;
secondHeader.partitionEntriesLBA = secondHeader.lastUsableLBA + UINT64_C(1); secondHeader.partitionEntriesLBA = secondHeader.lastUsableLBA + UINT64_C(1);
} // GPTData::FixSecondHeaderLocation() } // GPTData::FixSecondHeaderLocation()

16
gpt.h
View File

@@ -1,7 +1,7 @@
/* gpt.h -- GPT and data structure definitions, types, and /* gpt.h -- GPT and data structure definitions, types, and
functions */ 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. */ under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
#include <stdint.h> #include <stdint.h>
@@ -11,12 +11,12 @@
#include "mbr.h" #include "mbr.h"
#include "bsd.h" #include "bsd.h"
#include "gptpart.h" #include "gptpart.h"
#include "partnotes.h" #include "gptpartnotes.h"
#ifndef __GPTSTRUCTS #ifndef __GPTSTRUCTS
#define __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- // Constants used by GPTData::PartsToMBR(). MBR_EMPTY must be the lowest-
// numbered value to refer to partition numbers. (Most will be 0 or positive, // numbered value to refer to partition numbers. (Most will be 0 or positive,
@@ -29,9 +29,9 @@
#define MAX_ALIGNMENT 65536 #define MAX_ALIGNMENT 65536
#define MIN_AF_ALIGNMENT 8 #define MIN_AF_ALIGNMENT 8
// Below constant corresponds to a ~596GiB (640MB) disk, since WD has // Below constant corresponds to a ~279GiB (300GB) disk, since the
// introduced a smaller Advanced Format drive // smallest Advanced Format drive I know of is 320GB in size
#define SMALLEST_ADVANCED_FORMAT UINT64_C(1250263728) #define SMALLEST_ADVANCED_FORMAT UINT64_C(585937500)
using namespace std; using namespace std;
@@ -103,6 +103,7 @@ public:
GPTData(void); GPTData(void);
GPTData(string deviceFilename); GPTData(string deviceFilename);
virtual ~GPTData(void); virtual ~GPTData(void);
GPTData & operator=(const GPTData & orig);
// Verify (or update) data integrity // Verify (or update) data integrity
int Verify(void); int Verify(void);
@@ -118,6 +119,7 @@ public:
int FindInsanePartitions(void); int FindInsanePartitions(void);
// Load or save data from/to disk // Load or save data from/to disk
int SetFile(const string & deviceFilename);
int LoadMBR(const string & f) {return protectiveMBR.ReadMBRData(f);} int LoadMBR(const string & f) {return protectiveMBR.ReadMBRData(f);}
int WriteProtectiveMBR(void) {return protectiveMBR.WriteMBRData(&myDisk);} int WriteProtectiveMBR(void) {return protectiveMBR.WriteMBRData(&myDisk);}
void PartitionScan(void); void PartitionScan(void);
@@ -125,7 +127,7 @@ public:
int ForceLoadGPTData(void); int ForceLoadGPTData(void);
int LoadMainTable(void); int LoadMainTable(void);
int LoadSecondTableAsMain(void); int LoadSecondTableAsMain(void);
int SaveGPTData(int quiet = 0, string filename = ""); int SaveGPTData(int quiet = 0);
int SaveGPTBackup(const string & filename); int SaveGPTBackup(const string & filename);
int LoadGPTBackup(const string & filename); int LoadGPTBackup(const string & filename);
int SaveMBR(void); int SaveMBR(void);

View File

@@ -24,16 +24,12 @@
using namespace std; using namespace std;
GPTPart::GPTPart(void) { GPTPart::GPTPart(void) {
int i;
partitionType.Zero(); partitionType.Zero();
uniqueGUID.Zero(); uniqueGUID.Zero();
firstLBA = 0; firstLBA = 0;
lastLBA = 0; lastLBA = 0;
attributes = 0; attributes = 0;
memset(name, 0, NAME_SIZE);
for (i = 0; i < NAME_SIZE; i++)
name[i] = '\0';
} // Default constructor } // Default constructor
GPTPart::~GPTPart(void) { GPTPart::~GPTPart(void) {
@@ -94,35 +90,32 @@ void GPTPart::SetType(PartType t) {
// string. This function creates a simple-minded copy for this. // string. This function creates a simple-minded copy for this.
void GPTPart::SetName(const string & theName) { void GPTPart::SetName(const string & theName) {
char newName[NAME_SIZE]; char newName[NAME_SIZE];
char *junk; size_t i;
int i;
// Blank out new name string, just to be on the safe side.... // Blank out new name string, so that it will terminate in a null
for (i = 0; i < NAME_SIZE; i++) // when data are copied to it....
newName[i] = '\0'; memset(newName, 0, NAME_SIZE);
if (theName == "") { // No name specified, so get one from the user if (theName == "") { // No name specified, so get one from the user
cout << "Enter name: "; 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.... // Input is likely to include a newline, so remove it....
i = (int) strlen(newName); i = strlen(newName);
if ((i > 0) && (i <= NAME_SIZE)) if (i && newName[i - 1] == '\n')
if (newName[i - 1] == '\n') newName[i - 1] = '\0';
newName[i - 1] = '\0';
} else { } else {
strcpy(newName, theName.substr(0, NAME_SIZE / 2).c_str()); strcpy(newName, theName.substr(0, NAME_SIZE / 2).c_str());
} // if } // if
// Copy the C-style ASCII string from newName into a form that the GPT // Copy the C-style ASCII string from newName into a form that the GPT
// table will accept.... // table will accept....
for (i = 0; i < NAME_SIZE; i++) { memset(name, 0, NAME_SIZE);
if ((i % 2) == 0) { for (i = 0; i < NAME_SIZE / 2; i++)
name[i] = newName[(i / 2)]; name[i * 2] = newName[i];
} else {
name[i] = '\0';
} // if/else
} // for
} // GPTPart::SetName() } // GPTPart::SetName()
// Set the name for the partition based on the current GUID partition type // Set the name for the partition based on the current GUID partition type
@@ -132,22 +125,19 @@ void GPTPart::SetDefaultDescription(void) {
} // GPTPart::SetDefaultDescription() } // GPTPart::SetDefaultDescription()
GPTPart & GPTPart::operator=(const GPTPart & orig) { GPTPart & GPTPart::operator=(const GPTPart & orig) {
int i;
partitionType = orig.partitionType; partitionType = orig.partitionType;
uniqueGUID = orig.uniqueGUID; uniqueGUID = orig.uniqueGUID;
firstLBA = orig.firstLBA; firstLBA = orig.firstLBA;
lastLBA = orig.lastLBA; lastLBA = orig.lastLBA;
attributes = orig.attributes; attributes = orig.attributes;
for (i = 0; i < NAME_SIZE; i++) memcpy(name, orig.name, NAME_SIZE);
name[i] = orig.name[i];
return *this; return *this;
} // assignment operator } // assignment operator
// Display summary information; does nothing if the partition is empty. // Display summary information; does nothing if the partition is empty.
void GPTPart::ShowSummary(int partNum, uint32_t blockSize) { void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
string sizeInSI; string sizeInSI;
int i; size_t i;
if (firstLBA != 0) { if (firstLBA != 0) {
sizeInSI = BytesToSI(lastLBA - firstLBA + 1, blockSize); sizeInSI = BytesToSI(lastLBA - firstLBA + 1, blockSize);
@@ -159,7 +149,7 @@ void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
cout.width(14); cout.width(14);
cout << lastLBA << " "; cout << lastLBA << " ";
cout << BytesToSI(lastLBA - firstLBA + 1, blockSize) << " "; 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 << " ";
cout.fill('0'); cout.fill('0');
cout.width(4); cout.width(4);
@@ -201,30 +191,21 @@ void GPTPart::ShowDetails(uint32_t blockSize) {
// Blank (delete) a single partition // Blank (delete) a single partition
void GPTPart::BlankPartition(void) { void GPTPart::BlankPartition(void) {
int j;
uniqueGUID.Zero(); uniqueGUID.Zero();
partitionType.Zero(); partitionType.Zero();
firstLBA = 0; firstLBA = 0;
lastLBA = 0; lastLBA = 0;
attributes = 0; attributes = 0;
for (j = 0; j < NAME_SIZE; j++) memset(name, 0, NAME_SIZE);
name[j] = '\0';
} // GPTPart::BlankPartition } // GPTPart::BlankPartition
// Returns 1 if the two partitions overlap, 0 if they don't // Returns 1 if the two partitions overlap, 0 if they don't
int GPTPart::DoTheyOverlap(const GPTPart & other) { int GPTPart::DoTheyOverlap(const GPTPart & other) {
int theyDo = 0;
// Don't bother checking unless these are defined (both start and end points // Don't bother checking unless these are defined (both start and end points
// are 0 for undefined partitions, so just check the start points) // are 0 for undefined partitions, so just check the start points)
if ((firstLBA != 0) && (other.firstLBA != 0)) { // cout << "Entering GPTPart::DoTheyOverlap()\n";
if ((firstLBA < other.lastLBA) && (lastLBA >= other.firstLBA)) return firstLBA && other.firstLBA &&
theyDo = 1; (firstLBA <= other.lastLBA) != (lastLBA < other.firstLBA);
if ((other.firstLBA < lastLBA) && (other.lastLBA >= firstLBA))
theyDo = 1;
} // if
return (theyDo);
} // GPTPart::DoTheyOverlap() } // GPTPart::DoTheyOverlap()
// Reverse the bytes of integral data types; used on big-endian systems. // 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. // name is the generic one for the partition type.
void GPTPart::ChangeType(void) { void GPTPart::ChangeType(void) {
char line[255]; char line[255];
char* junk; int changeName;
unsigned int changeName = 0;
PartType tempType = (GUIDData) "00000000-0000-0000-0000-000000000000"; PartType tempType = (GUIDData) "00000000-0000-0000-0000-000000000000";
if (GetDescription() == GetTypeName()) changeName = (GetDescription() == GetTypeName());
changeName = UINT16_C(1);
cout << "Current type is '" << GetTypeName() << "'\n"; cout << "Current type is '" << GetTypeName() << "'\n";
do { do {
cout << "Hex code or GUID (L to show codes, Enter = 0700): "; 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')) { if ((line[0] == 'L') || (line[0] == 'l')) {
partitionType.ShowAllTypes(); partitionType.ShowAllTypes();
} else { } else {

View File

@@ -29,7 +29,7 @@
#include <cstdio> #include <cstdio>
#include "attributes.h" #include "attributes.h"
#include "gpttext.h" #include "gpttext.h"
#include "partnotes.h" #include "gptpartnotes.h"
#include "support.h" #include "support.h"
using namespace std; using namespace std;
@@ -353,7 +353,6 @@ void GPTDataTextUI::ShowDetails(void) {
void GPTDataTextUI::MakeHybrid(void) { void GPTDataTextUI::MakeHybrid(void) {
uint32_t partNums[3]; uint32_t partNums[3];
char line[255]; char line[255];
char* junk;
int numPartsToCvt, i, j, mbrNum, bootable = 0; int numPartsToCvt, i, j, mbrNum, bootable = 0;
unsigned int hexCode = 0; unsigned int hexCode = 0;
struct PartInfo *newNote; struct PartInfo *newNote;
@@ -368,7 +367,10 @@ void GPTDataTextUI::MakeHybrid(void) {
// hybrid MBR.... // hybrid MBR....
cout << "Type from one to three GPT partition numbers, separated by spaces, to be\n" cout << "Type from one to three GPT partition numbers, separated by spaces, to be\n"
<< "added to the hybrid MBR, in sequence: "; << "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]); numPartsToCvt = sscanf(line, "%d %d %d", &partNums[0], &partNums[1], &partNums[2]);
if (numPartsToCvt > 0) { if (numPartsToCvt > 0) {
@@ -378,7 +380,7 @@ void GPTDataTextUI::MakeHybrid(void) {
for (i = 0; i < numPartsToCvt; i++) { for (i = 0; i < numPartsToCvt; i++) {
newNote = new struct PartInfo; newNote = new struct PartInfo;
j = newNote->gptPartNum = partNums[i] - 1; j = newNote->origPartNum = partNums[i] - 1;
if (partitions[j].IsUsed()) { if (partitions[j].IsUsed()) {
mbrNum = i + (eeFirst == 'Y'); mbrNum = i + (eeFirst == 'Y');
cout << "\nCreating entry for GPT partition #" << j + 1 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, // If this location (covering the main GPT data structures) is omitted,
// Linux won't find any partitions on the disk. // Linux won't find any partitions on the disk.
newNote = new struct PartInfo; newNote = new struct PartInfo;
newNote->gptPartNum = MBR_EFI_GPT; newNote->origPartNum = MBR_EFI_GPT;
newNote->firstLBA = 1; newNote->firstLBA = 1;
newNote->active = 0; newNote->active = 0;
newNote->hexCode = 0xEE; 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): "; 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 // Comment on above: Mac OS treats disks with more than one
// 0xEE MBR partition as MBR disks, not as GPT disks. // 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); sscanf(line, "%x", &hexCode);
if (line[0] == '\n') if (line[0] == '\n')
hexCode = 0x00; hexCode = 0x00;
} // while } // while
newNote = new struct PartInfo; newNote = new struct PartInfo;
newNote->gptPartNum = MBR_EFI_GPT; newNote->origPartNum = MBR_EFI_GPT;
newNote->active = 0; newNote->active = 0;
newNote->hexCode = hexCode; newNote->hexCode = hexCode;
newNote->type = PRIMARY; newNote->type = PRIMARY;
@@ -452,7 +457,7 @@ void GPTDataTextUI::MakeHybrid(void) {
// possible, but gives the user the option to override this suggestion. // possible, but gives the user the option to override this suggestion.
// Returns the number of partitions assigned (0 if problems or if the // Returns the number of partitions assigned (0 if problems or if the
// user aborts) // 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 i, partNum, allOK = 1, changesWanted = 1, countedParts, numPrimary = 0, numLogical = 0;
int newNumParts; // size of GPT table int newNumParts; // size of GPT table
@@ -527,7 +532,7 @@ int GPTDataTextUI::AssignPrimaryOrLogical(PartNotes & notes) {
int GPTDataTextUI::XFormToMBR(void) { int GPTDataTextUI::XFormToMBR(void) {
int numToConvert, numReallyConverted = 0; int numToConvert, numReallyConverted = 0;
int origNumParts; int origNumParts;
PartNotes notes; GptPartNotes notes;
GPTPart *tempGptParts; GPTPart *tempGptParts;
uint32_t i; uint32_t i;
@@ -576,7 +581,6 @@ int GPTDataTextUI::XFormToMBR(void) {
// Get an MBR type code from the user and return it // Get an MBR type code from the user and return it
int GetMBRTypeCode(int defType) { int GetMBRTypeCode(int defType) {
char line[255]; char line[255];
char* junk;
int typeCode; int typeCode;
cout.setf(ios::uppercase); cout.setf(ios::uppercase);
@@ -585,7 +589,10 @@ int GetMBRTypeCode(int defType) {
cout << "Enter an MBR hex code (default " << hex; cout << "Enter an MBR hex code (default " << hex;
cout.width(2); cout.width(2);
cout << defType << "): " << dec; 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') if (line[0] == '\n')
typeCode = defType; typeCode = defType;
else else

View File

@@ -50,7 +50,7 @@ class GPTDataTextUI : public GPTData {
int DestroyGPTwPrompt(void); // Returns 1 if user proceeds int DestroyGPTwPrompt(void); // Returns 1 if user proceeds
void ShowDetails(void); void ShowDetails(void);
void MakeHybrid(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 int XFormToMBR(void); // convert GPT to MBR, wiping GPT afterwards. Returns 1 if successful
}; // class GPTDataTextUI }; // class GPTDataTextUI

26
guid.cc
View File

@@ -16,6 +16,7 @@
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <string.h>
#include <string> #include <string>
#include <iostream> #include <iostream>
#include "guid.h" #include "guid.h"
@@ -29,10 +30,7 @@ GUIDData::GUIDData(void) {
} // constructor } // constructor
GUIDData::GUIDData(const GUIDData & orig) { GUIDData::GUIDData(const GUIDData & orig) {
int i; memcpy(uuidData, orig.uuidData, sizeof(uuidData));
for (i = 0; i < 16; i++)
uuidData[i] = orig.uuidData[i];
} // copy constructor } // copy constructor
GUIDData::GUIDData(const char * orig) { GUIDData::GUIDData(const char * orig) {
@@ -43,10 +41,7 @@ GUIDData::~GUIDData(void) {
} // destructor } // destructor
GUIDData & GUIDData::operator=(const GUIDData & orig) { GUIDData & GUIDData::operator=(const GUIDData & orig) {
int i; memcpy(uuidData, orig.uuidData, sizeof(uuidData));
for (i = 0; i < 16; i++)
uuidData[i] = orig.uuidData[i];
return *this; return *this;
} // GUIDData::operator=(const GUIDData & orig) } // GUIDData::operator=(const GUIDData & orig)
@@ -123,11 +118,7 @@ GUIDData & GUIDData::operator=(const char * orig) {
// Erase the contents of the GUID // Erase the contents of the GUID
void GUIDData::Zero(void) { void GUIDData::Zero(void) {
int i; memset(uuidData, 0, sizeof(uuidData));
for (i = 0; i < 16; i++) {
uuidData[i] = 0;
} // for
} // GUIDData::Zero() } // GUIDData::Zero()
// Set a completely random GUID value.... // 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 // Equality operator; returns 1 if the GUIDs are equal, 0 if they're unequal
int GUIDData::operator==(const GUIDData & orig) const { int GUIDData::operator==(const GUIDData & orig) const {
int retval = 1; // assume they're equal return !memcmp(uuidData, orig.uuidData, sizeof(uuidData));
int i;
for (i = 0; i < 16; i++)
if (uuidData[i] != orig.uuidData[i])
retval = 0;
return retval;
} // GUIDData::operator== } // GUIDData::operator==
// Inequality operator; returns 1 if the GUIDs are unequal, 0 if they're equal // Inequality operator; returns 1 if the GUIDs are unequal, 0 if they're equal

2
guid.h
View File

@@ -22,7 +22,7 @@
#ifdef _WIN32 #ifdef _WIN32
typedef unsigned char my_uuid_t[16]; typedef unsigned char my_uuid_t[16];
#else #else
#include </usr/include/uuid/uuid.h> #include <uuid/uuid.h>
typedef uuid_t my_uuid_t; typedef uuid_t my_uuid_t;
#endif #endif

964
mbr.cc

File diff suppressed because it is too large Load Diff

118
mbr.h
View File

@@ -6,23 +6,16 @@
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include "gptpart.h" #include "gptpart.h"
#include "partnotes.h" //#include "partnotes.h"
#include "diskio.h" #include "diskio.h"
#include "basicmbr.h"
#ifndef __MBRSTRUCTS #ifndef __MBRSTRUCTS
#define __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; 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 // Full data in tweaked MBR format
class MBRData { class MBRData : public BasicMBRData {
protected: protected:
uint8_t code[440]; int foo;
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
public: public:
MBRData(void); MBRData(void) {}
MBRData(string deviceFilename); MBRData(string deviceFilename) : BasicMBRData(deviceFilename) {}
~MBRData(void); MBRData & operator=(const MBRData & orig);
// 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);
// Functions to create, delete, or change partitions // Functions to create, delete, or change partitions
// Pass EmptyMBR 1 to clear the boot loader code, 0 to leave it intact // Pass EmptyMBR 1 to clear the boot loader code, 0 to leave it intact
void EmptyMBR(int clearBootloader = 1);
void EmptyBootloader(void);
void MakeProtectiveMBR(int clearBoot = 0); void MakeProtectiveMBR(int clearBoot = 0);
void MakePart(int num, uint32_t startLBA, uint32_t lengthLBA, int type = 0x07,
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 OptimizeEESize(void);
void RecomputeCHS(int partNum); int DeleteByLocation(uint64_t start64, uint64_t length64);
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);
// Functions to extract data on specific partitions.... // 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); GPTPart AsGPT(int i);
}; // struct MBRData }; // struct MBRData

View File

@@ -29,21 +29,16 @@ PartNotes::PartNotes() {
notes = NULL; notes = NULL;
currentNote = NULL; currentNote = NULL;
currentIndex = 0; currentIndex = 0;
gptParts = NULL; origTableSize = 0;
gptTableSize = 0;
blockSize = 512; blockSize = 512;
dummyNote.active = 0; dummyNote.active = 0;
dummyNote.gptPartNum = MBR_EMPTY; dummyNote.origPartNum = MBR_EMPTY;
dummyNote.hexCode = 0xEE; dummyNote.hexCode = 0xEE;
dummyNote.next = NULL; dummyNote.next = NULL;
dummyNote.spaceBefore = 0; dummyNote.spaceBefore = 0;
dummyNote.type = WILL_NOT_CONVERT; dummyNote.type = WILL_NOT_CONVERT;
} // PartNotes constructor } // 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 // 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. // store a pointer to an array that's allocated by the calling function.
PartNotes::~PartNotes() { 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. // Add a single partition to the end of the linked list.
// Returns 1 on success, 0 on failures. // Returns 1 on success, 0 on failures.
int PartNotes::AddToEnd(struct PartInfo *newOne) { int PartNotes::AddToEnd(struct PartInfo *newOne) {
@@ -344,10 +286,10 @@ uint8_t PartNotes::GetMbrHexType(int partNum) {
} // if/else } // if/else
} // PartNotes::GetMBRHexType() } // PartNotes::GetMBRHexType()
// Return the GPT partition number associated with this note, -1 if // Return the original partition number associated with this note, -1 if
// the notes list is empty, or the GPT partition number of the last // the notes list is empty, or the original partition number of the last
// partition if partNum is too high. // partition if partNum is too high.
int PartNotes::GetGptNum(int partNum) { int PartNotes::GetOrigNum(int partNum) {
int count = 0; int count = 0;
struct PartInfo *theNote; struct PartInfo *theNote;
@@ -355,11 +297,11 @@ int PartNotes::GetGptNum(int partNum) {
if (theNote != NULL) { if (theNote != NULL) {
while ((count++ < partNum) && (theNote->next != NULL)) while ((count++ < partNum) && (theNote->next != NULL))
theNote = theNote->next; theNote = theNote->next;
return theNote->gptPartNum; return theNote->origPartNum;
} else { } else {
return -1; return -1;
} // if/else } // if/else
} // PartNotes::GetGptNum() } // PartNotes::GetOrigNum()
// Return whether or not the partition is flagged as active (bootable) // Return whether or not the partition is flagged as active (bootable)
int PartNotes::GetActiveStatus(int partNum) { int PartNotes::GetActiveStatus(int partNum) {
@@ -417,23 +359,6 @@ int PartNotes::FindExtended(int &start) {
return length; return length;
} // PartNotes::FindExtended() } // 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 // Returns 1 if the set as a whole makes a legal MBR partition table
// (possibly with logicals), 0 if not // (possibly with logicals), 0 if not
int PartNotes::IsLegal(void) { int PartNotes::IsLegal(void) {
@@ -557,7 +482,7 @@ void PartNotes::TrimSmallestExtended() {
} // for } // for
// Find the smallest extended partition.... // Find the smallest extended partition....
shortestNum = gptTableSize + 1; shortestNum = origTableSize + 1;
for (i = 0; i < numExtended; i++) { for (i = 0; i < numExtended; i++) {
if (extendeds[i].numLogicals < shortestNum) { if (extendeds[i].numLogicals < shortestNum) {
shortestNum = extendeds[i].numLogicals; shortestNum = extendeds[i].numLogicals;
@@ -593,57 +518,8 @@ void PartNotes::TrimSmallestExtended() {
// Display summary information for the user // Display summary information for the user
void PartNotes::ShowSummary(void) { void PartNotes::ShowSummary(void) {
int j; cerr << "Program is calling PartNotes::ShowSummary(); this is a virtual base function,\n"
string sizeInSI; << "and should never be called.\n";
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
} // PartNotes::ShowSummary() } // PartNotes::ShowSummary()
// Interact with the user to create a change in the specified // 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 PartNotes::MakeChange(int partNum) {
int allOK = 1; int allOK = 1;
int type = 0; int type = 0;
char *junk;
char line[255], command; char line[255], command;
if (notes != NULL) { if (notes != NULL) {
@@ -676,7 +551,10 @@ int PartNotes::MakeChange(int partNum) {
} // switch } // switch
cout << " t - change MBR type code\n"; cout << " t - change MBR type code\n";
cout << "Action: "; 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); sscanf(line, "%c", &command);
switch (command) { switch (command) {
case 'a': case 'A': case 'a': case 'A':
@@ -694,7 +572,10 @@ int PartNotes::MakeChange(int partNum) {
case 't': case 'T': case 't': case 'T':
while (type == 0) { while (type == 0) {
cout << "Enter a 2-byte hexadecimal MBR type code: "; 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); sscanf(line, "%x", &type);
} // while } // while
SetMbrHexType(partNum, (uint8_t) type); SetMbrHexType(partNum, (uint8_t) type);
@@ -711,7 +592,7 @@ int PartNotes::MakeChange(int partNum) {
// Returns 1 unless there's a dire bug. // Returns 1 unless there's a dire bug.
int PartNotes::ChangeType(int partNum, int newType) { int PartNotes::ChangeType(int partNum, int newType) {
int origType, allOK = 1; int origType, allOK = 1;
char *junk, line[255]; char line[255];
if ((notes != NULL) && IsLegal()) { if ((notes != NULL) && IsLegal()) {
origType = GetType(partNum); origType = GetType(partNum);
@@ -733,7 +614,10 @@ int PartNotes::ChangeType(int partNum, int newType) {
<< "another\norder, such as deleting partitions before changing others' " << "another\norder, such as deleting partitions before changing others' "
<< "types.\n"; << "types.\n";
cout << "\nReverting change.\nPress <Enter> to continue: "; 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); SetType(partNum, origType);
} // if } // if
} else allOK = 0; // if } else allOK = 0; // if

View File

@@ -1,6 +1,6 @@
/* /*
partnotes.h -- Class that takes notes on GPT partitions for purpose of MBR conversion 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 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 it under the terms of the GNU General Public License as published by
@@ -21,8 +21,8 @@
#ifndef __PARTNOTES_H #ifndef __PARTNOTES_H
#define __PARTNOTES_H #define __PARTNOTES_H
#include "gpt.h" #include <stdint.h>
#include "gptpart.h" #include <sys/types.h>
using namespace std; using namespace std;
@@ -33,7 +33,7 @@ using namespace std;
// Data structure used in GPT-to-MBR conversions; holds pointer to GPT // Data structure used in GPT-to-MBR conversions; holds pointer to GPT
// partition number, start and end sectors, and a few MBR-specific details // partition number, start and end sectors, and a few MBR-specific details
struct PartInfo { struct PartInfo {
int gptPartNum; int origPartNum;
int spaceBefore; // boolean; if 1, can theoretically become a logical part. int spaceBefore; // boolean; if 1, can theoretically become a logical part.
int active; // boolean int active; // boolean
int type; // WILL_NOT_CONVERT, PRIMARY, or LOGICAL int type; // WILL_NOT_CONVERT, PRIMARY, or LOGICAL
@@ -54,22 +54,21 @@ class PartNotes {
struct PartInfo *notes; struct PartInfo *notes;
struct PartInfo *currentNote; struct PartInfo *currentNote;
int currentIndex; int currentIndex;
GPTPart *gptParts;
int gptTableSize;
int blockSize; int blockSize;
int origTableSize;
void DeleteNotes(void); void DeleteNotes(void);
public: public:
PartNotes(); PartNotes();
PartNotes(GPTPart *parts, GPTData *gpt, int num, int blockSize);
~PartNotes(); ~PartNotes();
// Add partition notes (little or no error checking) // 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 AddToEnd(struct PartInfo* newOne);
int AddToStart(struct PartInfo* newOne); int AddToStart(struct PartInfo* newOne);
void SetType(int partNum, int type); // type is PRIMARY, LOGICAL, or WILL_NOT_CONVERT 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); void ToggleActiveStatus(int partNum);
// Retrieve data or metadata // Retrieve data or metadata
@@ -81,12 +80,11 @@ class PartNotes {
int GetNumLogical(); int GetNumLogical();
int GetType(int partNum); int GetType(int partNum);
uint8_t GetMbrHexType(int i); uint8_t GetMbrHexType(int i);
int GetGptNum(int partNum); int GetOrigNum(int partNum);
int GetActiveStatus(int partNum); int GetActiveStatus(int partNum);
int CanBeLogical(int partNum); // returns boolean int CanBeLogical(int partNum); // returns boolean
int FindExtended(int &start); int FindExtended(int &start);
int IsSorted(void); int IsLegal(void); // returns Boolean
int IsLegal(void); // returns boolean
// Manipulate data or metadata // Manipulate data or metadata
void RemoveDuplicates(void); void RemoveDuplicates(void);
@@ -94,7 +92,7 @@ class PartNotes {
void TrimSmallestExtended(void); void TrimSmallestExtended(void);
// Interact with users, possibly changing data with error handling // Interact with users, possibly changing data with error handling
void ShowSummary(void); virtual void ShowSummary(void);
int MakeChange(int partNum); int MakeChange(int partNum);
int ChangeType(int partNum, int newType); int ChangeType(int partNum, int newType);
}; };

View File

@@ -2,7 +2,7 @@
// Class to manage partition type codes -- a slight variant on MBR type // Class to manage partition type codes -- a slight variant on MBR type
// codes, GUID type codes, and associated names. // 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. */ under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
#define __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS
@@ -163,7 +163,7 @@ void PartType::AddAllTypes(void) {
AddType(0xc002, "E2A1E728-32E3-11D6-A682-7B03A0000000", "HP-UX service"); AddType(0xc002, "E2A1E728-32E3-11D6-A682-7B03A0000000", "HP-UX service");
// EFI system and related partitions // 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(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 AddType(0xef02, "21686148-6449-6E6F-744E-656564454649", "BIOS boot partition"); // Boot loader

View File

@@ -570,6 +570,8 @@ Contributors:
* Dwight Schauer (dschauer@ti.com) * Dwight Schauer (dschauer@ti.com)
* Florian Zumbiehl (florz@florz.de)
.SH "SEE ALSO" .SH "SEE ALSO"
\fBcfdisk (8)\fR, \fBcfdisk (8)\fR,

View File

@@ -6,7 +6,7 @@
// //
// by Rod Smith, project began February 2009; sgdisk begun January 2010. // 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. */ under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
#include <stdio.h> #include <stdio.h>
@@ -20,6 +20,7 @@
#include "gpt.h" #include "gpt.h"
#include "support.h" #include "support.h"
#include "parttypes.h" #include "parttypes.h"
#include "gptpartnotes.h"
#include "attributes.h" #include "attributes.h"
using namespace std; using namespace std;
@@ -30,7 +31,7 @@ int BuildMBR(GPTData& theGPT, char* argument, int isHybrid);
int CountColons(char* argument); int CountColons(char* argument);
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
GPTData theGPT; GPTData theGPT, secondDevice;
uint32_t sSize; uint32_t sSize;
uint64_t low, high; uint64_t low, high;
int opt, numOptions = 0, saveData = 0, neverSaveData = 0; int opt, numOptions = 0, saveData = 0, neverSaveData = 0;
@@ -231,9 +232,10 @@ int main(int argc, char *argv[]) {
theGPT.ShowPartDetails(infoPartNum - 1); theGPT.ShowPartDetails(infoPartNum - 1);
break; break;
case 'l': case 'l':
if (theGPT.LoadGPTBackup((string) backupFile) == 1) if (theGPT.LoadGPTBackup((string) backupFile) == 1) {
theGPT.JustLooking(0);
saveData = 1; saveData = 1;
else { } else {
saveData = 0; saveData = 0;
neverSaveData = 1; neverSaveData = 1;
cerr << "Error loading backup file!\n"; cerr << "Error loading backup file!\n";
@@ -309,8 +311,11 @@ int main(int argc, char *argv[]) {
} else saveData = 1; } else saveData = 1;
break; break;
case 'R': case 'R':
theGPT.JustLooking(0); secondDevice = theGPT;
theGPT.SaveGPTData(1, outDevice); secondDevice.SetFile(outDevice);
secondDevice.JustLooking(0);
// secondDevice.FixupMBR();
secondDevice.SaveGPTData(1);
break; break;
case 's': case 's':
theGPT.JustLooking(0); theGPT.JustLooking(0);
@@ -424,7 +429,7 @@ int main(int argc, char *argv[]) {
// Create a hybrid or regular MBR from GPT data structures // Create a hybrid or regular MBR from GPT data structures
int BuildMBR(GPTData & theGPT, char* argument, int isHybrid) { int BuildMBR(GPTData & theGPT, char* argument, int isHybrid) {
int numParts, allOK = 1, i; int numParts, allOK = 1, i;
PartNotes notes; GptPartNotes notes;
struct PartInfo *newNote; struct PartInfo *newNote;
if ((&theGPT != NULL) && (argument != NULL)) { if ((&theGPT != NULL) && (argument != NULL)) {
@@ -432,17 +437,17 @@ int BuildMBR(GPTData & theGPT, char* argument, int isHybrid) {
if (numParts <= (4 - isHybrid)) { if (numParts <= (4 - isHybrid)) {
for (i = 0; i < numParts; i++) { for (i = 0; i < numParts; i++) {
newNote = new struct PartInfo; newNote = new struct PartInfo;
newNote->gptPartNum = GetInt(argument, i + 1) - 1; newNote->origPartNum = GetInt(argument, i + 1) - 1;
newNote->active = 0; newNote->active = 0;
newNote->hexCode = 0; // code to compute it from default newNote->hexCode = 0; // code to compute it from default
newNote->type = PRIMARY; newNote->type = PRIMARY;
newNote->firstLBA = theGPT[newNote->gptPartNum].GetFirstLBA(); newNote->firstLBA = theGPT[newNote->origPartNum].GetFirstLBA();
newNote->lastLBA = theGPT[newNote->gptPartNum].GetLastLBA(); newNote->lastLBA = theGPT[newNote->origPartNum].GetLastLBA();
notes.AddToEnd(newNote); notes.AddToEnd(newNote);
} // for } // for
if (isHybrid) { if (isHybrid) {
newNote = new struct PartInfo; newNote = new struct PartInfo;
newNote->gptPartNum = MBR_EFI_GPT; newNote->origPartNum = MBR_EFI_GPT;
newNote->active = 0; newNote->active = 0;
newNote->hexCode = 0xEE; newNote->hexCode = 0xEE;
newNote->type = PRIMARY; newNote->type = PRIMARY;

View File

@@ -63,11 +63,13 @@ int GetNumber(int low, int high, int def, const string & prompt) {
char GetYN(void) { char GetYN(void) {
char line[255]; char line[255];
char response; char response;
char *junk;
do { do {
cout << "(Y/N): "; 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); sscanf(line, "%c", &response);
if (response == 'y') if (response == 'y')
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 // Extract integer data from argument string, which should be colon-delimited
uint64_t GetInt(const string & argument, int itemNum) { uint64_t GetInt(const string & argument, int itemNum) {
int startPos = -1, endPos = -1; uint64_t retval;
uint64_t retval = 0;
while (itemNum-- > 0) { istringstream inString(GetString(argument, itemNum));
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));
inString >> retval; inString >> retval;
return retval; return retval;
} // GetInt() } // GetInt()
// Extract string data from argument string, which should be colon-delimited // Extract string data from argument string, which should be colon-delimited
string GetString(const string & argument, int itemNum) { string GetString(const string & argument, int itemNum) {
int startPos = -1, endPos = -1; size_t startPos = -1, endPos = -1;
while (itemNum-- > 0) { while (itemNum-- > 0) {
startPos = endPos + 1; startPos = endPos + 1;
endPos = (int) argument.find(':', startPos); endPos = argument.find(':', startPos);
} }
if (endPos == (int) string::npos) if (endPos == string::npos)
endPos = (int) argument.length(); endPos = argument.length();
endPos--; endPos--;
return argument.substr(startPos, endPos - startPos + 1); return argument.substr(startPos, endPos - startPos + 1);