Home | History | Annotate | Download | only in devinfo
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     28 /*	  All Rights Reserved  	*/
     29 
     30 /*
     31  *	Two output fields under the -i option will always be
     32  *	output as zero, since they are not supported by Sun:
     33  *		Software version, and
     34  *		Drive id number.
     35  *	AT&T filled these 2 fields with data from their "pdsector",
     36  *	which Sun doesn't support per se.
     37  */
     38 
     39 
     40 #include <stdio.h>
     41 #include <fcntl.h>
     42 #include <stdlib.h>
     43 #include <unistd.h>
     44 #include <string.h>
     45 #include <sys/types.h>
     46 #include <sys/stat.h>
     47 #include <sys/dkio.h>
     48 #include <sys/efi_partition.h>
     49 #include <sys/vtoc.h>
     50 #include <sys/mkdev.h>
     51 #include <errno.h>
     52 
     53 #define	DRERR	2
     54 #define	OPENERR	2
     55 
     56 /*
     57  * Standard I/O file descriptors.
     58  */
     59 #define	STDOUT	1		/* Standard output */
     60 #define	STDERR	2		/* Standard error */
     61 
     62 static	void	partinfo(int fd, char *device);
     63 static	void	devinfo(struct dk_geom *geom, int fd, char *device);
     64 static	int	readvtoc(int fd, char *name, struct extvtoc *vtoc);
     65 static	int	warn(char *what, char *why);
     66 static	void	usage(void);
     67 
     68 int
     69 main(int argc, char **argv)
     70 {
     71 	struct dk_geom  geom;
     72 	int errflg, iflg, pflg, fd, c;
     73 	char *device;
     74 
     75 	iflg = 0;
     76 	pflg = 0;
     77 	errflg = 0;
     78 	while ((c = getopt(argc, argv, "i:p:")) != EOF) {
     79 		switch (c) {
     80 			case 'i':
     81 				iflg++;
     82 				device = optarg;
     83 				break;
     84 			case 'p':
     85 				pflg++;
     86 				device = optarg;
     87 				break;
     88 			case '?':
     89 				errflg++;
     90 				break;
     91 			default:
     92 				errflg++;
     93 				break;
     94 		}
     95 		if (errflg)
     96 			usage();
     97 	}
     98 	if ((optind > argc) || (optind == 1) || (pflg && iflg))
     99 		usage();
    100 
    101 	if ((fd = open(device, O_RDONLY)) < 0) {
    102 		(void) fprintf(stderr, "devinfo: %s: %s\n",
    103 			device, strerror(errno));
    104 		exit(OPENERR);
    105 	}
    106 
    107 	if (iflg) {
    108 		if (ioctl(fd, DKIOCGGEOM, &geom) == -1) {
    109 			if (errno == ENOTSUP) {
    110 				(void) warn(device,
    111 "This operation is not supported on EFI labeled devices");
    112 			} else {
    113 				(void) warn(device,
    114 "Unable to read Disk geometry");
    115 			}
    116 			(void) close(fd);
    117 			exit(DRERR);
    118 		}
    119 		devinfo(&geom, fd, device);
    120 	}
    121 	if (pflg)
    122 		partinfo(fd, device);
    123 	(void) close(fd);
    124 	return (0);
    125 }
    126 
    127 static void
    128 partinfo(int fd, char *device)
    129 {
    130 	int i;
    131 	int	slice;
    132 	major_t maj;
    133 	minor_t min;
    134 	struct stat64 statbuf;
    135 	struct extvtoc vtdata;
    136 	struct dk_gpt *efi;
    137 
    138 	i = stat64(device, &statbuf);
    139 	if (i < 0)
    140 		exit(DRERR);
    141 	maj = major(statbuf.st_rdev);
    142 	min = minor(statbuf.st_rdev);
    143 
    144 	if ((slice = readvtoc(fd, device, &vtdata)) >= 0) {
    145 
    146 		(void) printf("%s\t%0lx\t%0lx\t%llu\t%llu\t%x\t%x\n",
    147 			device, maj, min,
    148 			vtdata.v_part[slice].p_start,
    149 			vtdata.v_part[slice].p_size,
    150 			vtdata.v_part[slice].p_flag,
    151 			vtdata.v_part[slice].p_tag);
    152 	} else if ((slice == VT_ENOTSUP) &&
    153 	    (slice = efi_alloc_and_read(fd, &efi)) >= 0) {
    154 		(void) printf("%s\t%lx\t%lx\t%lld\t%lld\t%hx\t%hx\n",
    155 			device, maj, min,
    156 			efi->efi_parts[slice].p_start,
    157 			efi->efi_parts[slice].p_size,
    158 			efi->efi_parts[slice].p_flag,
    159 			efi->efi_parts[slice].p_tag);
    160 	} else {
    161 		exit(DRERR);
    162 	}
    163 }
    164 
    165 static void
    166 devinfo(struct dk_geom *geom, int fd, char *device)
    167 {
    168 	int i;
    169 	unsigned int nopartitions, sectorcyl, bytes;
    170 	struct extvtoc vtdata;
    171 /*
    172  *	unsigned int version = 0;
    173  *	unsigned int driveid = 0;
    174  */
    175 
    176 	nopartitions = 0;
    177 	sectorcyl = 0;
    178 	bytes = 0;
    179 
    180 	if (readvtoc(fd, device, &vtdata) < 0)
    181 		exit(DRERR);
    182 	sectorcyl = geom->dkg_nhead  *  geom->dkg_nsect;
    183 	bytes = vtdata.v_sectorsz;
    184 /*
    185  *	these are not supported by Sun.
    186  *
    187  *	driveid = osect0->newsect0.pdinfo.driveid;
    188  *	version = osect0->newsect0.pdinfo.version;
    189  */
    190 	for (i = 0; i < V_NUMPAR; i++)	{
    191 		if (vtdata.v_part[i].p_size != 0x00)
    192 			nopartitions++;
    193 	}
    194 /*
    195  *	(void) printf("%s	%0x	%0x	%d	%d	%d\n",
    196  *		device, version, driveid, sectorcyl, bytes, nopartitions);
    197  */
    198 	(void) printf("%s	%0x	%0x	%d	%d	%d\n",
    199 		device, 0, 0, sectorcyl, bytes, nopartitions);
    200 }
    201 
    202 
    203 /*
    204  * readvtoc()
    205  *
    206  * Read a partition map.
    207  */
    208 static int
    209 readvtoc(int fd, char *name, struct extvtoc *vtoc)
    210 {
    211 	int	retval;
    212 
    213 	retval = read_extvtoc(fd, vtoc);
    214 
    215 	switch (retval) {
    216 		case (VT_ERROR):
    217 			return (warn(name, strerror(errno)));
    218 		case (VT_EIO):
    219 			return (warn(name, "I/O error accessing VTOC"));
    220 		case (VT_EINVAL):
    221 			return (warn(name, "Invalid field in VTOC"));
    222 		}
    223 
    224 	return (retval);
    225 }
    226 
    227 
    228 /*
    229  * warn()
    230  *
    231  * Print an error message. Always returns -1.
    232  */
    233 static int
    234 warn(char *what, char *why)
    235 {
    236 	static char	myname[]  = "devinfo";
    237 	static char	between[] = ": ";
    238 	static char	after[]   = "\n";
    239 
    240 	(void) write(STDERR, myname, (uint_t)strlen(myname));
    241 	(void) write(STDERR, between, (uint_t)strlen(between));
    242 	(void) write(STDERR, what, (uint_t)strlen(what));
    243 	(void) write(STDERR, between, (uint_t)strlen(between));
    244 	(void) write(STDERR, why, (uint_t)strlen(why));
    245 	(void) write(STDERR, after, (uint_t)strlen(after));
    246 	return (-1);
    247 }
    248 
    249 static void
    250 usage(void)
    251 {
    252 	(void) fprintf(stderr, "Usage: devinfo -p device\n"
    253 		"       devinfo -i device \n");
    254 	exit(2);
    255 }
    256