[PATCH 1/2] partx: complete rewrite

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Davidlohr Bueso <dave@xxxxxxx>

Enhancements:
	* Use libblkid
	* Usable for for both real devices and regular files (images)
	* Control output by PARTNO, START, LENGTH, SECTORS SIZE, NAME and/or UUID
	* Interpret partition tables the same way the kernel does, empty ones are ignored
	* Translate partition name to whole disks
	* Keep backwards compatibility

Signed-off-by: Davidlohr Bueso <dave@xxxxxxx>
---
 partx/Makefile.am |   15 +-
 partx/bsd.c       |   83 -----
 partx/crc32.c     |  393 -----------------------
 partx/crc32.h     |   19 --
 partx/dos.c       |  138 --------
 partx/dos.h       |   13 -
 partx/efi.h       |   57 ----
 partx/gpt.c       |  510 ------------------------------
 partx/gpt.h       |  131 --------
 partx/mac.c       |   74 -----
 partx/partx.8     |   40 ++-
 partx/partx.c     |  905 +++++++++++++++++++++++++++++++++--------------------
 partx/partx.h     |   32 --
 partx/solaris.c   |   69 ----
 partx/sun.c       |  130 --------
 partx/unixware.c  |   83 -----
 16 files changed, 619 insertions(+), 2073 deletions(-)
 delete mode 100644 partx/bsd.c
 delete mode 100644 partx/crc32.c
 delete mode 100644 partx/crc32.h
 delete mode 100644 partx/dos.c
 delete mode 100644 partx/dos.h
 delete mode 100644 partx/efi.h
 delete mode 100644 partx/gpt.c
 delete mode 100644 partx/gpt.h
 delete mode 100644 partx/mac.c
 delete mode 100644 partx/partx.h
 delete mode 100644 partx/solaris.c
 delete mode 100644 partx/sun.c
 delete mode 100644 partx/unixware.c

diff --git a/partx/Makefile.am b/partx/Makefile.am
index a26963e..eea8ee8 100644
--- a/partx/Makefile.am
+++ b/partx/Makefile.am
@@ -3,13 +3,24 @@ include $(top_srcdir)/config/include-Makefile.am
 if BUILD_PARTX
 
 usrsbin_exec_PROGRAMS = addpart delpart partx
-partx_SOURCES = bsd.c dos.c partx.c solaris.c unixware.c sun.c mac.c gpt.c crc32.c \
-		efi.h gpt.h crc32.h partx.h dos.h $(top_srcdir)/lib/blkdev.c
+partx_SOURCES = partx.c $(top_srcdir)/lib/blkdev.c $(top_srcdir)/lib/tt.c
 
 if LINUX
 partx_SOURCES += $(top_srcdir)/lib/linux_version.c
 endif
 
+cflags_blkid = $(AM_CFLAGS)
+ldadd_blkid =
+
+if BUILD_LIBBLKID
+# only in-tree libblkid has topology support
+ldadd_blkid += $(ul_libblkid_la)
+cflags_blkid += -I$(ul_libblkid_incdir)
+endif
+
+partx_CFLAGS = $(cflags_blkid)
+partx_LDADD = $(ldadd_blkid)
+
 dist_man_MANS = addpart.8 delpart.8 partx.8
 
 endif
