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
CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64
LDFLAGS+=
LIB_NAMES=crc32 support guid partnotes gptpart mbr gpt bsd parttypes attributes diskio diskio-unix
LIB_NAMES=crc32 support guid partnotes gptpartnotes gptpart basicmbr mbr gpt bsd parttypes attributes diskio diskio-unix
LIB_SRCS=$(NAMES:=.cc)
LIB_OBJS=$(LIB_NAMES:=.o)
LIB_HEADERS=$(LIB_NAMES:=.h)
@@ -31,3 +31,355 @@ $(OBJS):
$(CRITICAL_CXX_FLAGS)
# DO NOT DELETE
attributes.o: /usr/include/stdint.h /usr/include/features.h
attributes.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
attributes.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
attributes.o: /usr/include/bits/wchar.h /usr/include/stdio.h
attributes.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
attributes.o: /usr/include/libio.h /usr/include/_G_config.h
attributes.o: /usr/include/wchar.h /usr/include/bits/stdio_lim.h
attributes.o: /usr/include/bits/sys_errlist.h attributes.h support.h
attributes.o: /usr/include/stdlib.h /usr/include/sys/types.h
attributes.o: /usr/include/time.h /usr/include/endian.h
attributes.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
attributes.o: /usr/include/sys/select.h /usr/include/bits/select.h
attributes.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
attributes.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
attributes.o: /usr/include/alloca.h
bsd.o: /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h
bsd.o: /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h
bsd.o: /usr/include/gnu/stubs-64.h /usr/include/bits/types.h
bsd.o: /usr/include/bits/typesizes.h /usr/include/libio.h
bsd.o: /usr/include/_G_config.h /usr/include/wchar.h
bsd.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
bsd.o: /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h
bsd.o: /usr/include/endian.h /usr/include/bits/endian.h
bsd.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
bsd.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
bsd.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
bsd.o: /usr/include/bits/pthreadtypes.h /usr/include/alloca.h
bsd.o: /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/fcntl.h
bsd.o: /usr/include/bits/fcntl.h /usr/include/sys/stat.h
bsd.o: /usr/include/bits/stat.h /usr/include/errno.h
bsd.o: /usr/include/bits/errno.h /usr/include/linux/errno.h
bsd.o: /usr/include/asm/errno.h /usr/include/asm-generic/errno.h
bsd.o: /usr/include/asm-generic/errno-base.h support.h bsd.h gptpart.h
bsd.o: parttypes.h guid.h /usr/include/uuid/uuid.h /usr/include/sys/time.h
bsd.o: attributes.h diskio.h /usr/include/sys/ioctl.h
bsd.o: /usr/include/bits/ioctls.h /usr/include/asm/ioctls.h
bsd.o: /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h
bsd.o: /usr/include/asm/ioctl.h /usr/include/asm-generic/ioctl.h
bsd.o: /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h
crc32.o: /usr/include/stdio.h /usr/include/features.h
crc32.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
crc32.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
crc32.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
crc32.o: /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h
crc32.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
crc32.o: /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h
crc32.o: /usr/include/endian.h /usr/include/bits/endian.h
crc32.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
crc32.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
crc32.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
crc32.o: /usr/include/bits/pthreadtypes.h /usr/include/alloca.h crc32.h
crc32.o: /usr/include/stdint.h /usr/include/bits/wchar.h
diskio.o: /usr/include/sys/ioctl.h /usr/include/features.h
diskio.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
diskio.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
diskio.o: /usr/include/bits/ioctls.h /usr/include/asm/ioctls.h
diskio.o: /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h
diskio.o: /usr/include/asm/ioctl.h /usr/include/asm-generic/ioctl.h
diskio.o: /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h
diskio.o: /usr/include/stdint.h /usr/include/bits/wchar.h
diskio.o: /usr/include/errno.h /usr/include/bits/errno.h
diskio.o: /usr/include/linux/errno.h /usr/include/asm/errno.h
diskio.o: /usr/include/asm-generic/errno.h
diskio.o: /usr/include/asm-generic/errno-base.h /usr/include/fcntl.h
diskio.o: /usr/include/bits/fcntl.h /usr/include/sys/types.h
diskio.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
diskio.o: /usr/include/time.h /usr/include/endian.h
diskio.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
diskio.o: /usr/include/sys/select.h /usr/include/bits/select.h
diskio.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
diskio.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
diskio.o: /usr/include/sys/stat.h /usr/include/bits/stat.h support.h
diskio.o: /usr/include/stdlib.h /usr/include/alloca.h diskio.h parttypes.h
diskio.o: guid.h /usr/include/uuid/uuid.h /usr/include/sys/time.h gpt.h
diskio.o: gptpart.h attributes.h mbr.h partnotes.h bsd.h
diskio-unix.o: /usr/include/sys/ioctl.h /usr/include/features.h
diskio-unix.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
diskio-unix.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
diskio-unix.o: /usr/include/bits/ioctls.h /usr/include/asm/ioctls.h
diskio-unix.o: /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h
diskio-unix.o: /usr/include/asm/ioctl.h /usr/include/asm-generic/ioctl.h
diskio-unix.o: /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h
diskio-unix.o: /usr/include/string.h /usr/include/xlocale.h
diskio-unix.o: /usr/include/stdint.h /usr/include/bits/wchar.h
diskio-unix.o: /usr/include/errno.h /usr/include/bits/errno.h
diskio-unix.o: /usr/include/linux/errno.h /usr/include/asm/errno.h
diskio-unix.o: /usr/include/asm-generic/errno.h
diskio-unix.o: /usr/include/asm-generic/errno-base.h /usr/include/fcntl.h
diskio-unix.o: /usr/include/bits/fcntl.h /usr/include/sys/types.h
diskio-unix.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
diskio-unix.o: /usr/include/time.h /usr/include/endian.h
diskio-unix.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
diskio-unix.o: /usr/include/sys/select.h /usr/include/bits/select.h
diskio-unix.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
diskio-unix.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
diskio-unix.o: /usr/include/sys/stat.h /usr/include/bits/stat.h diskio.h
diskio-unix.o: support.h /usr/include/stdlib.h /usr/include/alloca.h
diskio-unix.o: parttypes.h guid.h /usr/include/uuid/uuid.h
diskio-unix.o: /usr/include/sys/time.h
diskio-windows.o: /usr/include/stdio.h /usr/include/features.h
diskio-windows.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
diskio-windows.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
diskio-windows.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
diskio-windows.o: /usr/include/libio.h /usr/include/_G_config.h
diskio-windows.o: /usr/include/wchar.h /usr/include/bits/stdio_lim.h
diskio-windows.o: /usr/include/bits/sys_errlist.h /usr/include/stdint.h
diskio-windows.o: /usr/include/bits/wchar.h /usr/include/errno.h
diskio-windows.o: /usr/include/bits/errno.h /usr/include/linux/errno.h
diskio-windows.o: /usr/include/asm/errno.h /usr/include/asm-generic/errno.h
diskio-windows.o: /usr/include/asm-generic/errno-base.h /usr/include/fcntl.h
diskio-windows.o: /usr/include/bits/fcntl.h /usr/include/sys/types.h
diskio-windows.o: /usr/include/time.h /usr/include/endian.h
diskio-windows.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
diskio-windows.o: /usr/include/sys/select.h /usr/include/bits/select.h
diskio-windows.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
diskio-windows.o: /usr/include/sys/sysmacros.h
diskio-windows.o: /usr/include/bits/pthreadtypes.h /usr/include/sys/stat.h
diskio-windows.o: /usr/include/bits/stat.h support.h /usr/include/stdlib.h
diskio-windows.o: /usr/include/alloca.h diskio.h /usr/include/sys/ioctl.h
diskio-windows.o: /usr/include/bits/ioctls.h /usr/include/asm/ioctls.h
diskio-windows.o: /usr/include/asm-generic/ioctls.h
diskio-windows.o: /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h
diskio-windows.o: /usr/include/asm-generic/ioctl.h
diskio-windows.o: /usr/include/bits/ioctl-types.h
diskio-windows.o: /usr/include/sys/ttydefaults.h parttypes.h guid.h
diskio-windows.o: /usr/include/uuid/uuid.h /usr/include/sys/time.h
gdisk.o: /usr/include/stdio.h /usr/include/features.h
gdisk.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
gdisk.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
gdisk.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
gdisk.o: /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h
gdisk.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
gdisk.o: /usr/include/string.h /usr/include/xlocale.h mbr.h
gdisk.o: /usr/include/stdint.h /usr/include/bits/wchar.h
gdisk.o: /usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h
gdisk.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
gdisk.o: /usr/include/sys/select.h /usr/include/bits/select.h
gdisk.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
gdisk.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
gdisk.o: gptpart.h support.h /usr/include/stdlib.h /usr/include/alloca.h
gdisk.o: parttypes.h guid.h /usr/include/uuid/uuid.h /usr/include/sys/time.h
gdisk.o: attributes.h partnotes.h gpt.h bsd.h diskio.h
gdisk.o: /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h
gdisk.o: /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h
gdisk.o: /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h
gdisk.o: /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h
gdisk.o: /usr/include/sys/ttydefaults.h gpttext.h
gpt.o: /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h
gpt.o: /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h
gpt.o: /usr/include/gnu/stubs-64.h /usr/include/bits/types.h
gpt.o: /usr/include/bits/typesizes.h /usr/include/libio.h
gpt.o: /usr/include/_G_config.h /usr/include/wchar.h
gpt.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
gpt.o: /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h
gpt.o: /usr/include/endian.h /usr/include/bits/endian.h
gpt.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
gpt.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
gpt.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
gpt.o: /usr/include/bits/pthreadtypes.h /usr/include/alloca.h
gpt.o: /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/fcntl.h
gpt.o: /usr/include/bits/fcntl.h /usr/include/string.h /usr/include/xlocale.h
gpt.o: /usr/include/math.h /usr/include/bits/huge_val.h
gpt.o: /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h
gpt.o: /usr/include/bits/inf.h /usr/include/bits/nan.h
gpt.o: /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h
gpt.o: /usr/include/sys/stat.h /usr/include/bits/stat.h /usr/include/errno.h
gpt.o: /usr/include/bits/errno.h /usr/include/linux/errno.h
gpt.o: /usr/include/asm/errno.h /usr/include/asm-generic/errno.h
gpt.o: /usr/include/asm-generic/errno-base.h crc32.h gpt.h gptpart.h
gpt.o: support.h parttypes.h guid.h /usr/include/uuid/uuid.h
gpt.o: /usr/include/sys/time.h attributes.h mbr.h partnotes.h diskio.h
gpt.o: /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h
gpt.o: /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h
gpt.o: /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h
gpt.o: /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h
gpt.o: /usr/include/sys/ttydefaults.h bsd.h
gptpart.o: /usr/include/string.h /usr/include/features.h
gptpart.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
gptpart.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
gptpart.o: /usr/include/xlocale.h /usr/include/stdio.h
gptpart.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
gptpart.o: /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h
gptpart.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
gptpart.o: gptpart.h /usr/include/stdint.h /usr/include/bits/wchar.h
gptpart.o: /usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h
gptpart.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
gptpart.o: /usr/include/sys/select.h /usr/include/bits/select.h
gptpart.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
gptpart.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
gptpart.o: support.h /usr/include/stdlib.h /usr/include/alloca.h parttypes.h
gptpart.o: guid.h /usr/include/uuid/uuid.h /usr/include/sys/time.h
gptpart.o: attributes.h
gpttext.o: /usr/include/string.h /usr/include/features.h
gpttext.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
gpttext.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
gpttext.o: /usr/include/xlocale.h /usr/include/errno.h
gpttext.o: /usr/include/bits/errno.h /usr/include/linux/errno.h
gpttext.o: /usr/include/asm/errno.h /usr/include/asm-generic/errno.h
gpttext.o: /usr/include/asm-generic/errno-base.h /usr/include/stdint.h
gpttext.o: /usr/include/bits/wchar.h /usr/include/limits.h
gpttext.o: /usr/include/bits/posix1_lim.h /usr/include/bits/local_lim.h
gpttext.o: /usr/include/linux/limits.h /usr/include/bits/posix2_lim.h
gpttext.o: attributes.h gpttext.h gpt.h /usr/include/sys/types.h
gpttext.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
gpttext.o: /usr/include/time.h /usr/include/endian.h
gpttext.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
gpttext.o: /usr/include/sys/select.h /usr/include/bits/select.h
gpttext.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
gpttext.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
gpttext.o: gptpart.h support.h /usr/include/stdlib.h /usr/include/alloca.h
gpttext.o: parttypes.h guid.h /usr/include/uuid/uuid.h
gpttext.o: /usr/include/sys/time.h mbr.h partnotes.h diskio.h
gpttext.o: /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h
gpttext.o: /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h
gpttext.o: /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h
gpttext.o: /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h
gpttext.o: /usr/include/sys/ttydefaults.h bsd.h
guid.o: /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h
guid.o: /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h
guid.o: /usr/include/gnu/stubs-64.h /usr/include/bits/types.h
guid.o: /usr/include/bits/typesizes.h /usr/include/libio.h
guid.o: /usr/include/_G_config.h /usr/include/wchar.h
guid.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
guid.o: /usr/include/time.h guid.h /usr/include/stdint.h
guid.o: /usr/include/bits/wchar.h /usr/include/uuid/uuid.h
guid.o: /usr/include/sys/types.h /usr/include/endian.h
guid.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
guid.o: /usr/include/sys/select.h /usr/include/bits/select.h
guid.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
guid.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
guid.o: /usr/include/sys/time.h support.h /usr/include/stdlib.h
guid.o: /usr/include/alloca.h
mbr.o: /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h
mbr.o: /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h
mbr.o: /usr/include/gnu/stubs-64.h /usr/include/bits/types.h
mbr.o: /usr/include/bits/typesizes.h /usr/include/libio.h
mbr.o: /usr/include/_G_config.h /usr/include/wchar.h
mbr.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
mbr.o: /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h
mbr.o: /usr/include/endian.h /usr/include/bits/endian.h
mbr.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
mbr.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
mbr.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
mbr.o: /usr/include/bits/pthreadtypes.h /usr/include/alloca.h
mbr.o: /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/fcntl.h
mbr.o: /usr/include/bits/fcntl.h /usr/include/string.h /usr/include/xlocale.h
mbr.o: /usr/include/sys/stat.h /usr/include/bits/stat.h /usr/include/errno.h
mbr.o: /usr/include/bits/errno.h /usr/include/linux/errno.h
mbr.o: /usr/include/asm/errno.h /usr/include/asm-generic/errno.h
mbr.o: /usr/include/asm-generic/errno-base.h mbr.h gptpart.h support.h
mbr.o: parttypes.h guid.h /usr/include/uuid/uuid.h /usr/include/sys/time.h
mbr.o: attributes.h partnotes.h gpt.h bsd.h diskio.h /usr/include/sys/ioctl.h
mbr.o: /usr/include/bits/ioctls.h /usr/include/asm/ioctls.h
mbr.o: /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h
mbr.o: /usr/include/asm/ioctl.h /usr/include/asm-generic/ioctl.h
mbr.o: /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h
partnotes.o: /usr/include/stdio.h /usr/include/features.h
partnotes.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
partnotes.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
partnotes.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
partnotes.o: /usr/include/libio.h /usr/include/_G_config.h
partnotes.o: /usr/include/wchar.h /usr/include/bits/stdio_lim.h
partnotes.o: /usr/include/bits/sys_errlist.h partnotes.h gpt.h
partnotes.o: /usr/include/stdint.h /usr/include/bits/wchar.h
partnotes.o: /usr/include/sys/types.h /usr/include/time.h
partnotes.o: /usr/include/endian.h /usr/include/bits/endian.h
partnotes.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
partnotes.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
partnotes.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
partnotes.o: /usr/include/bits/pthreadtypes.h gptpart.h support.h
partnotes.o: /usr/include/stdlib.h /usr/include/alloca.h parttypes.h guid.h
partnotes.o: /usr/include/uuid/uuid.h /usr/include/sys/time.h attributes.h
partnotes.o: mbr.h diskio.h /usr/include/sys/ioctl.h
partnotes.o: /usr/include/bits/ioctls.h /usr/include/asm/ioctls.h
partnotes.o: /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h
partnotes.o: /usr/include/asm/ioctl.h /usr/include/asm-generic/ioctl.h
partnotes.o: /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h
partnotes.o: bsd.h
parttypes.o: /usr/include/string.h /usr/include/features.h
parttypes.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
parttypes.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
parttypes.o: /usr/include/xlocale.h /usr/include/stdint.h
parttypes.o: /usr/include/bits/wchar.h /usr/include/stdio.h
parttypes.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
parttypes.o: /usr/include/libio.h /usr/include/_G_config.h
parttypes.o: /usr/include/wchar.h /usr/include/bits/stdio_lim.h
parttypes.o: /usr/include/bits/sys_errlist.h parttypes.h
parttypes.o: /usr/include/stdlib.h /usr/include/sys/types.h
parttypes.o: /usr/include/time.h /usr/include/endian.h
parttypes.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
parttypes.o: /usr/include/sys/select.h /usr/include/bits/select.h
parttypes.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
parttypes.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
parttypes.o: /usr/include/alloca.h support.h guid.h /usr/include/uuid/uuid.h
parttypes.o: /usr/include/sys/time.h
sgdisk.o: /usr/include/stdio.h /usr/include/features.h
sgdisk.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
sgdisk.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
sgdisk.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
sgdisk.o: /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h
sgdisk.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
sgdisk.o: /usr/include/popt.h /usr/include/errno.h /usr/include/bits/errno.h
sgdisk.o: /usr/include/linux/errno.h /usr/include/asm/errno.h
sgdisk.o: /usr/include/asm-generic/errno.h
sgdisk.o: /usr/include/asm-generic/errno-base.h /usr/include/stdint.h
sgdisk.o: /usr/include/bits/wchar.h mbr.h /usr/include/sys/types.h
sgdisk.o: /usr/include/time.h /usr/include/endian.h
sgdisk.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
sgdisk.o: /usr/include/sys/select.h /usr/include/bits/select.h
sgdisk.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
sgdisk.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
sgdisk.o: gptpart.h support.h /usr/include/stdlib.h /usr/include/alloca.h
sgdisk.o: parttypes.h guid.h /usr/include/uuid/uuid.h /usr/include/sys/time.h
sgdisk.o: attributes.h partnotes.h gpt.h bsd.h diskio.h
sgdisk.o: /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h
sgdisk.o: /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h
sgdisk.o: /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h
sgdisk.o: /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h
sgdisk.o: /usr/include/sys/ttydefaults.h
support.o: /usr/include/stdio.h /usr/include/features.h
support.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
support.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
support.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
support.o: /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h
support.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
support.o: /usr/include/stdint.h /usr/include/bits/wchar.h
support.o: /usr/include/errno.h /usr/include/bits/errno.h
support.o: /usr/include/linux/errno.h /usr/include/asm/errno.h
support.o: /usr/include/asm-generic/errno.h
support.o: /usr/include/asm-generic/errno-base.h /usr/include/fcntl.h
support.o: /usr/include/bits/fcntl.h /usr/include/sys/types.h
support.o: /usr/include/time.h /usr/include/endian.h
support.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
support.o: /usr/include/sys/select.h /usr/include/bits/select.h
support.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
support.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
support.o: /usr/include/string.h /usr/include/xlocale.h
support.o: /usr/include/sys/stat.h /usr/include/bits/stat.h support.h
support.o: /usr/include/stdlib.h /usr/include/alloca.h
testguid.o: guid.h /usr/include/stdint.h /usr/include/features.h
testguid.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
testguid.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
testguid.o: /usr/include/bits/wchar.h /usr/include/uuid/uuid.h
testguid.o: /usr/include/sys/types.h /usr/include/bits/types.h
testguid.o: /usr/include/bits/typesizes.h /usr/include/time.h
testguid.o: /usr/include/endian.h /usr/include/bits/endian.h
testguid.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
testguid.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
testguid.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
testguid.o: /usr/include/bits/pthreadtypes.h /usr/include/sys/time.h
testguid.o: parttypes.h /usr/include/stdlib.h /usr/include/alloca.h support.h

