All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matt_Domsch@Dell.com
To: linux-ia64@vger.kernel.org
Subject: [Linux-ia64] GPT patch for parted 1.4.7
Date: Tue, 06 Mar 2001 18:01:00 +0000	[thread overview]
Message-ID: <marc-linux-ia64-105590693005247@msgid-missing> (raw)

[-- Attachment #1: Type: text/plain, Size: 1294 bytes --]

Attached is a patch against GNU Parted 1.4.7 which adds EFI GPT support.
This has not yet been submitted to the GNU Parted team officially, I'm
waiting on a kernel IOCTL patch to be included first.  A lot of people are
interested in this, so I'm making it available for testing.  I haven't
tested this against newer versions of parted, but expect it to drop in with
minimal effort.

Notes:
- This works for all disks with an even number of 512-byte sectors.
- This works for SCSI disks with an odd number of 512-byte sectors by using
SCSI Generic (sg) commands to read/write the last odd sector.  Odd-sized IDE
disks won't work.
- Pending the inclusion of a kernel patch to allow reading/writing the last
sector of any disk via a block layer IOCTL, I'll re-write this patch to
remove the sg hacks and use that instead.

Assistance:
If anyone wants to help, particularly in adding Unicode support to parted,
I'd appreciate it.  Please join the bug-parted mailing list.
To subscribe or unsubscribe via the World Wide Web, visit
	http://mail.gnu.org/mailman/listinfo/bug-parted
or, via email, send a message with subject or body 'help' to
	bug-parted-request@gnu.org


Your feedback is encouraged.  

Thanks,
Matt

--
Matt Domsch
Dell Linux Systems Group
Linux OS Development
www.dell.com/linux



[-- Attachment #2: parted-1.4.7-gpt-010124.patch --]
[-- Type: application/octet-stream, Size: 163242 bytes --]

diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/include/parted/Makefile.am parted-1.4.7-gpt/include/parted/Makefile.am
--- parted-1.4.7/include/parted/Makefile.am	Mon Dec  4 13:12:47 2000
+++ parted-1.4.7-gpt/include/parted/Makefile.am	Thu Jan 18 11:24:42 2001
@@ -6,6 +6,7 @@
 			exception.h	\
 			filesys.h	\
 			natmath.h	\
+			crc32.h		\
 			parted.h
 
 noinst_HEADERS	      = disk_bsd.h	\
@@ -13,5 +14,6 @@
 			disk_loop.h	\
 			disk_mac.h	\
 			disk_pc98.h	\
+			disk_gpt.h	\
 			endian.h
 
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/include/parted/crc32.h parted-1.4.7-gpt/include/parted/crc32.h
--- parted-1.4.7/include/parted/crc32.h	Wed Dec 31 18:00:00 1969
+++ parted-1.4.7-gpt/include/parted/crc32.h	Thu Jan 18 11:24:42 2001
@@ -0,0 +1,34 @@
+/*
+    libparted - a library for manipulating disk partitions
+    Copyright (C) 1998-2000 Free Software Foundation, Inc.
+
+    crc32.h
+
+    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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _CRC32_H
+#define _CRC32_H
+
+#include <linux/types.h>
+
+/*
+ * This computes a 32 bit CRC of the data in the buffer, and returns the CRC.
+ * The polynomial used is 0xedb88320.
+ */
+
+extern __u32 crc32 (const void *buf, unsigned long len, __u32 seed);
+
+#endif /* _CRC32_H */
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/include/parted/disk_gpt.h parted-1.4.7-gpt/include/parted/disk_gpt.h
--- parted-1.4.7/include/parted/disk_gpt.h	Wed Dec 31 18:00:00 1969
+++ parted-1.4.7-gpt/include/parted/disk_gpt.h	Wed Jan 24 11:23:31 2001
@@ -0,0 +1,195 @@
+/*
+    libparted - a library for manipulating disk partitions
+
+    Copyright (C) 2000-2001 Dell Computer Corporation
+    disk_gpt.[ch] by Matt Domsch <Matt_Domsch@dell.com> 
+
+    EFI GUID Partition Table handling
+    Per Intel EFI Specification v1.02
+    http://developer.intel.com/technology/efi/efi.htm
+
+    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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef EFI_GPT_H
+#define EFI_GPT_H
+
+
+#include <linux/types.h>
+
+#define EFI_PMBR_OSTYPE_EFI 0xEF
+#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE
+#define MSDOS_MBR_SIGNATURE 0xaa55
+#define GUID_PT_BLOCK_SIZE 512
+
+
+#define GUID_PT_HEADER_SIGNATURE 0x5452415020494645
+#define GUID_PT_HEADER_REVISION_V1_02 0x00010200
+#define GUID_PT_HEADER_REVISION_V1_00 0x00010000
+#define GUID_PT_HEADER_REVISION_V0_99 0x00009900
+
+typedef __u16 efi_char16_t;	/* UNICODE character */
+
+typedef struct {
+	__u32 data1;
+	__u16 data2;
+	__u16 data3;
+	__u8 data4[8];
+} __attribute__ ((packed)) efi_guid_t;
+
+
+#define UNUSED_ENTRY_GUID    \
+    ((efi_guid_t) { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }})
+#define PARTITION_SYSTEM_GUID \
+    ((efi_guid_t) { 0xC12A7328, 0xF81F, 0x11d2, { 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B }})
+#define LEGACY_MBR_PARTITION_GUID \
+    ((efi_guid_t) { 0x024DEE41, 0x33E7, 0x11d3, { 0x9D, 0x69, 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F }})
+#define PARTITION_MSFT_RESERVED_GUID \
+    ((efi_guid_t) { 0xE3C9E316, 0x0B5C, 0x4DB8, { 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE }})
+#define PARTITION_BASIC_DATA_GUID \
+    ((efi_guid_t) { 0xEBD0A0A2, 0xB9E5, 0x4433, { 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 }})
+#define PARTITION_RAID_GUID \
+    ((efi_guid_t) { 0xa19d880f, 0x05fc, 0x4d3b, { 0xa0, 0x06, 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e }})
+#define PARTITION_SWAP_GUID \
+    ((efi_guid_t) { 0x0657fd6d, 0xa4ab, 0x43c4, { 0x84, 0xe5, 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f }})
+#define PARTITION_LVM_GUID \
+    ((efi_guid_t) { 0xe6d6d379, 0xf507, 0x44c2, { 0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28 }})
+#define PARTITION_RESERVED_GUID \
+    ((efi_guid_t) { 0x8da63339, 0x0007, 0x60c0, { 0xc4, 0x36, 0x08, 0x3a, 0xc8, 0x23, 0x09, 0x08 }})
+
+typedef struct _GuidPartitionTableHeader_t {
+	__u64 Signature;
+	__u32 Revision;
+	__u32 HeaderSize;
+	__u32 HeaderCRC32;
+	__u32 Reserved1;
+	__u64 MyLBA;
+	__u64 AlternateLBA;
+	__u64 FirstUsableLBA;
+	__u64 LastUsableLBA;
+	efi_guid_t DiskGUID;
+	__u64 PartitionEntryLBA;
+	__u32 NumberOfPartitionEntries;
+	__u32 SizeOfPartitionEntry;
+	__u32 PartitionEntryArrayCRC32;
+	__u8 Reserved2[GUID_PT_BLOCK_SIZE - 92];
+} __attribute__ ((packed)) GuidPartitionTableHeader_t;
+
+typedef struct _GuidPartitionEntryAttributes_t {
+	__u64 RequiredToFunction:1;
+	__u64 Reserved:47;
+        __u64 GuidSpecific:16;
+} __attribute__ ((packed)) GuidPartitionEntryAttributes_t;
+
+typedef struct _GuidPartitionEntry_t {
+	efi_guid_t PartitionTypeGuid;
+	efi_guid_t UniquePartitionGuid;
+	__u64 StartingLBA;
+	__u64 EndingLBA;
+	GuidPartitionEntryAttributes_t Attributes;
+	efi_char16_t PartitionName[72 / sizeof(efi_char16_t)];
+} __attribute__ ((packed)) GuidPartitionEntry_t;
+
+
+/* 
+   These values are only defaults.  The actual on-disk structures
+   may define different sizes, so use those unless creating a new GPT disk!
+*/
+
+#define GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE 16384
+/* 
+   Number of actual partition entries should be calculated
+   as: 
+*/
+#define GPT_DEFAULT_RESERVED_PARTITION_ENTRIES \
+        (GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE / \
+         sizeof(GuidPartitionEntry_t))
+
+
+typedef struct _PartitionRecord_t {
+	__u8 BootIndicator;	/* Not used by EFI firmware. Set to 0x80 to indicate that this
+				   is the bootable legacy partition. */
+	__u8 StartHead;		/* Start of partition in CHS address, not used by EFI firmware. */
+	__u8 StartSector;	/* Start of partition in CHS address, not used by EFI firmware. */
+	__u8 StartTrack;	/* Start of partition in CHS address, not used by EFI firmware. */
+	__u8 OSType;		/* OS type. A value of 0xEF defines an EFI system partition.
+				   Other values are reserved for legacy operating systems, and
+				   allocated independently of the EFI specification. */
+	__u8 EndHead;		/* End of partition in CHS address, not used by EFI firmware. */
+	__u8 EndSector;		/* End of partition in CHS address, not used by EFI firmware. */
+	__u8 EndTrack;		/* End of partition in CHS address, not used by EFI firmware. */
+	__u32 StartingLBA;	/* Starting LBA address of the partition on the disk. Used by
+				   EFI firmware to define the start of the partition. */
+	__u32 SizeInLBA;	/* Size of partition in LBA. Used by EFI firmware to determine
+				   the size of the partition. */
+} __attribute__ ((packed)) PartitionRecord_t;
+
+
+/* Protected Master Boot Record  & Legacy MBR share same structure */
+/* Needs to be packed because the u16s force misalignment. */
+
+typedef struct _LegacyMBR_t {
+	__u8 BootCode[440];
+	__u32 UniqueMBRSignature;
+	__u16 Unknown;
+	PartitionRecord_t PartitionRecord[4];
+	__u16 Signature;
+} __attribute__ ((packed)) LegacyMBR_t;
+
+
+
+
+#define EFI_GPT_PRIMARY_PARTITION_TABLE_LBA 1
+
+
+/* Parted has a PedDisk field disk_specific that we'll keep
+   our own useful info in.
+*/
+typedef struct _GPTDiskData {
+        GuidPartitionTableHeader_t *pgpt;
+ 	GuidPartitionTableHeader_t *agpt;
+ 	GuidPartitionEntry_t       *ptes;
+} GPTDiskData;
+
+/* Parted has a PedPartition field disk_specific that we'll keep
+   our own useful info in.
+*/
+typedef struct _GPTPartitionData {
+        GuidPartitionEntry_t *  pte;
+} GPTPartitionData;
+
+
+#define GPT_NAME	"GPT"
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4 
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/Makefile.am parted-1.4.7-gpt/libparted/Makefile.am
--- parted-1.4.7/libparted/Makefile.am	Mon Jan  8 13:57:26 2001
+++ parted-1.4.7-gpt/libparted/Makefile.am	Thu Jan 18 11:24:42 2001
@@ -15,12 +15,23 @@
 			llseek.c		\
 			llseek.h		\
 			natmath.c		\
+			crc32.c			\
 			disk.c			\
 			disk_bsd.c		\
 			disk_dos.c		\
 			disk_loop.c		\
 			disk_mac.c		\
-			disk_pc98.c
+			disk_pc98.c		\
+			disk_gpt.c              \
+			device_scsi.c           \
+			device_scsi.h           \
+			sg_map.c                \
+			sg_map.h                \
+			sg_dd.c                 \
+			sg_dd.h                 \
+			sg_err.c                \
+			sg_err.h             
+
 
 libparted_la_LIBADD   =	fs_ext2/libext2.la		\
 			fs_fat/libfat.la		\
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/crc32.c parted-1.4.7-gpt/libparted/crc32.c
--- parted-1.4.7/libparted/crc32.c	Wed Dec 31 18:00:00 1969
+++ parted-1.4.7-gpt/libparted/crc32.c	Thu Jan 18 11:24:42 2001
@@ -0,0 +1,125 @@
+/* 
+ * Dec 5, 2000 Matt Domsch <Matt_Domsch@dell.com>
+ * - Copied crc32.c from the linux/drivers/net/cipe directory.
+ * - Now pass seed as an arg
+ * - changed unsigned long to __u32, added #include<linux/types.h>
+ * - changed len to be an unsigned long
+ * - changed crc32val to be a register
+ * - License remains unchanged!  It's still GPL-compatable!
+ */
+
+  /* ============================================================= */
+  /*  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or       */
+  /*  code or tables extracted from it, as desired without restriction.     */
+  /*                                                                        */
+  /*  First, the polynomial itself and its table of feedback terms.  The    */
+  /*  polynomial is                                                         */
+  /*  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0   */
+  /*                                                                        */
+  /*  Note that we take it "backwards" and put the highest-order term in    */
+  /*  the lowest-order bit.  The X^32 term is "implied"; the LSB is the     */
+  /*  X^31 term, etc.  The X^0 term (usually shown as "+1") results in      */
+  /*  the MSB being 1.                                                      */
+  /*                                                                        */
+  /*  Note that the usual hardware shift register implementation, which     */
+  /*  is what we're using (we're merely optimizing it by doing eight-bit    */
+  /*  chunks at a time) shifts bits into the lowest-order term.  In our     */
+  /*  implementation, that means shifting towards the right.  Why do we     */
+  /*  do it this way?  Because the calculated CRC must be transmitted in    */
+  /*  order from highest-order term to lowest-order term.  UARTs transmit   */
+  /*  characters in order from LSB to MSB.  By storing the CRC this way,    */
+  /*  we hand it to the UART in the order low-byte to high-byte; the UART   */
+  /*  sends each low-bit to hight-bit; and the result is transmission bit   */
+  /*  by bit from highest- to lowest-order term without requiring any bit   */
+  /*  shuffling on our part.  Reception works similarly.                    */
+  /*                                                                        */
+  /*  The feedback terms table consists of 256, 32-bit entries.  Notes:     */
+  /*                                                                        */
+  /*      The table can be generated at runtime if desired; code to do so   */
+  /*      is shown later.  It might not be obvious, but the feedback        */
+  /*      terms simply represent the results of eight shift/xor opera-      */
+  /*      tions for all combinations of data and CRC register values.       */
+  /*                                                                        */
+  /*      The values must be right-shifted by eight bits by the "updcrc"    */
+  /*      logic; the shift must be unsigned (bring in zeroes).  On some     */
+  /*      hardware you could probably optimize the shift in assembler by    */
+  /*      using byte-swap instructions.                                     */
+  /*      polynomial $edb88320                                              */
+  /*                                                                        */
+  /*  --------------------------------------------------------------------  */
+
+#include<linux/types.h>
+
+static __u32 crc32_tab[] = {
+      0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+      0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+      0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+      0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+      0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+      0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+      0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+      0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+      0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+      0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+      0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+      0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+      0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+      0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+      0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+      0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+      0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+      0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+      0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+      0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+      0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+      0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+      0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+      0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+      0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+      0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+      0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+      0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+      0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+      0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+      0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+      0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+      0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+      0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+      0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+      0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+      0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+      0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+      0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+      0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+      0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+      0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+      0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+      0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+      0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+      0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+      0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+      0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+      0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+      0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+      0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+      0x2d02ef8dL
+   };
+
+/* Return a 32-bit CRC of the contents of the buffer. */
+
+__u32
+crc32(const void *buf, unsigned long len, __u32 seed)
+{
+  unsigned long i;
+  register __u32 crc32val;
+  const unsigned char *s = buf;
+
+  crc32val = seed;
+  for (i = 0;  i < len;  i ++)
+    {
+      crc32val =
+	crc32_tab[(crc32val ^ s[i]) & 0xff] ^
+	  (crc32val >> 8);
+    }
+  return crc32val;
+}
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/device.c parted-1.4.7-gpt/libparted/device.c
--- parted-1.4.7/libparted/device.c	Tue Jan  9 12:28:22 2001
+++ parted-1.4.7-gpt/libparted/device.c	Thu Jan 18 11:24:42 2001
@@ -41,6 +41,7 @@
 #include <sys/sysmacros.h>
 #include <sys/stat.h>
 #include <scsi/scsi.h>
+#include "device_scsi.h"
 
 #include <parted/parted.h>
 
@@ -828,6 +829,20 @@
 	PED_ASSERT (!dev->external_mode, return 0);
 	PED_ASSERT (buffer != NULL, return 0);
 
+
+	/* Kludge.  This is necessary to read/write the last
+	   block of an odd-sized SCSI disk, until 2.5.x kernel fixes.
+	   This is only used by disk_gpt.c, and only to read/write
+	   one sector, so we don't have to be fancy.
+	*/
+
+	if (dev->type == PED_DEVICE_SCSI &&
+	    (dev->length & 1) &&
+	    (count == 1) &&
+	    start == dev->length - 1) {
+		return ped_device_read_scsi(dev, buffer, start, count);
+	}
+
 	while (1) {
 		if (ped_device_seek (dev, start))
 			break;
@@ -946,6 +961,19 @@
 			return 0;
 		else
 			return 1;
+	}
+
+	/* Kludge.  This is necessary to read/write the last
+	   block of an odd-sized SCSI disk, until 2.5.x kernel fixes.
+	   This is only used by disk_gpt.c, and only to read/write
+	   one sector, so we don't have to be fancy.
+	*/
+
+	if (dev->type == PED_DEVICE_SCSI &&
+	    (dev->length & 1) &&
+	    (count == 1) &&
+	    start == dev->length - 1) {
+		return ped_device_write_scsi(dev, buffer, start, count);
 	}
 
 	while (1) {
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/device_scsi.c parted-1.4.7-gpt/libparted/device_scsi.c
--- parted-1.4.7/libparted/device_scsi.c	Wed Dec 31 18:00:00 1969
+++ parted-1.4.7-gpt/libparted/device_scsi.c	Thu Jan 18 11:24:42 2001
@@ -0,0 +1,102 @@
+/*
+    libparted - a library for manipulating disk partitions
+    Copyright (C) 1998-2000 Free Software Foundation, Inc.
+
+    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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include<stdio.h>
+#include<stdlib.h>
+#include<string.h>
+#include <fcntl.h>
+
+#include <parted/parted.h>
+#include"sg_map.h"
+#include"sg_dd.h"
+
+static const char *
+sg_from_sd(const char *sd)
+{
+	int i;
+	for (i=0; i<MAX_SG_DEVS; i++)
+		if (!strncmp(sd, sg_to_sd[i].sd, 16)) return sg_to_sd[i].sg;
+	return NULL;
+}
+
+int
+ped_device_read_scsi (PedDevice* dev, const void* buffer, PedSector start,
+		      PedSector count)
+{
+	const char *sg = NULL;
+	extern int sg_to_sd_map_made;
+	int rc;
+	int sg_fd, diop = 0;
+
+	// printf("in ped_device_read_scsi()\n");
+	PED_ASSERT(dev != NULL, return 0);
+	PED_ASSERT(dev->type == PED_DEVICE_SCSI, return 0);
+	PED_ASSERT(buffer != NULL, return 0);
+	PED_ASSERT(count == 1, return 0);	
+	
+	if (!sg_to_sd_map_made) make_sg_to_sd_map();
+
+	sg = sg_from_sd(dev->path);
+	if (!sg) return 0;
+
+	// printf("sg=%s\n", sg);
+	/* Must open RDRW because we write the command to the disk
+	   then read the results */
+	if ((sg_fd = open(sg, O_RDWR)) < 0)
+                return 0;
+	
+	rc = sg_read(sg_fd, (unsigned char *)buffer, count, start,
+		     dev->sector_size, &diop);
+	
+	close(sg_fd);
+	return !rc;
+}
+
+int
+ped_device_write_scsi (PedDevice* dev, const void* buffer, PedSector start,
+		       PedSector count)
+{
+	char *sg = NULL;
+	extern int sg_to_sd_map_made;
+	int rc;
+	int sg_fd, diop = 0;
+
+	// printf("in ped_device_write_scsi()\n");
+	PED_ASSERT(dev != NULL, return 0);
+	PED_ASSERT(dev->type == PED_DEVICE_SCSI, return 0);
+	PED_ASSERT(buffer != NULL, return 0);
+	PED_ASSERT(count == 1, return 0);	
+
+	if (!sg_to_sd_map_made) make_sg_to_sd_map();
+	sg = sg_from_sd(dev->path);
+	if (!sg) return 0;
+
+	// printf("sg=%s\n", sg);
+	/* Must open RDRW because we write the command to the disk
+	   then read the results */
+	if ((sg_fd = open(sg, O_RDWR)) < 0)
+                return 0;
+	
+	rc = sg_write(sg_fd, (unsigned char *)buffer, count, start,
+		     dev->sector_size, &diop);
+	
+	close(sg_fd);
+	return !rc;
+
+}
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/device_scsi.h parted-1.4.7-gpt/libparted/device_scsi.h
--- parted-1.4.7/libparted/device_scsi.h	Wed Dec 31 18:00:00 1969
+++ parted-1.4.7-gpt/libparted/device_scsi.h	Thu Jan 18 11:24:42 2001
@@ -0,0 +1,28 @@
+/*
+    libparted - a library for manipulating disk partitions
+    Copyright (C) 1998-2000 Free Software Foundation, Inc.
+
+    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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "parted/device.h"
+
+int
+ped_device_read_scsi (PedDevice* dev, const void* buffer, PedSector start,
+		      PedSector count);
+int
+ped_device_write_scsi (PedDevice* dev, const void* buffer, PedSector start,
+		       PedSector count);
+
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/disk.c parted-1.4.7-gpt/libparted/disk.c
--- parted-1.4.7/libparted/disk.c	Mon Jan  8 10:49:15 2001
+++ parted-1.4.7-gpt/libparted/disk.c	Thu Jan 18 11:32:50 2001
@@ -174,6 +174,7 @@
 	disk->dev = dev;
 	disk->type = disk_type;
 	disk->update_mode = 0;
+	disk->disk_specific = NULL;
 
 	disk->part_list = ped_partition_new (
 		disk, PED_PARTITION_FREESPACE, NULL,
@@ -581,6 +582,7 @@
 	part->type = type;
 	part->part_list = NULL;
 	part->fs_type = fs_type;
+	part->disk_specific = NULL;
 
 	return part;
 
@@ -599,6 +601,8 @@
 	PedPartition*	part;
 
 	PED_ASSERT (disk != NULL, return NULL);
+	PED_ASSERT (disk->type != NULL, return NULL);
+	PED_ASSERT (disk->type->ops != NULL, return NULL);
 	PED_ASSERT (disk->type->ops->partition_new != NULL, return NULL);
 
 	supports_extended = ped_disk_type_check_feature (disk->type,
@@ -1314,10 +1318,10 @@
 	PED_ASSERT (part != NULL, return 0);
 
 #ifdef VERBOSE
-	printf ("ped_disk_add_partition (dev=\"%s\", start=%d, end=%d,"
+	printf ("ped_disk_add_partition (dev=\"%s\", start=%llx, end=%llx,"
 		" type=%x)\n",
-		disk->dev->path, (int) part->geom.start, (int) part->geom.end,
-		(int) part->system);
+		disk->dev->path, part->geom.start, part->geom.end,
+		part->type);
 #endif
 
 	if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/disk_dos.c parted-1.4.7-gpt/libparted/disk_dos.c
--- parted-1.4.7/libparted/disk_dos.c	Tue Jan  9 12:29:52 2001
+++ parted-1.4.7-gpt/libparted/disk_dos.c	Mon Jan 22 11:42:31 2001
@@ -232,6 +232,12 @@
 			return 0;
 	}
 
+	/* If this is a GPT disk, fail here */
+	for (i = 0; i < 4; i++) {
+		if (part_table.partitions[i].type == 0xEE)
+ 			return 0;
+ 	}
+
 	/* HACK: it's impossible to tell PC98 and msdos disk labels apart.
 	 * Someone made the signatures the same (very clever).  Since
 	 * PC98 has some idiosyncracies with it's boot-loader, it's detection
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/disk_gpt.c parted-1.4.7-gpt/libparted/disk_gpt.c
--- parted-1.4.7/libparted/disk_gpt.c	Wed Dec 31 18:00:00 1969
+++ parted-1.4.7-gpt/libparted/disk_gpt.c	Wed Jan 24 11:47:09 2001
@@ -0,0 +1,1738 @@
+/*
+    libparted - a library for manipulating disk partitions
+
+    Copyright (C) 2000-2001 Dell Computer Corporation
+    disk_gpt.[ch] by Matt Domsch <Matt_Domsch@dell.com> 
+
+    EFI GUID Partition Table handling
+    Per Intel EFI Specification v1.02
+    http://developer.intel.com/technology/efi/efi.htm
+
+    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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* 
+   TODO:
+   - Make partition labels get/set properly
+*/
+
+#include "config.h"
+
+#include <parted/parted.h>
+#include <parted/endian.h>
+#include <parted/crc32.h>
+#include <parted/disk_gpt.h>
+#include <parted/natmath.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <uuid/uuid.h>
+#include <unicode.h>
+
+#include <libintl.h>
+#if ENABLE_NLS
+#  define _(String) gettext (String)
+#else
+#  define _(String) (String)
+#endif				/* ENABLE_NLS */
+
+
+void ped_disk_gpt_init();
+void ped_disk_gpt_done();
+
+static int gpt_probe(const PedDevice * dev);
+static PedDisk *gpt_open(PedDevice * dev);
+static PedDisk *gpt_create(PedDevice * dev);
+static int gpt_clobber(PedDevice * dev);
+static int gpt_close(PedDisk * disk);
+static int gpt_read(PedDisk * disk);
+static int gpt_write(PedDisk * disk);
+
+
+static PedPartition *gpt_partition_new(const PedDisk *disk,
+                             PedPartitionType part_type,
+                             const PedFileSystemType* fs_type,
+                             PedSector start,
+                             PedSector end);
+static void gpt_partition_destroy(PedPartition *part);
+static int gpt_partition_set_flag(PedPartition *part,
+                                  PedPartitionFlag flag,
+                                  int state);
+static int gpt_partition_get_flag(const PedPartition *part,
+                                  PedPartitionFlag flag);
+static int gpt_partition_is_flag_available(const PedPartition * part,
+                                           PedPartitionFlag flag);
+static void gpt_partition_set_name(PedPartition *part,
+                                   const char *name);
+static const char * gpt_partition_get_name (const PedPartition * part);
+static int gpt_partition_align(PedPartition * part,
+                               const PedConstraint * constraint);
+static int gpt_partition_enumerate(PedPartition * part);
+
+static int gpt_alloc_metadata(PedDisk * disk);
+static int gpt_get_max_primary_partition_count(const PedDisk *disk);
+
+/* gpt private function */
+static PedDisk * gpt_new(PedDisk * disk);
+
+static PedDiskOps gpt_disk_ops = {
+	probe                           : gpt_probe,
+	open                            : gpt_open,
+	create                          : gpt_create,
+        clobber                         : gpt_clobber,
+	close                           : gpt_close,
+	read                            : gpt_read,
+	write                           : gpt_write,
+        partition_new                   : gpt_partition_new,
+        partition_destroy               : gpt_partition_destroy,
+        partition_set_flag              : gpt_partition_set_flag,
+        partition_get_flag              : gpt_partition_get_flag,
+        partition_is_flag_available     : gpt_partition_is_flag_available,
+        partition_set_name              : gpt_partition_set_name,
+        partition_get_name              : gpt_partition_get_name,
+	partition_align                 : gpt_partition_align,
+	partition_enumerate             : gpt_partition_enumerate,
+	partition_set_extended_system   : NULL,
+	alloc_metadata                  : gpt_alloc_metadata,
+        get_max_primary_partition_count : gpt_get_max_primary_partition_count
+
+};
+
+static PedDiskType gpt_disk_type = {
+	next:NULL,
+	name:GPT_NAME,
+	ops:&gpt_disk_ops,
+        features: PED_DISK_TYPE_PARTITION_NAME
+};
+
+
+
+/************************************************************
+ * efi_crc32()
+ * Requires:
+ *  - a buffer of length len
+ * Modifies: nothing
+ * Returns:
+ *  EFI-style CRC32 value for buf
+ *  
+ * This function uses the crc32 function by Gary S. Brown,
+ * but seeds the function with ~0, and xor's with ~0 at the end.
+ ************************************************************/
+
+static inline __u32
+efi_crc32(const void *buf, unsigned long len)
+{
+  return (crc32(buf, len, ~0L) ^ ~0L);
+}
+
+
+static inline int
+IsLegacyMBRValid(LegacyMBR_t * mbr)
+{
+	return (mbr ? (mbr->Signature == MSDOS_MBR_SIGNATURE) : 0);
+}
+
+static inline int
+efi_guidcmp(efi_guid_t left, efi_guid_t right)
+{
+	return memcmp(&left, &right, sizeof(efi_guid_t));
+}
+
+
+/************************************************************
+ * LastLBA()
+ * Requires:
+ *  - dev
+ * Modifies: nothing
+ * Returns:
+ *  Last LBA value on success 
+ *  0 on error
+ ************************************************************/
+
+
+static __u64
+LastLBA(const PedDevice * dev)
+{
+        __u64 lastlba;
+	PED_ASSERT(dev != NULL, return 0);
+        lastlba = dev->length - 1;
+        /* Kludge until either:
+           a) kernel can read/write last
+           block on an odd-sized disk, or 
+           b) we use scsi-generic to do it.
+        */
+        // if (!(lastlba & 1)) lastlba--;
+        return lastlba;
+}
+
+
+
+/************************************************************
+ * IsLBAValid()
+ * Requires:
+ *  - dev
+ *  - lba is the logical block address desired
+ * Modifies: nothing
+ * Returns:
+ * - 1 if true
+ * - 0 if false
+ ************************************************************/
+
+
+
+static inline int
+IsLBAValid(PedDevice *dev, __u64 lba)
+{
+	return (lba <= LastLBA(dev));
+}
+
+
+/************************************************************
+ * WriteLBA()
+ * Requires:
+ *  - dev
+ *  - lba is the logical block address desired
+ *  - buffer is a buffer of size size into which data is read
+ *  - size_t count is size of the read (in bytes)
+ * Modifies:
+ *  - dev
+ * Returns:
+ *  - 1 on success
+ *  - 0 on error
+ ************************************************************/
+
+static int
+WriteLBA(PedDevice * dev, __u64 lba, void *buffer, size_t count)
+{
+	size_t blocks;
+        //printf("WriteLBA(lba=%llx, count=%llx)\n", lba, count);
+        PED_ASSERT(dev != NULL, return 0);
+        PED_ASSERT(dev->sector_size != 0, return 0);
+	blocks = count / dev->sector_size;
+	if (count % dev->sector_size)
+		blocks++;
+	return ped_device_write(dev, buffer, lba, blocks);
+}
+
+/************************************************************
+ * ReadLBA()
+ * Requires:
+ *  - dev
+ *  - lba is the logical block address desired
+ *  - buffer is a buffer of size size into which data is read
+ *  - size_t count is size of the read (in bytes)
+ * Modifies:
+ *  - dev
+ * Returns:
+ *  - 1 on success
+ *  - 0 on error
+ ************************************************************/
+
+static int
+ReadLBA(const PedDevice * dev, __u64 lba, void *buffer, size_t count)
+{
+	size_t blocks;
+        PED_ASSERT(dev != NULL, return 0);
+        PED_ASSERT(dev->sector_size != 0, return 0);
+        //printf("ReadLBA(lba=%llx, count=%llx)\n", lba, count);
+	blocks = count / dev->sector_size;
+	if (count % dev->sector_size)
+		blocks++;
+	return ped_device_read(dev, buffer, lba, blocks);
+}
+
+
+
+/************************************************************
+ * ReadGuidPartitionEntries()
+ * Requires:
+ *  - dev
+ *  - lba is the Logical Block Address of the partition table
+ *  - gpt is a buffer into which the GPT will be put  
+ * Modifies:
+ *  - dev
+ *  - gpt
+ * Returns:
+ *   pte on success
+ *   NULL on error
+ * Notes: remember to free pte when you're done!
+ ************************************************************/
+static GuidPartitionEntry_t *
+ReadGuidPartitionEntries(const PedDevice * dev,
+                         GuidPartitionTableHeader_t *
+                         gpt)
+{
+	GuidPartitionEntry_t *pte;
+
+	PED_ASSERT(dev != NULL, return NULL);
+	PED_ASSERT(gpt != NULL, return NULL);
+
+	pte = (GuidPartitionEntry_t *)
+                ped_malloc(gpt->NumberOfPartitionEntries *
+                           gpt->SizeOfPartitionEntry);
+
+        PED_ASSERT(pte != NULL, return NULL);
+
+        memset(pte, 0, gpt->NumberOfPartitionEntries *
+               gpt->SizeOfPartitionEntry);
+
+
+	if (!ReadLBA(dev, gpt->PartitionEntryLBA, pte,
+		     gpt->NumberOfPartitionEntries *
+		     gpt->SizeOfPartitionEntry)) {
+		free(pte);
+		return NULL;
+	}
+	return pte;
+}
+
+/************************************************************
+ * WriteGuidPartitionEntries()
+ * Requires:
+ *  - PedDevice *dev
+ *  - gpt 
+ *  - pte is a buffer that will be written
+ * Modifies:
+ *  - dev
+ *  - gpt
+ * Returns:
+ *   pte on success
+ *   NULL on error
+ * Notes: remember to free pte when you're done!
+ ************************************************************/
+static GuidPartitionEntry_t *
+WriteGuidPartitionEntries(PedDevice * dev,
+                          GuidPartitionTableHeader_t * gpt,
+                          GuidPartitionEntry_t *ptes)
+{
+        PED_ASSERT(gpt != NULL, return NULL);
+        PED_ASSERT(ptes != NULL, return NULL);
+
+	if (!WriteLBA
+	    (dev, gpt->PartitionEntryLBA, ptes,
+	     gpt->NumberOfPartitionEntries *
+	     gpt->SizeOfPartitionEntry)) return NULL;
+	return ptes;
+}
+
+
+static void
+PrintGuidPartitionEntry(GuidPartitionEntry_t * pte, int i)
+{
+	efi_guid_t unused_guid = UNUSED_ENTRY_GUID;
+	char uuid_buffer[40];
+	uuid_t uuid;
+        PED_ASSERT(pte != NULL, return);
+	if (!efi_guidcmp(pte->PartitionTypeGuid, unused_guid)) {
+		// printf("UNUSED_ENTRY_GUID\n");
+		return;
+	}
+	printf("GUID Partition Entry %d:\n", i);
+	memcpy(uuid, &pte->PartitionTypeGuid, sizeof(uuid_t));
+	uuid_unparse(uuid, uuid_buffer);
+	printf("\tPartitionTypeGuid : %s\n", uuid_buffer);
+	memcpy(uuid, &pte->UniquePartitionGuid, sizeof(uuid_t));
+	uuid_unparse(uuid, uuid_buffer);
+	printf("\tUniquePartitionGuid : %s\n", uuid_buffer);
+	printf("\tStartingLBA : %llx\n", pte->StartingLBA);
+	printf("\tEndingLBA   : %llx\n", pte->EndingLBA);
+	printf("\tAttributes  : ");
+	printf("\tRequiredToFunction: %x",
+	       pte->Attributes.RequiredToFunction);
+	printf("\tGuidSpecific: %x\n",
+	       pte->Attributes.GuidSpecific);
+        
+	//  printf("\tPartitionName : Unicode string.\n");
+	return;
+}
+
+
+static void
+PrintGuidPartitionTableHeader(GuidPartitionTableHeader_t * gpt)
+{
+	char uuid_buffer[40];
+	uuid_t uuid;
+	printf("GUID Partition Table Header\n");
+        PED_ASSERT(gpt != NULL, return);
+	printf("Signature      : %llx\n", gpt->Signature);
+	printf("Revision       : %x\n", gpt->Revision);
+	printf("HeaderSize     : %x\n", gpt->HeaderSize);
+	printf("HeaderCRC32    : %x\n", gpt->HeaderCRC32);
+	printf("MyLBA          : %llx\n", gpt->MyLBA);
+	printf("AlternateLBA   : %llx\n", gpt->AlternateLBA);
+	printf("FirstUsableLBA : %llx\n", gpt->FirstUsableLBA);
+	printf("LastUsableLBA  : %llx\n", gpt->LastUsableLBA);
+	memcpy(uuid, &gpt->DiskGUID, sizeof(uuid_t));
+	uuid_unparse(uuid, uuid_buffer);
+	printf("DiskGUID : %s\n", uuid_buffer);
+	printf("PartitionEntryLBA : %llx\n", gpt->PartitionEntryLBA);
+	printf("NumberOfPartitionEntries : %x\n",
+	       gpt->NumberOfPartitionEntries);
+	printf("SizeOfPartitionEntry : %x\n", gpt->SizeOfPartitionEntry);
+	printf("PartitionEntryArrayCRC32 : %x\n",
+	       gpt->PartitionEntryArrayCRC32); return;
+}
+
+
+/************************************************************
+ * ReadGuidPartitionTableHeader()
+ * Requires:
+ *  - dev
+ *  - lba is the Logical Block Address of the partition table
+ * Modifies:
+ *  - dev
+ * Returns:
+ *   GPTH on success
+ *   NULL on error
+ ************************************************************/
+static GuidPartitionTableHeader_t *
+ReadGuidPartitionTableHeader(const PedDevice * dev,
+                             __u64 lba)
+{
+	GuidPartitionTableHeader_t *gpt;
+	PED_ASSERT(dev != NULL, return 0);
+	gpt = (GuidPartitionTableHeader_t *)
+	    ped_malloc(sizeof(GuidPartitionTableHeader_t));
+        if (!gpt) return NULL;
+        memset(gpt, 0, sizeof (*gpt));
+	if (!ReadLBA(dev, lba, gpt, sizeof(GuidPartitionTableHeader_t))) {
+		free(gpt);
+		return NULL;
+	}
+
+	return gpt;
+}
+
+/************************************************************
+ * WriteGuidPartitionTableHeader()
+ * Requires:
+ *  - dev
+ *  - lba is the Logical Block Address of the partition table
+ *  - gpt is a buffer into which the GPT will be put  
+ * Modifies:
+ *  - dev
+ * Returns:
+ *   1 on success
+ *   0 on error
+ ************************************************************/
+static int
+WriteGuidPartitionTableHeader(PedDevice *dev,
+			      GuidPartitionTableHeader_t * gpt)
+{
+        PED_ASSERT(gpt != NULL, return 0);
+	if (!WriteLBA
+	    (dev, gpt->MyLBA, gpt,
+	     sizeof(GuidPartitionTableHeader_t))) return 0;
+	return 1;
+}
+
+
+/************************************************************
+ * IsGuidPartitionTableValid()
+ * Requires:
+ *  - dev
+ *  - lba is the Logical Block Address of the partition table
+ * Modifies:
+ *  - dev
+ *  - gpt  - reads data into gpt
+ *  - ptes - reads data into ptes
+ * Returns:
+ *   1 if valid
+ *   0 on error
+ ************************************************************/
+
+
+static int
+IsGuidPartitionTableValid(const PedDevice * dev, __u64 lba,
+			  GuidPartitionTableHeader_t ** gpt,
+			  GuidPartitionEntry_t ** ptes)
+{
+	int rc = 0;		/* default to not valid */
+	__u32 crc, origcrc;
+	PED_ASSERT(gpt != NULL, return 0);
+	PED_ASSERT(ptes != NULL, return 0);
+        // printf("IsGuidPartitionTableValid(%llx)\n", lba);
+	if (!(*gpt = ReadGuidPartitionTableHeader(dev, lba)))
+		return rc;
+	/* Check the GUID Partition Table Signature */
+	if ((*gpt)->Signature != GUID_PT_HEADER_SIGNATURE) {
+                /* 
+                printf("GUID Partition Table Header Signature is wrong: %llx != %llx\n",
+			(*gpt)->Signature, GUID_PT_HEADER_SIGNATURE);
+                */
+		free(*gpt);
+		*gpt = NULL;
+		return rc;
+	}
+
+	/* Check the GUID Partition Table Header CRC */
+	origcrc = (*gpt)->HeaderCRC32;
+	(*gpt)->HeaderCRC32 = 0;
+	crc = efi_crc32(*gpt, (*gpt)->HeaderSize);
+	if (crc != origcrc) {
+		// printf( "GPTH CRC check failed, %x != %x.\n", origcrc, crc);
+		(*gpt)->HeaderCRC32 = origcrc;
+		PrintGuidPartitionTableHeader(*gpt);
+		free(*gpt);
+		*gpt = NULL;
+		return rc;
+	}
+	(*gpt)->HeaderCRC32 = origcrc;
+	/* Check that the MyLBA entry points to the LBA
+	   that contains the GPT we read */
+	if ((*gpt)->MyLBA != lba) {
+		// printf( "MyLBA %llx != lba %llx.\n", (*gpt)->MyLBA, lba);
+		free(*gpt);
+		*gpt = NULL;
+		return rc;
+	}
+
+	if (!(*ptes = ReadGuidPartitionEntries(dev, *gpt))) {
+		free(*gpt);
+		*gpt = NULL;
+		return rc;
+	}
+
+
+	/* Check the GUID Partition Entry Array CRC */
+	crc = efi_crc32(*ptes, (*gpt)->NumberOfPartitionEntries *
+			   (*gpt)->SizeOfPartitionEntry);
+	if (crc != (*gpt)->PartitionEntryArrayCRC32) {
+		// printf("GUID Partitition Entry Array CRC check failed.\n");
+		free(*gpt);
+		*gpt = NULL;
+		free(*ptes);
+		*ptes = NULL;
+		return rc;
+	}
+
+	/* We're done, all's well */
+	return 1;
+}
+
+/************************************************************
+ * CreateNewPMBR()
+ * Requires:
+ *  - dev
+ * Modifies:
+ *  - dev
+ * Returns:
+ *   1 on success
+ *   0 on error
+ ************************************************************/
+
+
+static int
+CreateNewPMBR(PedDevice * dev)
+{
+	LegacyMBR_t pmbr;
+	memset(&pmbr, 0, sizeof(pmbr));
+	pmbr.Signature = MSDOS_MBR_SIGNATURE;
+	pmbr.PartitionRecord[0].OSType = EFI_PMBR_OSTYPE_EFI_GPT;
+	pmbr.PartitionRecord[0].EndHead = 0xFF;
+	pmbr.PartitionRecord[0].EndSector = 0xFE;
+	pmbr.PartitionRecord[0].EndTrack = 0xFF;
+	pmbr.PartitionRecord[0].StartingLBA = 1;
+	pmbr.PartitionRecord[0].SizeInLBA = LastLBA(dev) + 1;
+	if (!WriteLBA(dev, 0, &pmbr, sizeof(pmbr))) {
+
+		// printf("CreateNewPMBR(): Unable to create new PMBR.\n");
+		return 0;
+	}
+
+	return 1;
+
+}
+
+
+#if 0
+static int
+UpdateGuidPartition(PedPartition *part)
+{
+        GPTPartitionData *gpt_part_data;
+        PED_ASSERT(part != NULL, return -1);
+        PED_ASSERT(part->disk_specific != NULL, return 0);
+
+        gpt_part_data = part->disk_specific;
+        PED_ASSERT(gpt_part_data->pte != NULL, return -1);
+
+        gpt_part_data->pte->StartingLBA = part->geom.start;
+        gpt_part_data->pte->EndingLBA   = part->geom.end;
+        gpt_part_data->pte->PartitionTypeGuid =  PARTITION_BASIC_DATA_GUID;
+
+        /* FIXME: need to change type to PARTITION_SYSTEM_GUID
+           or tag raid and lvm flags into attributes */
+
+        return 1;
+}
+#endif
+
+#if 0
+/***********************************
+ * CreateDefaultMSRGuidPartition()
+ *
+ * Returns: 1 on success, 0 on failure
+ *
+ */
+
+
+static int
+CreateDefaultMSRGuidPartition(GuidPartitionTableHeader_t * gpt,
+			      GuidPartitionEntry_t * pte)
+{
+	__u64 size;
+	int i;
+        PED_ASSERT(gpt != NULL, return 0);
+        PED_ASSERT(pte != NULL, return 0);
+
+	/* The rule is :
+	   On drives < 16GB, MSR is 32MB.
+	   On drives >= 16GB, MSR is 128MB.
+	 */
+
+	/* This accounts for block size == 512 */
+	if (gpt->LastUsableLBA < 16 * 1024 * 1024 * 2)
+		size = (16 * 1024 * 1024) / 512;
+	else
+		size = (128 * 1024 * 1024) / 512;
+
+	i = CreateNextGuidPartition(gpt, pte, size);
+	if (i == -1)
+		return 0;
+
+	pte[i].PartitionTypeGuid = PARTITION_MSFT_RESERVED_GUID;
+	return 1;
+}
+
+
+static int
+CreateDefaultEFIGuidPartition(GuidPartitionTableHeader_t * gpt,
+			      GuidPartitionEntry_t * pte)
+{
+	int i;
+	__u64 size;
+        PED_ASSERT(gpt != NULL, return 0);
+        PED_ASSERT(pte != NULL, return 0);
+
+
+	/* The rule is :
+	   size = MAX(100MB, MIN(1% of physical disk, 1GB)) 
+	 */
+	size = PED_MAX((100 * 1024 * 1024) / 512;
+		   PED_MIN(gpt->LastUsableLBA / 100,
+		       (1024 * 1024 * 1024) / 512));
+
+	i = CreateNextGuidPartition(gpt, pte, size);
+	if (i == -1)
+		return 0;
+	pte[i].PartitionTypeGuid = PARTITION_SYSTEM_GUID;
+	return 1;
+}
+#endif
+
+/************************************************************n
+ * UpdateGuidPartitionTableHeaders()
+ * Updates the CRC fields for both primary and alternate GPTs
+ *
+ */
+static int
+UpdateGuidPartitionTableHeaders(GuidPartitionTableHeader_t *pgpt,
+                                GuidPartitionTableHeader_t *agpt,
+                                GuidPartitionEntry_t *ptes)
+{
+
+        // printf("in UpdateGuidPartitionTableHeaders()\n");
+        PED_ASSERT(pgpt != NULL, return 0);
+        PED_ASSERT(agpt != NULL, return 0);
+        PED_ASSERT(ptes != NULL, return 0);
+
+	pgpt->PartitionEntryArrayCRC32 =
+                agpt->PartitionEntryArrayCRC32 =
+                efi_crc32(ptes, pgpt->NumberOfPartitionEntries *
+                          pgpt->SizeOfPartitionEntry);
+        
+	pgpt->HeaderCRC32 = 0;
+	pgpt->HeaderCRC32 = efi_crc32(pgpt, pgpt->HeaderSize);
+	agpt->HeaderCRC32 = 0;
+	agpt->HeaderCRC32 = efi_crc32(agpt, agpt->HeaderSize);
+        return 1;
+}
+
+
+
+static int
+CreateNewGuidPartitionTableHeader(PedDevice *dev)
+{
+	__u64 size;
+	uuid_t uuid;
+	GuidPartitionTableHeader_t gpt, agpt;
+	GuidPartitionEntry_t ptes[GPT_DEFAULT_RESERVED_PARTITION_ENTRIES];
+	int count;
+
+        // printf("in CreateNewGuidPartitionTableHeader()\n");
+	memset(&gpt, 0, sizeof(gpt));
+	gpt.Signature = GUID_PT_HEADER_SIGNATURE;
+	gpt.Revision = GUID_PT_HEADER_REVISION_V1_02;
+	gpt.HeaderSize = 92; /* per 1.02 spec */
+	gpt.MyLBA = 1;
+	gpt.AlternateLBA = LastLBA(dev);
+	gpt.FirstUsableLBA = (GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE /
+                              dev->sector_size) + 2;
+	gpt.LastUsableLBA =
+                gpt.AlternateLBA -
+                (GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE /
+                 dev->sector_size) - 1;
+	uuid_generate(uuid);
+	memcpy(&(gpt.DiskGUID), uuid, sizeof(uuid));
+	gpt.PartitionEntryLBA = 2;
+	gpt.NumberOfPartitionEntries = GPT_DEFAULT_RESERVED_PARTITION_ENTRIES;
+	gpt.SizeOfPartitionEntry = sizeof(GuidPartitionEntry_t);
+
+	memset(ptes, 0,
+	       gpt.NumberOfPartitionEntries * gpt.SizeOfPartitionEntry);
+
+	/* Fix up Alternate GPT */
+	memcpy(&agpt, &gpt, sizeof(gpt));
+	agpt.MyLBA = gpt.AlternateLBA;
+	agpt.AlternateLBA = gpt.MyLBA;
+	agpt.PartitionEntryLBA = agpt.MyLBA -
+                (GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE /
+                 dev->sector_size);
+
+        if (!UpdateGuidPartitionTableHeaders(&gpt, &agpt, ptes))
+                return 0;
+
+        // printf("update successful\n");
+
+	/* Before the writes */
+	/* Write PTH and PTEs */
+	if (!WriteGuidPartitionTableHeader(dev, &gpt))
+		return 0;
+	if (!WriteGuidPartitionEntries(dev, &gpt, ptes))
+		return 0;
+
+
+	/* Write Alternate PTH & PTEs */
+	if (!WriteGuidPartitionEntries(dev, &agpt, ptes))
+		return 0;
+	if (!WriteGuidPartitionTableHeader(dev, &agpt))
+		return 0;
+
+	return 1;
+}
+
+
+
+static int
+CreateNewGPTDisk(PedDevice * dev)
+{
+	if (!CreateNewPMBR(dev))
+		return 0;
+	if (!CreateNewGuidPartitionTableHeader(dev))
+		return 0;
+	return 1;
+}
+
+
+/************************************************************
+ * FixPrimaryGuidPartitionTable()
+ * Uses values from alternate GPT and puts them in primary GPT.
+ * Requires:
+ * pgpt, agpt, ptes.
+ *  
+ * Modifies:
+ * pgpt
+ * 
+ * Returns:
+ *   1 if valid
+ *   0 on error
+ ************************************************************/
+
+static int
+FixBrokenGuidPartitionTable(PedDevice *dev,
+                            GuidPartitionTableHeader_t **badgpt,
+                            GuidPartitionTableHeader_t *goodgpt,
+                            GuidPartitionEntry_t     *ptes)
+{
+
+        PED_ASSERT(badgpt != NULL, return 0);
+        PED_ASSERT(goodgpt != NULL, return 0);
+        PED_ASSERT(ptes != NULL, return 0);
+
+	*badgpt = (GuidPartitionTableHeader_t *)
+                ped_malloc(sizeof(GuidPartitionTableHeader_t));
+	if (!*badgpt) return 0;
+        memset(*badgpt, 0, sizeof(**badgpt));
+
+	memcpy(*badgpt, goodgpt, sizeof(*goodgpt));
+
+	/* Change badgpt values */
+	(*badgpt)->MyLBA = goodgpt->AlternateLBA;
+	(*badgpt)->AlternateLBA = goodgpt->MyLBA;
+
+        
+        if ((*badgpt)->MyLBA == 1) 
+                (*badgpt)->PartitionEntryLBA = (*badgpt)->MyLBA + 1;
+        else
+                (*badgpt)->PartitionEntryLBA = (*badgpt)->MyLBA - 
+                        (GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE /
+                         dev->sector_size);
+        
+        return UpdateGuidPartitionTableHeaders(*badgpt, goodgpt, ptes);
+}
+
+
+
+
+static void
+PrintPartitionRecord(PartitionRecord_t * pr, int i)
+{
+	if (!pr)
+		return;
+	if (!(pr->OSType))
+		return;
+	printf("Legacy Partition Record %d\n", i);
+	printf("\tBootInd %02x", pr->BootIndicator);
+	printf("\tSHead %02x", pr->StartHead);
+	printf("\tSSector %02x", pr->StartSector);
+	printf("\tSTrack %02x\n", pr->StartTrack);
+	printf("\tOSType %02x", pr->OSType);
+	printf("\tEHead %02x", pr->EndHead);
+	printf("\tESector %02x", pr->EndSector);
+	printf("\tETrack %02x\n", pr->EndTrack);
+	printf("\tStartingLBA : %x", pr->StartingLBA);
+	printf("\tSizeInLBA : %x\n", pr->SizeInLBA);
+	return;
+}
+
+static void
+PrintLegacyMBR(LegacyMBR_t * mbr)
+{
+	int i;
+	if (!mbr)
+		return;
+	if (!IsLegacyMBRValid(mbr)) {
+		printf("MBR is invalid.\n");
+		return;
+	}
+
+	printf("UniqueMBRSignature: %x\n", mbr->UniqueMBRSignature);
+	for (i = 0; i < 4; i++)
+		PrintPartitionRecord(&(mbr->PartitionRecord[i]), i);
+	printf("Signature: %x\n", mbr->Signature);
+	return;
+}
+
+
+
+/************************************************************
+ * FindValidGPT()
+ * Requires:
+ *  - dev 
+ *  - pgpt is a GPTH if it's valid
+ *  - agpt is a GPTH if it's valid
+ *  - ptes is a PTE
+ * Modifies:
+ *  - gpt & ptes
+ * Returns:
+ *   1 if valid
+ *   0 on error
+ ************************************************************/
+static int
+FindValidGPT(const PedDevice * dev,
+	     GuidPartitionTableHeader_t ** pgpt,
+             GuidPartitionTableHeader_t ** agpt,
+	     GuidPartitionEntry_t       ** ptes)
+{
+	int rc = 0;
+	GuidPartitionEntry_t *pptes = NULL, *aptes = NULL;
+	__u64 lastlba;
+
+        PED_ASSERT(dev  != NULL, return 0);
+        PED_ASSERT(pgpt != NULL, return 0);
+        PED_ASSERT(agpt != NULL, return 0);
+        PED_ASSERT(ptes != NULL, return 0);
+
+        // printf("FindValidGPT()\n");
+	lastlba = LastLBA(dev);
+	/* Check the Primary GPT */
+	rc = IsGuidPartitionTableValid(dev, 1, pgpt, &pptes);
+	if (rc) {
+		/* Primary GPT is OK, check the alternate and warn if bad */
+		rc = IsGuidPartitionTableValid(dev, (*pgpt)->AlternateLBA,
+					       agpt, &aptes);
+
+		if (!rc) {
+                        *agpt = NULL;
+                        printf("Alternate GPT is invalid, using primary GPT.\n");
+
+		}
+		if (aptes) free(aptes);
+		*ptes = pptes;
+		return 1;
+	} /* if primary is valid */
+	else {
+		/* Primary GPT is bad, check the Alternate GPT */
+                *pgpt = NULL;
+		rc = IsGuidPartitionTableValid(dev, lastlba,
+					       agpt, &aptes);
+		if (rc) {
+			/* Primary is bad, alternate is good.
+			   Return values from the alternate and warn.
+			 */
+			printf
+			    ("Primary GPT is invalid, using alternate GPT.\n");
+			*ptes = aptes;
+			return 1;
+		}
+	}
+	/* Both primary and alternate GPTs are bad.
+	 * This isn't our disk, return 0.
+	 */
+        *pgpt = NULL;
+        *agpt = NULL;
+        *ptes = NULL;
+	return 0;
+}
+
+
+static void
+PrintDiskInfo(PedDevice *dev)
+{
+	unsigned int i;
+	LegacyMBR_t mbr;
+	GuidPartitionTableHeader_t *pgpt = NULL, *agpt = NULL, *gpt = NULL;
+	GuidPartitionEntry_t *pte = NULL, zeropte;
+
+        // printf("PrintDiskInfo()\n");
+	memset(&zeropte, 0, sizeof(zeropte));
+	if (!ReadLBA(dev, 0, &mbr, sizeof(mbr))) {
+		printf("PrintDiskInfo error: ReadLBA(mbr) error.\n");
+		return;
+	}
+	PrintLegacyMBR(&mbr);
+	if (mbr.PartitionRecord[0].OSType == EFI_PMBR_OSTYPE_EFI_GPT) {
+		/* This is an EFI GPT disk */
+		if (!ReadLBA(dev, 1, &pgpt, sizeof(*pgpt))) {
+			printf("PrintDiskInfo error: ReadLBA(gpt) error.\n");
+			return;
+		}
+		printf("This is an EFI GPT disk.\n");
+                if (FindValidGPT(dev, &pgpt, &agpt, &pte)) {
+                        if (pgpt) gpt = pgpt;
+                        else if (agpt) gpt = agpt;
+                }
+                else {
+			printf("GUID Partition Table is invalid.\n");
+			return;
+		}
+		for (i = 0; pte && i < gpt->NumberOfPartitionEntries; i++) {
+			/* Partition entry is unused if all bytes are 0 */
+			if (memcmp(&zeropte, &pte[i], sizeof(zeropte)))
+				PrintGuidPartitionEntry(&pte[i], i);
+		}
+		if (pgpt) free(pgpt);
+		if (agpt) free(agpt);
+		if (pte)  free(pte);
+	} else {
+		printf("This is not an EFI GPT disk.  Try using fdisk.\n");
+	}
+	return;
+}
+
+
+
+
+
+
+void
+ped_disk_gpt_init()
+{
+	PED_ASSERT(sizeof(GuidPartitionTableHeader_t) == 512, return);
+	PED_ASSERT(sizeof(GuidPartitionEntryAttributes_t) == 8, return);
+	PED_ASSERT(sizeof(GuidPartitionEntry_t) == 128, return);
+
+	ped_register_disk_type(&gpt_disk_type);
+}
+
+void
+ped_disk_gpt_done()
+{
+	ped_unregister_disk_type(&gpt_disk_type);
+}
+
+static int
+gpt_probe(const PedDevice * dev)
+{
+	GuidPartitionTableHeader_t *pgpt = NULL, *agpt = NULL;
+	GuidPartitionEntry_t *ptes = NULL;
+
+	PED_ASSERT(dev != NULL, return 0);
+
+        // printf("gpt_probe()\n");
+
+	if (!ped_device_open((PedDevice *) dev))
+		return 0;
+
+	if (!(FindValidGPT(dev, &pgpt, &agpt, &ptes))) {
+		ped_device_close((PedDevice *) dev);
+		return 0;
+	}
+
+	ped_device_close((PedDevice *) dev);
+
+	if (pgpt) free(pgpt);
+	if (agpt) free(agpt);
+	if (ptes) free(ptes);
+        // printf("gpt_probe returning 1\n");
+	return 1;
+}
+
+static PedDisk *
+gpt_open(PedDevice * dev)
+{
+	PedDisk *disk;
+
+        // printf("gpt_open()\n");
+
+	PED_ASSERT(dev != NULL, return 0);
+
+	if (!gpt_probe(dev))
+		goto error;
+        
+
+	ped_device_open((PedDevice *) dev);
+
+        // printf("gpt_open() called ped_device_open()\n");
+	disk = ped_disk_alloc(dev, &gpt_disk_type);
+        // printf("gpt_open called ped_disk_alloc()\n");
+
+	if (!disk)
+		goto error;
+
+        // printf("gpt_open: ped_disk_alloc() succeeded\n");
+
+        // printf("gpt_open() calling gpt_read()\n");
+	if (!gpt_read(disk))
+          goto error_free_disk_specific;
+
+        // printf("gpt_open returning disk\n");
+	return disk;
+
+      error_free_disk_specific:
+        ped_free(disk->disk_specific);
+      error_free_disk:
+	ped_free(disk);
+      error:
+        // printf("gpt_open() returning NULL\n");
+	return NULL;
+}
+
+static PedDisk *
+gpt_create(PedDevice * dev)
+{
+        PedDisk *newdisk;
+	PED_ASSERT(dev != NULL, return 0);
+
+        // printf("gpt_create()\n");
+	if (!ped_device_open(dev))
+		goto error;
+
+
+	CreateNewGPTDisk(dev);
+
+	if (!ped_device_sync(dev))
+		goto error_close_dev;
+
+	ped_device_close(dev);
+        newdisk = gpt_open(dev);
+        return newdisk;
+
+      error_close_dev:
+	ped_device_close(dev);
+      error:
+	return 0;
+}
+
+static int
+gpt_close(PedDisk * disk)
+{
+        // printf("in gpt_close()\n");
+	PED_ASSERT(disk != NULL, return 0);
+
+	ped_device_close(disk->dev);
+	ped_disk_delete_all(disk);
+        if (disk->disk_specific) ped_free(disk->disk_specific);
+	ped_free(disk);
+	return 1;
+}
+
+
+
+
+
+
+static int
+gpt_read(PedDisk * disk)
+{
+	PedPartition *part;
+	unsigned int i;
+        GPTDiskData *gpt_disk_data;
+        GPTPartitionData *gpt_part_data;
+	PedConstraint*		constraint_exact;
+        efi_guid_t unused = UNUSED_ENTRY_GUID;
+
+        // printf("in gpt_read()\n");        
+	PED_ASSERT(disk != NULL, return 0);
+	PED_ASSERT(disk->dev != NULL, return 0);
+
+
+	ped_disk_delete_all(disk);
+
+        // printf("gpt_read(): ped_disk_delete_all() returned.\n");
+
+        if (!disk->disk_specific) gpt_new(disk);
+        PED_ASSERT(disk->disk_specific != NULL, return 0);
+        gpt_disk_data = disk->disk_specific;
+
+
+	if (!FindValidGPT(disk->dev, &(gpt_disk_data->pgpt), &(gpt_disk_data->agpt), &(gpt_disk_data->ptes)))
+		return 0;
+
+        /* If one of the gpts are broken, fix it. */
+        if (!gpt_disk_data->pgpt) {
+                FixBrokenGuidPartitionTable(disk->dev,
+                                            &gpt_disk_data->pgpt,
+                                            gpt_disk_data->agpt,
+                                            gpt_disk_data->ptes);
+        }
+        else if (!gpt_disk_data->agpt) {
+                FixBrokenGuidPartitionTable(disk->dev,
+                                            &gpt_disk_data->agpt,
+                                            gpt_disk_data->pgpt,
+                                            gpt_disk_data->ptes);
+        }
+        
+	for (i = 0; i < gpt_disk_data->pgpt->NumberOfPartitionEntries; i++) {
+                
+                if (!efi_guidcmp(gpt_disk_data->ptes[i].PartitionTypeGuid,
+                                 unused)) continue;
+
+                // printf("calling ped_partition_alloc() in gpt_read(), i=%u\n", i);
+                // PrintGuidPartitionEntry(&gpt_disk_data->ptes[i], i);
+		part = ped_partition_alloc(disk, PED_PARTITION_PRIMARY, NULL,
+					 gpt_disk_data->ptes[i].StartingLBA,
+					 gpt_disk_data->ptes[i].EndingLBA);
+		if (!part)
+			return 0;
+
+                part->num = i+1;
+
+                gpt_part_data = part->disk_specific =
+                        ped_malloc(sizeof(GPTPartitionData));
+                if (!gpt_part_data) {
+                        ped_free(part);
+                        return 0;
+                }
+                memset(gpt_part_data, 0, sizeof(*gpt_part_data));
+                
+                gpt_part_data->pte  = &(gpt_disk_data->ptes[i]);
+
+                // printf("handling constraints\n");
+		constraint_exact = ped_constraint_exact (&part->geom);
+		if (!ped_disk_add_partition(disk, part, constraint_exact)) {
+			ped_free(gpt_part_data);
+                        ped_free(part);
+                        // printf("gpt_read() returning 0 after ped_disk_add_partition()\n");
+                        return 0;
+                }
+		ped_constraint_destroy (constraint_exact);
+
+	}
+        // printf("gpt_read() returning 1\n");
+	return 1;
+}
+
+
+static int
+gpt_write(PedDisk * disk)
+{
+
+        GPTDiskData *gpt_disk_data;
+        PedPartition *part = NULL;
+
+        // printf("!!!!!in gpt_write()\n");
+	PED_ASSERT(disk != NULL, return 0);
+	PED_ASSERT(disk->dev != NULL, return 0);
+        PED_ASSERT(disk->disk_specific != NULL, return 0);
+        gpt_disk_data = disk->disk_specific;
+
+        if (!CreateNewPMBR(disk->dev)) return 0;
+
+        UpdateGuidPartitionTableHeaders(gpt_disk_data->pgpt,
+                                        gpt_disk_data->agpt,
+                                        gpt_disk_data->ptes);
+
+	/* Write PTH and PTEs */
+	if (!WriteGuidPartitionTableHeader(disk->dev, gpt_disk_data->pgpt))
+		return 0;
+	if (!WriteGuidPartitionEntries(disk->dev, gpt_disk_data->pgpt, gpt_disk_data->ptes))
+		return 0;
+
+
+	/* Write Alternate PTH & PTEs */
+	if (!WriteGuidPartitionEntries(disk->dev, gpt_disk_data->agpt, gpt_disk_data->ptes))
+		return 0;
+	if (!WriteGuidPartitionTableHeader(disk->dev, gpt_disk_data->agpt))
+		return 0;
+
+
+
+
+	if (!ped_device_sync(disk->dev))
+		return 0;
+
+	return 1;
+}
+
+
+
+static int
+add_metadata_part(PedDisk * disk, PedPartitionType type, PedSector start,
+		  PedSector length)
+{
+	PedPartition *new_part;
+        PedConstraint * constraint_exact;
+	PED_ASSERT(disk != NULL, return 0);
+
+
+        // printf("calling ped_partition_new() in add_metadata_part()\n");
+	new_part =
+	    ped_partition_new(disk, type | PED_PARTITION_METADATA, NULL,
+			      start, start + length - 1);
+	if (!new_part)
+		goto error;
+
+        constraint_exact = ped_constraint_exact (&new_part->geom);
+
+	if (!ped_disk_add_partition(disk, new_part, constraint_exact))
+		goto error_destroy_new_part;
+
+	return 1;
+
+      error_destroy_new_part:
+	ped_partition_destroy(new_part);
+      error:
+	return 0;
+}
+
+static PedPartition *
+gpt_partition_new(const PedDisk *disk,
+                  PedPartitionType part_type,
+                  const PedFileSystemType* fs_type,
+                  PedSector start,
+                  PedSector end)
+{
+        unsigned int i;
+	uuid_t uuid;
+	efi_guid_t unused_entry_guid = UNUSED_ENTRY_GUID;
+        GPTDiskData *gpt_disk_data;
+        GPTPartitionData *gpt_part_data;
+        PedPartition *part;
+        
+        PED_ASSERT(disk != NULL, return NULL);
+
+
+	part = ped_partition_alloc (disk, part_type, fs_type, start, end);
+	if (!part) return NULL;
+
+        if (part_type != PED_PARTITION_PRIMARY)
+                return part;
+
+        if (!ped_disk_check_overlap(disk, part)) {
+		ped_exception_throw (
+			PED_EXCEPTION_ERROR,
+			PED_EXCEPTION_CANCEL,
+			_("The new partition overlaps with another "
+			  "partition."));
+                ped_free(part);
+                return NULL;
+        }
+
+        PED_ASSERT(disk->disk_specific != NULL, return NULL);
+
+        gpt_disk_data = disk->disk_specific;
+        // printf("in gpt_partition_new(s=%llx, e=%llx t=%d)\n", start, end, part_type);
+
+
+        PED_ASSERT(gpt_disk_data->pgpt != NULL, return NULL);
+        PED_ASSERT(gpt_disk_data->agpt != NULL, return NULL);
+        PED_ASSERT(gpt_disk_data->ptes != NULL, return NULL);
+
+
+        for (i = 0; i < gpt_disk_data->pgpt->NumberOfPartitionEntries; i++) {
+		if (!efi_guidcmp
+		    (gpt_disk_data->ptes[i].PartitionTypeGuid, unused_entry_guid)) {
+			break;
+		}
+	}
+	/* No unused entries */
+	if (i == gpt_disk_data->pgpt->NumberOfPartitionEntries){
+                ped_free(part);
+		return NULL;
+        }
+
+        // printf("Found unused entry at i=%u\n", i);
+        part->num = i + 1;
+	gpt_disk_data->ptes[i].StartingLBA = part->geom.start;
+	gpt_disk_data->ptes[i].EndingLBA = part->geom.end;
+	uuid_generate(uuid);
+	memcpy(&(gpt_disk_data->ptes[i].UniquePartitionGuid), uuid, sizeof(uuid));
+
+        gpt_disk_data->ptes[i].PartitionTypeGuid = PARTITION_BASIC_DATA_GUID;
+
+        if (fs_type && fs_type->name && !strcmp(fs_type->name, "linux-swap"))
+                gpt_disk_data->ptes[i].PartitionTypeGuid = 
+                        PARTITION_SWAP_GUID;
+
+        
+        gpt_part_data = part->disk_specific =
+                ped_malloc(sizeof(GPTPartitionData));
+        if (!gpt_part_data) return part;
+        memset(gpt_part_data, 0, sizeof(*gpt_part_data));
+
+        gpt_part_data->pte = &(gpt_disk_data->ptes[i]);
+
+        return part;
+}
+
+static void
+gpt_partition_destroy(PedPartition *part)
+{
+        GPTPartitionData *gpt_part_data;
+
+        PED_ASSERT(part != NULL, return);
+        // printf("in gpt_partition_destroy(type=%x)\n", part->type);
+
+        if (part->type != PED_PARTITION_PRIMARY)
+                return;
+
+        PED_ASSERT(part->disk_specific != NULL, return);
+        gpt_part_data = part->disk_specific;
+        if (gpt_part_data->pte)
+                memset(gpt_part_data->pte, 0, sizeof(*(gpt_part_data->pte)));
+
+        ped_free(part->disk_specific);
+        part->disk_specific = NULL;
+        ped_free(part);
+        // printf("returning from gpt_partition_destroy()\n");        
+}
+
+/**********************************************************
+ * Allocate metadata partitions for the GPTH and PTES.
+ *
+ */
+static int
+_alloc_metadata_unknown(PedDisk * disk)
+{
+        __u64 pte_reserved_blocks;
+	PED_ASSERT(disk != NULL, return 0);
+        PED_ASSERT(disk->dev != NULL, return 0);
+
+        pte_reserved_blocks = 
+                (GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE /
+                 disk->dev->sector_size);
+
+        
+        //  printf("in _alloc_metadata_unknown()\n");
+	/* metadata at the start of the disk includes the MBR */
+        // printf("adding metadata at start of the disk.\n");
+	if (!add_metadata_part(disk, PED_PARTITION_PRIMARY,
+			       0,
+                               1 + 1 + pte_reserved_blocks))
+		return 0;
+
+	/* metadata at the end of the disk */
+        // printf("adding metadata at end of the disk.\n");
+	if (!add_metadata_part(disk, PED_PARTITION_PRIMARY,
+			       LastLBA(disk->dev) -
+                               pte_reserved_blocks,
+                               1 + pte_reserved_blocks))
+                return 0;
+
+        return 1;
+}
+
+
+/**********************************************************
+ * Allocate metadata partitions for the GPTH and PTES
+ * when we know the actual metadata size
+ */
+static int
+_alloc_metadata_known(PedDisk * disk)
+{
+	int i;
+	PedSector gptlength, pteslength = 0;
+        GPTDiskData *gpt_disk_data;
+        
+        // printf("in _alloc_metadata_known()\n");
+	PED_ASSERT(disk != NULL, return 0);
+	PED_ASSERT(disk->dev != NULL, return 0);
+        PED_ASSERT(disk->disk_specific != NULL, return 0);
+        gpt_disk_data = disk->disk_specific;
+
+	/* allocate space for the header */
+	gptlength = gpt_disk_data->pgpt->HeaderSize / disk->dev->sector_size;
+	if (gpt_disk_data->pgpt->HeaderSize % disk->dev->sector_size)
+		gptlength++;
+	/* allocate space for the ptes */
+	pteslength =
+	    (gpt_disk_data->pgpt->NumberOfPartitionEntries *
+	     gpt_disk_data->pgpt->SizeOfPartitionEntry) /
+                disk->dev->sector_size;
+	if ((gpt_disk_data->pgpt->NumberOfPartitionEntries *
+	     gpt_disk_data->pgpt->SizeOfPartitionEntry) %
+            disk->dev->sector_size)
+		pteslength++;
+
+	/* metadata at the start of the disk includes the MBR */
+        // printf("adding metadata at start of the disk.\n");
+	if (!add_metadata_part(disk, PED_PARTITION_PRIMARY,
+			       0, 1 + gptlength + pteslength))
+		return 0;
+
+	/* metadata at the end of the disk */
+        // printf("adding metadata at end of the disk.\n");
+	if (!add_metadata_part(disk, PED_PARTITION_PRIMARY,
+			       LastLBA(disk->dev) - gptlength - pteslength + 1,
+                               gptlength + pteslength))
+                return 0;
+
+        return 1;
+}
+
+
+
+
+/**********************************************************
+ * Allocate metadata partitions for the GPTH and PTES.
+ *
+ */
+static int
+gpt_alloc_metadata(PedDisk * disk)
+{
+        GPTDiskData *gpt_disk_data;
+	PED_ASSERT(disk != NULL, return 0);
+	PED_ASSERT(disk->dev != NULL, return 0);
+
+        gpt_disk_data = disk->disk_specific;
+
+	if (!gpt_disk_data ||
+            !gpt_disk_data->pgpt ||
+            !gpt_disk_data->agpt ||
+            !gpt_disk_data->ptes)
+                return _alloc_metadata_unknown(disk);
+        
+        return _alloc_metadata_known(disk);
+}
+
+/************************************************************
+ * gpt_partition_enumerate()
+ * Requires:
+ *  - part 
+ * Modifies:
+ *  - part->num
+ * Returns:
+ *   1 if valid
+ *   0 on error
+ * Actions:
+ *   Does nothing, as the read/new/destroy functions maintain
+ *   part->num.
+ *   
+ *   
+ ************************************************************/
+static int
+gpt_partition_enumerate(PedPartition * part)
+{
+        return 1;
+}
+
+
+/************************************************************
+ * gpt_clobber()
+ * Requires:
+ *  - dev 
+ * Modifies:
+ *  - dev
+ * Returns:
+ *   1 if valid
+ *   0 on error
+ * Actions:
+ *   This writes zeros to the PMBR and the primary and
+ *   alternate GPTHs and PTEs.
+ ************************************************************/
+static int
+gpt_clobber(PedDevice * dev)
+{
+	LegacyMBR_t pmbr;
+        GuidPartitionTableHeader_t gpt;
+        GuidPartitionEntry_t ptes[GPT_DEFAULT_RESERVED_PARTITION_ENTRIES];
+        __u64 lastLBA, pte_reserved_blocks;
+        
+
+        // printf("in gpt_clobber()\n");
+        PED_ASSERT (dev != NULL, return 0);
+        PED_ASSERT (gpt_probe(dev), return 0);
+
+        if (!ped_device_open(dev)) return 0;
+
+        PED_ASSERT(dev->sector_size != 0, return 0);
+        pte_reserved_blocks = GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE /
+                dev->sector_size;
+
+
+	memset(&pmbr, 0, sizeof(pmbr));
+        memset(&gpt, 0, sizeof(gpt));
+        memset(ptes, 0,
+               GPT_DEFAULT_RESERVED_PARTITION_ENTRIES *
+               sizeof(GuidPartitionEntry_t));
+        lastLBA = LastLBA(dev);
+               
+	if (!WriteLBA(dev, 0, &pmbr, sizeof(pmbr))) {
+		printf("gpt_clobber(): Unable to write empty PMBR.\n");
+		return 0;
+	}
+	if (!WriteLBA(dev, 1, &gpt, sizeof(gpt))) {
+		printf("gpt_clobber(): Unable to write empty PGPTH.\n");
+		return 0;
+	}
+	if (!WriteLBA(dev, 2, ptes, sizeof(ptes))) {
+		printf("gpt_clobber(): Unable to write empty PPTES.\n");
+		return 0;
+	}
+	if (!WriteLBA(dev, lastLBA-pte_reserved_blocks, ptes,
+                      sizeof(ptes))) {
+		printf("gpt_clobber(): Unable to write empty APTES.\n");
+		return 0;
+	}
+	if (!WriteLBA(dev, lastLBA, &gpt, sizeof(gpt))) {
+		printf("gpt_clobber(): Unable to write empty AGPTH.\n");
+		return 0;
+	}
+        return 1;
+}
+
+
+static int
+gpt_partition_set_flag(PedPartition *part,
+                       PedPartitionFlag flag,
+                       int state)
+{
+        GPTPartitionData *gpt_part_data;
+        PED_ASSERT(part != NULL, return 0);
+        PED_ASSERT(part->disk_specific != NULL, return 0);
+        gpt_part_data = part->disk_specific;
+        PED_ASSERT(gpt_part_data->pte != NULL, return 0);
+
+
+	switch (flag) {
+	case PED_PARTITION_RAID:
+                if (state)
+                        gpt_part_data->pte->PartitionTypeGuid =
+                                PARTITION_RAID_GUID;
+                else
+                        gpt_part_data->pte->PartitionTypeGuid =
+                                PARTITION_BASIC_DATA_GUID;
+                break;
+	case PED_PARTITION_LVM:
+                if (state)
+                        gpt_part_data->pte->PartitionTypeGuid =
+                                PARTITION_LVM_GUID;
+                else
+                        gpt_part_data->pte->PartitionTypeGuid =
+                                PARTITION_BASIC_DATA_GUID;
+
+                break;
+	case PED_PARTITION_BOOT:
+                if (state)
+                        gpt_part_data->pte->PartitionTypeGuid = 
+                                PARTITION_SYSTEM_GUID;
+                else
+                        gpt_part_data->pte->PartitionTypeGuid = 
+                                PARTITION_BASIC_DATA_GUID;
+
+                break;
+	case PED_PARTITION_LBA:
+                if (!state) return 0;
+		break;
+	case PED_PARTITION_HIDDEN:
+	default:
+		return 0;
+        }
+
+        if (part->fs_type && part->fs_type->name &&
+            !strcmp(part->fs_type->name, "linux-swap"))
+                        gpt_part_data->pte->PartitionTypeGuid = 
+                                PARTITION_SWAP_GUID;
+                
+
+        return 1;
+}
+
+static int
+gpt_partition_get_flag(const PedPartition *part,
+                       PedPartitionFlag flag)
+{
+        GPTPartitionData *gpt_part_data = NULL;
+        PED_ASSERT(part->disk_specific != NULL, return 0);
+        gpt_part_data = part->disk_specific;
+
+	switch (flag) {
+	case PED_PARTITION_RAID:
+                return (!efi_guidcmp(gpt_part_data->pte->PartitionTypeGuid, 
+                                     PARTITION_RAID_GUID));
+	case PED_PARTITION_LVM:
+                return (!efi_guidcmp(gpt_part_data->pte->PartitionTypeGuid, 
+                                     PARTITION_LVM_GUID));
+	case PED_PARTITION_BOOT:
+                return (!efi_guidcmp(gpt_part_data->pte->PartitionTypeGuid,
+                                     PARTITION_SYSTEM_GUID));
+	case PED_PARTITION_LBA:
+		return 1;
+	case PED_PARTITION_HIDDEN:
+	default:
+		return 0;
+        }
+        return 0;
+}
+
+static int
+gpt_partition_is_flag_available(const PedPartition * part,
+                                PedPartitionFlag flag)
+{
+	switch (flag) {
+	case PED_PARTITION_RAID:
+	case PED_PARTITION_LVM:
+	case PED_PARTITION_LBA:
+	case PED_PARTITION_BOOT:
+		return 1;
+	case PED_PARTITION_HIDDEN:
+	default:
+		return 0;
+        }
+        return 0;
+}
+
+static void
+gpt_partition_set_name(PedPartition *part,
+                       const char *name)
+{
+        unsigned int i;
+        GPTPartitionData *gpt_part_data = NULL;
+        PED_ASSERT(part->disk_specific != NULL, return);
+        gpt_part_data = part->disk_specific;
+
+        if (!gpt_part_data->pte) return;
+
+        memset(gpt_part_data->pte->PartitionName, 0, sizeof(gpt_part_data->pte->PartitionName));
+
+        for (i=0; i < (72 / sizeof(efi_char16_t)) && i < strlen(name); i++) {
+                gpt_part_data->pte->PartitionName[i] = name[i];
+        }
+        return;
+}
+static const char *
+gpt_partition_get_name (const PedPartition * part)
+{
+        /* The name is stored in Unicode in the GPT entry */
+        char *name;
+        unsigned int i, namelen = (72 / sizeof(efi_char16_t));
+        GPTPartitionData *gpt_part_data = NULL;
+        PED_ASSERT(part->disk_specific != NULL, return 0);
+        gpt_part_data = part->disk_specific;
+
+        if (!gpt_part_data->pte) return NULL;
+
+        name = ped_malloc(namelen);
+        if (!name) return NULL;
+
+        memset(name, 0, namelen);
+
+        for (i=0; i < namelen ; i++) {
+                name[i] = gpt_part_data->pte->PartitionName[i];
+        }
+
+        return name;
+}
+
+
+static int
+gpt_get_max_primary_partition_count(const PedDisk *disk)
+{
+        int rc = GPT_DEFAULT_RESERVED_PARTITION_ENTRIES; /* 128 */
+        GPTDiskData *gpt_disk_data;
+        PED_ASSERT(disk != NULL, return 0);
+        gpt_disk_data = disk->disk_specific;
+        
+        if (gpt_disk_data  && gpt_disk_data->pgpt)
+                rc = gpt_disk_data->pgpt->NumberOfPartitionEntries;
+        return rc;
+}
+
+/* There are no alignment issues with GPT */
+static int
+gpt_partition_align(PedPartition * part,
+                    const PedConstraint * constraint)
+{
+        // printf("in gpt_partition_align()\n");
+        return 1;
+}
+
+static PedDisk *
+gpt_new(PedDisk * disk)
+{
+        // printf("gpt_new(%p)\n", disk);
+        PED_ASSERT(disk != NULL, return NULL);
+        if (disk->disk_specific) return disk;
+
+        disk->disk_specific = ped_malloc(sizeof(GPTDiskData));
+        PED_ASSERT(disk->disk_specific != NULL, return NULL);
+        memset(disk->disk_specific, 0, sizeof(GPTDiskData));
+        return disk;
+}  
+
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4 
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/fs_ext2/interface.c parted-1.4.7-gpt/libparted/fs_ext2/interface.c
--- parted-1.4.7/libparted/fs_ext2/interface.c	Mon Dec  4 13:12:47 2000
+++ parted-1.4.7-gpt/libparted/fs_ext2/interface.c	Thu Jan 18 11:45:14 2001
@@ -31,6 +31,7 @@
 #include <parted/disk_pc98.h>
 #include <parted/disk_mac.h>
 #include <parted/disk_bsd.h>
+#include <parted/disk_gpt.h>
 #include "ext2.h"
 #include "parted_io.h"
 
@@ -342,6 +343,15 @@
 	if (strcmp (disk_type->name, BSD_NAME) == 0) {
 		BSDPartitionData* bsd_data = part->disk_specific;
 		bsd_data->type = 0x8;
+		return 1;
+	}
+
+	if (strcmp (disk_type->name, GPT_NAME) == 0) {
+		GPTPartitionData *gpt_part_data = part->disk_specific;
+		PED_ASSERT(gpt_part_data      != NULL, return 0);	
+		PED_ASSERT(gpt_part_data->pte != NULL, return 0);
+		gpt_part_data->pte->PartitionTypeGuid =
+			PARTITION_BASIC_DATA_GUID;
 		return 1;
 	}
 
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/fs_fat/fat.c parted-1.4.7-gpt/libparted/fs_fat/fat.c
--- parted-1.4.7/libparted/fs_fat/fat.c	Mon Dec  4 13:12:47 2000
+++ parted-1.4.7-gpt/libparted/fs_fat/fat.c	Thu Jan 18 11:42:08 2001
@@ -22,6 +22,7 @@
 #include <parted/disk_loop.h>
 #include <parted/disk_pc98.h>
 #include <parted/disk_mac.h>
+#include <parted/disk_gpt.h>
 
 #include "fat.h"
 #include "calc.h"
@@ -751,6 +752,15 @@
 		else
 			strcpy (mac_data->system_name, "FAT");
 		mac_data->status = 0x33;
+		return 1;
+	}
+
+	if (strcmp (disk_type->name, GPT_NAME) == 0) {
+		GPTPartitionData *gpt_part_data = part->disk_specific;
+		PED_ASSERT(gpt_part_data      != NULL, return 0);	
+		PED_ASSERT(gpt_part_data->pte != NULL, return 0);
+		gpt_part_data->pte->PartitionTypeGuid =
+			PARTITION_BASIC_DATA_GUID;
 		return 1;
 	}
 
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/fs_hfs/hfs.c parted-1.4.7-gpt/libparted/fs_hfs/hfs.c
--- parted-1.4.7/libparted/fs_hfs/hfs.c	Fri Jan  5 07:30:56 2001
+++ parted-1.4.7-gpt/libparted/fs_hfs/hfs.c	Thu Jan 18 11:44:07 2001
@@ -25,6 +25,7 @@
 #include <parted/disk_loop.h>
 #include <parted/disk_pc98.h>
 #include <parted/disk_mac.h>