diff --git a/partx/bsd.c b/partx/bsd.c
deleted file mode 100644
index 4532c32..0000000
--- a/partx/bsd.c
+++ /dev/null
@@ -1,83 +0,0 @@
-#include <stdio.h>
-#include "partx.h"
-
-#define BSD_DISKMAGIC	(0x82564557UL)	/* The disk magic number */
-#define XBSD_MAXPARTITIONS	16
-#define BSD_FS_UNUSED		0
-
-struct bsd_disklabel {
-	unsigned int	d_magic;	/* the magic number */
-	short int	d_type;		/* drive type */
-	short int	d_subtype;	/* controller/d_type specific */
-	char	d_typename[16];		/* type name, e.g. "eagle" */
-	char	d_packname[16];		/* pack identifier */ 
-	unsigned int	d_secsize;	/* # of bytes per sector */
-	unsigned int	d_nsectors;	/* # of data sectors per track */
-	unsigned int	d_ntracks;	/* # of tracks per cylinder */
-	unsigned int	d_ncylinders;	/* # of data cylinders per unit */
-	unsigned int	d_secpercyl;	/* # of data sectors per cylinder */
-	unsigned int	d_secperunit;	/* # of data sectors per unit */
-	unsigned short	d_sparespertrack;/* # of spare sectors per track */
-	unsigned short	d_sparespercyl;	/* # of spare sectors per cylinder */
-	unsigned int	d_acylinders;	/* # of alt. cylinders per unit */
-	unsigned short	d_rpm;		/* rotational speed */
-	unsigned short	d_interleave;	/* hardware sector interleave */
-	unsigned short	d_trackskew;	/* sector 0 skew, per track */
-	unsigned short	d_cylskew;	/* sector 0 skew, per cylinder */
-	unsigned int	d_headswitch;	/* head switch time, usec */
-	unsigned int	d_trkseek;	/* track-to-track seek, usec */
-	unsigned int	d_flags;	/* generic flags */
-	unsigned int	d_drivedata[5];	/* drive-type specific information */
-	unsigned int	d_spare[5];	/* reserved for future use */
-	unsigned int	d_magic2;	/* the magic number (again) */
-	unsigned short	d_checksum;	/* xor of data incl. partitions */
-
-			/* filesystem and partition information: */
-	unsigned short	d_npartitions;	/* number of partitions in following */
-	unsigned int	d_bbsize;	/* size of boot area at sn0, bytes */
-	unsigned int	d_sbsize;	/* max size of fs superblock, bytes */
-	struct	bsd_partition {		/* the partition table */
-		unsigned int	p_size;	  /* number of sectors in partition */
-		unsigned int	p_offset; /* starting sector */
-		unsigned int	p_fsize;  /* filesystem basic fragment size */
-		unsigned char	p_fstype; /* filesystem type, see below */
-		unsigned char	p_frag;	  /* filesystem fragments per block */
-		unsigned short	p_cpg;	  /* filesystem cylinders per group */
-	} d_partitions[XBSD_MAXPARTITIONS];/* actually may be more */
-};
-
-int
-read_bsd_pt(int fd, struct slice all, struct slice *sp, int ns) {
-	struct bsd_disklabel *l;
-	struct bsd_partition *p;
-	unsigned int offset = all.start;
-	int max_partitions;
-	unsigned char *bp;
-	int n = 0;
-
-	bp = getblock(fd, offset+1); 	/* 1 sector suffices */
-	if (bp == NULL)
-		return -1;
-
-	l = (struct bsd_disklabel *) bp;
-	if (l->d_magic != BSD_DISKMAGIC)
-		return -1;
-
-	max_partitions = 16;
-	if (l->d_npartitions < max_partitions)
-		max_partitions = l->d_npartitions;
-	for (p = l->d_partitions; p - l->d_partitions <  max_partitions; p++) {
-		if (p->p_fstype == BSD_FS_UNUSED)
-			/* nothing */;
-		else if (n < ns) {
-			sp[n].start = p->p_offset;
-			sp[n].size = p->p_size;
-			n++;
-		} else {
-			fprintf(stderr,
-				"bsd_partition: too many slices\n");
-			break;
-		}
-	}
-	return n;
-}
diff --git a/partx/crc32.c b/partx/crc32.c
deleted file mode 100644
index 4120f72..0000000
--- a/partx/crc32.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/* 
- * crc32.c
- * This code is in the public domain; copyright abandoned.
- * Liability for non-performance of this code is limited to the amount
- * you paid for it.  Since it is distributed for free, your refund will
- * be very very small.  If it breaks, you get to keep both pieces.
- */
-
-#include "crc32.h"
-
-#if __GNUC__ >= 3	/* 2.x has "attribute", but only 3.0 has "pure */
-#define attribute(x) __attribute__(x)
-#else
-#define attribute(x)
-#endif
-
-/*
- * There are multiple 16-bit CRC polynomials in common use, but this is
- * *the* standard CRC-32 polynomial, first popularized by Ethernet.
- * 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
- */
-#define CRCPOLY_LE 0xedb88320
-#define CRCPOLY_BE 0x04c11db7
-
-/* How many bits at a time to use.  Requires a table of 4<<CRC_xx_BITS bytes. */
-/* For less performance-sensitive, use 4 */
-#define CRC_LE_BITS 8
-#define CRC_BE_BITS 8
-
-/*
- * Little-endian CRC computation.  Used with serial bit streams sent
- * lsbit-first.  Be sure to use cpu_to_le32() to append the computed CRC.
- */
-#if CRC_LE_BITS > 8 || CRC_LE_BITS < 1 || CRC_LE_BITS & CRC_LE_BITS-1
-# error CRC_LE_BITS must be a power of 2 between 1 and 8
-#endif
-
-#if CRC_LE_BITS == 1
-/*
- * In fact, the table-based code will work in this case, but it can be
- * simplified by inlining the table in ?: form.
- */
-#define crc32init_le()
-#define crc32cleanup_le()
-/**
- * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32
- * @crc - seed value for computation.  ~0 for Ethernet, sometimes 0 for
- *        other uses, or the previous crc32 value if computing incrementally.
- * @p   - pointer to buffer over which CRC is run
- * @len - length of buffer @p
- * 
- */
-uint32_t attribute((pure)) crc32_le(uint32_t crc, unsigned char const *p, size_t len)
-{
-	int i;
-	while (len--) {
-		crc ^= *p++;
-		for (i = 0; i < 8; i++)
-			crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
-	}
-	return crc;
-}
-#else				/* Table-based approach */
-
-static uint32_t *crc32table_le;
-/**
- * crc32init_le() - allocate and initialize LE table data
- *
- * crc is the crc of the byte i; other entries are filled in based on the
- * fact that crctable[i^j] = crctable[i] ^ crctable[j].
- *
- */
-static int
-crc32init_le(void)
-{
-	unsigned i, j;
-	uint32_t crc = 1;
-
-	crc32table_le =
-		malloc((1 << CRC_LE_BITS) * sizeof(uint32_t));
-	if (!crc32table_le)
-		return 1;
-	crc32table_le[0] = 0;
-
-	for (i = 1 << (CRC_LE_BITS - 1); i; i >>= 1) {
-		crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
-		for (j = 0; j < 1 << CRC_LE_BITS; j += 2 * i)
-			crc32table_le[i + j] = crc ^ crc32table_le[j];
-	}
-	return 0;
-}
-
-/**
- * crc32cleanup_le(): free LE table data
- */
-static void
-crc32cleanup_le(void)
-{
-	free(crc32table_le);
-	crc32table_le = NULL;
-}
-
-/**
- * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32
- * @crc - seed value for computation.  ~0 for Ethernet, sometimes 0 for
- *        other uses, or the previous crc32 value if computing incrementally.
- * @p   - pointer to buffer over which CRC is run
- * @len - length of buffer @p
- * 
- */
-uint32_t attribute((pure)) crc32_le(uint32_t crc, unsigned char const *p, size_t len)
-{
-	while (len--) {
-# if CRC_LE_BITS == 8
-		crc = (crc >> 8) ^ crc32table_le[(crc ^ *p++) & 255];
-# elif CRC_LE_BITS == 4
-		crc ^= *p++;
-		crc = (crc >> 4) ^ crc32table_le[crc & 15];
-		crc = (crc >> 4) ^ crc32table_le[crc & 15];
-# elif CRC_LE_BITS == 2
-		crc ^= *p++;
-		crc = (crc >> 2) ^ crc32table_le[crc & 3];
-		crc = (crc >> 2) ^ crc32table_le[crc & 3];
-		crc = (crc >> 2) ^ crc32table_le[crc & 3];
-		crc = (crc >> 2) ^ crc32table_le[crc & 3];
-# endif
-	}
-	return crc;
-}
-#endif
-
-/*
- * Big-endian CRC computation.  Used with serial bit streams sent
- * msbit-first.  Be sure to use cpu_to_be32() to append the computed CRC.
- */
-#if CRC_BE_BITS > 8 || CRC_BE_BITS < 1 || CRC_BE_BITS & CRC_BE_BITS-1
-# error CRC_BE_BITS must be a power of 2 between 1 and 8
-#endif
-
-#if CRC_BE_BITS == 1
-/*
- * In fact, the table-based code will work in this case, but it can be
- * simplified by inlining the table in ?: form.
- */
-#define crc32init_be()
-#define crc32cleanup_be()
-
-/**
- * crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32
- * @crc - seed value for computation.  ~0 for Ethernet, sometimes 0 for
- *        other uses, or the previous crc32 value if computing incrementally.
- * @p   - pointer to buffer over which CRC is run
- * @len - length of buffer @p
- * 
- */
-uint32_t attribute((pure)) crc32_be(uint32_t crc, unsigned char const *p, size_t len)
-{
-	int i;
-	while (len--) {
-		crc ^= *p++ << 24;
-		for (i = 0; i < 8; i++)
-			crc =
-			    (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE :
-					  0);
-	}
-	return crc;
-}
-
-#else				/* Table-based approach */
-static uint32_t *crc32table_be;
-
-/**
- * crc32init_be() - allocate and initialize BE table data
- */
-static int
-crc32init_be(void)
-{
-	unsigned i, j;
-	uint32_t crc = 0x80000000;
-
-	crc32table_be =
-		malloc((1 << CRC_BE_BITS) * sizeof(uint32_t));
-	if (!crc32table_be)
-		return 1;
-	crc32table_be[0] = 0;
-
-	for (i = 1; i < 1 << CRC_BE_BITS; i <<= 1) {
-		crc = (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE : 0);
-		for (j = 0; j < i; j++)
-			crc32table_be[i + j] = crc ^ crc32table_be[j];
-	}
-	return 0;
-}
-
-/**
- * crc32cleanup_be(): free BE table data
- */
-static void
-crc32cleanup_be(void)
-{
-	free(crc32table_be);
-	crc32table_be = NULL;
-}
-
-
-/**
- * crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32
- * @crc - seed value for computation.  ~0 for Ethernet, sometimes 0 for
- *        other uses, or the previous crc32 value if computing incrementally.
- * @p   - pointer to buffer over which CRC is run
- * @len - length of buffer @p
- * 
- */
-uint32_t attribute((pure)) crc32_be(uint32_t crc, unsigned char const *p, size_t len)
-{
-	while (len--) {
-# if CRC_BE_BITS == 8
-		crc = (crc << 8) ^ crc32table_be[(crc >> 24) ^ *p++];
-# elif CRC_BE_BITS == 4
-		crc ^= *p++ << 24;
-		crc = (crc << 4) ^ crc32table_be[crc >> 28];
-		crc = (crc << 4) ^ crc32table_be[crc >> 28];
-# elif CRC_BE_BITS == 2
-		crc ^= *p++ << 24;
-		crc = (crc << 2) ^ crc32table_be[crc >> 30];
-		crc = (crc << 2) ^ crc32table_be[crc >> 30];
-		crc = (crc << 2) ^ crc32table_be[crc >> 30];
-		crc = (crc << 2) ^ crc32table_be[crc >> 30];
-# endif
-	}
-	return crc;
-}
-#endif
-
-/*
- * A brief CRC tutorial.
- *
- * A CRC is a long-division remainder.  You add the CRC to the message,
- * and the whole thing (message+CRC) is a multiple of the given
- * CRC polynomial.  To check the CRC, you can either check that the
- * CRC matches the recomputed value, *or* you can check that the
- * remainder computed on the message+CRC is 0.  This latter approach
- * is used by a lot of hardware implementations, and is why so many
- * protocols put the end-of-frame flag after the CRC.
- *
- * It's actually the same long division you learned in school, except that
- * - We're working in binary, so the digits are only 0 and 1, and
- * - When dividing polynomials, there are no carries.  Rather than add and
- *   subtract, we just xor.  Thus, we tend to get a bit sloppy about
- *   the difference between adding and subtracting.
- *
- * A 32-bit CRC polynomial is actually 33 bits long.  But since it's
- * 33 bits long, bit 32 is always going to be set, so usually the CRC
- * is written in hex with the most significant bit omitted.  (If you're
- * familiar with the IEEE 754 floating-point format, it's the same idea.)
- *
- * Note that a CRC is computed over a string of *bits*, so you have
- * to decide on the endianness of the bits within each byte.  To get
- * the best error-detecting properties, this should correspond to the
- * order they're actually sent.  For example, standard RS-232 serial is
- * little-endian; the most significant bit (sometimes used for parity)
- * is sent last.  And when appending a CRC word to a message, you should
- * do it in the right order, matching the endianness.
- *
- * Just like with ordinary division, the remainder is always smaller than
- * the divisor (the CRC polynomial) you're dividing by.  Each step of the
- * division, you take one more digit (bit) of the dividend and append it
- * to the current remainder.  Then you figure out the appropriate multiple
- * of the divisor to subtract to being the remainder back into range.
- * In binary, it's easy - it has to be either 0 or 1, and to make the
- * XOR cancel, it's just a copy of bit 32 of the remainder.
- *
- * When computing a CRC, we don't care about the quotient, so we can
- * throw the quotient bit away, but subtract the appropriate multiple of
- * the polynomial from the remainder and we're back to where we started,
- * ready to process the next bit.
- *
- * A big-endian CRC written this way would be coded like:
- * for (i = 0; i < input_bits; i++) {
- * 	multiple = remainder & 0x80000000 ? CRCPOLY : 0;
- * 	remainder = (remainder << 1 | next_input_bit()) ^ multiple;
- * }
- * Notice how, to get at bit 32 of the shifted remainder, we look
- * at bit 31 of the remainder *before* shifting it.
- *
- * But also notice how the next_input_bit() bits we're shifting into
- * the remainder don't actually affect any decision-making until
- * 32 bits later.  Thus, the first 32 cycles of this are pretty boring.
- * Also, to add the CRC to a message, we need a 32-bit-long hole for it at
- * the end, so we have to add 32 extra cycles shifting in zeros at the
- * end of every message,
- *
- * So the standard trick is to rearrage merging in the next_input_bit()
- * until the moment it's needed.  Then the first 32 cycles can be precomputed,
- * and merging in the final 32 zero bits to make room for the CRC can be
- * skipped entirely.
- * This changes the code to:
- * for (i = 0; i < input_bits; i++) {
- *      remainder ^= next_input_bit() << 31;
- * 	multiple = (remainder & 0x80000000) ? CRCPOLY : 0;
- * 	remainder = (remainder << 1) ^ multiple;
- * }
- * With this optimization, the little-endian code is simpler:
- * for (i = 0; i < input_bits; i++) {
- *      remainder ^= next_input_bit();
- * 	multiple = (remainder & 1) ? CRCPOLY : 0;
- * 	remainder = (remainder >> 1) ^ multiple;
- * }
- *
- * Note that the other details of endianness have been hidden in CRCPOLY
- * (which must be bit-reversed) and next_input_bit().
- *
- * However, as long as next_input_bit is returning the bits in a sensible
- * order, we can actually do the merging 8 or more bits at a time rather
- * than one bit at a time:
- * for (i = 0; i < input_bytes; i++) {
- * 	remainder ^= next_input_byte() << 24;
- * 	for (j = 0; j < 8; j++) {
- * 		multiple = (remainder & 0x80000000) ? CRCPOLY : 0;
- * 		remainder = (remainder << 1) ^ multiple;
- * 	}
- * }
- * Or in little-endian:
- * for (i = 0; i < input_bytes; i++) {
- * 	remainder ^= next_input_byte();
- * 	for (j = 0; j < 8; j++) {
- * 		multiple = (remainder & 1) ? CRCPOLY : 0;
- * 		remainder = (remainder << 1) ^ multiple;
- * 	}
- * }
- * If the input is a multiple of 32 bits, you can even XOR in a 32-bit
- * word at a time and increase the inner loop count to 32.
- *
- * You can also mix and match the two loop styles, for example doing the
- * bulk of a message byte-at-a-time and adding bit-at-a-time processing
- * for any fractional bytes at the end.
- *
- * The only remaining optimization is to the byte-at-a-time table method.
- * Here, rather than just shifting one bit of the remainder to decide
- * in the correct multiple to subtract, we can shift a byte at a time.
- * This produces a 40-bit (rather than a 33-bit) intermediate remainder,
- * but again the multiple of the polynomial to subtract depends only on
- * the high bits, the high 8 bits in this case.  
- *
- * The multile we need in that case is the low 32 bits of a 40-bit
- * value whose high 8 bits are given, and which is a multiple of the
- * generator polynomial.  This is simply the CRC-32 of the given
- * one-byte message.
- *
- * Two more details: normally, appending zero bits to a message which
- * is already a multiple of a polynomial produces a larger multiple of that
- * polynomial.  To enable a CRC to detect this condition, it's common to
- * invert the CRC before appending it.  This makes the remainder of the
- * message+crc come out not as zero, but some fixed non-zero value.
- *
- * The same problem applies to zero bits prepended to the message, and
- * a similar solution is used.  Instead of starting with a remainder of
- * 0, an initial remainder of all ones is used.  As long as you start
- * the same way on decoding, it doesn't make a difference.
- */
-
-
-/**
- * init_crc32(): generates CRC32 tables
- * 
- * On successful initialization, use count is increased.
- * This guarantees that the library functions will stay resident
- * in memory, and prevents someone from 'rmmod crc32' while
- * a driver that needs it is still loaded.
- * This also greatly simplifies drivers, as there's no need
- * to call an initialization/cleanup function from each driver.
- * Since crc32.o is a library module, there's no requirement
- * that the user can unload it.
- */
-int
-init_crc32(void)
-{
-	int rc1, rc2, rc;
-	rc1 = crc32init_le();
-	rc2 = crc32init_be();
-	rc = rc1 || rc2;
-	return rc;
-}
-
-/**
- * cleanup_crc32(): frees crc32 data when no longer needed
- */
-void
-cleanup_crc32(void)
-{
-	crc32cleanup_le();
-	crc32cleanup_be();
-}
diff --git a/partx/crc32.h b/partx/crc32.h
deleted file mode 100644
index a4505b8..0000000
--- a/partx/crc32.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * crc32.h
- */
-#ifndef _CRC32_H
-#define _CRC32_H
-
-#include <inttypes.h>
-#include <stdlib.h>
-
-extern int init_crc32(void);
-extern void cleanup_crc32(void);
-extern uint32_t  crc32_le(uint32_t crc, unsigned char const *p, size_t len);
-extern uint32_t  crc32_be(uint32_t crc, unsigned char const *p, size_t len);
-
-#define crc32(seed, data, length)  crc32_le(seed, (unsigned char const *)data, length)
-#define ether_crc_le(length, data) crc32_le(~0, data, length)
-#define ether_crc(length, data)    crc32_be(~0, data, length)
-
-#endif /* _CRC32_H */
diff --git a/partx/dos.c b/partx/dos.c
deleted file mode 100644
index f962f37..0000000
--- a/partx/dos.c
+++ /dev/null
@@ -1,138 +0,0 @@
-#include <stdio.h>
-
-#include "blkdev.h"
-
-#include "partx.h"
-#include "dos.h"
-
-static int
-is_extended(int type) {
-	return (type == 5 || type == 0xf || type == 0x85);
-}
-
-/* assemble badly aligned little endian integer */
-static inline unsigned int
-assemble4le(unsigned char *p) {
-	return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-}
-
-static inline unsigned int
-partition_start(struct partition *p) {
-	return assemble4le(&(p->start_sect[0]));
-}
-
-static inline unsigned int
-partition_size(struct partition *p) {
-	return assemble4le(&(p->nr_sects[0]));
-}
-
-static int
-read_extended_partition(int fd, struct partition *ep,
-			struct slice *sp, int ns, int ssf)
-{
-	struct partition *p;
-	unsigned long start, here;
-	unsigned char *bp;
-	int loopct = 0;
-	int moretodo = 1;
-	int i, n=0;
-
-	here = start = partition_start(ep);;
-
-	while (moretodo) {
-		moretodo = 0;
-		if (++loopct > 100)
-			return n;
-
-		bp = getblock(fd, here * ssf);	/* in 512 blocks */
-		if (bp == NULL)
-			return n;
-
-		if (bp[510] != 0x55 || bp[511] != 0xaa)
-			return n;
-
-		p = (struct partition *) (bp + 0x1be);
-
-		for (i=0; i<2; i++, p++) {
-			if (partition_size(p) == 0 || is_extended(p->sys_type))
-				continue;
-			if (n < ns) {
-				sp[n].start = (here + partition_start(p)) * ssf;
-				sp[n].size = partition_size(p) * ssf;
-				n++;
-			} else {
-				fprintf(stderr,
-				    "dos_extd_partition: too many slices\n");
-				return n;
-			}
-			loopct = 0;
-		}
-
-		p -= 2;
-		for (i=0; i<2; i++, p++) {
-			if (partition_size(p) != 0 &&
-			    is_extended(p->sys_type)) {
-				here = start + partition_start(p);
-				moretodo = 1;
-				break;
-			}
-		}
-	}
-	return n;
-}
-
-static int
-is_gpt(int type) {
-	return (type == 0xEE);
-}
-
-int
-read_dos_pt(int fd, struct slice all, struct slice *sp, int ns) {
-	struct partition *p;
-	unsigned long offset = all.start;
-	int i, n=0;
-	unsigned char *bp;
-	int ssf;
-
-	bp = getblock(fd, offset);
-	if (bp == NULL)
-		return -1;
-
-	if (bp[510] != 0x55 || bp[511] != 0xaa)
-		return -1;
-
-	/* msdos PT depends sector size... */
-	if (blkdev_get_sector_size(fd, &ssf) != 0)
-		ssf = DEFAULT_SECTOR_SIZE;
-
-	/* ... but partx counts everything in 512-byte sectors */
-	ssf /= 512;
-
-	p = (struct partition *) (bp + 0x1be);
-	for (i=0; i<4; i++) {
-		if (is_gpt(p->sys_type))
-			return 0;
-		p++;
-	}
-	p = (struct partition *) (bp + 0x1be);
-	for (i=0; i<4; i++) {
-		/* always add, even if zero length */
-		if (n < ns) {
-			sp[n].start = partition_start(p) * ssf;
-			sp[n].size = partition_size(p) * ssf;
-			n++;
-		} else {
-			fprintf(stderr,
-				"dos_partition: too many slices\n");
-			break;
-		}
-		p++;
-	}
-	p = (struct partition *) (bp + 0x1be);
-	for (i=0; i<4; i++) {
-		if (is_extended(p->sys_type))
-			n += read_extended_partition(fd, p, sp+n, ns-n, ssf);
-		p++;
-	}
-	return n;
-}
diff --git a/partx/dos.h b/partx/dos.h
deleted file mode 100644
index 877beec..0000000
--- a/partx/dos.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef DOS_H_INCLUDED
-#define DOS_H_INCLUDED
-
-struct partition {
-	unsigned char boot_ind;	/* 0x80 - active */
-	unsigned char bh, bs, bc;
-	unsigned char sys_type;
-	unsigned char eh, es, ec;
-	unsigned char start_sect[4];
-	unsigned char nr_sects[4];
-};
-
-#endif				/* DOS_H_INCLUDED */
diff --git a/partx/efi.h b/partx/efi.h
deleted file mode 100644
index fcf2740..0000000
--- a/partx/efi.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-  efi.[ch] - Manipulates EFI variables as exported in /proc/efi/vars
- 
-  Copyright (C) 2001 Dell Computer Corporation <Matt_Domsch@xxxxxxxx>
- 
-    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_H
-#define EFI_H
-
-/*
- * Extensible Firmware Interface
- * Based on 'Extensible Firmware Interface Specification'
- *      version 1.02, 12 December, 2000
- */
-#include <stdint.h>
-
-typedef struct {
-	uint8_t  b[16];
-} efi_guid_t;
-
-#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
-((efi_guid_t) \
-{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
-  (b) & 0xff, ((b) >> 8) & 0xff, \
-  (c) & 0xff, ((c) >> 8) & 0xff, \
-  (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }})
-
-
-/******************************************************
- * GUIDs
- ******************************************************/
-#define NULL_GUID \
-EFI_GUID( 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
-
-static inline int
-efi_guidcmp(efi_guid_t left, efi_guid_t right)
-{
-	return memcmp(&left, &right, sizeof (efi_guid_t));
-}
-
-typedef uint16_t efi_char16_t;		/* UNICODE character */
-
-#endif /* EFI_H */
diff --git a/partx/gpt.c b/partx/gpt.c
deleted file mode 100644
index be612fc..0000000
--- a/partx/gpt.c
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
-    gpt.[ch]
-
-    Copyright (C) 2000-2001 Dell Computer Corporation <Matt_Domsch@xxxxxxxx>
-
-    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
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "blkdev.h"
-#include "crc32.h"
-#include "gpt.h"
-#include "partx.h"
-#include "bitops.h"
-
-static inline uint32_t
-efi_crc32(const void *buf, unsigned long len)
-{
-	return (crc32(~0L, buf, len) ^ ~0L);
-}
-
-/**
- * is_pmbr_valid(): test Protective MBR for validity
- * @mbr: pointer to a legacy mbr structure
- *
- * Description: Returns 1 if PMBR is valid, 0 otherwise.
- * Validity depends on two things:
- *  1) MSDOS signature is in the last two bytes of the MBR
- *  2) One partition of type 0xEE is found
- */
-static int
-is_pmbr_valid(legacy_mbr *mbr)
-{
-	int i, found = 0, signature = 0;
-	if (!mbr)
-		return 0;
-	signature = (le16_to_cpu(mbr->signature) == MSDOS_MBR_SIGNATURE);
-	for (i = 0; signature && i < 4; i++) {
-		if (mbr->partition[i].sys_type ==
-                    EFI_PMBR_OSTYPE_EFI_GPT) {
-			found = 1;
-			break;
-		}
-	}
-	return (signature && found);
-}
-
-static int
-get_sector_size (int fd)
-{
-	int sector_size;
-
-	if (blkdev_get_sector_size(fd, &sector_size) == -1)
-		return DEFAULT_SECTOR_SIZE;
-	return sector_size;
-}
-
-static uint64_t
-get_num_sectors(int fd)
-{
-	unsigned long long bytes=0;
-
-	if (blkdev_get_size(fd, &bytes) == -1)
-		return 0;
-	return bytes / get_sector_size(fd);
-}
-
-static uint64_t
-last_lba(int filedes)
-{
-	int rc;
-	uint64_t sectors = 0;
-	struct stat s;
-	memset(&s, 0, sizeof (s));
-	rc = fstat(filedes, &s);
-	if (rc == -1) {
-		fprintf(stderr, "last_lba() could not stat: %s\n",
-			strerror(errno));
-		return 0;
-	}
-
-	if (S_ISBLK(s.st_mode)) {
-		sectors = get_num_sectors(filedes);
-	} else {
-		fprintf(stderr,
-			"last_lba(): I don't know how to handle files with mode %x\n",
-			s.st_mode);
-		sectors = 1;
-	}
-
-	return sectors - 1;
-}
-
-static ssize_t
-read_lba(int fd, uint64_t lba, void *buffer, size_t bytes)
-{
-	int sector_size = get_sector_size(fd);
-	off_t offset = lba * sector_size;
-
-	lseek(fd, offset, SEEK_SET);
-	return read(fd, buffer, bytes);
-}
-
-/**
- * alloc_read_gpt_entries(): reads partition entries from disk
- * @fd  is an open file descriptor to the whole disk
- * @gpt is a buffer into which the GPT will be put  
- * Description: Returns ptes on success,  NULL on error.
- * Allocates space for PTEs based on information found in @gpt.
- * Notes: remember to free pte when you're done!
- */
-static gpt_entry *
-alloc_read_gpt_entries(int fd, gpt_header * gpt)
-{
-	gpt_entry *pte;
-        size_t count = le32_to_cpu(gpt->num_partition_entries) *
-                le32_to_cpu(gpt->sizeof_partition_entry);
-
-        if (!count) return NULL;
-
-	pte = (gpt_entry *)malloc(count);
-	if (!pte)
-		return NULL;
-	memset(pte, 0, count);
-
-	if (!read_lba(fd, le64_to_cpu(gpt->partition_entry_lba), pte,
-                      count)) {
-		free(pte);
-		return NULL;
-	}
-	return pte;
-}
-
-/**
- * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
- * @fd  is an open file descriptor to the whole disk
- * @lba is the Logical Block Address of the partition table
- * 
- * Description: returns GPT header on success, NULL on error.   Allocates
- * and fills a GPT header starting at @ from @bdev.
- * Note: remember to free gpt when finished with it.
- */
-static gpt_header *
-alloc_read_gpt_header(int fd, uint64_t lba)
-{
-	gpt_header *gpt;
-	gpt = (gpt_header *)
-	    malloc(sizeof (gpt_header));
-	if (!gpt)
-		return NULL;
-	memset(gpt, 0, sizeof (*gpt));
-	if (!read_lba(fd, lba, gpt, sizeof (gpt_header))) {
-		free(gpt);
-		return NULL;
-	}
-
-	return gpt;
-}
-
-/**
- * is_gpt_valid() - tests one GPT header and PTEs for validity
- * @fd  is an open file descriptor to the whole disk
- * @lba is the logical block address of the GPT header to test
- * @gpt is a GPT header ptr, filled on return.
- * @ptes is a PTEs ptr, filled on return.
- *
- * Description: returns 1 if valid,  0 on error.
- * If valid, returns pointers to newly allocated GPT header and PTEs.
- */
-static int
-is_gpt_valid(int fd, uint64_t lba,
-             gpt_header ** gpt, gpt_entry ** ptes)
-{
-	int rc = 0;		/* default to not valid */
-	uint32_t crc, origcrc;
-
-	if (!gpt || !ptes)
-                return 0;
-	if (!(*gpt = alloc_read_gpt_header(fd, lba)))
-		return 0;
-
-	/* Check the GUID Partition Table signature */
-	if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
-		/* 
-		   printf("GUID Partition Table Header signature is wrong: %" PRIx64" != %" PRIx64 "\n",
-		   le64_to_cpu((*gpt)->signature), GUID_PT_HEADER_SIGNATURE);
-		 */
-		free(*gpt);
-		*gpt = NULL;
-		return rc;
-	}
-
-	/* Check the GUID Partition Table Header CRC */
-	origcrc = le32_to_cpu((*gpt)->header_crc32);
-	(*gpt)->header_crc32 = 0;
-	crc = efi_crc32(*gpt, le32_to_cpu((*gpt)->header_size));
-	if (crc != origcrc) {
-		/* printf( "GPTH CRC check failed, %x != %x.\n", origcrc, crc); */
-		(*gpt)->header_crc32 = cpu_to_le32(origcrc);
-		free(*gpt);
-		*gpt = NULL;
-		return 0;
-	}
-	(*gpt)->header_crc32 = cpu_to_le32(origcrc);
-
-	/* Check that the my_lba entry points to the LBA
-	 * that contains the GPT we read */
-	if (le64_to_cpu((*gpt)->my_lba) != lba) {
-		/* printf( "my_lba % PRIx64 "x != lba %"PRIx64 "x.\n", le64_to_cpu((*gpt)->my_lba), lba); */
-		free(*gpt);
-		*gpt = NULL;
-		return 0;
-	}
-
-	if (!(*ptes = alloc_read_gpt_entries(fd, *gpt))) {
-		free(*gpt);
-		*gpt = NULL;
-		return 0;
-	}
-
-	/* Check the GUID Partition Entry Array CRC */
-	crc = efi_crc32(*ptes,
-                        le32_to_cpu((*gpt)->num_partition_entries) *
-			le32_to_cpu((*gpt)->sizeof_partition_entry));
-	if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
-		/* printf("GUID Partitition Entry Array CRC check failed.\n"); */
-		free(*gpt);
-		*gpt = NULL;
-		free(*ptes);
-		*ptes = NULL;
-		return 0;
-	}
-
-	/* We're done, all's well */
-	return 1;
-}
-/**
- * compare_gpts() - Search disk for valid GPT headers and PTEs
- * @pgpt is the primary GPT header
- * @agpt is the alternate GPT header
- * @lastlba is the last LBA number
- * Description: Returns nothing.  Sanity checks pgpt and agpt fields
- * and prints warnings on discrepancies.
- *
- */
-static void
-compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba)
-{
-	int error_found = 0;
-	if (!pgpt || !agpt)
-		return;
-	if (le64_to_cpu(pgpt->my_lba) != le64_to_cpu(agpt->alternate_lba)) {
-		fprintf(stderr,
-		       "GPT:Primary header LBA != Alt. header alternate_lba\n");
-		fprintf(stderr,  "GPT:%" PRIx64 "x != %" PRIx64 "x\n",
-		       le64_to_cpu(pgpt->my_lba),
-		       le64_to_cpu(agpt->alternate_lba));
-		error_found++;
-	}
-	if (le64_to_cpu(pgpt->alternate_lba) != le64_to_cpu(agpt->my_lba)) {
-		fprintf(stderr,
-		       "GPT:Primary header alternate_lba != Alt. header my_lba\n");
-		fprintf(stderr,  "GPT:%" PRIx64 " != %" PRIx64 "\n",
-		       le64_to_cpu(pgpt->alternate_lba),
-		       le64_to_cpu(agpt->my_lba));
-		error_found++;
-	}
-	if (le64_to_cpu(pgpt->first_usable_lba) !=
-            le64_to_cpu(agpt->first_usable_lba)) {
-		fprintf(stderr,  "GPT:first_usable_lbas don't match.\n");
-		fprintf(stderr,  "GPT:%" PRIx64 " != %" PRIx64 "\n",
-		       le64_to_cpu(pgpt->first_usable_lba),
-		       le64_to_cpu(agpt->first_usable_lba));
-		error_found++;
-	}
-	if (le64_to_cpu(pgpt->last_usable_lba) !=
-            le64_to_cpu(agpt->last_usable_lba)) {
-		fprintf(stderr,  "GPT:last_usable_lbas don't match.\n");
-		fprintf(stderr,  "GPT:%" PRIx64 " != %" PRIx64 "\n",
-		       le64_to_cpu(pgpt->last_usable_lba),
-		       le64_to_cpu(agpt->last_usable_lba));
-		error_found++;
-	}
-	if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) {
-		fprintf(stderr,  "GPT:disk_guids don't match.\n");
-		error_found++;
-	}
-	if (le32_to_cpu(pgpt->num_partition_entries) !=
-            le32_to_cpu(agpt->num_partition_entries)) {
-		fprintf(stderr,  "GPT:num_partition_entries don't match: "
-		       "0x%x != 0x%x\n",
-		       le32_to_cpu(pgpt->num_partition_entries),
-		       le32_to_cpu(agpt->num_partition_entries));
-		error_found++;
-	}
-	if (le32_to_cpu(pgpt->sizeof_partition_entry) !=
-            le32_to_cpu(agpt->sizeof_partition_entry)) {
-		fprintf(stderr,
-		       "GPT:sizeof_partition_entry values don't match: "
-		       "0x%x != 0x%x\n",
-		       le32_to_cpu(pgpt->sizeof_partition_entry),
-		       le32_to_cpu(agpt->sizeof_partition_entry));
-		error_found++;
-	}
-	if (le32_to_cpu(pgpt->partition_entry_array_crc32) !=
-            le32_to_cpu(agpt->partition_entry_array_crc32)) {
-		fprintf(stderr,
-		       "GPT:partition_entry_array_crc32 values don't match: "
-		       "0x%x != 0x%x\n",
-		       le32_to_cpu(pgpt->partition_entry_array_crc32),
-		       le32_to_cpu(agpt->partition_entry_array_crc32));
-		error_found++;
-	}
-	if (le64_to_cpu(pgpt->alternate_lba) != lastlba) {
-		fprintf(stderr,
-		       "GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
-		fprintf(stderr,  "GPT:%" PRIx64 " != %" PRIx64 "\n",
-		       le64_to_cpu(pgpt->alternate_lba), lastlba);
-		error_found++;
-	}
-
-	if (le64_to_cpu(agpt->my_lba) != lastlba) {
-		fprintf(stderr,
-		       "GPT:Alternate GPT header not at the end of the disk.\n");
-		fprintf(stderr,  "GPT:%" PRIx64 " != %" PRIx64 "\n",
-		       le64_to_cpu(agpt->my_lba), lastlba);
-		error_found++;
-	}
-
-	if (error_found)
-		fprintf(stderr,
-		       "GPT: Use GNU Parted to correct GPT errors.\n");
-	return;
-}
-
-/**
- * find_valid_gpt() - Search disk for valid GPT headers and PTEs
- * @fd  is an open file descriptor to the whole disk
- * @gpt is a GPT header ptr, filled on return.
- * @ptes is a PTEs ptr, filled on return.
- * Description: Returns 1 if valid, 0 on error.
- * If valid, returns pointers to newly allocated GPT header and PTEs.
- * Validity depends on finding either the Primary GPT header and PTEs valid,
- * or the Alternate GPT header and PTEs valid, and the PMBR valid.
- */
-static int
-find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes)
-{
-        extern int force_gpt;
-	int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
-	gpt_header *pgpt = NULL, *agpt = NULL;
-	gpt_entry *pptes = NULL, *aptes = NULL;
-	legacy_mbr *legacymbr = NULL;
-	uint64_t lastlba;
-	if (!gpt || !ptes)
-		return 0;
-
-	lastlba = last_lba(fd);
-	good_pgpt = is_gpt_valid(fd, GPT_PRIMARY_PARTITION_TABLE_LBA,
-				 &pgpt, &pptes);
-        if (good_pgpt) {
-		good_agpt = is_gpt_valid(fd,
-                                         le64_to_cpu(pgpt->alternate_lba),
-					 &agpt, &aptes);
-                if (!good_agpt) {
-                        good_agpt = is_gpt_valid(fd, lastlba,
-                                                 &agpt, &aptes);
-                }
-        }
-        else {
-                good_agpt = is_gpt_valid(fd, lastlba,
-                                         &agpt, &aptes);
-        }
-
-        /* The obviously unsuccessful case */
-        if (!good_pgpt && !good_agpt) {
-                goto fail;
-        }
-
-	/* This will be added to the EFI Spec. per Intel after v1.02. */
-        legacymbr = malloc(sizeof (*legacymbr));
-        if (legacymbr) {
-                memset(legacymbr, 0, sizeof (*legacymbr));
-                read_lba(fd, 0, (uint8_t *) legacymbr,
-                         sizeof (*legacymbr));
-                good_pmbr = is_pmbr_valid(legacymbr);
-                free(legacymbr);
-                legacymbr=NULL;
-        }
-
-        /* Failure due to bad PMBR */
-        if ((good_pgpt || good_agpt) && !good_pmbr && !force_gpt) {
-                fprintf(stderr,
-                       "  Warning: Disk has a valid GPT signature "
-                       "but invalid PMBR.\n"
-                       "  Assuming this disk is *not* a GPT disk anymore.\n"
-                       "  Use gpt kernel option to override.  "
-                       "Use GNU Parted to correct disk.\n");
-                goto fail;
-        }
-
-        /* Would fail due to bad PMBR, but force GPT anyhow */
-        if ((good_pgpt || good_agpt) && !good_pmbr && force_gpt) {
-                fprintf(stderr, 
-                       "  Warning: Disk has a valid GPT signature but "
-                       "invalid PMBR.\n"
-                       "  Use GNU Parted to correct disk.\n"
-                       "  gpt option taken, disk treated as GPT.\n");
-        }
-
-        compare_gpts(pgpt, agpt, lastlba);
-
-        /* The good cases */
-        if (good_pgpt && (good_pmbr || force_gpt)) {
-                *gpt  = pgpt;
-                *ptes = pptes;
-                if (agpt)  { free(agpt);   agpt = NULL; }
-                if (aptes) { free(aptes); aptes = NULL; }
-                if (!good_agpt) {
-                        fprintf(stderr, 
-			       "Alternate GPT is invalid, "
-                               "using primary GPT.\n");
-                }
-                return 1;
-        }
-        else if (good_agpt && (good_pmbr || force_gpt)) {
-                *gpt  = agpt;
-                *ptes = aptes;
-                if (pgpt)  { free(pgpt);   pgpt = NULL; }
-                if (pptes) { free(pptes); pptes = NULL; }
-                fprintf(stderr, 
-                       "Primary GPT is invalid, using alternate GPT.\n");
-                return 1;
-        }
-
- fail:
-        if (pgpt)  { free(pgpt);   pgpt=NULL; }
-        if (agpt)  { free(agpt);   agpt=NULL; }
-        if (pptes) { free(pptes); pptes=NULL; }
-        if (aptes) { free(aptes); aptes=NULL; }
-        *gpt = NULL;
-        *ptes = NULL;
-        return 0;
-}
-
-/**
- * read_gpt_pt() 
- * @fd
- * @all - slice with start/size of whole disk
- *
- *  0 if this isn't our partition table
- *  number of partitions if successful
- *
- */
-int
-read_gpt_pt (int fd, struct slice all, struct slice *sp, int ns)
-{
-	gpt_header *gpt = NULL;
-	gpt_entry *ptes = NULL;
-	uint32_t i;
-	int n = 0;
-        int last_used_index=-1;
-
-	if (!find_valid_gpt (fd, &gpt, &ptes) || !gpt || !ptes) {
-		free (gpt);
-		free (ptes);
-		return 0;
-	}
-
-	for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < ns; i++) {
-		if (!efi_guidcmp (NULL_GUID, ptes[i].partition_type_guid)) {
-			sp[n].start = 0;
-			sp[n].size = 0;
-			n++;
-		} else {
-			sp[n].start = le64_to_cpu(ptes[i].starting_lba);
-			sp[n].size  = le64_to_cpu(ptes[i].ending_lba) -
-				le64_to_cpu(ptes[i].starting_lba) + 1;
-                        last_used_index=n;
-			n++;
-		}
-	}
-	free (ptes);
-	free (gpt);
-	return last_used_index+1;
-}
diff --git a/partx/gpt.h b/partx/gpt.h
deleted file mode 100644
index 39814b5..0000000
--- a/partx/gpt.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
-    gpt.[ch]
-
-    Copyright (C) 2000-2001 Dell Computer Corporation <Matt_Domsch@xxxxxxxx> 
-
-    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 _GPT_H
-#define _GPT_H
-
-
-#include <inttypes.h>
-#include "partx.h"
-#include "dos.h"
-#include "efi.h"
-
-#define EFI_PMBR_OSTYPE_EFI 0xEF
-#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE
-#define MSDOS_MBR_SIGNATURE 0xaa55
-#define GPT_BLOCK_SIZE 512
-
-#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL
-#define GPT_HEADER_REVISION_V1_02 0x00010200
-#define GPT_HEADER_REVISION_V1_00 0x00010000
-#define GPT_HEADER_REVISION_V0_99 0x00009900
-#define GPT_PRIMARY_PARTITION_TABLE_LBA 1
-
-typedef struct _gpt_header {
-	uint64_t signature;
-	uint32_t revision;
-	uint32_t header_size;
-	uint32_t header_crc32;
-	uint32_t reserved1;
-	uint64_t my_lba;
-	uint64_t alternate_lba;
-	uint64_t first_usable_lba;
-	uint64_t last_usable_lba;
-	efi_guid_t disk_guid;
-	uint64_t partition_entry_lba;
-	uint32_t num_partition_entries;
-	uint32_t sizeof_partition_entry;
-	uint32_t partition_entry_array_crc32;
-	uint8_t reserved2[GPT_BLOCK_SIZE - 92];
-} __attribute__ ((packed)) gpt_header;
-
-typedef struct _gpt_entry_attributes {
-	uint64_t required_to_function:1;
-	uint64_t reserved:47;
-        uint64_t type_guid_specific:16;
-} __attribute__ ((packed)) gpt_entry_attributes;
-
-typedef struct _gpt_entry {
-	efi_guid_t partition_type_guid;
-	efi_guid_t unique_partition_guid;
-	uint64_t starting_lba;
-	uint64_t ending_lba;
-	gpt_entry_attributes attributes;
-	efi_char16_t partition_name[72 / sizeof(efi_char16_t)];
-} __attribute__ ((packed)) gpt_entry;
-
-
-/* 
-   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(gpt_entry))
-
-
-/* Protected Master Boot Record  & Legacy MBR share same structure */
-/* Needs to be packed because the u16s force misalignment. */
-
-typedef struct _legacy_mbr {
-	uint8_t bootcode[440];
-	uint32_t unique_mbr_signature;
-	uint16_t unknown;
-	struct partition partition[4];
-	uint16_t signature;
-} __attribute__ ((packed)) legacy_mbr;
-
-
-#define EFI_GPT_PRIMARY_PARTITION_TABLE_LBA 1
-
-/* Functions */
-int read_gpt_pt (int fd, struct slice all, struct slice *sp, int ns);
-
-
-#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 --git a/partx/mac.c b/partx/mac.c
deleted file mode 100644
index a5677f0..0000000
--- a/partx/mac.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Lifted from kpartx's mac.c
- *
- * Integrated to partx (utils-linux-ng)
- *       Davidlohr Bueso <dave@xxxxxxx>
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-
-#include "bitops.h"
-#include "partx.h"
-
-#define MAC_PARTITION_MAGIC     0x504d
-#define MAC_DRIVER_MAGIC        0x4552
-
-struct mac_partition {
-        uint16_t  signature;      /* expected to be MAC_PARTITION_MAGIC */
-        uint16_t  res1;
-        uint32_t  map_count;      /* # blocks in partition map */
-        uint32_t  start_block;    /* absolute starting block # of partition */
-        uint32_t  block_count;    /* number of blocks in partition */
-        /* there is more stuff after this that we don't need */
-};
-
-/* Driver descriptor structure, in block 0 */
-struct mac_driver_desc {
-        uint16_t  signature;      /* expected to be MAC_DRIVER_MAGIC */
-        uint16_t  block_size;
-        uint32_t  block_count;
-};
-
-int
-read_mac_pt(int fd, struct slice all, struct slice *sp, int ns) {
-	struct mac_driver_desc *md;
-        struct mac_partition *part;
-	unsigned secsize;
-	unsigned char *data;
-	int blk, blocks_in_map;
-        int n = 0;
-
-	md = (struct mac_driver_desc *) getblock(fd, 0);
-	if (md == NULL)
-		return -1;
-
-	if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC)
-		return -1;
-
-	secsize = be16_to_cpu(md->block_size);
-	data = getblock(fd, secsize/512);
-	if (!data)
-		return -1;
-	part = (struct mac_partition *) (data + secsize%512);
-
-	if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
-		return -1;
-
-	blocks_in_map = be32_to_cpu(part->map_count);
-	for (blk = 1; blk <= blocks_in_map && blk <= ns; ++blk, ++n) {
-		int pos = blk * secsize;
-		data = getblock(fd, pos/512);
-		if (!data)
-			return -1;
-
-		part = (struct mac_partition *) (data + pos%512);
-		if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
-			break;
-
-		sp[n].start = be32_to_cpu(part->start_block) * (secsize/512);
-		sp[n].size = be32_to_cpu(part->block_count) * (secsize/512);
-	}
-	return n;
-}
diff --git a/partx/partx.8 b/partx/partx.8
index c6d04c8..41270b7 100644
--- a/partx/partx.8
+++ b/partx/partx.8
@@ -1,11 +1,12 @@
 .\" partx.8 --
 .\" Copyright 2007 Karel Zak <kzak@xxxxxxxxxx>
 .\" Copyright 2007 Red Hat, Inc.