View File

@@ -2,7 +2,7 @@ CC=gcc
CXX=g++
CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g
CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
LIB_NAMES=crc32 support guid partnotes gptpart mbr gpt bsd parttypes attributes diskio diskio-unix
LIB_NAMES=crc32 support guid partnotes gptpartnotes gptpart basicmbr mbr gpt bsd parttypes attributes diskio diskio-unix
LIB_SRCS=$(NAMES:=.cc)
LIB_OBJS=$(LIB_NAMES:=.o)
LIB_HEADERS=$(LIB_NAMES:=.h)

View File

@@ -1,10 +1,10 @@
CC=/usr/bin/i586-mingw32msvc-gcc
CXX=/usr/bin/i586-mingw32msvc-g++
STRIP=/usr/bin/i586-mingw32msvc-strip
CC=/usr/bin/i686-pc-mingw32-gcc
CXX=/usr/bin/i686-pc-mingw32-g++
STRIP=/usr/bin/i686-pc-mingw32-strip
CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g
CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -g
#CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
LIB_NAMES=guid gptpart partnotes bsd parttypes attributes crc32 mbr gpt support diskio diskio-windows
LIB_NAMES=guid gptpart bsd parttypes partnotes gptpartnotes attributes crc32 basicmbr mbr gpt support diskio diskio-windows
LIB_SRCS=$(NAMES:=.cc)
LIB_OBJS=$(LIB_NAMES:=.o)
LIB_HEADERS=$(LIB_NAMES:=.h)
@@ -12,8 +12,8 @@ DEPEND= makedepend $(CFLAGS)
all: gdisk
gdisk: $(LIB_OBJS) gpttext.o gdisk.o
$(CXX) $(LIB_OBJS) gpttext.o gdisk.o -luuid -o gdisk.exe
gdisk: $(LIB_OBJS) gdisk.o gpttext.o
$(CXX) $(LIB_OBJS) gdisk.o gpttext.o -luuid -static-libgcc -o gdisk.exe
sgdisk: $(LIB_OBJS) sgdisk.o
$(CXX) $(LIB_OBJS) sgdisk.o -lpopt -o sgdisk.exe

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):
------------------

