1 /* $NetBSD: vnconfig.c,v 1.42 2014/05/23 20:50:16 dholland 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 #include <sys/bitops.h> 77 78 #include <dev/vndvar.h> 79 80 #include <disktab.h> 81 #include <err.h> 82 #include <dirent.h> 83 #include <errno.h> 84 #include <fcntl.h> 85 #include <stddef.h> 86 #include <stdio.h> 87 #include <stdlib.h> 88 #include <string.h> 89 #include <unistd.h> 90 #include <util.h> 91 #include <paths.h> 92 93 #define VND_CONFIG 1 94 #define VND_UNCONFIG 2 95 #define VND_GET 3 96 97 static int verbose = 0; 98 static int readonly = 0; 99 static int force = 0; 100 static int compressed = 0; 101 static char *tabname; 102 103 static void show(int, int); 104 static int config(char *, char *, char *, int); 105 static int getgeom(struct vndgeom *, char *); 106 __dead static void usage(void); 107 108 int 109 main(int argc, char *argv[]) 110 { 111 int ch, rv, action = VND_CONFIG; 112 113 while ((ch = getopt(argc, argv, "Fcf:lrt:uvz")) != -1) { 114 switch (ch) { 115 case 'F': 116 force = 1; 117 break; 118 case 'c': 119 action = VND_CONFIG; 120 break; 121 case 'f': 122 if (setdisktab(optarg) == -1) 123 usage(); 124 break; 125 case 'l': 126 action = VND_GET; 127 break; 128 case 'r': 129 readonly = 1; 130 break; 131 case 't': 132 tabname = optarg; 133 break; 134 case 'u': 135 action = VND_UNCONFIG; 136 break; 137 case 'v': 138 verbose = 1; 139 break; 140 case 'z': 141 compressed = 1; 142 readonly = 1; 143 break; 144 default: 145 case '?': 146 usage(); 147 /* NOTREACHED */ 148 } 149 } 150 argc -= optind; 151 argv += optind; 152 153 if (action == VND_CONFIG) { 154 if ((argc < 2 || argc > 3) || 155 (argc == 3 && tabname != NULL)) 156 usage(); 157 rv = config(argv[0], argv[1], (argc == 3) ? argv[2] : NULL, 158 action); 159 } else if (action == VND_UNCONFIG) { 160 if (argc != 1 || tabname != NULL) 161 usage(); 162 rv = config(argv[0], NULL, NULL, action); 163 } else { /* VND_GET */ 164 int n, v; 165 const char *vn; 166 char path[64]; 167 168 if (argc != 0 && argc != 1) 169 usage(); 170 171 vn = argc ? argv[0] : "vnd0"; 172 173 v = opendisk(vn, O_RDONLY, path, sizeof(path), 0); 174 if (v == -1) 175 err(1, "open: %s", vn); 176 177 if (argc) 178 show(v, -1); 179 else { 180 DIR *dirp; 181 struct dirent *dp; 182 __BITMAP_TYPE(, uint32_t, 65536) bm; 183 184 __BITMAP_ZERO(&bm); 185 186 if ((dirp = opendir(_PATH_DEV)) == NULL) 187 err(1, "opendir: %s", _PATH_DEV); 188 189 while ((dp = readdir(dirp)) != NULL) { 190 if (strncmp(dp->d_name, "rvnd", 4) != 0) 191 continue; 192 n = atoi(dp->d_name + 4); 193 if (__BITMAP_ISSET(n, &bm)) 194 continue; 195 __BITMAP_SET(n, &bm); 196 show(v, n); 197 } 198 199 closedir(dirp); 200 } 201 close(v); 202 rv = 0; 203 } 204 return rv; 205 } 206 207 static void 208 show(int v, int n) 209 { 210 struct vnd_user vnu; 211 char *dev; 212 struct statvfs *mnt; 213 int i, nmount; 214 215 vnu.vnu_unit = n; 216 if (ioctl(v, VNDIOCGET, &vnu) == -1) 217 err(1, "VNDIOCGET"); 218 219 if (vnu.vnu_ino == 0) { 220 printf("vnd%d: not in use\n", vnu.vnu_unit); 221 return; 222 } 223 224 printf("vnd%d: ", vnu.vnu_unit); 225 226 dev = devname(vnu.vnu_dev, S_IFBLK); 227 if (dev != NULL) 228 nmount = getmntinfo(&mnt, MNT_NOWAIT); 229 else { 230 mnt = NULL; 231 nmount = 0; 232 } 233 234 if (mnt != NULL) { 235 for (i = 0; i < nmount; i++) { 236 if (strncmp(mnt[i].f_mntfromname, "/dev/", 5) == 0 && 237 strcmp(mnt[i].f_mntfromname + 5, dev) == 0) 238 break; 239 } 240 if (i < nmount) 241 printf("%s (%s) ", mnt[i].f_mntonname, 242 mnt[i].f_mntfromname); 243 else 244 printf("%s ", dev); 245 } 246 else if (dev != NULL) 247 printf("%s ", dev); 248 else 249 printf("dev %llu,%llu ", 250 (unsigned long long)major(vnu.vnu_dev), 251 (unsigned long long)minor(vnu.vnu_dev)); 252 253 printf("inode %llu\n", (unsigned long long)vnu.vnu_ino); 254 } 255 256 static int 257 config(char *dev, char *file, char *geom, int action) 258 { 259 struct vnd_ioctl vndio; 260 struct disklabel *lp; 261 char rdev[MAXPATHLEN + 1]; 262 int fd, rv; 263 264 fd = opendisk(dev, O_RDWR, rdev, sizeof(rdev), 0); 265 if (fd < 0) { 266 warn("%s: opendisk", rdev); 267 return (1); 268 } 269 270 memset(&vndio, 0, sizeof(vndio)); 271 #ifdef __GNUC__ 272 rv = 0; /* XXX */ 273 #endif 274 275 vndio.vnd_file = file; 276 if (geom != NULL) { 277 rv = getgeom(&vndio.vnd_geom, geom); 278 if (rv != 0) 279 errx(1, "invalid geometry: %s", geom); 280 vndio.vnd_flags = VNDIOF_HASGEOM; 281 } else if (tabname != NULL) { 282 lp = getdiskbyname(tabname); 283 if (lp == NULL) 284 errx(1, "unknown disk type: %s", tabname); 285 vndio.vnd_geom.vng_secsize = lp->d_secsize; 286 vndio.vnd_geom.vng_nsectors = lp->d_nsectors; 287 vndio.vnd_geom.vng_ntracks = lp->d_ntracks; 288 vndio.vnd_geom.vng_ncylinders = lp->d_ncylinders; 289 vndio.vnd_flags = VNDIOF_HASGEOM; 290 } 291 292 if (readonly) 293 vndio.vnd_flags |= VNDIOF_READONLY; 294 295 if (compressed) 296 vndio.vnd_flags |= VNF_COMP; 297 298 /* 299 * Clear (un-configure) the device 300 */ 301 if (action == VND_UNCONFIG) { 302 if (force) 303 vndio.vnd_flags |= VNDIOF_FORCE; 304 rv = ioctl(fd, VNDIOCCLR, &vndio); 305 #ifdef VNDIOOCCLR 306 if (rv && errno == ENOTTY) 307 rv = ioctl(fd, VNDIOOCCLR, &vndio); 308 #endif 309 if (rv) 310 warn("%s: VNDIOCCLR", rdev); 311 else if (verbose) 312 printf("%s: cleared\n", rdev); 313 } 314 /* 315 * Configure the device 316 */ 317 if (action == VND_CONFIG) { 318 int ffd; 319 320 ffd = open(file, readonly ? O_RDONLY : O_RDWR); 321 if (ffd < 0) { 322 warn("%s", file); 323 rv = -1; 324 } else { 325 (void) close(ffd); 326 327 rv = ioctl(fd, VNDIOCSET, &vndio); 328 #ifdef VNDIOOCSET 329 if (rv && errno == ENOTTY) { 330 rv = ioctl(fd, VNDIOOCSET, &vndio); 331 vndio.vnd_size = vndio.vnd_osize; 332 } 333 #endif 334 if (rv) 335 warn("%s: VNDIOCSET", rdev); 336 else if (verbose) { 337 printf("%s: %" PRIu64 " bytes on %s", rdev, 338 vndio.vnd_size, file); 339 if (vndio.vnd_flags & VNDIOF_HASGEOM) 340 printf(" using geometry %d/%d/%d/%d", 341 vndio.vnd_geom.vng_secsize, 342 vndio.vnd_geom.vng_nsectors, 343 vndio.vnd_geom.vng_ntracks, 344 vndio.vnd_geom.vng_ncylinders); 345 printf("\n"); 346 } 347 } 348 } 349 350 (void) close(fd); 351 fflush(stdout); 352 return (rv < 0); 353 } 354 355 static int 356 getgeom(struct vndgeom *vng, char *cp) 357 { 358 char *secsize, *nsectors, *ntracks, *ncylinders; 359 360 #define GETARG(arg) \ 361 do { \ 362 if (cp == NULL || *cp == '\0') \ 363 return (1); \ 364 arg = strsep(&cp, "/"); \ 365 if (arg == NULL) \ 366 return (1); \ 367 } while (0) 368 369 GETARG(secsize); 370 GETARG(nsectors); 371 GETARG(ntracks); 372 GETARG(ncylinders); 373 374 #undef GETARG 375 376 /* Too many? */ 377 if (cp != NULL) 378 return (1); 379 380 #define CVTARG(str, num) \ 381 do { \ 382 num = strtol(str, &cp, 10); \ 383 if (*cp != '\0') \ 384 return (1); \ 385 } while (0) 386 387 CVTARG(secsize, vng->vng_secsize); 388 CVTARG(nsectors, vng->vng_nsectors); 389 CVTARG(ntracks, vng->vng_ntracks); 390 CVTARG(ncylinders, vng->vng_ncylinders); 391 392 #undef CVTARG 393 394 return (0); 395 } 396 397 static void 398 usage(void) 399 { 400 401 (void)fprintf(stderr, "%s%s", 402 "usage: vnconfig [-crvz] [-f disktab] [-t typename] vnode_disk" 403 " regular-file [geomspec]\n", 404 " vnconfig -u [-Fv] vnode_disk\n" 405 " vnconfig -l [vnode_disk]\n"); 406 exit(1); 407 } 408