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