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