Home | History | Annotate | Line # | Download | only in vnconfig
vnconfig.c revision 1.3
      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 <stdlib.h>
     45 #include <string.h>
     46 #include <errno.h>
     47 #include <sys/param.h>
     48 #include <sys/ioctl.h>
     49 #include <sys/mount.h>
     50 #include <sys/stat.h>
     51 #include <dev/vnioctl.h>
     52 
     53 #define MAXVNDISK	16
     54 #define LINESIZE	1024
     55 
     56 struct vndisk {
     57 	char	*dev;
     58 	char	*file;
     59 	int	flags;
     60 	char	*oarg;
     61 } vndisks[MAXVNDISK];
     62 
     63 #define VN_CONFIG	0x01
     64 #define VN_UNCONFIG	0x02
     65 #define VN_ENABLE	0x04
     66 #define VN_DISABLE	0x08
     67 #define	VN_SWAP		0x10
     68 #define VN_MOUNTRO	0x20
     69 #define VN_MOUNTRW	0x40
     70 #define VN_IGNORE	0x80
     71 
     72 int nvndisks;
     73 
     74 int all = 0;
     75 int verbose = 0;
     76 char *configfile;
     77 char *pname;
     78 
     79 char *rawdevice __P((char *));
     80 
     81 main(argc, argv)
     82 	char **argv;
     83 {
     84 	extern int optind, optopt, opterr;
     85 	extern char *optarg;
     86 	register int i, rv;
     87 	int flags = 0;
     88 
     89 	pname = argv[0];
     90 	configfile = _PATH_VNTAB;
     91 	while ((i = getopt(argc, argv, "acdef:uv")) != EOF)
     92 		switch (i) {
     93 
     94 		/* all -- use config file */
     95 		case 'a':
     96 			all++;
     97 			break;
     98 
     99 		/* configure */
    100 		case 'c':
    101 			flags |= VN_CONFIG;
    102 			flags &= ~VN_UNCONFIG;
    103 			break;
    104 
    105 		/* disable */
    106 		case 'd':
    107 			flags |= VN_DISABLE;
    108 			flags &= ~VN_ENABLE;
    109 			break;
    110 
    111 		/* enable */
    112 		case 'e':
    113 			flags |= (VN_ENABLE|VN_CONFIG);
    114 			flags &= ~(VN_DISABLE|VN_UNCONFIG);
    115 			break;
    116 
    117 		/* alternate config file */
    118 		case 'f':
    119 			configfile = optarg;
    120 			break;
    121 
    122 		/* unconfigure */
    123 		case 'u':
    124 			flags |= (VN_DISABLE|VN_UNCONFIG);
    125 			flags &= ~(VN_ENABLE|VN_CONFIG);
    126 			break;
    127 
    128 		/* verbose */
    129 		case 'v':
    130 			verbose++;
    131 			break;
    132 
    133 		default:
    134 			fprintf(stderr, "invalid option '%c'\n", optopt);
    135 			usage();
    136 		}
    137 
    138 	if (flags == 0)
    139 		flags = VN_CONFIG;
    140 	if (all)
    141 		readconfig(flags);
    142 	else {
    143 		if (argc < optind + 2)
    144 			usage();
    145 		vndisks[0].dev = argv[optind++];
    146 		vndisks[0].file = argv[optind++];
    147 		vndisks[0].flags = flags;
    148 		if (optind < argc)
    149 			getoptions(&vndisks[0], argv[optind]);
    150 		nvndisks = 1;
    151 	}
    152 	rv = 0;
    153 	for (i = 0; i < nvndisks; i++)
    154 		rv += config(&vndisks[i]);
    155 	exit(rv);
    156 }
    157 
    158 config(vnp)
    159 	struct vndisk *vnp;
    160 {
    161 	char *dev, *file, *oarg;
    162 	int flags;
    163 	struct vn_ioctl vnio;
    164 	register int rv;
    165 	char *rdev;
    166 	FILE *f;
    167 	extern int errno;
    168 
    169 	dev = vnp->dev;
    170 	file = vnp->file;
    171 	flags = vnp->flags;
    172 	oarg = vnp->oarg;
    173 
    174 	if (flags & VN_IGNORE)
    175 		return(0);
    176 
    177 	rdev = rawdevice(dev);
    178 	f = fopen(rdev, "rw");
    179 	if (f == NULL) {
    180 		perror("open");
    181 		return(1);
    182 	}
    183 	vnio.vn_file = file;
    184 
    185 	/*
    186 	 * Disable the device
    187 	 */
    188 	if (flags & VN_DISABLE) {
    189 		if (flags & (VN_MOUNTRO|VN_MOUNTRW)) {
    190 			rv = unmount(oarg, 0);
    191 			if (rv) {
    192 				if (errno == EBUSY)
    193 					flags &= ~VN_UNCONFIG;
    194 				if ((flags & VN_UNCONFIG) == 0)
    195 					perror("umount");
    196 			} else if (verbose)
    197 				printf("%s: unmounted\n", dev);
    198 		}
    199 	}
    200 	/*
    201 	 * Clear (un-configure) the device
    202 	 */
    203 	if (flags & VN_UNCONFIG) {
    204 		rv = ioctl(fileno(f), VNIOCCLR, &vnio);
    205 		if (rv) {
    206 			if (errno == ENODEV) {
    207 				if (verbose)
    208 					printf("%s: not configured\n", dev);
    209 				rv = 0;
    210 			} else
    211 				perror("VNIOCCLR");
    212 		} else if (verbose)
    213 			printf("%s: cleared\n", dev);
    214 	}
    215 	/*
    216 	 * Configure the device
    217 	 */
    218 	if (flags & VN_CONFIG) {
    219 		rv = ioctl(fileno(f), VNIOCSET, &vnio);
    220 		if (rv) {
    221 			perror("VNIOCSET");
    222 			flags &= ~VN_ENABLE;
    223 		} else if (verbose)
    224 			printf("%s: %d bytes on %s\n",
    225 			       dev, vnio.vn_size, file);
    226 	}
    227 	/*
    228 	 * Enable special functions on the device
    229 	 */
    230 	if (flags & VN_ENABLE) {
    231 		if (flags & VN_SWAP) {
    232 			rv = swapon(dev);
    233 			if (rv)
    234 				perror("swapon");
    235 			else if (verbose)
    236 				printf("%s: swapping enabled\n", dev);
    237 		}
    238 		if (flags & (VN_MOUNTRO|VN_MOUNTRW)) {
    239 			struct ufs_args args;
    240 			int mflags;
    241 
    242 			args.fspec = dev;
    243 			mflags = (flags & VN_MOUNTRO) ? MNT_RDONLY : 0;
    244 			rv = mount(MOUNT_UFS, oarg, mflags, &args);
    245 			if (rv)
    246 				perror("mount");
    247 			else if (verbose)
    248 				printf("%s: mounted on %s\n", dev, oarg);
    249 		}
    250 	}
    251 done:
    252 	fclose(f);
    253 	fflush(stdout);
    254 	return(rv < 0);
    255 }
    256 
    257 #define EOL(c)		((c) == '\0' || (c) == '\n')
    258 #define WHITE(c)	((c) == ' ' || (c) == '\t' || (c) == '\n')
    259 
    260 readconfig(flags)
    261 	int flags;
    262 {
    263 	char buf[LINESIZE];
    264 	FILE *f;
    265 	register char *cp, *sp;
    266 	register int ix;
    267 
    268 	f = fopen(configfile, "r");
    269 	if (f == NULL) {
    270 		perror(configfile);
    271 		exit(1);
    272 	}
    273 	ix = 0;
    274 	while (fgets(buf, LINESIZE, f) != NULL) {
    275 		cp = buf;
    276 		if (*cp == '#')
    277 			continue;
    278 		while (!EOL(*cp) && WHITE(*cp))
    279 			cp++;
    280 		if (EOL(*cp))
    281 			continue;
    282 		sp = cp;
    283 		while (!EOL(*cp) && !WHITE(*cp))
    284 			cp++;
    285 		if (EOL(*cp))
    286 			continue;
    287 		*cp++ = '\0';
    288 		vndisks[ix].dev = malloc(cp - sp);
    289 		strcpy(vndisks[ix].dev, sp);
    290 		while (!EOL(*cp) && WHITE(*cp))
    291 			cp++;
    292 		if (EOL(*cp))
    293 			continue;
    294 		sp = cp;
    295 		while (!EOL(*cp) && !WHITE(*cp))
    296 			cp++;
    297 		*cp++ = '\0';
    298 		vndisks[ix].file = malloc(cp - sp);
    299 		strcpy(vndisks[ix].file, sp);
    300 		while (!EOL(*cp) && WHITE(*cp))
    301 			cp++;
    302 		vndisks[ix].flags = flags;
    303 		if (!EOL(*cp)) {
    304 			sp = cp;
    305 			while (!EOL(*cp) && !WHITE(*cp))
    306 				cp++;
    307 			*cp++ = '\0';
    308 			getoptions(&vndisks[ix], sp);
    309 		}
    310 		nvndisks++;
    311 		ix++;
    312 	}
    313 }
    314 
    315 getoptions(vnp, fstr)
    316 	struct vndisk *vnp;
    317 	char *fstr;
    318 {
    319 	int flags = 0;
    320 	char *oarg = NULL;
    321 
    322 	if (strcmp(fstr, "swap") == 0)
    323 		flags |= VN_SWAP;
    324 	else if (strncmp(fstr, "mount=", 6) == 0) {
    325 		flags |= VN_MOUNTRW;
    326 		oarg = &fstr[6];
    327 	} else if (strncmp(fstr, "mountrw=", 8) == 0) {
    328 		flags |= VN_MOUNTRW;
    329 		oarg = &fstr[8];
    330 	} else if (strncmp(fstr, "mountro=", 8) == 0) {
    331 		flags |= VN_MOUNTRO;
    332 		oarg = &fstr[8];
    333 	} else if (strcmp(fstr, "ignore") == 0)
    334 		flags |= VN_IGNORE;
    335 	vnp->flags |= flags;
    336 	if (oarg) {
    337 		vnp->oarg = malloc(strlen(oarg) + 1);
    338 		strcpy(vnp->oarg, oarg);
    339 	} else
    340 		vnp->oarg = NULL;
    341 }
    342 
    343 char *
    344 rawdevice(dev)
    345 	char *dev;
    346 {
    347 	register char *rawbuf, *dp, *ep;
    348 	struct stat sb;
    349 	int len;
    350 
    351 	len = strlen(dev);
    352 	rawbuf = malloc(len + 2);
    353 	strcpy(rawbuf, dev);
    354 	if (stat(rawbuf, &sb) != 0 || !S_ISCHR(sb.st_mode)) {
    355 		dp = rindex(rawbuf, '/');
    356 		if (dp) {
    357 			for (ep = &rawbuf[len]; ep > dp; --ep)
    358 				*(ep+1) = *ep;
    359 			*++ep = 'r';
    360 		}
    361 	}
    362 	return (rawbuf);
    363 }
    364 
    365 usage()
    366 {
    367 	fprintf(stderr, "usage: %s [-acdefuv] [special-device file]\n",
    368 		pname);
    369 	exit(1);
    370 }
    371