xref: /illumos-gate/usr/src/cmd/prtvtoc/prtvtoc.c (revision 03074a12)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5342440ecSPrasad Singamsetty  * Common Development and Distribution License (the "License").
6342440ecSPrasad Singamsetty  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2151706d6cSJoshua M. Clulow /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
2251706d6cSJoshua M. Clulow /*	  All Rights Reserved */
237c478bd9Sstevel@tonic-gate 
247c478bd9Sstevel@tonic-gate 
2551706d6cSJoshua M. Clulow /*	Copyright (c) 1984 AT&T */
2651706d6cSJoshua M. Clulow /*	  All Rights Reserved   */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
30342440ecSPrasad Singamsetty  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
317c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
3283a62956SJason King  * Copyright 2021 Jason King
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate  * Print a disk partition map (volume table of contents, or VTOC).
377c478bd9Sstevel@tonic-gate  */
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #include <errno.h>
407c478bd9Sstevel@tonic-gate #include <fcntl.h>
417c478bd9Sstevel@tonic-gate #include <unistd.h>
427c478bd9Sstevel@tonic-gate #include <stdlib.h>
437c478bd9Sstevel@tonic-gate #include <string.h>
447c478bd9Sstevel@tonic-gate #include <stdio.h>
457c478bd9Sstevel@tonic-gate #include <limits.h>
4651706d6cSJoshua M. Clulow #include <err.h>
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #include <sys/types.h>
497c478bd9Sstevel@tonic-gate #include <sys/stat.h>
507c478bd9Sstevel@tonic-gate #include <sys/dkio.h>
517c478bd9Sstevel@tonic-gate #include <sys/vtoc.h>
527c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
537c478bd9Sstevel@tonic-gate #include <sys/vfstab.h>
547c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #include <sys/efi_partition.h>
577c478bd9Sstevel@tonic-gate /*
587c478bd9Sstevel@tonic-gate  * Assumes V_NUMPAR must be a power of 2.
597c478bd9Sstevel@tonic-gate  *
607c478bd9Sstevel@tonic-gate  * for V_NUMPAR = 8, we have
6151706d6cSJoshua M. Clulow  *	parttn(x)=(x & 0x07)	noparttn(x)=(x & 0x3fff8)
627c478bd9Sstevel@tonic-gate  *
637c478bd9Sstevel@tonic-gate  * for V_NUMPAR = 16, we have
6451706d6cSJoshua M. Clulow  *	parttn(x)=(x & 0x0f)	noparttn(x)=(x & 0x3fff0)
657c478bd9Sstevel@tonic-gate  */
667c478bd9Sstevel@tonic-gate #define	parttn(x)	(x % V_NUMPAR)
677c478bd9Sstevel@tonic-gate #define	noparttn(x)	(x & (MAXMIN & ~(V_NUMPAR-1)))
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate  * Disk freespace structure.
717c478bd9Sstevel@tonic-gate  */
727c478bd9Sstevel@tonic-gate typedef struct {
737c478bd9Sstevel@tonic-gate 	u_longlong_t	fr_start;	/* Start of free space */
747c478bd9Sstevel@tonic-gate 	u_longlong_t	fr_size;	/* Length of free space */
757c478bd9Sstevel@tonic-gate } freemap_t;
767c478bd9Sstevel@tonic-gate 
77342440ecSPrasad Singamsetty static	freemap_t	*findfree(struct dk_geom *, struct extvtoc *);
787c478bd9Sstevel@tonic-gate static	int	partcmp(const void *, const void *);
797c478bd9Sstevel@tonic-gate static	int	partcmp64(const void *, const void *);
807c478bd9Sstevel@tonic-gate static	int	prtvtoc(char *);
81342440ecSPrasad Singamsetty static	void	putfree(struct extvtoc *, freemap_t *);
827c478bd9Sstevel@tonic-gate static	void	putfree64(struct dk_gpt *, freemap_t *);
83342440ecSPrasad Singamsetty static	void	puttable(struct dk_geom *, struct extvtoc *, freemap_t *,
847c478bd9Sstevel@tonic-gate 			char *, char **);
857c478bd9Sstevel@tonic-gate static	void	puttable64(struct dk_gpt *, freemap_t *,
867c478bd9Sstevel@tonic-gate 			char *, char **);
877c478bd9Sstevel@tonic-gate static	int	readgeom(int, char *, struct dk_geom *);
88342440ecSPrasad Singamsetty static	int	readvtoc(int, char *, struct extvtoc *);
897c478bd9Sstevel@tonic-gate static	int	readefi(int, char *, struct dk_gpt **);
907c478bd9Sstevel@tonic-gate static	void	usage(void);
9151706d6cSJoshua M. Clulow static	char	*safe_strdup(const char *, const char *);
9251706d6cSJoshua M. Clulow static	void	*safe_calloc(const char *, size_t, size_t);
9351706d6cSJoshua M. Clulow 
9451706d6cSJoshua M. Clulow #define	SAFE_STRDUP(a)		safe_strdup(__func__, (a))
9551706d6cSJoshua M. Clulow #define	SAFE_CALLOC(a, b)	safe_calloc(__func__, (a), (b))
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate  * External variables.
997c478bd9Sstevel@tonic-gate  */
1007c478bd9Sstevel@tonic-gate extern char	*getfullrawname();
1017c478bd9Sstevel@tonic-gate /*
1027c478bd9Sstevel@tonic-gate  * Static variables.
1037c478bd9Sstevel@tonic-gate  */
1047c478bd9Sstevel@tonic-gate static short	fflag;			/* Print freespace shell assignments */
1057c478bd9Sstevel@tonic-gate static short	hflag;			/* Omit headers */
1067c478bd9Sstevel@tonic-gate static short	sflag;			/* Omit all but the column header */
1077c478bd9Sstevel@tonic-gate static char	*fstab = VFSTAB;	/* Fstab pathname */
1087c478bd9Sstevel@tonic-gate static char	*mnttab = MNTTAB;	/* mnttab pathname */
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate int
main(int argc,char * argv[])11151706d6cSJoshua M. Clulow main(int argc, char *argv[])
1127c478bd9Sstevel@tonic-gate {
11351706d6cSJoshua M. Clulow 	int status = EXIT_SUCCESS;
11451706d6cSJoshua M. Clulow 	int c;
1157c478bd9Sstevel@tonic-gate 
11651706d6cSJoshua M. Clulow 	while ((c = getopt(argc, argv, "fhst:m:")) != -1) {
11751706d6cSJoshua M. Clulow 		switch (c) {
1187c478bd9Sstevel@tonic-gate 		case 'f':
1197c478bd9Sstevel@tonic-gate 			++fflag;
1207c478bd9Sstevel@tonic-gate 			break;
1217c478bd9Sstevel@tonic-gate 		case 'h':
1227c478bd9Sstevel@tonic-gate 			++hflag;
1237c478bd9Sstevel@tonic-gate 			break;
1247c478bd9Sstevel@tonic-gate 		case 's':
1257c478bd9Sstevel@tonic-gate 			++sflag;
1267c478bd9Sstevel@tonic-gate 			break;
1277c478bd9Sstevel@tonic-gate 		case 't':
1287c478bd9Sstevel@tonic-gate 			fstab = optarg;
1297c478bd9Sstevel@tonic-gate 			break;
1307c478bd9Sstevel@tonic-gate 		case 'm':
1317c478bd9Sstevel@tonic-gate 			mnttab = optarg;
1327c478bd9Sstevel@tonic-gate 			break;
1337c478bd9Sstevel@tonic-gate 		default:
1347c478bd9Sstevel@tonic-gate 			usage();
1357c478bd9Sstevel@tonic-gate 		}
13651706d6cSJoshua M. Clulow 	}
13751706d6cSJoshua M. Clulow 
13851706d6cSJoshua M. Clulow 	if (optind >= argc)
1397c478bd9Sstevel@tonic-gate 		usage();
14051706d6cSJoshua M. Clulow 
14151706d6cSJoshua M. Clulow 	for (int i = optind; i < argc; i++) {
14251706d6cSJoshua M. Clulow 		if (prtvtoc(argv[i]) != 0) {
14351706d6cSJoshua M. Clulow 			status = EXIT_FAILURE;
14451706d6cSJoshua M. Clulow 		}
14551706d6cSJoshua M. Clulow 	}
14651706d6cSJoshua M. Clulow 
14751706d6cSJoshua M. Clulow 	return (status);
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate static freemap_t	*freemap;
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate  * findfree(): Find free space on a disk.
1537c478bd9Sstevel@tonic-gate  */
1547c478bd9Sstevel@tonic-gate static freemap_t *
findfree(struct dk_geom * geom,struct extvtoc * vtoc)155342440ecSPrasad Singamsetty findfree(struct dk_geom *geom, struct extvtoc *vtoc)
1567c478bd9Sstevel@tonic-gate {
15751706d6cSJoshua M. Clulow 	struct extpartition *part;
15851706d6cSJoshua M. Clulow 	struct extpartition **list;
15951706d6cSJoshua M. Clulow 	freemap_t *freeidx;
16051706d6cSJoshua M. Clulow 	diskaddr_t fullsize;
16151706d6cSJoshua M. Clulow 	ulong_t cylsize;
16251706d6cSJoshua M. Clulow 	struct extpartition *sorted[V_NUMPAR + 1];
16351706d6cSJoshua M. Clulow 
1647c478bd9Sstevel@tonic-gate 	if (vtoc->v_nparts > V_NUMPAR) {
16551706d6cSJoshua M. Clulow 		errx(EXIT_FAILURE, "putfree(): Too many partitions on disk!");
1667c478bd9Sstevel@tonic-gate 	}
16751706d6cSJoshua M. Clulow 
16851706d6cSJoshua M. Clulow 	freemap = SAFE_CALLOC(sizeof (freemap_t), V_NUMPAR + 1);
16951706d6cSJoshua M. Clulow 	cylsize = (geom->dkg_nsect) * (geom->dkg_nhead);
17051706d6cSJoshua M. Clulow 	fullsize = (diskaddr_t)(geom->dkg_ncyl) * cylsize;
1717c478bd9Sstevel@tonic-gate 	list = sorted;
17251706d6cSJoshua M. Clulow 	for (part = vtoc->v_part; part < vtoc->v_part + vtoc->v_nparts;
17351706d6cSJoshua M. Clulow 	    ++part) {
1747c478bd9Sstevel@tonic-gate 		if (part->p_size && part->p_tag != V_BACKUP)
1757c478bd9Sstevel@tonic-gate 			*list++ = part;
17651706d6cSJoshua M. Clulow 	}
1777c478bd9Sstevel@tonic-gate 	*list = 0;
17851706d6cSJoshua M. Clulow 	qsort(sorted, list - sorted, sizeof (*sorted), partcmp);
1797c478bd9Sstevel@tonic-gate 	freeidx = freemap;
1807c478bd9Sstevel@tonic-gate 	freeidx->fr_start = 0;
18151706d6cSJoshua M. Clulow 	for (list = sorted; (part = *list) != NULL; ++list) {
18251706d6cSJoshua M. Clulow 		if (part->p_start <= freeidx->fr_start) {
1837c478bd9Sstevel@tonic-gate 			freeidx->fr_start += part->p_size;
18451706d6cSJoshua M. Clulow 		} else {
1857c478bd9Sstevel@tonic-gate 			freeidx->fr_size = part->p_start - freeidx->fr_start;
1867c478bd9Sstevel@tonic-gate 			(++freeidx)->fr_start = part->p_start + part->p_size;
1877c478bd9Sstevel@tonic-gate 		}
18851706d6cSJoshua M. Clulow 	}
1897c478bd9Sstevel@tonic-gate 	if (freeidx->fr_start < fullsize) {
1907c478bd9Sstevel@tonic-gate 		freeidx->fr_size = fullsize - freeidx->fr_start;
1917c478bd9Sstevel@tonic-gate 		++freeidx;
1927c478bd9Sstevel@tonic-gate 	}
1937c478bd9Sstevel@tonic-gate 	freeidx->fr_start = freeidx->fr_size = 0;
1947c478bd9Sstevel@tonic-gate 	return (freemap);
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate /*
1987c478bd9Sstevel@tonic-gate  * findfree64(): Find free space on a disk.
1997c478bd9Sstevel@tonic-gate  */
2007c478bd9Sstevel@tonic-gate static freemap_t *
findfree64(struct dk_gpt * efi)2017c478bd9Sstevel@tonic-gate findfree64(struct dk_gpt *efi)
2027c478bd9Sstevel@tonic-gate {
20351706d6cSJoshua M. Clulow 	struct dk_part *part;
20451706d6cSJoshua M. Clulow 	struct dk_part **list;
20551706d6cSJoshua M. Clulow 	freemap_t *freeidx;
20651706d6cSJoshua M. Clulow 	diskaddr_t fullsize;
20751706d6cSJoshua M. Clulow 	struct dk_part **sorted;
20851706d6cSJoshua M. Clulow 
20951706d6cSJoshua M. Clulow 	freemap = SAFE_CALLOC(sizeof (freemap_t), efi->efi_nparts + 1);
21051706d6cSJoshua M. Clulow 	sorted = SAFE_CALLOC(sizeof (struct dk_part), efi->efi_nparts + 1);
2117c478bd9Sstevel@tonic-gate 	fullsize = efi->efi_last_u_lba;
2127c478bd9Sstevel@tonic-gate 	list = sorted;
21351706d6cSJoshua M. Clulow 	for (part = efi->efi_parts; part < efi->efi_parts + efi->efi_nparts;
21451706d6cSJoshua M. Clulow 	    ++part) {
2157c478bd9Sstevel@tonic-gate 		if (part->p_size && part->p_tag != V_BACKUP)
2167c478bd9Sstevel@tonic-gate 			*list++ = part;
21751706d6cSJoshua M. Clulow 	}
2187c478bd9Sstevel@tonic-gate 	*list = 0;
21951706d6cSJoshua M. Clulow 	qsort(sorted, list - sorted, sizeof (*sorted), partcmp64);
2207c478bd9Sstevel@tonic-gate 	freeidx = freemap;
2217c478bd9Sstevel@tonic-gate 	freeidx->fr_start = efi->efi_first_u_lba;
22251706d6cSJoshua M. Clulow 	for (list = sorted; (part = *list) != NULL; ++list) {
22351706d6cSJoshua M. Clulow 		if (part->p_start == freeidx->fr_start) {
2247c478bd9Sstevel@tonic-gate 			freeidx->fr_start += part->p_size;
22551706d6cSJoshua M. Clulow 		} else {
2267c478bd9Sstevel@tonic-gate 			freeidx->fr_size = part->p_start - freeidx->fr_start;
2277c478bd9Sstevel@tonic-gate 			(++freeidx)->fr_start = part->p_start + part->p_size;
2287c478bd9Sstevel@tonic-gate 		}
22951706d6cSJoshua M. Clulow 	}
2307c478bd9Sstevel@tonic-gate 	if (freeidx->fr_start < fullsize) {
2317c478bd9Sstevel@tonic-gate 		freeidx->fr_size = fullsize - freeidx->fr_start;
2327c478bd9Sstevel@tonic-gate 		++freeidx;
2337c478bd9Sstevel@tonic-gate 	}
2347c478bd9Sstevel@tonic-gate 	freeidx->fr_start = freeidx->fr_size = 0;
2357c478bd9Sstevel@tonic-gate 	return (freemap);
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate /*
2397c478bd9Sstevel@tonic-gate  * getmntpt()
2407c478bd9Sstevel@tonic-gate  *
2417c478bd9Sstevel@tonic-gate  * Get the filesystem mountpoint of each partition on the disk
2427c478bd9Sstevel@tonic-gate  * from the fstab or mnttab. Returns a pointer to an array of pointers to
2437c478bd9Sstevel@tonic-gate  * directory names (indexed by partition number).
2447c478bd9Sstevel@tonic-gate  */
2457c478bd9Sstevel@tonic-gate static char **
getmntpt(major_t slot,minor_t nopartminor)2467c478bd9Sstevel@tonic-gate getmntpt(major_t slot, minor_t nopartminor)
2477c478bd9Sstevel@tonic-gate {
2487c478bd9Sstevel@tonic-gate 	FILE *file;
2497c478bd9Sstevel@tonic-gate 	char devbuf[PATH_MAX], *item;
2507c478bd9Sstevel@tonic-gate 	static char *list[V_NUMPAR];
2517c478bd9Sstevel@tonic-gate 	struct stat sb;
2527c478bd9Sstevel@tonic-gate 	struct mnttab mtab;
2537c478bd9Sstevel@tonic-gate 	struct vfstab vtab;
2547c478bd9Sstevel@tonic-gate 
25551706d6cSJoshua M. Clulow 	for (unsigned idx = 0; idx < V_NUMPAR; ++idx)
2567c478bd9Sstevel@tonic-gate 		list[idx] = NULL;
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	/* read mnttab for partition mountpoints */
2597c478bd9Sstevel@tonic-gate 	if ((file = fopen(mnttab, "r")) == NULL) {
26051706d6cSJoshua M. Clulow 		warn("failed to open %s", mnttab);
2617c478bd9Sstevel@tonic-gate 	} else {
2627c478bd9Sstevel@tonic-gate 		while (getmntent(file, &mtab) == 0) {
2637c478bd9Sstevel@tonic-gate 			item = mtab.mnt_special;
26451706d6cSJoshua M. Clulow 			if (item == NULL || mtab.mnt_mountp == NULL)
2657c478bd9Sstevel@tonic-gate 				continue;
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 			/*
2687c478bd9Sstevel@tonic-gate 			 * Is it from /dev?
2697c478bd9Sstevel@tonic-gate 			 */
27051706d6cSJoshua M. Clulow 			if (strncmp(item, "/dev/", strlen("/dev/")) != 0)
2717c478bd9Sstevel@tonic-gate 				continue;
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 			/*
2747c478bd9Sstevel@tonic-gate 			 * Is it a character device?
2757c478bd9Sstevel@tonic-gate 			 */
2767c478bd9Sstevel@tonic-gate 			(void) snprintf(devbuf, sizeof (devbuf), "/dev/r%s",
2777c478bd9Sstevel@tonic-gate 			    item + strlen("/dev/"));
2787c478bd9Sstevel@tonic-gate 
27951706d6cSJoshua M. Clulow 			if (stat(devbuf, &sb) != 0 ||
28051706d6cSJoshua M. Clulow 			    (sb.st_mode & S_IFMT) != S_IFCHR) {
2817c478bd9Sstevel@tonic-gate 				continue;
28251706d6cSJoshua M. Clulow 			}
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 			/*
2857c478bd9Sstevel@tonic-gate 			 * device must match input slot and nopartminor
2867c478bd9Sstevel@tonic-gate 			 */
28751706d6cSJoshua M. Clulow 			if (major(sb.st_rdev) != slot ||
28851706d6cSJoshua M. Clulow 			    noparttn(minor(sb.st_rdev)) != nopartminor) {
2897c478bd9Sstevel@tonic-gate 				continue;
29051706d6cSJoshua M. Clulow 			}
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 			list[parttn(minor(sb.st_rdev))] =
29351706d6cSJoshua M. Clulow 			    SAFE_STRDUP(mtab.mnt_mountp);
2947c478bd9Sstevel@tonic-gate 		}
2957c478bd9Sstevel@tonic-gate 		(void) fclose(file);
2967c478bd9Sstevel@tonic-gate 	}
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	if ((file = fopen(fstab, "r")) == NULL) {
29951706d6cSJoshua M. Clulow 		warn("failed to open %s", fstab);
3007c478bd9Sstevel@tonic-gate 		return (list);
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	/*
3047c478bd9Sstevel@tonic-gate 	 * Look for the disk in the vfstab so that we can report its mount
3057c478bd9Sstevel@tonic-gate 	 * point even if it isn't currently mounted.
3067c478bd9Sstevel@tonic-gate 	 */
3077c478bd9Sstevel@tonic-gate 	while (getvfsent(file, &vtab) == 0) {
3087c478bd9Sstevel@tonic-gate 		item = vtab.vfs_special;
30951706d6cSJoshua M. Clulow 		if (item == NULL || vtab.vfs_mountp == NULL)
3107c478bd9Sstevel@tonic-gate 			continue;
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 		if (strncmp(item, "/dev/", strlen("/dev/")) != 0)
3137c478bd9Sstevel@tonic-gate 			continue;
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 		/*
3167c478bd9Sstevel@tonic-gate 		 * Is it a character device?
3177c478bd9Sstevel@tonic-gate 		 */
3187c478bd9Sstevel@tonic-gate 		(void) snprintf(devbuf, sizeof (devbuf), "/dev/r%s",
3197c478bd9Sstevel@tonic-gate 		    item + strlen("/dev/"));
3207c478bd9Sstevel@tonic-gate 
32151706d6cSJoshua M. Clulow 		if (stat(devbuf, &sb) != 0 ||
32251706d6cSJoshua M. Clulow 		    (sb.st_mode & S_IFMT) != S_IFCHR) {
3237c478bd9Sstevel@tonic-gate 			continue;
32451706d6cSJoshua M. Clulow 		}
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 		/*
3277c478bd9Sstevel@tonic-gate 		 * device must match input slot and nopartminor
3287c478bd9Sstevel@tonic-gate 		 */
32951706d6cSJoshua M. Clulow 		if (major(sb.st_rdev) != slot ||
33051706d6cSJoshua M. Clulow 		    noparttn(minor(sb.st_rdev)) != nopartminor) {
3317c478bd9Sstevel@tonic-gate 			continue;
33251706d6cSJoshua M. Clulow 		}
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 		/*
3357c478bd9Sstevel@tonic-gate 		 * use mnttab entry if both tables have entries
3367c478bd9Sstevel@tonic-gate 		 */
3377c478bd9Sstevel@tonic-gate 		if (list[parttn(minor(sb.st_rdev))] != NULL)
3387c478bd9Sstevel@tonic-gate 			continue;
3397c478bd9Sstevel@tonic-gate 
34051706d6cSJoshua M. Clulow 		list[parttn(minor(sb.st_rdev))] = SAFE_STRDUP(vtab.vfs_mountp);
3417c478bd9Sstevel@tonic-gate 	}
3427c478bd9Sstevel@tonic-gate 	(void) fclose(file);
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	return (list);
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate /*
3487c478bd9Sstevel@tonic-gate  * partcmp(): Qsort() key comparison of partitions by starting sector numbers.
3497c478bd9Sstevel@tonic-gate  */
3507c478bd9Sstevel@tonic-gate static int
partcmp(const void * one,const void * two)3517c478bd9Sstevel@tonic-gate partcmp(const void *one, const void *two)
3527c478bd9Sstevel@tonic-gate {
35351706d6cSJoshua M. Clulow 	struct partition *p1 = *(struct partition **)one;
35451706d6cSJoshua M. Clulow 	struct partition *p2 = *(struct partition **)two;
35551706d6cSJoshua M. Clulow 
35651706d6cSJoshua M. Clulow 	if (p1->p_start > p2->p_start) {
35751706d6cSJoshua M. Clulow 		return (1);
35851706d6cSJoshua M. Clulow 	} else if (p1->p_start < p2->p_start) {
35951706d6cSJoshua M. Clulow 		return (-1);
36051706d6cSJoshua M. Clulow 	} else {
36151706d6cSJoshua M. Clulow 		return (0);
36251706d6cSJoshua M. Clulow 	}
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate static int
partcmp64(const void * one,const void * two)3667c478bd9Sstevel@tonic-gate partcmp64(const void *one, const void *two)
3677c478bd9Sstevel@tonic-gate {
36851706d6cSJoshua M. Clulow 	dk_part_t *p1 = *(dk_part_t **)one;
36951706d6cSJoshua M. Clulow 	dk_part_t *p2 = *(dk_part_t **)two;
3707c478bd9Sstevel@tonic-gate 
37151706d6cSJoshua M. Clulow 	if (p1->p_start > p2->p_start) {
37251706d6cSJoshua M. Clulow 		return (1);
37351706d6cSJoshua M. Clulow 	} else if (p1->p_start < p2->p_start) {
37451706d6cSJoshua M. Clulow 		return (-1);
37551706d6cSJoshua M. Clulow 	} else {
37651706d6cSJoshua M. Clulow 		return (0);
37751706d6cSJoshua M. Clulow 	}
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate /*
3817c478bd9Sstevel@tonic-gate  * prtvtoc(): Read and print a VTOC.
3827c478bd9Sstevel@tonic-gate  */
3837c478bd9Sstevel@tonic-gate static int
prtvtoc(char * devname)3847c478bd9Sstevel@tonic-gate prtvtoc(char *devname)
3857c478bd9Sstevel@tonic-gate {
38651706d6cSJoshua M. Clulow 	int fd;
387*03074a12SKlaus Ziegler 	int idx = 0;
38851706d6cSJoshua M. Clulow 	freemap_t *freemap;
38951706d6cSJoshua M. Clulow 	struct stat sb;
39051706d6cSJoshua M. Clulow 	struct extvtoc vtoc;
39151706d6cSJoshua M. Clulow 	int geo;
39251706d6cSJoshua M. Clulow 	struct dk_geom geom;
39351706d6cSJoshua M. Clulow 	char *name;
39451706d6cSJoshua M. Clulow 	int newvtoc = 0;
39551706d6cSJoshua M. Clulow 	struct dk_gpt *efi;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	name = getfullrawname(devname);
39851706d6cSJoshua M. Clulow 	if (name == NULL) {
39951706d6cSJoshua M. Clulow 		warnx("%s: internal administrative call (getfullrawname) "
40051706d6cSJoshua M. Clulow 		    "failed", devname);
40151706d6cSJoshua M. Clulow 		return (-1);
40251706d6cSJoshua M. Clulow 	}
4037c478bd9Sstevel@tonic-gate 	if (strcmp(name, "") == 0)
4047c478bd9Sstevel@tonic-gate 		name = devname;
40551706d6cSJoshua M. Clulow 	if ((fd = open(name, O_NONBLOCK|O_RDONLY)) < 0) {
40651706d6cSJoshua M. Clulow 		warn("%s: failed to open device", name);
40751706d6cSJoshua M. Clulow 		return (-1);
40851706d6cSJoshua M. Clulow 	}
40951706d6cSJoshua M. Clulow 	if (fstat(fd, &sb) < 0) {
41051706d6cSJoshua M. Clulow 		warn("%s: failed to stat device", name);
41151706d6cSJoshua M. Clulow 		return (-1);
41251706d6cSJoshua M. Clulow 	}
41351706d6cSJoshua M. Clulow 	if ((sb.st_mode & S_IFMT) != S_IFCHR) {
41451706d6cSJoshua M. Clulow 		warnx("%s: Not a raw device", name);
41551706d6cSJoshua M. Clulow 		return (-1);
41651706d6cSJoshua M. Clulow 	}
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	geo = (readgeom(fd, name, &geom) == 0);
4197c478bd9Sstevel@tonic-gate 	if (geo) {
4207c478bd9Sstevel@tonic-gate 		if ((idx = readvtoc(fd, name, &vtoc)) == VT_ENOTSUP) {
4217c478bd9Sstevel@tonic-gate 			idx = (readefi(fd, name, &efi) == 0);
4227c478bd9Sstevel@tonic-gate 			newvtoc = 1;
42351706d6cSJoshua M. Clulow 		} else {
4247c478bd9Sstevel@tonic-gate 			idx = (idx == 0);
42551706d6cSJoshua M. Clulow 		}
4267c478bd9Sstevel@tonic-gate 	}
4277c478bd9Sstevel@tonic-gate 	(void) close(fd);
4287c478bd9Sstevel@tonic-gate 	if ((!geo) || (!idx))
4297c478bd9Sstevel@tonic-gate 		return (-1);
4307c478bd9Sstevel@tonic-gate 	if (!newvtoc)
4317c478bd9Sstevel@tonic-gate 		freemap = findfree(&geom, &vtoc);
4327c478bd9Sstevel@tonic-gate 	else
4337c478bd9Sstevel@tonic-gate 		freemap = findfree64(efi);
4347c478bd9Sstevel@tonic-gate 	if (fflag) {
4357c478bd9Sstevel@tonic-gate 		if (!newvtoc)
4367c478bd9Sstevel@tonic-gate 			putfree(&vtoc, freemap);
4377c478bd9Sstevel@tonic-gate 		else
4387c478bd9Sstevel@tonic-gate 			putfree64(efi, freemap);
4397c478bd9Sstevel@tonic-gate 	} else {
44051706d6cSJoshua M. Clulow 		if (!newvtoc) {
4417c478bd9Sstevel@tonic-gate 			puttable(&geom, &vtoc, freemap, devname,
4427c478bd9Sstevel@tonic-gate 			    getmntpt(major(sb.st_rdev),
4437c478bd9Sstevel@tonic-gate 			    noparttn(minor(sb.st_rdev))));
44451706d6cSJoshua M. Clulow 		} else {
4457c478bd9Sstevel@tonic-gate 			puttable64(efi, freemap, devname,
4467c478bd9Sstevel@tonic-gate 			    getmntpt(major(sb.st_rdev),
4477c478bd9Sstevel@tonic-gate 			    noparttn(minor(sb.st_rdev))));
44851706d6cSJoshua M. Clulow 		}
4497c478bd9Sstevel@tonic-gate 	}
4507c478bd9Sstevel@tonic-gate 	if (newvtoc)
4517c478bd9Sstevel@tonic-gate 		efi_free(efi);
4527c478bd9Sstevel@tonic-gate 	return (0);
4537c478bd9Sstevel@tonic-gate }
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate /*
4567c478bd9Sstevel@tonic-gate  * putfree():
4577c478bd9Sstevel@tonic-gate  *
4587c478bd9Sstevel@tonic-gate  * Print shell assignments for disk free space. FREE_START and FREE_SIZE
4597c478bd9Sstevel@tonic-gate  * represent the starting block and number of blocks of the first chunk
4607c478bd9Sstevel@tonic-gate  * of free space. FREE_PART lists the unassigned partitions.
4617c478bd9Sstevel@tonic-gate  */
4627c478bd9Sstevel@tonic-gate static void
putfree(struct extvtoc * vtoc,freemap_t * freemap)463342440ecSPrasad Singamsetty putfree(struct extvtoc *vtoc, freemap_t *freemap)
4647c478bd9Sstevel@tonic-gate {
4657c478bd9Sstevel@tonic-gate 	freemap_t *freeidx;
4667c478bd9Sstevel@tonic-gate 	ushort_t idx;
4677c478bd9Sstevel@tonic-gate 	int free_count = 0;
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	for (freeidx = freemap; freeidx->fr_size; ++freeidx)
4707c478bd9Sstevel@tonic-gate 		free_count++;
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	(void) printf("FREE_START=%llu FREE_SIZE=%llu FREE_COUNT=%d FREE_PART=",
4737c478bd9Sstevel@tonic-gate 	    freemap->fr_start, freemap->fr_size, free_count);
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	for (idx = 0; idx < vtoc->v_nparts; ++idx) {
4767c478bd9Sstevel@tonic-gate 		if (vtoc->v_part[idx].p_size == 0 && idx != 2)
4777c478bd9Sstevel@tonic-gate 			(void) printf("%x", idx);
4787c478bd9Sstevel@tonic-gate 	}
4797c478bd9Sstevel@tonic-gate 	(void) printf("\n");
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate static void
putfree64(struct dk_gpt * efi,freemap_t * freemap)4837c478bd9Sstevel@tonic-gate putfree64(struct dk_gpt *efi, freemap_t *freemap)
4847c478bd9Sstevel@tonic-gate {
4857c478bd9Sstevel@tonic-gate 	freemap_t *freeidx;
4867c478bd9Sstevel@tonic-gate 	ushort_t idx;
4877c478bd9Sstevel@tonic-gate 	int free_count = 0;
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	for (freeidx = freemap; freeidx->fr_size; ++freeidx)
4907c478bd9Sstevel@tonic-gate 		free_count++;
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	(void) printf("FREE_START=%llu FREE_SIZE=%llu FREE_COUNT=%d FREE_PART=",
4937c478bd9Sstevel@tonic-gate 	    freemap->fr_start, freemap->fr_size, free_count);
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 	for (idx = 0; idx < efi->efi_nparts; ++idx) {
4967c478bd9Sstevel@tonic-gate 		if (efi->efi_parts[idx].p_size == 0 && idx != 2)
4977c478bd9Sstevel@tonic-gate 			(void) printf("%x", idx);
4987c478bd9Sstevel@tonic-gate 	}
4997c478bd9Sstevel@tonic-gate 	(void) printf("\n");
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate 
50251706d6cSJoshua M. Clulow static void
print_table_header()50351706d6cSJoshua M. Clulow print_table_header()
50451706d6cSJoshua M. Clulow {
50551706d6cSJoshua M. Clulow 	(void) printf("*                            First       Sector"
50651706d6cSJoshua M. Clulow 	    "      Last\n");
50751706d6cSJoshua M. Clulow 	(void) printf("* Partition  Tag  Flags      Sector       Count"
50851706d6cSJoshua M. Clulow 	    "      Sector  Mount Directory\n");
50951706d6cSJoshua M. Clulow }
51051706d6cSJoshua M. Clulow 
51151706d6cSJoshua M. Clulow static void
print_table_row(uint_t partition,uint_t tag,uint_t flag,u_longlong_t first_sector,u_longlong_t sector_count,u_longlong_t last_sector,const char * mount_dir)51251706d6cSJoshua M. Clulow print_table_row(uint_t partition, uint_t tag, uint_t flag,
51351706d6cSJoshua M. Clulow     u_longlong_t first_sector, u_longlong_t sector_count,
51451706d6cSJoshua M. Clulow     u_longlong_t last_sector, const char *mount_dir)
51551706d6cSJoshua M. Clulow {
51651706d6cSJoshua M. Clulow 	(void) printf("  %6u   %4u    %02x  %11llu %11llu %11llu",
51751706d6cSJoshua M. Clulow 	    partition, tag, flag, first_sector, sector_count, last_sector);
51851706d6cSJoshua M. Clulow 	if (mount_dir != NULL) {
51951706d6cSJoshua M. Clulow 		(void) printf("   %s", mount_dir);
52051706d6cSJoshua M. Clulow 	}
52151706d6cSJoshua M. Clulow 	(void) printf("\n");
52251706d6cSJoshua M. Clulow }
52351706d6cSJoshua M. Clulow 
52451706d6cSJoshua M. Clulow static void
print_freemap(freemap_t * freemap)52551706d6cSJoshua M. Clulow print_freemap(freemap_t *freemap)
52651706d6cSJoshua M. Clulow {
52751706d6cSJoshua M. Clulow 	if (freemap->fr_size == 0) {
52851706d6cSJoshua M. Clulow 		/*
52951706d6cSJoshua M. Clulow 		 * The freemap is completely empty, so do not print the header.
53051706d6cSJoshua M. Clulow 		 */
53151706d6cSJoshua M. Clulow 		return;
53251706d6cSJoshua M. Clulow 	}
53351706d6cSJoshua M. Clulow 
53451706d6cSJoshua M. Clulow 	(void) printf("* Unallocated space:\n"
53551706d6cSJoshua M. Clulow 	    "*         First       Sector      Last\n"
53651706d6cSJoshua M. Clulow 	    "*         Sector       Count      Sector\n");
53751706d6cSJoshua M. Clulow 
53851706d6cSJoshua M. Clulow 	do {
53951706d6cSJoshua M. Clulow 		(void) printf("*   %11llu %11llu %11llu\n",
54051706d6cSJoshua M. Clulow 		    freemap->fr_start, freemap->fr_size,
54151706d6cSJoshua M. Clulow 		    freemap->fr_size + freemap->fr_start - 1);
54251706d6cSJoshua M. Clulow 	} while ((++freemap)->fr_size != 0);
54351706d6cSJoshua M. Clulow 
54451706d6cSJoshua M. Clulow 	(void) printf("*\n");
54551706d6cSJoshua M. Clulow }
54651706d6cSJoshua M. Clulow 
5477c478bd9Sstevel@tonic-gate /*
5487c478bd9Sstevel@tonic-gate  * puttable(): Print a human-readable VTOC.
5497c478bd9Sstevel@tonic-gate  */
5507c478bd9Sstevel@tonic-gate static void
puttable(struct dk_geom * geom,struct extvtoc * vtoc,freemap_t * freemap,char * name,char ** mtab)551342440ecSPrasad Singamsetty puttable(struct dk_geom *geom, struct extvtoc *vtoc, freemap_t *freemap,
5527c478bd9Sstevel@tonic-gate     char *name, char **mtab)
5537c478bd9Sstevel@tonic-gate {
55451706d6cSJoshua M. Clulow 	ushort_t idx;
55551706d6cSJoshua M. Clulow 	ulong_t cylsize;
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 	cylsize = (geom->dkg_nsect) * (geom->dkg_nhead);
5587c478bd9Sstevel@tonic-gate 	if (!hflag && !sflag) {
55983a62956SJason King 		u_longlong_t asectors = (u_longlong_t)cylsize * geom->dkg_ncyl;
56083a62956SJason King 		u_longlong_t sectors = (u_longlong_t)cylsize * geom->dkg_pcyl;
56183a62956SJason King 
5627c478bd9Sstevel@tonic-gate 		(void) printf("* %s", name);
56351706d6cSJoshua M. Clulow 		if (vtoc->v_volume[0] != '\0')
5647c478bd9Sstevel@tonic-gate 			(void) printf(" (volume \"%.8s\")", vtoc->v_volume);
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 		(void) printf(" partition map\n");
5677c478bd9Sstevel@tonic-gate 		(void) printf("*\n* Dimensions:\n");
56851706d6cSJoshua M. Clulow 		(void) printf("* %11u bytes/sector\n", vtoc->v_sectorsz);
56951706d6cSJoshua M. Clulow 		(void) printf("* %11u sectors/track\n", geom->dkg_nsect);
57051706d6cSJoshua M. Clulow 		(void) printf("* %11u tracks/cylinder\n", geom->dkg_nhead);
57151706d6cSJoshua M. Clulow 		(void) printf("* %11lu sectors/cylinder\n", cylsize);
57251706d6cSJoshua M. Clulow 		(void) printf("* %11u cylinders\n", geom->dkg_pcyl);
57351706d6cSJoshua M. Clulow 		(void) printf("* %11u accessible cylinders\n", geom->dkg_ncyl);
57483a62956SJason King 		(void) printf("* %11llu sectors\n", sectors);
57583a62956SJason King 		(void) printf("* %11llu accessible sectors\n", asectors);
5767c478bd9Sstevel@tonic-gate 		(void) printf("*\n* Flags:\n");
5777c478bd9Sstevel@tonic-gate 		(void) printf("*   1: unmountable\n");
5787c478bd9Sstevel@tonic-gate 		(void) printf("*  10: read-only\n*\n");
5797c478bd9Sstevel@tonic-gate 
58051706d6cSJoshua M. Clulow 		print_freemap(freemap);
5817c478bd9Sstevel@tonic-gate 	}
58251706d6cSJoshua M. Clulow 
58351706d6cSJoshua M. Clulow 	if (!hflag) {
58451706d6cSJoshua M. Clulow 		print_table_header();
5857c478bd9Sstevel@tonic-gate 	}
58651706d6cSJoshua M. Clulow 
5877c478bd9Sstevel@tonic-gate 	for (idx = 0; idx < vtoc->v_nparts; ++idx) {
58851706d6cSJoshua M. Clulow 		const char *mount_dir = NULL;
58951706d6cSJoshua M. Clulow 		struct extpartition *p = &vtoc->v_part[idx];
59051706d6cSJoshua M. Clulow 
59151706d6cSJoshua M. Clulow 		if (p->p_size == 0)
5927c478bd9Sstevel@tonic-gate 			continue;
59351706d6cSJoshua M. Clulow 
59451706d6cSJoshua M. Clulow 		if (mtab != NULL) {
59551706d6cSJoshua M. Clulow 			mount_dir = mtab[idx];
59651706d6cSJoshua M. Clulow 		}
59751706d6cSJoshua M. Clulow 
59851706d6cSJoshua M. Clulow 		print_table_row(idx, p->p_tag, p->p_flag, p->p_start,
59951706d6cSJoshua M. Clulow 		    p->p_size, p->p_start + p->p_size - 1, mount_dir);
6007c478bd9Sstevel@tonic-gate 	}
6017c478bd9Sstevel@tonic-gate }
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate /*
6047c478bd9Sstevel@tonic-gate  * puttable(): Print a human-readable VTOC.
6057c478bd9Sstevel@tonic-gate  */
6067c478bd9Sstevel@tonic-gate static void
puttable64(struct dk_gpt * efi,freemap_t * freemap,char * name,char ** mtab)60751706d6cSJoshua M. Clulow puttable64(struct dk_gpt *efi, freemap_t *freemap, char *name, char **mtab)
6087c478bd9Sstevel@tonic-gate {
6097c478bd9Sstevel@tonic-gate 	if (!hflag && !sflag) {
6107c478bd9Sstevel@tonic-gate 		(void) printf("* %s", name);
61151706d6cSJoshua M. Clulow 		for (uint_t idx = 0; idx < efi->efi_nparts; idx++) {
61251706d6cSJoshua M. Clulow 			if (efi->efi_parts[idx].p_tag == V_RESERVED &&
61351706d6cSJoshua M. Clulow 			    efi->efi_parts[idx].p_name[0] != '\0') {
61451706d6cSJoshua M. Clulow 				(void) printf(" (volume \"%.8s\")",
6157c478bd9Sstevel@tonic-gate 				    efi->efi_parts[idx].p_name);
61651706d6cSJoshua M. Clulow 			}
61751706d6cSJoshua M. Clulow 		}
6187c478bd9Sstevel@tonic-gate 		(void) printf(" partition map\n");
6197c478bd9Sstevel@tonic-gate 		(void) printf("*\n* Dimensions:\n");
62051706d6cSJoshua M. Clulow 		(void) printf("* %11u bytes/sector\n", efi->efi_lbasize);
62151706d6cSJoshua M. Clulow 		(void) printf("* %11llu sectors\n", efi->efi_last_lba + 1);
62251706d6cSJoshua M. Clulow 		(void) printf("* %11llu accessible sectors\n",
6237c478bd9Sstevel@tonic-gate 		    efi->efi_last_u_lba - efi->efi_first_u_lba + 1);
6247c478bd9Sstevel@tonic-gate 		(void) printf("*\n* Flags:\n");
6257c478bd9Sstevel@tonic-gate 		(void) printf("*   1: unmountable\n");
6267c478bd9Sstevel@tonic-gate 		(void) printf("*  10: read-only\n*\n");
6277c478bd9Sstevel@tonic-gate 
62851706d6cSJoshua M. Clulow 		print_freemap(freemap);
6297c478bd9Sstevel@tonic-gate 	}
63051706d6cSJoshua M. Clulow 
63151706d6cSJoshua M. Clulow 	if (!hflag) {
63251706d6cSJoshua M. Clulow 		print_table_header();
6337c478bd9Sstevel@tonic-gate 	}
63451706d6cSJoshua M. Clulow 
63551706d6cSJoshua M. Clulow 	for (uint_t idx = 0; idx < efi->efi_nparts; ++idx) {
63651706d6cSJoshua M. Clulow 		const char *mount_dir = NULL;
63751706d6cSJoshua M. Clulow 		dk_part_t *p = &efi->efi_parts[idx];
63851706d6cSJoshua M. Clulow 
63951706d6cSJoshua M. Clulow 		if (p->p_size == 0)
64051706d6cSJoshua M. Clulow 			continue;
64151706d6cSJoshua M. Clulow 
64251706d6cSJoshua M. Clulow 		if (idx < 7 && mtab != NULL) {
64351706d6cSJoshua M. Clulow 			mount_dir = mtab[idx];
64451706d6cSJoshua M. Clulow 		}
64551706d6cSJoshua M. Clulow 
64651706d6cSJoshua M. Clulow 		print_table_row(idx, p->p_tag, p->p_flag, p->p_start,
64751706d6cSJoshua M. Clulow 		    p->p_size, p->p_start + p->p_size - 1, mount_dir);
6487c478bd9Sstevel@tonic-gate 	}
6497c478bd9Sstevel@tonic-gate }
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate /*
6527c478bd9Sstevel@tonic-gate  * readgeom(): Read the disk geometry.
6537c478bd9Sstevel@tonic-gate  */
6547c478bd9Sstevel@tonic-gate static int
readgeom(int fd,char * name,struct dk_geom * geom)6557c478bd9Sstevel@tonic-gate readgeom(int fd, char *name, struct dk_geom *geom)
6567c478bd9Sstevel@tonic-gate {
65751706d6cSJoshua M. Clulow 	if (ioctl(fd, DKIOCGGEOM, geom) < 0) {
65851706d6cSJoshua M. Clulow 		if (errno != ENOTSUP) {
65951706d6cSJoshua M. Clulow 			warnx("%s: Unable to read Disk geometry errno = 0x%x",
66051706d6cSJoshua M. Clulow 			    name, errno);
66151706d6cSJoshua M. Clulow 			return (-1);
66251706d6cSJoshua M. Clulow 		}
66351706d6cSJoshua M. Clulow 
6647c478bd9Sstevel@tonic-gate 		(void) memset(geom, 0, sizeof (struct dk_geom));
6657c478bd9Sstevel@tonic-gate 	}
66651706d6cSJoshua M. Clulow 
6677c478bd9Sstevel@tonic-gate 	return (0);
6687c478bd9Sstevel@tonic-gate }
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate /*
6717c478bd9Sstevel@tonic-gate  * readvtoc(): Read a partition map.
6727c478bd9Sstevel@tonic-gate  */
6737c478bd9Sstevel@tonic-gate static int
readvtoc(int fd,char * name,struct extvtoc * vtoc)674342440ecSPrasad Singamsetty readvtoc(int fd, char *name, struct extvtoc *vtoc)
6757c478bd9Sstevel@tonic-gate {
67651706d6cSJoshua M. Clulow 	int retval;
6777c478bd9Sstevel@tonic-gate 
678342440ecSPrasad Singamsetty 	if ((retval = read_extvtoc(fd, vtoc)) >= 0)
6797c478bd9Sstevel@tonic-gate 		return (0);
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	switch (retval) {
68251706d6cSJoshua M. Clulow 	case VT_EIO:
68351706d6cSJoshua M. Clulow 		warnx("%s: Unable to read VTOC", name);
68451706d6cSJoshua M. Clulow 		return (-1);
68551706d6cSJoshua M. Clulow 	case VT_EINVAL:
68651706d6cSJoshua M. Clulow 		warnx("%s: Invalid VTOC", name);
68751706d6cSJoshua M. Clulow 		return (-1);
68851706d6cSJoshua M. Clulow 	case VT_ERROR:
68951706d6cSJoshua M. Clulow 		warnx("%s: Unknown problem reading VTOC", name);
69051706d6cSJoshua M. Clulow 		return (-1);
6917c478bd9Sstevel@tonic-gate 	}
69251706d6cSJoshua M. Clulow 
6937c478bd9Sstevel@tonic-gate 	return (retval);
6947c478bd9Sstevel@tonic-gate }
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate /*
6977c478bd9Sstevel@tonic-gate  * readefi(): Read a partition map.
6987c478bd9Sstevel@tonic-gate  */
6997c478bd9Sstevel@tonic-gate static int
readefi(int fd,char * name,struct dk_gpt ** efi)7007c478bd9Sstevel@tonic-gate readefi(int fd, char *name, struct dk_gpt **efi)
7017c478bd9Sstevel@tonic-gate {
7027c478bd9Sstevel@tonic-gate 	int	retval;
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	if ((retval = efi_alloc_and_read(fd, efi)) >= 0)
7057c478bd9Sstevel@tonic-gate 		return (0);
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 	switch (retval) {
70851706d6cSJoshua M. Clulow 	case VT_EIO:
70951706d6cSJoshua M. Clulow 		warnx("%s: Unable to read VTOC", name);
71051706d6cSJoshua M. Clulow 		return (-1);
71151706d6cSJoshua M. Clulow 	case VT_EINVAL:
71251706d6cSJoshua M. Clulow 		warnx("%s: Invalid VTOC", name);
71351706d6cSJoshua M. Clulow 		return (-1);
71451706d6cSJoshua M. Clulow 	case VT_ERROR:
71551706d6cSJoshua M. Clulow 		warnx("%s: Unknown problem reading VTOC", name);
71651706d6cSJoshua M. Clulow 		return (-1);
7177c478bd9Sstevel@tonic-gate 	}
71851706d6cSJoshua M. Clulow 
7197c478bd9Sstevel@tonic-gate 	return (retval);
7207c478bd9Sstevel@tonic-gate }
7217c478bd9Sstevel@tonic-gate 
72251706d6cSJoshua M. Clulow static void
memory_err(size_t l,int e,const char * fname)72351706d6cSJoshua M. Clulow memory_err(size_t l, int e, const char *fname)
72451706d6cSJoshua M. Clulow {
72551706d6cSJoshua M. Clulow 	const char *reason;
72651706d6cSJoshua M. Clulow 
72751706d6cSJoshua M. Clulow 	switch (e) {
72851706d6cSJoshua M. Clulow 	case EAGAIN:
72951706d6cSJoshua M. Clulow 		reason = "not enough memory was available, please try again";
73051706d6cSJoshua M. Clulow 		break;
73151706d6cSJoshua M. Clulow 	case ENOMEM:
73251706d6cSJoshua M. Clulow 		reason = "allocation size was too large";
73351706d6cSJoshua M. Clulow 		break;
73451706d6cSJoshua M. Clulow 	default:
73551706d6cSJoshua M. Clulow 		reason = strerror(e);
73651706d6cSJoshua M. Clulow 		break;
73751706d6cSJoshua M. Clulow 	}
73851706d6cSJoshua M. Clulow 
73951706d6cSJoshua M. Clulow 	errx(EXIT_FAILURE, "%s: failed to allocate %llu bytes of memory: %s",
74051706d6cSJoshua M. Clulow 	    fname, (u_longlong_t)l, reason);
74151706d6cSJoshua M. Clulow }
74251706d6cSJoshua M. Clulow 
74351706d6cSJoshua M. Clulow static void *
safe_calloc(const char * fname,size_t nelem,size_t elsize)74451706d6cSJoshua M. Clulow safe_calloc(const char *fname, size_t nelem, size_t elsize)
74551706d6cSJoshua M. Clulow {
74651706d6cSJoshua M. Clulow 	void *r;
74751706d6cSJoshua M. Clulow 
74851706d6cSJoshua M. Clulow 	if ((r = calloc(nelem, elsize)) == NULL) {
74951706d6cSJoshua M. Clulow 		memory_err(nelem * elsize, errno, fname);
75051706d6cSJoshua M. Clulow 	}
75151706d6cSJoshua M. Clulow 
75251706d6cSJoshua M. Clulow 	return (r);
75351706d6cSJoshua M. Clulow }
75451706d6cSJoshua M. Clulow 
7557c478bd9Sstevel@tonic-gate static char *
safe_strdup(const char * fname,const char * str)75651706d6cSJoshua M. Clulow safe_strdup(const char *fname, const char *str)
7577c478bd9Sstevel@tonic-gate {
75851706d6cSJoshua M. Clulow 	size_t l = strlen(str);
75951706d6cSJoshua M. Clulow 	char *r;
76051706d6cSJoshua M. Clulow 
76151706d6cSJoshua M. Clulow 	if ((r = strndup(str, l)) == NULL) {
76251706d6cSJoshua M. Clulow 		memory_err(l + 1, errno, fname);
7637c478bd9Sstevel@tonic-gate 	}
76451706d6cSJoshua M. Clulow 
76551706d6cSJoshua M. Clulow 	return (r);
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate /*
7697c478bd9Sstevel@tonic-gate  * usage(): Print a helpful message and exit.
7707c478bd9Sstevel@tonic-gate  */
7717c478bd9Sstevel@tonic-gate static void
usage()7727c478bd9Sstevel@tonic-gate usage()
7737c478bd9Sstevel@tonic-gate {
7747c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "Usage:\t%s [ -fhs ] [ -t fstab ] [ -m mnttab ] "
77551706d6cSJoshua M. Clulow 	    "rawdisk ...\n", getprogname());
7767c478bd9Sstevel@tonic-gate 	exit(1);
7777c478bd9Sstevel@tonic-gate }
778