+#include <parted/disk_gpt.h>
 
 #include <libintl.h>
 #if ENABLE_NLS
@@ -151,6 +152,15 @@
 			strcpy (mac_data->system_name, "Apple_HFS");
 			mac_data->status |= 0x7f;
 		}
+		return 1;
+	}
+
+	if (strcmp (disk_type->name, GPT_NAME) == 0) {
+		GPTPartitionData *gpt_part_data = part->disk_specific;
+		PED_ASSERT(gpt_part_data      != NULL, return 0);	
+		PED_ASSERT(gpt_part_data->pte != NULL, return 0);
+		gpt_part_data->pte->PartitionTypeGuid =
+			PARTITION_BASIC_DATA_GUID;
 		return 1;
 	}
 
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/fs_linux_swap/linux_swap.c parted-1.4.7-gpt/libparted/fs_linux_swap/linux_swap.c
--- parted-1.4.7/libparted/fs_linux_swap/linux_swap.c	Fri Jan  5 07:31:23 2001
+++ parted-1.4.7-gpt/libparted/fs_linux_swap/linux_swap.c	Thu Jan 18 11:24:42 2001
@@ -28,6 +28,7 @@
 #include <parted/disk_pc98.h>
 #include <parted/disk_mac.h>
 #include <parted/disk_bsd.h>
