1 /* $NetBSD: vnconfig.c,v 1.48 2018/10/07 20:30:50 wiz Exp $ */ 2 3 /*- 4 * Copyright (c) 1997 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 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 * 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. 30 */ 31 32 /* 33 * Copyright (c) 1993 University of Utah. 34 * Copyright (c) 1990, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * This code is derived from software contributed to Berkeley by 38 * the Systems Programming Group of the University of Utah Computer 39 * Science Department. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 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. 52 * 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 63 * SUCH DAMAGE. 64 * 65 * from: Utah $Hdr: vnconfig.c 1.1 93/12/15$ 66 * 67 * @(#)vnconfig.c 8.1 (Berkeley) 12/15/93 68 */ 69 70 #include <sys/param.h> 71 #include <sys/ioctl.h> 72 #include <sys/mount.h> 73 #include <sys/buf.h> 74 #include <sys/disklabel.h> 75 #include <sys/disk.h> 76 77 #include <dev/vndvar.h> 78 79 #include <disktab.h> 80 #include <err.h> 81 #include <errno.h> 82 #include <fcntl.h> 83 #include <stddef.h> 84 #include <stdio.h> 85 #include <stdlib.h> 86 #include <string.h> 87 #include <unistd.h> 88 #include <util.h> 89 #include <paths.h> 90 #include <limits.h> 91 92 #define VND_CONFIG 1 93 #define VND_UNCONFIG 2 94 #define VND_GET 3 95 96 /* with -l we always print at least this many entries */ 97 #define DUMMY_FREE 4 98 99 static int verbose = 0; 100 static int readonly = 0; 101 static int fileio = 0; 102 static int force = 0; 103 static int compressed = 0; 104 static int minimum = DUMMY_FREE; 105 static char *tabname; 106 107 static int show(int, int, const char * const); 108 static int config(char *, char *, char *, int); 109 static int getgeom(struct vndgeom *, char *); 110 __dead static void usage(void); 111 static void show_unused(int); 112 113 int 114 main(int argc, char *argv[]) 115 { 116 int ch, rv, action = VND_CONFIG; 117 char *end; 118 unsigned long cnt; 119 120 while ((ch = getopt(argc, argv, "Fcf:lm:rit:uvz")) != -1) { 121 switch (ch) { 122 case 'F': 123 force = 1; 124 break; 125 case 'c': 126 action = VND_CONFIG; 127 break; 128 case 'f': 129 if (setdisktab(optarg) == -1) 130 usage(); 131 break; 132 case 'l': 133 action = VND_GET; 134 break; 135 case 'm': 136 cnt = strtoul(optarg, &end, 10); 137 if (cnt >= INT_MAX || end == optarg || *end != '\0') 138 usage(); 139 minimum = (int)cnt; 140 break; 141 case 'r': 142 readonly = 1; 143 break; 144 case 'i': 145 fileio = 1; 146 break; 147 case 't': 148 tabname = optarg; 149 break; 150 case 'u': 151 action = VND_UNCONFIG; 152 break; 153 case 'v': 154 verbose = 1; 155 break; 156 case 'z': 157 compressed = 1; 158 readonly = 1; 159 break; 160 default: 161 case '?': 162 usage(); 163 /* NOTREACHED */ 164 } 165 } 166 argc -= optind; 167 argv += optind; 168 169 if (action == VND_CONFIG) { 170 if ((argc < 2 || argc > 3) || 171 (argc == 3 && tabname != NULL)) 172 usage(); 173 rv = config(argv[0], argv[1], (argc == 3) ? argv[2] : NULL, 174 action); 175 } else if (action == VND_UNCONFIG) { 176 if (argc != 1 || tabname != NULL) 177 usage(); 178 rv = config(argv[0], NULL, NULL, action); 179 } else { /* VND_GET */ 180 int n, vdisk; 181 const char *vn; 182 char path[64]; 183 184 if (argc == 0) { 185 vn = "vnd0"; 186 187 vdisk = opendisk(vn, O_RDONLY, path, sizeof(path), 0); 188 if (vdisk == -1) { 189 if (minimum == 0) 190 return 1; 191 err(1, "open: %s", vn); 192 } 193 194 for (n = 0; show(vdisk, n, 0); n++) 195 continue; 196 while (n < minimum) 197 show_unused(n++); 198 close(vdisk); 199 return 0; 200 } 201 202 rv = 0; 203 while (--argc >= 0) { 204 vn = *argv++; 205 206 vdisk = opendisk(vn, O_RDONLY, path, sizeof(path), 0); 207 if (vdisk == -1) { 208 warn("open: %s", vn); 209 rv = 1; 210 continue; 211 } 212 213 if (!show(vdisk, -1, vn)) 214 rv = 1; 215 close(vdisk); 216 } 217 } 218 return rv; 219 } 220 221 static void 222 show_unused(int n) 223 { 224 if (minimum == 0) 225 return; 226 227 printf("vnd%d: not in use\n", n); 228 } 229 230 static int 231 show(int v, int n, const char * const name) 232 { 233 struct vnd_user vnu; 234 char *dev; 235 struct statvfs *mnt; 236 int i, nmount; 237 238 vnu.vnu_unit = n; 239 if (ioctl(v, VNDIOCGET, &vnu) == -1) { 240 if (errno != ENXIO) { 241 if (n != -1) 242 err(1, "VNDIOCGET"); 243 warn("%s: VNDIOCGET", name); 244 } 245 return 0; 246 } 247 248 if (vnu.vnu_ino == 0) { 249 show_unused(vnu.vnu_unit); 250 return -1; 251 } 252 253 printf("vnd%d: ", vnu.vnu_unit); 254 255 dev = devname(vnu.vnu_dev, S_IFBLK); 256 if (dev != NULL) 257 nmount = getmntinfo(&mnt, MNT_NOWAIT); 258 else { 259 mnt = NULL; 260 nmount = 0; 261 } 262 263 if (mnt != NULL) { 264 for (i = 0; i < nmount; i++) { 265 if (strncmp(mnt[i].f_mntfromname, "/dev/", 5) == 0 && 266 strcmp(mnt[i].f_mntfromname + 5, dev) == 0) 267 break; 268 } 269 if (i < nmount) 270 printf("%s (%s) ", mnt[i].f_mntonname, 271 mnt[i].f_mntfromname); 272 else 273 printf("%s ", dev); 274 } 275 else if (dev != NULL) 276 printf("%s ", dev); 277 else 278 printf("dev %llu,%llu ", 279 (unsigned long long)major(vnu.vnu_dev), 280 (unsigned long long)minor(vnu.vnu_dev)); 281 282 printf("inode %llu\n", (unsigned long long)vnu.vnu_ino); 283 return 1; 284 } 285 286 static int 287 config(char *dev, char *file, char *geom, int action) 288 { 289 struct vnd_ioctl vndio; 290 struct disklabel *lp; 291 char rdev[MAXPATHLEN + 1]; 292 int fd, rv; 293 294 fd = opendisk(dev, O_RDWR, rdev, sizeof(rdev), 0); 295 if (fd < 0) { 296 warn("%s: opendisk", rdev); 297 return (1); 298 } 299 300 memset(&vndio, 0, sizeof(vndio)); 301 #ifdef __GNUC__ 302 rv = 0; /* XXX */ 303 #endif 304 305 vndio.vnd_file = file; 306 if (geom != NULL) { 307 rv = getgeom(&vndio.vnd_geom, geom); 308 if (rv != 0) 309 errx(1, "invalid geometry: %s", geom); 310 vndio.vnd_flags = VNDIOF_HASGEOM; 311 } else if (tabname != NULL) { 312 lp = getdiskbyname(tabname); 313 if (lp == NULL) 314 errx(1, "unknown disk type: %s", tabname); 315 vndio.vnd_geom.vng_secsize = lp->d_secsize; 316 vndio.vnd_geom.vng_nsectors = lp->d_nsectors; 317 vndio.vnd_geom.vng_ntracks = lp->d_ntracks; 318 vndio.vnd_geom.vng_ncylinders = lp->d_ncylinders; 319 vndio.vnd_flags = VNDIOF_HASGEOM; 320 } 321 322 if (readonly) 323 vndio.vnd_flags |= VNDIOF_READONLY; 324 325 if (compressed) 326 vndio.vnd_flags |= VNF_COMP; 327 328 if (fileio) 329 vndio.vnd_flags |= VNDIOF_FILEIO; 330 331 /* 332 * Clear (un-configure) the device 333 */ 334 if (action == VND_UNCONFIG) { 335 if (force) 336 vndio.vnd_flags |= VNDIOF_FORCE; 337 rv = ioctl(fd, VNDIOCCLR, &vndio); 338 #ifdef VNDIOOCCLR 339 if (rv && errno == ENOTTY) 340 rv = ioctl(fd, VNDIOOCCLR, &vndio); 341 #endif 342 if (rv) 343 warn("%s: VNDIOCCLR", rdev); 344 else if (verbose) 345 printf("%s: cleared\n", rdev); 346 } 347 /* 348 * Configure the device 349 */ 350 if (action == VND_CONFIG) { 351 int ffd; 352 353 ffd = open(file, readonly ? O_RDONLY : O_RDWR); 354 if (ffd < 0) { 355 warn("%s", file); 356 rv = -1; 357 } else { 358 (void) close(ffd); 359 360 rv = ioctl(fd, VNDIOCSET, &vndio); 361 #ifdef VNDIOOCSET 362 if (rv && errno == ENOTTY) { 363 rv = ioctl(fd, VNDIOOCSET, &vndio); 364 vndio.vnd_size = vndio.vnd_osize; 365 } 366 #endif 367 if (rv) 368 warn("%s: VNDIOCSET", rdev); 369 else if (verbose) { 370 printf("%s: %" PRIu64 " bytes on %s", rdev, 371 vndio.vnd_size, file); 372 if (vndio.vnd_flags & VNDIOF_HASGEOM) 373 printf(" using geometry %d/%d/%d/%d", 374 vndio.vnd_geom.vng_secsize, 375 vndio.vnd_geom.vng_nsectors, 376 vndio.vnd_geom.vng_ntracks, 377 vndio.vnd_geom.vng_ncylinders); 378 printf("\n"); 379 } 380 } 381 } 382 383 (void) close(fd); 384 fflush(stdout); 385 return (rv < 0); 386 } 387 388 static int 389 getgeom(struct vndgeom *vng, char *cp) 390 { 391 char *secsize, *nsectors, *ntracks, *ncylinders; 392 393 #define GETARG(arg) \ 394 do { \ 395 if (cp == NULL || *cp == '\0') \ 396 return (1); \ 397 arg = strsep(&cp, "/"); \ 398 if (arg == NULL) \ 399 return (1); \ 400 } while (0) 401 402 GETARG(secsize); 403 GETARG(nsectors); 404 GETARG(ntracks); 405 GETARG(ncylinders); 406 407 #undef GETARG 408 409 /* Too many? */ 410 if (cp != NULL) 411 return (1); 412 413 #define CVTARG(str, num) \ 414 do { \ 415 num = strtol(str, &cp, 10); \ 416 if (*cp != '\0') \ 417 return (1); \ 418 } while (0) 419 420 CVTARG(secsize, vng->vng_secsize); 421 CVTARG(nsectors, vng->vng_nsectors); 422 CVTARG(ntracks, vng->vng_ntracks); 423 CVTARG(ncylinders, vng->vng_ncylinders); 424 425 #undef CVTARG 426 427 return (0); 428 } 429 430 static void 431 usage(void) 432 { 433 const char *p = getprogname(); 434 (void)fprintf(stderr, 435 "Usage: %s [-cirvz] [-f dsktab] [-t type] vnode_disk" 436 " reg-file [geomspec]\n" 437 " %s -u [-Fv] vnode_disk\n" 438 " %s -l [-m num | vnode_disk...]\n", p, p, p); 439 exit(1); 440 } 441