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