+#include <parted/disk_gpt.h>
 
 #include <libintl.h>
 #if ENABLE_NLS
@@ -565,6 +566,15 @@
 	if (strcmp (disk_type->name, BSD_NAME) == 0) {
 		BSDPartitionData* bsd_data = part->disk_specific;
 		bsd_data->type = 0x1;
+		return 1;
+	}
+
+	if (strcmp (disk_type->name, GPT_NAME) == 0) {
+		GPTPartitionData* gpt_part_data = part->disk_specific;
+		PED_ASSERT(gpt_part_data      != NULL, return 0);
+		PED_ASSERT(gpt_part_data->pte != NULL, return 0);
+		gpt_part_data->pte->PartitionTypeGuid =
+			PARTITION_SWAP_GUID;
 		return 1;
 	}
 
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/fs_ntfs/ntfs.c parted-1.4.7-gpt/libparted/fs_ntfs/ntfs.c
--- parted-1.4.7/libparted/fs_ntfs/ntfs.c	Fri Jan  5 07:29:47 2001
+++ parted-1.4.7-gpt/libparted/fs_ntfs/ntfs.c	Thu Jan 18 11:45:18 2001
@@ -25,6 +25,7 @@
 #include <parted/disk_loop.h>
 #include <parted/disk_pc98.h>
 #include <parted/disk_mac.h>
