ccdconfig.c revision 69793
113044Sasami/* $NetBSD: ccdconfig.c,v 1.2.2.1 1995/11/11 02:43:35 thorpej Exp $ */ 213044Sasami 313044Sasami/* 413044Sasami * Copyright (c) 1995 Jason R. Thorpe. 513044Sasami * All rights reserved. 613044Sasami * 713044Sasami * Redistribution and use in source and binary forms, with or without 813044Sasami * modification, are permitted provided that the following conditions 913044Sasami * are met: 1013044Sasami * 1. Redistributions of source code must retain the above copyright 1113044Sasami * notice, this list of conditions and the following disclaimer. 1213044Sasami * 2. Redistributions in binary form must reproduce the above copyright 1313044Sasami * notice, this list of conditions and the following disclaimer in the 1413044Sasami * documentation and/or other materials provided with the distribution. 1513044Sasami * 3. All advertising materials mentioning features or use of this software 1613044Sasami * must display the following acknowledgement: 1713044Sasami * This product includes software developed for the NetBSD Project 1813044Sasami * by Jason R. Thorpe. 1913044Sasami * 4. The name of the author may not be used to endorse or promote products 2013044Sasami * derived from this software without specific prior written permission. 2113044Sasami * 2213044Sasami * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2313044Sasami * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2413044Sasami * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2513044Sasami * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2613044Sasami * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2713044Sasami * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2813044Sasami * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2913044Sasami * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 3013044Sasami * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3113044Sasami * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3213044Sasami * SUCH DAMAGE. 3313044Sasami */ 3413044Sasami 3536628Scharnier#ifndef lint 3636628Scharnierstatic const char rcsid[] = 3750476Speter "$FreeBSD: head/sbin/ccdconfig/ccdconfig.c 69793 2000-12-09 09:35:55Z obrien $"; 3836628Scharnier#endif /* not lint */ 3936628Scharnier 4013044Sasami#include <sys/param.h> 4148568Sbillf#include <sys/linker.h> 4213044Sasami#include <sys/disklabel.h> 4313044Sasami#include <sys/stat.h> 4445329Speter#include <sys/module.h> 4513044Sasami#include <ctype.h> 4613044Sasami#include <err.h> 4713044Sasami#include <errno.h> 4813044Sasami#include <fcntl.h> 4913044Sasami#include <kvm.h> 5013044Sasami#include <limits.h> 5169793Sobrien#include <paths.h> 5213044Sasami#include <stdio.h> 5313044Sasami#include <stdlib.h> 5413044Sasami#include <string.h> 5513044Sasami#include <unistd.h> 5613044Sasami 5739228Sgibbs#include <sys/devicestat.h> 5813052Sasami#include <sys/ccdvar.h> 5913044Sasami 6013044Sasami#include "pathnames.h" 6113044Sasami 6213044Sasamistatic int lineno = 0; 6313044Sasamistatic int verbose = 0; 6413044Sasamistatic char *ccdconf = _PATH_CCDCONF; 6513044Sasami 6613044Sasamistatic char *core = NULL; 6713044Sasamistatic char *kernel = NULL; 6813044Sasami 6913044Sasamistruct flagval { 7013044Sasami char *fv_flag; 7113044Sasami int fv_val; 7213044Sasami} flagvaltab[] = { 7313044Sasami { "CCDF_SWAP", CCDF_SWAP }, 7413044Sasami { "CCDF_UNIFORM", CCDF_UNIFORM }, 7513762Sasami { "CCDF_MIRROR", CCDF_MIRROR }, 7613762Sasami { "CCDF_PARITY", CCDF_PARITY }, 7713044Sasami { NULL, 0 }, 7813044Sasami}; 7913044Sasami 8013044Sasamistatic struct nlist nl[] = { 8113044Sasami { "_ccd_softc" }, 8213044Sasami#define SYM_CCDSOFTC 0 8313044Sasami { "_numccd" }, 8413044Sasami#define SYM_NUMCCD 1 8513044Sasami { NULL }, 8613044Sasami}; 8713044Sasami 8813044Sasami#define CCD_CONFIG 0 /* configure a device */ 8913044Sasami#define CCD_CONFIGALL 1 /* configure all devices */ 9013044Sasami#define CCD_UNCONFIG 2 /* unconfigure a device */ 9113044Sasami#define CCD_UNCONFIGALL 3 /* unconfigure all devices */ 9213044Sasami#define CCD_DUMP 4 /* dump a ccd's configuration */ 9313044Sasami 9413044Sasamistatic int checkdev __P((char *)); 9513044Sasamistatic int do_io __P((char *, u_long, struct ccd_ioctl *)); 9613044Sasamistatic int do_single __P((int, char **, int)); 9713044Sasamistatic int do_all __P((int)); 9813044Sasamistatic int dump_ccd __P((int, char **)); 9913044Sasamistatic int getmaxpartitions __P((void)); 10013044Sasamistatic int getrawpartition __P((void)); 10113044Sasamistatic int flags_to_val __P((char *)); 10213044Sasamistatic void print_ccd_info __P((struct ccd_softc *, kvm_t *)); 10313044Sasamistatic char *resolve_ccdname __P((char *)); 10413044Sasamistatic void usage __P((void)); 10513044Sasami 10613044Sasamiint 10713044Sasamimain(argc, argv) 10813044Sasami int argc; 10913044Sasami char **argv; 11013044Sasami{ 11113044Sasami int ch, options = 0, action = CCD_CONFIG; 11213044Sasami 11313044Sasami while ((ch = getopt(argc, argv, "cCf:gM:N:uUv")) != -1) { 11413044Sasami switch (ch) { 11513044Sasami case 'c': 11613044Sasami action = CCD_CONFIG; 11713044Sasami ++options; 11813044Sasami break; 11913044Sasami 12013044Sasami case 'C': 12113044Sasami action = CCD_CONFIGALL; 12213044Sasami ++options; 12313044Sasami break; 12413044Sasami 12513044Sasami case 'f': 12613044Sasami ccdconf = optarg; 12713044Sasami break; 12813044Sasami 12913044Sasami case 'g': 13013044Sasami action = CCD_DUMP; 13113044Sasami break; 13213044Sasami 13313044Sasami case 'M': 13413044Sasami core = optarg; 13513044Sasami break; 13613044Sasami 13713044Sasami case 'N': 13813044Sasami kernel = optarg; 13913044Sasami break; 14013044Sasami 14113044Sasami case 'u': 14213044Sasami action = CCD_UNCONFIG; 14313044Sasami ++options; 14413044Sasami break; 14513044Sasami 14613044Sasami case 'U': 14713044Sasami action = CCD_UNCONFIGALL; 14813044Sasami ++options; 14913044Sasami break; 15013044Sasami 15113044Sasami case 'v': 15213044Sasami verbose = 1; 15313044Sasami break; 15413044Sasami 15513044Sasami default: 15613044Sasami usage(); 15713044Sasami } 15813044Sasami } 15913044Sasami argc -= optind; 16013044Sasami argv += optind; 16113044Sasami 16213044Sasami if (options > 1) 16313044Sasami usage(); 16413044Sasami 16532116Simp /* 16632116Simp * Discard setgid privileges if not the running kernel so that bad 16732116Simp * guys can't print interesting stuff from kernel memory. 16832116Simp */ 16932116Simp if (core != NULL || kernel != NULL || action != CCD_DUMP) { 17032116Simp setegid(getgid()); 17132116Simp setgid(getgid()); 17232116Simp } 17332116Simp 17445329Speter if (modfind("ccd") < 0) { 17545329Speter /* Not present in kernel, try loading it */ 17645329Speter if (kldload("ccd") < 0 || modfind("ccd") < 0) 17745329Speter warn("ccd module not available!"); 17845329Speter } 17945329Speter 18013044Sasami switch (action) { 18113044Sasami case CCD_CONFIG: 18213044Sasami case CCD_UNCONFIG: 18313044Sasami exit(do_single(argc, argv, action)); 18413044Sasami /* NOTREACHED */ 18513044Sasami 18613044Sasami case CCD_CONFIGALL: 18713044Sasami case CCD_UNCONFIGALL: 18813044Sasami exit(do_all(action)); 18913044Sasami /* NOTREACHED */ 19013044Sasami 19113044Sasami case CCD_DUMP: 19213044Sasami exit(dump_ccd(argc, argv)); 19313044Sasami /* NOTREACHED */ 19413044Sasami } 19513044Sasami /* NOTREACHED */ 19636628Scharnier return (0); 19713044Sasami} 19813044Sasami 19913044Sasamistatic int 20013044Sasamido_single(argc, argv, action) 20113044Sasami int argc; 20213044Sasami char **argv; 20313044Sasami int action; 20413044Sasami{ 20513044Sasami struct ccd_ioctl ccio; 20613044Sasami char *ccd, *cp, *cp2, **disks; 20751690Sbillf int noflags = 0, i, ileave, flags = 0, j; 20813044Sasami 20913044Sasami bzero(&ccio, sizeof(ccio)); 21013044Sasami 21113044Sasami /* 21213044Sasami * If unconfiguring, all arguments are treated as ccds. 21313044Sasami */ 21413044Sasami if (action == CCD_UNCONFIG || action == CCD_UNCONFIGALL) { 21513044Sasami for (i = 0; argc != 0; ) { 21613044Sasami cp = *argv++; --argc; 21713044Sasami if ((ccd = resolve_ccdname(cp)) == NULL) { 21813044Sasami warnx("invalid ccd name: %s", cp); 21913044Sasami i = 1; 22013044Sasami continue; 22113044Sasami } 22213044Sasami if (do_io(ccd, CCDIOCCLR, &ccio)) 22313044Sasami i = 1; 22413044Sasami else 22513044Sasami if (verbose) 22613044Sasami printf("%s unconfigured\n", cp); 22713044Sasami } 22813044Sasami return (i); 22913044Sasami } 23013044Sasami 23113044Sasami /* Make sure there are enough arguments. */ 23248568Sbillf if (argc < 4) { 23313044Sasami if (argc == 3) { 23413044Sasami /* Assume that no flags are specified. */ 23513044Sasami noflags = 1; 23613044Sasami } else { 23713044Sasami if (action == CCD_CONFIGALL) { 23813044Sasami warnx("%s: bad line: %d", ccdconf, lineno); 23913044Sasami return (1); 24013044Sasami } else 24113044Sasami usage(); 24213044Sasami } 24348568Sbillf } 24413044Sasami 24513044Sasami /* First argument is the ccd to configure. */ 24613044Sasami cp = *argv++; --argc; 24713044Sasami if ((ccd = resolve_ccdname(cp)) == NULL) { 24813044Sasami warnx("invalid ccd name: %s", cp); 24913044Sasami return (1); 25013044Sasami } 25113044Sasami 25213044Sasami /* Next argument is the interleave factor. */ 25313044Sasami cp = *argv++; --argc; 25413044Sasami errno = 0; /* to check for ERANGE */ 25513044Sasami ileave = (int)strtol(cp, &cp2, 10); 25613044Sasami if ((errno == ERANGE) || (ileave < 0) || (*cp2 != '\0')) { 25713044Sasami warnx("invalid interleave factor: %s", cp); 25813044Sasami return (1); 25913044Sasami } 26013044Sasami 26113044Sasami if (noflags == 0) { 26213044Sasami /* Next argument is the ccd configuration flags. */ 26313044Sasami cp = *argv++; --argc; 26413044Sasami if ((flags = flags_to_val(cp)) < 0) { 26513044Sasami warnx("invalid flags argument: %s", cp); 26613044Sasami return (1); 26713044Sasami } 26813044Sasami } 26913044Sasami 27013044Sasami /* Next is the list of disks to make the ccd from. */ 27113044Sasami disks = malloc(argc * sizeof(char *)); 27213044Sasami if (disks == NULL) { 27313044Sasami warnx("no memory to configure ccd"); 27413044Sasami return (1); 27513044Sasami } 27613044Sasami for (i = 0; argc != 0; ) { 27713044Sasami cp = *argv++; --argc; 27813044Sasami if ((j = checkdev(cp)) == 0) 27913044Sasami disks[i++] = cp; 28013044Sasami else { 28113044Sasami warnx("%s: %s", cp, strerror(j)); 28213044Sasami return (1); 28313044Sasami } 28413044Sasami } 28513044Sasami 28613044Sasami /* Fill in the ccio. */ 28713044Sasami ccio.ccio_disks = disks; 28813044Sasami ccio.ccio_ndisks = i; 28913044Sasami ccio.ccio_ileave = ileave; 29013044Sasami ccio.ccio_flags = flags; 29113044Sasami 29213044Sasami if (do_io(ccd, CCDIOCSET, &ccio)) { 29313044Sasami free(disks); 29413044Sasami return (1); 29513044Sasami } 29613044Sasami 29713044Sasami if (verbose) { 29813044Sasami printf("ccd%d: %d components ", ccio.ccio_unit, 29913044Sasami ccio.ccio_ndisks); 30013044Sasami for (i = 0; i < ccio.ccio_ndisks; ++i) { 30113044Sasami if ((cp2 = strrchr(disks[i], '/')) != NULL) 30213044Sasami ++cp2; 30313044Sasami else 30413044Sasami cp2 = disks[i]; 30513044Sasami printf("%c%s%c", 30613044Sasami i == 0 ? '(' : ' ', cp2, 30713044Sasami i == ccio.ccio_ndisks - 1 ? ')' : ','); 30813044Sasami } 30948568Sbillf printf(", %lu blocks ", (u_long)ccio.ccio_size); 31013044Sasami if (ccio.ccio_ileave != 0) 31113044Sasami printf("interleaved at %d blocks\n", ccio.ccio_ileave); 31213044Sasami else 31313044Sasami printf("concatenated\n"); 31413044Sasami } 31513044Sasami 31613044Sasami free(disks); 31713044Sasami return (0); 31813044Sasami} 31913044Sasami 32013044Sasamistatic int 32113044Sasamido_all(action) 32213044Sasami int action; 32313044Sasami{ 32413044Sasami FILE *f; 32513044Sasami char line[_POSIX2_LINE_MAX]; 32613044Sasami char *cp, **argv; 32713044Sasami int argc, rval; 32832116Simp gid_t egid; 32913044Sasami 33051690Sbillf rval = 0; 33132116Simp egid = getegid(); 33232116Simp setegid(getgid()); 33313044Sasami if ((f = fopen(ccdconf, "r")) == NULL) { 33432116Simp setegid(egid); 33513044Sasami warn("fopen: %s", ccdconf); 33613044Sasami return (1); 33713044Sasami } 33832116Simp setegid(egid); 33913044Sasami 34013044Sasami while (fgets(line, sizeof(line), f) != NULL) { 34113044Sasami argc = 0; 34213044Sasami argv = NULL; 34313044Sasami ++lineno; 34413044Sasami if ((cp = strrchr(line, '\n')) != NULL) 34513044Sasami *cp = '\0'; 34613044Sasami 34713044Sasami /* Break up the line and pass it's contents to do_single(). */ 34813044Sasami if (line[0] == '\0') 34913044Sasami goto end_of_line; 35013044Sasami for (cp = line; (cp = strtok(cp, " \t")) != NULL; cp = NULL) { 35113044Sasami if (*cp == '#') 35213044Sasami break; 35313044Sasami if ((argv = realloc(argv, 35413044Sasami sizeof(char *) * ++argc)) == NULL) { 35513044Sasami warnx("no memory to configure ccds"); 35613044Sasami return (1); 35713044Sasami } 35813044Sasami argv[argc - 1] = cp; 35913044Sasami /* 36013044Sasami * If our action is to unconfigure all, then pass 36113044Sasami * just the first token to do_single() and ignore 36213044Sasami * the rest. Since this will be encountered on 36313044Sasami * our first pass through the line, the Right 36413044Sasami * Thing will happen. 36513044Sasami */ 36613044Sasami if (action == CCD_UNCONFIGALL) { 36713044Sasami if (do_single(argc, argv, action)) 36813044Sasami rval = 1; 36913044Sasami goto end_of_line; 37013044Sasami } 37113044Sasami } 37213044Sasami if (argc != 0) 37313044Sasami if (do_single(argc, argv, action)) 37413044Sasami rval = 1; 37513044Sasami 37613044Sasami end_of_line: 37713044Sasami if (argv != NULL) 37813044Sasami free(argv); 37913044Sasami } 38013044Sasami 38113044Sasami (void)fclose(f); 38213044Sasami return (rval); 38313044Sasami} 38413044Sasami 38513044Sasamistatic int 38613044Sasamicheckdev(path) 38713044Sasami char *path; 38813044Sasami{ 38913044Sasami struct stat st; 39013044Sasami 39113044Sasami if (stat(path, &st) != 0) 39213044Sasami return (errno); 39313044Sasami 39413044Sasami if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) 39513044Sasami return (EINVAL); 39613044Sasami 39713044Sasami return (0); 39813044Sasami} 39913044Sasami 40013044Sasamistatic int 40113044Sasamipathtounit(path, unitp) 40213044Sasami char *path; 40313044Sasami int *unitp; 40413044Sasami{ 40513044Sasami struct stat st; 40613044Sasami int maxpartitions; 40713044Sasami 40813044Sasami if (stat(path, &st) != 0) 40913044Sasami return (errno); 41013044Sasami 41113044Sasami if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) 41213044Sasami return (EINVAL); 41313044Sasami 41413044Sasami if ((maxpartitions = getmaxpartitions()) < 0) 41513044Sasami return (errno); 41613044Sasami 41713044Sasami *unitp = minor(st.st_rdev) / maxpartitions; 41813044Sasami 41913044Sasami return (0); 42013044Sasami} 42113044Sasami 42213044Sasamistatic char * 42313044Sasamiresolve_ccdname(name) 42413044Sasami char *name; 42513044Sasami{ 42636628Scharnier char c, *path; 42713044Sasami size_t len, newlen; 42813044Sasami int rawpart; 42913044Sasami 43013044Sasami if (name[0] == '/' || name[0] == '.') { 43113044Sasami /* Assume they gave the correct pathname. */ 43213044Sasami return (strdup(name)); 43313044Sasami } 43413044Sasami 43513044Sasami len = strlen(name); 43613044Sasami c = name[len - 1]; 43713044Sasami 43813044Sasami newlen = len + 8; 43913044Sasami if ((path = malloc(newlen)) == NULL) 44013044Sasami return (NULL); 44113044Sasami bzero(path, newlen); 44213044Sasami 44313044Sasami if (isdigit(c)) { 44413044Sasami if ((rawpart = getrawpartition()) < 0) { 44513044Sasami free(path); 44613044Sasami return (NULL); 44713044Sasami } 44869793Sobrien (void)sprintf(path, "%s%s%c", _PATH_DEV, name, 'a' + rawpart); 44913044Sasami } else 45069793Sobrien (void)sprintf(path, "%s%s", _PATH_DEV, name); 45113044Sasami 45213044Sasami return (path); 45313044Sasami} 45413044Sasami 45513044Sasamistatic int 45613044Sasamido_io(path, cmd, cciop) 45713044Sasami char *path; 45813044Sasami u_long cmd; 45913044Sasami struct ccd_ioctl *cciop; 46013044Sasami{ 46113044Sasami int fd; 46213044Sasami char *cp; 46313044Sasami 46413044Sasami if ((fd = open(path, O_RDWR, 0640)) < 0) { 46513044Sasami warn("open: %s", path); 46613044Sasami return (1); 46713044Sasami } 46813044Sasami 46913044Sasami if (ioctl(fd, cmd, cciop) < 0) { 47013044Sasami switch (cmd) { 47113044Sasami case CCDIOCSET: 47213044Sasami cp = "CCDIOCSET"; 47313044Sasami break; 47413044Sasami 47513044Sasami case CCDIOCCLR: 47613044Sasami cp = "CCDIOCCLR"; 47713044Sasami break; 47813044Sasami 47913044Sasami default: 48013044Sasami cp = "unknown"; 48113044Sasami } 48213044Sasami warn("ioctl (%s): %s", cp, path); 48313044Sasami return (1); 48413044Sasami } 48513044Sasami 48613044Sasami return (0); 48713044Sasami} 48813044Sasami 48913044Sasami#define KVM_ABORT(kd, str) { \ 49013044Sasami (void)kvm_close((kd)); \ 49164275Skris warnx("%s", (str)); \ 49264275Skris warnx("%s", kvm_geterr((kd))); \ 49313044Sasami return (1); \ 49413044Sasami} 49513044Sasami 49613044Sasamistatic int 49713044Sasamidump_ccd(argc, argv) 49813044Sasami int argc; 49913044Sasami char **argv; 50013044Sasami{ 50113044Sasami char errbuf[_POSIX2_LINE_MAX], *ccd, *cp; 50213044Sasami struct ccd_softc *cs, *kcs; 50313044Sasami size_t readsize; 50413044Sasami int i, error, numccd, numconfiged = 0; 50513044Sasami kvm_t *kd; 50613044Sasami 50713044Sasami bzero(errbuf, sizeof(errbuf)); 50813044Sasami 50913044Sasami if ((kd = kvm_openfiles(kernel, core, NULL, O_RDONLY, 51013044Sasami errbuf)) == NULL) { 51113044Sasami warnx("can't open kvm: %s", errbuf); 51213044Sasami return (1); 51313044Sasami } 51413044Sasami 51513044Sasami if (kvm_nlist(kd, nl)) 51613044Sasami KVM_ABORT(kd, "ccd-related symbols not available"); 51713044Sasami 51813044Sasami /* Check to see how many ccds are currently configured. */ 51913044Sasami if (kvm_read(kd, nl[SYM_NUMCCD].n_value, (char *)&numccd, 52013044Sasami sizeof(numccd)) != sizeof(numccd)) 52113044Sasami KVM_ABORT(kd, "can't determine number of configured ccds"); 52213044Sasami 52313044Sasami if (numccd == 0) { 52413044Sasami printf("ccd driver in kernel, but is uninitialized\n"); 52513044Sasami goto done; 52613044Sasami } 52713044Sasami 52813044Sasami /* Allocate space for the configuration data. */ 52913044Sasami readsize = numccd * sizeof(struct ccd_softc); 53013044Sasami if ((cs = malloc(readsize)) == NULL) { 53113044Sasami warnx("no memory for configuration data"); 53213044Sasami goto bad; 53313044Sasami } 53413044Sasami bzero(cs, readsize); 53513044Sasami 53613044Sasami /* 53713044Sasami * Read the ccd configuration data from the kernel and dump 53813044Sasami * it to stdout. 53913044Sasami */ 54013044Sasami if (kvm_read(kd, nl[SYM_CCDSOFTC].n_value, (char *)&kcs, 54113044Sasami sizeof(kcs)) != sizeof(kcs)) { 54213044Sasami free(cs); 54313044Sasami KVM_ABORT(kd, "can't find pointer to configuration data"); 54413044Sasami } 54513044Sasami if (kvm_read(kd, (u_long)kcs, (char *)cs, readsize) != readsize) { 54613044Sasami free(cs); 54713044Sasami KVM_ABORT(kd, "can't read configuration data"); 54813044Sasami } 54913044Sasami 55013044Sasami if (argc == 0) { 55113044Sasami for (i = 0; i < numccd; ++i) 55213044Sasami if (cs[i].sc_flags & CCDF_INITED) { 55313044Sasami ++numconfiged; 55413044Sasami print_ccd_info(&cs[i], kd); 55513044Sasami } 55613044Sasami 55713044Sasami if (numconfiged == 0) 55813044Sasami printf("no concatenated disks configured\n"); 55913044Sasami } else { 56013044Sasami while (argc) { 56113044Sasami cp = *argv++; --argc; 56213044Sasami if ((ccd = resolve_ccdname(cp)) == NULL) { 56313044Sasami warnx("invalid ccd name: %s", cp); 56413044Sasami continue; 56513044Sasami } 56613044Sasami if ((error = pathtounit(ccd, &i)) != 0) { 56713044Sasami warnx("%s: %s", ccd, strerror(error)); 56813044Sasami continue; 56913044Sasami } 57013044Sasami if (i >= numccd) { 57113044Sasami warnx("ccd%d not configured", i); 57213044Sasami continue; 57313044Sasami } 57413044Sasami if (cs[i].sc_flags & CCDF_INITED) 57513044Sasami print_ccd_info(&cs[i], kd); 57613044Sasami else 57713044Sasami printf("ccd%d not configured\n", i); 57813044Sasami } 57913044Sasami } 58013044Sasami 58113044Sasami free(cs); 58213044Sasami 58313044Sasami done: 58413044Sasami (void)kvm_close(kd); 58513044Sasami return (0); 58613044Sasami 58713044Sasami bad: 58813044Sasami (void)kvm_close(kd); 58913044Sasami return (1); 59013044Sasami} 59113044Sasami 59213044Sasamistatic void 59313044Sasamiprint_ccd_info(cs, kd) 59413044Sasami struct ccd_softc *cs; 59513044Sasami kvm_t *kd; 59613044Sasami{ 59713044Sasami static int header_printed = 0; 59813044Sasami struct ccdcinfo *cip; 59913044Sasami size_t readsize; 60013044Sasami char path[MAXPATHLEN]; 60113044Sasami int i; 60213044Sasami 60313044Sasami if (header_printed == 0 && verbose) { 60413044Sasami printf("# ccd\t\tileave\tflags\tcompnent devices\n"); 60513044Sasami header_printed = 1; 60613044Sasami } 60713044Sasami 60813044Sasami readsize = cs->sc_nccdisks * sizeof(struct ccdcinfo); 60913044Sasami if ((cip = malloc(readsize)) == NULL) { 61013044Sasami warn("ccd%d: can't allocate memory for component info", 61113044Sasami cs->sc_unit); 61213044Sasami return; 61313044Sasami } 61413044Sasami bzero(cip, readsize); 61513044Sasami 61613044Sasami /* Dump out softc information. */ 61713044Sasami printf("ccd%d\t\t%d\t%d\t", cs->sc_unit, cs->sc_ileave, 61813044Sasami cs->sc_cflags & CCDF_USERMASK); 61913044Sasami fflush(stdout); 62013044Sasami 62113044Sasami /* Read in the component info. */ 62213044Sasami if (kvm_read(kd, (u_long)cs->sc_cinfo, (char *)cip, 62313044Sasami readsize) != readsize) { 62413044Sasami printf("\n"); 62513044Sasami warnx("can't read component info"); 62664275Skris warnx("%s", kvm_geterr(kd)); 62713044Sasami goto done; 62813044Sasami } 62913044Sasami 63013044Sasami /* Read component pathname and display component info. */ 63113044Sasami for (i = 0; i < cs->sc_nccdisks; ++i) { 63213044Sasami if (kvm_read(kd, (u_long)cip[i].ci_path, (char *)path, 63313044Sasami cip[i].ci_pathlen) != cip[i].ci_pathlen) { 63413044Sasami printf("\n"); 63513044Sasami warnx("can't read component pathname"); 63664282Salex warnx("%s", kvm_geterr(kd)); 63713044Sasami goto done; 63813044Sasami } 63913044Sasami printf((i + 1 < cs->sc_nccdisks) ? "%s " : "%s\n", path); 64013044Sasami fflush(stdout); 64113044Sasami } 64213044Sasami 64313044Sasami done: 64413044Sasami free(cip); 64513044Sasami} 64613044Sasami 64713044Sasamistatic int 64813044Sasamigetmaxpartitions() 64913044Sasami{ 65013052Sasami return (MAXPARTITIONS); 65113044Sasami} 65213044Sasami 65313044Sasamistatic int 65413044Sasamigetrawpartition() 65513044Sasami{ 65613052Sasami return (RAW_PART); 65713044Sasami} 65813044Sasami 65913044Sasamistatic int 66013044Sasamiflags_to_val(flags) 66113044Sasami char *flags; 66213044Sasami{ 66313044Sasami char *cp, *tok; 66413044Sasami int i, tmp, val = ~CCDF_USERMASK; 66513044Sasami size_t flagslen; 66613044Sasami 66713044Sasami /* 66813044Sasami * The most common case is that of NIL flags, so check for 66913044Sasami * those first. 67013044Sasami */ 67113044Sasami if (strcmp("none", flags) == 0 || strcmp("0x0", flags) == 0 || 67213044Sasami strcmp("0", flags) == 0) 67313044Sasami return (0); 67413044Sasami 67513044Sasami flagslen = strlen(flags); 67613044Sasami 67713044Sasami /* Check for values represented by strings. */ 67813044Sasami if ((cp = strdup(flags)) == NULL) 67913044Sasami err(1, "no memory to parse flags"); 68013044Sasami tmp = 0; 68113044Sasami for (tok = cp; (tok = strtok(tok, ",")) != NULL; tok = NULL) { 68213044Sasami for (i = 0; flagvaltab[i].fv_flag != NULL; ++i) 68313044Sasami if (strcmp(tok, flagvaltab[i].fv_flag) == 0) 68413044Sasami break; 68513044Sasami if (flagvaltab[i].fv_flag == NULL) { 68613044Sasami free(cp); 68713044Sasami goto bad_string; 68813044Sasami } 68913044Sasami tmp |= flagvaltab[i].fv_val; 69013044Sasami } 69113044Sasami 69213044Sasami /* If we get here, the string was ok. */ 69313044Sasami free(cp); 69413044Sasami val = tmp; 69513044Sasami goto out; 69613044Sasami 69713044Sasami bad_string: 69813044Sasami 69913044Sasami /* Check for values represented in hex. */ 70013044Sasami if (flagslen > 2 && flags[0] == '0' && flags[1] == 'x') { 70113044Sasami errno = 0; /* to check for ERANGE */ 70213044Sasami val = (int)strtol(&flags[2], &cp, 16); 70313044Sasami if ((errno == ERANGE) || (*cp != '\0')) 70413044Sasami return (-1); 70513044Sasami goto out; 70613044Sasami } 70713044Sasami 70813044Sasami /* Check for values represented in decimal. */ 70913044Sasami errno = 0; /* to check for ERANGE */ 71013044Sasami val = (int)strtol(flags, &cp, 10); 71113044Sasami if ((errno == ERANGE) || (*cp != '\0')) 71213044Sasami return (-1); 71313044Sasami 71413044Sasami out: 71513044Sasami return (((val & ~CCDF_USERMASK) == 0) ? val : -1); 71613044Sasami} 71713044Sasami 71813044Sasamistatic void 71913044Sasamiusage() 72013044Sasami{ 72126541Scharnier fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 72226541Scharnier "usage: ccdconfig [-cv] ccd ileave [flags] dev [...]", 72326541Scharnier " ccdconfig -C [-v] [-f config_file]", 72426541Scharnier " ccdconfig -u [-v] ccd [...]", 72526541Scharnier " ccdconfig -U [-v] [-f config_file]", 72626541Scharnier " ccdconfig -g [-M core] [-N system] [ccd [...]]"); 72713044Sasami exit(1); 72813044Sasami} 72926541Scharnier 73013052Sasami/* Local Variables: */ 73113052Sasami/* c-argdecl-indent: 8 */ 73213052Sasami/* c-indent-level: 8 */ 73313052Sasami/* End: */ 734