1 1.48 wiz /* $NetBSD: vnconfig.c,v 1.48 2018/10/07 20:30:50 wiz Exp $ */ 2 1.9 thorpej 3 1.9 thorpej /*- 4 1.9 thorpej * Copyright (c) 1997 The NetBSD Foundation, Inc. 5 1.9 thorpej * All rights reserved. 6 1.9 thorpej * 7 1.9 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.9 thorpej * by Jason R. Thorpe. 9 1.9 thorpej * 10 1.9 thorpej * Redistribution and use in source and binary forms, with or without 11 1.9 thorpej * modification, are permitted provided that the following conditions 12 1.9 thorpej * are met: 13 1.9 thorpej * 1. Redistributions of source code must retain the above copyright 14 1.9 thorpej * notice, this list of conditions and the following disclaimer. 15 1.9 thorpej * 2. Redistributions in binary form must reproduce the above copyright 16 1.9 thorpej * notice, this list of conditions and the following disclaimer in the 17 1.9 thorpej * documentation and/or other materials provided with the distribution. 18 1.9 thorpej * 19 1.9 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.9 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.9 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.11 jtc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.11 jtc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.9 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.9 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.9 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.9 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.9 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.9 thorpej * POSSIBILITY OF SUCH DAMAGE. 30 1.9 thorpej */ 31 1.8 thorpej 32 1.1 brezak /* 33 1.39 rmind * Copyright (c) 1993 University of Utah. 34 1.1 brezak * Copyright (c) 1990, 1993 35 1.1 brezak * The Regents of the University of California. All rights reserved. 36 1.29 agc * 37 1.29 agc * This code is derived from software contributed to Berkeley by 38 1.29 agc * the Systems Programming Group of the University of Utah Computer 39 1.29 agc * Science Department. 40 1.29 agc * 41 1.29 agc * Redistribution and use in source and binary forms, with or without 42 1.29 agc * modification, are permitted provided that the following conditions 43 1.29 agc * are met: 44 1.29 agc * 1. Redistributions of source code must retain the above copyright 45 1.29 agc * notice, this list of conditions and the following disclaimer. 46 1.29 agc * 2. Redistributions in binary form must reproduce the above copyright 47 1.29 agc * notice, this list of conditions and the following disclaimer in the 48 1.29 agc * documentation and/or other materials provided with the distribution. 49 1.29 agc * 3. Neither the name of the University nor the names of its contributors 50 1.29 agc * may be used to endorse or promote products derived from this software 51 1.29 agc * without specific prior written permission. 52 1.29 agc * 53 1.29 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 1.29 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 1.29 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 1.29 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 1.29 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 1.29 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 1.29 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 1.29 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 1.29 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 1.29 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 1.29 agc * SUCH DAMAGE. 64 1.29 agc * 65 1.29 agc * from: Utah $Hdr: vnconfig.c 1.1 93/12/15$ 66 1.29 agc * 67 1.29 agc * @(#)vnconfig.c 8.1 (Berkeley) 12/15/93 68 1.29 agc */ 69 1.29 agc 70 1.1 brezak #include <sys/param.h> 71 1.1 brezak #include <sys/ioctl.h> 72 1.1 brezak #include <sys/mount.h> 73 1.9 thorpej #include <sys/buf.h> 74 1.9 thorpej #include <sys/disklabel.h> 75 1.9 thorpej #include <sys/disk.h> 76 1.4 glass 77 1.9 thorpej #include <dev/vndvar.h> 78 1.1 brezak 79 1.16 tron #include <disktab.h> 80 1.4 glass #include <err.h> 81 1.4 glass #include <errno.h> 82 1.9 thorpej #include <fcntl.h> 83 1.38 dsl #include <stddef.h> 84 1.4 glass #include <stdio.h> 85 1.4 glass #include <stdlib.h> 86 1.4 glass #include <string.h> 87 1.10 mikel #include <unistd.h> 88 1.12 enami #include <util.h> 89 1.41 christos #include <paths.h> 90 1.44 martin #include <limits.h> 91 1.1 brezak 92 1.7 cgd #define VND_CONFIG 1 93 1.7 cgd #define VND_UNCONFIG 2 94 1.25 atatat #define VND_GET 3 95 1.1 brezak 96 1.44 martin /* with -l we always print at least this many entries */ 97 1.44 martin #define DUMMY_FREE 4 98 1.44 martin 99 1.40 joerg static int verbose = 0; 100 1.40 joerg static int readonly = 0; 101 1.47 mlelstv static int fileio = 0; 102 1.40 joerg static int force = 0; 103 1.40 joerg static int compressed = 0; 104 1.44 martin static int minimum = DUMMY_FREE; 105 1.40 joerg static char *tabname; 106 1.40 joerg 107 1.44 martin static int show(int, int, const char * const); 108 1.40 joerg static int config(char *, char *, char *, int); 109 1.40 joerg static int getgeom(struct vndgeom *, char *); 110 1.40 joerg __dead static void usage(void); 111 1.44 martin static void show_unused(int); 112 1.1 brezak 113 1.9 thorpej int 114 1.40 joerg main(int argc, char *argv[]) 115 1.1 brezak { 116 1.7 cgd int ch, rv, action = VND_CONFIG; 117 1.44 martin char *end; 118 1.44 martin unsigned long cnt; 119 1.4 glass 120 1.47 mlelstv while ((ch = getopt(argc, argv, "Fcf:lm:rit:uvz")) != -1) { 121 1.5 mycroft switch (ch) { 122 1.27 drochner case 'F': 123 1.27 drochner force = 1; 124 1.27 drochner break; 125 1.1 brezak case 'c': 126 1.7 cgd action = VND_CONFIG; 127 1.1 brezak break; 128 1.24 fredette case 'f': 129 1.24 fredette if (setdisktab(optarg) == -1) 130 1.24 fredette usage(); 131 1.24 fredette break; 132 1.25 atatat case 'l': 133 1.25 atatat action = VND_GET; 134 1.25 atatat break; 135 1.44 martin case 'm': 136 1.44 martin cnt = strtoul(optarg, &end, 10); 137 1.44 martin if (cnt >= INT_MAX || end == optarg || *end != '\0') 138 1.44 martin usage(); 139 1.44 martin minimum = (int)cnt; 140 1.44 martin break; 141 1.26 yamt case 'r': 142 1.26 yamt readonly = 1; 143 1.26 yamt break; 144 1.47 mlelstv case 'i': 145 1.47 mlelstv fileio = 1; 146 1.47 mlelstv break; 147 1.9 thorpej case 't': 148 1.9 thorpej tabname = optarg; 149 1.9 thorpej break; 150 1.1 brezak case 'u': 151 1.7 cgd action = VND_UNCONFIG; 152 1.1 brezak break; 153 1.1 brezak case 'v': 154 1.5 mycroft verbose = 1; 155 1.1 brezak break; 156 1.33 hubertf case 'z': 157 1.33 hubertf compressed = 1; 158 1.33 hubertf readonly = 1; 159 1.33 hubertf break; 160 1.1 brezak default: 161 1.5 mycroft case '?': 162 1.1 brezak usage(); 163 1.4 glass /* NOTREACHED */ 164 1.1 brezak } 165 1.5 mycroft } 166 1.5 mycroft argc -= optind; 167 1.5 mycroft argv += optind; 168 1.1 brezak 169 1.9 thorpej if (action == VND_CONFIG) { 170 1.9 thorpej if ((argc < 2 || argc > 3) || 171 1.9 thorpej (argc == 3 && tabname != NULL)) 172 1.9 thorpej usage(); 173 1.9 thorpej rv = config(argv[0], argv[1], (argc == 3) ? argv[2] : NULL, 174 1.9 thorpej action); 175 1.25 atatat } else if (action == VND_UNCONFIG) { 176 1.9 thorpej if (argc != 1 || tabname != NULL) 177 1.9 thorpej usage(); 178 1.9 thorpej rv = config(argv[0], NULL, NULL, action); 179 1.26 yamt } else { /* VND_GET */ 180 1.44 martin int n, vdisk; 181 1.37 lukem const char *vn; 182 1.37 lukem char path[64]; 183 1.25 atatat 184 1.44 martin if (argc == 0) { 185 1.44 martin vn = "vnd0"; 186 1.25 atatat 187 1.44 martin vdisk = opendisk(vn, O_RDONLY, path, sizeof(path), 0); 188 1.44 martin if (vdisk == -1) { 189 1.44 martin if (minimum == 0) 190 1.44 martin return 1; 191 1.44 martin err(1, "open: %s", vn); 192 1.44 martin } 193 1.25 atatat 194 1.44 martin for (n = 0; show(vdisk, n, 0); n++) 195 1.43 christos continue; 196 1.44 martin while (n < minimum) 197 1.44 martin show_unused(n++); 198 1.44 martin close(vdisk); 199 1.44 martin return 0; 200 1.41 christos } 201 1.44 martin 202 1.41 christos rv = 0; 203 1.44 martin while (--argc >= 0) { 204 1.44 martin vn = *argv++; 205 1.44 martin 206 1.44 martin vdisk = opendisk(vn, O_RDONLY, path, sizeof(path), 0); 207 1.44 martin if (vdisk == -1) { 208 1.44 martin warn("open: %s", vn); 209 1.44 martin rv = 1; 210 1.44 martin continue; 211 1.44 martin } 212 1.44 martin 213 1.44 martin if (!show(vdisk, -1, vn)) 214 1.44 martin rv = 1; 215 1.44 martin close(vdisk); 216 1.44 martin } 217 1.41 christos } 218 1.41 christos return rv; 219 1.41 christos } 220 1.41 christos 221 1.44 martin static void 222 1.44 martin show_unused(int n) 223 1.44 martin { 224 1.44 martin if (minimum == 0) 225 1.44 martin return; 226 1.44 martin 227 1.44 martin printf("vnd%d: not in use\n", n); 228 1.44 martin } 229 1.44 martin 230 1.43 christos static int 231 1.44 martin show(int v, int n, const char * const name) 232 1.41 christos { 233 1.41 christos struct vnd_user vnu; 234 1.41 christos char *dev; 235 1.41 christos struct statvfs *mnt; 236 1.41 christos int i, nmount; 237 1.41 christos 238 1.41 christos vnu.vnu_unit = n; 239 1.43 christos if (ioctl(v, VNDIOCGET, &vnu) == -1) { 240 1.44 martin if (errno != ENXIO) { 241 1.44 martin if (n != -1) 242 1.44 martin err(1, "VNDIOCGET"); 243 1.44 martin warn("%s: VNDIOCGET", name); 244 1.44 martin } 245 1.43 christos return 0; 246 1.43 christos } 247 1.41 christos 248 1.41 christos if (vnu.vnu_ino == 0) { 249 1.44 martin show_unused(vnu.vnu_unit); 250 1.44 martin return -1; 251 1.41 christos } 252 1.41 christos 253 1.41 christos printf("vnd%d: ", vnu.vnu_unit); 254 1.30 atatat 255 1.41 christos dev = devname(vnu.vnu_dev, S_IFBLK); 256 1.41 christos if (dev != NULL) 257 1.41 christos nmount = getmntinfo(&mnt, MNT_NOWAIT); 258 1.41 christos else { 259 1.41 christos mnt = NULL; 260 1.41 christos nmount = 0; 261 1.41 christos } 262 1.25 atatat 263 1.41 christos if (mnt != NULL) { 264 1.41 christos for (i = 0; i < nmount; i++) { 265 1.41 christos if (strncmp(mnt[i].f_mntfromname, "/dev/", 5) == 0 && 266 1.41 christos strcmp(mnt[i].f_mntfromname + 5, dev) == 0) 267 1.25 atatat break; 268 1.25 atatat } 269 1.41 christos if (i < nmount) 270 1.41 christos printf("%s (%s) ", mnt[i].f_mntonname, 271 1.41 christos mnt[i].f_mntfromname); 272 1.41 christos else 273 1.41 christos printf("%s ", dev); 274 1.9 thorpej } 275 1.41 christos else if (dev != NULL) 276 1.41 christos printf("%s ", dev); 277 1.41 christos else 278 1.41 christos printf("dev %llu,%llu ", 279 1.41 christos (unsigned long long)major(vnu.vnu_dev), 280 1.41 christos (unsigned long long)minor(vnu.vnu_dev)); 281 1.41 christos 282 1.41 christos printf("inode %llu\n", (unsigned long long)vnu.vnu_ino); 283 1.43 christos return 1; 284 1.1 brezak } 285 1.1 brezak 286 1.40 joerg static int 287 1.40 joerg config(char *dev, char *file, char *geom, int action) 288 1.1 brezak { 289 1.7 cgd struct vnd_ioctl vndio; 290 1.9 thorpej struct disklabel *lp; 291 1.12 enami char rdev[MAXPATHLEN + 1]; 292 1.9 thorpej int fd, rv; 293 1.1 brezak 294 1.22 christos fd = opendisk(dev, O_RDWR, rdev, sizeof(rdev), 0); 295 1.9 thorpej if (fd < 0) { 296 1.14 enami warn("%s: opendisk", rdev); 297 1.5 mycroft return (1); 298 1.1 brezak } 299 1.9 thorpej 300 1.9 thorpej memset(&vndio, 0, sizeof(vndio)); 301 1.10 mikel #ifdef __GNUC__ 302 1.10 mikel rv = 0; /* XXX */ 303 1.10 mikel #endif 304 1.9 thorpej 305 1.7 cgd vndio.vnd_file = file; 306 1.9 thorpej if (geom != NULL) { 307 1.9 thorpej rv = getgeom(&vndio.vnd_geom, geom); 308 1.10 mikel if (rv != 0) 309 1.10 mikel errx(1, "invalid geometry: %s", geom); 310 1.9 thorpej vndio.vnd_flags = VNDIOF_HASGEOM; 311 1.9 thorpej } else if (tabname != NULL) { 312 1.9 thorpej lp = getdiskbyname(tabname); 313 1.9 thorpej if (lp == NULL) 314 1.9 thorpej errx(1, "unknown disk type: %s", tabname); 315 1.9 thorpej vndio.vnd_geom.vng_secsize = lp->d_secsize; 316 1.9 thorpej vndio.vnd_geom.vng_nsectors = lp->d_nsectors; 317 1.9 thorpej vndio.vnd_geom.vng_ntracks = lp->d_ntracks; 318 1.9 thorpej vndio.vnd_geom.vng_ncylinders = lp->d_ncylinders; 319 1.9 thorpej vndio.vnd_flags = VNDIOF_HASGEOM; 320 1.9 thorpej } 321 1.1 brezak 322 1.26 yamt if (readonly) 323 1.27 drochner vndio.vnd_flags |= VNDIOF_READONLY; 324 1.26 yamt 325 1.33 hubertf if (compressed) 326 1.33 hubertf vndio.vnd_flags |= VNF_COMP; 327 1.33 hubertf 328 1.47 mlelstv if (fileio) 329 1.47 mlelstv vndio.vnd_flags |= VNDIOF_FILEIO; 330 1.47 mlelstv 331 1.1 brezak /* 332 1.1 brezak * Clear (un-configure) the device 333 1.1 brezak */ 334 1.7 cgd if (action == VND_UNCONFIG) { 335 1.27 drochner if (force) 336 1.27 drochner vndio.vnd_flags |= VNDIOF_FORCE; 337 1.9 thorpej rv = ioctl(fd, VNDIOCCLR, &vndio); 338 1.38 dsl #ifdef VNDIOOCCLR 339 1.38 dsl if (rv && errno == ENOTTY) 340 1.38 dsl rv = ioctl(fd, VNDIOOCCLR, &vndio); 341 1.38 dsl #endif 342 1.6 mycroft if (rv) 343 1.14 enami warn("%s: VNDIOCCLR", rdev); 344 1.6 mycroft else if (verbose) 345 1.14 enami printf("%s: cleared\n", rdev); 346 1.1 brezak } 347 1.1 brezak /* 348 1.1 brezak * Configure the device 349 1.1 brezak */ 350 1.7 cgd if (action == VND_CONFIG) { 351 1.23 tron int ffd; 352 1.23 tron 353 1.26 yamt ffd = open(file, readonly ? O_RDONLY : O_RDWR); 354 1.42 dholland if (ffd < 0) { 355 1.23 tron warn("%s", file); 356 1.42 dholland rv = -1; 357 1.42 dholland } else { 358 1.23 tron (void) close(ffd); 359 1.23 tron 360 1.23 tron rv = ioctl(fd, VNDIOCSET, &vndio); 361 1.38 dsl #ifdef VNDIOOCSET 362 1.38 dsl if (rv && errno == ENOTTY) { 363 1.38 dsl rv = ioctl(fd, VNDIOOCSET, &vndio); 364 1.38 dsl vndio.vnd_size = vndio.vnd_osize; 365 1.38 dsl } 366 1.38 dsl #endif 367 1.23 tron if (rv) 368 1.23 tron warn("%s: VNDIOCSET", rdev); 369 1.23 tron else if (verbose) { 370 1.38 dsl printf("%s: %" PRIu64 " bytes on %s", rdev, 371 1.23 tron vndio.vnd_size, file); 372 1.23 tron if (vndio.vnd_flags & VNDIOF_HASGEOM) 373 1.23 tron printf(" using geometry %d/%d/%d/%d", 374 1.23 tron vndio.vnd_geom.vng_secsize, 375 1.23 tron vndio.vnd_geom.vng_nsectors, 376 1.23 tron vndio.vnd_geom.vng_ntracks, 377 1.9 thorpej vndio.vnd_geom.vng_ncylinders); 378 1.23 tron printf("\n"); 379 1.23 tron } 380 1.9 thorpej } 381 1.1 brezak } 382 1.10 mikel 383 1.9 thorpej (void) close(fd); 384 1.1 brezak fflush(stdout); 385 1.5 mycroft return (rv < 0); 386 1.1 brezak } 387 1.1 brezak 388 1.40 joerg static int 389 1.40 joerg getgeom(struct vndgeom *vng, char *cp) 390 1.9 thorpej { 391 1.9 thorpej char *secsize, *nsectors, *ntracks, *ncylinders; 392 1.9 thorpej 393 1.9 thorpej #define GETARG(arg) \ 394 1.9 thorpej do { \ 395 1.10 mikel if (cp == NULL || *cp == '\0') \ 396 1.9 thorpej return (1); \ 397 1.9 thorpej arg = strsep(&cp, "/"); \ 398 1.9 thorpej if (arg == NULL) \ 399 1.9 thorpej return (1); \ 400 1.9 thorpej } while (0) 401 1.9 thorpej 402 1.9 thorpej GETARG(secsize); 403 1.9 thorpej GETARG(nsectors); 404 1.9 thorpej GETARG(ntracks); 405 1.9 thorpej GETARG(ncylinders); 406 1.9 thorpej 407 1.9 thorpej #undef GETARG 408 1.9 thorpej 409 1.9 thorpej /* Too many? */ 410 1.9 thorpej if (cp != NULL) 411 1.9 thorpej return (1); 412 1.9 thorpej 413 1.9 thorpej #define CVTARG(str, num) \ 414 1.9 thorpej do { \ 415 1.9 thorpej num = strtol(str, &cp, 10); \ 416 1.9 thorpej if (*cp != '\0') \ 417 1.9 thorpej return (1); \ 418 1.9 thorpej } while (0) 419 1.9 thorpej 420 1.9 thorpej CVTARG(secsize, vng->vng_secsize); 421 1.9 thorpej CVTARG(nsectors, vng->vng_nsectors); 422 1.9 thorpej CVTARG(ntracks, vng->vng_ntracks); 423 1.9 thorpej CVTARG(ncylinders, vng->vng_ncylinders); 424 1.9 thorpej 425 1.9 thorpej #undef CVTARG 426 1.9 thorpej 427 1.9 thorpej return (0); 428 1.1 brezak } 429 1.1 brezak 430 1.40 joerg static void 431 1.40 joerg usage(void) 432 1.1 brezak { 433 1.46 christos const char *p = getprogname(); 434 1.46 christos (void)fprintf(stderr, 435 1.48 wiz "Usage: %s [-cirvz] [-f dsktab] [-t type] vnode_disk" 436 1.46 christos " reg-file [geomspec]\n" 437 1.46 christos " %s -u [-Fv] vnode_disk\n" 438 1.46 christos " %s -l [-m num | vnode_disk...]\n", p, p, p); 439 1.1 brezak exit(1); 440 1.1 brezak } 441