changeset 11091:d25092d8295b

6895679 libdiskmgt needs to support extended partitions 6483812 libdiskmgt.so provides wrong values for the partition sizes
author Virginia Wray <Virginia.Wray@Sun.COM>
date Wed, 18 Nov 2009 09:28:52 -0700
parents 15bf339bd614
children 17a676e9520e
files usr/src/lib/Makefile usr/src/lib/libdiskmgt/Makefile.com usr/src/lib/libdiskmgt/common/libdiskmgt.h usr/src/lib/libdiskmgt/common/partition.c
diffstat 4 files changed, 420 insertions(+), 230 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/Makefile	Wed Nov 18 07:29:02 2009 -0700
+++ b/usr/src/lib/Makefile	Wed Nov 18 09:28:52 2009 -0700
@@ -651,6 +651,7 @@
 libhotplug:	libnvpair
 cfgadm_plugins:	libhotplug
 libilb:		libsocket
+$(INTEL_BUILD)libdiskmgt:libfdisk
 
 #
 # The reason this rule checks for the existence of the
--- a/usr/src/lib/libdiskmgt/Makefile.com	Wed Nov 18 07:29:02 2009 -0700
+++ b/usr/src/lib/libdiskmgt/Makefile.com	Wed Nov 18 09:28:52 2009 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -34,8 +34,10 @@
 include ../../Makefile.lib
 
 LIBS =		$(DYNLIB) $(LINTLIB)
-LDLIBS +=	-ldevinfo -ladm -ldevid -lkstat -lsysevent \
-		-lnvpair -lefi -lc
+i386_LDLIBS =   -lfdisk
+sparc_LDLIBS =
+LDLIBS +=       -ldevinfo -ladm -ldevid -lkstat -lsysevent \
+                -lnvpair -lefi -lc $($(MACH)_LDLIBS)
 DYNFLAGS +=	-R/opt/VRTSvxvm/lib
 
 SRCDIR =	../common
--- a/usr/src/lib/libdiskmgt/common/libdiskmgt.h	Wed Nov 18 07:29:02 2009 -0700
+++ b/usr/src/lib/libdiskmgt/common/libdiskmgt.h	Wed Nov 18 09:28:52 2009 -0700
@@ -19,15 +19,13 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #ifndef _LIBDISKMGT_H
 #define	_LIBDISKMGT_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -116,6 +114,13 @@
     DM_SLICE_STAT_USE = 0
 } dm_slice_stat_t;
 
+/* partition type */
+typedef enum {
+	DM_PRIMARY = 0,
+	DM_EXTENDED,
+	DM_LOGICAL
+} dm_partition_type_t;
+
 /* attribute definitions */
 
 /* drive */
@@ -190,7 +195,8 @@
 #define	DM_ECYL			"ecyl"
 #define	DM_EHEAD		"ehead"
 #define	DM_ESECT		"esect"
-#define	DM_PTYPE		"ptype"
+#define	DM_PTYPE		"ptype" /* this references the partition id */
+#define	DM_PARTITION_TYPE	"part_type" /* primary, extended, logical */
 #define	DM_RELSECT		"relsect"
 
 /* slice */
--- a/usr/src/lib/libdiskmgt/common/partition.c	Wed Nov 18 07:29:02 2009 -0700
+++ b/usr/src/lib/libdiskmgt/common/partition.c	Wed Nov 18 09:28:52 2009 -0700
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <fcntl.h>
 #include <libdevinfo.h>
 #include <stdio.h>
@@ -37,6 +35,11 @@
 #include <unistd.h>
 #include <sys/dkio.h>
 
+#if defined(i386) || defined(__amd64)
+#include <sys/dktp/fdisk.h>
+#include <libfdisk.h>
+#endif
+
 #include "libdiskmgt.h"
 #include "disks_private.h"
 #include "partition.h"
@@ -50,6 +53,8 @@
 #define	lel(val)	(val)
 #endif
 
+#define	TOTAL_NUMPART	(FD_NUMPART + MAX_EXT_PARTS)
+
 #define	ISIZE		FD_NUMPART * sizeof (struct ipart)
 
 static int	desc_ok(descriptor_t *dp);
