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