xref: /illumos-gate/usr/src/cmd/devinfo/devinfo.c (revision 0173c38a73f34277e0c97a19fedfd25d81ba8380)
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  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27 /*	  All Rights Reserved  	*/
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
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 
41 #include <stdio.h>
42 #include <fcntl.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include <string.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <sys/dkio.h>
49 #include <sys/efi_partition.h>
50 #include <sys/vtoc.h>
51 #include <sys/mkdev.h>
52 #include <errno.h>
53 
54 #define	DRERR	2
55 #define	OPENERR	2
56 
57 /*
58  * Standard I/O file descriptors.
59  */
60 #define	STDOUT	1		/* Standard output */
61 #define	STDERR	2		/* Standard error */
62 
63 static	void	partinfo(int fd, char *device);
64 static	void	devinfo(struct dk_geom *geom, int fd, char *device);
65 static	int	readvtoc(int fd, char *name, struct vtoc *vtoc);
66 static	int	warn(char *what, char *why);
67 static	void	usage(void);
68 
69 int
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\t%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\t%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