@@ -65,21 +70,21 @@
     int *errp)
 {
 	if (!desc_ok(desc)) {
-	    *errp = ENODEV;
-	    return (NULL);
+		*errp = ENODEV;
+		return (NULL);
 	}
 
 	switch (type) {
 	case DM_MEDIA:
-	    return (media_get_assocs(desc, errp));
+		return (media_get_assocs(desc, errp));
 	case DM_SLICE:
-	    if (!has_slices(desc, errp)) {
-		if (*errp != 0) {
-		    return (NULL);
+		if (!has_slices(desc, errp)) {
+			if (*errp != 0) {
+				return (NULL);
+			}
+			return (libdiskmgt_empty_desc_array(errp));
 		}
-		return (libdiskmgt_empty_desc_array(errp));
-	    }
-	    return (slice_get_assocs(desc, errp));
+		return (slice_get_assocs(desc, errp));
 	}
 
 	*errp = EINVAL;
@@ -97,7 +102,7 @@
 	descriptor_t	**partitions;
 	int		pos;
 	int		i;
-	struct ipart	iparts[FD_NUMPART];
+	struct ipart	iparts[TOTAL_NUMPART];
 	char		pname[MAXPATHLEN];
 	int		conv_flag = 0;
 #if defined(i386) || defined(__amd64)
@@ -105,24 +110,24 @@
 #endif
 
 	if (get_parts(desc->p.disk, iparts, pname, sizeof (pname)) != 0) {
-	    return (libdiskmgt_empty_desc_array(errp));
+		return (libdiskmgt_empty_desc_array(errp));
 	}
 
 	/* allocate the array for the descriptors */
-	partitions = (descriptor_t **)calloc(FD_NUMPART + 1,
+	partitions = (descriptor_t **)calloc(TOTAL_NUMPART + 1,
 	    sizeof (descriptor_t *));
 	if (partitions == NULL) {
-	    *errp = ENOMEM;
-	    return (NULL);
+		*errp = ENOMEM;
+		return (NULL);
 	}
 
 #if defined(i386) || defined(__amd64)
-	    /* convert part. name (e.g. c0d0p0) */
-	    len = strlen(pname);
-	    if (len > 1 && *(pname + (len - 2)) == 'p') {
+	/* convert part. name (e.g. c0d0p1) */
+	len = strlen(pname);
+	if (len > 1 && *(pname + (len - 2)) == 'p') {
 		conv_flag = 1;
 		*(pname + (len - 1)) = 0;
-	    }
+	}
 #endif
 
 	/*
@@ -130,77 +135,88 @@
 	 * and if there isn't one then we need the first solaris partition.
 	 */
 	if (desc->type == DM_SLICE) {
-	    for (i = 0; i < FD_NUMPART; i++) {
-		if (iparts[i].bootid == ACTIVE &&
-		    (iparts[i].systid == SUNIXOS ||
-		    iparts[i].systid == SUNIXOS2)) {
-			break;
+		for (i = 0; i < TOTAL_NUMPART; i++) {
+			if (iparts[i].bootid == ACTIVE &&
+			    (iparts[i].systid == SUNIXOS ||
+			    iparts[i].systid == SUNIXOS2)) {
+				break;
+			}
 		}
-	    }
 
-	    /* no active solaris part., try to get the first solaris part. */
-	    if (i >= FD_NUMPART) {
-		for (i = 0; i < FD_NUMPART; i++) {
-		    if (iparts[i].systid == SUNIXOS ||
-			iparts[i].systid == SUNIXOS2) {
-			    break;
-		    }
-		}
-	    }
-
-	    if (i < FD_NUMPART) {
-		/* we found a solaris partition to use */
-		char	part_name[MAXPATHLEN];
-
-		if (conv_flag) {
-		    /* convert part. name (e.g. c0d0p0) */
-		    (void) snprintf(part_name, sizeof (part_name), "%s%d",
-			pname, i);
-		} else {
-		    (void) snprintf(part_name, sizeof (part_name), "%d", i);
+		/*
+		 * no active solaris part.,*try to get the first solaris part.
+		 */
+		if (i >= TOTAL_NUMPART) {
+			for (i = 0; i < TOTAL_NUMPART; i++) {
+				if (iparts[i].systid == SUNIXOS ||
+				    iparts[i].systid == SUNIXOS2) {
+					break;
+				}
+			}
 		}
 
-		/* the media name comes from the slice desc. */
-		partitions[0] = cache_get_desc(DM_PARTITION, desc->p.disk,
-		    part_name, desc->secondary_name, errp);
-		if (*errp != 0) {
-		    cache_free_descriptors(partitions);
-		    return (NULL);
+		if (i < TOTAL_NUMPART) {
+		/* we found a solaris partition to use */
+			char	part_name[MAXPATHLEN];
+
+			if (conv_flag) {
+			/* convert part. name (e.g. c0d0p1) */
+				(void) snprintf(part_name, sizeof (part_name),
+				    "%s%d", pname, i+1);
+			} else {
+				(void) snprintf(part_name, sizeof (part_name),
+				    "%d", i+1);
+			}
+
+			/* the media name comes from the slice desc. */
+			partitions[0] = cache_get_desc(DM_PARTITION,
+			    desc->p.disk, part_name, desc->secondary_name,
+			    errp);
+			if (*errp != 0) {
+				cache_free_descriptors(partitions);
+				return (NULL);
+			}
+			partitions[1] = NULL;
+
+			return (partitions);
 		}
-		partitions[1] = NULL;
 
-		return (partitions);
-
-	    }
-
-	    return (libdiskmgt_empty_desc_array(errp));
+		return (libdiskmgt_empty_desc_array(errp));
 	}
 
 	/* Must be for media, so get all the parts. */
 
 	pos = 0;
-	for (i = 0; i < FD_NUMPART; i++) {
-	    if (iparts[i].systid != 0) {
-		char	part_name[MAXPATHLEN];
+	for (i = 0; i < TOTAL_NUMPART; i++) {
+		if (iparts[i].systid != UNUSED) {
+			char	part_name[MAXPATHLEN];
 
-		if (conv_flag) {
-		    /* convert part. name (e.g. c0d0p0) */
-		    (void) snprintf(part_name, sizeof (part_name), "%s%d",
-			pname, i);
-		} else {
-		    (void) snprintf(part_name, sizeof (part_name), "%d", i);
+			/*
+			 * Process the descriptors and modify the cxdxpx
+			 * format so that it refers to the fdisk partition
+			 * number and not to the physical disk. This is
+			 * achieved by i+1, where i is the number of the
+			 * physical disk partition.
+			 */
+			if (conv_flag) {
+				/* convert part. name (e.g. c0d0p1) */
+				(void) snprintf(part_name, sizeof (part_name),
+				    "%s%d", pname, i+1);
+			} else {
+				(void) snprintf(part_name, sizeof (part_name),
+				    "%d", i+1);
+			}
+
+			/* the media name comes from the media desc. */
+			partitions[pos] = cache_get_desc(DM_PARTITION,
+			    desc->p.disk, part_name, desc->name, errp);
+			if (*errp != 0) {
+				cache_free_descriptors(partitions);
+				return (NULL);
+			}
+
+			pos++;
 		}
-
-		/* the media name comes from the media desc. */
-		partitions[pos] = cache_get_desc(DM_PARTITION, desc->p.disk,
-		    part_name, desc->name, errp);
-		if (*errp != 0) {
-		    cache_free_descriptors(partitions);
-		    return (NULL);
-		}
-
-		pos++;
-	    }
 	}
 	partitions[pos] = NULL;
 
@@ -212,25 +228,25 @@
 partition_get_attributes(descriptor_t *dp, int *errp)
 {
 	nvlist_t	*attrs = NULL;
-	struct ipart	iparts[FD_NUMPART];
+	struct ipart	iparts[TOTAL_NUMPART];
 
 	if (!desc_ok(dp)) {
-	    *errp = ENODEV;
-	    return (NULL);
+		*errp = ENODEV;
+		return (NULL);
 	}
 
 	if ((*errp = get_parts(dp->p.disk, iparts, NULL, 0)) != 0) {
-	    return (NULL);
+		return (NULL);
 	}
 
 	if (nvlist_alloc(&attrs, NVATTRS, 0) != 0) {
-	    *errp = ENOMEM;
-	    return (NULL);
+		*errp = ENOMEM;
+		return (NULL);
 	}
 
 	if ((*errp = get_attrs(dp, iparts, attrs)) != 0) {
-	    nvlist_free(attrs);
-	    attrs = NULL;
+		nvlist_free(attrs);
+		attrs = NULL;
 	}
 
 	return (attrs);
@@ -248,21 +264,21 @@
 
 	partitions = cache_get_descriptors(DM_PARTITION, errp);
 	if (*errp != 0) {
-	    return (NULL);
+		return (NULL);
 	}
 
 	for (i = 0; partitions[i]; i++) {
-	    if (libdiskmgt_str_eq(name, partitions[i]->name)) {
-		partition = partitions[i];
-	    } else {
-		/* clean up the unused descriptors */
-		cache_free_descriptor(partitions[i]);
-	    }
+		if (libdiskmgt_str_eq(name, partitions[i]->name)) {
+			partition = partitions[i];
+		} else {
+			/* clean up the unused descriptors */
+			cache_free_descriptor(partitions[i]);
+		}
 	}
 	free(partitions);
 
 	if (partition == NULL) {
-	    *errp = ENODEV;
+		*errp = ENODEV;
 	}
 
 	return (partition);
@@ -298,8 +314,8 @@
 
 #ifdef sparc
 	if (dp->drv_type == DM_DT_FIXED) {
-	    /* on sparc, only removable media can have fdisk parts. */
-	    return (0);
+		/* on sparc, only removable media can have fdisk parts. */
+		return (0);
 	}
 #endif
 
@@ -309,16 +325,29 @@
 	 */
 
 	if ((ioctl(fd, DKIOCGMBOOT, bootsect) < 0) && (errno != ENOTTY)) {
-	    return (0);
+		return (0);
 	}
 
 	return (1);
 }
 
 /*
+ * partition_make_descriptors
+ *
  * A partition descriptor points to a disk, the name is the partition number
- * and the secondary name is the media name.
+ * and the secondary name is the media name. The iparts parameter returned
+ * by the get_parts function contains the structures of all of the identified
+ * partitions found on each disk on a system. These are processed into an array
+ * of descriptors. A descriptor contains all of the information about a
+ * specific partition.
+ *
+ * Parameters:  none
+ *
+ * Returns:     0 on success
+ *              Error value on failure
+ *
  */
+
 int
 partition_make_descriptors()
 {
@@ -327,49 +356,61 @@
 
 	dp = cache_get_disklist();
 	while (dp != NULL) {
-	    struct ipart	iparts[FD_NUMPART];
-	    char		pname[MAXPATHLEN];
+		struct ipart	iparts[TOTAL_NUMPART];
+		char		pname[MAXPATHLEN];
 
-	    if (get_parts(dp, iparts, pname, sizeof (pname)) == 0) {
-		int	i;
-		char	mname[MAXPATHLEN];
-		int	conv_flag = 0;
+		if (get_parts(dp, iparts, pname, sizeof (pname)) == 0) {
+			int	i;
+			char	mname[MAXPATHLEN];
+			int	conv_flag = 0;
 #if defined(i386) || defined(__amd64)
-		/* convert part. name (e.g. c0d0p0) */
-		int	len;
+			/* convert part. name (e.g. c0d0p1) */
+			int	len;
 
-		len = strlen(pname);
-		if (len > 1 && *(pname + (len - 2)) == 'p') {
-		    conv_flag = 1;
-		    *(pname + (len - 1)) = 0;
-		}
+			len = strlen(pname);
+			if (len > 1 && *(pname + (len - 2)) == 'p') {
+				conv_flag = 1;
+				*(pname + (len - 1)) = 0;
+			}
 #endif
 
-		mname[0] = 0;
-		(void) media_read_name(dp, mname, sizeof (mname));
+			mname[0] = 0;
+			(void) media_read_name(dp, mname, sizeof (mname));
 
-		for (i = 0; i < FD_NUMPART; i++) {
-		    if (iparts[i].systid != 0) {
-			char	part_name[MAXPATHLEN];
+			/*
+			 * Process the descriptors and modify the cxdxpx
+			 * format so that it refers to the fdisk partition
+			 * number and not to the physical disk. This is
+			 * achieved by i+1, where i is the number of the
+			 * physical disk partition.
+			 */
+			for (i = 0; i < TOTAL_NUMPART; i++) {
+				if (iparts[i].systid != UNUSED) {
+					char    part_name[MAXPATHLEN];
 
-			if (conv_flag) {
-			    /* convert part. name (e.g. c0d0p0) */
-			    (void) snprintf(part_name, sizeof (part_name),
-				"%s%d", pname, i);
-			} else {
-			    (void) snprintf(part_name, sizeof (part_name),
-				"%d", i);
-			}
+					if (conv_flag) {
+						/*
+						 * convert partition name
+						 * (e.g. c0d0p1)
+						 */
+						(void) snprintf(part_name,
+						    sizeof (part_name),
+						    "%s%d", pname, i+1);
+					} else {
+						(void) snprintf(part_name,
+						    sizeof (part_name),
+						    "%d", i+1);
+					}
 
-			cache_load_desc(DM_PARTITION, dp, part_name, mname,
-			    &error);
-			if (error != 0) {
-			    return (error);
+					cache_load_desc(DM_PARTITION, dp,
+					    part_name, mname, &error);
+					if (error != 0) {
+						return (error);
+					}
+				}
 			}
-		    }
 		}
-	    }
-	    dp = dp->next;
+		dp = dp->next;
 	}
 
 	return (0);
@@ -388,72 +429,122 @@
 
 	p = strrchr(dp->name, 'p');
 	if (p == NULL) {
-	    p = dp->name;
+		p = dp->name;
 	} else {
-	    p++;
+		p++;
 	}
 	part_num = atoi(p);
-	if (part_num >= FD_NUMPART || iparts[part_num].systid == 0) {
-	    return (ENODEV);
+	if (part_num > TOTAL_NUMPART ||
+	    iparts[part_num - 1].systid == UNUSED) {
+		return (ENODEV);
 	}
 
-	/* we found the partition */
+	/*
+	 * A partition has been found. Determine what type of
+	 * partition it is: logical, extended, or primary.
+	 * Collect the information for the partition.
+	 */
+#if defined(i386) || defined(__amd64)
+	if (part_num > FD_NUMPART) {
+		if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
+		    DM_LOGICAL) != 0)  {
+			return (ENOMEM);
+		}
+	} else if (fdisk_is_dos_extended(iparts[part_num - 1].systid)) {
+		if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
+		    DM_EXTENDED) != 0)  {
+			return (ENOMEM);
+		}
+
+	} else {
+		if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
+		    DM_PRIMARY) != 0) {
+			return (ENOMEM);
+		}
+	}
+#endif
+
+#ifdef sparc
+	if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
+	    DM_PRIMARY) != 0) {
+		return (ENOMEM);
+	}
+#endif
+
 
 	if (nvlist_add_uint32(attrs, DM_BOOTID,
-	    (unsigned int)iparts[part_num].bootid) != 0) {
-	    return (ENOMEM);
+	    (unsigned int)iparts[part_num - 1].bootid) != 0) {
+		return (ENOMEM);
 	}
 
 	if (nvlist_add_uint32(attrs, DM_PTYPE,
-	    (unsigned int)iparts[part_num].systid) != 0) {
-	    return (ENOMEM);
+	    (unsigned int)iparts[part_num - 1].systid) != 0) {
+		return (ENOMEM);
 	}
 
 	if (nvlist_add_uint32(attrs, DM_BHEAD,
-	    (unsigned int)iparts[part_num].beghead) != 0) {
-	    return (ENOMEM);
+	    (unsigned int)iparts[part_num - 1].beghead) != 0) {
+		return (ENOMEM);
 	}
 
 	if (nvlist_add_uint32(attrs, DM_BSECT,
-	    (unsigned int)((iparts[part_num].begsect) & 0x3f)) != 0) {
-	    return (ENOMEM);
+	    (unsigned int)((iparts[part_num - 1].begsect) & 0x3f)) != 0) {
+		return (ENOMEM);
 	}
 
 	if (nvlist_add_uint32(attrs, DM_BCYL, (unsigned int)
-	    ((iparts[part_num].begcyl & 0xff) |
-	    ((iparts[part_num].begsect & 0xc0) << 2))) != 0) {
-	    return (ENOMEM);
+	    ((iparts[part_num - 1].begcyl & 0xff) |
+	    ((iparts[part_num - 1].begsect & 0xc0) << 2))) != 0) {
+		return (ENOMEM);
 	}
 
 	if (nvlist_add_uint32(attrs, DM_EHEAD,
-	    (unsigned int)iparts[part_num].endhead) != 0) {
-	    return (ENOMEM);
+	    (unsigned int)iparts[part_num - 1].endhead) != 0) {
+		return (ENOMEM);
 	}
 
 	if (nvlist_add_uint32(attrs, DM_ESECT,
-	    (unsigned int)((iparts[part_num].endsect) & 0x3f)) != 0) {
-	    return (ENOMEM);
+	    (unsigned int)((iparts[part_num - 1].endsect) & 0x3f)) != 0) {
+		return (ENOMEM);
 	}
 
 	if (nvlist_add_uint32(attrs, DM_ECYL, (unsigned int)
-	    ((iparts[part_num].endcyl & 0xff) |
-	    ((iparts[part_num].endsect & 0xc0) << 2))) != 0) {
-	    return (ENOMEM);
+	    ((iparts[part_num - 1].endcyl & 0xff) |
+	    ((iparts[part_num - 1].endsect & 0xc0) << 2))) != 0) {
+		return (ENOMEM);
 	}
 
 	if (nvlist_add_uint32(attrs, DM_RELSECT,
-	    (unsigned int)iparts[part_num].relsect) != 0) {
-	    return (ENOMEM);
+	    (unsigned int)iparts[part_num - 1].relsect) != 0) {
+		return (ENOMEM);
 	}
 
 	if (nvlist_add_uint32(attrs, DM_NSECTORS,
-	    (unsigned int)iparts[part_num].numsect) != 0) {
-	    return (ENOMEM);
+	    (unsigned int)iparts[part_num - 1].numsect) != 0) {
+		return (ENOMEM);
 	}
 
 	return (0);
 }
 
