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
main(int argc,char ** argv)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
partinfo(int fd,char * device)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
devinfo(struct dk_geom * geom,int fd,char * device)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
readvtoc(int fd,char * name,struct extvtoc * vtoc)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
warn(char * what,char * why)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
usage(void)250 usage(void)
251 {
252 (void) fprintf(stderr, "Usage: devinfo -p device\n"
253 " devinfo -i device \n");
254 exit(2);
255 }
256