View File

@@ -1,8 +1,9 @@
// attributes.cc
// Class to manage partition attribute codes. These are binary bit fields,
// of which only three are currently (2/2009) documented on Wikipedia.
// of which only four are currently (2/2011) documented on Wikipedia, and
// two others found from other sources.
/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
/* This program is copyright (c) 2009-2011 by Roderick W. Smith. It is distributed
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
#define __STDC_LIMIT_MACROS

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. */
#include <stdint.h>

View File

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

View File

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

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
problems if partitions are not aligned properly for their internal data
structures. On new disks, GPT fdisk attempts to align partitions on
2048\-sector (1MiB) boundaries by default, which optimizes performance
for both of these disk types. On pre\-partitioned disks, GPT fdisk
attempts to identify the alignment value used on that disk. In either
case, it can be changed by using this option.
2048\-sector (1MiB) boundaries by default, which optimizes performance for
both of these disk types. On pre\-partitioned disks, GPT fdisk attempts to
identify the alignment value used on that disk, but will set 8-sector
alignment on disks larger than 300 GB even if lesser alignment values are
detected. In either case, it can be changed by using this option.
.TP
.B m
@@ -663,6 +664,8 @@ Contributors:
* Dwight Schauer (dschauer@ti.com)
* Florian Zumbiehl (florz@florz.de)
.SH "SEE ALSO"
\fBcfdisk (8)\fR,