+#include <parted/disk_gpt.h>
 
 #include <libintl.h>
 #if ENABLE_NLS
@@ -147,6 +148,15 @@
 		else
 			strcpy (mac_data->system_name, "Apple_UNIX_SVR2");
 		mac_data->status = 0x33;
+		return 1;
+	}
+
+	if (strcmp (disk_type->name, GPT_NAME) == 0) {
+		GPTPartitionData *gpt_part_data = part->disk_specific;
+		PED_ASSERT(gpt_part_data      != NULL, return 0);	
+		PED_ASSERT(gpt_part_data->pte != NULL, return 0);
+		gpt_part_data->pte->PartitionTypeGuid =
+			PARTITION_BASIC_DATA_GUID;
 		return 1;
 	}
 
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/fs_reiserfs/reiserfs.c parted-1.4.7-gpt/libparted/fs_reiserfs/reiserfs.c
--- parted-1.4.7/libparted/fs_reiserfs/reiserfs.c	Fri Jan  5 07:30:13 2001
+++ parted-1.4.7-gpt/libparted/fs_reiserfs/reiserfs.c	Thu Jan 18 11:42:34 2001
@@ -25,6 +25,7 @@
 #include <parted/disk_loop.h>
 #include <parted/disk_pc98.h>
 #include <parted/disk_mac.h>
