Home | History | Annotate | Line # | Download | only in vnconfig
vnconfig.c revision 1.1
      1 /*
      2  * Copyright (c) 1993 University of Utah.
      3  * Copyright (c) 1990, 1993
      4  *	The Regents of the University of California.  All rights reserved.
      5  *
      6  * This code is derived from software contributed to Berkeley by
      7  * the Systems Programming Group of the University of Utah Computer
      8  * Science Department.
      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  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *	This product includes software developed by the University of
     21  *	California, Berkeley and its contributors.
     22  * 4. Neither the name of the University nor the names of its contributors
     23  *    may be used to endorse or promote products derived from this software
     24  *    without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     36  * SUCH DAMAGE.
     37  *
     38  * from: Utah $Hdr: vnconfig.c 1.1 93/12/15$
     39  *
     40  *	@(#)vnconfig.c	8.1 (Berkeley) 12/15/93
     41  */
     42 
     43 #include <stdio.h>
     44 #include <errno.h>
     45 #include <sys/param.h>
     46 #include <sys/ioctl.h>
     47 #include <sys/mount.h>
     48 #include <sys/stat.h>
     49 #include <dev/vnioctl.h>
     50 
     51 #define MAXVNDISK	16
     52 #define LINESIZE	1024
     53 
     54 struct vndisk {
     55 	char	*dev;
     56 	char	*file;
     57 	int	flags;
     58 	char	*oarg;
     59 } vndisks[MAXVNDISK];
     60 
     61 #define VN_CONFIG	0x01
     62 #define VN_UNCONFIG	0x02
     63 #define VN_ENABLE	0x04
     64 #define VN_DISABLE	0x08
     65 #define	VN_SWAP		0x10
     66 #define VN_MOUNTRO	0x20
     67 #define VN_MOUNTRW	0x40
     68 #define VN_IGNORE	0x80
     69 
     70 int nvndisks;
     71 
     72 int all = 0;
     73 int verbose = 0;
     74 char *configfile;
     75 char *pname;
     76 
     77 char *malloc(), *rawdevice(), *rindex();
     78 
     79 main(argc, argv)
     80 	char **argv;
     81 {
     82 	extern int optind, optopt, opterr;
     83 	extern char *optarg;
     84 	register int i, rv;
     85 	int flags = 0;
     86 
     87 	pname = argv[0];
     88 	configfile = _PATH_VNTAB;
     89 	while ((i = getopt(argc, argv, "acdef:uv")) != EOF)
     90 		switch (i) {
     91 
     92 		/* all -- use config file */
     93 		case 'a':
     94 			all++;
     95 			break;
     96 
     97 		/* configure */
     98 		case 'c':
     99 			flags |= VN_CONFIG;
    100 			flags &= ~VN_UNCONFIG;
    101 			break;
    102 
    103 		/* disable */
    104 		case 'd':
    105 			flags |= VN_DISABLE;
    106 			flags &= ~VN_ENABLE;
    107 			break;
    108 
    109 		/* enable */
    110 		case 'e':
    111 			flags |= (VN_ENABLE|VN_CONFIG);
    112 			flags &= ~(VN_DISABLE|VN_UNCONFIG);
    113 			break;
    114 
    115 		/* alternate config file */
    116 		case 'f':
    117 			configfile = optarg;
    118 			break;
    119 
    120 		/* unconfigure */
    121 		case 'u':
    122 			flags |= (VN_DISABLE|VN_UNCONFIG);
    123 			flags &= ~(VN_ENABLE|VN_CONFIG);
    124 			break;
    125 
    126 		/* verbose */
    127 		case 'v':
    128 			verbose++;
    129 			break;
    130 
    131 		default:
    132 			fprintf(stderr, "invalid option '%c'\n", optopt);
    133 			usage();
    134 		}
    135 
    136 	if (flags == 0)
    137 		flags = VN_CONFIG;
    138 	if (all)
    139 		readconfig(flags);
    140 	else {
    141 		if (argc < optind + 2)
    142 			usage();
    143 		vndisks[0].dev = argv[optind++];
    144 		vndisks[0].file = argv[optind++];
    145 		vndisks[0].flags = flags;
    146 		if (optind < argc)
    147 			getoptions(&vndisks[0], argv[optind]);
    148 		nvndisks = 1;
    149 	}
    150 	rv = 0;
    151 	for (i = 0; i < nvndisks; i++)
    152 		rv += config(&vndisks[i]);
    153 	exit(rv);
    154 }
    155 
    156 config(vnp)
    157 	struct vndisk *vnp;
    158 {
    159 	char *dev, *file, *oarg;
    160 	int flags;
    161 	struct vn_ioctl vnio;
    162 	register int rv;
    163 	char *rdev;
    164 	FILE *f;
    165 	extern int errno;
    166 
    167 	dev = vnp->dev;
    168 	file = vnp->file;
    169 	flags = vnp->flags;
    170 	oarg = vnp->oarg;
    171 
    172 	if (flags & VN_IGNORE)
    173 		return(0);
    174 
    175 	rdev = rawdevice(dev);
    176 	f = fopen(rdev, "rw");
    177 	if (f == NULL) {
    178 		perror("open");
    179 		return(1);
    180 	}
    181 	vnio.vn_file = file;
    182 
    183 	/*
    184 	 * Disable the device
    185 	 */
    186 	if (flags & VN_DISABLE) {
    187 		if (flags & (VN_MOUNTRO|VN_MOUNTRW)) {
    188 			rv = unmount(oarg, 0);
    189 			if (rv) {
    190 				if (errno == EBUSY)
    191 					flags &= ~VN_UNCONFIG;
    192 				if ((flags & VN_UNCONFIG) == 0)
    193 					perror("umount");
    194 			} else if (verbose)
    195 				printf("%s: unmounted\n", dev);
    196 		}
    197 	}
    198 	/*
    199 	 * Clear (un-configure) the device
    200 	 */
    201 	if (flags & VN_UNCONFIG) {
    202 		rv = ioctl(fileno(f), VNIOCCLR, &vnio);
    203 		if (rv) {
    204 			if (errno == ENODEV) {
    205 				if (verbose)
    206 					printf("%s: not configured\n", dev);
    207 				rv = 0;
    208 			} else
    209 				perror("VNIOCCLR");
    210 		} else if (verbose)
    211 			printf("%s: cleared\n", dev);
    212 	}
    213 	/*
    214 	 * Configure the device
    215 	 */
    216 	if (flags & VN_CONFIG) {
    217 		rv = ioctl(fileno(f), VNIOCSET, &vnio);
    218 		if (rv) {
    219 			if (errno == EBUSY) {
    220 				if ((flags & VN_ENABLE) == 0 && verbose)
    221 					printf("%s: already configured\n",dev);
    222 				rv = 0;
    223 			} else {
    224 				perror("VNIOCSET");
    225 				flags &= ~VN_ENABLE;
    226 			}
    227 		} else if (verbose)
    228 			printf("%s: %d bytes on %s\n",
    229 			       dev, vnio.vn_size, file);
    230 	}
    231 	/*
    232 	 * Enable special functions on the device
    233 	 */
    234 	if (flags & VN_ENABLE) {
    235 		if (flags & VN_SWAP) {
    236 			rv = swapon(dev);
    237 			if (rv)
    238 				perror("swapon");
    239 			else if (verbose)
    240 				printf("%s: swapping enabled\n", dev);
    241 		}
    242 		if (flags & (VN_MOUNTRO|VN_MOUNTRW)) {
    243 			struct ufs_args args;
    244 			int mflags;
    245 
    246 			args.fspec = dev;
    247 			mflags = (flags & VN_MOUNTRO) ? MNT_RDONLY : 0;
    248 			rv = mount(MOUNT_UFS, oarg, mflags, &args);
    249 			if (rv)
    250 				perror("mount");
    251 			else if (verbose)
    252 				printf("%s: mounted on %s\n", dev, oarg);
    253 		}
    254 	}
    255 done:
    256 	fclose(f);
    257 	fflush(stdout);
    258 	return(rv < 0);
    259 }
    260 
    261 #define EOL(c)		((c) == '\0' || (c) == '\n')
    262 #define WHITE(c)	((c) == ' ' || (c) == '\t' || (c) == '\n')
    263 
    264 readconfig(flags)
    265 	int flags;
    266 {
    267 	char buf[LINESIZE];
    268 	FILE *f;
    269 	register char *cp, *sp;
    270 	register int ix;
    271 
    272 	f = fopen(configfile, "r");
    273 	if (f == NULL) {
    274 		perror(configfile);
    275 		exit(1);
    276 	}
    277 	ix = 0;
    278 	while (fgets(buf, LINESIZE, f) != NULL) {
    279 		cp = buf;
    280 		if (*cp == '#')
    281 			continue;
    282 		while (!EOL(*cp) && WHITE(*cp))
    283 			cp++;
    284 		if (EOL(*cp))
    285 			continue;
    286 		sp = cp;
    287 		while (!EOL(*cp) && !WHITE(*cp))
    288 			cp++;
    289 		if (EOL(*cp))
    290 			continue;
    291 		*cp++ = '\0';
    292 		vndisks[ix].dev = malloc(cp - sp);
    293 		strcpy(vndisks[ix].dev, sp);
    294 		while (!EOL(*cp) && WHITE(*cp))
    295 			cp++;
    296 		if (EOL(*cp))
    297 			continue;
    298 		sp = cp;
    299 		while (!EOL(*cp) && !WHITE(*cp))
    300 			cp++;
    301 		*cp++ = '\0';
    302 		vndisks[ix].file = malloc(cp - sp);
    303 		strcpy(vndisks[ix].file, sp);
    304 		while (!EOL(*cp) && WHITE(*cp))
    305 			cp++;
    306 		vndisks[ix].flags = flags;
    307 		if (!EOL(*cp)) {
    308 			sp = cp;
    309 			while (!EOL(*cp) && !WHITE(*cp))
    310 				cp++;
    311 			*cp++ = '\0';
    312 			getoptions(&vndisks[ix], sp);
    313 		}
    314 		nvndisks++;
    315 		ix++;
    316 	}
    317 }
    318 
    319 getoptions(vnp, fstr)
    320 	struct vndisk *vnp;
    321 	char *fstr;
    322 {
    323 	int flags = 0;
    324 	char *oarg = NULL;
    325 
    326 	if (strcmp(fstr, "swap") == 0)
    327 		flags |= VN_SWAP;
    328 	else if (strncmp(fstr, "mount=", 6) == 0) {
    329 		flags |= VN_MOUNTRW;
    330 		oarg = &fstr[6];
    331 	} else if (strncmp(fstr, "mountrw=", 8) == 0) {
    332 		flags |= VN_MOUNTRW;
    333 		oarg = &fstr[8];
    334 	} else if (strncmp(fstr, "mountro=", 8) == 0) {
    335 		flags |= VN_MOUNTRO;
    336 		oarg = &fstr[8];
    337 	} else if (strcmp(fstr, "ignore") == 0)
    338 		flags |= VN_IGNORE;
    339 	vnp->flags |= flags;
    340 	if (oarg) {
    341 		vnp->oarg = malloc(strlen(oarg) + 1);
    342 		strcpy(vnp->oarg, oarg);
    343 	} else
    344 		vnp->oarg = NULL;
    345 }
    346 
    347 char *
    348 rawdevice(dev)
    349 	char *dev;
    350 {
    351 	register char *rawbuf, *dp, *ep;
    352 	struct stat sb;
    353 	int len;
    354 
    355 	len = strlen(dev);
    356 	rawbuf = malloc(len + 2);
    357 	strcpy(rawbuf, dev);
    358 	if (stat(rawbuf, &sb) != 0 || !S_ISCHR(sb.st_mode)) {
    359 		dp = rindex(rawbuf, '/');
    360 		if (dp) {
    361 			for (ep = &rawbuf[len]; ep > dp; --ep)
    362 				*(ep+1) = *ep;
    363 			*++ep = 'r';
    364 		}
    365 	}
    366 	return (rawbuf);
    367 }
    368 
    369 usage()
    370 {
    371 	fprintf(stderr, "usage: %s [-acdefuv] [special-device file]\n",
    372 		pname);
    373 	exit(1);
    374 }
    375