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