+#include <parted/disk_gpt.h>
 
 #include <libintl.h>
 #if ENABLE_NLS
@@ -181,6 +182,15 @@
 		else
 			strcpy (mac_data->system_name, "Apple_UNIX_SVR2");
 		mac_data->status = 0x33;
+		return 1;
+	}
+
+	if (strcmp (disk_type->name, GPT_NAME) == 0) {
+		GPTPartitionData *gpt_part_data = part->disk_specific;
+		PED_ASSERT(gpt_part_data      != NULL, return 0);	
+		PED_ASSERT(gpt_part_data->pte != NULL, return 0);
+		gpt_part_data->pte->PartitionTypeGuid =
+			PARTITION_BASIC_DATA_GUID;
 		return 1;
 	}
 
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/libparted.c parted-1.4.7-gpt/libparted/libparted.c
--- parted-1.4.7/libparted/libparted.c	Thu Jan 11 13:03:16 2001
+++ parted-1.4.7-gpt/libparted/libparted.c	Thu Jan 18 11:24:42 2001
@@ -65,6 +65,7 @@
 	ped_disk_pc98_init ();
 	ped_disk_mac_init ();
 	ped_disk_bsd_init ();
+	ped_disk_gpt_init ();
 }
 
 static void
@@ -102,6 +103,7 @@
 	ped_disk_loop_done ();
 	ped_disk_mac_done ();
 	ped_disk_bsd_done ();
