| /* |
| * 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 <stdio.h> |
| #include <fcntl.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <sys/dkio.h> |
| #include <sys/efi_partition.h> |
| #include <sys/vtoc.h> |
| #include <sys/mkdev.h> |
| #include <errno.h> |
| |
| #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); |
| } |