+.\" Copyright 2010 Davidlohr Bueso <dave@xxxxxxx>
 .\" May be distributed under the GNU General Public License
-.TH PARTX 8 "11 Jan 2007"
+.TH PARTX 8 "28 Oct 2010"
 .SH NAME
 partx \-
-telling the kernel about presence and numbering of on-disk partitions.
+tell the linux kernel about presence and numbering of on-disk partitions.
 .SH SYNOPSIS
 .B partx
 .RB [ \-a | \-d | \-l ]
@@ -15,12 +16,19 @@ telling the kernel about presence and numbering of on-disk partitions.
 .IR M-N ]
 .RI [ partition ]
 .I disk
+
+.B partx
+.RB [ \-a | \-d | \-l ]
+.RB [ \-\-type
+.IR TYPE ]
+.RB [ \-\-nr
+.IR M-N ]
+.RI partition
+.I [disk]
+
 .SH DESCRIPTION
-Given a block device (
-.B disk
-) and a partition table
-.B type
-, try to parse the partition table, and list the
+Given a device (partition and/or disk) or disk-image,
+try to parse the partition table, and list the
 contents. Optionally add or remove partitions.
 
 This is not an fdisk - adding and removing partitions
@@ -38,12 +46,27 @@ delete specified or all partitions
 .B \-l
 list partitions. Note that the all numbers are in 512-byte sectors.
 .TP
