/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Two output fields under the -i option will always be * output as zero, since they are not supported by Sun: * Software version, and * Drive id number. * AT&T filled these 2 fields with data from their "pdsector", * which Sun doesn't support per se. */ #include #include #include #include #include #include #include #include #include #include #include #include #define DRERR 2 #define OPENERR 2 /* * Standard I/O file descriptors. */ #define STDOUT 1 /* Standard output */ #define STDERR 2 /* Standard error */ static void partinfo(int fd, char *device); static void devinfo(struct dk_geom *geom, int fd, char *device); static int readvtoc(int fd, char *name, struct extvtoc *vtoc); static int warn(char *what, char *why); static void usage(void); int main(int argc, char **argv) { struct dk_geom geom; int errflg, iflg, pflg, fd, c; char *device; iflg = 0; pflg = 0; errflg = 0; while ((c = getopt(argc, argv, "i:p:")) != EOF) { switch (c) { case 'i': iflg++; device = optarg; break; case 'p': pflg++; device = optarg; break; case '?': errflg++; break; default: errflg++; break; } if (errflg) usage(); } if ((optind > argc) || (optind == 1) || (pflg && iflg)) usage(); if ((fd = open(device, O_RDONLY)) < 0) { (void) fprintf(stderr, "devinfo: %s: %s\n", device, strerror(errno)); exit(OPENERR); } if (iflg) { if (ioctl(fd, DKIOCGGEOM, &geom) == -1) { if (errno == ENOTSUP) { (void) warn(device, "This operation is not supported on EFI labeled devices"); } else { (void) warn(device, "Unable to read Disk geometry"); } (void) close(fd); exit(DRERR); } devinfo(&geom, fd, device); } if (pflg) partinfo(fd, device); (void) close(fd); return (0); } static void partinfo(int fd, char *device) { int i; int slice; major_t maj; minor_t min; struct stat64 statbuf; struct extvtoc vtdata; struct dk_gpt *efi; i = stat64(device, &statbuf); if (i < 0) exit(DRERR); maj = major(statbuf.st_rdev); min = minor(statbuf.st_rdev); if ((slice = readvtoc(fd, device, &vtdata)) >= 0) { (void) printf("%s\t%0lx\t%0lx\t%llu\t%llu\t%x\t%x\n", device, maj, min, vtdata.v_part[slice].p_start, vtdata.v_part[slice].p_size, vtdata.v_part[slice].p_flag, vtdata.v_part[slice].p_tag); } else if ((slice == VT_ENOTSUP) && (slice = efi_alloc_and_read(fd, &efi)) >= 0) { (void) printf("%s\t%lx\t%lx\t%lld\t%lld\t%hx\t%hx\n", device, maj, min, efi->efi_parts[slice].p_start, efi->efi_parts[slice].p_size, efi->efi_parts[slice].p_flag, efi->efi_parts[slice].p_tag); } else { exit(DRERR); } } static void devinfo(struct dk_geom *geom, int fd, char *device) { int i; unsigned int nopartitions, sectorcyl, bytes; struct extvtoc vtdata; /* * unsigned int version = 0; * unsigned int driveid = 0; */ nopartitions = 0; sectorcyl = 0; bytes = 0; if (readvtoc(fd, device, &vtdata) < 0) exit(DRERR); sectorcyl = geom->dkg_nhead * geom->dkg_nsect; bytes = vtdata.v_sectorsz; /* * these are not supported by Sun. * * driveid = osect0->newsect0.pdinfo.driveid; * version = osect0->newsect0.pdinfo.version; */ for (i = 0; i < V_NUMPAR; i++) { if (vtdata.v_part[i].p_size != 0x00) nopartitions++; } /* * (void) printf("%s %0x %0x %d %d %d\n", * device, version, driveid, sectorcyl, bytes, nopartitions); */ (void) printf("%s %0x %0x %d %d %d\n", device, 0, 0, sectorcyl, bytes, nopartitions); } /* * readvtoc() * * Read a partition map. */ static int readvtoc(int fd, char *name, struct extvtoc *vtoc) { int retval; retval = read_extvtoc(fd, vtoc); switch (retval) { case (VT_ERROR): return (warn(name, strerror(errno))); case (VT_EIO): return (warn(name, "I/O error accessing VTOC")); case (VT_EINVAL): return (warn(name, "Invalid field in VTOC")); } return (retval); } /* * warn() * * Print an error message. Always returns -1. */ static int warn(char *what, char *why) { static char myname[] = "devinfo"; static char between[] = ": "; static char after[] = "\n"; (void) write(STDERR, myname, (uint_t)strlen(myname)); (void) write(STDERR, between, (uint_t)strlen(between)); (void) write(STDERR, what, (uint_t)strlen(what)); (void) write(STDERR, between, (uint_t)strlen(between)); (void) write(STDERR, why, (uint_t)strlen(why)); (void) write(STDERR, after, (uint_t)strlen(after)); return (-1); } static void usage(void) { (void) fprintf(stderr, "Usage: devinfo -p device\n" " devinfo -i device \n"); exit(2); }