+/*
+ * get_parts
+ * Discovers the primary, extended, and logical partitions that have
+ * been created on a disk. get_parts loops through the partitions,
+ * collects the information on each partition and stores it in a
+ * partition table.
+ *
+ * Parameters;
+ *		disk		-The disk device to be evaluated for partitions
+ *		iparts		-The structure that holds information about
+ *				 the partitions
+ *		opath		-The device path
+ *		opath_len 	-Buffer size used with opath
+ * Returns:
+ *		0 on Successful completion
+ *		Error Value on failure
+ *
+ */
 static int
 get_parts(disk_t *disk, struct ipart *iparts, char *opath, int opath_len)
 {
@@ -463,67 +554,157 @@
 	char		bootsect[512];
 	int		i;
 
+#if defined(i386) || defined(__amd64)
+	int 		j, ret;
+	ext_part_t	*epp;		/* extended partition structure */
+	char 		*device;	/* name of fixed disk drive */
+	size_t 		len;
+	logical_drive_t	*log_drv;	/* logical drive structure */
+	uint64_t 	tmpsect;
+#endif
+
 	/* Can't use drive_open_disk since we need the partition dev name. */
 	if ((fd = open_disk(disk, opath, opath_len)) < 0) {
-	    return (ENODEV);
+		return (ENODEV);
 	}
 
 	/* First make sure media is inserted and spun up. */
 	if (!media_read_info(fd, &minfo)) {
-	    (void) close(fd);
-	    return (ENODEV);
+		(void) close(fd);
+		return (ENODEV);
 	}
 
 	if (!partition_has_fdisk(disk, fd)) {
-	    (void) close(fd);
-	    return (ENOTTY);
+		(void) close(fd);
+		return (ENOTTY);
 	}
 
 	if (lseek(fd, 0, 0) == -1) {
-	    (void) close(fd);
-	    return (ENODEV);
+		(void) close(fd);
+		return (ENODEV);
 	}
 
 	if (read(fd, bootsect, 512) != 512) {
-	    (void) close(fd);
-	    return (ENODEV);
+		(void) close(fd);
+		return (ENODEV);
 	}
 	(void) close(fd);
 
 	(void) memcpy(&bootblk, bootsect, sizeof (bootblk));
 
 	if (les(bootblk.signature) != MBB_MAGIC)  {
-	    return (ENOTTY);
+		return (ENOTTY);
+	}
+
+	/*
+	 * Initialize the memory space to clear unknown garbage
+	 * that might create confusing results.
+	 */
+	for (i = 0;  i < TOTAL_NUMPART; i++) {
+		memset(&iparts[i], 0, sizeof (struct ipart));
+		iparts[i].systid = UNUSED;
 	}
 
 	(void) memcpy(iparts, bootblk.parts, ISIZE);
 
+	/*
+	 * Check to see if a valid partition exists. If a valid partition
+	 * exists, check to see if it is an extended partition.
+	 * If an extended partition exists, collect the logical partition
+	 * data.
+	 */
 	for (i = 0; i < FD_NUMPART; i++) {
-	    if (iparts[i].systid != 0) {
+		if (iparts[i].systid == UNUSED)
+			continue;
+
 		iparts[i].relsect = lel(iparts[i].relsect);
 		iparts[i].numsect = lel(iparts[i].numsect);
-	    }
+
+#if defined(i386) || defined(__amd64)
+		if (!fdisk_is_dos_extended(iparts[i].systid))
+			continue;
+
+		len = strlen(disk->aliases->alias) + strlen("/dev/rdsk/") + 1;
+		if ((device = malloc(len)) == NULL) {
+			if (device)
+				free(device);
+			continue;
+		}
+
+		/* Check the above fix w Jean */
+		(void) snprintf(device, len, "/dev/rdsk/%s",
+		    disk->aliases->alias);
+
+		if ((ret = libfdisk_init(&epp, device, &iparts[i],
+		    FDISK_READ_DISK)) != FDISK_SUCCESS) {
+
+			switch (ret) {
+				/*
+				 * The first 2 error cases indicate that
+				 * there is no Solaris logical partition,
+				 * which is a valid condition,
+				 * so iterating through the disk continues.
+				 * Any other error cases indicate there is
+				 * a potential problem with the disk, so
+				 * don't continue iterating through the disk
+				 * and return an error.
+				 */
+				case FDISK_EBADLOGDRIVE:
+				case FDISK_ENOLOGDRIVE:
+					free(device);
+					continue;
+				default:
+					free(device);
+					return (ENODEV);
+			}
+		}
+
+		/*
+		 * Collect logical drive information
+		 */
+		for (log_drv = fdisk_get_ld_head(epp),  j = FD_NUMPART,
+		    tmpsect = 0; (j < TOTAL_NUMPART) && (log_drv != NULL);
+		    log_drv = log_drv->next, j++) {
+			iparts[j].bootid = log_drv->parts[0].bootid;
+			iparts[j].beghead = log_drv->parts[0].beghead;
+			iparts[j].begsect = log_drv->parts[0].begsect;
+			iparts[j].begcyl = log_drv->parts[0].begcyl;
+			iparts[j].systid = log_drv->parts[0].systid;
+			iparts[j].endhead = log_drv->parts[0].endhead;
+			iparts[j].endsect = log_drv->parts[0].endsect;
+			iparts[j].endcyl = log_drv->parts[0].endcyl;
+			iparts[j].relsect = (tmpsect +
+			    lel(log_drv->parts[0].relsect) + epp->ext_beg_sec);
+			iparts[j].numsect = lel(log_drv->parts[0].numsect);
+			tmpsect = lel(log_drv->parts[1].relsect);
+		}
+
+		/* free the device and the epp memory. */
+		free(device);
+		libfdisk_fini(&epp);
+#endif
 	}
 
 	return (0);
 }