+.B \-s
+list partitions in a new format, adding name and UUID (if applicable). All numbers are in 512-byte sectors.
+.TP
 .BI --type " TYPE"
 Specify the partition type -- dos, bsd, solaris, unixware or gpt.
 .TP
 .BI --nr " M-N"
 Specify the range of partitions (e.g --nr 2-4).
 
+.SH EXAMPLES
+.IP "\fBpartx \-\-list /dev/sdb3\fP"
+List partition 3 of /dev/sdb
+.IP "\fBpartx \-\-list /dev/sda\fP"
+Lists all partitions on /dev/sda
+.IP "\fBpartx \-\-list \-o LENGTH,SIZE /dev/sda5 /dev/sda\fP"
+List the length and size of partition 5 on /dev/sda
+.IP "\fBpartx \-\-add --nr 3-5 /dev/sdd\fP"
+Adds all available partitions from 3 to 5 (inclusive) on /dev/sdd
+.IP "\fBpartx \-d /dev/sdd\fP"
+Removes all available partitions on /dev/sdd
+
 .SH SEE ALSO
 .BR addpart (8),
 .BR delpart (8),
@@ -51,6 +74,9 @@ Specify the range of partitions (e.g --nr 2-4).
 .BR parted (8),
 .BR partprobe (8)
 
