xref: /netbsd-src/usr.sbin/vnconfig/vnconfig.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: vnconfig.c,v 1.42 2014/05/23 20:50:16 dholland 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 #include <sys/bitops.h>
77 
78 #include <dev/vndvar.h>
79 
80 #include <disktab.h>
81 #include <err.h>
82 #include <dirent.h>
83 #include <errno.h>
84 #include <fcntl.h>
85 #include <stddef.h>
86 #include <stdio.h>
87 #include <stdlib.h>
88 #include <string.h>
89 #include <unistd.h>
90 #include <util.h>
91 #include <paths.h>
92 
93 #define VND_CONFIG	1
94 #define VND_UNCONFIG	2
95 #define VND_GET		3
96 
97 static int	verbose = 0;
98 static int	readonly = 0;
99 static int	force = 0;
100 static int	compressed = 0;
101 static char	*tabname;
102 
103 static void	show(int, int);
104 static int	config(char *, char *, char *, int);
105 static int	getgeom(struct vndgeom *, char *);
106 __dead static void	usage(void);
107 
108 int
109 main(int argc, char *argv[])
110 {
111 	int ch, rv, action = VND_CONFIG;
112 
113 	while ((ch = getopt(argc, argv, "Fcf:lrt:uvz")) != -1) {
114 		switch (ch) {
115 		case 'F':
116 			force = 1;
117 			break;
118 		case 'c':
119 			action = VND_CONFIG;
120 			break;
121 		case 'f':
122 			if (setdisktab(optarg) == -1)
123 				usage();
124 			break;
125 		case 'l':
126 			action = VND_GET;
127 			break;
128 		case 'r':
129 			readonly = 1;
130 			break;
131 		case 't':
132 			tabname = optarg;
133 			break;
134 		case 'u':
135 			action = VND_UNCONFIG;
136 			break;
137 		case 'v':
138 			verbose = 1;
139 			break;
140 		case 'z':
141 			compressed = 1;
142 			readonly = 1;
143 			break;
144 		default:
145 		case '?':
146 			usage();
147 			/* NOTREACHED */
148 		}
149 	}
150 	argc -= optind;
151 	argv += optind;
152 
153 	if (action == VND_CONFIG) {
154 		if ((argc < 2 || argc > 3) ||
155 		    (argc == 3 && tabname != NULL))
156 			usage();
157 		rv = config(argv[0], argv[1], (argc == 3) ? argv[2] : NULL,
158 		    action);
159 	} else if (action == VND_UNCONFIG) {
160 		if (argc != 1 || tabname != NULL)
161 			usage();
162 		rv = config(argv[0], NULL, NULL, action);
163 	} else { /* VND_GET */
164 		int n, v;
165 		const char *vn;
166 		char path[64];
167 
168 		if (argc != 0 && argc != 1)
169 			usage();
170 
171 		vn = argc ? argv[0] : "vnd0";
172 
173 		v = opendisk(vn, O_RDONLY, path, sizeof(path), 0);
174 		if (v == -1)
175 			err(1, "open: %s", vn);
176 
177 		if (argc)
178 			show(v, -1);
179 		else {
180 			DIR *dirp;
181 			struct dirent *dp;
182 			__BITMAP_TYPE(, uint32_t, 65536) bm;
183 
184 			__BITMAP_ZERO(&bm);
185 
186 			if ((dirp = opendir(_PATH_DEV)) == NULL)
187 				err(1, "opendir: %s", _PATH_DEV);
188 
189 			while ((dp = readdir(dirp)) != NULL) {
190 				if (strncmp(dp->d_name, "rvnd", 4) != 0)
191 					continue;
192 				n = atoi(dp->d_name + 4);
193 				if (__BITMAP_ISSET(n, &bm))
194 					continue;
195 				__BITMAP_SET(n, &bm);
196 				show(v, n);
197 			}
198 
199 			closedir(dirp);
200 		}
201 		close(v);
202 		rv = 0;
203 	}
204 	return rv;
205 }
206 
207 static void
208 show(int v, int n)
209 {
210 	struct vnd_user vnu;
211 	char *dev;
212 	struct statvfs *mnt;
213 	int i, nmount;
214 
215 	vnu.vnu_unit = n;
216 	if (ioctl(v, VNDIOCGET, &vnu) == -1)
217 		err(1, "VNDIOCGET");
218 
219 	if (vnu.vnu_ino == 0) {
220 		printf("vnd%d: not in use\n", vnu.vnu_unit);
221 		return;
222 	}
223 
224 	printf("vnd%d: ", vnu.vnu_unit);
225 
226 	dev = devname(vnu.vnu_dev, S_IFBLK);
227 	if (dev != NULL)
228 		nmount = getmntinfo(&mnt, MNT_NOWAIT);
229 	else {
230 		mnt = NULL;
231 		nmount = 0;
232 	}
233 
234 	if (mnt != NULL) {
235 		for (i = 0; i < nmount; i++) {
236 			if (strncmp(mnt[i].f_mntfromname, "/dev/", 5) == 0 &&
237 			    strcmp(mnt[i].f_mntfromname + 5, dev) == 0)
238 				break;
239 		}
240 		if (i < nmount)
241 			printf("%s (%s) ", mnt[i].f_mntonname,
242 			    mnt[i].f_mntfromname);
243 		else
244 			printf("%s ", dev);
245 	}
246 	else if (dev != NULL)
247 		printf("%s ", dev);
248 	else
249 		printf("dev %llu,%llu ",
250 		    (unsigned long long)major(vnu.vnu_dev),
251 		    (unsigned long long)minor(vnu.vnu_dev));
252 
253 	printf("inode %llu\n", (unsigned long long)vnu.vnu_ino);
254 }
255 
256 static int
257 config(char *dev, char *file, char *geom, int action)
258 {
259 	struct vnd_ioctl vndio;
260 	struct disklabel *lp;
261 	char rdev[MAXPATHLEN + 1];
262 	int fd, rv;
263 
264 	fd = opendisk(dev, O_RDWR, rdev, sizeof(rdev), 0);
265 	if (fd < 0) {
266 		warn("%s: opendisk", rdev);
267 		return (1);
268 	}
269 
270 	memset(&vndio, 0, sizeof(vndio));
271 #ifdef __GNUC__
272 	rv = 0;			/* XXX */
273 #endif
274 
275 	vndio.vnd_file = file;
276 	if (geom != NULL) {
277 		rv = getgeom(&vndio.vnd_geom, geom);
278 		if (rv != 0)
279 			errx(1, "invalid geometry: %s", geom);
280 		vndio.vnd_flags = VNDIOF_HASGEOM;
281 	} else if (tabname != NULL) {
282 		lp = getdiskbyname(tabname);
283 		if (lp == NULL)
284 			errx(1, "unknown disk type: %s", tabname);
285 		vndio.vnd_geom.vng_secsize = lp->d_secsize;
286 		vndio.vnd_geom.vng_nsectors = lp->d_nsectors;
287 		vndio.vnd_geom.vng_ntracks = lp->d_ntracks;
288 		vndio.vnd_geom.vng_ncylinders = lp->d_ncylinders;
289 		vndio.vnd_flags = VNDIOF_HASGEOM;
290 	}
291 
292 	if (readonly)
293 		vndio.vnd_flags |= VNDIOF_READONLY;
294 
295 	if (compressed)
296 		vndio.vnd_flags |= VNF_COMP;
297 
298 	/*
299 	 * Clear (un-configure) the device
300 	 */
301 	if (action == VND_UNCONFIG) {
302 		if (force)
303 			vndio.vnd_flags |= VNDIOF_FORCE;
304 		rv = ioctl(fd, VNDIOCCLR, &vndio);
305 #ifdef VNDIOOCCLR
306 		if (rv && errno == ENOTTY)
307 			rv = ioctl(fd, VNDIOOCCLR, &vndio);
308 #endif
309 		if (rv)
310 			warn("%s: VNDIOCCLR", rdev);
311 		else if (verbose)
312 			printf("%s: cleared\n", rdev);
313 	}
314 	/*
315 	 * Configure the device
316 	 */
317 	if (action == VND_CONFIG) {
318 		int	ffd;
319 
320 		ffd = open(file, readonly ? O_RDONLY : O_RDWR);
321 		if (ffd < 0) {
322 			warn("%s", file);
323 			rv = -1;
324 		} else {
325 			(void) close(ffd);
326 
327 			rv = ioctl(fd, VNDIOCSET, &vndio);
328 #ifdef VNDIOOCSET
329 			if (rv && errno == ENOTTY) {
330 				rv = ioctl(fd, VNDIOOCSET, &vndio);
331 				vndio.vnd_size = vndio.vnd_osize;
332 			}
333 #endif
334 			if (rv)
335 				warn("%s: VNDIOCSET", rdev);
336 			else if (verbose) {
337 				printf("%s: %" PRIu64 " bytes on %s", rdev,
338 				    vndio.vnd_size, file);
339 				if (vndio.vnd_flags & VNDIOF_HASGEOM)
340 					printf(" using geometry %d/%d/%d/%d",
341 					    vndio.vnd_geom.vng_secsize,
342 					    vndio.vnd_geom.vng_nsectors,
343 					    vndio.vnd_geom.vng_ntracks,
344 				    vndio.vnd_geom.vng_ncylinders);
345 				printf("\n");
346 			}
347 		}
348 	}
349 
350 	(void) close(fd);
351 	fflush(stdout);
352 	return (rv < 0);
353 }
354 
355 static int
356 getgeom(struct vndgeom *vng, char *cp)
357 {
358 	char *secsize, *nsectors, *ntracks, *ncylinders;
359 
360 #define	GETARG(arg) \
361 	do { \
362 		if (cp == NULL || *cp == '\0') \
363 			return (1); \
364 		arg = strsep(&cp, "/"); \
365 		if (arg == NULL) \
366 			return (1); \
367 	} while (0)
368 
369 	GETARG(secsize);
370 	GETARG(nsectors);
371 	GETARG(ntracks);
372 	GETARG(ncylinders);
373 
374 #undef GETARG
375 
376 	/* Too many? */
377 	if (cp != NULL)
378 		return (1);
379 
380 #define	CVTARG(str, num) \
381 	do { \
382 		num = strtol(str, &cp, 10); \
383 		if (*cp != '\0') \
384 			return (1); \
385 	} while (0)
386 
387 	CVTARG(secsize, vng->vng_secsize);
388 	CVTARG(nsectors, vng->vng_nsectors);
389 	CVTARG(ntracks, vng->vng_ntracks);
390 	CVTARG(ncylinders, vng->vng_ncylinders);
391 
392 #undef CVTARG
393 
394 	return (0);
395 }
396 
397 static void
398 usage(void)
399 {
400 
401 	(void)fprintf(stderr, "%s%s",
402 	    "usage: vnconfig [-crvz] [-f disktab] [-t typename] vnode_disk"
403 		" regular-file [geomspec]\n",
404 	    "       vnconfig -u [-Fv] vnode_disk\n"
405 	    "       vnconfig -l [vnode_disk]\n");
406 	exit(1);
407 }
408