]> Zhao Yanbai Git Server - minix.git/commitdiff
Import NetBSD vndconfig(8) 89/989/2
authorDavid van Moolenbroek <david@minix3.org>
Wed, 18 Sep 2013 12:06:46 +0000 (14:06 +0200)
committerLionel Sambuc <lionel@minix3.org>
Sat, 1 Mar 2014 08:04:54 +0000 (09:04 +0100)
The tool has been changed heavily to match our VND driver model.

NetBSD is in the process of renaming it from vnconfig(8) to
vndconfig(8). To keep things in sync, we have to play along.

Change-Id: Ie86df184f03ab00573ea76b43c9caa0412e8321d

distrib/sets/lists/minix/mi
include/minix/paths.h
releasetools/nbsd_ports
usr.sbin/Makefile
usr.sbin/vnconfig/Makefile [new file with mode: 0644]
usr.sbin/vnconfig/vnconfig.8 [new file with mode: 0644]
usr.sbin/vnconfig/vnconfig.c [new file with mode: 0644]

index ded48abb50d7eca7715969f9ae61b00e57ab39b2..71814ed0a9bff2dd23128643220d912a4944064f 100644 (file)
 ./usr/man/man8/usermod.8                                       minix-sys
 ./usr/man/man8/vbfs.8                                  minix-sys
 ./usr/man/man8/vipw.8                                  minix-sys
+./usr/man/man8/vnconfig.8                              minix-sys
+./usr/man/man8/vndconfig.8                             minix-sys
 ./usr/man/man8/zdump.8                                 minix-sys
 ./usr/man/man8/zic.8                                   minix-sys
 ./usr/man/man9                                 minix-sys
 ./usr/sbin/vfs                         minix-sys
 ./usr/sbin/vipw                                minix-sys
 ./usr/sbin/vm                          minix-sys
+./usr/sbin/vnconfig                    minix-sys
+./usr/sbin/vndconfig                   minix-sys
 ./usr/sbin/vnd                         minix-sys
 ./usr/sbin/zic                         minix-sys
 ./usr/share                            minix-sys
index 65ea4325badb9c99a9754bb9d2564ccc73ba830a..447c465afad3cec833047495a3cf142ca48c5a05 100644 (file)
@@ -17,4 +17,6 @@
 
 #define _PATH_RAMDISK  "/dev/ram"
 
+#define _PATH_DRIVERS  "/usr/sbin"
+
 #endif /* _MINIX_PATHS_H_ */
index fda6c052cac02dbe5bbec62d9ff18478feaa2d4a..80b6af0a9ef28de846852ab7e095953deb2ba998 100644 (file)
 2012/10/17 12:00:00,usr.sbin/unlink
 2011/01/04 10:30:21,usr.sbin/user
 2009/04/19 00:44:49,usr.sbin/vipw
+2013/07/31 12:00:00,usr.sbin/vnconfig
 2009/04/22 15:23:10,usr.sbin/zic
index 0282e16246536a873181f66c32ff8058adb3b976..5baeffa2a9fe1a014685e4bfa9741404dd5c541a 100644 (file)
@@ -12,6 +12,7 @@ SUBDIR= \
        rdate \
        unlink user \
        vipw \
+       vnconfig \
        zic
 
 # LSC MINIX Specific
