xref: /illumos-gate/usr/src/cmd/devinfo/devinfo.c (revision 141040e8a310da49386b596573e5dde5580572ec)
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