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