1 /* $NetBSD: vnconfig.c,v 1.42 2014/05/23 20:50:16 dholland Exp $ */
4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 1993 University of Utah.
34 * Copyright (c) 1990, 1993
35 * The Regents of the University of California. All rights reserved.
37 * This code is derived from software contributed to Berkeley by
38 * the Systems Programming Group of the University of Utah Computer
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * from: Utah $Hdr: vnconfig.c 1.1 93/12/15$
67 * @(#)vnconfig.c 8.1 (Berkeley) 12/15/93
70 #include <sys/param.h>
71 #include <sys/ioctl.h>
72 #include <sys/mount.h>
75 #include <sys/disklabel.h>
77 #include <sys/bitops.h>
79 #include <minix/paths.h>
81 #endif /* !defined(__minix) */
83 #include <dev/vndvar.h>
99 #define VND_UNCONFIG 2
102 static int verbose
= 0;
103 static int readonly
= 0;
104 static int force
= 0;
105 static int compressed
= 0;
106 static char *tabname
;
108 static int service
= 1;
109 #endif /* defined(__minix) */
111 #if !defined(__minix)
112 static void show(int, int);
114 static void show(const char *, int);
115 #endif /* !defined(__minix) */
116 static int config(char *, char *, char *, int);
117 static int getgeom(struct vndgeom
*, char *);
118 __dead
static void usage(void);
122 * Start a driver instance for the given vnd name. The return value indicates
123 * whether the instance has been started successfully.
126 start_service(char *dev
)
128 char *p
, *endp
, cmd
[PATH_MAX
];
131 p
= strrchr(dev
, '/');
132 if (p
== NULL
) p
= dev
;
136 * There are two alternatives to get the instance number for the
137 * driver: either we scan the given device name, or we obtain its major
138 * number. We choose to scan the name, because major numbers are more
139 * likely to change in the future.
141 if (strncmp(p
, "vnd", 3) != 0)
143 n
= strtoul(p
+ 3, &endp
, 10);
148 printf("%s: starting driver\n", dev
);
150 snprintf(cmd
, sizeof(cmd
),
151 "%s up %s/vnd -label vnd%u -args instance=%u -dev %s",
152 _PATH_MINIX_SERVICE
, _PATH_DRIVERS
, n
, n
, dev
);
154 status
= system(cmd
);
156 if (!WIFEXITED(status
))
158 return !WEXITSTATUS(status
);
162 * Stop the driver instance responsible for the given file descriptor.
163 * The file descriptor is closed upon return.
166 stop_service(int fd
, char *dev
)
170 int openct
, stop
= 0;
172 /* Only shut down the driver if the device is opened once, by us. */
173 if (ioctl(fd
, DIOCOPENCT
, &openct
) == 0 && openct
== 1) {
174 /* We let the driver tell us what instance number it has. */
175 if (ioctl(fd
, VNDIOCGET
, &vnu
) == 0)
179 /* Close the file descriptor before shutting down the driver! */
184 printf("%s: stopping driver\n", dev
);
186 snprintf(cmd
, sizeof(cmd
), "%s down vnd%u",
187 _PATH_MINIX_SERVICE
, vnu
.vnu_unit
);
192 #endif /* defined(__minix) */
195 main(int argc
, char *argv
[])
197 int ch
, rv
, action
= VND_CONFIG
;
199 #if !defined(__minix)
200 while ((ch
= getopt(argc
, argv
, "Fcf:lrt:uvz")) != -1) {
202 /* MINIX3: added -S; no support for -f, -t, -z at this time. */
203 while ((ch
= getopt(argc
, argv
, "SFclruv")) != -1) {
204 #endif /* !defined(__minix) */
210 #endif /* defined(__minix) */
218 #if !defined(__minix)
219 if (setdisktab(optarg
) == -1)
221 #endif /* !defined(__minix) */
233 action
= VND_UNCONFIG
;
251 if (action
== VND_CONFIG
) {
252 if ((argc
< 2 || argc
> 3) ||
253 (argc
== 3 && tabname
!= NULL
))
255 rv
= config(argv
[0], argv
[1], (argc
== 3) ? argv
[2] : NULL
,
257 } else if (action
== VND_UNCONFIG
) {
258 if (argc
!= 1 || tabname
!= NULL
)
260 rv
= config(argv
[0], NULL
, NULL
, action
);
261 } else { /* VND_GET */
262 #if !defined(__minix)
268 #endif /* !defined(__minix) */
270 if (argc
!= 0 && argc
!= 1)
273 #if !defined(__minix)
274 vn
= argc
? argv
[0] : "vnd0";
276 v
= opendisk(vn
, O_RDONLY
, path
, sizeof(path
), 0);
278 err(1, "open: %s", vn
);
279 #endif /* !defined(__minix) */
282 #if !defined(__minix)
286 #endif /* !defined(__minix) */
290 #if !defined(__minix)
291 __BITMAP_TYPE(, uint32_t, 65536) bm
;
296 #endif /* !defined(__minix) */
298 if ((dirp
= opendir(_PATH_DEV
)) == NULL
)
299 err(1, "opendir: %s", _PATH_DEV
);
301 while ((dp
= readdir(dirp
)) != NULL
) {
302 #if !defined(__minix)
303 if (strncmp(dp
->d_name
, "rvnd", 4) != 0)
305 n
= atoi(dp
->d_name
+ 4);
306 if (__BITMAP_ISSET(n
, &bm
))
308 __BITMAP_SET(n
, &bm
);
311 if (strncmp(dp
->d_name
, "vnd", 3) != 0)
313 n
= strtoul(dp
->d_name
+ 3, &endp
, 10);
317 #endif /* !defined(__minix) */
322 #if !defined(__minix)
324 #endif /* !defined(__minix) */
331 #if !defined(__minix)
334 show(const char *vn
, int n
)
335 #endif /* !defined(__minix) */
345 v
= opendisk(vn
, O_RDONLY
, path
, sizeof(path
), 0);
348 err(1, "open: %s", vn
);
350 printf("vnd%d: not in use\n", n
);
353 #endif /* defined(__minix) */
356 if (ioctl(v
, VNDIOCGET
, &vnu
) == -1)
361 #endif /* defined(__minix) */
363 if (vnu
.vnu_ino
== 0) {
364 printf("vnd%d: not in use\n", vnu
.vnu_unit
);
368 printf("vnd%d: ", vnu
.vnu_unit
);
370 dev
= devname(vnu
.vnu_dev
, S_IFBLK
);
372 nmount
= getmntinfo(&mnt
, MNT_NOWAIT
);
379 for (i
= 0; i
< nmount
; i
++) {
380 if (strncmp(mnt
[i
].f_mntfromname
, "/dev/", 5) == 0 &&
381 strcmp(mnt
[i
].f_mntfromname
+ 5, dev
) == 0)
385 printf("%s (%s) ", mnt
[i
].f_mntonname
,
386 mnt
[i
].f_mntfromname
);
390 else if (dev
!= NULL
)
393 printf("dev %llu,%llu ",
394 (unsigned long long)major(vnu
.vnu_dev
),
395 (unsigned long long)minor(vnu
.vnu_dev
));
397 printf("inode %llu\n", (unsigned long long)vnu
.vnu_ino
);
401 config(char *dev
, char *file
, char *geom
, int action
)
403 struct vnd_ioctl vndio
;
404 #if !defined(__minix)
405 struct disklabel
*lp
;
408 #endif /* !defined(__minix) */
409 char rdev
[MAXPATHLEN
+ 1];
414 * MINIX does not have the concept of raw devices. As such, the access
415 * checks that apply to opening block devices, automatically apply here
416 * as well. Therefore, we must open the device as read-only, or we
417 * would be unable to un-configure a device that was configured as
418 * read-only: opening such a device as read-write would fail.
420 fd
= opendisk(dev
, O_RDONLY
, rdev
, sizeof(rdev
), 0);
422 if (fd
< 0 && errno
== ENXIO
&& action
== VND_CONFIG
&& service
) {
423 stop
= start_service(rdev
);
425 fd
= opendisk(dev
, O_RDONLY
, rdev
, sizeof(rdev
), 0);
428 fd
= opendisk(dev
, O_RDWR
, rdev
, sizeof(rdev
), 0);
429 #endif /* defined(__minix) */
431 warn("%s: opendisk", rdev
);
435 memset(&vndio
, 0, sizeof(vndio
));
440 #if !defined(__minix)
441 vndio
.vnd_file
= file
;
442 #endif /* !defined(__minix) */
444 rv
= getgeom(&vndio
.vnd_geom
, geom
);
447 stop_service(fd
, rdev
);
448 #endif /* defined(__minix) */
450 errx(1, "invalid geometry: %s", geom
);
451 vndio
.vnd_flags
= VNDIOF_HASGEOM
;
452 #if !defined(__minix)
453 } else if (tabname
!= NULL
) {
454 lp
= getdiskbyname(tabname
);
456 errx(1, "unknown disk type: %s", tabname
);
457 vndio
.vnd_geom
.vng_secsize
= lp
->d_secsize
;
458 vndio
.vnd_geom
.vng_nsectors
= lp
->d_nsectors
;
459 vndio
.vnd_geom
.vng_ntracks
= lp
->d_ntracks
;
460 vndio
.vnd_geom
.vng_ncylinders
= lp
->d_ncylinders
;
461 vndio
.vnd_flags
= VNDIOF_HASGEOM
;
462 #endif /* !defined(__minix) */
466 vndio
.vnd_flags
|= VNDIOF_READONLY
;
468 #if !defined(__minix)
470 vndio
.vnd_flags
|= VNF_COMP
;
471 #endif /* !defined(__minix) */
474 * Clear (un-configure) the device
476 if (action
== VND_UNCONFIG
) {
478 vndio
.vnd_flags
|= VNDIOF_FORCE
;
479 rv
= ioctl(fd
, VNDIOCCLR
, &vndio
);
481 if (rv
&& errno
== ENOTTY
)
482 rv
= ioctl(fd
, VNDIOOCCLR
, &vndio
);
485 warn("%s: VNDIOCCLR", rdev
);
487 printf("%s: cleared\n", rdev
);
491 #endif /* defined(__minix) */
494 * Configure the device
496 if (action
== VND_CONFIG
) {
499 ffd
= open(file
, readonly
? O_RDONLY
: O_RDWR
);
504 #if !defined(__minix)
507 vndio
.vnd_fildes
= ffd
;
508 #endif /* !defined(__minix) */
510 rv
= ioctl(fd
, VNDIOCSET
, &vndio
);
512 if (rv
&& errno
== ENOTTY
) {
513 rv
= ioctl(fd
, VNDIOOCSET
, &vndio
);
514 vndio
.vnd_size
= vndio
.vnd_osize
;
519 #endif /* defined(__minix) */
521 warn("%s: VNDIOCSET", rdev
);
523 printf("%s: %" PRIu64
" bytes on %s", rdev
,
524 vndio
.vnd_size
, file
);
525 if (vndio
.vnd_flags
& VNDIOF_HASGEOM
)
526 printf(" using geometry %d/%d/%d/%d",
527 vndio
.vnd_geom
.vng_secsize
,
528 vndio
.vnd_geom
.vng_nsectors
,
529 vndio
.vnd_geom
.vng_ntracks
,
530 vndio
.vnd_geom
.vng_ncylinders
);
535 if ((ffd
< 0 || rv
) && service
)
537 #endif /* defined(__minix) */
542 stop_service(fd
, rdev
);
544 #endif /* defined(__minix) */
551 getgeom(struct vndgeom
*vng
, char *cp
)
553 char *secsize
, *nsectors
, *ntracks
, *ncylinders
;
555 #define GETARG(arg) \
557 if (cp == NULL || *cp == '\0') \
559 arg = strsep(&cp, "/"); \
575 #define CVTARG(str, num) \
577 num = strtol(str, &cp, 10); \
582 CVTARG(secsize
, vng
->vng_secsize
);
583 CVTARG(nsectors
, vng
->vng_nsectors
);
584 CVTARG(ntracks
, vng
->vng_ntracks
);
585 CVTARG(ncylinders
, vng
->vng_ncylinders
);
596 (void)fprintf(stderr
, "%s%s",
597 #if !defined(__minix)
598 "usage: vnconfig [-crvz] [-f disktab] [-t typename] vnode_disk"
599 " regular-file [geomspec]\n",
600 " vnconfig -u [-Fv] vnode_disk\n"
602 "usage: vnconfig [-Scrv] vnode_disk regular-file [geomspec]\n",
603 " vnconfig -u [-SFv] vnode_disk\n"
604 #endif /* !defined(__minix) */
605 " vnconfig -l [vnode_disk]\n");