+.SH SEE ALSO
+The partx command was completely rewritten by Davidlohr Bueso <dave@xxxxxxx>
+
 .SH AVAILABILITY
 The partx command is part of the util-linux-ng package and is available from
 ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/partx/partx.c b/partx/partx.c
index aa5a2ad..f7e9387 100644
--- a/partx/partx.c
+++ b/partx/partx.c
@@ -1,404 +1,645 @@
 /*
- * Given a block device and a partition table type,
- * try to parse the partition table, and list the
- * contents. Optionally add or remove partitions.
- *
+ * partx: tell the kernel about your disk's partitions
  * [This is not an fdisk - adding and removing partitions
  * is not a change of the disk, but just telling the kernel
  * about presence and numbering of on-disk partitions.]
  *
- * Call:
- *	partx [-{l|a|d}] [--type TYPE] [--nr M-N] [partition] wholedisk
- * where TYPE is {dos|bsd|solaris|unixware|gpt}.
- *
- * Read wholedisk and add all partitions:
- *	partx -a wholedisk
- *
- * Subdivide a partition into slices (and delete or shrink the partition):
- * [Not easy: one needs the partition number of partition -
- *  that is the last 4 or 6 bits of the minor; it can also be found
- *  in /proc/partitions; but there is no good direct way.]
- *	partx -a partition wholedisk
- *
- * Delete all partitions from wholedisk:
- *	partx -d wholedisk
- *
- * Delete partitions M-N from wholedisk:
- *	partx -d --nr M-N wholedisk
- *
  * aeb, 2000-03-21 -- sah is 42 now
+ *
+ * Copyright (C) 2010 Davidlohr Bueso <dave@xxxxxxx>
+ *      Rewritten to use libblkid for util-linux-ng
+ *      based on ideas from Karel Zak <kzak@xxxxxxxxxx>
  */
 
 #include <stdio.h>
 #include <fcntl.h>
+#include <err.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 #include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <unistd.h>
+#include <assert.h>
 #include <sys/ioctl.h>
-#include <linux/hdreg.h>        /* HDIO_GETGEO */
+#include <linux/blkpg.h>
 #ifdef HAVE_LINUX_COMPILER_H
 #include <linux/compiler.h>
 #endif
-#include <linux/blkpg.h>
 
-#include "c.h"
+#include <blkid.h>
+
+#include "nls.h"
+#include "tt.h"
 #include "blkdev.h"
 
-#include "partx.h"
-#include "crc32.h"
-static void errmerge(int err, int m, char *msg1, char *msg2);
+#define noret __attribute__((__noreturn__))
+
+/* all units in byte sectors */
+#define BSECTORS  512
+
+/* all the columns (-o option) */
+enum {
+	COL_PARTNO,
+	COL_START,
+	COL_LENGTH,
+	COL_SECTORS,
+	COL_SIZE,
+	COL_NAME,
+	COL_UUID,
+	__NCOLUMNS
+};
+
+enum {
+	OLDFMT,
+	NEWFMT,
+};
+
+/* column names */
+struct colinfo {
+	const char *name;
+	double whint;
+	int truncate;
+};
+
+/* columns descriptions */
+struct colinfo infos[__NCOLUMNS] = {
+	[COL_PARTNO]   = { "PART",    0.25, 1 },
+	[COL_START]    = { "START",   0.30, 1 },
+	[COL_LENGTH]   = { "LENGTH",  0.30, 1 },
+	[COL_SECTORS]  = { "SECTORS", 0.30, 1 },
+	[COL_SIZE]     = { "SIZE",    0.30, 1 },
+	[COL_NAME]     = { "NAME",    0.30, 1 },
+	[COL_UUID]     = { "UUID",    0.30, 1 },
+};
+/* array with IDs of enabled columns */
+static int columns[__NCOLUMNS], ncolumns = 0;
+
+/* when passed --nr N-M, lower=N, upper=M */
+static int lower, upper;
+
+/*
+ * determine the listing format to be used
+ * mainly to maintain backwards compatibility
+*/
+int outfmt;
+
+/*
+ * used if only the partition is passed
+ *  ie: partx /dev/sda1 (partnumber=1)
+ *      partx /dev/sdd4 /dev/sdd (partnumber=4)
+ */
+static int partnumber = -1;
 
-#define MAXTYPES	64
-#define MAXSLICES	256
+static int verbose = 0;
 
-struct slice slices[MAXSLICES];
+static int get_column_id(int num)
+{
+	assert(num < ncolumns);
+	assert(columns[num] < __NCOLUMNS);
+	return columns[num];
+}
+
+static struct colinfo *get_column_info(int num)
+{
+	return &infos[ get_column_id(num) ];
+}
+
+static const char *get_column_name(int num)
+{
+	return get_column_info(num)->name;
+}
 
-enum action { LIST, ADD, DELETE };
+static float get_column_whint(int num)
+{
+	return get_column_info(num)->whint;
+}
 
-struct pt {
-	char *type;
-	ptreader *fn;
-} pts[MAXTYPES];
-int ptct;
+static const char *column_id_to_name(int id)
+{
+	assert(id < __NCOLUMNS);
+	return infos[id].name;
+}
 