+
 /* return 1 if the partition descriptor is still valid, 0 if not. */
 static int
 desc_ok(descriptor_t *dp)
 {
 	/* First verify the media name for removable media */
 	if (dp->p.disk->removable) {
-	    char	mname[MAXPATHLEN];
+		char	mname[MAXPATHLEN];
 
-	    if (!media_read_name(dp->p.disk, mname, sizeof (mname))) {
-		return (0);
-	    }
+		if (!media_read_name(dp->p.disk, mname, sizeof (mname))) {
+			return (0);
+		}
 
-	    if (mname[0] == 0) {
-		return (libdiskmgt_str_eq(dp->secondary_name, NULL));
-	    } else {
-		return (libdiskmgt_str_eq(dp->secondary_name, mname));
-	    }
+		if (mname[0] == 0) {
+			return (libdiskmgt_str_eq(dp->secondary_name, NULL));
+		} else {
+			return (libdiskmgt_str_eq(dp->secondary_name, mname));
+		}
 	}
 
 	/*
@@ -544,18 +725,18 @@
 	int		pnum;
 	int		i;
 	char		*p;
-	struct ipart	iparts[FD_NUMPART];
+	struct ipart	iparts[TOTAL_NUMPART];
 
 	if (get_parts(desc->p.disk, iparts, NULL, 0) != 0) {
-	    *errp = ENODEV;
-	    return (0);
+		*errp = ENODEV;
+		return (0);
 	}
 
 	p = strrchr(desc->name, 'p');
 	if (p == NULL) {
-	    p = desc->name;
+		p = desc->name;
 	} else {
-	    p++;
+		p++;
 	}
 	pnum = atoi(p);
 
@@ -570,31 +751,31 @@
 	    iparts[pnum].systid == SUNIXOS2)) {
 		return (1);
 	} else {
-	    int	active = 0;
+		int	active = 0;
 
-	    /* Check if there are no active solaris partitions. */
-	    for (i = 0; i < FD_NUMPART; i++) {
-		if (iparts[i].bootid == ACTIVE &&
-		    (iparts[i].systid == SUNIXOS ||
-		    iparts[i].systid == SUNIXOS2)) {
-			active = 1;
-			break;
-		}
-	    }
-
-	    if (!active) {
-		/* Check if this is the first solaris partition. */
-		for (i = 0; i < FD_NUMPART; i++) {
-		    if (iparts[i].systid == SUNIXOS ||
-			iparts[i].systid == SUNIXOS2) {
-			    break;
-		    }
+		/* Check if there are no active solaris partitions. */
+		for (i = 0; i < TOTAL_NUMPART; i++) {
+			if (iparts[i].bootid == ACTIVE &&
+			    (iparts[i].systid == SUNIXOS ||
+			    iparts[i].systid == SUNIXOS2)) {
+				active = 1;
+				break;
+			}
 		}
 
-		if (i < FD_NUMPART && i == pnum) {
-		    return (1);
+		if (!active) {
+			/* Check if this is the first solaris partition. */
+			for (i = 0; i < TOTAL_NUMPART; i++) {
+				if (iparts[i].systid == SUNIXOS ||
+				    iparts[i].systid == SUNIXOS2) {
+					break;
+				}
+			}
+
+			if (i < TOTAL_NUMPART && i == pnum) {
+				return (1);
+			}
 		}
-	    }
 	}
 
 	return (0);
@@ -608,38 +789,38 @@
 	 */
 	if (diskp->aliases != NULL && diskp->aliases->devpaths != NULL) {
 #ifdef sparc
-	    if (opath != NULL) {
+	if (opath != NULL) {
 		(void) strlcpy(opath, diskp->aliases->devpaths->devpath, len);
-	    }
-	    return (open(diskp->aliases->devpaths->devpath, O_RDONLY|O_NDELAY));
+	}
+	return (open(diskp->aliases->devpaths->devpath, O_RDONLY|O_NDELAY));
 #else
-	    /* On intel we need to open partition device (e.g. c0d0p0). */
-	    char	part_dev[MAXPATHLEN];
-	    char	*p;
+	/* On intel we need to open partition device (e.g. c0d0p1). */
+	char	part_dev[MAXPATHLEN];
+	char	*p;
 
-	    (void) strlcpy(part_dev, diskp->aliases->devpaths->devpath,
-		sizeof (part_dev));
-	    p = strrchr(part_dev, '/');
-	    if (p == NULL) {
+	(void) strlcpy(part_dev, diskp->aliases->devpaths->devpath,
+	    sizeof (part_dev));
+	p = strrchr(part_dev, '/');
+	if (p == NULL) {
 		p = strrchr(part_dev, 's');
 		if (p != NULL) {
-		    *p = 'p';
+			*p = 'p';
 		}
-	    } else {
+	} else {
 		char *ps;
 
 		*p = 0;
 		ps = strrchr((p + 1), 's');
 		if (ps != NULL) {
-		    *ps = 'p';
+			*ps = 'p';
 		}
 		*p = '/';
-	    }
+	}
 
-	    if (opath != NULL) {
+	if (opath != NULL) {
 		(void) strlcpy(opath, part_dev, len);
-	    }
-	    return (open(part_dev, O_RDONLY|O_NDELAY));
+	}
+	return (open(part_dev, O_RDONLY|O_NDELAY));
 #endif
 	}