122
gdisk.cc
View File

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

143
gpt.cc
View File

@@ -3,7 +3,7 @@
/* By Rod Smith, initial coding January to February, 2009 */
/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
/* This program is copyright (c) 2009-2011 by Roderick W. Smith. It is distributed
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
#define __STDC_LIMIT_MACROS
@@ -96,6 +96,45 @@ GPTData::~GPTData(void) {
delete[] partitions;
} // GPTData destructor
// Assignment operator
GPTData & GPTData::operator=(const GPTData & orig) {
uint32_t i;
mainHeader = orig.mainHeader;
numParts = orig.numParts;
secondHeader = orig.secondHeader;
protectiveMBR = orig.protectiveMBR;
device = orig.device;
blockSize = orig.blockSize;
diskSize = orig.diskSize;
state = orig.state;
justLooking = orig.justLooking;
mainCrcOk = orig.mainCrcOk;
secondCrcOk = orig.secondCrcOk;
mainPartsCrcOk = orig.mainPartsCrcOk;
secondPartsCrcOk = orig.secondPartsCrcOk;
apmFound = orig.apmFound;
bsdFound = orig.bsdFound;
sectorAlignment = orig.sectorAlignment;
beQuiet = orig.beQuiet;
whichWasUsed = orig.whichWasUsed;
myDisk.OpenForRead(orig.myDisk.GetName());
delete[] partitions;
partitions = new GPTPart [numParts * sizeof (GPTPart)];
if (partitions != NULL) {
for (i = 0; i < numParts; i++) {
partitions[i] = orig.partitions[i];
}
} else {
numParts = 0;
cerr << "Error! Could not allocate memory for partitions in GPTData::operator=()!\n"
<< "Continuing, but strange problems may occur!\n";
} // if/else
return *this;
} // GPTData::operator=()
/*********************************************************************
* *
* Begin functions that verify data, or that adjust the verification *
@@ -107,7 +146,7 @@ GPTData::~GPTData(void) {
// do *NOT* recover from these problems. Returns the total number of
// problems identified.
int GPTData::Verify(void) {
int problems = 0;
int problems = 0, alignProbs = 0;
uint32_t i, numSegments;
uint64_t totalFree, largestSegment;
@@ -210,11 +249,11 @@ int GPTData::Verify(void) {
// Now check for a few other miscellaneous problems...
// Check that the disk size will hold the data...
if (mainHeader.backupLBA > diskSize) {
if (mainHeader.backupLBA >= diskSize) {
problems++;
cout << "\nProblem: Disk is too small to hold all the data!\n"
<< "(Disk size is " << diskSize << " sectors, needs to be "
<< mainHeader.backupLBA << " sectors.)\n"
<< mainHeader.backupLBA + UINT64_C(1) << " sectors.)\n"
<< "The 'e' option on the experts' menu may fix this problem.\n";
} // if
@@ -240,14 +279,18 @@ int GPTData::Verify(void) {
cout << "\nCaution: Partition " << i + 1 << " doesn't begin on a "
<< sectorAlignment << "-sector boundary. This may\nresult "
<< "in degraded performance on some modern (2009 and later) hard disks.\n";
alignProbs++;
} // if
} // for
if (alignProbs > 0)
cout << "\nConsult http://www.ibm.com/developerworks/linux/library/l-4kb-sector-disks/\n"
<< "for information on disk alignment.\n";
// Now compute available space, but only if no problems found, since
// problems could affect the results
if (problems == 0) {
totalFree = FindFreeBlocks(&numSegments, &largestSegment);
cout << "No problems found. " << totalFree << " free sectors ("
cout << "\nNo problems found. " << totalFree << " free sectors ("
<< BytesToSI(totalFree, blockSize) << ") available in "
<< numSegments << "\nsegments, the largest of which is "
<< largestSegment << " (" << BytesToSI(largestSegment, blockSize)
@@ -563,6 +606,24 @@ int GPTData::FindInsanePartitions(void) {
* *
******************************************************************/
// Change the filename associated with the GPT. Used for duplicating
// the partition table to a new disk and saving backups.
// Returns 1 on success, 0 on failure.
int GPTData::SetFile(const string & deviceFilename) {
int err, allOK = 1;
device = deviceFilename;
if (allOK && myDisk.OpenForRead(deviceFilename)) {
// store disk information....
diskSize = myDisk.DiskSize(&err);
blockSize = (uint32_t) myDisk.GetBlockSize();
} // if
protectiveMBR.SetDisk(&myDisk);
protectiveMBR.SetDiskSize(diskSize);
protectiveMBR.SetBlockSize(blockSize);
return allOK;
} // GPTData::SetFile()
// Scan for partition data. This function loads the MBR data (regular MBR or
// protective MBR) and loads BSD disklabel data (which is probably invalid).
// It also looks for APM data, forces a load of GPT data, and summarizes
@@ -869,20 +930,15 @@ int GPTData::CheckTable(struct GPTHeader *header) {
return newCrcOk;
} // GPTData::CheckTable()
// Writes GPT (and protective MBR) to disk. Returns 1 on successful
// Writes GPT (and protective MBR) to disk. If quiet==1,
// Returns 1 on successful
// write, 0 if there was a problem.
int GPTData::SaveGPTData(int quiet, string filename) {
int GPTData::SaveGPTData(int quiet) {
int allOK = 1, littleEndian;
char answer;
littleEndian = IsLittleEndian();
if (filename == "")
filename = device;
if (filename == "") {
cerr << "Device not defined.\n";
} // if
// First do some final sanity checks....
// This test should only fail on read-only disks....
@@ -891,30 +947,34 @@ int GPTData::SaveGPTData(int quiet, string filename) {
allOK = 0;
} // if
// Check that disk is really big enough to handle the second header...
if (mainHeader.backupLBA >= diskSize) {
cerr << "Caution! Secondary header was placed beyond the disk's limits! Moving the\n"
<< "header, but other problems may occur!\n";
MoveSecondHeaderToEnd();
} // if
// Is there enough space to hold the GPT headers and partition tables,
// given the partition sizes?
if (CheckGPTSize() > 0) {
allOK = 0;
} // if
// Check that disk is really big enough to handle this...
if (mainHeader.backupLBA > diskSize) {
cerr << "Error! Disk is too small! The 'e' option on the experts' menu might fix the\n"
<< "problem (or it might not). Aborting!\n(Disk size is "
<< diskSize << " sectors, needs to be " << mainHeader.backupLBA << " sectors.)\n";
allOK = 0;
} // if
// Check that second header is properly placed. Warn and ask if this should
// be corrected if the test fails....
if ((mainHeader.backupLBA < (diskSize - UINT64_C(1))) && (quiet == 0)) {
cout << "Warning! Secondary header is placed too early on the disk! Do you want to\n"
<< "correct this problem? ";
if (GetYN() == 'Y') {
if (mainHeader.backupLBA < (diskSize - UINT64_C(1))) {
if (quiet == 0) {
cout << "Warning! Secondary header is placed too early on the disk! Do you want to\n"
<< "correct this problem? ";
if (GetYN() == 'Y') {
MoveSecondHeaderToEnd();
cout << "Have moved second header and partition table to correct location.\n";
} else {
cout << "Have not corrected the problem. Strange problems may occur in the future!\n";
} // if correction requested
} else { // Go ahead and do correction automatically
MoveSecondHeaderToEnd();
cout << "Have moved second header and partition table to correct location.\n";
} else {
cout << "Have not corrected the problem. Strange problems may occur in the future!\n";
} // if correction requested
} // if/else quiet
} // if
// Check for overlapping or insane partitions....
@@ -942,7 +1002,7 @@ int GPTData::SaveGPTData(int quiet, string filename) {
// Do it!
if (allOK) {
if (myDisk.OpenForWrite(filename)) {
if (myDisk.OpenForWrite()) {
// As per UEFI specs, write the secondary table and GPT first....
allOK = SavePartitionTable(myDisk, secondHeader.partitionEntriesLBA);
if (!allOK)
@@ -975,7 +1035,7 @@ int GPTData::SaveGPTData(int quiet, string filename) {
myDisk.Close();
} else {
cerr << "Unable to open device " << filename << " for writing! Errno is "
cerr << "Unable to open device " << myDisk.GetName() << " for writing! Errno is "
<< errno << "! Aborting write!\n";
allOK = 0;
} // if/else
@@ -1513,24 +1573,24 @@ int GPTData::PartsToMBR(PartNotes * notes) {
notes->MakeItLegal();
notes->Rewind();
while (notes->GetNextInfo(&convInfo) >= 0) {
if ((convInfo.gptPartNum >= 0) && (convInfo.type == PRIMARY)) {
numConverted += OnePartToMBR((uint32_t) convInfo.gptPartNum, mbrNum);
if ((convInfo.origPartNum >= 0) && (convInfo.type == PRIMARY)) {
numConverted += OnePartToMBR((uint32_t) convInfo.origPartNum, mbrNum);
if (convInfo.hexCode != 0)
protectiveMBR.SetPartType(mbrNum, convInfo.hexCode);
if (convInfo.active)
protectiveMBR.SetPartBootable(mbrNum);
mbrNum++;
} // if
if (convInfo.gptPartNum == MBR_EFI_GPT)
if (convInfo.origPartNum == MBR_EFI_GPT)
mbrNum++;
} // for
// Now go through and set sizes for MBR_EFI_GPT partitions....
notes->Rewind();
mbrNum = 0;
while (notes->GetNextInfo(&convInfo) >= 0) {
if ((convInfo.gptPartNum >= 0) && (convInfo.type == PRIMARY))
if ((convInfo.origPartNum >= 0) && (convInfo.type == PRIMARY))
mbrNum++;
if (convInfo.gptPartNum == MBR_EFI_GPT) {
if (convInfo.origPartNum == MBR_EFI_GPT) {
if (protectiveMBR.FindFirstAvailable() == UINT32_C(1)) {
protectiveMBR.MakePart(mbrNum, 1, protectiveMBR.FindLastInFree(1), convInfo.hexCode);
protectiveMBR.SetHybrid();
@@ -1803,11 +1863,22 @@ int GPTData::ClearGPTData(void) {
} // GPTData::ClearGPTData()
// Set the location of the second GPT header data to the end of the disk.
// If the disk size has actually changed, this also adjusts the protective
// entry in the MBR, since it's probably no longer correct.
// Used internally and called by the 'e' option on the recovery &
// transformation menu, to help users of RAID arrays who add disk space
// to their arrays.
// to their arrays or to adjust data structures in restore operations
// involving unequal-sized disks.
void GPTData::MoveSecondHeaderToEnd() {
mainHeader.backupLBA = secondHeader.currentLBA = diskSize - UINT64_C(1);
if (mainHeader.lastUsableLBA != diskSize - mainHeader.firstUsableLBA) {
if (protectiveMBR.GetValidity() == hybrid) {
protectiveMBR.OptimizeEESize();
RecomputeCHS();
} // if
if (protectiveMBR.GetValidity() == gpt)
MakeProtectiveMBR();
} // if
mainHeader.lastUsableLBA = secondHeader.lastUsableLBA = diskSize - mainHeader.firstUsableLBA;
secondHeader.partitionEntriesLBA = secondHeader.lastUsableLBA + UINT64_C(1);
} // GPTData::FixSecondHeaderLocation()

16
gpt.h
View File

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

View File

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

View File

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

View File

@@ -50,7 +50,7 @@ class GPTDataTextUI : public GPTData {
int DestroyGPTwPrompt(void); // Returns 1 if user proceeds
void ShowDetails(void);
void MakeHybrid(void);
int AssignPrimaryOrLogical(PartNotes& notes);
int AssignPrimaryOrLogical(GptPartNotes& notes);
int XFormToMBR(void); // convert GPT to MBR, wiping GPT afterwards. Returns 1 if successful
}; // class GPTDataTextUI

26
guid.cc
View File

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

2
guid.h
View File

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

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 <sys/types.h>
#include "gptpart.h"
#include "partnotes.h"
//#include "partnotes.h"
#include "diskio.h"
#include "basicmbr.h"
#ifndef __MBRSTRUCTS
#define __MBRSTRUCTS
#define MBR_SIGNATURE UINT16_C(0xAA55)
#define MAX_HEADS 255 /* numbered 0 - 254 */
#define MAX_SECSPERTRACK 63 /* numbered 1 - 63 */
#define MAX_CYLINDERS 1024 /* numbered 0 - 1023 */
// Maximum number of MBR partitions
#define MAX_MBR_PARTS 128
using namespace std;
class PartNotes;
// class PartNotes;
/****************************************
* *
@@ -30,115 +23,22 @@ class PartNotes;
* *
****************************************/
// Data for a single MBR partition record
// Note that firstSector and lastSector are in CHS addressing, which
// splits the bits up in a weird way.
// On read or write of MBR entries, firstLBA is an absolute disk sector.
// On read of logical entries, it's relative to the EBR record for that
// partition. When writing EBR records, it's relative to the extended
// partition's start.
#pragma pack(1)
struct MBRRecord {
uint8_t status;
uint8_t firstSector[3];
uint8_t partitionType;
uint8_t lastSector[3];
uint32_t firstLBA; // see above
uint32_t lengthLBA;
}; // struct MBRRecord
// A 512-byte data structure into which the MBR can be loaded in one
// go. Also used when loading logical partitions.
#pragma pack(1)
struct TempMBR {
uint8_t code[440];
uint32_t diskSignature;
uint16_t nulls;
struct MBRRecord partitions[4];
uint16_t MBRSignature;
}; // struct TempMBR
// Possible states of the MBR
enum MBRValidity {invalid, gpt, hybrid, mbr};
// Full data in tweaked MBR format
class MBRData {
class MBRData : public BasicMBRData {
protected:
uint8_t code[440];
uint32_t diskSignature;
uint16_t nulls;
// MAX_MBR_PARTS defaults to 128. This array holds both the primary and
// the logical partitions, to simplify data retrieval for GPT conversions.
struct MBRRecord partitions[MAX_MBR_PARTS];
uint16_t MBRSignature;
// Above are basic MBR data; now add more stuff....
uint32_t blockSize; // block size (usually 512)
uint64_t diskSize; // size in blocks
uint64_t numHeads; // number of heads, in CHS scheme
uint64_t numSecspTrack; // number of sectors per track, in CHS scheme
DiskIO* myDisk;
int canDeleteMyDisk;
string device;
MBRValidity state;
struct MBRRecord* GetPartition(int i); // Return primary or logical partition
int foo;
public:
MBRData(void);
MBRData(string deviceFilename);
~MBRData(void);
// File I/O functions...
int ReadMBRData(const string & deviceFilename);
int ReadMBRData(DiskIO * theDisk, int checkBlockSize = 1);
// ReadLogicalPart() returns last partition # read to logicals[] array,
// or -1 if there was a problem....
int ReadLogicalPart(uint32_t extendedStart, uint32_t diskOffset,
int partNum);
int WriteMBRData(void);
int WriteMBRData(DiskIO *theDisk);
int WriteMBRData(const string & deviceFilename);
int WriteMBRData(struct TempMBR & mbr, DiskIO *theDisk, uint64_t sector);
void SetDisk(DiskIO *theDisk) {myDisk = theDisk; canDeleteMyDisk = 0;}
// Display data for user...
void DisplayMBRData(int maxParts = 4);
void ShowState(void);
// Functions that set or get disk metadata (size, CHS geometry, etc.)
void SetDiskSize(uint64_t ds) {diskSize = ds;}
MBRValidity GetValidity(void) {return state;}
void SetHybrid(void) {state = hybrid;} // Set hybrid flag
void SetCHSGeom(uint32_t h, uint32_t s);
int LBAtoCHS(uint64_t lba, uint8_t * chs); // Convert LBA to CHS
int Verify(void);
MBRData(void) {}
MBRData(string deviceFilename) : BasicMBRData(deviceFilename) {}
MBRData & operator=(const MBRData & orig);
// Functions to create, delete, or change partitions
// Pass EmptyMBR 1 to clear the boot loader code, 0 to leave it intact
void EmptyMBR(int clearBootloader = 1);
void EmptyBootloader(void);
void MakeProtectiveMBR(int clearBoot = 0);
void MakePart(int num, uint32_t startLBA, uint32_t lengthLBA, int type = 0x07,
int bootable = 0);
int SetPartType(int num, int type);
int SetPartBootable(int num, int bootable = 1);
int MakeBiggestPart(int i, int type); // Make partition filling most space
void DeletePartition(int i);
int DeleteByLocation(uint64_t start64, uint64_t length64);
void OptimizeEESize(void);
void RecomputeCHS(int partNum);
int CreateLogicals(PartNotes * notes);
// Functions to find information on free space....
uint32_t FindFirstAvailable(uint32_t start = 1);
uint32_t FindLastInFree(uint32_t start);
uint32_t FindFirstInFree(uint32_t start);
int IsFree(uint32_t sector);
int DeleteByLocation(uint64_t start64, uint64_t length64);
// Functions to extract data on specific partitions....
uint8_t GetStatus(int i);
uint8_t GetType(int i);
uint32_t GetFirstSector(int i);
uint32_t GetLength(int i);
GPTPart AsGPT(int i);
}; // struct MBRData

View File

@@ -29,21 +29,16 @@ PartNotes::PartNotes() {
notes = NULL;
currentNote = NULL;
currentIndex = 0;
gptParts = NULL;
gptTableSize = 0;
origTableSize = 0;
blockSize = 512;
dummyNote.active = 0;
dummyNote.gptPartNum = MBR_EMPTY;
dummyNote.origPartNum = MBR_EMPTY;
dummyNote.hexCode = 0xEE;
dummyNote.next = NULL;
dummyNote.spaceBefore = 0;
dummyNote.type = WILL_NOT_CONVERT;
} // PartNotes constructor
PartNotes::PartNotes(GPTPart *parts, GPTData *gpt, int num, int s) {
PassPartitions(parts, gpt, num, s);
} // PartNotes constructor passing partition information
// Destructor. Note that we do NOT delete the gptParts array, since we just
// store a pointer to an array that's allocated by the calling function.
PartNotes::~PartNotes() {
@@ -71,59 +66,6 @@ void PartNotes::DeleteNotes(void) {
* *
*************************************************************************/
// Creates the notes linked list with as many entries as there are
// in-use GPT partitions. Note that the parts array must be pre-sorted!
// If not, this function will reject the partition table.
// Returns the number of partitions -- normally identical to num,
// unless there were problems, in which case it returns 0.
int PartNotes::PassPartitions(GPTPart *parts, GPTData *gpt, int num, int s) {
int i;
struct PartInfo *tempNote = NULL, *lastNote = NULL;
if ((parts != NULL) && (num > 0)) {
blockSize = s;
gptParts = parts;
gptTableSize = num;
if (notes != NULL)
DeleteNotes();
for (i = 0; i < num; i++) {
if (gptParts[i].IsUsed()){
tempNote = new struct PartInfo;
tempNote->next = NULL;
tempNote->firstLBA = gptParts[i].GetFirstLBA();
tempNote->lastLBA = gptParts[i].GetLastLBA();
if (gpt->IsFree(gptParts[i].GetFirstLBA() - 1)) {
tempNote->spaceBefore = 1;
tempNote->type = LOGICAL;
} else {
tempNote->spaceBefore = 0;
tempNote->type = PRIMARY;
} // if/else
tempNote->gptPartNum = i;
tempNote->active = 0;
if (lastNote == NULL) {
lastNote = tempNote;
notes = tempNote;
} else {
lastNote->next = tempNote;
lastNote = tempNote;
} // if/else
} // if GPT partition in use
} // for
if (!IsSorted()) {
DeleteNotes();
gptParts = NULL;
gptTableSize = 0;
cerr << "The partition table must be sorted before calling PartNotes::PassPartitions()!\n";
} // if
} else {
notes = NULL;
gptParts = NULL;
gptTableSize = 0;
} // if/else
return gptTableSize;
} // PartNotes::PassPartitions
// Add a single partition to the end of the linked list.
// Returns 1 on success, 0 on failures.
int PartNotes::AddToEnd(struct PartInfo *newOne) {
@@ -344,10 +286,10 @@ uint8_t PartNotes::GetMbrHexType(int partNum) {
} // if/else
} // PartNotes::GetMBRHexType()
// Return the GPT partition number associated with this note, -1 if
// the notes list is empty, or the GPT partition number of the last
// Return the original partition number associated with this note, -1 if
// the notes list is empty, or the original partition number of the last
// partition if partNum is too high.
int PartNotes::GetGptNum(int partNum) {
int PartNotes::GetOrigNum(int partNum) {
int count = 0;
struct PartInfo *theNote;
@@ -355,11 +297,11 @@ int PartNotes::GetGptNum(int partNum) {
if (theNote != NULL) {
while ((count++ < partNum) && (theNote->next != NULL))
theNote = theNote->next;
return theNote->gptPartNum;
return theNote->origPartNum;
} else {
return -1;
} // if/else
} // PartNotes::GetGptNum()
} // PartNotes::GetOrigNum()
// Return whether or not the partition is flagged as active (bootable)
int PartNotes::GetActiveStatus(int partNum) {
@@ -417,23 +359,6 @@ int PartNotes::FindExtended(int &start) {
return length;
} // PartNotes::FindExtended()
// Returns 1 if the GPT partition table is sorted, 0 if not (or if the
// pointer is NULL)
int PartNotes::IsSorted(void) {
int i, sorted = 1;
uint64_t lastStartLBA = 0;
if (gptParts == NULL) {
sorted = 0;
} else {
for (i = 0; i < gptTableSize; i++) {
if (lastStartLBA > gptParts[i].GetFirstLBA())
sorted = 0;
} // for
} // if/else
return sorted;
} // PartNotes::IsSorted()
// Returns 1 if the set as a whole makes a legal MBR partition table
// (possibly with logicals), 0 if not
int PartNotes::IsLegal(void) {
@@ -557,7 +482,7 @@ void PartNotes::TrimSmallestExtended() {
} // for
// Find the smallest extended partition....
shortestNum = gptTableSize + 1;
shortestNum = origTableSize + 1;
for (i = 0; i < numExtended; i++) {
if (extendeds[i].numLogicals < shortestNum) {
shortestNum = extendeds[i].numLogicals;
@@ -593,57 +518,8 @@ void PartNotes::TrimSmallestExtended() {
// Display summary information for the user
void PartNotes::ShowSummary(void) {
int j;
string sizeInSI;
struct PartInfo *theNote;
if ((gptParts != NULL) && (notes != NULL)) {
theNote = notes;
cout << "Sorted GPT partitions and their current conversion status:\n";
cout << " Can Be\n";
cout << "Number Boot Size Status Logical Code GPT Name\n";
while (theNote != NULL) {
if (gptParts[theNote->gptPartNum].IsUsed()) {
cout.fill(' ');
cout.width(4);
cout << theNote->gptPartNum + 1 << " ";
if (theNote->active)
cout << " * ";
else
cout << " ";
sizeInSI = BytesToSI((gptParts[theNote->gptPartNum].GetLastLBA() -
gptParts[theNote->gptPartNum].GetFirstLBA() + 1), blockSize);
cout << " " << sizeInSI;
for (j = 0; j < 12 - (int) sizeInSI.length(); j++)
cout << " ";
switch (theNote->type) {
case PRIMARY:
cout << "primary ";
break;
case LOGICAL:
cout << "logical ";
break;
case WILL_NOT_CONVERT:
cout << "OMITTED ";
break;
default:
cout << "**ERROR** ";
break;
} // switch
if (theNote->spaceBefore)
cout << "Y ";
else
cout << "- ";
cout.fill('0');
cout.width(2);
cout.setf(ios::uppercase);
cout << hex << (int) theNote->hexCode << " " << dec;
cout.fill(' ');
cout << gptParts[theNote->gptPartNum].GetDescription().substr(0, 25) << "\n";
} // if
theNote = theNote->next;
} // for
} // if
cerr << "Program is calling PartNotes::ShowSummary(); this is a virtual base function,\n"
<< "and should never be called.\n";
} // PartNotes::ShowSummary()
// Interact with the user to create a change in the specified
@@ -654,7 +530,6 @@ void PartNotes::ShowSummary(void) {
int PartNotes::MakeChange(int partNum) {
int allOK = 1;
int type = 0;
char *junk;
char line[255], command;
if (notes != NULL) {
@@ -676,7 +551,10 @@ int PartNotes::MakeChange(int partNum) {
} // switch
cout << " t - change MBR type code\n";
cout << "Action: ";
junk = fgets(line, 255, stdin);
if (!fgets(line, 255, stdin)) {
cerr << "Critical error! Failed fgets() in PartNotes::MakeChange()!\n";
exit(1);
} // if
sscanf(line, "%c", &command);
switch (command) {
case 'a': case 'A':
@@ -694,7 +572,10 @@ int PartNotes::MakeChange(int partNum) {
case 't': case 'T':
while (type == 0) {
cout << "Enter a 2-byte hexadecimal MBR type code: ";
junk = fgets(line, 255, stdin);
if (!fgets(line, 255, stdin)) {
cerr << "Critical error! Failed fgets() in PartNotes::MakeChange()\n";
exit(1);
} // if
sscanf(line, "%x", &type);
} // while
SetMbrHexType(partNum, (uint8_t) type);
@@ -711,7 +592,7 @@ int PartNotes::MakeChange(int partNum) {
// Returns 1 unless there's a dire bug.
int PartNotes::ChangeType(int partNum, int newType) {
int origType, allOK = 1;
char *junk, line[255];
char line[255];
if ((notes != NULL) && IsLegal()) {
origType = GetType(partNum);
@@ -733,7 +614,10 @@ int PartNotes::ChangeType(int partNum, int newType) {
<< "another\norder, such as deleting partitions before changing others' "
<< "types.\n";
cout << "\nReverting change.\nPress <Enter> to continue: ";
junk = fgets(line, 255, stdin);
if (!fgets(line, 255, stdin)) {
cerr << "Critical error! Failed fgets() in PartNotes::ChangeType()\n";
exit(1);
} // if
SetType(partNum, origType);
} // if
} else allOK = 0; // if

View File

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

View File

@@ -2,7 +2,7 @@
// Class to manage partition type codes -- a slight variant on MBR type
// codes, GUID type codes, and associated names.
/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
/* This program is copyright (c) 2009-2011 by Roderick W. Smith. It is distributed
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
#define __STDC_LIMIT_MACROS
@@ -163,7 +163,7 @@ void PartType::AddAllTypes(void) {
AddType(0xc002, "E2A1E728-32E3-11D6-A682-7B03A0000000", "HP-UX service");
// EFI system and related partitions
AddType(0xef00, "C12A7328-F81F-11D2-BA4B-00A0C93EC93B", "EFI System"); // Parted marks Linux boot partitions as this
AddType(0xef00, "C12A7328-F81F-11D2-BA4B-00A0C93EC93B", "EFI System"); // Parted identifies these as having the "boot flag" set
AddType(0xef01, "024DEE41-33E7-11D3-9D69-0008C781F39F", "MBR partition scheme"); // Used to nest MBR in GPT
AddType(0xef02, "21686148-6449-6E6F-744E-656564454649", "BIOS boot partition"); // Boot loader

View File

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

View File

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

View File

@@ -63,11 +63,13 @@ int GetNumber(int low, int high, int def, const string & prompt) {
char GetYN(void) {
char line[255];
char response;
char *junk;
do {
cout << "(Y/N): ";
junk = fgets(line, 255, stdin);
if (!fgets(line, 255, stdin)) {
cerr << "Critical error! Failed fgets() in GetYN()\n";
exit(1);
} // if
sscanf(line, "%c", &response);
if (response == 'y')
response = 'Y';
@@ -306,32 +308,23 @@ void ReverseBytes(void* theValue, int numBytes) {
// Extract integer data from argument string, which should be colon-delimited
uint64_t GetInt(const string & argument, int itemNum) {
int startPos = -1, endPos = -1;
uint64_t retval = 0;
uint64_t retval;
while (itemNum-- > 0) {
startPos = endPos + 1;
endPos = (int) argument.find(':', startPos);
}
if (endPos == (int) string::npos)
endPos = (int) argument.length();
endPos--;
istringstream inString(argument.substr(startPos, endPos - startPos + 1));
istringstream inString(GetString(argument, itemNum));
inString >> retval;
return retval;
} // GetInt()
// Extract string data from argument string, which should be colon-delimited
string GetString(const string & argument, int itemNum) {
int startPos = -1, endPos = -1;
size_t startPos = -1, endPos = -1;
while (itemNum-- > 0) {
startPos = endPos + 1;
endPos = (int) argument.find(':', startPos);
endPos = argument.find(':', startPos);
}
if (endPos == (int) string::npos)
endPos = (int) argument.length();
if (endPos == string::npos)
endPos = argument.length();
endPos--;
return argument.substr(startPos, endPos - startPos + 1);