diff --git a/usr.sbin/vnconfig/Makefile b/usr.sbin/vnconfig/Makefile
new file mode 100644 (file)
index 0000000..4916628
--- /dev/null
@@ -0,0 +1,10 @@
+#      $NetBSD: Makefile,v 1.8 2013/06/09 22:00:50 jmmv Exp $
+
+PROG=          vnconfig
+MAN=           vnconfig.8
+DPADD+=                ${LIBUTIL}
+LDADD+=                -lutil
+LINKS+=                ${BINDIR}/vnconfig ${BINDIR}/vndconfig
+MLINKS+=       vnconfig.8 vndconfig.8
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/vnconfig/vnconfig.8 b/usr.sbin/vnconfig/vnconfig.8
new file mode 100644 (file)
index 0000000..5b6ca00
--- /dev/null
@@ -0,0 +1,195 @@
+.\"    $NetBSD: vnconfig.8,v 1.39 2013/06/09 18:39:31 christos Exp $
+.\"
+.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Jason R. Thorpe.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" Copyright (c) 1993 University of Utah.
+.\" Copyright (c) 1980, 1989, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the Systems Programming Group of the University of Utah Computer
+.\" Science Department.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)vnconfig.8  8.1 (Berkeley) 6/5/93
+.\"
+.Dd June 9, 2013
+.Dt VNDCONFIG 8
+.Os
+.Sh NAME
+.Nm vndconfig
+.Nd configure vnode disks
+.Sh SYNOPSIS
+.Nm
+.Op Fl Scrv
+.Ar vnode_disk
+.Ar regular_file
+.Op Ar geomspec
+.Nm
+.Fl u
+.Op Fl SFv
+.Ar vnode_disk
+.Nm
+.Fl l
+.Op Ar vnode_disk
+.Sh DESCRIPTION
+The
+.Nm
+command configures vnode pseudo disk devices.
+It will associate the vnode disk
+.Ar vnode_disk
+with the regular file
+.Ar regular_file
+allowing the latter to be accessed as though it were a disk.
+Hence a regular file within the filesystem can be used for swapping
+or can contain a filesystem that is mounted in the name space.
+The
+.Ar vnode_disk
+is a special file of raw partition or name of vnode disk like
+.Pa vnd0 .
+.Pp
+Options indicate an action to be performed:
+.Bl -tag -width indent
+.It Fl c
+Configures the device.
+If successful, references to
+.Ar vnode_disk
+will access the contents of
+.Ar regular_file .
+.Pp
+If
+.Ar geomspec
+is specified, the vnode device will emulate the specified disk geometry.
+The format of the
+.Ar geomspec
+argument is:
+.Bd -ragged -offset indent
+.Sm off
+.Xo Ar secsize Li / Ar nsectors Li /
+.Ar ntracks Li / Ar ncylinders Xc
+.Sm on
+.Ed
+.Pp
+If geometry is not specified, the driver will choose a default based on 1MB
+cylinders.
+.Ar secsize
+is the number of bytes per sector.
+It must be an even multiple of 512.
+.Ar nsectors
+is the number of sectors per track.
+.Ar ntracks
+is the number of tracks per cylinder.
+.Ar ncylinders
+is the number of cylinders in the device.
+.It Fl S
+Do not start or stop the corresponding device driver instance.
+.It Fl F
+Force unconfiguration if the device is in use.
+Does not imply
+.Fl u .
+.It Fl l
+List the vnd devices and indicate which ones are in use.
+If a specific
+.Ar vnode_disk
+is given, then only that will be described.
+.It Fl r
+Configure the device as read-only.
+.It Fl u
+Unconfigures the device.
+.It Fl v
+Print messages to stdout describing actions taken.
+.El
+.Pp
+If no action option is given,
+.Fl c
+is assumed.
+.Sh FILES
+.Bl -tag -width /dev/vnd* -compact
+.It Pa /dev/vnd*
+.El
+.Sh EXAMPLES
+.Dl vndconfig vnd0 /tmp/diskimage
+or
+.Dl vndconfig /dev/vnd0 /tmp/diskimage
+.Pp
+Configures the vnode disk
+.Pa vnd0 .
+.Pp
+.Dl vndconfig vnd0 /tmp/floppy.img 512/18/2/80
+.Pp
+Configures the vnode disk
+.Pa vnd0
+emulating the geometry of 512 bytes per sector, 18 sectors per track,
+2 tracks per cylinder, and 80 cylinders total.
+.Pp
+.Dl vndconfig -u vnd0
+.Pp
+Unconfigures the
+.Pa vnd0
+device.
+.Sh NOTES
+If
+.Ic vnconfig -uF
+is used and the device was still in use, the driver instance
+will not be shut down, even if
+.Fl S
+was not given. One may manually shut down
+the service later with
+.Ic service down
+.Ar vndN
+where
+.Ar N
+is the instance number, or simply
+leave the driver running for later reuse.
+.Sh SEE ALSO
+.Xr opendisk 3 ,
+.Xr mount 8 ,
+.Xr umount 8
diff --git a/usr.sbin/vnconfig/vnconfig.c b/usr.sbin/vnconfig/vnconfig.c
new file mode 100644 (file)
index 0000000..e95f6d2
--- /dev/null
@@ -0,0 +1,605 @@
+/*     $NetBSD: vnconfig.c,v 1.41 2013/06/09 13:25:40 christos Exp $   */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1993 University of Utah.
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah $Hdr: vnconfig.c 1.1 93/12/15$
+ *
+ *     @(#)vnconfig.c  8.1 (Berkeley) 12/15/93
+ */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#ifndef __minix
+#include <sys/buf.h>
+#include <sys/disklabel.h>
+#include <sys/disk.h>
+#include <sys/bitops.h>
+#else
+#include <sys/wait.h>
+#endif
+
+#include <dev/vndvar.h>
+
+#include <disktab.h>
+#include <err.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+#include <paths.h>
+
+#define VND_CONFIG     1
+#define VND_UNCONFIG   2
+#define VND_GET                3
+
+static int     verbose = 0;
+static int     readonly = 0;
+static int     force = 0;
+static int     compressed = 0;
+static char    *tabname;
+#ifdef __minix
+static int     service = 1;
+#endif
+
+#ifndef __minix
+static void    show(int, int);
+#else
+static void    show(const char *, int);
+#endif
+static int     config(char *, char *, char *, int);
+static int     getgeom(struct vndgeom *, char *);
+__dead static void     usage(void);
+
+#ifdef __minix
+/*
+ * Start a driver instance for the given vnd name.  The return value indicates
+ * whether the instance has been started successfully.
+ */
+static int
+start_service(char *dev)
+{
+       char *p, *endp, cmd[PATH_MAX];
+       int n, status;
+
+       p = strrchr(dev, '/');
+       if (p == NULL) p = dev;
+       else p++;
+
+       /*
+        * There are two alternatives to get the instance number for the
+        * driver: either we scan the given device name, or we obtain its major
+        * number.  We choose to scan the name, because major numbers are more
+        * likely to change in the future.
+        */
+       if (strncmp(p, "vnd", 3) != 0)
+               return 0;
+       n = strtoul(p + 3, &endp, 10);
+       if (endp[0])
+               return 0;
+
+       if (verbose)
+               printf("%s: starting driver\n", dev);
+
+       snprintf(cmd, sizeof(cmd),
+           "%s up %s/vnd -label vnd%u -args instance=%u -dev %s",
+           _PATH_SERVICE, _PATH_DRIVERS, n, n, dev);
+
+       status = system(cmd);
+
+       if (!WIFEXITED(status))
+               return 0;
+       return !WEXITSTATUS(status);
+}
+
+/*
+ * Stop the driver instance responsible for the given file descriptor.
+ * The file descriptor is closed upon return.
+ */
+static void
+stop_service(int fd, char *dev)
+{
+       char cmd[PATH_MAX];
+       struct vnd_user vnu;
+       int openct, stop = 0;
+
+       /* Only shut down the driver if the device is opened once, by us. */
+       if (ioctl(fd, DIOCOPENCT, &openct) == 0 && openct == 1) {
+               /* We let the driver tell us what instance number it has. */
+               if (ioctl(fd, VNDIOCGET, &vnu) == 0)
+                       stop = 1;
+       }
+
+       /* Close the file descriptor before shutting down the driver! */
+       (void) close(fd);
+
+       if (stop) {
+               if (verbose)
+                       printf("%s: stopping driver\n", dev);
+
+               snprintf(cmd, sizeof(cmd), "%s down vnd%u", _PATH_SERVICE,
+                   vnu.vnu_unit);
+
+               system(cmd);
+       }
+}
+#endif
+
+int
+main(int argc, char *argv[])
+{
+       int ch, rv, action = VND_CONFIG;
+
+#ifndef __minix
+       while ((ch = getopt(argc, argv, "Fcf:lrt:uvz")) != -1) {
+#else
+       /* MINIX3: added -S; no support for -f, -t, -z at this time. */
+       while ((ch = getopt(argc, argv, "SFclruv")) != -1) {
+#endif
+               switch (ch) {
+#ifdef __minix
+               case 'S':
+                       service = 0;
+                       break;
+#endif
+               case 'F':
+                       force = 1;
+                       break;
+               case 'c':
+                       action = VND_CONFIG;
+                       break;
+               case 'f':
+#ifndef __minix
+                       if (setdisktab(optarg) == -1)
+                               usage();
+#endif
+                       break;
+               case 'l':
+                       action = VND_GET;
+                       break;
+               case 'r':
+                       readonly = 1;
+                       break;
+               case 't':
+                       tabname = optarg;
+                       break;
+               case 'u':
+                       action = VND_UNCONFIG;
+                       break;
+               case 'v':
+                       verbose = 1;
+                       break;
+               case 'z':
+                       compressed = 1;
+                       readonly = 1;
+                       break;
+               default:
+               case '?':
+                       usage();
+                       /* NOTREACHED */
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       if (action == VND_CONFIG) {
+               if ((argc < 2 || argc > 3) ||
+                   (argc == 3 && tabname != NULL))
+                       usage();
+               rv = config(argv[0], argv[1], (argc == 3) ? argv[2] : NULL,
+                   action);
+       } else if (action == VND_UNCONFIG) {
+               if (argc != 1 || tabname != NULL)
+                       usage();
+               rv = config(argv[0], NULL, NULL, action);
+       } else { /* VND_GET */
+#ifndef __minix
+               int n, v;
+               const char *vn;
+               char path[64];
+#else
+               int n;
+#endif
+
+               if (argc != 0 && argc != 1)
+                       usage();
+
+#ifndef __minix
+               vn = argc ? argv[0] : "vnd0";
+
+               v = opendisk(vn, O_RDONLY, path, sizeof(path), 0);
+               if (v == -1)
+                       err(1, "open: %s", vn);
+#endif
+
+               if (argc)
+#ifndef __minix
+                       show(v, -1);
+#else
+                       show(argv[0], -1);
+#endif
+               else {
+                       DIR *dirp;
+                       struct dirent *dp;
+#ifndef __minix
+                       __BITMAP_TYPE(, uint32_t, 65536) bm;
+
+                       __BITMAP_ZERO(&bm);
+#else
+                       char *endp;
+#endif
+
+                       if ((dirp = opendir(_PATH_DEV)) == NULL)
+                               err(1, "opendir: %s", _PATH_DEV);
+
+                       while ((dp = readdir(dirp)) != NULL) {
+#ifndef __minix
+                               if (strncmp(dp->d_name, "rvnd", 4) != 0)
+                                       continue;
+                               n = atoi(dp->d_name + 4);
+                               if (__BITMAP_ISSET(n, &bm))
+                                       continue;
+                               __BITMAP_SET(n, &bm);
+                               show(v, n);
+#else
+                               if (strncmp(dp->d_name, "vnd", 3) != 0)
+                                       continue;
+                               n = strtoul(dp->d_name + 3, &endp, 10);
+                               if (endp[0])
+                                       continue;
+                               show(dp->d_name, n);
+#endif
+                       }
+
+                       closedir(dirp);
+               }
+#ifndef __minix
+               close(v);
+#endif
+               rv = 0;
+       }
+       return rv;
+}
+
+static void
+#ifndef __minix
+show(int v, int n)
+#else
+show(const char *vn, int n)
+#endif
+{
+       struct vnd_user vnu;
+       char *dev;
+       struct statvfs *mnt;
+       int i, nmount;
+#ifdef __minix
+       int v;
+       char path[PATH_MAX];
+
+       v = opendisk(vn, O_RDONLY, path, sizeof(path), 0);
+       if (v == -1) {
+               if (n == -1)
+                       err(1, "open: %s", vn);
+               else
+                       printf("vnd%d: not in use\n", n);
+               return;
+       }
+#endif
+
+       vnu.vnu_unit = n;
+       if (ioctl(v, VNDIOCGET, &vnu) == -1)
+               err(1, "VNDIOCGET");
+
+#ifdef __minix
+       close(v);
+#endif
+
+       if (vnu.vnu_ino == 0) {
+               printf("vnd%d: not in use\n", vnu.vnu_unit);
+               return;
+       }
+
+       printf("vnd%d: ", vnu.vnu_unit);
+
+       dev = devname(vnu.vnu_dev, S_IFBLK);
+       if (dev != NULL)
+               nmount = getmntinfo(&mnt, MNT_NOWAIT);
+       else {
+               mnt = NULL;
+               nmount = 0;
+       }
+
+       if (mnt != NULL) {
+               for (i = 0; i < nmount; i++) {
+                       if (strncmp(mnt[i].f_mntfromname, "/dev/", 5) == 0 &&
+                           strcmp(mnt[i].f_mntfromname + 5, dev) == 0)
+                               break;
+               }
+               if (i < nmount)
+                       printf("%s (%s) ", mnt[i].f_mntonname,
+                           mnt[i].f_mntfromname);
+               else
+                       printf("%s ", dev);
+       }
+       else if (dev != NULL)
+               printf("%s ", dev);
+       else
+               printf("dev %llu,%llu ",
+                   (unsigned long long)major(vnu.vnu_dev),
+                   (unsigned long long)minor(vnu.vnu_dev));
+
+       printf("inode %llu\n", (unsigned long long)vnu.vnu_ino);
+}
+
+static int
+config(char *dev, char *file, char *geom, int action)
+{
+       struct vnd_ioctl vndio;
+#ifndef __minix
+       struct disklabel *lp;
+#else
+       int stop = 0;
+#endif
+       char rdev[MAXPATHLEN + 1];
+       int fd, rv;
+
+#ifdef __minix
+       /*
+        * MINIX does not have the concept of raw devices.  As such, the access
+        * checks that apply to opening block devices, automatically apply here
+        * as well.  Therefore, we must open the device as read-only, or we
+        * would be unable to un-configure a device that was configured as
+        * read-only: opening such a device as read-write would fail.
+        */
+       fd = opendisk(dev, O_RDONLY, rdev, sizeof(rdev), 0);
+
+       if (fd < 0 && errno == ENXIO && action == VND_CONFIG && service) {
+               stop = start_service(rdev);
+
+               fd = opendisk(dev, O_RDONLY, rdev, sizeof(rdev), 0);
+       }
+#else
+       fd = opendisk(dev, O_RDWR, rdev, sizeof(rdev), 0);
+#endif
+       if (fd < 0) {
+               warn("%s: opendisk", rdev);
+               return (1);
+       }
+
+       memset(&vndio, 0, sizeof(vndio));
+#ifdef __GNUC__
+       rv = 0;                 /* XXX */
+#endif
+
+#ifndef __minix
+       vndio.vnd_file = file;
+#endif
+       if (geom != NULL) {
+               rv = getgeom(&vndio.vnd_geom, geom);
+#ifdef __minix
+               if (rv && stop)
+                       stop_service(fd, rdev);
+#endif
+               if (rv != 0)
+                       errx(1, "invalid geometry: %s", geom);
+               vndio.vnd_flags = VNDIOF_HASGEOM;
+#ifndef __minix
+       } else if (tabname != NULL) {
+               lp = getdiskbyname(tabname);
+               if (lp == NULL)
+                       errx(1, "unknown disk type: %s", tabname);
+               vndio.vnd_geom.vng_secsize = lp->d_secsize;
+               vndio.vnd_geom.vng_nsectors = lp->d_nsectors;
+               vndio.vnd_geom.vng_ntracks = lp->d_ntracks;
+               vndio.vnd_geom.vng_ncylinders = lp->d_ncylinders;
+               vndio.vnd_flags = VNDIOF_HASGEOM;
+#endif
+       }
+
+       if (readonly)
+               vndio.vnd_flags |= VNDIOF_READONLY;
+
+#ifndef __minix
+       if (compressed)
+               vndio.vnd_flags |= VNF_COMP;
+#endif
+
+       /*
+        * Clear (un-configure) the device
+        */
+       if (action == VND_UNCONFIG) {
+               if (force)
+                       vndio.vnd_flags |= VNDIOF_FORCE;
+               rv = ioctl(fd, VNDIOCCLR, &vndio);
+#ifdef VNDIOOCCLR
+               if (rv && errno == ENOTTY)
+                       rv = ioctl(fd, VNDIOOCCLR, &vndio);
+#endif
+               if (rv)
+                       warn("%s: VNDIOCCLR", rdev);
+               else if (verbose)
+                       printf("%s: cleared\n", rdev);
+#ifdef __minix
+               if (!rv && service)
+                       stop = 2;
+#endif
+       }
+       /*
+        * Configure the device
+        */
+       if (action == VND_CONFIG) {
+               int     ffd;
+
+               ffd = open(file, readonly ? O_RDONLY : O_RDWR);
+               if (ffd < 0)
+                       warn("%s", file);
+               else {
+#ifndef __minix
+                       (void) close(ffd);
+#else
+                       vndio.vnd_fildes = ffd;
+#endif
+
+                       rv = ioctl(fd, VNDIOCSET, &vndio);
+#ifdef VNDIOOCSET
+                       if (rv && errno == ENOTTY) {
+                               rv = ioctl(fd, VNDIOOCSET, &vndio);
+                               vndio.vnd_size = vndio.vnd_osize;
+                       }
+#endif
+#ifdef __minix
+                       (void) close(ffd);
+#endif
+                       if (rv)
+                               warn("%s: VNDIOCSET", rdev);
+                       else if (verbose) {
+                               printf("%s: %" PRIu64 " bytes on %s", rdev,
+                                   vndio.vnd_size, file);
+                               if (vndio.vnd_flags & VNDIOF_HASGEOM)
+                                       printf(" using geometry %d/%d/%d/%d",
+                                           vndio.vnd_geom.vng_secsize,
+                                           vndio.vnd_geom.vng_nsectors,
+                                           vndio.vnd_geom.vng_ntracks,
+                                   vndio.vnd_geom.vng_ncylinders);
+                               printf("\n");
+                       }
+               }
+#ifdef __minix
+               if ((ffd < 0 || rv) && service)
+                       stop++;
+#endif
+       }
+
+#ifdef __minix
+       if (stop >= 2)
+               stop_service(fd, rdev);
+       else
+#endif
+       (void) close(fd);
+       fflush(stdout);
+       return (rv < 0);
+}
+
+static int
+getgeom(struct vndgeom *vng, char *cp)
+{
+       char *secsize, *nsectors, *ntracks, *ncylinders;
+
+#define        GETARG(arg) \
+       do { \
+               if (cp == NULL || *cp == '\0') \
+                       return (1); \
+               arg = strsep(&cp, "/"); \
+               if (arg == NULL) \
+                       return (1); \
+       } while (0)
+
+       GETARG(secsize);
+       GETARG(nsectors);
+       GETARG(ntracks);
+       GETARG(ncylinders);
+
+#undef GETARG
+
+       /* Too many? */
+       if (cp != NULL)
+               return (1);
+
+#define        CVTARG(str, num) \
+       do { \
+               num = strtol(str, &cp, 10); \
+               if (*cp != '\0') \
+                       return (1); \
+       } while (0)
+
+       CVTARG(secsize, vng->vng_secsize);
+       CVTARG(nsectors, vng->vng_nsectors);
+       CVTARG(ntracks, vng->vng_ntracks);
+       CVTARG(ncylinders, vng->vng_ncylinders);
+
+#undef CVTARG
+
+       return (0);
+}
+
+static void
+usage(void)
+{
+
+       (void)fprintf(stderr, "%s%s",
+#ifndef __minix
+           "usage: vnconfig [-crvz] [-f disktab] [-t typename] vnode_disk"
+               " regular-file [geomspec]\n",
+           "       vnconfig -u [-Fv] vnode_disk\n"
+#else
+           "usage: vnconfig [-Scrv] vnode_disk regular-file [geomspec]\n",
+           "       vnconfig -u [-SFv] vnode_disk\n"
+#endif
+           "       vnconfig -l [vnode_disk]\n");
+       exit(1);
+}