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