xref: /netbsd-src/usr.sbin/vnconfig/vnconfig.c (revision 9573673d78c64ea1eac42d7f2e9521be89932ae5)
1 /*	$NetBSD: vnconfig.c,v 1.43 2015/11/09 17:39:20 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 1997 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Copyright (c) 1993 University of Utah.
34  * Copyright (c) 1990, 1993
35  *	The Regents of the University of California.  All rights reserved.
36  *
37  * This code is derived from software contributed to Berkeley by
38  * the Systems Programming Group of the University of Utah Computer
39  * Science Department.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. Neither the name of the University nor the names of its contributors
50  *    may be used to endorse or promote products derived from this software
51  *    without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63  * SUCH DAMAGE.
64  *
65  * from: Utah $Hdr: vnconfig.c 1.1 93/12/15$
66  *
67  *	@(#)vnconfig.c	8.1 (Berkeley) 12/15/93
68  */
69 
70 #include <sys/param.h>
71 #include <sys/ioctl.h>
72 #include <sys/mount.h>
73 #include <sys/buf.h>
74 #include <sys/disklabel.h>
75 #include <sys/disk.h>
76 
77 #include <dev/vndvar.h>
78 
79 #include <disktab.h>
80 #include <err.h>
81 #include <errno.h>
82 #include <fcntl.h>
83 #include <stddef.h>
84 #include <stdio.h>
85 #include <stdlib.h>
86 #include <string.h>
87 #include <unistd.h>
88 #include <util.h>
89 #include <paths.h>
90 
91 #define VND_CONFIG	1
92 #define VND_UNCONFIG	2
93 #define VND_GET		3
94 
95 static int	verbose = 0;
96 static int	readonly = 0;
97 static int	force = 0;
98 static int	compressed = 0;
99 static char	*tabname;
100 
101 static int	show(int, int);
102 static int	config(char *, char *, char *, int);
103 static int	getgeom(struct vndgeom *, char *);
104 __dead static void	usage(void);
105 
106 int
107 main(int argc, char *argv[])
108 {
109 	int ch, rv, action = VND_CONFIG;
110 
111 	while ((ch = getopt(argc, argv, "Fcf:lrt:uvz")) != -1) {
112 		switch (ch) {
113 		case 'F':
114 			force = 1;
115 			break;
116 		case 'c':
117 			action = VND_CONFIG;
118 			break;
119 		case 'f':
120 			if (setdisktab(optarg) == -1)
121 				usage();
122 			break;
123 		case 'l':
124 			action = VND_GET;
125 			break;
126 		case 'r':
127 			readonly = 1;
128 			break;
129 		case 't':
130 			tabname = optarg;
131 			break;
132 		case 'u':
133 			action = VND_UNCONFIG;
134 			break;
135 		case 'v':
136 			verbose = 1;
137 			break;
138 		case 'z':
139 			compressed = 1;
140 			readonly = 1;
141 			break;
142 		default:
143 		case '?':
144 			usage();
145 			/* NOTREACHED */
146 		}
147 	}
148 	argc -= optind;
149 	argv += optind;
150 
151 	if (action == VND_CONFIG) {
152 		if ((argc < 2 || argc > 3) ||
153 		    (argc == 3 && tabname != NULL))
154 			usage();
155 		rv = config(argv[0], argv[1], (argc == 3) ? argv[2] : NULL,
156 		    action);
157 	} else if (action == VND_UNCONFIG) {
158 		if (argc != 1 || tabname != NULL)
159 			usage();
160 		rv = config(argv[0], NULL, NULL, action);
161 	} else { /* VND_GET */
162 		int n, v;
163 		const char *vn;
164 		char path[64];
165 
166 		if (argc != 0 && argc != 1)
167 			usage();
168 
169 		vn = argc ? argv[0] : "vnd0";
170 
171 		v = opendisk(vn, O_RDONLY, path, sizeof(path), 0);
172 		if (v == -1)
173 			err(1, "open: %s", vn);
174 
175 		if (argc)
176 			show(v, -1);
177 		else {
178 			for (n = 0; show(v, n); n++)
179 				continue;
180 		}
181 		close(v);
182 		rv = 0;
183 	}
184 	return rv;
185 }
186 
187 static int
188 show(int v, int n)
189 {
190 	struct vnd_user vnu;
191 	char *dev;
192 	struct statvfs *mnt;
193 	int i, nmount;
194 
195 	vnu.vnu_unit = n;
196 	if (ioctl(v, VNDIOCGET, &vnu) == -1) {
197 		if (errno != ENXIO)
198 			err(1, "VNDIOCGET");
199 		return 0;
200 	}
201 
202 	if (vnu.vnu_ino == 0) {
203 		printf("vnd%d: not in use\n", vnu.vnu_unit);
204 		return 1;
205 	}
206 
207 	printf("vnd%d: ", vnu.vnu_unit);
208 
209 	dev = devname(vnu.vnu_dev, S_IFBLK);
210 	if (dev != NULL)
211 		nmount = getmntinfo(&mnt, MNT_NOWAIT);
212 	else {
213 		mnt = NULL;
214 		nmount = 0;
215 	}
216 
217 	if (mnt != NULL) {
218 		for (i = 0; i < nmount; i++) {
219 			if (strncmp(mnt[i].f_mntfromname, "/dev/", 5) == 0 &&
220 			    strcmp(mnt[i].f_mntfromname + 5, dev) == 0)
221 				break;
222 		}
223 		if (i < nmount)
224 			printf("%s (%s) ", mnt[i].f_mntonname,
225 			    mnt[i].f_mntfromname);
226 		else
227 			printf("%s ", dev);
228 	}
229 	else if (dev != NULL)
230 		printf("%s ", dev);
231 	else
232 		printf("dev %llu,%llu ",
233 		    (unsigned long long)major(vnu.vnu_dev),
234 		    (unsigned long long)minor(vnu.vnu_dev));
235 
236 	printf("inode %llu\n", (unsigned long long)vnu.vnu_ino);
237 	return 1;
238 }
239 
240 static int
241 config(char *dev, char *file, char *geom, int action)
242 {
243 	struct vnd_ioctl vndio;
244 	struct disklabel *lp;
245 	char rdev[MAXPATHLEN + 1];
246 	int fd, rv;
247 
248 	fd = opendisk(dev, O_RDWR, rdev, sizeof(rdev), 0);
249 	if (fd < 0) {
250 		warn("%s: opendisk", rdev);
251 		return (1);
252 	}
253 
254 	memset(&vndio, 0, sizeof(vndio));
255 #ifdef __GNUC__
256 	rv = 0;			/* XXX */
257 #endif
258 
259 	vndio.vnd_file = file;
260 	if (geom != NULL) {
261 		rv = getgeom(&vndio.vnd_geom, geom);
262 		if (rv != 0)
263 			errx(1, "invalid geometry: %s", geom);
264 		vndio.vnd_flags = VNDIOF_HASGEOM;
265 	} else if (tabname != NULL) {
266 		lp = getdiskbyname(tabname);
267 		if (lp == NULL)
268 			errx(1, "unknown disk type: %s", tabname);
269 		vndio.vnd_geom.vng_secsize = lp->d_secsize;
270 		vndio.vnd_geom.vng_nsectors = lp->d_nsectors;
271 		vndio.vnd_geom.vng_ntracks = lp->d_ntracks;
272 		vndio.vnd_geom.vng_ncylinders = lp->d_ncylinders;
273 		vndio.vnd_flags = VNDIOF_HASGEOM;
274 	}
275 
276 	if (readonly)
277 		vndio.vnd_flags |= VNDIOF_READONLY;
278 
279 	if (compressed)
280 		vndio.vnd_flags |= VNF_COMP;
281 
282 	/*
283 	 * Clear (un-configure) the device
284 	 */
285 	if (action == VND_UNCONFIG) {
286 		if (force)
287 			vndio.vnd_flags |= VNDIOF_FORCE;
288 		rv = ioctl(fd, VNDIOCCLR, &vndio);
289 #ifdef VNDIOOCCLR
290 		if (rv && errno == ENOTTY)
291 			rv = ioctl(fd, VNDIOOCCLR, &vndio);
292 #endif
293 		if (rv)
294 			warn("%s: VNDIOCCLR", rdev);
295 		else if (verbose)
296 			printf("%s: cleared\n", rdev);
297 	}
298 	/*
299 	 * Configure the device
300 	 */
301 	if (action == VND_CONFIG) {
302 		int	ffd;
303 
304 		ffd = open(file, readonly ? O_RDONLY : O_RDWR);
305 		if (ffd < 0) {
306 			warn("%s", file);
307 			rv = -1;
308 		} else {
309 			(void) close(ffd);
310 
311 			rv = ioctl(fd, VNDIOCSET, &vndio);
312 #ifdef VNDIOOCSET
313 			if (rv && errno == ENOTTY) {
314 				rv = ioctl(fd, VNDIOOCSET, &vndio);
315 				vndio.vnd_size = vndio.vnd_osize;
316 			}
317 #endif
318 			if (rv)
319 				warn("%s: VNDIOCSET", rdev);
320 			else if (verbose) {
321 				printf("%s: %" PRIu64 " bytes on %s", rdev,
322 				    vndio.vnd_size, file);
323 				if (vndio.vnd_flags & VNDIOF_HASGEOM)
324 					printf(" using geometry %d/%d/%d/%d",
325 					    vndio.vnd_geom.vng_secsize,
326 					    vndio.vnd_geom.vng_nsectors,
327 					    vndio.vnd_geom.vng_ntracks,
328 				    vndio.vnd_geom.vng_ncylinders);
329 				printf("\n");
330 			}
331 		}
332 	}
333 
334 	(void) close(fd);
335 	fflush(stdout);
336 	return (rv < 0);
337 }
338 
339 static int
340 getgeom(struct vndgeom *vng, char *cp)
341 {
342 	char *secsize, *nsectors, *ntracks, *ncylinders;
343 
344 #define	GETARG(arg) \
345 	do { \
346 		if (cp == NULL || *cp == '\0') \
347 			return (1); \
348 		arg = strsep(&cp, "/"); \
349 		if (arg == NULL) \
350 			return (1); \
351 	} while (0)
352 
353 	GETARG(secsize);
354 	GETARG(nsectors);
355 	GETARG(ntracks);
356 	GETARG(ncylinders);
357 
358 #undef GETARG
359 
360 	/* Too many? */
361 	if (cp != NULL)
362 		return (1);
363 
364 #define	CVTARG(str, num) \
365 	do { \
366 		num = strtol(str, &cp, 10); \
367 		if (*cp != '\0') \
368 			return (1); \
369 	} while (0)
370 
371 	CVTARG(secsize, vng->vng_secsize);
372 	CVTARG(nsectors, vng->vng_nsectors);
373 	CVTARG(ntracks, vng->vng_ntracks);
374 	CVTARG(ncylinders, vng->vng_ncylinders);
375 
376 #undef CVTARG
377 
378 	return (0);
379 }
380 
381 static void
382 usage(void)
383 {
384 
385 	(void)fprintf(stderr, "%s%s",
386 	    "usage: vnconfig [-crvz] [-f disktab] [-t typename] vnode_disk"
387 		" regular-file [geomspec]\n",
388 	    "       vnconfig -u [-Fv] vnode_disk\n"
389 	    "       vnconfig -l [vnode_disk]\n");
390 	exit(1);
391 }
392