1 1.58 mlelstv /* $NetBSD: ccdconfig.c,v 1.58 2020/10/06 18:47:07 mlelstv Exp $ */ 2 1.1 thorpej 3 1.5 thorpej /*- 4 1.8 thorpej * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. 5 1.1 thorpej * All rights reserved. 6 1.1 thorpej * 7 1.5 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.5 thorpej * by Jason R. Thorpe. 9 1.5 thorpej * 10 1.1 thorpej * Redistribution and use in source and binary forms, with or without 11 1.1 thorpej * modification, are permitted provided that the following conditions 12 1.1 thorpej * are met: 13 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 14 1.1 thorpej * notice, this list of conditions and the following disclaimer. 15 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 17 1.1 thorpej * documentation and/or other materials provided with the distribution. 18 1.1 thorpej * 19 1.5 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.5 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.5 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.13 jtc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.13 jtc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.5 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.5 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.5 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.5 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.5 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.5 thorpej * POSSIBILITY OF SUCH DAMAGE. 30 1.1 thorpej */ 31 1.1 thorpej 32 1.10 thorpej #include <sys/cdefs.h> 33 1.10 thorpej #ifndef lint 34 1.48 lukem __COPYRIGHT("@(#) Copyright (c) 1996, 1997\ 35 1.48 lukem The NetBSD Foundation, Inc. All rights reserved."); 36 1.58 mlelstv __RCSID("$NetBSD: ccdconfig.c,v 1.58 2020/10/06 18:47:07 mlelstv Exp $"); 37 1.10 thorpej #endif 38 1.29 enami 39 1.1 thorpej #include <sys/param.h> 40 1.1 thorpej #include <sys/ioctl.h> 41 1.1 thorpej #include <sys/disklabel.h> 42 1.1 thorpej #include <sys/disk.h> 43 1.1 thorpej #include <sys/stat.h> 44 1.1 thorpej #include <sys/sysctl.h> 45 1.1 thorpej #include <ctype.h> 46 1.1 thorpej #include <err.h> 47 1.1 thorpej #include <errno.h> 48 1.1 thorpej #include <fcntl.h> 49 1.1 thorpej #include <limits.h> 50 1.1 thorpej #include <nlist.h> 51 1.1 thorpej #include <stdio.h> 52 1.1 thorpej #include <stdlib.h> 53 1.1 thorpej #include <string.h> 54 1.1 thorpej #include <unistd.h> 55 1.6 thorpej #include <util.h> 56 1.1 thorpej 57 1.1 thorpej #include <dev/ccdvar.h> 58 1.1 thorpej 59 1.1 thorpej #include "pathnames.h" 60 1.1 thorpej 61 1.20 mrg 62 1.16 thorpej static size_t lineno; 63 1.20 mrg static gid_t egid; 64 1.16 thorpej static int verbose; 65 1.33 thorpej static const char *ccdconf = _PATH_CCDCONF; 66 1.1 thorpej 67 1.51 joerg static struct flagval { 68 1.33 thorpej const char *fv_flag; 69 1.1 thorpej int fv_val; 70 1.1 thorpej } flagvaltab[] = { 71 1.1 thorpej { "CCDF_UNIFORM", CCDF_UNIFORM }, 72 1.38 lukem { "CCDF_NOLABEL", CCDF_NOLABEL }, 73 1.1 thorpej { NULL, 0 }, 74 1.1 thorpej }; 75 1.1 thorpej 76 1.1 thorpej #define CCD_CONFIG 0 /* configure a device */ 77 1.1 thorpej #define CCD_CONFIGALL 1 /* configure all devices */ 78 1.1 thorpej #define CCD_UNCONFIG 2 /* unconfigure a device */ 79 1.1 thorpej #define CCD_UNCONFIGALL 3 /* unconfigure all devices */ 80 1.1 thorpej #define CCD_DUMP 4 /* dump a ccd's configuration */ 81 1.1 thorpej 82 1.40 xtraeme static int checkdev(char *); 83 1.40 xtraeme static int do_io(char *, u_long, struct ccd_ioctl *); 84 1.40 xtraeme static int do_single(int, char **, int); 85 1.40 xtraeme static int do_all(int); 86 1.40 xtraeme static int dump_ccd(int, char **, int); 87 1.40 xtraeme static int flags_to_val(char *); 88 1.40 xtraeme static int pathtounit(char *, int *); 89 1.40 xtraeme static char *resolve_ccdname(char *); 90 1.51 joerg __dead static void usage(void); 91 1.1 thorpej 92 1.1 thorpej int 93 1.40 xtraeme main(int argc, char *argv[]) 94 1.1 thorpej { 95 1.1 thorpej int ch, options = 0, action = CCD_CONFIG; 96 1.1 thorpej 97 1.20 mrg egid = getegid(); 98 1.20 mrg setegid(getgid()); 99 1.52 christos while ((ch = getopt(argc, argv, "cCf:guUv")) != -1) { 100 1.1 thorpej switch (ch) { 101 1.1 thorpej case 'c': 102 1.1 thorpej action = CCD_CONFIG; 103 1.1 thorpej ++options; 104 1.1 thorpej break; 105 1.1 thorpej 106 1.1 thorpej case 'C': 107 1.1 thorpej action = CCD_CONFIGALL; 108 1.1 thorpej ++options; 109 1.1 thorpej break; 110 1.1 thorpej 111 1.1 thorpej case 'f': 112 1.1 thorpej ccdconf = optarg; 113 1.1 thorpej break; 114 1.1 thorpej 115 1.1 thorpej case 'g': 116 1.1 thorpej action = CCD_DUMP; 117 1.1 thorpej break; 118 1.1 thorpej 119 1.1 thorpej case 'u': 120 1.1 thorpej action = CCD_UNCONFIG; 121 1.1 thorpej ++options; 122 1.1 thorpej break; 123 1.1 thorpej 124 1.1 thorpej case 'U': 125 1.1 thorpej action = CCD_UNCONFIGALL; 126 1.1 thorpej ++options; 127 1.1 thorpej break; 128 1.1 thorpej 129 1.1 thorpej case 'v': 130 1.1 thorpej verbose = 1; 131 1.1 thorpej break; 132 1.1 thorpej 133 1.1 thorpej default: 134 1.1 thorpej usage(); 135 1.1 thorpej } 136 1.1 thorpej } 137 1.1 thorpej argc -= optind; 138 1.1 thorpej argv += optind; 139 1.1 thorpej 140 1.1 thorpej if (options > 1) 141 1.1 thorpej usage(); 142 1.7 thorpej 143 1.1 thorpej switch (action) { 144 1.1 thorpej case CCD_CONFIG: 145 1.1 thorpej case CCD_UNCONFIG: 146 1.1 thorpej exit(do_single(argc, argv, action)); 147 1.1 thorpej /* NOTREACHED */ 148 1.1 thorpej 149 1.1 thorpej case CCD_CONFIGALL: 150 1.1 thorpej case CCD_UNCONFIGALL: 151 1.1 thorpej exit(do_all(action)); 152 1.1 thorpej /* NOTREACHED */ 153 1.1 thorpej 154 1.1 thorpej case CCD_DUMP: 155 1.10 thorpej default: 156 1.8 thorpej exit(dump_ccd(argc, argv, action)); 157 1.1 thorpej /* NOTREACHED */ 158 1.1 thorpej } 159 1.1 thorpej /* NOTREACHED */ 160 1.1 thorpej } 161 1.1 thorpej 162 1.1 thorpej static int 163 1.40 xtraeme do_single(int argc, char **argv, int action) 164 1.1 thorpej { 165 1.1 thorpej struct ccd_ioctl ccio; 166 1.1 thorpej char *ccd, *cp, *cp2, **disks; 167 1.56 mlelstv char buf[MAXPATHLEN]; 168 1.10 thorpej int noflags = 0, i, ileave, flags, j; 169 1.56 mlelstv unsigned int ndisks, ui; 170 1.56 mlelstv int ret = 1; 171 1.1 thorpej 172 1.10 thorpej flags = 0; 173 1.14 lukem memset(&ccio, 0, sizeof(ccio)); 174 1.1 thorpej 175 1.1 thorpej /* 176 1.1 thorpej * If unconfiguring, all arguments are treated as ccds. 177 1.1 thorpej */ 178 1.1 thorpej if (action == CCD_UNCONFIG || action == CCD_UNCONFIGALL) { 179 1.1 thorpej for (i = 0; argc != 0; ) { 180 1.1 thorpej cp = *argv++; --argc; 181 1.1 thorpej if ((ccd = resolve_ccdname(cp)) == NULL) { 182 1.1 thorpej warnx("invalid ccd name: %s", cp); 183 1.1 thorpej i = 1; 184 1.1 thorpej continue; 185 1.1 thorpej } 186 1.1 thorpej if (do_io(ccd, CCDIOCCLR, &ccio)) 187 1.1 thorpej i = 1; 188 1.1 thorpej else 189 1.1 thorpej if (verbose) 190 1.2 thorpej printf("%s unconfigured\n", cp); 191 1.44 christos free(ccd); 192 1.1 thorpej } 193 1.1 thorpej return (i); 194 1.1 thorpej } 195 1.1 thorpej 196 1.1 thorpej /* Make sure there are enough arguments. */ 197 1.23 ross if (argc < 4) { 198 1.1 thorpej if (argc == 3) { 199 1.1 thorpej /* Assume that no flags are specified. */ 200 1.1 thorpej noflags = 1; 201 1.1 thorpej } else { 202 1.1 thorpej if (action == CCD_CONFIGALL) { 203 1.16 thorpej warnx("%s: bad line: %lu", ccdconf, 204 1.16 thorpej (u_long)lineno); 205 1.1 thorpej return (1); 206 1.1 thorpej } else 207 1.1 thorpej usage(); 208 1.1 thorpej } 209 1.23 ross } 210 1.1 thorpej 211 1.1 thorpej /* First argument is the ccd to configure. */ 212 1.1 thorpej cp = *argv++; --argc; 213 1.1 thorpej if ((ccd = resolve_ccdname(cp)) == NULL) { 214 1.1 thorpej warnx("invalid ccd name: %s", cp); 215 1.1 thorpej return (1); 216 1.1 thorpej } 217 1.1 thorpej 218 1.1 thorpej /* Next argument is the interleave factor. */ 219 1.1 thorpej cp = *argv++; --argc; 220 1.1 thorpej errno = 0; /* to check for ERANGE */ 221 1.1 thorpej ileave = (int)strtol(cp, &cp2, 10); 222 1.1 thorpej if ((errno == ERANGE) || (ileave < 0) || (*cp2 != '\0')) { 223 1.1 thorpej warnx("invalid interleave factor: %s", cp); 224 1.43 hubertf free(ccd); 225 1.1 thorpej return (1); 226 1.1 thorpej } 227 1.1 thorpej 228 1.1 thorpej if (noflags == 0) { 229 1.1 thorpej /* Next argument is the ccd configuration flags. */ 230 1.1 thorpej cp = *argv++; --argc; 231 1.1 thorpej if ((flags = flags_to_val(cp)) < 0) { 232 1.1 thorpej warnx("invalid flags argument: %s", cp); 233 1.43 hubertf free(ccd); 234 1.1 thorpej return (1); 235 1.1 thorpej } 236 1.1 thorpej } 237 1.1 thorpej 238 1.1 thorpej /* Next is the list of disks to make the ccd from. */ 239 1.52 christos disks = emalloc(argc * sizeof(char *)); 240 1.56 mlelstv for (ndisks = 0; argc != 0; ++argv, --argc) { 241 1.56 mlelstv if (getfsspecname(buf, sizeof(buf), *argv) == NULL) { 242 1.56 mlelstv warn("%s", *argv); 243 1.56 mlelstv goto error; 244 1.56 mlelstv } 245 1.56 mlelstv 246 1.56 mlelstv cp = strdup(buf); 247 1.56 mlelstv if (cp == NULL) { 248 1.57 mrg warn("strdup failed"); 249 1.56 mlelstv goto error; 250 1.56 mlelstv } 251 1.56 mlelstv 252 1.1 thorpej if ((j = checkdev(cp)) == 0) 253 1.56 mlelstv disks[ndisks++] = cp; 254 1.1 thorpej else { 255 1.1 thorpej warnx("%s: %s", cp, strerror(j)); 256 1.56 mlelstv goto error; 257 1.1 thorpej } 258 1.1 thorpej } 259 1.1 thorpej 260 1.1 thorpej /* Fill in the ccio. */ 261 1.1 thorpej ccio.ccio_disks = disks; 262 1.56 mlelstv ccio.ccio_ndisks = ndisks; 263 1.1 thorpej ccio.ccio_ileave = ileave; 264 1.1 thorpej ccio.ccio_flags = flags; 265 1.1 thorpej 266 1.56 mlelstv if (do_io(ccd, CCDIOCSET, &ccio)) 267 1.56 mlelstv goto error; 268 1.1 thorpej 269 1.1 thorpej if (verbose) { 270 1.1 thorpej printf("ccd%d: %d components ", ccio.ccio_unit, 271 1.1 thorpej ccio.ccio_ndisks); 272 1.49 lukem for (ui = 0; ui < ccio.ccio_ndisks; ++ui) { 273 1.49 lukem if ((cp2 = strrchr(disks[ui], '/')) != NULL) 274 1.1 thorpej ++cp2; 275 1.1 thorpej else 276 1.49 lukem cp2 = disks[ui]; 277 1.1 thorpej printf("%c%s%c", 278 1.49 lukem ui == 0 ? '(' : ' ', cp2, 279 1.49 lukem ui == ccio.ccio_ndisks - 1 ? ')' : ','); 280 1.1 thorpej } 281 1.54 sborrill printf(", %ju blocks ", (uintmax_t)ccio.ccio_size); 282 1.1 thorpej if (ccio.ccio_ileave != 0) 283 1.1 thorpej printf("interleaved at %d blocks\n", ccio.ccio_ileave); 284 1.1 thorpej else 285 1.1 thorpej printf("concatenated\n"); 286 1.1 thorpej } 287 1.1 thorpej 288 1.56 mlelstv ret = 0; 289 1.56 mlelstv 290 1.56 mlelstv error: 291 1.43 hubertf free(ccd); 292 1.56 mlelstv while (ndisks > 0) 293 1.56 mlelstv free(disks[--ndisks]); 294 1.1 thorpej free(disks); 295 1.56 mlelstv return (ret); 296 1.1 thorpej } 297 1.1 thorpej 298 1.1 thorpej static int 299 1.40 xtraeme do_all(int action) 300 1.1 thorpej { 301 1.1 thorpej FILE *f; 302 1.35 itojun char *line, *cp, *vp, **argv, **nargv; 303 1.16 thorpej int argc, rval; 304 1.16 thorpej size_t len; 305 1.1 thorpej 306 1.10 thorpej rval = 0; 307 1.10 thorpej 308 1.17 mrg (void)setegid(getgid()); 309 1.1 thorpej if ((f = fopen(ccdconf, "r")) == NULL) { 310 1.17 mrg (void)setegid(egid); 311 1.1 thorpej warn("fopen: %s", ccdconf); 312 1.1 thorpej return (1); 313 1.1 thorpej } 314 1.17 mrg (void)setegid(egid); 315 1.1 thorpej 316 1.15 lukem while ((line = fparseln(f, &len, &lineno, "\\\\#", FPARSELN_UNESCALL)) 317 1.15 lukem != NULL) { 318 1.1 thorpej argc = 0; 319 1.1 thorpej argv = NULL; 320 1.15 lukem if (len == 0) 321 1.15 lukem goto end_of_line; 322 1.15 lukem 323 1.15 lukem for (cp = line; cp != NULL; ) { 324 1.15 lukem while ((vp = strsep(&cp, "\t ")) != NULL && *vp == '\0') 325 1.15 lukem ; 326 1.15 lukem if (vp == NULL) 327 1.15 lukem continue; 328 1.1 thorpej 329 1.52 christos nargv = erealloc(argv, sizeof(char *) * (argc + 1)); 330 1.35 itojun argv = nargv; 331 1.35 itojun argc++; 332 1.15 lukem argv[argc - 1] = vp; 333 1.15 lukem 334 1.1 thorpej /* 335 1.1 thorpej * If our action is to unconfigure all, then pass 336 1.1 thorpej * just the first token to do_single() and ignore 337 1.1 thorpej * the rest. Since this will be encountered on 338 1.1 thorpej * our first pass through the line, the Right 339 1.1 thorpej * Thing will happen. 340 1.1 thorpej */ 341 1.1 thorpej if (action == CCD_UNCONFIGALL) { 342 1.1 thorpej if (do_single(argc, argv, action)) 343 1.1 thorpej rval = 1; 344 1.1 thorpej goto end_of_line; 345 1.1 thorpej } 346 1.1 thorpej } 347 1.1 thorpej if (argc != 0) 348 1.1 thorpej if (do_single(argc, argv, action)) 349 1.1 thorpej rval = 1; 350 1.1 thorpej 351 1.1 thorpej end_of_line: 352 1.1 thorpej if (argv != NULL) 353 1.1 thorpej free(argv); 354 1.15 lukem free(line); 355 1.1 thorpej } 356 1.1 thorpej 357 1.1 thorpej (void)fclose(f); 358 1.1 thorpej return (rval); 359 1.1 thorpej } 360 1.1 thorpej 361 1.1 thorpej static int 362 1.40 xtraeme checkdev(char *path) 363 1.1 thorpej { 364 1.1 thorpej struct stat st; 365 1.1 thorpej 366 1.1 thorpej if (stat(path, &st) != 0) 367 1.1 thorpej return (errno); 368 1.1 thorpej 369 1.1 thorpej if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) 370 1.1 thorpej return (EINVAL); 371 1.1 thorpej 372 1.1 thorpej return (0); 373 1.1 thorpej } 374 1.1 thorpej 375 1.1 thorpej static int 376 1.40 xtraeme pathtounit(char *path, int *unitp) 377 1.1 thorpej { 378 1.1 thorpej struct stat st; 379 1.1 thorpej 380 1.1 thorpej if (stat(path, &st) != 0) 381 1.1 thorpej return (errno); 382 1.1 thorpej 383 1.1 thorpej if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) 384 1.1 thorpej return (EINVAL); 385 1.1 thorpej 386 1.42 lukem *unitp = DISKUNIT(st.st_rdev); 387 1.1 thorpej 388 1.1 thorpej return (0); 389 1.1 thorpej } 390 1.1 thorpej 391 1.1 thorpej static char * 392 1.40 xtraeme resolve_ccdname(char *name) 393 1.1 thorpej { 394 1.58 mlelstv char *path, *buf; 395 1.58 mlelstv const char *p; 396 1.58 mlelstv char c; 397 1.37 itojun size_t len; 398 1.1 thorpej int rawpart; 399 1.1 thorpej 400 1.1 thorpej if (name[0] == '/' || name[0] == '.') { 401 1.1 thorpej /* Assume they gave the correct pathname. */ 402 1.58 mlelstv path = estrdup(name); 403 1.58 mlelstv } else { 404 1.58 mlelstv 405 1.58 mlelstv len = strlen(name); 406 1.58 mlelstv c = name[len - 1]; 407 1.58 mlelstv 408 1.58 mlelstv if (isdigit((unsigned char)c)) { 409 1.58 mlelstv if ((rawpart = getrawpartition()) < 0) 410 1.58 mlelstv return NULL; 411 1.58 mlelstv easprintf(&path, "/dev/%s%c", name, 'a' + rawpart); 412 1.58 mlelstv } else 413 1.58 mlelstv easprintf(&path, "/dev/%s", name); 414 1.1 thorpej } 415 1.1 thorpej 416 1.58 mlelstv /* 417 1.58 mlelstv * Convert to raw device if possible. 418 1.58 mlelstv */ 419 1.58 mlelstv buf = emalloc(MAXPATHLEN); 420 1.58 mlelstv p = getdiskrawname(buf, MAXPATHLEN, path); 421 1.58 mlelstv if (p) { 422 1.58 mlelstv free(path); 423 1.58 mlelstv path = estrdup(p); 424 1.58 mlelstv } 425 1.58 mlelstv free(buf); 426 1.1 thorpej 427 1.52 christos return path; 428 1.1 thorpej } 429 1.1 thorpej 430 1.1 thorpej static int 431 1.40 xtraeme do_io(char *path, u_long cmd, struct ccd_ioctl *cciop) 432 1.1 thorpej { 433 1.1 thorpej int fd; 434 1.33 thorpej const char *cp; 435 1.1 thorpej 436 1.1 thorpej if ((fd = open(path, O_RDWR, 0640)) < 0) { 437 1.1 thorpej warn("open: %s", path); 438 1.1 thorpej return (1); 439 1.1 thorpej } 440 1.1 thorpej 441 1.1 thorpej if (ioctl(fd, cmd, cciop) < 0) { 442 1.1 thorpej switch (cmd) { 443 1.1 thorpej case CCDIOCSET: 444 1.1 thorpej cp = "CCDIOCSET"; 445 1.1 thorpej break; 446 1.1 thorpej 447 1.1 thorpej case CCDIOCCLR: 448 1.1 thorpej cp = "CCDIOCCLR"; 449 1.1 thorpej break; 450 1.1 thorpej 451 1.1 thorpej default: 452 1.1 thorpej cp = "unknown"; 453 1.1 thorpej } 454 1.1 thorpej warn("ioctl (%s): %s", cp, path); 455 1.50 wiz (void)close(fd); 456 1.1 thorpej return (1); 457 1.1 thorpej } 458 1.1 thorpej 459 1.50 wiz (void)close(fd); 460 1.1 thorpej return (0); 461 1.1 thorpej } 462 1.1 thorpej 463 1.52 christos static void 464 1.52 christos print_ccd_info(int u, struct ccddiskinfo *ccd, char *str) 465 1.1 thorpej { 466 1.52 christos static int header_printed = 0; 467 1.1 thorpej 468 1.52 christos if (header_printed == 0 && verbose) { 469 1.52 christos printf("# ccd\t\tileave\tflags\t\tsize\tcomponent devices\n"); 470 1.52 christos header_printed = 1; 471 1.1 thorpej } 472 1.1 thorpej 473 1.52 christos /* Dump out softc information. */ 474 1.55 apb printf("ccd%d\t\t%d\t0x%x\t%ju\t", u, ccd->ccd_ileave, 475 1.55 apb ccd->ccd_flags & CCDF_USERMASK, 476 1.55 apb (uintmax_t)ccd->ccd_size * DEV_BSIZE); 477 1.1 thorpej 478 1.52 christos /* Read component pathname and display component info. */ 479 1.52 christos for (size_t i = 0; i < ccd->ccd_ndisks; ++i) { 480 1.52 christos fputs(str, stdout); 481 1.52 christos fputc((i + 1 < ccd->ccd_ndisks) ? ' ' : '\n', stdout); 482 1.52 christos str += strlen(str) + 1; 483 1.1 thorpej } 484 1.52 christos fflush(stdout); 485 1.52 christos } 486 1.1 thorpej 487 1.52 christos static int 488 1.52 christos printccdinfo(int u) 489 1.52 christos { 490 1.52 christos struct ccddiskinfo ccd; 491 1.52 christos size_t s = sizeof(ccd); 492 1.52 christos size_t len; 493 1.52 christos const char *str; 494 1.42 lukem 495 1.52 christos if (sysctlbyname(str = "kern.ccd.info", &ccd, &s, &u, sizeof(u)) 496 1.52 christos == -1) { 497 1.52 christos if (errno == ENOENT) 498 1.52 christos warnx("ccd unit %d not configured", u); 499 1.52 christos else 500 1.52 christos warn("error getting %s for ccd%d", str, u); 501 1.52 christos return 1; 502 1.1 thorpej } 503 1.1 thorpej 504 1.52 christos if (sysctlbyname(str = "kern.ccd.components", NULL, &len, &u, sizeof(u)) 505 1.52 christos == -1) { 506 1.52 christos warn("Error getting %s for ccd%d", str, u); 507 1.52 christos return 1; 508 1.52 christos } 509 1.52 christos 510 1.52 christos char *names; 511 1.52 christos names = emalloc(len); 512 1.52 christos if (sysctlbyname(str = "kern.ccd.components", names, &len, &u, 513 1.52 christos sizeof(u)) == -1) { 514 1.52 christos warn("error getting %s for ccd%d", str, u); 515 1.52 christos free(names); 516 1.52 christos return 1; 517 1.52 christos } 518 1.52 christos print_ccd_info(u, &ccd, names); 519 1.52 christos free(names); 520 1.52 christos return 0; 521 1.52 christos } 522 1.42 lukem 523 1.52 christos static int 524 1.52 christos dump_ccd(int argc, char **argv, int action) 525 1.52 christos { 526 1.52 christos const char *sys; 527 1.52 christos int errs = 0; 528 1.1 thorpej if (argc == 0) { 529 1.52 christos int *units; 530 1.52 christos size_t nunits = 0; 531 1.52 christos if (sysctlbyname(sys = "kern.ccd.units", NULL, &nunits, NULL, 0) 532 1.52 christos == -1) { 533 1.52 christos switch (errno) { 534 1.52 christos case ENOENT: 535 1.52 christos warnx("no ccd driver in the kernel"); 536 1.52 christos return 1; 537 1.52 christos case ENOMEM: 538 1.52 christos break; 539 1.52 christos default: 540 1.52 christos err(EXIT_FAILURE, "1 error getting %s", sys); 541 1.1 thorpej } 542 1.52 christos } 543 1.52 christos 544 1.52 christos if (nunits == 0) { 545 1.52 christos warnx("no concatenated disks configured"); 546 1.52 christos return 1; 547 1.52 christos } 548 1.52 christos 549 1.52 christos units = emalloc(nunits); 550 1.52 christos 551 1.52 christos if (sysctlbyname(sys, units, &nunits, NULL, 0) == -1) 552 1.52 christos err(EXIT_FAILURE, "2 error getting %s", sys); 553 1.52 christos nunits /= sizeof(*units); 554 1.52 christos for (size_t i = 0; i < nunits; i++) 555 1.52 christos errs += printccdinfo(units[i]); 556 1.52 christos free(units); 557 1.52 christos return errs; 558 1.52 christos } 559 1.1 thorpej 560 1.52 christos /* Dump ccd configuration to stdout. */ 561 1.52 christos while (argc) { 562 1.53 christos int i = 0; /* XXX: vax gcc */ 563 1.52 christos int error; 564 1.52 christos char *cp = *argv++; --argc; 565 1.52 christos char *ccd; 566 1.52 christos 567 1.52 christos if ((ccd = resolve_ccdname(cp)) == NULL) { 568 1.52 christos warnx("invalid ccd name: %s", cp); 569 1.52 christos errs++; 570 1.52 christos continue; 571 1.52 christos } 572 1.52 christos if ((error = pathtounit(ccd, &i)) != 0) { 573 1.52 christos warn("%s", ccd); 574 1.44 christos free(ccd); 575 1.52 christos errs++; 576 1.52 christos continue; 577 1.1 thorpej } 578 1.52 christos errs += printccdinfo(i); 579 1.58 mlelstv free(ccd); 580 1.1 thorpej } 581 1.52 christos return errs; 582 1.1 thorpej } 583 1.1 thorpej 584 1.8 thorpej 585 1.1 thorpej static int 586 1.40 xtraeme flags_to_val(char *flags) 587 1.1 thorpej { 588 1.1 thorpej char *cp, *tok; 589 1.1 thorpej int i, tmp, val = ~CCDF_USERMASK; 590 1.1 thorpej size_t flagslen; 591 1.1 thorpej 592 1.1 thorpej /* 593 1.1 thorpej * The most common case is that of NIL flags, so check for 594 1.1 thorpej * those first. 595 1.1 thorpej */ 596 1.1 thorpej if (strcmp("none", flags) == 0 || strcmp("0x0", flags) == 0 || 597 1.1 thorpej strcmp("0", flags) == 0) 598 1.1 thorpej return (0); 599 1.1 thorpej 600 1.1 thorpej flagslen = strlen(flags); 601 1.1 thorpej 602 1.1 thorpej /* Check for values represented by strings. */ 603 1.52 christos cp = estrdup(flags); 604 1.1 thorpej tmp = 0; 605 1.1 thorpej for (tok = cp; (tok = strtok(tok, ",")) != NULL; tok = NULL) { 606 1.1 thorpej for (i = 0; flagvaltab[i].fv_flag != NULL; ++i) 607 1.1 thorpej if (strcmp(tok, flagvaltab[i].fv_flag) == 0) 608 1.1 thorpej break; 609 1.1 thorpej if (flagvaltab[i].fv_flag == NULL) { 610 1.1 thorpej free(cp); 611 1.1 thorpej goto bad_string; 612 1.1 thorpej } 613 1.1 thorpej tmp |= flagvaltab[i].fv_val; 614 1.1 thorpej } 615 1.1 thorpej 616 1.1 thorpej /* If we get here, the string was ok. */ 617 1.1 thorpej free(cp); 618 1.1 thorpej val = tmp; 619 1.1 thorpej goto out; 620 1.1 thorpej 621 1.1 thorpej bad_string: 622 1.1 thorpej 623 1.1 thorpej /* Check for values represented in hex. */ 624 1.1 thorpej if (flagslen > 2 && flags[0] == '0' && flags[1] == 'x') { 625 1.1 thorpej errno = 0; /* to check for ERANGE */ 626 1.1 thorpej val = (int)strtol(&flags[2], &cp, 16); 627 1.1 thorpej if ((errno == ERANGE) || (*cp != '\0')) 628 1.1 thorpej return (-1); 629 1.1 thorpej goto out; 630 1.1 thorpej } 631 1.1 thorpej 632 1.1 thorpej /* Check for values represented in decimal. */ 633 1.1 thorpej errno = 0; /* to check for ERANGE */ 634 1.1 thorpej val = (int)strtol(flags, &cp, 10); 635 1.1 thorpej if ((errno == ERANGE) || (*cp != '\0')) 636 1.1 thorpej return (-1); 637 1.1 thorpej 638 1.1 thorpej out: 639 1.1 thorpej return (((val & ~CCDF_USERMASK) == 0) ? val : -1); 640 1.1 thorpej } 641 1.1 thorpej 642 1.1 thorpej static void 643 1.40 xtraeme usage(void) 644 1.1 thorpej { 645 1.34 cgd const char *progname = getprogname(); 646 1.1 thorpej 647 1.34 cgd fprintf(stderr, "usage: %s [-cv] ccd ileave [flags] dev [...]\n", 648 1.34 cgd progname); 649 1.34 cgd fprintf(stderr, " %s -C [-v] [-f config_file]\n", progname); 650 1.34 cgd fprintf(stderr, " %s -u [-v] ccd [...]\n", progname); 651 1.34 cgd fprintf(stderr, " %s -U [-v] [-f config_file]\n", progname); 652 1.52 christos fprintf(stderr, " %s -g [ccd [...]]\n", 653 1.34 cgd progname); 654 1.1 thorpej exit(1); 655 1.1 thorpej } 656