-static void
-addpts(char *t, ptreader f)
+/*
+ * converts @name to column ID
+ */
+static int column_name_to_id(const char *name, size_t namesz)
 {
-	if (ptct >= MAXTYPES) {
-		fprintf(stderr, "addpts: too many types\n");
-		exit(1);
+	int i;
+
+	for (i = 0; i < __NCOLUMNS; i++) {
+		const char *cn = column_id_to_name(i);
+
+		if (!strncasecmp(name, cn, namesz) && !*(cn + namesz))
+			return i;
 	}
-	pts[ptct].type = t;
-	pts[ptct].fn = f;
-	ptct++;
+	warnx(_("unknown column: %s"), name);
+	return -1;
 }
 
-static void
-initpts(void)
+/*
+ * parses list of columns from @str and add IDs to columns[]
+ */
+static int set_columns(const char *str)
 {
-	addpts("gpt", read_gpt_pt);
-	addpts("dos", read_dos_pt);
-	addpts("bsd", read_bsd_pt);
-	addpts("solaris", read_solaris_pt);
-	addpts("unixware", read_unixware_pt);
-	addpts("sun", read_sun_pt);
-	addpts("mac", read_mac_pt);
+	const char *begin = NULL, *p;
+
+	ncolumns = 0;
+
+	if (!str || !*str)
+		return -1;
+
+	ncolumns = 0;
+
+	for (p = str; p && *p; p++) {
+		const char *end = NULL;
+		int id;
+
+		if (!begin)
+			begin = p;		/* begin of the column name */
+		if (*p == ',')
+			end = p;		/* terminate the name */
+		if (*(p + 1) == '\0')
+			end = p + 1;		/* end of string */
+		if (!begin || !end)
+			continue;
+		if (end <= begin)
+			return -1;
+
+		id = column_name_to_id(begin, end - begin);
+		if (id == -1)
+			return -1;
+		columns[ncolumns++] = id;
+		begin = NULL;
+		if (end && !*end)
+			break;
+	}
+	return 0;
 }
 
-static char short_opts[] = "ladgvn:t:";
-static const struct option long_opts[] = {
-	{ "gpt",	no_argument,	        NULL,	'g' },
-	{ "type",	required_argument,	NULL,	't' },
-	{ "nr",		required_argument,	NULL,	'n' },
-	{ NULL, 0, NULL, 0 }
-};
 
-/* Used in gpt.c */
-int force_gpt=0;
-
-int
-main(int argc, char **argv){
-        int fd, fd2, c, i, j, k, n;
-	unsigned long long size;
-	struct hd_geometry g;
-	struct slice all;
-        struct blkpg_ioctl_arg a;
-        struct blkpg_partition pt;
-	struct pt *ptp;
-	enum action what = LIST;
-	char *p, *type, *diskdevice, *device;
-	int lower, upper;
-	int verbose = 0;
-	int ret = 0;
-
-	initpts();
-	init_crc32();
+static int noret errx_mutually_exclusive(const char *opts)
+{
+	errx(EXIT_FAILURE, "%s %s", opts, _("options are mutually exclusive"));
+}
 
-	lower = upper = 0;
-	type = device = diskdevice = NULL;
-
-	while ((c = getopt_long (argc, argv, short_opts, long_opts, NULL))
-	        != -1) switch(c) {
-	case 'l':
-		what = LIST; break;
-	case 'a':
-		what = ADD; break;
-	case 'd':
-		what = DELETE; break;
-	case 'g':
-		force_gpt = 1; break;
-	case 'n':
-		p = optarg;
-		lower = atoi(p);
-		p = strchr(p, '-');
-		if (p)
-			upper = atoi(p+1);
-		else
-			upper = lower;
-		break;
-	case 't':
-		type = optarg;
-		break;
-	case 'v':
-		verbose = 1;
-		break;
-	case '?':
-	default:
-		fprintf(stderr, "unknown option\n");
-		exit(1);
+/*
+ * given a partition return the corresponding partition number. Returns -1 on error.
+ * Note that this function assumes that the last characters are
+ * always numeric (sda1, sdc20, etc).
+ */
+static int get_partno_from_device(char *partition)
+{
+	int num = -1, i=0, j=0;
+	char *str = malloc(sizeof(char) * strlen(partition));
+
+	if (!isdigit(partition[strlen(partition) - 1])) {
+		free(str);
+		return num;
 	}
 
-	if (optind == argc-2) {
-		device = argv[optind];
-		diskdevice = argv[optind+1];
-	} else if (optind == argc-1) {
-		diskdevice = device = argv[optind];
-	} else {
-		fprintf(stderr, "call: partx -opts [device] wholedisk\n");
-		exit(1);
+	for (i = 0; partition[i] != '\0'; i++) {
+		if (!isdigit(partition[i]))
+			continue;
+		else
+			str[j++] = partition[i];
 	}
 
-	fd = open(diskdevice, O_RDONLY);
-	if (fd == -1) {
-		perror(diskdevice);
-		exit(1);
+	num = strtol(str, (char **) NULL, 10);
+
+	free(str);
+	return num;
+}
+
+static char *show_errhelper(void)
+{
+	/*
+	 * append more useful information
+	 * as to why the error occured
+	 */
+	switch (errno) {
+	case EBUSY:
+		return "(mounted partition?)";
+	case ENXIO:
+		return "(no such non-empty partition)";
+	case EACCES:
+	case EPERM:
+		return "(permission denied)";
+	default:
+		return NULL;
 	}
+}
 
-	/* remove the indicated partitions from the kernel partition tables */
-	if (what == DELETE) {
-		if (device != diskdevice) {
-			fprintf(stderr,
-				"call: partx -d [--nr M-N] wholedisk\n");
-			exit(1);
-		}
+static void do_add(int fd, int partno, unsigned long start, unsigned long size)
+{
+	struct blkpg_ioctl_arg a;
+	struct blkpg_partition pt;
+
+	pt.pno = partno;
+	pt.start = BSECTORS * start;
+	pt.length = BSECTORS * size;
+	pt.devname[0] = pt.volname[0] = 0;
+	a.op = BLKPG_ADD_PARTITION;
+	a.flags = 0;
+	a.datalen = sizeof(pt);
+	a.data = &pt;
+
+	if (ioctl(fd, BLKPG, &a) == -1)
+		fprintf(stderr, "error adding partition #%d %s\n",
+			partno, show_errhelper());
+	else if (verbose)
+		printf("added partition #%d\n", partno);
+}
 
-		if (!lower)
-			lower = 1;
-
-		while (upper == 0 || lower <= upper) {
-			int err;
-
-			if (lower > MAXSLICES)
-				break;
-			pt.pno = lower;
-			pt.start = 0;
-			pt.length = 0;
-			pt.devname[0] = 0;
-			pt.volname[0] = 0;
-			a.op = BLKPG_DEL_PARTITION;
-			a.flags = 0;
-			a.datalen = sizeof(pt);
-			a.data = &pt;
-			if (ioctl(fd, BLKPG, &a) == -1)
-			    err = errno;
-			else
-			    err = 0;
-			errmerge(err, lower,
-				 "error deleting partition %d: ",
-				 "error deleting partitions %d-%d: ");
-			/* expected errors:
-			   EBUSY: mounted or in use as swap
-			   ENXIO: no such nonempty partition
-			   EINVAL: not wholedisk, or bad pno
-			   EACCES/EPERM: permission denied
-			*/
-			if (err && err != EBUSY && err != ENXIO) {
-				ret = 1;
-				break;
+static void add_part(int fd, blkid_partlist ls)
+{
+
+	int i, j, nparts;
+
+	nparts = blkid_partlist_numof_partitions(ls);
+	if (!nparts)
+		return;
+
+	for (i = 0; i < nparts; i++) {
+		blkid_partition par = blkid_partlist_get_partition(ls, i);
+		unsigned long long start = blkid_partition_get_start(par);
+		unsigned long long size =  blkid_partition_get_size(par);
+		int partno = blkid_partition_get_partno(par);
+
+		/* skip unwanted partition numbers, if any */
+		if (lower && upper)
+			if (partno < lower || partno > upper)
+				continue;
+		if (partnumber != -1)
+			if (partnumber != partno)
+				continue;
+
+		/*
+		 * test for overlap, as in the case of an
+		 * extended partition, and reduce size
+		 */
+		for (j=i+1; j <= nparts; j++) {
+			blkid_partition par2 = blkid_partlist_get_partition(ls, j);
+			unsigned long long start2 = blkid_partition_get_start(par2);
+
+			if (start2 > start && start2 < start + size) {
+				size = start2 - start;
+				if (verbose)
+					printf("reduced size of partition #%d to %llu\n", 
+					       partno, size);
 			}
-			if (err == 0 && verbose)
-				printf("deleted partition %d\n", lower);
-			lower++;
 		}
-		errmerge(0, 0,
-			 "error deleting partition %d: ",
-			 "error deleting partitions %d-%d: ");
-		return ret;
+
+		do_add(fd, partno, start, size);
 	}
+}
 
-	if (device != diskdevice) {
-		fd2 = open(device, O_RDONLY);
-		if (fd2 == -1) {
-			perror(device);
-			exit(1);
-		}
-	} else {
-		fd2 = fd;
+static void del_part(int fd, blkid_partlist ls)
+{
+	struct blkpg_ioctl_arg a;
+	struct blkpg_partition pt;
+	int i, nparts = blkid_partlist_numof_partitions(ls);
+	if (!nparts)
+		return;
+
+	for (i = 0; i < nparts; i++) {
+		blkid_partition par = blkid_partlist_get_partition(ls, i);
+		unsigned long long start = blkid_partition_get_start(par);
+		unsigned long long size =  blkid_partition_get_size(par);
+		int partno = blkid_partition_get_partno(par);
+
+		/* skip unwanted partition numbers, if any */
+		if (lower && upper)
+			if (partno < lower || partno > upper)
+				continue;
+		if (partnumber != -1)
+			if (partnumber != partno)
+				continue;
+
+		pt.pno = partno;
+		pt.start = start;
+		pt.length = start + size - 1;
+		pt.devname[0] = pt.volname[0] = 0;
+		a.op = BLKPG_DEL_PARTITION;
+		a.flags = 0;
+		a.datalen = sizeof(pt);
+		a.data = &pt;
+
+		if (ioctl(fd, BLKPG, &a) == -1)
+			fprintf(stderr, "error deleting #partition %d - %s\n",
+				partno, show_errhelper());
+		else if (verbose)
+			printf("deleted partition #%d\n", partno);
 	}
+}
+
+/* format data and add it as a whole column, for later printing the table */
+static void add_line(struct tt *tt, int partno, unsigned long long start,
+		     unsigned long long size, const char *name, const char *uuid)
+{
+	int i, rc = -1;
+	char *str = NULL;
 
-	if (ioctl(fd, HDIO_GETGEO, &g)) {
-		perror("HDIO_GETGEO");
-		exit(1);
+	struct tt_line *line = tt_add_line(tt, NULL);
+	if (!line) {
+		warn(_("failed to add line to output"));
+		return;
 	}
-	if (g.start != 0) {
-		fprintf(stderr, "last arg is not the whole disk\n");
-		fprintf(stderr, "call: partx -opts device wholedisk\n");
-		exit(1);
+
+	for (i = 0; i < ncolumns; i++) {
+		switch (get_column_id(i)) {
+		case COL_PARTNO:
+			rc = asprintf(&str, "#%2d", partno);
+			break;
+		case COL_START:
+			rc = asprintf(&str, "%llu", start);
+			break;
+		case COL_LENGTH:
+			rc = asprintf(&str, "%llu", start + size - 1);
+			break;
+		case COL_SECTORS:
+			rc = asprintf(&str, "%llu", size);
+			break;
+		case COL_SIZE:
+			rc = asprintf(&str, "%6llu MB",
+				      (BSECTORS * size) / 1000000);
+			break;
+		case COL_NAME:
+			str = (char *) name;
+			break;
+		case COL_UUID:
+			str = (char *) uuid;
+			break;
+		default:
+			break;
+		}
+
+		(!rc || !str ) ?
+			/* something weired just happened */
+			tt_line_set_data(line, i, "-") :
+			tt_line_set_data(line, i, str);
 	}
+}
 
-	if (ioctl(fd2, HDIO_GETGEO, &g)) {
-		perror("HDIO_GETGEO");
-		exit(1);
+static void show_part(blkid_partlist ls)
+{
+	int i, tt_flags = 0;
+	struct tt *tt;
+	int nparts = blkid_partlist_numof_partitions(ls);
+	if (!nparts)
+		return;
+
+	tt = tt_new_table(tt_flags);
+	if (!tt) {
+		warn(_("failed to initialize output table"));
+		return;
 	}
-	all.start = g.start;
 
-	if (blkdev_get_sectors(fd2, &size) != 0) {
-		perror("partx");
-		exit(1);
+	for (i = 0; i < ncolumns; i++)
+		if (!tt_define_column(tt, get_column_name(i), get_column_whint(i), 0))
+			warn(_("failed to initialize output column"));
+
+	for (i = 0; i < nparts; i++) {
+		blkid_partition par = blkid_partlist_get_partition(ls, i);
+		unsigned long long start = blkid_partition_get_start(par);
+		unsigned long long size =  blkid_partition_get_size(par);
+		int partno = blkid_partition_get_partno(par);
+		const char *name = blkid_partition_get_name(par);
+		const char *uuid = blkid_partition_get_uuid(par);
+
+		/* skip unwanted partition numbers, if any */
+		if (lower && upper)
+			if (partno < lower || partno > upper)
+				continue;
+		if (partnumber != -1)
+			if (partnumber != partno)
+				continue;
+		add_line(tt, partno, start, size, name, uuid);
 	}
-	all.size = (unsigned int) size;
 
-	if (verbose)
-		printf("device %s: start %d size %d\n",
-		       device, all.start, all.size);
+	tt_print_table(tt);
+	tt_free_table(tt);
+}
 
-	if (all.size == 0) {
-		fprintf(stderr, "That disk slice has size 0\n");
-		exit(0);
+/* old style output, backwards compatibility */
+static void show_oldpart(blkid_partlist ls, const char *device)
+{
+	int i, nparts = blkid_partlist_numof_partitions(ls);
+	if (!nparts)
+		return;
+
+	for (i = 0; i < nparts; i++) {
+		blkid_partition par = blkid_partlist_get_partition(ls, i);
+		unsigned long long start = blkid_partition_get_start(par);
+		unsigned long long size =  blkid_partition_get_size(par);
+		int partno = blkid_partition_get_partno(par);
+
+		/* skip unwanted partition numbers, if any */
+		if (lower && upper)
+			if (partno < lower || partno > upper)
+				continue;
+		if (partnumber != -1)
+			if (partnumber != partno)
+				continue;
+
+		printf("#%2d: %9llu-%9llu (%9llu sectors, %6llu MB)\n",
+		       partno, start, start + size -1,
+		       size, (BSECTORS * size) / 1000000);
 	}
-	if (all.size == 2)
-		all.size = 0;	/* probably extended partition */
-
-	/* add the indicated partitions to the kernel partition tables */
-	if (!lower)
-		lower = 1;
-	for (i = 0; i < ptct; i++) {
-		ptp = &pts[i];
-		if (!type || !strcmp(type, ptp->type)) {
-			n = ptp->fn(fd, all, slices, ARRAY_SIZE(slices));
-			if (n >= 0 && verbose)
-			    printf("%s: %d slices\n", ptp->type, n);
-			if (n > 0 && (verbose || what == LIST)) {
-			    for (j=0; j<n; j++)
-				printf("#%2d: %9d-%9d (%9d sectors, %6d MB)\n",
-				       lower+j,
-				       slices[j].start,
-				       slices[j].start+slices[j].size-1,
-				       slices[j].size,
-				       (int)((512 * (long long) slices[j].size)
-					/ 1000000));
-			}
-			if (n > 0 && what == ADD) {
-			    /* test for overlap, as in the case of an
-			       extended partition, and reduce size */
-			    for (j=0; j<n; j++) {
-				for (k=j+1; k<n; k++) {
-				    if (slices[k].start > slices[j].start &&
-					slices[k].start < slices[j].start +
-					slices[j].size) {
-					    slices[j].size = slices[k].start -
-						slices[j].start;
-					    if (verbose)
-						printf("reduced size of "
-						       "partition #%d to %d\n",
-						       lower+j,
-						       slices[j].size);
-				    }
-				}
-			    }
-			    for (j=0; j<n; j++) {
-			        /* skip unused/empty partitions */
-				if (slices[j].size == 0)
-				    continue;
-				pt.pno = lower+j;
-				pt.start = 512 * (long long) slices[j].start;
-				pt.length = 512 * (long long) slices[j].size;
-				pt.devname[0] = 0;
-				pt.volname[0] = 0;
-				a.op = BLKPG_ADD_PARTITION;
-				a.flags = 0;
-				a.datalen = sizeof(pt);
-				a.data = &pt;
-				if (ioctl(fd, BLKPG, &a) == -1) {
-				    perror("BLKPG");
-				    fprintf(stderr,
-					    "error adding partition %d\n",
-					    lower+j);
-				} else if (verbose)
-				    printf("added partition %d\n", lower+j);
-			    }
-			}
-		}
+}
+
+/* used for verbose option only */
+static void show_device_vinfo(blkid_probe pr, blkid_partlist ls, const char *device)
+{
+	unsigned long long start, size;
+
+	if (partnumber != -1) {/* using a specific partition */
+		int i, nparts = blkid_partlist_numof_partitions(ls);
+		for (i = 0; i < nparts; i++) {
+			blkid_partition par = blkid_partlist_get_partition(ls, i);
+			int partno = blkid_partition_get_partno(par);
+					
+			if (partnumber != partno)
+				continue;
+
+			start = blkid_partition_get_start(par);
+			size =  blkid_partition_get_size(par);	
+		}	
+	}
+	else { /* using the wholedisk */
+		start = 0LL; /* this always seems to be the case! */
+		size = blkid_probe_get_sectors(pr);
 	}
+	printf("device %s: start %llu size %llu\n", device, start, size);
+}
 
-	return 0;
+static int noret usage(FILE *out)
+{
+	fprintf(out, _("Usage:\n"
+		       "partx [-a|-d|-l] [--nr N-M] [partition] [wholedisk]\n"
+		       "\nOptions:\n"
+		       " -a, --add             add specified partitions or all of them\n"
+		       " -d, --delete          delete specified partitions or all of them\n"
+		       " -l, --list            list partitions (units of 512-byte sectors)\n"
+		       " -s, --show-details    list partitions (new format)\n\n"
+		       
+		       " -t, --type   <TYPE>   specify the partition type (dos, bsd, solaris, etc.)\n"
+		       " -n, --nr     <N-M>    specify the range of partitions (--nr 2-4)\n"
+		       " -o, --output <LIST>   output column\n"
+		       " -h, --help            print this help\n\n"));
+
+	fprintf(out, _("\nFor more information see partx(8).\n"));
+	exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
 }
 
-static void *
-xmalloc (size_t size) {
-	void *t;
+int main(int argc, char **argv)
+{
+	int fd, c;
+	int show, del, add;
+	char *type = NULL;
+	char *p;
+	char *device = NULL; /* ie: /dev/sda1 */
+	char *wholedisk = NULL; /* ie: /dev/sda */
+	dev_t disk;
+	blkid_probe pr;
+	blkid_partlist ls;
+	struct stat sb;
+	static const struct option long_opts[] = {
+		{ "list",	  no_argument,	      NULL,	'l' },
+		{ "show-details", no_argument,        NULL,     's' },
+		{ "add",	  no_argument,        NULL,	'a' },
+		{ "delete",	  no_argument,	      NULL,	'd' },
+		{ "type",	  required_argument,  NULL,	't' },
+		{ "nr",		  required_argument,  NULL,	'n' },
+		{ "output",	  required_argument,  NULL,	'o' },
+		{ "help",	  no_argument,        NULL,	'h' },
+		{ NULL, 0, NULL, 0 }
+	};
+
+	/* initialize default values */
+	outfmt = OLDFMT;
+	show = del = add = 0;
+	lower = upper = 0;
+	columns[ncolumns++] = COL_PARTNO;
+	columns[ncolumns++] = COL_START;
+	columns[ncolumns++] = COL_LENGTH;
+	columns[ncolumns++] = COL_SECTORS;
+	columns[ncolumns++] = COL_SIZE;
+	columns[ncolumns++] = COL_NAME;
+	columns[ncolumns++] = COL_UUID;
+
+	while ((c = getopt_long(argc, argv, "lsadvn:t:o:h", long_opts, NULL)) != -1) {
+		switch(c) {
+		case 'o':
+			if (set_columns(optarg))
+				err(EXIT_FAILURE, "set_columns failure");
+		case 's':
+			outfmt = NEWFMT;
+			break;
+		case 'l':
+			show = 1;
+			break;
+		case 'a':
+			add = 1;
+			break;
+		case 'd':
+			del = 1;
+			break;
+		case 'n':
+			p = optarg;
+			lower = atoi(p);
+			p = strchr(p, '-');
+			if (p)
+				upper = atoi(p+1);
+			else
+				upper = lower;
+			if (lower > upper)
+				errx(EXIT_FAILURE, _("invalid --nr option"));
+			break;
+		case 't':
+			type = optarg;
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 'h':
+			usage(stdout);
+		case '?':
+		default:
+			usage(stderr);
+		}
+	}
 
-	if (size == 0)
-		return NULL;
-	t = malloc (size);
-	if (t == NULL) {
-		fprintf(stderr, "Out of memory\n");
-		exit(1);
+	/*
+	 * Start parsing the /dev/sdaX /dev/sda options.
+	 * note that 'partx /dev/sda1' == 'partx /dev/sda1 /dev/sda'
+	 * so assume that the device and/or disk are always the last
+	 * arguments to be passed to partx.
+	 */
+	if (optind == argc-2) {
+		/* passed 2 args (ie: /dev/sda1 /dev/sda) */
+		if (upper || lower) /* cant do --nr N-M /dev/sda1 /dev/sda */
+			errx_mutually_exclusive("--nr, partition");
+		device = argv[optind];
+		wholedisk = argv[optind+1];
 	}
-	return t;
-}
+	else if (optind == argc-1) {
+		/* passed only one arg (ie: /dev/sda3 or /dev/sda) */
+		device = argv[optind];
+		if (stat(device, &sb) == -1)
+			err(EXIT_FAILURE, _("error: `%s' is not a device"), device);
 
-static int
-sseek(int fd, unsigned int secnr) {
-	long long in, out;
-	in = ((long long) secnr << 9);
-	out = 1;
+		blkid_devno_to_wholedisk(sb.st_rdev, wholedisk, sizeof(wholedisk), &disk);
+		wholedisk = blkid_devno_to_devname(disk);
+		if (!wholedisk) /* should always have a value for blkid */
+			wholedisk = device;
+	}
+	else
+		usage(stderr);
 
-	if ((out = lseek(fd, in, SEEK_SET)) != in)
-	{
-		fprintf(stderr, "lseek error\n");
-		return -1;
+	/* always compute this, if it's -1 we will just ignore it */
+	partnumber = get_partno_from_device(device);
+
+	if ((fd = open(wholedisk, O_RDONLY)) == -1)
+		err(EXIT_FAILURE, "failed to open %s", wholedisk);
+
+	/* init libblkid (always use wholedisk, not partitions, if any) */
+	pr = blkid_new_probe_from_filename(wholedisk);
+	if (!pr) {
+		close(fd);
+		err(EXIT_FAILURE, "%s: unable to probe device", wholedisk);
+	}
+	if (type) {
+		/* setup to use only the specified pt type */
+		char *name[] = {type, NULL};
+		blkid_probe_filter_partitions_type(pr, BLKID_FLTR_ONLYIN, name);
+		blkid_do_safeprobe(pr);
+	}
+	ls = blkid_probe_get_partitions(pr);
+	if (!ls) {
+		close(fd);
+		blkid_free_probe(pr);
+		/* error may depend largely on the pt type passed */
+		type ? 	errx(EXIT_FAILURE, "%s: failed to read '%s' partition(s)", wholedisk, type):
+			errx(EXIT_FAILURE, "%s: failed to read partition(s)", wholedisk);
 	}
-	return 0;
-}
 
-static
-struct block {
-	unsigned int secnr;
-	unsigned char *block;
-	struct block *next;
-} *blockhead;
-
-unsigned char *
-getblock(int fd, unsigned int secnr) {
-	struct block *bp;
-
-	for (bp = blockhead; bp; bp = bp->next)
-		if (bp->secnr == secnr)
-			return bp->block;
-	if (sseek(fd, secnr))
-		return NULL;
-	bp = xmalloc(sizeof(struct block));
-	bp->secnr = secnr;
-	bp->next = blockhead;
-	blockhead = bp;
-	bp->block = (unsigned char *) xmalloc(1024);
-	if (read(fd, bp->block, 1024) != 1024) {
-		fprintf(stderr, "read error, sector %d\n", secnr);
-		bp->block = NULL;
+	if (show || !(add || del)) {
+		if (verbose)
+			show_device_vinfo(pr, ls, device);
+		outfmt == NEWFMT ? show_part(ls) : show_oldpart(ls, device);
 	}
-	return bp->block;
-}
 
-/* call with errno and integer m and error message */
-/* merge to interval m-n */
-static void
-errmerge(int err, int m, char *msg1, char *msg2) {
-	static int preverr, firstm, prevm;
+	if (add)
+		add_part(fd, ls);
 
-	if (err != preverr) {
-		if (preverr) {
-			if (firstm == prevm)
-				fprintf(stderr, msg1, firstm);
-			else
-				fprintf(stderr, msg2, firstm, prevm);
-			errno = preverr;
-			perror("BLKPG");
-		}
-		preverr = err;
-		firstm = prevm = m;
-	} else
-		prevm = m;
+	if (del)
+		del_part(fd, ls);
+
+	close(fd);
+	blkid_free_probe(pr);
+	return EXIT_SUCCESS;
 }
diff --git a/partx/partx.h b/partx/partx.h
deleted file mode 100644
index 8702f25..0000000
--- a/partx/partx.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef PARTX_H_INCLUDED
-#define PARTX_H_INCLUDED
-
-/*
- * For each partition type there is a routine that takes
- * a block device and a range, and returns the list of
- * slices found there in the supplied array SP that can
- * hold NS entries. The return value is the number of
- * entries stored, or -1 if the appropriate type is not
- * present.
- */
-
-
-/* units: 512 byte sectors */
-struct slice {
-	unsigned int start;
-	unsigned int size;
-};
-
-typedef int (ptreader)(int fd, struct slice all, struct slice *sp, int ns);
-
-extern ptreader read_dos_pt, read_bsd_pt, read_solaris_pt, read_unixware_pt, read_gpt_pt;
-extern ptreader read_sun_pt, read_mac_pt;
-
-unsigned char *getblock(int fd, unsigned int secnr);
-
-static inline int
-four2int(unsigned char *p) {
-	return p[0] + (p[1]<<8) + (p[2]<<16) + (p[3]<<24);
-}
-
-#endif /* PARTX_H_INCLUDED */
diff --git a/partx/solaris.c b/partx/solaris.c
deleted file mode 100644
index 24075ae..0000000
--- a/partx/solaris.c
+++ /dev/null
@@ -1,69 +0,0 @@
-#include <stdio.h>
-#include <time.h>		/* time_t */
-#include <sys/types.h>
-#include "partx.h"
-
-#define SOLARIS_X86_NUMSLICE	8
-#define SOLARIS_X86_VTOC_SANE	(0x600DDEEEUL)
-
-struct solaris_x86_slice {
-	unsigned short	s_tag;		/* ID tag of partition */
-	unsigned short	s_flag;		/* permision flags */
-	daddr_t 	s_start;	/* start sector no of partition */
-	long		s_size;		/* # of blocks in partition */
-};
-
-struct solaris_x86_vtoc {
-	unsigned long v_bootinfo[3];	/* info for mboot */
-	unsigned long v_sanity;		/* to verify vtoc sanity */
-	unsigned long v_version;	/* layout version */
-	char	v_volume[8];		/* volume name */
-	unsigned short	v_sectorsz;	/* sector size in bytes */
-	unsigned short	v_nparts;	/* number of partitions */
-	unsigned long v_reserved[10];	/* free space */
-	struct solaris_x86_slice
-		v_slice[SOLARIS_X86_NUMSLICE];   /* slice headers */
-	time_t	timestamp[SOLARIS_X86_NUMSLICE]; /* timestamp */
-	char	v_asciilabel[128];	/* for compatibility */
-};
-
-int
-read_solaris_pt(int fd, struct slice all, struct slice *sp, int ns) {
-	struct solaris_x86_vtoc *v;
-	struct solaris_x86_slice *s;
-	unsigned int offset = all.start;
-	int i, n;
-	unsigned char *bp;
-
-	bp = getblock(fd, offset+1); 	/* 1 sector suffices */
-	if (bp == NULL)
-		return -1;
-
-	v = (struct solaris_x86_vtoc *) bp;
-	if(v->v_sanity != SOLARIS_X86_VTOC_SANE)
-		return -1;
-
-	if(v->v_version != 1) {
-		fprintf(stderr, "Cannot handle solaris version %ld vtoc\n",
-		       v->v_version);
-		return 0;
-	}
-
-	for(i=0, n=0; i<SOLARIS_X86_NUMSLICE; i++) {
-		s = &v->v_slice[i];
-
-		if (s->s_size == 0)
-			continue;
-		if (n < ns) {
-			sp[n].start = offset + s->s_start;
-			sp[n].size = s->s_size;
-			n++;
-		} else {
-			fprintf(stderr,
-				"solaris_x86_partition: too many slices\n");
-			break;
-		}
-	}
-	return n;
-}
-
diff --git a/partx/sun.c b/partx/sun.c
deleted file mode 100644
index 30cbd9f..0000000
--- a/partx/sun.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Lifted from kpartx's sun.c
- *
- * Copyrights of the original file apply
- * Copyright (c) 2007 Hannes Reinecke
- *
- * Integrated to partx (utils-linux-ng)
- *       Davidlohr Bueso <dave@xxxxxxx>
- */
-
-#include <stdio.h>
-#include <sys/types.h>
-
-#include "bitops.h"
-#include "partx.h"
-
-#define SUN_DISK_MAGIC		0xDABE	/* Disk magic number */
-#define SUN_DISK_MAXPARTITIONS	8
-
-struct __attribute__ ((packed)) sun_raw_part {
-	u_int32_t	start_cylinder; /* where the part starts... */
-	u_int32_t	num_sectors;	/* ...and it's length */
-};
-
-struct __attribute__ ((packed)) sun_part_info {
-	u_int8_t	spare1;
-	u_int8_t	id;		/* Partition type */
-	u_int8_t	spare2;
-	u_int8_t	flags;		/* Partition flags */
-};
-
-struct __attribute__ ((packed)) sun_disk_label {
-	char		info[128];	/* Informative text string */
-	u_int8_t	spare0[14];
-	struct sun_part_info infos[SUN_DISK_MAXPARTITIONS];
-	u_int8_t	spare1[246];	/* Boot information etc. */
-	u_int16_t	rspeed;		/* Disk rotational speed */
-	u_int16_t	pcylcount;	/* Physical cylinder count */
-	u_int16_t	sparecyl;	/* extra sects per cylinder */
-	u_int8_t	spare2[4];	/* More magic... */
-	u_int16_t	ilfact;		/* Interleave factor */
-	u_int16_t	ncyl;		/* Data cylinder count */
-	u_int16_t	nacyl;		/* Alt. cylinder count */
-	u_int16_t	ntrks;		/* Tracks per cylinder */
-	u_int16_t	nsect;		/* Sectors per track */
-	u_int8_t	spare3[4];	/* Even more magic... */
-	struct sun_raw_part partitions[SUN_DISK_MAXPARTITIONS];
-	u_int16_t	magic;		/* Magic number */
-	u_int16_t	csum;		/* Label xor'd checksum */
-};
-
-/* Checksum Verification */
-static int
-sun_verify_checksum (struct sun_disk_label *label)
-{
-	u_int16_t *ush = ((u_int16_t *)(label + 1)) - 1;
-	u_int16_t csum = 0;
-
-	while (ush >= (u_int16_t *)label)
-		csum ^= *ush--;
-
-	return !csum;
-}
-
-int
-read_sun_pt(int fd, struct slice all, struct slice *sp, int ns) {
-	struct sun_disk_label *l;
-	struct sun_raw_part *s;
-	unsigned int offset = all.start, end;
-	int i, j, n;
-	unsigned char *bp;
-
-	bp = getblock(fd, offset);
-	if (bp == NULL)
-		return -1;
-
-	l = (struct sun_disk_label *) bp;
-	if(be16_to_cpu(l->magic) != SUN_DISK_MAGIC)
-		return -1;
-
-	if (!sun_verify_checksum(l)) {
-		fprintf(stderr, "Corrupted Sun disk label\n");
-		return -1;
-	}
-
-	for(i=0, n=0; i<SUN_DISK_MAXPARTITIONS; i++) {
-		s = &l->partitions[i];
-
-		if (s->num_sectors == 0)
-			continue;
-		if (n < ns) {
-			sp[n].start = offset +
-				be32_to_cpu(s->start_cylinder) * be16_to_cpu(l->nsect) * be16_to_cpu(l->ntrks);
-			sp[n].size = be32_to_cpu(s->num_sectors);
-			n++;
-		} else {
-			fprintf(stderr,
-				"sun_disklabel: too many slices\n");
-			break;
-		}
-	}
-	/*
-	 * Convention has it that the SUN disklabel will always have
-	 * the 'c' partition spanning the entire disk.
-	 * So we have to check for contained slices.
-	 */
-	for(i = 0; i < SUN_DISK_MAXPARTITIONS; i++) {
-		if (sp[i].size == 0)
-			continue;
-
-		end = sp[i].start + sp[i].size;
-		for(j = 0; j < SUN_DISK_MAXPARTITIONS; j ++) {
-			if ( i == j )
-				continue;
-			if (sp[j].size == 0)
-				continue;
-
-			if (sp[i].start < sp[j].start) {
-				if (end > sp[j].start &&
-				    end < sp[j].start + sp[j].size) {
-					/* Invalid slice */
-					fprintf(stderr,
-						"sun_disklabel: slice %d overlaps with %d\n", i , j);
-					sp[i].size = 0;
-				}
-			}
-		}
-	}
-	return n;
-}
diff --git a/partx/unixware.c b/partx/unixware.c
deleted file mode 100644
index c131475..0000000
--- a/partx/unixware.c
+++ /dev/null
@@ -1,83 +0,0 @@
-#include <stdio.h>
-#include "partx.h"
-
-#define UNIXWARE_FS_UNUSED     0
-#define UNIXWARE_NUMSLICE      16
-#define UNIXWARE_DISKMAGIC     (0xCA5E600D)
-#define UNIXWARE_DISKMAGIC2    (0x600DDEEE)
-
-struct unixware_slice {
-	unsigned short s_label;		/* label */
-	unsigned short s_flags;		/* permission flags */
-	unsigned int   start_sect;	/* starting sector */
-	unsigned int   nr_sects;	/* number of sectors in slice */
-};
-
-struct unixware_disklabel {
-	unsigned int   d_type;		/* drive type */
-	unsigned char  d_magic[4];	/* the magic number */
-	unsigned int   d_version;	/* version number */
-	char    d_serial[12];	   	/* serial number of the device */
-	unsigned int   d_ncylinders;	/* # of data cylinders per device */
-	unsigned int   d_ntracks;	/* # of tracks per cylinder */
-	unsigned int   d_nsectors;	/* # of data sectors per track */
-	unsigned int   d_secsize;	/* # of bytes per sector */
-	unsigned int   d_part_start;	/* # of first sector of this partition */
-	unsigned int   d_unknown1[12];	/* ? */
-	unsigned int   d_alt_tbl;	/* byte offset of alternate table */
-	unsigned int   d_alt_len;	/* byte length of alternate table */
-	unsigned int   d_phys_cyl;	/* # of physical cylinders per device */
-	unsigned int   d_phys_trk;	/* # of physical tracks per cylinder */
-	unsigned int   d_phys_sec;	/* # of physical sectors per track */
-	unsigned int   d_phys_bytes;	/* # of physical bytes per sector */
-	unsigned int   d_unknown2;	/* ? */
-	unsigned int   d_unknown3;	/* ? */
-	unsigned int   d_pad[8];	/* pad */
-
-	struct unixware_vtoc {
-		unsigned char   v_magic[4];	/* the magic number */
-		unsigned int    v_version;	/* version number */
-		char    v_name[8];	      	/* volume name */
-		unsigned short  v_nslices;	/* # of slices */
-		unsigned short  v_unknown1;	/* ? */
-		unsigned int    v_reserved[10];	/* reserved */
-		struct unixware_slice
-		    v_slice[UNIXWARE_NUMSLICE]; /* slice headers */
-	} vtoc;
-
-};  /* 408 */
-
-int
-read_unixware_pt(int fd, struct slice all, struct slice *sp, int ns) {
-	struct unixware_disklabel *l;
-	struct unixware_slice *p;
-	unsigned int offset = all.start;
-	unsigned char *bp;
-	int n = 0;
-
-	bp = getblock(fd, offset+29); 	/* 1 sector suffices */
-	if (bp == NULL)
-		return -1;
-
-	l = (struct unixware_disklabel *) bp;
-	if (four2int(l->d_magic) != UNIXWARE_DISKMAGIC ||
-	    four2int(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2)
-		return -1;
-
-	p = &l->vtoc.v_slice[1];	/* slice 0 is the whole disk. */
-	while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
-		if (p->s_label == UNIXWARE_FS_UNUSED)
-			/* nothing */;
-		else if (n < ns) {
-			sp[n].start = p->start_sect;
-			sp[n].size = p->nr_sects;
-			n++;
-		} else {
-			fprintf(stderr,
-				"unixware_partition: too many slices\n");
-			break;
-		}
-		p++;
-	}
-	return n;
-}
-- 
1.7.1




--
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux