ccdconfig.c revision 13052
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 3513044Sasami#include <sys/param.h> 3613044Sasami#include <sys/ioctl.h> 3713044Sasami#include <sys/disklabel.h> 3813044Sasami#include <sys/device.h> 3913044Sasami#include <sys/disk.h> 4013044Sasami#include <sys/stat.h> 4113044Sasami#include <sys/sysctl.h> 4213044Sasami#include <ctype.h> 4313044Sasami#include <err.h> 4413044Sasami#include <errno.h> 4513044Sasami#include <fcntl.h> 4613044Sasami#include <kvm.h> 4713044Sasami#include <limits.h> 4813044Sasami#include <nlist.h> 4913044Sasami#include <stdio.h> 5013044Sasami#include <stdlib.h> 5113044Sasami#include <string.h> 5213044Sasami#include <unistd.h> 5313044Sasami 5413052Sasami#include <sys/ccdvar.h> 5513044Sasami 5613044Sasami#include "pathnames.h" 5713044Sasami 5813044Sasamiextern char *__progname; 5913044Sasami 6013044Sasamistatic int lineno = 0; 6113044Sasamistatic int verbose = 0; 6213044Sasamistatic char *ccdconf = _PATH_CCDCONF; 6313044Sasami 6413044Sasamistatic char *core = NULL; 6513044Sasamistatic char *kernel = NULL; 6613044Sasami 6713044Sasamistruct flagval { 6813044Sasami char *fv_flag; 6913044Sasami int fv_val; 7013044Sasami} flagvaltab[] = { 7113044Sasami { "CCDF_SWAP", CCDF_SWAP }, 7213044Sasami { "CCDF_UNIFORM", CCDF_UNIFORM }, 7313044Sasami { NULL, 0 }, 7413044Sasami}; 7513044Sasami 7613044Sasamistatic struct nlist nl[] = { 7713044Sasami { "_ccd_softc" }, 7813044Sasami#define SYM_CCDSOFTC 0 7913044Sasami { "_numccd" }, 8013044Sasami#define SYM_NUMCCD 1 8113044Sasami { NULL }, 8213044Sasami}; 8313044Sasami 8413044Sasami#define CCD_CONFIG 0 /* configure a device */ 8513044Sasami#define CCD_CONFIGALL 1 /* configure all devices */ 8613044Sasami#define CCD_UNCONFIG 2 /* unconfigure a device */ 8713044Sasami#define CCD_UNCONFIGALL 3 /* unconfigure all devices */ 8813044Sasami#define CCD_DUMP 4 /* dump a ccd's configuration */ 8913044Sasami 9013044Sasamistatic int checkdev __P((char *)); 9113044Sasamistatic int do_io __P((char *, u_long, struct ccd_ioctl *)); 9213044Sasamistatic int do_single __P((int, char **, int)); 9313044Sasamistatic int do_all __P((int)); 9413044Sasamistatic int dump_ccd __P((int, char **)); 9513044Sasamistatic int getmaxpartitions __P((void)); 9613044Sasamistatic int getrawpartition __P((void)); 9713044Sasamistatic int flags_to_val __P((char *)); 9813044Sasamistatic int pathtodevt __P((char *, dev_t *)); 9913044Sasamistatic void print_ccd_info __P((struct ccd_softc *, kvm_t *)); 10013044Sasamistatic char *resolve_ccdname __P((char *)); 10113044Sasamistatic void usage __P((void)); 10213044Sasami 10313044Sasamiint 10413044Sasamimain(argc, argv) 10513044Sasami int argc; 10613044Sasami char **argv; 10713044Sasami{ 10813044Sasami int ch, options = 0, action = CCD_CONFIG; 10913044Sasami 11013044Sasami while ((ch = getopt(argc, argv, "cCf:gM:N:uUv")) != -1) { 11113044Sasami switch (ch) { 11213044Sasami case 'c': 11313044Sasami action = CCD_CONFIG; 11413044Sasami ++options; 11513044Sasami break; 11613044Sasami 11713044Sasami case 'C': 11813044Sasami action = CCD_CONFIGALL; 11913044Sasami ++options; 12013044Sasami break; 12113044Sasami 12213044Sasami case 'f': 12313044Sasami ccdconf = optarg; 12413044Sasami break; 12513044Sasami 12613044Sasami case 'g': 12713044Sasami action = CCD_DUMP; 12813044Sasami break; 12913044Sasami 13013044Sasami case 'M': 13113044Sasami core = optarg; 13213044Sasami break; 13313044Sasami 13413044Sasami case 'N': 13513044Sasami kernel = optarg; 13613044Sasami break; 13713044Sasami 13813044Sasami case 'u': 13913044Sasami action = CCD_UNCONFIG; 14013044Sasami ++options; 14113044Sasami break; 14213044Sasami 14313044Sasami case 'U': 14413044Sasami action = CCD_UNCONFIGALL; 14513044Sasami ++options; 14613044Sasami break; 14713044Sasami 14813044Sasami case 'v': 14913044Sasami verbose = 1; 15013044Sasami break; 15113044Sasami 15213044Sasami default: 15313044Sasami usage(); 15413044Sasami } 15513044Sasami } 15613044Sasami argc -= optind; 15713044Sasami argv += optind; 15813044Sasami 15913044Sasami if (options > 1) 16013044Sasami usage(); 16113044Sasami 16213044Sasami switch (action) { 16313044Sasami case CCD_CONFIG: 16413044Sasami case CCD_UNCONFIG: 16513044Sasami exit(do_single(argc, argv, action)); 16613044Sasami /* NOTREACHED */ 16713044Sasami 16813044Sasami case CCD_CONFIGALL: 16913044Sasami case CCD_UNCONFIGALL: 17013044Sasami exit(do_all(action)); 17113044Sasami /* NOTREACHED */ 17213044Sasami 17313044Sasami case CCD_DUMP: 17413044Sasami exit(dump_ccd(argc, argv)); 17513044Sasami /* NOTREACHED */ 17613044Sasami } 17713044Sasami /* NOTREACHED */ 17813044Sasami} 17913044Sasami 18013044Sasamistatic int 18113044Sasamido_single(argc, argv, action) 18213044Sasami int argc; 18313044Sasami char **argv; 18413044Sasami int action; 18513044Sasami{ 18613044Sasami struct ccd_ioctl ccio; 18713044Sasami char *ccd, *cp, *cp2, **disks; 18813044Sasami int noflags = 0, i, ileave, flags, j, error; 18913044Sasami 19013044Sasami bzero(&ccio, sizeof(ccio)); 19113044Sasami 19213044Sasami /* 19313044Sasami * If unconfiguring, all arguments are treated as ccds. 19413044Sasami */ 19513044Sasami if (action == CCD_UNCONFIG || action == CCD_UNCONFIGALL) { 19613044Sasami for (i = 0; argc != 0; ) { 19713044Sasami cp = *argv++; --argc; 19813044Sasami if ((ccd = resolve_ccdname(cp)) == NULL) { 19913044Sasami warnx("invalid ccd name: %s", cp); 20013044Sasami i = 1; 20113044Sasami continue; 20213044Sasami } 20313044Sasami if (do_io(ccd, CCDIOCCLR, &ccio)) 20413044Sasami i = 1; 20513044Sasami else 20613044Sasami if (verbose) 20713044Sasami printf("%s unconfigured\n", cp); 20813044Sasami } 20913044Sasami return (i); 21013044Sasami } 21113044Sasami 21213044Sasami /* Make sure there are enough arguments. */ 21313044Sasami if (argc < 4) 21413044Sasami if (argc == 3) { 21513044Sasami /* Assume that no flags are specified. */ 21613044Sasami noflags = 1; 21713044Sasami } else { 21813044Sasami if (action == CCD_CONFIGALL) { 21913044Sasami warnx("%s: bad line: %d", ccdconf, lineno); 22013044Sasami return (1); 22113044Sasami } else 22213044Sasami usage(); 22313044Sasami } 22413044Sasami 22513044Sasami /* First argument is the ccd to configure. */ 22613044Sasami cp = *argv++; --argc; 22713044Sasami if ((ccd = resolve_ccdname(cp)) == NULL) { 22813044Sasami warnx("invalid ccd name: %s", cp); 22913044Sasami return (1); 23013044Sasami } 23113044Sasami 23213044Sasami /* Next argument is the interleave factor. */ 23313044Sasami cp = *argv++; --argc; 23413044Sasami errno = 0; /* to check for ERANGE */ 23513044Sasami ileave = (int)strtol(cp, &cp2, 10); 23613044Sasami if ((errno == ERANGE) || (ileave < 0) || (*cp2 != '\0')) { 23713044Sasami warnx("invalid interleave factor: %s", cp); 23813044Sasami return (1); 23913044Sasami } 24013044Sasami 24113044Sasami if (noflags == 0) { 24213044Sasami /* Next argument is the ccd configuration flags. */ 24313044Sasami cp = *argv++; --argc; 24413044Sasami if ((flags = flags_to_val(cp)) < 0) { 24513044Sasami warnx("invalid flags argument: %s", cp); 24613044Sasami return (1); 24713044Sasami } 24813044Sasami } 24913044Sasami 25013044Sasami /* Next is the list of disks to make the ccd from. */ 25113044Sasami disks = malloc(argc * sizeof(char *)); 25213044Sasami if (disks == NULL) { 25313044Sasami warnx("no memory to configure ccd"); 25413044Sasami return (1); 25513044Sasami } 25613044Sasami for (i = 0; argc != 0; ) { 25713044Sasami cp = *argv++; --argc; 25813044Sasami if ((j = checkdev(cp)) == 0) 25913044Sasami disks[i++] = cp; 26013044Sasami else { 26113044Sasami warnx("%s: %s", cp, strerror(j)); 26213044Sasami return (1); 26313044Sasami } 26413044Sasami } 26513044Sasami 26613044Sasami /* Fill in the ccio. */ 26713044Sasami ccio.ccio_disks = disks; 26813044Sasami ccio.ccio_ndisks = i; 26913044Sasami ccio.ccio_ileave = ileave; 27013044Sasami ccio.ccio_flags = flags; 27113044Sasami 27213044Sasami if (do_io(ccd, CCDIOCSET, &ccio)) { 27313044Sasami free(disks); 27413044Sasami return (1); 27513044Sasami } 27613044Sasami 27713044Sasami if (verbose) { 27813044Sasami printf("ccd%d: %d components ", ccio.ccio_unit, 27913044Sasami ccio.ccio_ndisks); 28013044Sasami for (i = 0; i < ccio.ccio_ndisks; ++i) { 28113044Sasami if ((cp2 = strrchr(disks[i], '/')) != NULL) 28213044Sasami ++cp2; 28313044Sasami else 28413044Sasami cp2 = disks[i]; 28513044Sasami printf("%c%s%c", 28613044Sasami i == 0 ? '(' : ' ', cp2, 28713044Sasami i == ccio.ccio_ndisks - 1 ? ')' : ','); 28813044Sasami } 28913044Sasami printf(", %d blocks ", ccio.ccio_size); 29013044Sasami if (ccio.ccio_ileave != 0) 29113044Sasami printf("interleaved at %d blocks\n", ccio.ccio_ileave); 29213044Sasami else 29313044Sasami printf("concatenated\n"); 29413044Sasami } 29513044Sasami 29613044Sasami free(disks); 29713044Sasami return (0); 29813044Sasami} 29913044Sasami 30013044Sasamistatic int 30113044Sasamido_all(action) 30213044Sasami int action; 30313044Sasami{ 30413044Sasami FILE *f; 30513044Sasami char line[_POSIX2_LINE_MAX]; 30613044Sasami char *cp, **argv; 30713044Sasami int argc, rval; 30813044Sasami 30913044Sasami if ((f = fopen(ccdconf, "r")) == NULL) { 31013044Sasami warn("fopen: %s", ccdconf); 31113044Sasami return (1); 31213044Sasami } 31313044Sasami 31413044Sasami while (fgets(line, sizeof(line), f) != NULL) { 31513044Sasami argc = 0; 31613044Sasami argv = NULL; 31713044Sasami ++lineno; 31813044Sasami if ((cp = strrchr(line, '\n')) != NULL) 31913044Sasami *cp = '\0'; 32013044Sasami 32113044Sasami /* Break up the line and pass it's contents to do_single(). */ 32213044Sasami if (line[0] == '\0') 32313044Sasami goto end_of_line; 32413044Sasami for (cp = line; (cp = strtok(cp, " \t")) != NULL; cp = NULL) { 32513044Sasami if (*cp == '#') 32613044Sasami break; 32713044Sasami if ((argv = realloc(argv, 32813044Sasami sizeof(char *) * ++argc)) == NULL) { 32913044Sasami warnx("no memory to configure ccds"); 33013044Sasami return (1); 33113044Sasami } 33213044Sasami argv[argc - 1] = cp; 33313044Sasami /* 33413044Sasami * If our action is to unconfigure all, then pass 33513044Sasami * just the first token to do_single() and ignore 33613044Sasami * the rest. Since this will be encountered on 33713044Sasami * our first pass through the line, the Right 33813044Sasami * Thing will happen. 33913044Sasami */ 34013044Sasami if (action == CCD_UNCONFIGALL) { 34113044Sasami if (do_single(argc, argv, action)) 34213044Sasami rval = 1; 34313044Sasami goto end_of_line; 34413044Sasami } 34513044Sasami } 34613044Sasami if (argc != 0) 34713044Sasami if (do_single(argc, argv, action)) 34813044Sasami rval = 1; 34913044Sasami 35013044Sasami end_of_line: 35113044Sasami if (argv != NULL) 35213044Sasami free(argv); 35313044Sasami } 35413044Sasami 35513044Sasami (void)fclose(f); 35613044Sasami return (rval); 35713044Sasami} 35813044Sasami 35913044Sasamistatic int 36013044Sasamicheckdev(path) 36113044Sasami char *path; 36213044Sasami{ 36313044Sasami struct stat st; 36413044Sasami 36513044Sasami if (stat(path, &st) != 0) 36613044Sasami return (errno); 36713044Sasami 36813044Sasami if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) 36913044Sasami return (EINVAL); 37013044Sasami 37113044Sasami return (0); 37213044Sasami} 37313044Sasami 37413044Sasamistatic int 37513044Sasamipathtounit(path, unitp) 37613044Sasami char *path; 37713044Sasami int *unitp; 37813044Sasami{ 37913044Sasami struct stat st; 38013044Sasami dev_t dev; 38113044Sasami int maxpartitions; 38213044Sasami 38313044Sasami if (stat(path, &st) != 0) 38413044Sasami return (errno); 38513044Sasami 38613044Sasami if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) 38713044Sasami return (EINVAL); 38813044Sasami 38913044Sasami if ((maxpartitions = getmaxpartitions()) < 0) 39013044Sasami return (errno); 39113044Sasami 39213044Sasami *unitp = minor(st.st_rdev) / maxpartitions; 39313044Sasami 39413044Sasami return (0); 39513044Sasami} 39613044Sasami 39713044Sasamistatic char * 39813044Sasamiresolve_ccdname(name) 39913044Sasami char *name; 40013044Sasami{ 40113044Sasami char c, *cp, *path; 40213044Sasami size_t len, newlen; 40313044Sasami int rawpart; 40413044Sasami 40513044Sasami if (name[0] == '/' || name[0] == '.') { 40613044Sasami /* Assume they gave the correct pathname. */ 40713044Sasami return (strdup(name)); 40813044Sasami } 40913044Sasami 41013044Sasami len = strlen(name); 41113044Sasami c = name[len - 1]; 41213044Sasami 41313044Sasami newlen = len + 8; 41413044Sasami if ((path = malloc(newlen)) == NULL) 41513044Sasami return (NULL); 41613044Sasami bzero(path, newlen); 41713044Sasami 41813044Sasami if (isdigit(c)) { 41913044Sasami if ((rawpart = getrawpartition()) < 0) { 42013044Sasami free(path); 42113044Sasami return (NULL); 42213044Sasami } 42313044Sasami (void)sprintf(path, "/dev/%s%c", name, 'a' + rawpart); 42413044Sasami } else 42513044Sasami (void)sprintf(path, "/dev/%s", name); 42613044Sasami 42713044Sasami return (path); 42813044Sasami} 42913044Sasami 43013044Sasamistatic int 43113044Sasamido_io(path, cmd, cciop) 43213044Sasami char *path; 43313044Sasami u_long cmd; 43413044Sasami struct ccd_ioctl *cciop; 43513044Sasami{ 43613044Sasami int fd; 43713044Sasami char *cp; 43813044Sasami 43913044Sasami if ((fd = open(path, O_RDWR, 0640)) < 0) { 44013044Sasami warn("open: %s", path); 44113044Sasami return (1); 44213044Sasami } 44313044Sasami 44413044Sasami if (ioctl(fd, cmd, cciop) < 0) { 44513044Sasami switch (cmd) { 44613044Sasami case CCDIOCSET: 44713044Sasami cp = "CCDIOCSET"; 44813044Sasami break; 44913044Sasami 45013044Sasami case CCDIOCCLR: 45113044Sasami cp = "CCDIOCCLR"; 45213044Sasami break; 45313044Sasami 45413044Sasami default: 45513044Sasami cp = "unknown"; 45613044Sasami } 45713044Sasami warn("ioctl (%s): %s", cp, path); 45813044Sasami return (1); 45913044Sasami } 46013044Sasami 46113044Sasami return (0); 46213044Sasami} 46313044Sasami 46413044Sasami#define KVM_ABORT(kd, str) { \ 46513044Sasami (void)kvm_close((kd)); \ 46613044Sasami warnx((str)); \ 46713044Sasami warnx(kvm_geterr((kd))); \ 46813044Sasami return (1); \ 46913044Sasami} 47013044Sasami 47113044Sasamistatic int 47213044Sasamidump_ccd(argc, argv) 47313044Sasami int argc; 47413044Sasami char **argv; 47513044Sasami{ 47613044Sasami char errbuf[_POSIX2_LINE_MAX], *ccd, *cp; 47713044Sasami struct ccd_softc *cs, *kcs; 47813044Sasami size_t readsize; 47913044Sasami int i, error, numccd, numconfiged = 0; 48013044Sasami kvm_t *kd; 48113044Sasami 48213044Sasami bzero(errbuf, sizeof(errbuf)); 48313044Sasami 48413044Sasami if ((kd = kvm_openfiles(kernel, core, NULL, O_RDONLY, 48513044Sasami errbuf)) == NULL) { 48613044Sasami warnx("can't open kvm: %s", errbuf); 48713044Sasami return (1); 48813044Sasami } 48913044Sasami 49013044Sasami if (kvm_nlist(kd, nl)) 49113044Sasami KVM_ABORT(kd, "ccd-related symbols not available"); 49213044Sasami 49313044Sasami /* Check to see how many ccds are currently configured. */ 49413044Sasami if (kvm_read(kd, nl[SYM_NUMCCD].n_value, (char *)&numccd, 49513044Sasami sizeof(numccd)) != sizeof(numccd)) 49613044Sasami KVM_ABORT(kd, "can't determine number of configured ccds"); 49713044Sasami 49813044Sasami if (numccd == 0) { 49913044Sasami printf("ccd driver in kernel, but is uninitialized\n"); 50013044Sasami goto done; 50113044Sasami } 50213044Sasami 50313044Sasami /* Allocate space for the configuration data. */ 50413044Sasami readsize = numccd * sizeof(struct ccd_softc); 50513044Sasami if ((cs = malloc(readsize)) == NULL) { 50613044Sasami warnx("no memory for configuration data"); 50713044Sasami goto bad; 50813044Sasami } 50913044Sasami bzero(cs, readsize); 51013044Sasami 51113044Sasami /* 51213044Sasami * Read the ccd configuration data from the kernel and dump 51313044Sasami * it to stdout. 51413044Sasami */ 51513044Sasami if (kvm_read(kd, nl[SYM_CCDSOFTC].n_value, (char *)&kcs, 51613044Sasami sizeof(kcs)) != sizeof(kcs)) { 51713044Sasami free(cs); 51813044Sasami KVM_ABORT(kd, "can't find pointer to configuration data"); 51913044Sasami } 52013044Sasami if (kvm_read(kd, (u_long)kcs, (char *)cs, readsize) != readsize) { 52113044Sasami free(cs); 52213044Sasami KVM_ABORT(kd, "can't read configuration data"); 52313044Sasami } 52413044Sasami 52513044Sasami if (argc == 0) { 52613044Sasami for (i = 0; i < numccd; ++i) 52713044Sasami if (cs[i].sc_flags & CCDF_INITED) { 52813044Sasami ++numconfiged; 52913044Sasami print_ccd_info(&cs[i], kd); 53013044Sasami } 53113044Sasami 53213044Sasami if (numconfiged == 0) 53313044Sasami printf("no concatenated disks configured\n"); 53413044Sasami } else { 53513044Sasami while (argc) { 53613044Sasami cp = *argv++; --argc; 53713044Sasami if ((ccd = resolve_ccdname(cp)) == NULL) { 53813044Sasami warnx("invalid ccd name: %s", cp); 53913044Sasami continue; 54013044Sasami } 54113044Sasami if ((error = pathtounit(ccd, &i)) != 0) { 54213044Sasami warnx("%s: %s", ccd, strerror(error)); 54313044Sasami continue; 54413044Sasami } 54513044Sasami if (i >= numccd) { 54613044Sasami warnx("ccd%d not configured", i); 54713044Sasami continue; 54813044Sasami } 54913044Sasami if (cs[i].sc_flags & CCDF_INITED) 55013044Sasami print_ccd_info(&cs[i], kd); 55113044Sasami else 55213044Sasami printf("ccd%d not configured\n", i); 55313044Sasami } 55413044Sasami } 55513044Sasami 55613044Sasami free(cs); 55713044Sasami 55813044Sasami done: 55913044Sasami (void)kvm_close(kd); 56013044Sasami return (0); 56113044Sasami 56213044Sasami bad: 56313044Sasami (void)kvm_close(kd); 56413044Sasami return (1); 56513044Sasami} 56613044Sasami 56713044Sasamistatic void 56813044Sasamiprint_ccd_info(cs, kd) 56913044Sasami struct ccd_softc *cs; 57013044Sasami kvm_t *kd; 57113044Sasami{ 57213044Sasami static int header_printed = 0; 57313044Sasami struct ccdcinfo *cip; 57413044Sasami size_t readsize; 57513044Sasami char path[MAXPATHLEN]; 57613044Sasami int i; 57713044Sasami 57813044Sasami if (header_printed == 0 && verbose) { 57913044Sasami printf("# ccd\t\tileave\tflags\tcompnent devices\n"); 58013044Sasami header_printed = 1; 58113044Sasami } 58213044Sasami 58313044Sasami readsize = cs->sc_nccdisks * sizeof(struct ccdcinfo); 58413044Sasami if ((cip = malloc(readsize)) == NULL) { 58513044Sasami warn("ccd%d: can't allocate memory for component info", 58613044Sasami cs->sc_unit); 58713044Sasami return; 58813044Sasami } 58913044Sasami bzero(cip, readsize); 59013044Sasami 59113044Sasami /* Dump out softc information. */ 59213044Sasami printf("ccd%d\t\t%d\t%d\t", cs->sc_unit, cs->sc_ileave, 59313044Sasami cs->sc_cflags & CCDF_USERMASK); 59413044Sasami fflush(stdout); 59513044Sasami 59613044Sasami /* Read in the component info. */ 59713044Sasami if (kvm_read(kd, (u_long)cs->sc_cinfo, (char *)cip, 59813044Sasami readsize) != readsize) { 59913044Sasami printf("\n"); 60013044Sasami warnx("can't read component info"); 60113044Sasami warnx(kvm_geterr(kd)); 60213044Sasami goto done; 60313044Sasami } 60413044Sasami 60513044Sasami /* Read component pathname and display component info. */ 60613044Sasami for (i = 0; i < cs->sc_nccdisks; ++i) { 60713044Sasami if (kvm_read(kd, (u_long)cip[i].ci_path, (char *)path, 60813044Sasami cip[i].ci_pathlen) != cip[i].ci_pathlen) { 60913044Sasami printf("\n"); 61013044Sasami warnx("can't read component pathname"); 61113044Sasami warnx(kvm_geterr(kd)); 61213044Sasami goto done; 61313044Sasami } 61413044Sasami printf((i + 1 < cs->sc_nccdisks) ? "%s " : "%s\n", path); 61513044Sasami fflush(stdout); 61613044Sasami } 61713044Sasami 61813044Sasami done: 61913044Sasami free(cip); 62013044Sasami} 62113044Sasami 62213044Sasamistatic int 62313044Sasamigetmaxpartitions() 62413044Sasami{ 62513052Sasami return (MAXPARTITIONS); 62613044Sasami} 62713044Sasami 62813044Sasamistatic int 62913044Sasamigetrawpartition() 63013044Sasami{ 63113052Sasami return (RAW_PART); 63213044Sasami} 63313044Sasami 63413044Sasamistatic int 63513044Sasamiflags_to_val(flags) 63613044Sasami char *flags; 63713044Sasami{ 63813044Sasami char *cp, *tok; 63913044Sasami int i, tmp, val = ~CCDF_USERMASK; 64013044Sasami size_t flagslen; 64113044Sasami 64213044Sasami /* 64313044Sasami * The most common case is that of NIL flags, so check for 64413044Sasami * those first. 64513044Sasami */ 64613044Sasami if (strcmp("none", flags) == 0 || strcmp("0x0", flags) == 0 || 64713044Sasami strcmp("0", flags) == 0) 64813044Sasami return (0); 64913044Sasami 65013044Sasami flagslen = strlen(flags); 65113044Sasami 65213044Sasami /* Check for values represented by strings. */ 65313044Sasami if ((cp = strdup(flags)) == NULL) 65413044Sasami err(1, "no memory to parse flags"); 65513044Sasami tmp = 0; 65613044Sasami for (tok = cp; (tok = strtok(tok, ",")) != NULL; tok = NULL) { 65713044Sasami for (i = 0; flagvaltab[i].fv_flag != NULL; ++i) 65813044Sasami if (strcmp(tok, flagvaltab[i].fv_flag) == 0) 65913044Sasami break; 66013044Sasami if (flagvaltab[i].fv_flag == NULL) { 66113044Sasami free(cp); 66213044Sasami goto bad_string; 66313044Sasami } 66413044Sasami tmp |= flagvaltab[i].fv_val; 66513044Sasami } 66613044Sasami 66713044Sasami /* If we get here, the string was ok. */ 66813044Sasami free(cp); 66913044Sasami val = tmp; 67013044Sasami goto out; 67113044Sasami 67213044Sasami bad_string: 67313044Sasami 67413044Sasami /* Check for values represented in hex. */ 67513044Sasami if (flagslen > 2 && flags[0] == '0' && flags[1] == 'x') { 67613044Sasami errno = 0; /* to check for ERANGE */ 67713044Sasami val = (int)strtol(&flags[2], &cp, 16); 67813044Sasami if ((errno == ERANGE) || (*cp != '\0')) 67913044Sasami return (-1); 68013044Sasami goto out; 68113044Sasami } 68213044Sasami 68313044Sasami /* Check for values represented in decimal. */ 68413044Sasami errno = 0; /* to check for ERANGE */ 68513044Sasami val = (int)strtol(flags, &cp, 10); 68613044Sasami if ((errno == ERANGE) || (*cp != '\0')) 68713044Sasami return (-1); 68813044Sasami 68913044Sasami out: 69013044Sasami return (((val & ~CCDF_USERMASK) == 0) ? val : -1); 69113044Sasami} 69213044Sasami 69313044Sasamistatic void 69413044Sasamiusage() 69513044Sasami{ 69613044Sasami 69713044Sasami fprintf(stderr, "usage: %s [-cv] ccd ileave [flags] %s\n", __progname, 69813044Sasami "dev [...]"); 69913044Sasami fprintf(stderr, " %s -C [-v] [-f config_file]\n", __progname); 70013044Sasami fprintf(stderr, " %s -u [-v] ccd [...]\n", __progname); 70113044Sasami fprintf(stderr, " %s -U [-v] [-f config_file]\n", __progname); 70213044Sasami fprintf(stderr, " %s -g [-M core] [-N system] %s\n", __progname, 70313044Sasami "[ccd [...]]"); 70413044Sasami exit(1); 70513044Sasami} 70613052Sasami 70713052Sasami/* Local Variables: */ 70813052Sasami/* c-argdecl-indent: 8 */ 70913052Sasami/* c-indent-level: 8 */ 71013052Sasami/* End: */ 711