Merge branch 'vendor/MDOCML'
[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. 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
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
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
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
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 %s\n", file);
394                                                 return(0);
395                                         }
396                                         st.st_size -= (off_t)n;
397                                 }
398                         }
399                         close(fd);
400                 } else {
401                         printf("Unable to open file %s\n", file);
402                         return(0);
403                 }
404         } else if (file == NULL && vnp->size == 0 && (flags & VN_CONFIG)) {
405                 warnx("specify regular filename or swap size");
406                 return (0);
407         }
408
409         rdev = rawdevice(dev);
410         f = fopen(rdev, "rw");
411         if (f == NULL) {
412                 warn("%s", dev);
413                 return(1);
414         }
415         if (!strcmp(rdev, "/dev/vn")) {
416                 printf("Using: %s\n", fdevname(fileno(f)));
417                 rv = asprintf(&dev, "%s%s", _PATH_DEV, fdevname(fileno(f)));
418                 if (rv < 0)
419                         dev = fdevname(fileno(f));
420         }
421
422         vnio.vn_file = file;
423         vnio.vn_size = vnp->size;       /* non-zero only if swap backed */
424
425         /*
426          * Disable the device
427          */
428         if (flags & VN_DISABLE) {
429                 if (flags & (VN_MOUNTRO|VN_MOUNTRW)) {
430                         rv = unmount(oarg, 0);
431                         if (rv) {
432                                 status--;
433                                 if (errno == EBUSY)
434                                         flags &= ~VN_UNCONFIG;
435                                 if ((flags & VN_UNCONFIG) == 0)
436                                         warn("umount");
437                         } else if (verbose)
438                                 printf("%s: unmounted\n", dev);
439                 }
440         }
441         /*
442          * Clear (un-configure) the device
443          */
444         if (flags & VN_UNCONFIG) {
445                 rv = ioctl(fileno(f), VNIOCDETACH, &vnio);
446                 if (rv) {
447                         if (errno == ENODEV) {
448                                 if (verbose)
449                                         printf("%s: not configured\n", dev);
450                                 rv = 0;
451                         } else {
452                                 status--;
453                                 warn("VNIOCDETACH");
454                         }
455                 } else if (verbose)
456                         printf("%s: cleared\n", dev);
457         }
458         /*
459          * Set specified options
460          */
461         if (flags & VN_SET) {
462                 l = setopt;
463                 if (global)
464                         rv = ioctl(fileno(f), VNIOCGSET, &l);
465                 else
466                         rv = ioctl(fileno(f), VNIOCUSET, &l);
467                 if (rv) {
468                         status--;
469                         warn("VNIO[GU]SET");
470                 } else if (verbose)
471                         printf("%s: flags now=%08lx\n",dev,l);
472         }
473         /*
474          * Reset specified options
475          */
476         if (flags & VN_RESET) {
477                 l = resetopt;
478                 if (global)
479                         rv = ioctl(fileno(f), VNIOCGCLEAR, &l);
480                 else
481                         rv = ioctl(fileno(f), VNIOCUCLEAR, &l);
482                 if (rv) {
483                         status--;
484                         warn("VNIO[GU]CLEAR");
485                 } else if (verbose)
486                         printf("%s: flags now=%08lx\n",dev,l);
487         }
488         /*
489          * Configure the device
490          */
491         if (flags & VN_CONFIG) {
492                 rv = ioctl(fileno(f), VNIOCATTACH, &vnio);
493                 if (rv) {
494                         status--;
495                         warn("VNIOCATTACH");
496                         flags &= ~VN_ENABLE;
497                 } else {
498                         if (verbose) {
499                                 printf("%s: %s, ", dev, file);
500                                 if (vnp->size != 0) {
501                                     printf("%jd bytes mapped\n", (intmax_t)vnio.vn_size);
502                                 } else {
503                                     printf("complete file mapped\n");
504                                 }
505                         }
506                         /*
507                          * autolabel
508                          */
509                         if (vnp->autolabel) {
510                                 do_autolabel(vnp->dev, vnp->autolabel);
511                         }
512                 }
513         }
514         /*
515          * Set an option
516          */
517         if (flags & VN_SET) {
518                 l = setopt;
519                 if (global)
520                         rv = ioctl(fileno(f), VNIOCGSET, &l);
521                 else
522                         rv = ioctl(fileno(f), VNIOCUSET, &l);
523                 if (rv) {
524                         status--;
525                         warn("VNIO[GU]SET");
526                 } else if (verbose)
527                         printf("%s: flags now=%08lx\n",dev,l);
528         }
529         /*
530          * Reset an option
531          */
532         if (flags & VN_RESET) {
533                 l = resetopt;
534                 if (global)
535                         rv = ioctl(fileno(f), VNIOCGCLEAR, &l);
536                 else
537                         rv = ioctl(fileno(f), VNIOCUCLEAR, &l);
538                 if (rv) {
539                         status--;
540                         warn("VNIO[GU]CLEAR");
541                 } else if (verbose)
542                         printf("%s: flags now=%08lx\n",dev,l);
543         }
544
545         /*
546          * Close the device now, as we may want to mount it.
547          */
548         fclose(f);
549
550         /*
551          * Enable special functions on the device
552          */
553         if (flags & VN_ENABLE) {
554                 if (flags & VN_SWAP) {
555                         rv = swapon(dev);
556                         if (rv) {
557                                 status--;
558                                 warn("swapon");
559                         }
560                         else if (verbose)
561                                 printf("%s: swapping enabled\n", dev);
562                 }
563                 if (flags & (VN_MOUNTRO|VN_MOUNTRW)) {
564                         struct ufs_args args;
565                         int mflags;
566
567                         args.fspec = dev;
568                         mflags = (flags & VN_MOUNTRO) ? MNT_RDONLY : 0;
569                         rv = mount("ufs", oarg, mflags, &args);
570                         if (rv) {
571                                 status--;
572                                 warn("mount");
573                         }
574                         else if (verbose)
575                                 printf("%s: mounted on %s\n", dev, oarg);
576                 }
577         }
578 /* done: */
579         fflush(stdout);
580         return(status < 0);
581 }
582
583 #define EOL(c)          ((c) == '\0' || (c) == '\n')
584 #define WHITE(c)        ((c) == ' ' || (c) == '\t' || (c) == '\n')
585
586 void
587 readconfig(int flags)
588 {
589         char buf[LINESIZE];
590         FILE *f;
591         char *cp, *sp;
592         int ix;
593         int ax;
594
595         f = fopen(configfile, "r");
596         if (f == NULL)
597                 err(1, "%s", configfile);
598         ix = 0;         /* number of elements */
599         ax = 0;         /* allocated elements */
600         while (fgets(buf, LINESIZE, f) != NULL) {
601                 cp = buf;
602                 if (*cp == '#')
603                         continue;
604                 while (!EOL(*cp) && WHITE(*cp))
605                         cp++;
606                 if (EOL(*cp))
607                         continue;
608                 sp = cp;
609                 while (!EOL(*cp) && !WHITE(*cp))
610                         cp++;
611                 if (EOL(*cp))
612                         continue;
613                 *cp++ = '\0';
614
615                 if (ix == ax) {
616                         ax = ax + 16;
617                         vndisks = realloc(vndisks, ax * sizeof(struct vndisk));
618                         bzero(&vndisks[ix], (ax - ix) * sizeof(struct vndisk));
619                 }
620                 vndisks[ix].dev = malloc(cp - sp);
621                 strcpy(vndisks[ix].dev, sp);
622                 while (!EOL(*cp) && WHITE(*cp))
623                         cp++;
624                 if (EOL(*cp))
625                         continue;
626                 sp = cp;
627                 while (!EOL(*cp) && !WHITE(*cp))
628                         cp++;
629                 *cp++ = '\0';
630
631                 if (*sp == '%' && strtol(sp + 1, NULL, 0) > 0) {
632                         vndisks[ix].size = getsize(sp + 1);
633                 } else {
634                         vndisks[ix].file = malloc(cp - sp);
635                         strcpy(vndisks[ix].file, sp);
636                 }
637
638                 while (!EOL(*cp) && WHITE(*cp))
639                         cp++;
640                 vndisks[ix].flags = flags;
641                 if (!EOL(*cp)) {
642                         sp = cp;
643                         while (!EOL(*cp) && !WHITE(*cp))
644                                 cp++;
645                         *cp++ = '\0';
646                         getoptions(&vndisks[ix], sp);
647                 }
648                 nvndisks++;
649                 ix++;
650         }
651 }
652
653 void
654 getoptions(struct vndisk *vnp, const char *fstr)
655 {
656         int flags = 0;
657         const char *oarg = NULL;
658
659         if (strcmp(fstr, "swap") == 0)
660                 flags |= VN_SWAP;
661         else if (strncmp(fstr, "mount=", 6) == 0) {
662                 flags |= VN_MOUNTRW;
663                 oarg = &fstr[6];
664         } else if (strncmp(fstr, "mountrw=", 8) == 0) {
665                 flags |= VN_MOUNTRW;
666                 oarg = &fstr[8];
667         } else if (strncmp(fstr, "mountro=", 8) == 0) {
668                 flags |= VN_MOUNTRO;
669                 oarg = &fstr[8];
670         } else if (strcmp(fstr, "ignore") == 0)
671                 flags |= VN_IGNORE;
672         vnp->flags |= flags;
673         if (oarg) {
674                 vnp->oarg = malloc(strlen(oarg) + 1);
675                 strcpy(vnp->oarg, oarg);
676         } else
677                 vnp->oarg = NULL;
678 }
679
680 char *
681 rawdevice(const char *dev)
682 {
683         char *rawbuf, *dp, *ep;
684         struct stat sb;
685         int len;
686
687         len = strlen(dev);
688         rawbuf = malloc(len + 2);
689         strcpy(rawbuf, dev);
690         if (stat(rawbuf, &sb) != 0 || !S_ISCHR(sb.st_mode)) {
691                 dp = strrchr(rawbuf, '/');
692                 if (dp) {
693                         for (ep = &rawbuf[len]; ep > dp; --ep)
694                                 *(ep+1) = *ep;
695                         *++ep = 'r';
696                 }
697         }
698         return (rawbuf);
699 }
700
701 static void
702 usage(void)
703 {
704         fprintf(stderr, "%s\n%s\n%s\n%s\n",
705                 "usage: vnconfig [-cdeguvTZ] [-s options] [-r options]",
706                 "                [-S value] special_file [regular_file] [feature]",
707                 "       vnconfig -a [-cdeguv] [-s options] [-r options] [-f config_file]",
708                 "       vnconfig -l [special_file ...]");
709         exit(1);
710 }
711
712 static int64_t
713 getsize(const char *arg)
714 {
715         char *ptr;
716         int pgsize = getpagesize();
717         int64_t size = strtoq(arg, &ptr, 0);
718
719         switch(tolower(*ptr)) {
720         case 't':
721                 /*
722                  * GULP!  Terabytes.  It's actually possible to create
723                  * a 7.9 TB VN device, though newfs can't handle any single
724                  * filesystem larger then 1 TB.
725                  */
726                 size *= 1024;
727                 /* fall through */
728         case 'g':
729                 size *= 1024;
730                 /* fall through */
731         default:
732         case 'm':
733                 size *= 1024;
734                 /* fall through */
735         case 'k':
736                 size *= 1024;
737                 /* fall through */
738         case 'c':
739                 break;
740         }
741         size = (size + pgsize - 1) / pgsize;
742         return(size);
743 }
744
745 /*
746  * DO_AUTOLABEL
747  *
748  *      Automatically label the device.  This will wipe any preexisting
749  *      label.
750  */
751
752 static void
753 do_autolabel(const char *dev __unused, const char *label __unused)
754 {
755         /* XXX not yet implemented */
756         fprintf(stderr, "autolabel not yet implemented, sorry\n");
757         exit(1);
758 }
759