public inbox for linux-ia64@vger.kernel.org
 help / color / mirror / Atom feed
* [Linux-ia64] GPT patch for parted 1.4.7
@ 2001-03-06 18:01 Matt_Domsch
  0 siblings, 0 replies; only message in thread
From: Matt_Domsch @ 2001-03-06 18:01 UTC (permalink / raw)
  To: linux-ia64

[-- 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();
+

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2001-03-06 18:01 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-03-06 18:01 [Linux-ia64] GPT patch for parted 1.4.7 Matt_Domsch

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox