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 2004 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 /* 32 * Two output fields under the -i option will always be 33 * output as zero, since they are not supported by Sun: 34 * Software version, and 35 * Drive id number. 36 * AT&T filled these 2 fields with data from their "pdsector", 37 * which Sun doesn't support per se. 38 */ 39 40 #pragma ident "%Z%%M% %I% %E% SMI" 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 main(int argc, char **argv) 71 { 72 struct dk_geom geom; 73 int errflg, iflg, pflg, fd, c; 74 char *device; 75 76 iflg = 0; 77 pflg = 0; 78 errflg = 0; 79 while ((c = getopt(argc, argv, "i:p:")) != EOF) { 80 switch (c) { 81 case 'i': 82 iflg++; 83 device = optarg; 84 break; 85 case 'p': 86 pflg++; 87 device = optarg; 88 break; 89 case '?': 90 errflg++; 91 break; 92 default: 93 errflg++; 94 break; 95 } 96 if (errflg) 97 usage(); 98 } 99 if ((optind > argc) || (optind == 1) || (pflg && iflg)) 100 usage(); 101 102 if ((fd = open(device, O_RDONLY)) < 0) { 103 (void) fprintf(stderr, "devinfo: %s: %s\n", 104 device, strerror(errno)); 105 exit(OPENERR); 106 } 107 108 if (iflg) { 109 if (ioctl(fd, DKIOCGGEOM, &geom) == -1) { 110 if (errno == ENOTSUP) { 111 (void) warn(device, 112 "This operation is not supported on EFI labeled devices"); 113 } else { 114 (void) warn(device, 115 "Unable to read Disk geometry"); 116 } 117 (void) close(fd); 118 exit(DRERR); 119 } 120 devinfo(&geom, fd, device); 121 } 122 if (pflg) 123 partinfo(fd, device); 124 (void) close(fd); 125 return (0); 126 } 127 128 static void 129 partinfo(int fd, char *device) 130 { 131 int i; 132 int slice; 133 major_t maj; 134 minor_t min; 135 struct stat64 statbuf; 136 struct vtoc vtdata; 137 struct dk_gpt *efi; 138 139 i = stat64(device, &statbuf); 140 if (i < 0) 141 exit(DRERR); 142 maj = major(statbuf.st_rdev); 143 min = minor(statbuf.st_rdev); 144 145 if ((slice = readvtoc(fd, device, &vtdata)) >= 0) { 146 147 (void) printf("%s\t%0lx %0lx\t%ld\t%ld\t%x\t%x\n", 148 device, maj, min, 149 vtdata.v_part[slice].p_start, 150 vtdata.v_part[slice].p_size, 151 vtdata.v_part[slice].p_flag, 152 vtdata.v_part[slice].p_tag); 153 } else if ((slice == VT_ENOTSUP) && 154 (slice = efi_alloc_and_read(fd, &efi)) >= 0) { 155 (void) printf("%s\t%lx %lx\t%lld\t%lld\t%hx\t%hx\n", 156 device, maj, min, 157 efi->efi_parts[slice].p_start, 158 efi->efi_parts[slice].p_size, 159 efi->efi_parts[slice].p_flag, 160 efi->efi_parts[slice].p_tag); 161 } else { 162 exit(DRERR); 163 } 164 } 165 166 static void 167 devinfo(struct dk_geom *geom, int fd, char *device) 168 { 169 int i; 170 unsigned int nopartitions, sectorcyl, bytes; 171 struct vtoc vtdata; 172 /* 173 * unsigned int version = 0; 174 * unsigned int driveid = 0; 175 */ 176 177 nopartitions = 0; 178 sectorcyl = 0; 179 bytes = 0; 180 181 if (readvtoc(fd, device, &vtdata) < 0) 182 exit(DRERR); 183 sectorcyl = geom->dkg_nhead * geom->dkg_nsect; 184 bytes = vtdata.v_sectorsz; 185 /* 186 * these are not supported by Sun. 187 * 188 * driveid = osect0->newsect0.pdinfo.driveid; 189 * version = osect0->newsect0.pdinfo.version; 190 */ 191 for (i = 0; i < V_NUMPAR; i++) { 192 if (vtdata.v_part[i].p_size != 0x00) 193 nopartitions++; 194 } 195 /* 196 * (void) printf("%s %0x %0x %d %d %d\n", 197 * device, version, driveid, sectorcyl, bytes, nopartitions); 198 */ 199 (void) printf("%s %0x %0x %d %d %d\n", 200 device, 0, 0, sectorcyl, bytes, nopartitions); 201 } 202 203 204 /* 205 * readvtoc() 206 * 207 * Read a partition map. 208 */ 209 static int 210 readvtoc(int fd, char *name, struct vtoc *vtoc) 211 { 212 int retval; 213 214 retval = read_vtoc(fd, vtoc); 215 216 switch (retval) { 217 case (VT_ERROR): 218 return (warn(name, strerror(errno))); 219 case (VT_EIO): 220 return (warn(name, "I/O error accessing VTOC")); 221 case (VT_EINVAL): 222 return (warn(name, "Invalid field in VTOC")); 223 } 224 225 return (retval); 226 } 227 228 229 /* 230 * warn() 231 * 232 * Print an error message. Always returns -1. 233 */ 234 static int 235 warn(char *what, char *why) 236 { 237 static char myname[] = "devinfo"; 238 static char between[] = ": "; 239 static char after[] = "\n"; 240 241 (void) write(STDERR, myname, (uint_t)strlen(myname)); 242 (void) write(STDERR, between, (uint_t)strlen(between)); 243 (void) write(STDERR, what, (uint_t)strlen(what)); 244 (void) write(STDERR, between, (uint_t)strlen(between)); 245 (void) write(STDERR, why, (uint_t)strlen(why)); 246 (void) write(STDERR, after, (uint_t)strlen(after)); 247 return (-1); 248 } 249 250 static void 251 usage(void) 252 { 253 (void) fprintf(stderr, "Usage: devinfo -p device\n" 254 " devinfo -i device \n"); 255 exit(2); 256 } 257