+	ped_disk_gpt_done ();
 }
 
 static void
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/sg_dd.c parted-1.4.7-gpt/libparted/sg_dd.c
--- parted-1.4.7/libparted/sg_dd.c	Wed Dec 31 18:00:00 1969
+++ parted-1.4.7-gpt/libparted/sg_dd.c	Thu Jan 18 11:24:42 2001
@@ -0,0 +1,781 @@
+ /*
+    libparted - a library for manipulating disk partitions
+    Copyright (C) 1998-2000 Free Software Foundation, Inc.
+
+    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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#define _XOPEN_SOURCE 500
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <linux/../scsi/sg.h>  /* cope with silly includes */
+#include <linux/major.h> 
+typedef unsigned char u_char;	/* horrible, for scsi.h */
+#include "sg_err.h"
+
+#if 0
+#include "sg_llseek.h"
+#endif
+
+/* A utility program for the Linux OS SCSI generic ("sg") device driver.
+*  Copyright (C) 1999, 2000 D. Gilbert and P. Allworth
+*  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
+*  the Free Software Foundation; either version 2, or (at your option)
+*  any later version.
+
+   This program is a specialization of the Unix "dd" command in which
+   either the input or the output file is a scsi generic device or a
+   raw device. The block size ('bs') is assumed to be 512 if not given. 
+   This program complains if 'ibs' or 'obs' are given with a value
+   that differs from 'bs' (or the default 512).
+   If 'if' is not given or 'if=-' then stdin is assumed. If 'of' is
+   not given or 'of=-' then stdout assumed. Multipliers:
+     'c','C'  *1       'b','B' *512      'k' *1024      'K' *1000
+     'm' *(1024^2)     'M' *(1000^2)     'g' *(1024^3)  'G' *(1000^3)
+
+   A non-standard argument "bpt" (blocks per transfer) is added to control
+   the maximum number of blocks in each transfer. The default value is 128.
+   For example if "bs=512" and "bpt=32" then a maximum of 32 blocks (16KB
+   in this case) is transferred to or from the sg device in a single SCSI
+   command.
+
+   This version should compile with Linux sg drivers with version numbers
+   >= 30000 .
+
+   Version 5.11 20001220
+*/
+
+#define DEF_BLOCK_SIZE 512
+#define DEF_BLOCKS_PER_TRANSFER 128
+
+// #define SG_DEBUG
+
+#define SENSE_BUFF_LEN 32       /* Arbitrary, could be larger */
+#define READ_CAP_REPLY_LEN 8
+#define DEF_TIMEOUT 40000       /* 40,000 millisecs == 40 seconds */
+
+#ifndef RAW_MAJOR
+#define RAW_MAJOR 255	/*unlikey value */
+#endif 
+
+#define FT_OTHER 0		/* filetype other than sg or raw device */
+#define FT_SG 1			/* filetype is sg char device */
+#define FT_RAW 2		/* filetype is raw char device */
+
+static int sum_of_resids = 0;
+
+static int dd_count = -1;
+static int in_full = 0;
+static int in_partial = 0;
+static int out_full = 0;
+static int out_partial = 0;
+
+static void install_handler (int sig_num, void (*sig_handler) (int sig))
+{
+    struct sigaction sigact;
+    sigaction (sig_num, NULL, &sigact);
+    if (sigact.sa_handler != SIG_IGN)
+    {
+        sigact.sa_handler = sig_handler;
+        sigemptyset (&sigact.sa_mask);
+        sigact.sa_flags = 0;
+        sigaction (sig_num, &sigact, NULL);
+    }
+}
+
+static void print_stats()
+{
+    if (0 != dd_count)
+        fprintf(stderr, "  remaining block count=%d\n", dd_count);
+    fprintf(stderr, "%d+%d records in\n", in_full, in_partial);
+    fprintf(stderr, "%d+%d records out\n", out_full, out_partial);
+}
+
+static void interrupt_handler(int sig)
+{
+    struct sigaction sigact;
+
+    sigact.sa_handler = SIG_DFL;
+    sigemptyset (&sigact.sa_mask);
+    sigact.sa_flags = 0;
+    sigaction (sig, &sigact, NULL);
+    fprintf(stderr, "Interrupted by signal,");
+    print_stats ();
+    kill (getpid (), sig);
+}
+
+static void siginfo_handler(int sig)
+{
+    fprintf(stderr, "Progress report, continuing ...\n");
+    print_stats ();
+}
+
+static int dd_filetype(const char * filename)
+{
+    struct stat st;
+
+    if (stat(filename, &st) < 0)
+	return FT_OTHER;
+    if (S_ISCHR(st.st_mode)) {
+	if (RAW_MAJOR == major(st.st_rdev))
+	    return FT_RAW;
+	else if (SCSI_GENERIC_MAJOR == major(st.st_rdev))
+	    return FT_SG;
+    }
+    return FT_OTHER;
+}
+
+static void usage()
+{
+    fprintf(stderr, "Usage: "
+           "sg_dd  [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>]\n"
+           "              [bs=<num>] [bpt=<num>] [count=<n>]"
+           " [dio=<n>]\n"
+           "            either 'if' or 'of' must be a sg or raw device\n"
+           " 'bpt' is blocks_per_transfer (default is 128)\n"
+           " 'dio' is direct IO, 1->attempt, 0->indirect IO (def)\n");
+}
+
+/* Return of 0 -> success, -1 -> failure, 2 -> try again */
+static int read_capacity(int sg_fd, int * num_sect, int * sect_sz)
+{
+    int res;
+    unsigned char rcCmdBlk [10] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    unsigned char rcBuff[READ_CAP_REPLY_LEN];
+    unsigned char sense_b[64];
+    sg_io_hdr_t io_hdr;
+
+    memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
+    io_hdr.interface_id = 'S';
+    io_hdr.cmd_len = sizeof(rcCmdBlk);
+    io_hdr.mx_sb_len = sizeof(sense_b);
+    io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+    io_hdr.dxfer_len = sizeof(rcBuff);
+    io_hdr.dxferp = rcBuff;
+    io_hdr.cmdp = rcCmdBlk;
+    io_hdr.sbp = sense_b;
+    io_hdr.timeout = DEF_TIMEOUT;
+
+    if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
+        perror("read_capacity (SG_IO) error");
+        return -1;
+    }
+    res = sg_err_category3(&io_hdr);
+    if (SG_ERR_CAT_MEDIA_CHANGED == res)
+        return 2; /* probably have another go ... */
+    else if (SG_ERR_CAT_CLEAN != res) {
+        sg_chk_n_print3("read capacity", &io_hdr);
+        return -1;
+    }
+    *num_sect = 1 + ((rcBuff[0] << 24) | (rcBuff[1] << 16) |
+                (rcBuff[2] << 8) | rcBuff[3]);
+    *sect_sz = (rcBuff[4] << 24) | (rcBuff[5] << 16) |
+               (rcBuff[6] << 8) | rcBuff[7];
+    return 0;
+}
+
+/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM),
+   2 -> try again */
+int sg_read(int sg_fd, unsigned char * buff, unsigned int blocks, unsigned int from_block,
+            int bs, int * diop)
+{
+    unsigned char rdCmd[10] = {0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    unsigned char senseBuff[SENSE_BUFF_LEN];
+    sg_io_hdr_t io_hdr;
+    int res;
+
+    rdCmd[2] = (unsigned char)((from_block >> 24) & 0xFF);
+    rdCmd[3] = (unsigned char)((from_block >> 16) & 0xFF);
+    rdCmd[4] = (unsigned char)((from_block >> 8) & 0xFF);
+    rdCmd[5] = (unsigned char)(from_block & 0xFF);
+    rdCmd[7] = (unsigned char)((blocks >> 8) & 0xff);
+    rdCmd[8] = (unsigned char)(blocks & 0xff);
+
+    memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
+    io_hdr.interface_id = 'S';
+    io_hdr.cmd_len = sizeof(rdCmd);
+    io_hdr.cmdp = rdCmd;
+    io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+    io_hdr.dxfer_len = bs * blocks;
+    io_hdr.dxferp = buff;
+    io_hdr.mx_sb_len = SENSE_BUFF_LEN;
+    io_hdr.sbp = senseBuff;
+    io_hdr.timeout = DEF_TIMEOUT;
+    io_hdr.pack_id = from_block;
+    if (diop && *diop)
+        io_hdr.flags |= SG_FLAG_DIRECT_IO;
+
+    while (((res = write(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) &&
+           (EINTR == errno))
+        ;
+    if (res < 0) {
+        if (ENOMEM == errno)
+            return 1;
+        perror("reading (wr) on sg device, error");
+        return -1;
+    }
+
+    while (((res = read(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) &&
+           (EINTR == errno))
+        ;
+    if (res < 0) {
+        perror("reading (rd) on sg device, error");
+        return -1;
+    }
+    switch (sg_err_category3(&io_hdr)) {
+    case SG_ERR_CAT_CLEAN:
+        break;
+    case SG_ERR_CAT_RECOVERED:
+        fprintf(stderr, "Recovered error while reading block=%d, num=%d\n",
+               from_block, blocks);
+        break;
+    case SG_ERR_CAT_MEDIA_CHANGED:
+        return 2;
+    default:
+        sg_chk_n_print3("reading", &io_hdr);
+        return -1;
+    }
+    if (diop && *diop && 
+        ((io_hdr.info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
+        *diop = 0;      /* flag that dio not done (completely) */
+    sum_of_resids += io_hdr.resid;
+#if SG_DEBUG
+    fprintf(stderr, "duration=%u ms\n", io_hdr.duration);
+#endif
+    return 0;
+}
+
+/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM),
+   2 -> try again */
+int sg_write(int sg_fd, unsigned char * buff, unsigned int blocks, unsigned int to_block,
+             int bs, int * diop)
+{
+    unsigned char wrCmd[10] = {0x2a, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    unsigned char senseBuff[SENSE_BUFF_LEN];
+    sg_io_hdr_t io_hdr;
+    int res;
+
+    wrCmd[2] = (unsigned char)((to_block >> 24) & 0xFF);
+    wrCmd[3] = (unsigned char)((to_block >> 16) & 0xFF);
+    wrCmd[4] = (unsigned char)((to_block >> 8) & 0xFF);
+    wrCmd[5] = (unsigned char)(to_block & 0xFF);
+    wrCmd[7] = (unsigned char)((blocks >> 8) & 0xff);
+    wrCmd[8] = (unsigned char)(blocks & 0xff);
+
+    memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
+    io_hdr.interface_id = 'S';
+    io_hdr.cmd_len = sizeof(wrCmd);
+    io_hdr.cmdp = wrCmd;
+    io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
+    io_hdr.dxfer_len = bs * blocks;
+    io_hdr.dxferp = buff;
+    io_hdr.mx_sb_len = SENSE_BUFF_LEN;
+    io_hdr.sbp = senseBuff;
+    io_hdr.timeout = DEF_TIMEOUT;
+    io_hdr.pack_id = to_block;
+    if (diop && *diop)
+        io_hdr.flags |= SG_FLAG_DIRECT_IO;
+
+    while (((res = write(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) &&
+           (EINTR == errno))
+        ;
+    if (res < 0) {
+        if (ENOMEM == errno)
+            return 1;
+        perror("writing (wr) on sg device, error");
+        return -1;
+    }
+
+    while (((res = read(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) &&
+           (EINTR == errno))
+        ;
+    if (res < 0) {
+        perror("writing (rd) on sg device, error");
+        return -1;
+    }
+    switch (sg_err_category3(&io_hdr)) {
+    case SG_ERR_CAT_CLEAN:
+        break;
+    case SG_ERR_CAT_RECOVERED:
+        fprintf(stderr, "Recovered error while writing block=%d, num=%d\n",
+               to_block, blocks);
+        break;
+    case SG_ERR_CAT_MEDIA_CHANGED:
+        return 2;
+    default:
+        sg_chk_n_print3("writing", &io_hdr);
+        return -1;
+    }
+    if (diop && *diop && 
+        ((io_hdr.info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
+        *diop = 0;      /* flag that dio not done (completely) */
+    return 0;
+}
+
+static int get_num(char * buf)
+{
+    int res, num;
+    char c;
+
+    res = sscanf(buf, "%d%c", &num, &c);
+    if (0 == res)
+        return -1;
+    else if (1 == res)
+        return num;
+    else {
+    	switch (c) {
+	case 'c':
+	case 'C':
+            return num;
+	case 'b':
+	case 'B':
+            return num * 512;
+	case 'k':
+            return num * 1024;
+	case 'K':
+            return num * 1000;
+	case 'm':
+            return num * 1024 * 1024;
+	case 'M':
+            return num * 1000000;
+	case 'g':
+            return num * 1024 * 1024 * 1024;
+	case 'G':
+            return num * 1000000000;
+        default:
+            fprintf(stderr, "unrecognized multiplier\n");
+            return -1;
+	}
+    }
+}
+
+#if 0
+static int sg_dd_main(int argc, char * argv[])
+{
+    int skip = 0;
+    int seek = 0;
+    int bs = 0;
+    int ibs = 0;
+    int obs = 0;
+    int bpt = DEF_BLOCKS_PER_TRANSFER;
+    char str[512];
+    char * key;
+    char * buf;
+    char inf[512];
+    int in_type = FT_OTHER;
+    char outf[512];
+    int out_type = FT_OTHER;
+    int dio = 0;
+    int dio_incomplete = 0;
+    int res, k, t, buf_sz, dio_tmp;
+    int infd, outfd, blocks;
+    unsigned char * wrkBuff;
+    unsigned char * wrkPos;
+    int in_num_sect = 0;
+    int out_num_sect = 0;
+    int in_sect_sz, out_sect_sz;
+    char ebuff[256];
+    int blocks_per;
+
+    inf[0] = '\0';
+    outf[0] = '\0';
+    if (argc < 2) {
+        usage();
+        return 1;
+    }
+
+    for(k = 1; k < argc; k++) {
+        if (argv[k])
+            strcpy(str, argv[k]);
+        else
+            continue;
+        for(key = str, buf = key; *buf && *buf != '=';)
+            buf++;
+        if (*buf)
+            *buf++ = '\0';
+        if (strcmp(key,"if") == 0)
+            strcpy(inf, buf);
+        else if (strcmp(key,"of") == 0)
+            strcpy(outf, buf);
+        else if (0 == strcmp(key,"ibs"))
+            ibs = get_num(buf);
+        else if (0 == strcmp(key,"obs"))
+            obs = get_num(buf);
+        else if (0 == strcmp(key,"bs"))
+            bs = get_num(buf);
+        else if (0 == strcmp(key,"bpt"))
+            bpt = get_num(buf);
+        else if (0 == strcmp(key,"skip"))
+            skip = get_num(buf);
+        else if (0 == strcmp(key,"seek"))
+            seek = get_num(buf);
+        else if (0 == strcmp(key,"count"))
+            dd_count = get_num(buf);
+        else if (0 == strcmp(key,"dio"))
+            dio = get_num(buf);
+        else {
+            fprintf(stderr, "Unrecognized argument '%s'\n", key);
+            usage();
+            return 1;
+        }
+    }
+    if (bs <= 0) {
+        bs = DEF_BLOCK_SIZE;
+        fprintf(stderr, "Assume default 'bs' (block size) of %d bytes\n", bs);
+    }
+    if ((ibs && (ibs != bs)) || (obs && (obs != bs))) {
+        fprintf(stderr, "If 'ibs' or 'obs' given must be same as 'bs'\n");
+        usage();
+        return 1;
+    }
+    if ((skip < 0) || (seek < 0)) {
+        fprintf(stderr, "skip and seek cannot be negative\n");
+        return 1;
+    }
+#ifdef SG_DEBUG
+    fprintf(stderr, "sg_dd: if=%s skip=%d of=%s seek=%d count=%d\n",
+           inf, skip, outf, seek, dd_count);
+#endif
+    install_handler (SIGINT, interrupt_handler);
+    install_handler (SIGQUIT, interrupt_handler);
+    install_handler (SIGPIPE, interrupt_handler);
+    install_handler (SIGUSR1, siginfo_handler);
+
+    infd = STDIN_FILENO;
+    outfd = STDOUT_FILENO;
+    if (inf[0] && ('-' != inf[0])) {
+	in_type = dd_filetype(inf);
+
+	if (FT_SG == in_type) {
+	    if ((infd = open(inf, O_RDWR)) < 0) {
+                sprintf(ebuff, "sg_dd: could not open %s for sg reading", inf);
+                perror(ebuff);
+                return 1;
+            }
+	    t = bs * bpt;
+            res = ioctl(infd, SG_SET_RESERVED_SIZE, &t);
+            if (res < 0)
+                perror("sg_dd: SG_SET_RESERVED_SIZE error");
+            res = ioctl(infd, SG_GET_VERSION_NUM, &t);
+            if ((res < 0) || (t < 30000)) {
+                fprintf(stderr, "sg_dd: sg driver prior to 3.x.y\n");
+                return 1;
+            }
+        }
+        if (FT_SG != in_type) {
+            if ((infd = open(inf, O_RDONLY)) < 0) {
+                sprintf(ebuff, "sg_dd: could not open %s for reading", inf);
+                perror(ebuff);
+                return 1;
+            }
+            else if (skip > 0) {
+                llse_loff_t offset = skip;
+
+                offset *= bs;       /* could exceed 32 bits here! */
+                if (llse_llseek(infd, offset, SEEK_SET) < 0) {
+                    sprintf(ebuff,
+                "sg_dd: couldn't skip to required position on %s", inf);
+                    perror(ebuff);
+                    return 1;
+                }
+            }
+        }
+    }
+
+    if (outf[0] && ('-' != outf[0])) {
+	out_type = dd_filetype(outf);
+
+	if (FT_SG == out_type) {
+	    if ((outfd = open(outf, O_RDWR)) < 0) {
+                sprintf(ebuff, "sg_dd: could not open %s for sg writing", outf);
+                perror(ebuff);
+                return 1;
+            }
+            t = bs * bpt;
+            res = ioctl(outfd, SG_SET_RESERVED_SIZE, &t);
+            if (res < 0)
+                perror("sg_dd: SG_SET_RESERVED_SIZE error");
+            res = ioctl(outfd, SG_GET_VERSION_NUM, &t);
+            if ((res < 0) || (t < 30000)) {
+                fprintf(stderr, "sg_dd: sg driver prior to 3.x.y\n");
+                return 1;
+            }
+        }
+	else {
+	    if (FT_OTHER == out_type) {
+		if ((outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) {
+		    sprintf(ebuff,
+			    "sg_dd: could not open %s for writing", outf);
+		    perror(ebuff);
+		    return 1;
+		}
+	    }
+	    else {
+		if ((outfd = open(outf, O_WRONLY)) < 0) {
+		    sprintf(ebuff,
+			    "sg_dd: could not open %s for raw writing", outf);
+		    perror(ebuff);
+		    return 1;
+		}
+	    }
+            if (seek > 0) {
+                llse_loff_t offset = seek;
+
+                offset *= bs;       /* could exceed 32 bits here! */
+                if (llse_llseek(outfd, offset, SEEK_SET) < 0) {
+                    sprintf(ebuff,
+                "sg_dd: couldn't seek to required position on %s", outf);
+                    perror(ebuff);
+                    return 1;
+                }
+            }
+        }
+    }
+    if ((STDIN_FILENO == infd) && (STDOUT_FILENO == outfd)) {
+        fprintf(stderr, 
+		"Can't have both 'if' as stdin _and_ 'of' as stdout\n");
+        return 1;
+    }
+#if 1
+    if ((FT_OTHER == in_type) && (FT_OTHER == out_type)) {
+        fprintf(stderr, "Both 'if' and 'of' can't be ordinary files\n");
+        return 1;
+    }
+#endif
+    if (0 == dd_count)
+        return 0;
+    else if (dd_count < 0) {
+        if (FT_SG == in_type) {
+            res = read_capacity(infd, &in_num_sect, &in_sect_sz);
+            if (2 == res) {
+                fprintf(stderr, 
+			"Unit attention, media changed(in), try again\n");
+                res = read_capacity(infd, &in_num_sect, &in_sect_sz);
+            }
+            if (0 != res) {
+                fprintf(stderr, "Unable to read capacity on %s\n", inf);
+                in_num_sect = -1;
+            }
+            else {
+#if 0
+                if (0 == in_sect_sz)
+                    in_sect_sz = bs;
+                else if (in_sect_sz > bs)
+                    in_num_sect *=  (in_sect_sz / bs);
+                else if (in_sect_sz < bs)
+                    in_num_sect /=  (bs / in_sect_sz);
+#endif
+                if (in_num_sect > skip)
+                    in_num_sect -= skip;
+            }
+        }
+        if (FT_SG == out_type) {
+            res = read_capacity(outfd, &out_num_sect, &out_sect_sz);
+            if (2 == res) {
+                fprintf(stderr, 
+			"Unit attention, media changed(out), try again\n");
+                res = read_capacity(outfd, &out_num_sect, &out_sect_sz);
+            }
+            if (0 != res) {
+                fprintf(stderr, "Unable to read capacity on %s\n", outf);
+                out_num_sect = -1;
+            }
+            else {
+                if (out_num_sect > seek)
+                    out_num_sect -= seek;
+            }
+        }
+#ifdef SG_DEBUG
+    fprintf(stderr, 
+	    "Start of loop, count=%d, in_num_sect=%d, out_num_sect=%d\n", 
+            dd_count, in_num_sect, out_num_sect);
+#endif
+        if (in_num_sect > 0) {
+            if (out_num_sect > 0)
+                dd_count = (in_num_sect > out_num_sect) ? out_num_sect :
+                                                       in_num_sect;
+            else
+                dd_count = in_num_sect;
+        }
+        else
+            dd_count = out_num_sect;
+    }
+    if (dd_count <= 0) {
+        fprintf(stderr, "Couldn't calculate count, please give one\n");
+        return 1;
+    }
+
+    if (dio || (FT_RAW == in_type) || (FT_RAW == out_type)) {
+	size_t psz = getpagesize();
+	wrkBuff = malloc(bs * bpt + psz);
+	if (0 == wrkBuff) {
+            fprintf(stderr, "Not enough user memory for raw\n");
+            return 1;
+        }
+	wrkPos = (unsigned char *)(((unsigned long)wrkBuff + psz - 1) &
+		                   (~(psz - 1)));
+    }
+    else {
+	wrkBuff = malloc(bs * bpt);
+	if (0 == wrkBuff) {
+            fprintf(stderr, "Not enough user memory\n");
+            return 1;
+        }
+        wrkPos = wrkBuff;
+    }
+
+    blocks_per = bpt;
+#ifdef SG_DEBUG
+    fprintf(stderr, "Start of loop, count=%d, blocks_per=%d\n", 
+	    dd_count, blocks_per);
+#endif
+    while (dd_count > 0) {
+        blocks = (dd_count > blocks_per) ? blocks_per : dd_count;
+        if (FT_SG == in_type) {
+            dio_tmp = dio;
+            res = sg_read(infd, wrkPos, blocks, skip, bs, &dio_tmp);
+            if (1 == res) {     /* ENOMEM, find what's available+try that */
+                if (ioctl(infd, SG_GET_RESERVED_SIZE, &buf_sz) < 0) {
+                    perror("RESERVED_SIZE ioctls failed");
+                    break;
+                }
+                blocks_per = (buf_sz + bs - 1) / bs;
+                blocks = blocks_per;
+                fprintf(stderr, 
+			"Reducing read to %d blocks per loop\n", blocks_per);
+                res = sg_read(infd, wrkPos, blocks, skip, bs, &dio_tmp);
+            }
+            else if (2 == res) {
+                fprintf(stderr, 
+			"Unit attention, media changed, try again (r)\n");
+                res = sg_read(infd, wrkPos, blocks, skip, bs, &dio_tmp);
+            }
+            if (0 != res) {
+                fprintf(stderr, "sg_read failed, skip=%d\n", skip);
+                break;
+            }
+            else {
+                in_full += blocks;
+                if (dio && (0 == dio_tmp))
+                    dio_incomplete++;
+            }
+        }
+        else {
+	    while (((res = read(infd, wrkPos, blocks * bs)) < 0) &&
+		   (EINTR == errno))
+		;
+            if (res < 0) {
+                sprintf(ebuff, "sg_dd: reading, skip=%d ", skip);
+                perror(ebuff);
+                break;
+            }
+            else if (res < blocks * bs) {
+                dd_count = 0;
+                blocks = res / bs;
+                if ((res % bs) > 0) {
+                    blocks++;
+                    in_partial++;
+                }
+            }
+            in_full += blocks;
+        }
+
+        if (FT_SG == out_type) {
+            dio_tmp = dio;
+            res = sg_write(outfd, wrkPos, blocks, seek, bs, &dio_tmp);
+            if (1 == res) {     /* ENOMEM, find what's available+try that */
+                if (ioctl(outfd, SG_GET_RESERVED_SIZE, &buf_sz) < 0) {
+                    perror("RESERVED_SIZE ioctls failed");
+                    break;
+                }
+                blocks_per = (buf_sz + bs - 1) / bs;
+                blocks = blocks_per;
+                fprintf(stderr, 
+			"Reducing write to %d blocks per loop\n", blocks);
+                res = sg_write(outfd, wrkPos, blocks, seek, bs, &dio_tmp);
+            }
+            else if (2 == res) {
+                fprintf(stderr, 
+			"Unit attention, media changed, try again (w)\n");
+                res = sg_write(outfd, wrkPos, blocks, seek, bs, &dio_tmp);
+            }
+            else if (0 != res) {
+                fprintf(stderr, "sg_write failed, seek=%d\n", seek);
+                break;
+            }
+            else {
+                out_full += blocks;
+                if (dio && (0 == dio_tmp))
+                    dio_incomplete++;
+            }
+        }
+        else {
+	    while (((res = write(outfd, wrkPos, blocks * bs)) < 0)
+		   && (EINTR == errno))
+		;
+            if (res < 0) {
+                sprintf(ebuff, "sg_dd: writing, seek=%d ", seek);
+                perror(ebuff);
+                break;
+            }
+            else if (res < blocks * bs) {
+                fprintf(stderr, "output file probably full, seek=%d ", seek);
+                blocks = res / bs;
+                out_full += blocks;
+                if ((res % bs) > 0)
+                    out_partial++;
+                break;
+            }
+            else
+                out_full += blocks;
+        }
+        if (dd_count > 0)
+            dd_count -= blocks;
+        skip += blocks;
+        seek += blocks;
+    }
+
+    free(wrkBuff);
+    if (STDIN_FILENO != infd)
+        close(infd);
+    if (STDOUT_FILENO != outfd)
+        close(outfd);
+    res = 0;
+    if (0 != dd_count) {
+        fprintf(stderr, "Some error occurred,");
+	res = 2;
+    }
+    print_stats();
+    if (dio_incomplete)
+        fprintf(stderr, ">> Direct IO requested but incomplete %d times\n", 
+                dio_incomplete);
+    if (sum_of_resids)
+        fprintf(stderr, ">> Non-zero sum of residual counts=%d\n", 
+		sum_of_resids);
+    return res;
+}
+#endif
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/sg_dd.h parted-1.4.7-gpt/libparted/sg_dd.h
--- parted-1.4.7/libparted/sg_dd.h	Wed Dec 31 18:00:00 1969
+++ parted-1.4.7-gpt/libparted/sg_dd.h	Thu Jan 18 11:24:42 2001
@@ -0,0 +1,23 @@
+ /*
+    libparted - a library for manipulating disk partitions
+    Copyright (C) 1998-2000 Free Software Foundation, Inc.
+
+    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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+int sg_write(int sg_fd, unsigned char * buff, unsigned int blocks, unsigned int to_block,
+             int bs, int * diop);
+int sg_read(int sg_fd, unsigned char * buff, unsigned int blocks, unsigned int from_block,
+            int bs, int * diop);
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/sg_err.c parted-1.4.7-gpt/libparted/sg_err.c
--- parted-1.4.7/libparted/sg_err.c	Wed Dec 31 18:00:00 1969
+++ parted-1.4.7-gpt/libparted/sg_err.c	Thu Jan 18 11:24:42 2001
@@ -0,0 +1,648 @@
+ /*
+    libparted - a library for manipulating disk partitions
+    Copyright (C) 1998-2000 Free Software Foundation, Inc.
+
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include "sg_err.h"
+
+/* This file is a huge cut, paste and hack from linux/drivers/scsi/constant.c
+*  which I guess was written by:
+*         Copyright (C) 1993, 1994, 1995 Eric Youngdale
+
+* The rest of this is:
+*  Copyright (C) 1999 D. Gilbert
+*
+*  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
+*  the Free Software Foundation; either version 2, or (at your option)
+*  any later version.
+*
+*  ASCII values for a number of symbolic constants, printing functions, etc.
+*
+*  Some of the tables have been updated for SCSI 2.
+*
+*  Version 0.83 (991208)
+*/
+
+
+static const unsigned char scsi_command_size[8] = { 6, 10, 10, 12,
+                                                   12, 12, 10, 10 };
+
+#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
+
+static const char unknown[] = "UNKNOWN";
+
+static const char * group_0_commands[] = {
+/* 00-03 */ "Test Unit Ready", "Rezero Unit", unknown, "Request Sense",
+/* 04-07 */ "Format Unit", "Read Block Limits", unknown, "Reasssign Blocks",
+/* 08-0d */ "Read (6)", unknown, "Write (6)", "Seek (6)", unknown, unknown,
+/* 0e-12 */ unknown, "Read Reverse", "Write Filemarks", "Space", "Inquiry",
+/* 13-16 */ "Verify", "Recover Buffered Data", "Mode Select", "Reserve",
+/* 17-1b */ "Release", "Copy", "Erase", "Mode Sense", "Start/Stop Unit",
+/* 1c-1d */ "Receive Diagnostic", "Send Diagnostic",
+/* 1e-1f */ "Prevent/Allow Medium Removal", unknown,
+};
+
+
+static const char *group_1_commands[] = {
+/* 20-22 */  unknown, unknown, unknown,
+/* 23-28 */ unknown, "Define window parameters", "Read Capacity",
+            unknown, unknown, "Read (10)",
+/* 29-2d */ "Read Generation", "Write (10)", "Seek (10)", "Erase",
+            "Read updated block",
+/* 2e-31 */ "Write Verify","Verify", "Search High", "Search Equal",
+/* 32-34 */ "Search Low", "Set Limits", "Prefetch or Read Position",
+/* 35-37 */ "Synchronize Cache","Lock/Unlock Cache", "Read Defect Data",
+/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer",
+            "Read Buffer",
+/* 3d-3f */ "Update Block", "Read Long",  "Write Long",
+};
+
+static const char *group_2_commands[] = {
+/* 40-41 */ "Change Definition", "Write Same",
+/* 42-48 */ "Read sub-channel", "Read TOC", "Read header",
+            "Play audio (10)", unknown, "Play audio msf",
+            "Play audio track/index",
+/* 49-4f */ "Play track relative (10)", unknown, "Pause/resume",
+            "Log Select", "Log Sense", unknown, unknown,
+/* 50-55 */ unknown, unknown, unknown, unknown, unknown, "Mode Select (10)",
+/* 56-5b */ unknown, unknown, unknown, unknown, "Mode Sense (10)", unknown,
+/* 5c-5f */ unknown, unknown, unknown,
+};
+
+
+/* The following are 12 byte commands in group 5 */
+static const char *group_5_commands[] = {
+/* a0-a5 */ unknown, unknown, unknown, unknown, unknown,
+            "Move medium/play audio(12)",
+/* a6-a9 */ "Exchange medium", unknown, "Read(12)", "Play track relative(12)",
+/* aa-ae */ "Write(12)", unknown, "Erase(12)", unknown,
+            "Write and verify(12)",
+/* af-b1 */ "Verify(12)", "Search data high(12)", "Search data equal(12)",
+/* b2-b4 */ "Search data low(12)", "Set limits(12)", unknown,
+/* b5-b6 */ "Request volume element address", "Send volume tag",
+/* b7-b9 */ "Read defect data(12)", "Read element status", unknown,
+/* ba-bf */ unknown, unknown, unknown, unknown, unknown, unknown,
+};
+
+
+
+
+#define group(opcode) (((opcode) >> 5) & 7)
+
+#define RESERVED_GROUP  0
+#define VENDOR_GROUP    1
+
+static const char **commands[] = {
+    group_0_commands, group_1_commands, group_2_commands,
+    (const char **) RESERVED_GROUP, (const char **) RESERVED_GROUP,
+    group_5_commands, (const char **) VENDOR_GROUP,
+    (const char **) VENDOR_GROUP
+};
+
+static const char reserved[] = "RESERVED";
+static const char vendor[] = "VENDOR SPECIFIC";
+
+static void print_opcode(int opcode) {
+    const char **table = commands[ group(opcode) ];
+    switch ((unsigned long) table) {
+    case RESERVED_GROUP:
+        printf("%s(0x%02x) ", reserved, opcode);
+        break;
+    case VENDOR_GROUP:
+        printf("%s(0x%02x) ", vendor, opcode);
+        break;
+    default:
+        if (table[opcode & 0x1f] != unknown)
+            printf("%s ",table[opcode & 0x1f]);
+        else
+            printf("%s(0x%02x) ", unknown, opcode);
+        break;
+    }
+}
+
+void sg_print_command (const unsigned char * command) {
+    int i,s;
+    print_opcode(command[0]);
+    for ( i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
+        printf("%02x ", command[i]);
+    printf("\n");
+}
+
+static const char * statuses[] = {
+/* 0-4 */ "Good", "Check Condition", "Condition Met", unknown, "Busy",
+/* 5-9 */ unknown, unknown, unknown, "Intermediate", unknown,
+/* a-c */ "Intermediate-Condition Met", unknown, "Reservation Conflict",
+/* d-10 */ unknown, unknown, unknown, unknown,
+/* 11-14 */ "Command Terminated", unknown, unknown, "Queue Full",
+/* 15-1a */ unknown, unknown, unknown,  unknown, unknown, unknown,
+/* 1b-1f */ unknown, unknown, unknown,  unknown, unknown,
+};
+
+void sg_print_status (int masked_status) {
+    /* status = (status >> 1) & 0xf; */ /* already done */
+    printf("%s ",statuses[masked_status]);
+}
+
+#define D 0x001  /* DIRECT ACCESS DEVICE (disk) */
+#define T 0x002  /* SEQUENTIAL ACCESS DEVICE (tape) */
+#define L 0x004  /* PRINTER DEVICE */
+#define P 0x008  /* PROCESSOR DEVICE */
+#define W 0x010  /* WRITE ONCE READ MULTIPLE DEVICE */
+#define R 0x020  /* READ ONLY (CD-ROM) DEVICE */
+#define S 0x040  /* SCANNER DEVICE */
+#define O 0x080  /* OPTICAL MEMORY DEVICE */
+#define M 0x100  /* MEDIA CHANGER DEVICE */
+#define C 0x200  /* COMMUNICATION DEVICE */
+
+struct error_info{
+    unsigned char code1, code2;
+    unsigned short int devices;
+    const char * text;
+};
+
+struct error_info2{
+    unsigned char code1, code2_min, code2_max;
+    unsigned short int devices;
+    const char * text;
+};
+
+static struct error_info2 additional2[] =
+{
+  {0x40,0x00,0x7f,D,"Ram failure (%x)"},
+  {0x40,0x80,0xff,D|T|L|P|W|R|S|O|M|C,"Diagnostic failure on component (%x)"},
+  {0x41,0x00,0xff,D,"Data path failure (%x)"},
+  {0x42,0x00,0xff,D,"Power-on or self-test failure (%x)"},
+  {0, 0, 0, 0, NULL}
+};
+
+static struct error_info additional[] =
+{
+  {0x00,0x01,T,"Filemark detected"},
+  {0x00,0x02,T|S,"End-of-partition/medium detected"},
+  {0x00,0x03,T,"Setmark detected"},
+  {0x00,0x04,T|S,"Beginning-of-partition/medium detected"},
+  {0x00,0x05,T|S,"End-of-data detected"},
+  {0x00,0x06,D|T|L|P|W|R|S|O|M|C,"I/O process terminated"},
+  {0x00,0x11,R,"Audio play operation in progress"},
+  {0x00,0x12,R,"Audio play operation paused"},
+  {0x00,0x13,R,"Audio play operation successfully completed"},
+  {0x00,0x14,R,"Audio play operation stopped due to error"},
+  {0x00,0x15,R,"No current audio status to return"},
+  {0x01,0x00,D|W|O,"No index/sector signal"},
+  {0x02,0x00,D|W|R|O|M,"No seek complete"},
+  {0x03,0x00,D|T|L|W|S|O,"Peripheral device write fault"},
+  {0x03,0x01,T,"No write current"},
+  {0x03,0x02,T,"Excessive write errors"},
+  {0x04,0x00,D|T|L|P|W|R|S|O|M|C,
+     "Logical unit not ready, cause not reportable"},
+  {0x04,0x01,D|T|L|P|W|R|S|O|M|C,
+     "Logical unit is in process of becoming ready"},
+  {0x04,0x02,D|T|L|P|W|R|S|O|M|C,
+     "Logical unit not ready, initializing command required"},
+  {0x04,0x03,D|T|L|P|W|R|S|O|M|C,
+     "Logical unit not ready, manual intervention required"},
+  {0x04,0x04,D|T|L|O,"Logical unit not ready, format in progress"},
+  {0x05,0x00,D|T|L|W|R|S|O|M|C,"Logical unit does not respond to selection"},
+  {0x06,0x00,D|W|R|O|M,"No reference position found"},
+  {0x07,0x00,D|T|L|W|R|S|O|M,"Multiple peripheral devices selected"},
+  {0x08,0x00,D|T|L|W|R|S|O|M|C,"Logical unit communication failure"},
+  {0x08,0x01,D|T|L|W|R|S|O|M|C,"Logical unit communication time-out"},
+  {0x08,0x02,D|T|L|W|R|S|O|M|C,"Logical unit communication parity error"},
+  {0x09,0x00,D|T|W|R|O,"Track following error"},
+  {0x09,0x01,W|R|O,"Tracking servo failure"},
+  {0x09,0x02,W|R|O,"Focus servo failure"},
+  {0x09,0x03,W|R|O,"Spindle servo failure"},
+  {0x0A,0x00,D|T|L|P|W|R|S|O|M|C,"Error log overflow"},
+  {0x0C,0x00,T|S,"Write error"},
+  {0x0C,0x01,D|W|O,"Write error recovered with auto reallocation"},
+  {0x0C,0x02,D|W|O,"Write error - auto reallocation failed"},
+  {0x10,0x00,D|W|O,"Id crc or ecc error"},
+  {0x11,0x00,D|T|W|R|S|O,"Unrecovered read error"},
+  {0x11,0x01,D|T|W|S|O,"Read retries exhausted"},
+  {0x11,0x02,D|T|W|S|O,"Error too long to correct"},
+  {0x11,0x03,D|T|W|S|O,"Multiple read errors"},
+  {0x11,0x04,D|W|O,"Unrecovered read error - auto reallocate failed"},
+  {0x11,0x05,W|R|O,"L-ec uncorrectable error"},
+  {0x11,0x06,W|R|O,"Circ unrecovered error"},
+  {0x11,0x07,W|O,"Data resynchronization error"},
+  {0x11,0x08,T,"Incomplete block read"},
+  {0x11,0x09,T,"No gap found"},
+  {0x11,0x0A,D|T|O,"Miscorrected error"},
+  {0x11,0x0B,D|W|O,"Unrecovered read error - recommend reassignment"},
+  {0x11,0x0C,D|W|O,"Unrecovered read error - recommend rewrite the data"},
+  {0x12,0x00,D|W|O,"Address mark not found for id field"},
+  {0x13,0x00,D|W|O,"Address mark not found for data field"},
+  {0x14,0x00,D|T|L|W|R|S|O,"Recorded entity not found"},
+  {0x14,0x01,D|T|W|R|O,"Record not found"},
+  {0x14,0x02,T,"Filemark or setmark not found"},
+  {0x14,0x03,T,"End-of-data not found"},
+  {0x14,0x04,T,"Block sequence error"},
+  {0x15,0x00,D|T|L|W|R|S|O|M,"Random positioning error"},
+  {0x15,0x01,D|T|L|W|R|S|O|M,"Mechanical positioning error"},
+  {0x15,0x02,D|T|W|R|O,"Positioning error detected by read of medium"},
+  {0x16,0x00,D|W|O,"Data synchronization mark error"},
+  {0x17,0x00,D|T|W|R|S|O,"Recovered data with no error correction applied"},
+  {0x17,0x01,D|T|W|R|S|O,"Recovered data with retries"},
+  {0x17,0x02,D|T|W|R|O,"Recovered data with positive head offset"},
+  {0x17,0x03,D|T|W|R|O,"Recovered data with negative head offset"},
+  {0x17,0x04,W|R|O,"Recovered data with retries and/or circ applied"},
+  {0x17,0x05,D|W|R|O,"Recovered data using previous sector id"},
+  {0x17,0x06,D|W|O,"Recovered data without ecc - data auto-reallocated"},
+  {0x17,0x07,D|W|O,"Recovered data without ecc - recommend reassignment"},
+  {0x18,0x00,D|T|W|R|O,"Recovered data with error correction applied"},
+  {0x18,0x01,D|W|R|O,"Recovered data with error correction and retries applied"},
+  {0x18,0x02,D|W|R|O,"Recovered data - data auto-reallocated"},
+  {0x18,0x03,R,"Recovered data with circ"},
+  {0x18,0x04,R,"Recovered data with lec"},
+  {0x18,0x05,D|W|R|O,"Recovered data - recommend reassignment"},
+  {0x19,0x00,D|O,"Defect list error"},
+  {0x19,0x01,D|O,"Defect list not available"},
+  {0x19,0x02,D|O,"Defect list error in primary list"},
+  {0x19,0x03,D|O,"Defect list error in grown list"},
+  {0x1A,0x00,D|T|L|P|W|R|S|O|M|C,"Parameter list length error"},
+  {0x1B,0x00,D|T|L|P|W|R|S|O|M|C,"Synchronous data transfer error"},
+  {0x1C,0x00,D|O,"Defect list not found"},
+  {0x1C,0x01,D|O,"Primary defect list not found"},
+  {0x1C,0x02,D|O,"Grown defect list not found"},
+  {0x1D,0x00,D|W|O,"Miscompare during verify operation"},
+  {0x1E,0x00,D|W|O,"Recovered id with ecc correction"},
+  {0x20,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid command operation code"},
+  {0x21,0x00,D|T|W|R|O|M,"Logical block address out of range"},
+  {0x21,0x01,M,"Invalid element address"},
+  {0x22,0x00,D,"Illegal function (should use 20 00, 24 00, or 26 00)"},
+  {0x24,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid field in cdb"},
+  {0x25,0x00,D|T|L|P|W|R|S|O|M|C,"Logical unit not supported"},
+  {0x26,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid field in parameter list"},
+  {0x26,0x01,D|T|L|P|W|R|S|O|M|C,"Parameter not supported"},
+  {0x26,0x02,D|T|L|P|W|R|S|O|M|C,"Parameter value invalid"},
+  {0x26,0x03,D|T|L|P|W|R|S|O|M|C,"Threshold parameters not supported"},
+  {0x27,0x00,D|T|W|O,"Write protected"},
+  {0x28,0x00,D|T|L|P|W|R|S|O|M|C,"Not ready to ready transition (medium may have changed)"},
+  {0x28,0x01,M,"Import or export element accessed"},
+  {0x29,0x00,D|T|L|P|W|R|S|O|M|C,"Power on, reset, or bus device reset occurred"},
+  {0x2A,0x00,D|T|L|W|R|S|O|M|C,"Parameters changed"},
+  {0x2A,0x01,D|T|L|W|R|S|O|M|C,"Mode parameters changed"},
+  {0x2A,0x02,D|T|L|W|R|S|O|M|C,"Log parameters changed"},
+  {0x2B,0x00,D|T|L|P|W|R|S|O|C,"Copy cannot execute since host cannot disconnect"},
+  {0x2C,0x00,D|T|L|P|W|R|S|O|M|C,"Command sequence error"},
+  {0x2C,0x01,S,"Too many windows specified"},
+  {0x2C,0x02,S,"Invalid combination of windows specified"},
+  {0x2D,0x00,T,"Overwrite error on update in place"},
+  {0x2F,0x00,D|T|L|P|W|R|S|O|M|C,"Commands cleared by another initiator"},
+  {0x30,0x00,D|T|W|R|O|M,"Incompatible medium installed"},
+  {0x30,0x01,D|T|W|R|O,"Cannot read medium - unknown format"},
+  {0x30,0x02,D|T|W|R|O,"Cannot read medium - incompatible format"},
+  {0x30,0x03,D|T,"Cleaning cartridge installed"},
+  {0x31,0x00,D|T|W|O,"Medium format corrupted"},
+  {0x31,0x01,D|L|O,"Format command failed"},
+  {0x32,0x00,D|W|O,"No defect spare location available"},
+  {0x32,0x01,D|W|O,"Defect list update failure"},
+  {0x33,0x00,T,"Tape length error"},
+  {0x36,0x00,L,"Ribbon, ink, or toner failure"},
+  {0x37,0x00,D|T|L|W|R|S|O|M|C,"Rounded parameter"},
+  {0x39,0x00,D|T|L|W|R|S|O|M|C,"Saving parameters not supported"},
+  {0x3A,0x00,D|T|L|W|R|S|O|M,"Medium not present"},
+  {0x3B,0x00,T|L,"Sequential positioning error"},
+  {0x3B,0x01,T,"Tape position error at beginning-of-medium"},
+  {0x3B,0x02,T,"Tape position error at end-of-medium"},
+  {0x3B,0x03,L,"Tape or electronic vertical forms unit not ready"},
+  {0x3B,0x04,L,"Slew failure"},
+  {0x3B,0x05,L,"Paper jam"},
+  {0x3B,0x06,L,"Failed to sense top-of-form"},
+  {0x3B,0x07,L,"Failed to sense bottom-of-form"},
+  {0x3B,0x08,T,"Reposition error"},
+  {0x3B,0x09,S,"Read past end of medium"},
+  {0x3B,0x0A,S,"Read past beginning of medium"},
+  {0x3B,0x0B,S,"Position past end of medium"},
+  {0x3B,0x0C,S,"Position past beginning of medium"},
+  {0x3B,0x0D,M,"Medium destination element full"},
+  {0x3B,0x0E,M,"Medium source element empty"},
+  {0x3D,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid bits in identify message"},
+  {0x3E,0x00,D|T|L|P|W|R|S|O|M|C,"Logical unit has not self-configured yet"},
+  {0x3F,0x00,D|T|L|P|W|R|S|O|M|C,"Target operating conditions have changed"},
+  {0x3F,0x01,D|T|L|P|W|R|S|O|M|C,"Microcode has been changed"},
+  {0x3F,0x02,D|T|L|P|W|R|S|O|M|C,"Changed operating definition"},
+  {0x3F,0x03,D|T|L|P|W|R|S|O|M|C,"Inquiry data has changed"},
+  {0x43,0x00,D|T|L|P|W|R|S|O|M|C,"Message error"},
+  {0x44,0x00,D|T|L|P|W|R|S|O|M|C,"Internal target failure"},
+  {0x45,0x00,D|T|L|P|W|R|S|O|M|C,"Select or reselect failure"},
+  {0x46,0x00,D|T|L|P|W|R|S|O|M|C,"Unsuccessful soft reset"},
+  {0x47,0x00,D|T|L|P|W|R|S|O|M|C,"Scsi parity error"},
+  {0x48,0x00,D|T|L|P|W|R|S|O|M|C,"Initiator detected error message received"},
+  {0x49,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid message error"},
+  {0x4A,0x00,D|T|L|P|W|R|S|O|M|C,"Command phase error"},
+  {0x4B,0x00,D|T|L|P|W|R|S|O|M|C,"Data phase error"},
+  {0x4C,0x00,D|T|L|P|W|R|S|O|M|C,"Logical unit failed self-configuration"},
+  {0x4E,0x00,D|T|L|P|W|R|S|O|M|C,"Overlapped commands attempted"},
+  {0x50,0x00,T,"Write append error"},
+  {0x50,0x01,T,"Write append position error"},
+  {0x50,0x02,T,"Position error related to timing"},
+  {0x51,0x00,T|O,"Erase failure"},
+  {0x52,0x00,T,"Cartridge fault"},
+  {0x53,0x00,D|T|L|W|R|S|O|M,"Media load or eject failed"},
+  {0x53,0x01,T,"Unload tape failure"},
+  {0x53,0x02,D|T|W|R|O|M,"Medium removal prevented"},
+  {0x54,0x00,P,"Scsi to host system interface failure"},
+  {0x55,0x00,P,"System resource failure"},
+  {0x57,0x00,R,"Unable to recover table-of-contents"},
+  {0x58,0x00,O,"Generation does not exist"},
+  {0x59,0x00,O,"Updated block read"},
+  {0x5A,0x00,D|T|L|P|W|R|S|O|M,"Operator request or state change input (unspecified)"},
+  {0x5A,0x01,D|T|W|R|O|M,"Operator medium removal request"},
+  {0x5A,0x02,D|T|W|O,"Operator selected write protect"},
+  {0x5A,0x03,D|T|W|O,"Operator selected write permit"},
+  {0x5B,0x00,D|T|L|P|W|R|S|O|M,"Log exception"},
+  {0x5B,0x01,D|T|L|P|W|R|S|O|M,"Threshold condition met"},
+  {0x5B,0x02,D|T|L|P|W|R|S|O|M,"Log counter at maximum"},
+  {0x5B,0x03,D|T|L|P|W|R|S|O|M,"Log list codes exhausted"},
+  {0x5C,0x00,D|O,"Rpl status change"},
+  {0x5C,0x01,D|O,"Spindles synchronized"},
+  {0x5C,0x02,D|O,"Spindles not synchronized"},
+  {0x60,0x00,S,"Lamp failure"},
+  {0x61,0x00,S,"Video acquisition error"},
+  {0x61,0x01,S,"Unable to acquire video"},
+  {0x61,0x02,S,"Out of focus"},
+  {0x62,0x00,S,"Scan head positioning error"},
+  {0x63,0x00,R,"End of user area encountered on this track"},
+  {0x64,0x00,R,"Illegal mode for this track"},
+  {0, 0, 0, NULL}
+};
+
+static const char *snstext[] = {
+    "None",                     /* There is no sense information */
+    "Recovered Error",          /* The last command completed successfully
+                                   but used error correction */
+    "Not Ready",                /* The addressed target is not ready */
+    "Medium Error",             /* Data error detected on the medium */
+    "Hardware Error",           /* Controller or device failure */
+    "Illegal Request",
+    "Unit Attention",           /* Removable medium was changed, or
+                                   the target has been reset */
+    "Data Protect",             /* Access to the data is blocked */
+    "Blank Check",              /* Reached unexpected written or unwritten
+                                   region of the medium */
+    "Key=9",                    /* Vendor specific */
+    "Copy Aborted",             /* COPY or COMPARE was aborted */
+    "Aborted Command",          /* The target aborted the command */
+    "Equal",                    /* A SEARCH DATA command found data equal */
+    "Volume Overflow",          /* Medium full with still data to be written */
+    "Miscompare",               /* Source data and data on the medium
+                                   do not agree */
+    "Key=15"                    /* Reserved */
+};
+
+/* Print sense information */
+void sg_print_sense(const char * leadin, const unsigned char * sense_buffer,
+                    int sb_len)
+{
+    int i, s;
+    int sense_class, valid, code;
+    const char * error = NULL;
+
+    sense_class = (sense_buffer[0] >> 4) & 0x07;
+    code = sense_buffer[0] & 0xf;
+    valid = sense_buffer[0] & 0x80;
+
+    if (sense_class == 7) {     /* extended sense data */
+        s = sense_buffer[7] + 8;
+        if(s > sb_len)
+           s = sb_len;
+
+        if (!valid)
+            printf("[valid=0] ");
+        printf("Info fld=0x%x, ", (int)((sense_buffer[3] << 24) |
+               (sense_buffer[4] << 16) | (sense_buffer[5] << 8) |
+               sense_buffer[6]));
+
+        if (sense_buffer[2] & 0x80)
+           printf( "FMK ");     /* current command has read a filemark */
+        if (sense_buffer[2] & 0x40)
+           printf( "EOM ");     /* end-of-medium condition exists */
+        if (sense_buffer[2] & 0x20)
+           printf( "ILI ");     /* incorrect block length requested */
+
+        switch (code) {
+        case 0x0:
+            error = "Current";  /* error concerns current command */
+            break;
+        case 0x1:
+            error = "Deferred"; /* error concerns some earlier command */
+                /* e.g., an earlier write to disk cache succeeded, but
+                   now the disk discovers that it cannot write the data */
+            break;
+        default:
+            error = "Invalid";
+        }
+
+        printf("%s ", error);
+
+        if (leadin)
+            printf("%s: ", leadin);
+        printf("sense key: %s\n", snstext[sense_buffer[2] & 0x0f]);
+
+        /* Check to see if additional sense information is available */
+        if(sense_buffer[7] + 7 < 13 ||
+           (sense_buffer[12] == 0  && sense_buffer[13] ==  0)) goto done;
+
+        for(i=0; additional[i].text; i++)
+            if(additional[i].code1 == sense_buffer[12] &&
+               additional[i].code2 == sense_buffer[13])
+                printf("Additional sense indicates: %s\n",
+                       additional[i].text);
+
+        for(i=0; additional2[i].text; i++)
+            if(additional2[i].code1 == sense_buffer[12] &&
+               additional2[i].code2_min >= sense_buffer[13]  &&
+               additional2[i].code2_max <= sense_buffer[13]) {
+                printf("Additional sense indicates: ");
+                printf(additional2[i].text, sense_buffer[13]);
+                printf("\n");
+            };
+    } else {    /* non-extended sense data */
+
+         /*
+          * Standard says:
+          *    sense_buffer[0] & 0200 : address valid
+          *    sense_buffer[0] & 0177 : vendor-specific error code
+          *    sense_buffer[1] & 0340 : vendor-specific
+          *    sense_buffer[1..3] : 21-bit logical block address
+          */
+
+        if (leadin)
+            printf("%s: ", leadin);
+        if (sense_buffer[0] < 15)
+            printf("old sense: key %s\n", snstext[sense_buffer[0] & 0x0f]);
+        else
+            printf("sns = %2x %2x\n", sense_buffer[0], sense_buffer[2]);
+
+        printf("Non-extended sense class %d code 0x%0x ", sense_class, code);
+        s = 4;
+    }
+
+ done:
+    printf("Raw sense data (in hex):\n  ");
+    for (i = 0; i < s; ++i) {
+        if ((i > 0) && (0 == (i % 24)))
+            printf("\n  ");
+        printf("%02x ", sense_buffer[i]);
+    }
+    printf("\n");
+    return;
+}
+
+static const char * hostbyte_table[]={
+"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET",
+"DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
+"DID_PASSTHROUGH", "DID_SOFT_ERROR", NULL};
+
+void sg_print_host_status(int host_status)
+{   static int maxcode=0;
+    int i;
+
+    if(! maxcode) {
+        for(i = 0; hostbyte_table[i]; i++) ;
+        maxcode = i-1;
+    }
+    printf("Host_status=0x%02x", host_status);
+    if(host_status > maxcode) {
+        printf("is invalid ");
+        return;
+    }
+    printf("(%s) ",hostbyte_table[host_status]);
+}
+
+static const char * driverbyte_table[]={
+"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT",  "DRIVER_MEDIA", "DRIVER_ERROR",
+"DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE", NULL};
+
+static const char * driversuggest_table[]={"SUGGEST_OK",
+"SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE",
+unknown,unknown,unknown, "SUGGEST_SENSE",NULL};
+
+
+void sg_print_driver_status(int driver_status)
+{
+    static int driver_max =0 , suggest_max=0;
+    int i;
+    int dr = driver_status & SG_ERR_DRIVER_MASK;
+    int su = (driver_status & SG_ERR_SUGGEST_MASK) >> 4;
+
+    if(! driver_max) {
+        for(i = 0; driverbyte_table[i]; i++) ;
+        driver_max = i;
+        for(i = 0; driversuggest_table[i]; i++) ;
+        suggest_max = i;
+    }
+    printf("Driver_status=0x%02x",driver_status);
+    printf(" (%s,%s) ",
+        dr < driver_max  ? driverbyte_table[dr]:"invalid",
+        su < suggest_max ? driversuggest_table[su]:"invalid");
+}
+
+#ifdef SG_IO
+int sg_chk_n_print3(const char * leadin, sg_io_hdr_t * hp)
+{
+    return sg_chk_n_print(leadin, hp->masked_status, hp->host_status,
+                          hp->driver_status, hp->sbp, hp->sb_len_wr);
+}
+#endif
+
+int sg_chk_n_print(const char * leadin, int masked_status,
+                   int host_status, int driver_status,
+                   const unsigned char * sense_buffer, int sb_len)
+{
+    int done_leadin = 0;
+    int done_sense = 0;
+
+    if ((0 == masked_status) && (0 == host_status) &&
+        (0 == driver_status))
+        return 1;       /* No problems */
+    if (0 != masked_status) {
+        if (leadin)
+            printf("%s: ", leadin);
+        done_leadin = 1;
+        sg_print_status(masked_status);
+        printf("\n");
+        if (sense_buffer && ((masked_status == CHECK_CONDITION) ||
+                             (masked_status == COMMAND_TERMINATED))) {
+            sg_print_sense(0, sense_buffer, sb_len);
+            done_sense = 1;
+        }
+    }
+    if (0 != host_status) {
+        if (leadin && (! done_leadin))
+            printf("%s: ", leadin);
+        if (done_leadin)
+            printf("plus...: ");
+        else
+            done_leadin = 1;
+        sg_print_host_status(host_status);
+        printf("\n");
+    }
+    if (0 != driver_status) {
+        if (leadin && (! done_leadin))
+            printf("%s: ", leadin);
+        if (done_leadin)
+            printf("plus...: ");
+        else
+            done_leadin = 1;
+        sg_print_driver_status(driver_status);
+        printf("\n");
+        if (sense_buffer && (! done_sense) &&
+            (SG_ERR_DRIVER_SENSE & driver_status))
+            sg_print_sense(0, sense_buffer, sb_len);
+    }
+    return 0;
+}
+
+#ifdef SG_IO
+int sg_err_category3(sg_io_hdr_t * hp)
+{
+    return sg_err_category(hp->masked_status, hp->host_status,
+                           hp->driver_status, hp->sbp, hp->sb_len_wr);
+}
+#endif
+
+int sg_err_category(int masked_status, int host_status,
+                    int driver_status, const unsigned char * sense_buffer,
+                    int sb_len)
+{
+    if ((0 == masked_status) && (0 == host_status) &&
+        (0 == driver_status))
+        return SG_ERR_CAT_CLEAN;
+    if ((CHECK_CONDITION == masked_status) ||
+        (COMMAND_TERMINATED == masked_status) ||
+        (SG_ERR_DRIVER_SENSE & driver_status)) {
+        if (sense_buffer && (sb_len > 2)) {
+            if(RECOVERED_ERROR == sense_buffer[2])
+                return SG_ERR_CAT_RECOVERED;
+            else if ((UNIT_ATTENTION == (0x0f & sense_buffer[2])) &&
+                     (sb_len > 12)) {
+                if (0x28 == sense_buffer[12])
+                    return SG_ERR_CAT_MEDIA_CHANGED;
+                if (0x29 == sense_buffer[12])
+                    return SG_ERR_CAT_RESET;
+            }
+        }
+        return SG_ERR_CAT_SENSE;
+    }
+    if (0 != host_status) {
+        if ((SG_ERR_DID_NO_CONNECT == host_status) ||
+            (SG_ERR_DID_BUS_BUSY == host_status) ||
+            (SG_ERR_DID_TIME_OUT == host_status))
+            return SG_ERR_CAT_TIMEOUT;
+    }
+    if (0 != driver_status) {
+        if (SG_ERR_DRIVER_TIMEOUT == driver_status)
+            return SG_ERR_CAT_TIMEOUT;
+    }
+    return SG_ERR_CAT_OTHER;
+}
+
+int sg_get_command_size(unsigned char opcode)
+{
+    return COMMAND_SIZE(opcode);
+}
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/sg_err.h parted-1.4.7-gpt/libparted/sg_err.h
--- parted-1.4.7/libparted/sg_err.h	Wed Dec 31 18:00:00 1969
+++ parted-1.4.7-gpt/libparted/sg_err.h	Thu Jan 18 11:24:42 2001
@@ -0,0 +1,156 @@
+ /*
+    libparted - a library for manipulating disk partitions
+    Copyright (C) 1998-2000 Free Software Foundation, Inc.
+
+    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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef SG_ERR_H
+#define SG_ERR_H
+#include <linux/../scsi/scsi.h>  /* cope with silly includes */
+#include <linux/../scsi/sg.h>
+
+/* Feel free to copy and modify this GPL-ed code into your applications. */
+
+/* Version 0.83 (991208) */
+
+
+/* Some of the following error/status codes are exchanged between the
+   various layers of the SCSI sub-system in Linux and should never
+   reach the user. They are placed here for completeness. What appears
+   here is copied from drivers/scsi/scsi.h which is not visible in
+   the user space. */
+
+/* The following are 'host_status' codes */
+#ifndef DID_OK
+#define DID_OK 0x00
+#endif
+#ifndef DID_NO_CONNECT
+#define DID_NO_CONNECT 0x01     /* Unable to connect before timeout */
+#define DID_BUS_BUSY 0x02       /* Bus remain busy until timeout */
+#define DID_TIME_OUT 0x03       /* Timed out for some other reason */
+#define DID_BAD_TARGET 0x04     /* Bad target (id?) */
+#define DID_ABORT 0x05          /* Told to abort for some other reason */
+#define DID_PARITY 0x06         /* Parity error (on SCSI bus) */
+#define DID_ERROR 0x07          /* Internal error */
+#define DID_RESET 0x08          /* Reset by somebody */
+#define DID_BAD_INTR 0x09       /* Received an unexpected interrupt */
+#define DID_PASSTHROUGH 0x0a    /* Force command past mid-level */
+#define DID_SOFT_ERROR 0x0b     /* The low-level driver wants a retry */
+#endif
+
+/* These defines are to isolate applictaions from kernel define changes */
+#define SG_ERR_DID_OK           DID_OK
+#define SG_ERR_DID_NO_CONNECT   DID_NO_CONNECT
+#define SG_ERR_DID_BUS_BUSY     DID_BUS_BUSY
+#define SG_ERR_DID_TIME_OUT     DID_TIME_OUT
+#define SG_ERR_DID_BAD_TARGET   DID_BAD_TARGET
+#define SG_ERR_DID_ABORT        DID_ABORT
+#define SG_ERR_DID_PARITY       DID_PARITY
+#define SG_ERR_DID_ERROR        DID_ERROR
+#define SG_ERR_DID_RESET        DID_RESET
+#define SG_ERR_DID_BAD_INTR     DID_BAD_INTR
+#define SG_ERR_DID_PASSTHROUGH  DID_PASSTHROUGH
+#define SG_ERR_DID_SOFT_ERROR   DID_SOFT_ERROR
+
+/* The following are 'driver_status' codes */
+#ifndef DRIVER_OK
+#define DRIVER_OK 0x00
+#endif
+#ifndef DRIVER_BUSY
+#define DRIVER_BUSY 0x01
+#define DRIVER_SOFT 0x02
+#define DRIVER_MEDIA 0x03
+#define DRIVER_ERROR 0x04
+#define DRIVER_INVALID 0x05
+#define DRIVER_TIMEOUT 0x06
+#define DRIVER_HARD 0x07
+#define DRIVER_SENSE 0x08       /* Sense_buffer has been set */
+
+/* Following "suggests" are "or-ed" with one of previous 8 entries */
+#define SUGGEST_RETRY 0x10
+#define SUGGEST_ABORT 0x20
+#define SUGGEST_REMAP 0x30
+#define SUGGEST_DIE 0x40
+#define SUGGEST_SENSE 0x80
+#define SUGGEST_IS_OK 0xff
+#endif
+#ifndef DRIVER_MASK
+#define DRIVER_MASK 0x0f
+#endif
+#ifndef SUGGEST_MASK
+#define SUGGEST_MASK 0xf0
+#endif
+
+/* These defines are to isolate applictaions from kernel define changes */
+#define SG_ERR_DRIVER_OK        DRIVER_OK
+#define SG_ERR_DRIVER_BUSY      DRIVER_BUSY
+#define SG_ERR_DRIVER_SOFT      DRIVER_SOFT
+#define SG_ERR_DRIVER_MEDIA     DRIVER_MEDIA
+#define SG_ERR_DRIVER_ERROR     DRIVER_ERROR
+#define SG_ERR_DRIVER_INVALID   DRIVER_INVALID
+#define SG_ERR_DRIVER_TIMEOUT   DRIVER_TIMEOUT
+#define SG_ERR_DRIVER_HARD      DRIVER_HARD
+#define SG_ERR_DRIVER_SENSE     DRIVER_SENSE
+#define SG_ERR_SUGGEST_RETRY    SUGGEST_RETRY
+#define SG_ERR_SUGGEST_ABORT    SUGGEST_ABORT
+#define SG_ERR_SUGGEST_REMAP    SUGGEST_REMAP
+#define SG_ERR_SUGGEST_DIE      SUGGEST_DIE
+#define SG_ERR_SUGGEST_SENSE    SUGGEST_SENSE
+#define SG_ERR_SUGGEST_IS_OK    SUGGEST_IS_OK
+#define SG_ERR_DRIVER_MASK      DRIVER_MASK
+#define SG_ERR_SUGGEST_MASK     SUGGEST_MASK
+
+
+
+/* The following "print" functions send ACSII to stdout */
+extern void sg_print_command(const unsigned char * command);
+extern void sg_print_sense(const char * leadin,
+                           const unsigned char * sense_buffer, int sb_len);
+extern void sg_print_status(int masked_status);
+extern void sg_print_host_status(int host_status);
+extern void sg_print_driver_status(int driver_status);
+
+/* sg_chk_n_print() returns 1 quietly if there are no errors/warnings
+   else it prints to standard output and returns 0. */
+extern int sg_chk_n_print(const char * leadin, int masked_status,
+                          int host_status, int driver_status,
+                          const unsigned char * sense_buffer, int sb_len);
+#ifdef SG_IO
+extern int sg_chk_n_print3(const char * leadin, sg_io_hdr_t * hp);
+#endif
+
+
+/* The following "category" function returns one of the following */
+#define SG_ERR_CAT_CLEAN 0      /* No errors or other information */
+#define SG_ERR_CAT_MEDIA_CHANGED 1 /* interpreted from sense buffer */
+#define SG_ERR_CAT_RESET 2      /* interpreted from sense buffer */
+#define SG_ERR_CAT_TIMEOUT 3
+#define SG_ERR_CAT_RECOVERED 4  /* Successful command after recovered err */
+#define SG_ERR_CAT_SENSE 98     /* Something else is in the sense buffer */
+#define SG_ERR_CAT_OTHER 99     /* Some other error/warning has occurred */
+
+extern int sg_err_category(int masked_status, int host_status,
+               int driver_status, const unsigned char * sense_buffer,
+               int sb_len);
+#ifdef SG_IO
+extern int sg_err_category3(sg_io_hdr_t * hp);
+#endif
+
+
+/* Returns length of SCSI command given the opcode (first byte) */
+int sg_get_command_size(unsigned char opcode);
+
+#endif
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/sg_map.c parted-1.4.7-gpt/libparted/sg_map.c
--- parted-1.4.7/libparted/sg_map.c	Wed Dec 31 18:00:00 1969
+++ parted-1.4.7-gpt/libparted/sg_map.c	Thu Jan 18 11:24:42 2001
@@ -0,0 +1,422 @@
+/*
+    libparted - a library for manipulating disk partitions
+    Copyright (C) 1998-2000 Free Software Foundation, Inc.
+
+    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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <linux/../scsi/sg.h>  /* cope with silly includes */
+#include <linux/../scsi/scsi.h>
+
+/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg")
+   device driver.
+*  Copyright (C) 2000 D. Gilbert
+*  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
+*  the Free Software Foundation; either version 2, or (at your option)
+*  any later version.
+
+   This shows the mapping from "sg" devices to other scsi devices
+   (i.e. sd, scd or st) if any.
+   Options: -n   numeric scan: scan /dev/sg0,1,2, .... [default]
+            -a   alphabetical scan: scan /dev/sga,b,c, ....
+            -x   also show bus,chan,id,lun and type
+            -sd  only scan for sd devices (disks)
+            -st  only scan for st devices (tapes)
+            -scd (or -sr)  only scan for scd devices (cdroms)
+
+   Note: This program requires sg version 2 or better.
+
+   Version 0.12 20000415
+*/
+
+#include "sg_map.h"
+
+struct _sg_to_sd sg_to_sd[MAX_SG_DEVS];
+
+#ifndef SG_GET_RESERVED_SIZE
+#error "Need version 2 sg driver (linux kernel >= 2.2.6)"
+#endif
+
+static const char * devfs_id = "/dev/.devfsd";
+
+#define NUMERIC_SCAN_DEF 1   /* change to 0 to make alpha scan default */
+
+
+typedef struct my_map_info
+{
+    int active;
+    int lin_dev_type;
+    int oth_dev_num;
+    struct sg_scsi_id sg_dat;
+} my_map_info_t;
+
+
+#define MAX_SG_DEVS 128
+#define MAX_SD_DEVS 128
+#define MAX_SR_DEVS 128
+#define MAX_ST_DEVS 128
+#define MAX_ERRORS 4
+
+static my_map_info_t map_arr[MAX_SG_DEVS];
+
+#define LIN_DEV_TYPE_UNKNOWN 0
+#define LIN_DEV_TYPE_SD 1
+#define LIN_DEV_TYPE_SR 2
+#define LIN_DEV_TYPE_ST 3
+#define LIN_DEV_TYPE_SCD 4
+
+
+typedef struct my_scsi_idlun {
+/* why can't userland see this structure ??? */
+    int dev_id;
+    int host_unique_id;
+} My_scsi_idlun;
+
+
+#define EBUFF_LEN 256
+static char ebuff[EBUFF_LEN];
+
+static void scan_dev_type(const char * leadin, int max_dev, int do_numeric,
+                          int lin_dev_type, int last_sg_ind);
+
+static void usage()
+{
+    printf("Usage: 'sg_map [-a] [-n] [-x] [-sd] [-scd or -sr] [-st]'\n");
+    printf("    where: -a   do alphabetic scan (ie sga, sgb, sgc)\n");
+    printf("           -n   do numeric scan (ie sg0, sg1, sg2)\n");
+    printf("           -x   also show bus,chan,id,lun and type\n");
+    printf("           -sd  show mapping to disks\n");
+    printf("           -scd show mapping to cdroms (look for /dev/scd<n>\n");
+    printf("           -sr  show mapping to cdroms (look for /dev/sr<n>\n");
+    printf("           -st  show mapping to tapes\n");
+    printf("    If no '-s*' arguments given then show all mappings\n");
+}
+
+
+static void make_dev_name(char * fname, const char * leadin, int k, 
+                          int do_numeric)
+{
+    char buff[64];
+    int  big,little;
+
+    strcpy(fname, leadin ? leadin : "/dev/sg");
+    if (do_numeric) {
+        sprintf(buff, "%d", k);
+        strcat(fname, buff);
+    }
+    else {
+        if (k < 26) {
+            buff[0] = 'a' + (char)k;
+            buff[1] = '\0';
+            strcat(fname, buff);
+        }
+        else if (k <= 255) { /* assumes sequence goes x,y,z,aa,ab,ac etc */
+            big    = k/26;
+            little = k - (26 * big);
+            big    = big - 1;
+
+            buff[0] = 'a' + (char)big;
+            buff[1] = 'a' + (char)little;
+            buff[2] = '\0';
+            strcat(fname, buff);
+        }
+        else
+            strcat(fname, "xxxx");
+    }
+}
+
+int sg_to_sd_map_made = 0;
+
+int
+make_sg_to_sd_map()
+{
+    int sg_fd, res, k;
+    int do_numeric = NUMERIC_SCAN_DEF;
+    int do_all_s = 0;
+    int do_sd = 1;
+    int do_st = 0;
+    int do_sr = 0;
+    int do_scd = 0;
+    int do_extra = 0;
+    char fname[64];
+    int num_errors = 0;
+    int num_silent = 0;
+    int eacces_err = 0;
+    int last_sg_ind = -1;
+    struct stat stat_buf;
+
+    memset(&sg_to_sd, 0, MAX_SG_DEVS * sizeof(struct _sg_to_sd));
+
+#if 0
+    for (k = 1; k < argc; ++k) {
+        if (0 == strcmp("-n", argv[k]))
+            do_numeric = 1;
+        else if (0 == strcmp("-a", argv[k]))
+            do_numeric = 0;
+        else if (0 == strcmp("-x", argv[k]))
+            do_extra = 1;
+        else if (0 == strcmp("-sd", argv[k])) {
+            do_sd = 1;
+            do_all_s = 0;
+        }
+        else if (0 == strcmp("-st", argv[k])) {
+            do_st = 1;
+            do_all_s = 0;
+        }
+        else if (0 == strcmp("-sr", argv[k])) {
+            do_sr = 1;
+            do_all_s = 0;
+        }
+        else if (0 == strcmp("-scd", argv[k])) {
+            do_scd = 1;
+            do_all_s = 0;
+        }
+        else if ((0 == strcmp("-?", argv[k])) ||
+                 (0 == strncmp("-h", argv[k], 2))) {
+            printf(
+            "Show mapping from sg devices to other scsi device names\n\n");
+            usage();
+            return 1;
+        }
+        else if (*argv[k] == '-') {
+            printf("Unknown switch: %s\n", argv[k]);
+            usage();
+            return 1;
+        }
+        else if (*argv[k] != '-') {
+            printf("Unknown argument\n");
+            usage();
+            return 1;
+        }
+    }
+#endif
+
+    if (stat(devfs_id, &stat_buf) == 0)
+        printf("# Note: the devfs pseudo file system is present\n");
+
+    for (k = 0, res = 0; (k < MAX_SG_DEVS)  && (num_errors < MAX_ERRORS);
+         ++k, res = (sg_fd >= 0) ? close(sg_fd) : 0) {
+        if (res < 0) {
+            sprintf(ebuff, "Error closing %s ", fname);
+            perror("sg_map: close error");
+            return 1;
+        }
+        make_dev_name(fname, "/dev/sg", k, do_numeric);
+
+        sg_fd = open(fname, O_RDONLY | O_NONBLOCK);
+        if (sg_fd < 0) {
+            if (EBUSY == errno) {
+                map_arr[k].active = -2;
+                continue;
+            }
+            else if ((ENODEV == errno) || (ENOENT == errno) ||
+                     (ENXIO == errno)) {
+                ++num_errors;
+                ++num_silent;
+                map_arr[k].active = -1;
+                continue;
+            }
+            else {
+                if (EACCES == errno)
+                    eacces_err = 1;
+                sprintf(ebuff, "Error opening %s ", fname);
+                perror(ebuff);
+                ++num_errors;
+                continue;
+            }
+        }
+        res = ioctl(sg_fd, SG_GET_SCSI_ID, &map_arr[k].sg_dat);
+        if (res < 0) {
+            sprintf(ebuff, "device %s failed on sg ioctl, skip", fname);
+            perror(ebuff);
+            ++num_errors;
+            continue;
+        }
+        map_arr[k].active = 1;
+        map_arr[k].oth_dev_num = -1;
+        last_sg_ind = k;
+    }
+    if ((num_errors >= MAX_ERRORS) && (num_silent < num_errors)) {
+        printf("Stopping because there are too many error\n");
+        if (eacces_err)
+            printf("    root access may be required\n");
+        return 1;
+    }
+    if (last_sg_ind < 0) {
+        printf("Stopping because no sg devices found\n");
+    }
+
+    if (do_all_s || do_sd)
+        scan_dev_type("/dev/sd", MAX_SD_DEVS, 0, LIN_DEV_TYPE_SD, last_sg_ind);
+#if 0
+    if (do_all_s || do_sr)
+        scan_dev_type("/dev/sr", MAX_SR_DEVS, 1, LIN_DEV_TYPE_SR, last_sg_ind);
+    if (do_all_s || do_scd)
+        scan_dev_type("/dev/scd", MAX_SR_DEVS, 1, LIN_DEV_TYPE_SCD, 
+                      last_sg_ind);
+    if (do_all_s || do_st)
+        scan_dev_type("/dev/st", MAX_ST_DEVS, 1, LIN_DEV_TYPE_ST, last_sg_ind);
+#endif
+
+    for (k = 0; k <= last_sg_ind; ++k) {
+        make_dev_name(fname, "/dev/sg", k, do_numeric);
+        // printf("%s", fname);
+	snprintf(sg_to_sd[k].sg, 15, "%s", fname);
+        switch (map_arr[k].active)
+        {
+        case -2:
+            printf(do_extra ? "  -2 -2 -2 -2  -2" : "  busy");
+            break;
+        case -1:
+            printf(do_extra ? "  -1 -1 -1 -1  -1" : "  not present");
+            break;
+        case 0:
+            printf(do_extra ? "  -3 -3 -3 -3  -3" : "  some error\n");
+            break;
+        case 1:
+            if (do_extra) 
+                printf("  %d %d %d %d  %d", map_arr[k].sg_dat.host_no,
+                       map_arr[k].sg_dat.channel, map_arr[k].sg_dat.scsi_id,
+                       map_arr[k].sg_dat.lun, map_arr[k].sg_dat.scsi_type);
+            switch (map_arr[k].lin_dev_type)
+            {
+            case LIN_DEV_TYPE_SD:
+                make_dev_name(fname, "/dev/sd" , map_arr[k].oth_dev_num, 0);
+                // printf("  %s", fname);
+		snprintf(sg_to_sd[k].sd, 15, "%s", fname);
+                break;
+#if 0
+            case LIN_DEV_TYPE_ST:
+                make_dev_name(fname, "/dev/st" , map_arr[k].oth_dev_num, 1);
+                printf("  %s", fname);
+                break;
+            case LIN_DEV_TYPE_SR:
+                make_dev_name(fname, "/dev/sr" , map_arr[k].oth_dev_num, 1);
+                printf("  %s", fname);
+                break;
+            case LIN_DEV_TYPE_SCD:
+                make_dev_name(fname, "/dev/scd" , map_arr[k].oth_dev_num, 1);
+                printf("  %s", fname);
+                break;
+#endif
+            default:
+                break;
+            }
+            break;
+        default:
+            printf("  bad logic\n");
+            break;
+        }
+        // printf("\n");
+    }
+
+    sg_to_sd_map_made = 1;
+    return 0;
+}
+        
+static int find_dev_in_sg_arr(My_scsi_idlun * my_idlun, int host_no, 
+                              int last_sg_ind)
+{
+    int k;
+    struct sg_scsi_id * sidp;
+
+    for (k = 0; k <= last_sg_ind; ++k) {
+        sidp = &(map_arr[k].sg_dat);
+        if ((host_no == sidp->host_no) &&
+            ((my_idlun->dev_id & 0xff) == sidp->scsi_id) &&
+            (((my_idlun->dev_id >> 8) & 0xff) == sidp->lun) &&
+            (((my_idlun->dev_id >> 16) & 0xff) == sidp->channel))
+            return k;
+    }
+    return -1;
+}
+
+static void scan_dev_type(const char * leadin, int max_dev, int do_numeric,
+                          int lin_dev_type, int last_sg_ind)
+{
+    int k, res, ind, sg_fd;
+    int num_errors = 0;
+    int num_silent = 0;
+    int host_no = -1;
+    My_scsi_idlun my_idlun;
+    char fname[64];
+
+    for (k = 0, res = 0; (k < max_dev)  && (num_errors < MAX_ERRORS);
+         ++k, res = (sg_fd >= 0) ? close(sg_fd) : 0) {
+        if (res < 0) {
+            sprintf(ebuff, "Error closing %s ", fname);
+            perror("sg_map: close error");
+            return;
+        }
+        make_dev_name(fname, leadin, k, do_numeric);
+
+        sg_fd = open(fname, O_RDONLY | O_NONBLOCK);
+        if (sg_fd < 0) {
+            if (EBUSY == errno) {
+                printf("Device %s is busy\n", fname);
+                ++num_errors;
+                continue;
+            }
+            else if ((ENODEV == errno) || (ENOENT == errno) ||
+                     (ENXIO == errno)) {
+                ++num_errors;
+                ++num_silent;
+                continue;
+            }
+            else {
+                sprintf(ebuff, "Error opening %s ", fname);
+                perror(ebuff);
+                ++num_errors;
+                continue;
+            }
+        }
+
+        res = ioctl(sg_fd, SCSI_IOCTL_GET_IDLUN, &my_idlun);
+        if (res < 0) {
+            sprintf(ebuff, "device %s failed on scsi ioctl(idlun), skip", 
+                    fname);
+            perror(ebuff);
+            ++num_errors;
+            continue;
+        }
+        res = ioctl(sg_fd, SCSI_IOCTL_GET_BUS_NUMBER, &host_no);
+        if (res < 0) {
+            sprintf(ebuff, "device %s failed on scsi ioctl(bus_number), skip",
+                    fname);
+            perror(ebuff);
+            ++num_errors;
+            continue;
+        }
+        ind = find_dev_in_sg_arr(&my_idlun, host_no, last_sg_ind);
+        if (ind >= 0) {
+            map_arr[ind].oth_dev_num = k;
+            map_arr[ind].lin_dev_type = lin_dev_type;
+        }
+        else
+            printf("Strange, could not find device %s mapped to sg device??\n", 
+                   fname);
+    }
+}
+
diff -BburN --exclude *.orig --exclude *.spec --exclude=*Makefile.in --exclude=*.po* parted-1.4.7/libparted/sg_map.h parted-1.4.7-gpt/libparted/sg_map.h
--- parted-1.4.7/libparted/sg_map.h	Wed Dec 31 18:00:00 1969
+++ parted-1.4.7-gpt/libparted/sg_map.h	Thu Jan 18 11:24:42 2001
@@ -0,0 +1,33 @@
+ /*
+    libparted - a library for manipulating disk partitions
+    Copyright (C) 1998-2000 Free Software Foundation, Inc.
+
+    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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#define MAX_SG_DEVS 128
+
+
+struct _sg_to_sd {
+	char sg[16];
+	char sd[16];
+};
+
+
+extern struct _sg_to_sd sg_to_sd[MAX_SG_DEVS];
+extern int sg_to_sd_map_made;
+
+int make_sg_to_sd_map();
+

                 reply	other threads:[~2001-03-06 18:01 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=marc-linux-ia64-105590693005247@msgid-missing \
    --to=matt_domsch@dell.com \
    --cc=linux-ia64@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.