--- /dev/null
+.\" $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
--- /dev/null
+/* $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);
+}