xref: /dragonfly/usr.sbin/vnconfig/vnconfig.c (revision 7485684f)
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. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * from: Utah $Hdr: vnconfig.c 1.1 93/12/15$
35  *
36  * @(#)vnconfig.c	8.1 (Berkeley) 12/15/93
37  * $FreeBSD: src/usr.sbin/vnconfig/vnconfig.c,v 1.13.2.7 2003/06/02 09:10:27 maxim Exp $
38  * $DragonFly: src/usr.sbin/vnconfig/vnconfig.c,v 1.15 2008/07/27 22:36:01 thomas Exp $
39  */
40 
41 #include <ctype.h>
42 #include <err.h>
43 #include <errno.h>
44 #include <paths.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <fcntl.h>
48 #include <string.h>
49 #include <unistd.h>
50 #include <sys/param.h>
51 #include <sys/ioctl.h>
52 #include <sys/linker.h>
53 #include <sys/mount.h>
54 #include <sys/module.h>
55 #include <sys/stat.h>
56 #include <sys/vnioctl.h>
57 #include <vfs/ufs/ufsmount.h>
58 
59 #define LINESIZE	1024
60 #define ZBUFSIZE	32768
61 
62 struct vndisk {
63 	char	*dev;
64 	char	*file;
65 	char	*autolabel;
66 	int	flags;
67 	int64_t	size;
68 	char	*oarg;
69 } *vndisks;
70 
71 #define VN_CONFIG	0x01
72 #define VN_UNCONFIG	0x02
73 #define VN_ENABLE	0x04
74 #define VN_DISABLE	0x08
75 #define	VN_SWAP		0x10
76 #define VN_MOUNTRO	0x20
77 #define VN_MOUNTRW	0x40
78 #define VN_IGNORE	0x80
79 #define VN_SET		0x100
80 #define VN_RESET	0x200
81 #define VN_TRUNCATE	0x400
82 #define VN_ZERO		0x800
83 
84 int nvndisks;
85 
86 int all = 0;
87 int verbose = 0;
88 int global = 0;
89 int listopt = 0;
90 u_long setopt = 0;
91 u_long resetopt = 0;
92 const char *configfile;
93 
94 int config(struct vndisk *);
95 void getoptions(struct vndisk *, const char *);
96 int getinfo(const char *vname);
97 char *rawdevice(const char *);
98 void readconfig(int);
99 static void usage(void);
100 static int64_t getsize(const char *arg);
101 static void do_autolabel(const char *dev, const char *label);
102 int what_opt(const char *, u_long *);
103 
104 int
main(int argc,char * argv[])105 main(int argc, char *argv[])
106 {
107 	int i, rv;
108 	int flags = 0;
109 	int64_t size = 0;
110 	char *autolabel = NULL;
111 	char *s;
112 
113 	configfile = _PATH_VNTAB;
114 	while ((i = getopt(argc, argv, "acdef:glr:s:S:TZL:uv")) != -1)
115 		switch (i) {
116 
117 		/* all -- use config file */
118 		case 'a':
119 			all++;
120 			break;
121 
122 		/* configure */
123 		case 'c':
124 			flags |= VN_CONFIG;
125 			flags &= ~VN_UNCONFIG;
126 			break;
127 
128 		/* disable */
129 		case 'd':
130 			flags |= VN_DISABLE;
131 			flags &= ~VN_ENABLE;
132 			break;
133 
134 		/* enable */
135 		case 'e':
136 			flags |= (VN_ENABLE|VN_CONFIG);
137 			flags &= ~(VN_DISABLE|VN_UNCONFIG);
138 			break;
139 
140 		/* alternate config file */
141 		case 'f':
142 			configfile = optarg;
143 			break;
144 
145 		/* fiddle global options */
146 		case 'g':
147 			global = 1 - global;
148 			break;
149 
150 		/* reset options */
151 		case 'r':
152 			for (s = strtok(optarg, ","); s; s = strtok(NULL, ",")) {
153 				if (what_opt(s, &resetopt))
154 					errx(1, "invalid options '%s'", s);
155 			}
156 			flags |= VN_RESET;
157 			break;
158 
159 		case 'l':
160 			listopt = 1;
161 			break;
162 
163 		/* set options */
164 		case 's':
165 			for (s = strtok(optarg, ","); s; s = strtok(NULL, ",")) {
166 				if (what_opt(s, &setopt))
167 					errx(1, "invalid options '%s'", s);
168 			}
169 			flags |= VN_SET;
170 			break;
171 
172 		/* unconfigure */
173 		case 'u':
174 			flags |= (VN_DISABLE|VN_UNCONFIG);
175 			flags &= ~(VN_ENABLE|VN_CONFIG);
176 			break;
177 
178 		/* verbose */
179 		case 'v':
180 			verbose++;
181 			break;
182 
183 		case 'S':
184 			size = getsize(optarg);
185 			flags |= VN_CONFIG;
186 			flags &= ~VN_UNCONFIG;
187 			break;
188 
189 		case 'T':
190 			flags |= VN_TRUNCATE;
191 			break;
192 
193 		case 'Z':
194 			flags |= VN_ZERO;
195 			break;
196 
197 		case 'L':
198 			autolabel = optarg;
199 			break;
200 
201 		default:
202 			usage();
203 		}
204 
205 	if (modfind("vn") < 0)
206 		if (kldload("vn") < 0 || modfind("vn") < 0)
207 			warnx( "cannot find or load \"vn\" kernel module");
208 
209 	rv = 0;
210 	if (listopt) {
211 		if(argc > optind)
212 			while(argc > optind)
213 				rv += getinfo( argv[optind++]);
214 		else {
215 			rv = getinfo( NULL );
216 		}
217 		exit(rv);
218 	}
219 
220 	if (flags == 0)
221 		flags = VN_CONFIG;
222 	if (all) {
223 		readconfig(flags);
224 	} else {
225 		vndisks = calloc(sizeof(struct vndisk), 1);
226 		if (argc < optind + 1)
227 			usage();
228 		vndisks[0].dev = argv[optind++];
229 		vndisks[0].file = argv[optind++];	/* may be NULL */
230 		vndisks[0].flags = flags;
231 		vndisks[0].size = size;
232 		vndisks[0].autolabel = autolabel;
233 		if (optind < argc)
234 			getoptions(&vndisks[0], argv[optind]);
235 		nvndisks = 1;
236 	}
237 	rv = 0;
238 	for (i = 0; i < nvndisks; i++)
239 		rv += config(&vndisks[i]);
240 	exit(rv);
241 }
242 
243 int
what_opt(const char * str,u_long * p)244 what_opt(const char *str, u_long *p)
245 {
246 	if (!strcmp(str,"reserve")) { *p |= VN_RESERVE; return 0; }
247 	if (!strcmp(str,"labels")) { return 0; }	/* deprecated */
248 	if (!strcmp(str,"follow")) { *p |= VN_FOLLOW; return 0; }
249 	if (!strcmp(str,"debug")) { *p |= VN_DEBUG; return 0; }
250 	if (!strcmp(str,"io")) { *p |= VN_IO; return 0; }
251 	if (!strcmp(str,"all")) { *p |= ~0; return 0; }
252 	if (!strcmp(str,"none")) { *p |= 0; return 0; }
253 	return 1;
254 }
255 
256 /*
257  *
258  * GETINFO
259  *
260  *	Print vnode disk information to stdout for the device at
261  *	path 'vname', or all existing 'vn' devices if none is given.
262  *	Any 'vn' devices must exist under /dev in order to be queried.
263  *
264  *	Todo: correctly use vm_secsize for swap-backed vn's ..
265  */
266 
267 int
getinfo(const char * vname)268 getinfo( const char *vname )
269 {
270 	int i = 0, vd, printlim = 0;
271 	char vnpath[PATH_MAX];
272 	const char *tmp;
273 
274 	struct vn_user vnu;
275 	struct stat sb;
276 
277 	if (vname == NULL) {
278 		printlim = 1024;
279 	} else {
280 		tmp = vname;
281 		while (*tmp != 0) {
282 			if(isdigit(*tmp)){
283 				i = atoi(tmp);
284 				printlim = i + 1;
285 				break;
286 			}
287 			tmp++;
288 		}
289 		if (*tmp == '\0')
290 			errx(1, "unknown vn device: %s", vname);
291 	}
292 
293 	snprintf(vnpath, sizeof(vnpath), "/dev/vn%d", i);
294 
295 	vd = open(vnpath, O_RDONLY);
296 	if (vd < 0)
297 		err(1, "open: %s", vnpath);
298 
299 	for (; i<printlim; i++) {
300 
301 		bzero(&vnpath, sizeof(vnpath));
302 		bzero(&sb, sizeof(struct stat));
303 		bzero(&vnu, sizeof(struct vn_user));
304 
305 		vnu.vnu_unit = i;
306 
307 		snprintf(vnpath, sizeof(vnpath), "/dev/vn%d", vnu.vnu_unit);
308 
309 		if(stat(vnpath, &sb) < 0) {
310 			break;
311 		}
312 		else {
313 			if (ioctl(vd, VNIOCGET, &vnu) == -1) {
314 				warn("vn%d: ioctl", i);
315 					continue;
316 			}
317 
318 			fprintf(stdout, "vn%d: ", vnu.vnu_unit);
319 
320 			if (vnu.vnu_file[0] == 0)
321 				fprintf(stdout, "not in use\n");
322 			else if ((strcmp(vnu.vnu_file, _VN_USER_SWAP)) == 0)
323 				fprintf(stdout,
324 					"consuming %jd VM pages\n",
325 					(intmax_t)vnu.vnu_size);
326 			else
327 				fprintf(stdout,
328 					"covering %s on %s, inode %ju\n",
329 					vnu.vnu_file,
330 					devname(vnu.vnu_dev, S_IFBLK),
331 					(uintmax_t)vnu.vnu_ino);
332 		}
333 	}
334 	close(vd);
335 	return 0;
336 }
337 
338 int
config(struct vndisk * vnp)339 config(struct vndisk *vnp)
340 {
341 	char *dev, *file, *rdev, *oarg;
342 	FILE *f;
343 	struct vn_ioctl vnio;
344 	int flags, pgsize, rv, status;
345 	u_long l;
346 
347 	pgsize = getpagesize();
348 
349 	status = rv = 0;
350 
351 	/*
352 	 * Prepend "/dev/" to the specified device name, if necessary.
353 	 * Operate on vnp->dev because it is used later.
354 	 */
355 	if (vnp->dev[0] != '/' && vnp->dev[0] != '.')
356 		asprintf(&vnp->dev, "%s%s", _PATH_DEV, vnp->dev);
357 	dev = vnp->dev;
358 	file = vnp->file;
359 	flags = vnp->flags;
360 	oarg = vnp->oarg;
361 
362 	if (flags & VN_IGNORE)
363 		return(0);
364 
365 	/*
366 	 * When a regular file has been specified, do any requested setup
367 	 * of the file.  Truncation (also creates the file if necessary),
368 	 * sizing, and zeroing.
369 	 */
370 
371 	if (file && vnp->size != 0 && (flags & VN_CONFIG)) {
372 		int  fd;
373 		struct stat st;
374 
375 		if (flags & VN_TRUNCATE)
376 			fd = open(file, O_RDWR|O_CREAT|O_TRUNC, 0600);
377 		else
378 			fd = open(file, O_RDWR);
379 		if (fd >= 0 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
380 			if (st.st_size < vnp->size * pgsize)
381 				ftruncate(fd, vnp->size * pgsize);
382 			if (vnp->size != 0)
383 				st.st_size = vnp->size * pgsize;
384 
385 			if (flags & VN_ZERO) {
386 				char *buf = malloc(ZBUFSIZE);
387 				bzero(buf, ZBUFSIZE);
388 				while (st.st_size > 0) {
389 					int n = (st.st_size > ZBUFSIZE) ?
390 					    ZBUFSIZE : (int)st.st_size;
391 					if (write(fd, buf, n) != n) {
392 						ftruncate(fd, 0);
393 						printf("Unable to ZERO file "
394 						       "%s\n", file);
395 						return(0);
396 					}
397 					st.st_size -= (off_t)n;
398 				}
399 			}
400 			close(fd);
401 		} else {
402 			printf("Unable to open file %s\n", file);
403 			return(0);
404 		}
405 	} else if (file == NULL && vnp->size == 0 && (flags & VN_CONFIG)) {
406 		warnx("specify regular filename or swap size");
407 		return (0);
408 	}
409 
410 	rdev = rawdevice(dev);
411 	f = fopen(rdev, "rw");
412 	if (f == NULL) {
413 		warn("%s", dev);
414 		return(1);
415 	}
416 	if (!strcmp(rdev, "/dev/vn")) {
417 		printf("%s\n", fdevname(fileno(f)));
418 		rv = asprintf(&dev, "%s%s", _PATH_DEV, fdevname(fileno(f)));
419 		if (rv < 0)
420 			dev = fdevname(fileno(f));
421 	}
422 
423 	vnio.vn_file = file;
424 	vnio.vn_size = vnp->size;	/* non-zero only if swap backed */
425 
426 	/*
427 	 * Disable the device
428 	 */
429 	if (flags & VN_DISABLE) {
430 		if (flags & (VN_MOUNTRO|VN_MOUNTRW)) {
431 			rv = unmount(oarg, 0);
432 			if (rv) {
433 				status--;
434 				if (errno == EBUSY)
435 					flags &= ~VN_UNCONFIG;
436 				if ((flags & VN_UNCONFIG) == 0)
437 					warn("umount");
438 			} else if (verbose)
439 				printf("%s: unmounted\n", dev);
440 		}
441 	}
442 	/*
443 	 * Clear (un-configure) the device
444 	 */
445 	if (flags & VN_UNCONFIG) {
446 		rv = ioctl(fileno(f), VNIOCDETACH, &vnio);
447 		if (rv) {
448 			if (errno == ENODEV) {
449 				if (verbose)
450 					printf("%s: not configured\n", dev);
451 				rv = 0;
452 			} else {
453 				status--;
454 				warn("VNIOCDETACH");
455 			}
456 		} else if (verbose)
457 			printf("%s: cleared\n", dev);
458 	}
459 	/*
460 	 * Set specified options
461 	 */
462 	if (flags & VN_SET) {
463 		l = setopt;
464 		if (global)
465 			rv = ioctl(fileno(f), VNIOCGSET, &l);
466 		else
467 			rv = ioctl(fileno(f), VNIOCUSET, &l);
468 		if (rv) {
469 			status--;
470 			warn("VNIO[GU]SET");
471 		} else if (verbose)
472 			printf("%s: flags now=%08lx\n",dev,l);
473 	}
474 	/*
475 	 * Reset specified options
476 	 */
477 	if (flags & VN_RESET) {
478 		l = resetopt;
479 		if (global)
480 			rv = ioctl(fileno(f), VNIOCGCLEAR, &l);
481 		else
482 			rv = ioctl(fileno(f), VNIOCUCLEAR, &l);
483 		if (rv) {
484 			status--;
485 			warn("VNIO[GU]CLEAR");
486 		} else if (verbose)
487 			printf("%s: flags now=%08lx\n",dev,l);
488 	}
489 	/*
490 	 * Configure the device
491 	 */
492 	if (flags & VN_CONFIG) {
493 		rv = ioctl(fileno(f), VNIOCATTACH, &vnio);
494 		if (rv) {
495 			status--;
496 			warn("VNIOCATTACH");
497 			flags &= ~VN_ENABLE;
498 		} else {
499 			if (verbose) {
500 				printf("%s: %s, ", dev, file);
501 				if (vnp->size != 0) {
502 					printf("%jd bytes mapped\n",
503 					       (intmax_t)vnio.vn_size);
504 				} else {
505 					printf("complete file mapped\n");
506 				}
507 			}
508 			/*
509 			 * autolabel
510 			 */
511 			if (vnp->autolabel) {
512 				do_autolabel(vnp->dev, vnp->autolabel);
513 			}
514 		}
515 	}
516 	/*
517 	 * Set an option
518 	 */
519 	if (flags & VN_SET) {
520 		l = setopt;
521 		if (global)
522 			rv = ioctl(fileno(f), VNIOCGSET, &l);
523 		else
524 			rv = ioctl(fileno(f), VNIOCUSET, &l);
525 		if (rv) {
526 			status--;
527 			warn("VNIO[GU]SET");
528 		} else if (verbose)
529 			printf("%s: flags now=%08lx\n",dev,l);
530 	}
531 	/*
532 	 * Reset an option
533 	 */
534 	if (flags & VN_RESET) {
535 		l = resetopt;
536 		if (global)
537 			rv = ioctl(fileno(f), VNIOCGCLEAR, &l);
538 		else
539 			rv = ioctl(fileno(f), VNIOCUCLEAR, &l);
540 		if (rv) {
541 			status--;
542 			warn("VNIO[GU]CLEAR");
543 		} else if (verbose)
544 			printf("%s: flags now=%08lx\n",dev,l);
545 	}
546 
547 	/*
548 	 * Close the device now, as we may want to mount it.
549 	 */
550 	fclose(f);
551 
552 	/*
553 	 * Enable special functions on the device
554 	 */
555 	if (flags & VN_ENABLE) {
556 		if (flags & VN_SWAP) {
557 			rv = swapon(dev);
558 			if (rv) {
559 				status--;
560 				warn("swapon");
561 			}
562 			else if (verbose)
563 				printf("%s: swapping enabled\n", dev);
564 		}
565 		if (flags & (VN_MOUNTRO|VN_MOUNTRW)) {
566 			struct ufs_args args;
567 			int mflags;
568 
569 			args.fspec = dev;
570 			mflags = (flags & VN_MOUNTRO) ? MNT_RDONLY : 0;
571 			rv = mount("ufs", oarg, mflags, &args);
572 			if (rv) {
573 				status--;
574 				warn("mount");
575 			}
576 			else if (verbose)
577 				printf("%s: mounted on %s\n", dev, oarg);
578 		}
579 	}
580 /* done: */
581 	fflush(stdout);
582 	return(status < 0);
583 }
584 
585 #define EOL(c)		((c) == '\0' || (c) == '\n')
586 #define WHITE(c)	((c) == ' ' || (c) == '\t' || (c) == '\n')
587 
588 void
readconfig(int flags)589 readconfig(int flags)
590 {
591 	char buf[LINESIZE];
592 	FILE *f;
593 	char *cp, *sp;
594 	int ix;
595 	int ax;
596 
597 	f = fopen(configfile, "r");
598 	if (f == NULL)
599 		err(1, "%s", configfile);
600 	ix = 0;		/* number of elements */
601 	ax = 0;		/* allocated elements */
602 	while (fgets(buf, LINESIZE, f) != NULL) {
603 		cp = buf;
604 		if (*cp == '#')
605 			continue;
606 		while (!EOL(*cp) && WHITE(*cp))
607 			cp++;
608 		if (EOL(*cp))
609 			continue;
610 		sp = cp;
611 		while (!EOL(*cp) && !WHITE(*cp))
612 			cp++;
613 		if (EOL(*cp))
614 			continue;
615 		*cp++ = '\0';
616 
617 		if (ix == ax) {
618 			ax = ax + 16;
619 			vndisks = realloc(vndisks, ax * sizeof(struct vndisk));
620 			bzero(&vndisks[ix], (ax - ix) * sizeof(struct vndisk));
621 		}
622 		vndisks[ix].dev = malloc(cp - sp);
623 		strcpy(vndisks[ix].dev, sp);
624 		while (!EOL(*cp) && WHITE(*cp))
625 			cp++;
626 		if (EOL(*cp))
627 			continue;
628 		sp = cp;
629 		while (!EOL(*cp) && !WHITE(*cp))
630 			cp++;
631 		*cp++ = '\0';
632 
633 		if (*sp == '%' && strtol(sp + 1, NULL, 0) > 0) {
634 			vndisks[ix].size = getsize(sp + 1);
635 		} else {
636 			vndisks[ix].file = malloc(cp - sp);
637 			strcpy(vndisks[ix].file, sp);
638 		}
639 
640 		while (!EOL(*cp) && WHITE(*cp))
641 			cp++;
642 		vndisks[ix].flags = flags;
643 		if (!EOL(*cp)) {
644 			sp = cp;
645 			while (!EOL(*cp) && !WHITE(*cp))
646 				cp++;
647 			*cp++ = '\0';
648 			getoptions(&vndisks[ix], sp);
649 		}
650 		nvndisks++;
651 		ix++;
652 	}
653 }
654 
655 void
getoptions(struct vndisk * vnp,const char * fstr)656 getoptions(struct vndisk *vnp, const char *fstr)
657 {
658 	int flags = 0;
659 	const char *oarg = NULL;
660 
661 	if (strcmp(fstr, "swap") == 0)
662 		flags |= VN_SWAP;
663 	else if (strncmp(fstr, "mount=", 6) == 0) {
664 		flags |= VN_MOUNTRW;
665 		oarg = &fstr[6];
666 	} else if (strncmp(fstr, "mountrw=", 8) == 0) {
667 		flags |= VN_MOUNTRW;
668 		oarg = &fstr[8];
669 	} else if (strncmp(fstr, "mountro=", 8) == 0) {
670 		flags |= VN_MOUNTRO;
671 		oarg = &fstr[8];
672 	} else if (strcmp(fstr, "ignore") == 0)
673 		flags |= VN_IGNORE;
674 	vnp->flags |= flags;
675 	if (oarg) {
676 		vnp->oarg = malloc(strlen(oarg) + 1);
677 		strcpy(vnp->oarg, oarg);
678 	} else
679 		vnp->oarg = NULL;
680 }
681 
682 char *
rawdevice(const char * dev)683 rawdevice(const char *dev)
684 {
685 	char *rawbuf, *dp, *ep;
686 	struct stat sb;
687 	int len;
688 
689 	len = strlen(dev);
690 	rawbuf = malloc(len + 2);
691 	strcpy(rawbuf, dev);
692 	if (stat(rawbuf, &sb) != 0 || !S_ISCHR(sb.st_mode)) {
693 		dp = strrchr(rawbuf, '/');
694 		if (dp) {
695 			for (ep = &rawbuf[len]; ep > dp; --ep)
696 				*(ep+1) = *ep;
697 			*++ep = 'r';
698 		}
699 	}
700 	return (rawbuf);
701 }
702 
703 static void
usage(void)704 usage(void)
705 {
706 	fprintf(stderr, "%s\n%s\n%s\n%s\n",
707 		"usage: vnconfig [-cdeguvTZ] [-s options] [-r options]",
708 		"                [-S value] special_file [regular_file] [feature]",
709 		"       vnconfig -a [-cdeguv] [-s options] [-r options] [-f config_file]",
710 		"       vnconfig -l [special_file ...]");
711 	exit(1);
712 }
713 
714 static int64_t
getsize(const char * arg)715 getsize(const char *arg)
716 {
717 	char *ptr;
718 	int pgsize = getpagesize();
719 	int64_t size = strtoq(arg, &ptr, 0);
720 
721 	switch(tolower(*ptr)) {
722 	case 't':
723 		/*
724 		 * GULP!  Terabytes.  It's actually possible to create
725 		 * a 7.9 TB VN device, though newfs can't handle any single
726 		 * filesystem larger then 1 TB.
727 		 */
728 		size *= 1024;
729 		/* fall through */
730 	case 'g':
731 		size *= 1024;
732 		/* fall through */
733 	default:
734 	case 'm':
735 		size *= 1024;
736 		/* fall through */
737 	case 'k':
738 		size *= 1024;
739 		/* fall through */
740 	case 'c':
741 		break;
742 	}
743 	size = (size + pgsize - 1) / pgsize;
744 	return(size);
745 }
746 
747 /*
748  * DO_AUTOLABEL
749  *
750  *	Automatically label the device.  This will wipe any preexisting
751  *	label.
752  */
753 
754 static void
do_autolabel(const char * dev __unused,const char * label __unused)755 do_autolabel(const char *dev __unused, const char *label __unused)
756 {
757 	/* XXX not yet implemented */
758 	fprintf(stderr, "autolabel not yet implemented, sorry\n");
759 	exit(1);
760 }
761 
762