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