ccdconfig.c revision 83329
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 83329 2001-09-11 09:49:36Z ru $"; 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 <limits.h> 5069793Sobrien#include <paths.h> 5113044Sasami#include <stdio.h> 5213044Sasami#include <stdlib.h> 5313044Sasami#include <string.h> 5413044Sasami#include <unistd.h> 5513044Sasami 5639228Sgibbs#include <sys/devicestat.h> 5713052Sasami#include <sys/ccdvar.h> 5813044Sasami 5913044Sasami#include "pathnames.h" 6013044Sasami 6113044Sasamistatic int lineno = 0; 6213044Sasamistatic int verbose = 0; 6313044Sasamistatic char *ccdconf = _PATH_CCDCONF; 6413044Sasami 6513044Sasamistruct flagval { 6613044Sasami char *fv_flag; 6713044Sasami int fv_val; 6813044Sasami} flagvaltab[] = { 6913044Sasami { "CCDF_SWAP", CCDF_SWAP }, 7013044Sasami { "CCDF_UNIFORM", CCDF_UNIFORM }, 7113762Sasami { "CCDF_MIRROR", CCDF_MIRROR }, 7213762Sasami { "CCDF_PARITY", CCDF_PARITY }, 7313044Sasami { NULL, 0 }, 7413044Sasami}; 7513044Sasami 7613044Sasami#define CCD_CONFIG 0 /* configure a device */ 7713044Sasami#define CCD_CONFIGALL 1 /* configure all devices */ 7813044Sasami#define CCD_UNCONFIG 2 /* unconfigure a device */ 7913044Sasami#define CCD_UNCONFIGALL 3 /* unconfigure all devices */ 8013044Sasami#define CCD_DUMP 4 /* dump a ccd's configuration */ 8113044Sasami 8213044Sasamistatic int checkdev __P((char *)); 8313044Sasamistatic int do_io __P((char *, u_long, struct ccd_ioctl *)); 8413044Sasamistatic int do_single __P((int, char **, int)); 8513044Sasamistatic int do_all __P((int)); 8613044Sasamistatic int dump_ccd __P((int, char **)); 8713044Sasamistatic int getmaxpartitions __P((void)); 8813044Sasamistatic int getrawpartition __P((void)); 8913044Sasamistatic int flags_to_val __P((char *)); 9082943Sphkstatic void print_ccd_info __P((struct ccd_s *)); 9113044Sasamistatic char *resolve_ccdname __P((char *)); 9213044Sasamistatic void usage __P((void)); 9313044Sasami 9413044Sasamiint 9513044Sasamimain(argc, argv) 9613044Sasami int argc; 9713044Sasami char **argv; 9813044Sasami{ 9913044Sasami int ch, options = 0, action = CCD_CONFIG; 10013044Sasami 10183329Sru while ((ch = getopt(argc, argv, "cCf:guUv")) != -1) { 10213044Sasami switch (ch) { 10313044Sasami case 'c': 10413044Sasami action = CCD_CONFIG; 10513044Sasami ++options; 10613044Sasami break; 10713044Sasami 10813044Sasami case 'C': 10913044Sasami action = CCD_CONFIGALL; 11013044Sasami ++options; 11113044Sasami break; 11213044Sasami 11313044Sasami case 'f': 11413044Sasami ccdconf = optarg; 11513044Sasami break; 11613044Sasami 11713044Sasami case 'g': 11813044Sasami action = CCD_DUMP; 11913044Sasami break; 12013044Sasami 12113044Sasami case 'u': 12213044Sasami action = CCD_UNCONFIG; 12313044Sasami ++options; 12413044Sasami break; 12513044Sasami 12613044Sasami case 'U': 12713044Sasami action = CCD_UNCONFIGALL; 12813044Sasami ++options; 12913044Sasami break; 13013044Sasami 13113044Sasami case 'v': 13213044Sasami verbose = 1; 13313044Sasami break; 13413044Sasami 13513044Sasami default: 13613044Sasami usage(); 13713044Sasami } 13813044Sasami } 13913044Sasami argc -= optind; 14013044Sasami argv += optind; 14113044Sasami 14213044Sasami if (options > 1) 14313044Sasami usage(); 14413044Sasami 14545329Speter if (modfind("ccd") < 0) { 14645329Speter /* Not present in kernel, try loading it */ 14745329Speter if (kldload("ccd") < 0 || modfind("ccd") < 0) 14845329Speter warn("ccd module not available!"); 14945329Speter } 15045329Speter 15113044Sasami switch (action) { 15213044Sasami case CCD_CONFIG: 15313044Sasami case CCD_UNCONFIG: 15413044Sasami exit(do_single(argc, argv, action)); 15513044Sasami /* NOTREACHED */ 15613044Sasami 15713044Sasami case CCD_CONFIGALL: 15813044Sasami case CCD_UNCONFIGALL: 15913044Sasami exit(do_all(action)); 16013044Sasami /* NOTREACHED */ 16113044Sasami 16213044Sasami case CCD_DUMP: 16313044Sasami exit(dump_ccd(argc, argv)); 16413044Sasami /* NOTREACHED */ 16513044Sasami } 16613044Sasami /* NOTREACHED */ 16736628Scharnier return (0); 16813044Sasami} 16913044Sasami 17013044Sasamistatic int 17113044Sasamido_single(argc, argv, action) 17213044Sasami int argc; 17313044Sasami char **argv; 17413044Sasami int action; 17513044Sasami{ 17613044Sasami struct ccd_ioctl ccio; 17713044Sasami char *ccd, *cp, *cp2, **disks; 17851690Sbillf int noflags = 0, i, ileave, flags = 0, j; 17913044Sasami 18013044Sasami bzero(&ccio, sizeof(ccio)); 18113044Sasami 18213044Sasami /* 18313044Sasami * If unconfiguring, all arguments are treated as ccds. 18413044Sasami */ 18513044Sasami if (action == CCD_UNCONFIG || action == CCD_UNCONFIGALL) { 18613044Sasami for (i = 0; argc != 0; ) { 18713044Sasami cp = *argv++; --argc; 18813044Sasami if ((ccd = resolve_ccdname(cp)) == NULL) { 18913044Sasami warnx("invalid ccd name: %s", cp); 19013044Sasami i = 1; 19113044Sasami continue; 19213044Sasami } 19313044Sasami if (do_io(ccd, CCDIOCCLR, &ccio)) 19413044Sasami i = 1; 19513044Sasami else 19613044Sasami if (verbose) 19713044Sasami printf("%s unconfigured\n", cp); 19813044Sasami } 19913044Sasami return (i); 20013044Sasami } 20113044Sasami 20213044Sasami /* Make sure there are enough arguments. */ 20348568Sbillf if (argc < 4) { 20413044Sasami if (argc == 3) { 20513044Sasami /* Assume that no flags are specified. */ 20613044Sasami noflags = 1; 20713044Sasami } else { 20813044Sasami if (action == CCD_CONFIGALL) { 20913044Sasami warnx("%s: bad line: %d", ccdconf, lineno); 21013044Sasami return (1); 21113044Sasami } else 21213044Sasami usage(); 21313044Sasami } 21448568Sbillf } 21513044Sasami 21613044Sasami /* First argument is the ccd to configure. */ 21713044Sasami cp = *argv++; --argc; 21813044Sasami if ((ccd = resolve_ccdname(cp)) == NULL) { 21913044Sasami warnx("invalid ccd name: %s", cp); 22013044Sasami return (1); 22113044Sasami } 22213044Sasami 22313044Sasami /* Next argument is the interleave factor. */ 22413044Sasami cp = *argv++; --argc; 22513044Sasami errno = 0; /* to check for ERANGE */ 22613044Sasami ileave = (int)strtol(cp, &cp2, 10); 22713044Sasami if ((errno == ERANGE) || (ileave < 0) || (*cp2 != '\0')) { 22813044Sasami warnx("invalid interleave factor: %s", cp); 22913044Sasami return (1); 23013044Sasami } 23113044Sasami 23213044Sasami if (noflags == 0) { 23313044Sasami /* Next argument is the ccd configuration flags. */ 23413044Sasami cp = *argv++; --argc; 23513044Sasami if ((flags = flags_to_val(cp)) < 0) { 23613044Sasami warnx("invalid flags argument: %s", cp); 23713044Sasami return (1); 23813044Sasami } 23913044Sasami } 24013044Sasami 24113044Sasami /* Next is the list of disks to make the ccd from. */ 24213044Sasami disks = malloc(argc * sizeof(char *)); 24313044Sasami if (disks == NULL) { 24413044Sasami warnx("no memory to configure ccd"); 24513044Sasami return (1); 24613044Sasami } 24713044Sasami for (i = 0; argc != 0; ) { 24813044Sasami cp = *argv++; --argc; 24913044Sasami if ((j = checkdev(cp)) == 0) 25013044Sasami disks[i++] = cp; 25113044Sasami else { 25213044Sasami warnx("%s: %s", cp, strerror(j)); 25313044Sasami return (1); 25413044Sasami } 25513044Sasami } 25613044Sasami 25713044Sasami /* Fill in the ccio. */ 25813044Sasami ccio.ccio_disks = disks; 25913044Sasami ccio.ccio_ndisks = i; 26013044Sasami ccio.ccio_ileave = ileave; 26113044Sasami ccio.ccio_flags = flags; 26213044Sasami 26313044Sasami if (do_io(ccd, CCDIOCSET, &ccio)) { 26413044Sasami free(disks); 26513044Sasami return (1); 26613044Sasami } 26713044Sasami 26813044Sasami if (verbose) { 26913044Sasami printf("ccd%d: %d components ", ccio.ccio_unit, 27013044Sasami ccio.ccio_ndisks); 27113044Sasami for (i = 0; i < ccio.ccio_ndisks; ++i) { 27213044Sasami if ((cp2 = strrchr(disks[i], '/')) != NULL) 27313044Sasami ++cp2; 27413044Sasami else 27513044Sasami cp2 = disks[i]; 27613044Sasami printf("%c%s%c", 27713044Sasami i == 0 ? '(' : ' ', cp2, 27813044Sasami i == ccio.ccio_ndisks - 1 ? ')' : ','); 27913044Sasami } 28048568Sbillf printf(", %lu blocks ", (u_long)ccio.ccio_size); 28113044Sasami if (ccio.ccio_ileave != 0) 28213044Sasami printf("interleaved at %d blocks\n", ccio.ccio_ileave); 28313044Sasami else 28413044Sasami printf("concatenated\n"); 28513044Sasami } 28613044Sasami 28713044Sasami free(disks); 28813044Sasami return (0); 28913044Sasami} 29013044Sasami 29113044Sasamistatic int 29213044Sasamido_all(action) 29313044Sasami int action; 29413044Sasami{ 29513044Sasami FILE *f; 29613044Sasami char line[_POSIX2_LINE_MAX]; 29713044Sasami char *cp, **argv; 29813044Sasami int argc, rval; 29932116Simp gid_t egid; 30013044Sasami 30151690Sbillf rval = 0; 30232116Simp egid = getegid(); 30332116Simp setegid(getgid()); 30413044Sasami if ((f = fopen(ccdconf, "r")) == NULL) { 30532116Simp setegid(egid); 30613044Sasami warn("fopen: %s", ccdconf); 30713044Sasami return (1); 30813044Sasami } 30932116Simp setegid(egid); 31013044Sasami 31113044Sasami while (fgets(line, sizeof(line), f) != NULL) { 31213044Sasami argc = 0; 31313044Sasami argv = NULL; 31413044Sasami ++lineno; 31513044Sasami if ((cp = strrchr(line, '\n')) != NULL) 31613044Sasami *cp = '\0'; 31713044Sasami 31813044Sasami /* Break up the line and pass it's contents to do_single(). */ 31913044Sasami if (line[0] == '\0') 32013044Sasami goto end_of_line; 32113044Sasami for (cp = line; (cp = strtok(cp, " \t")) != NULL; cp = NULL) { 32213044Sasami if (*cp == '#') 32313044Sasami break; 32413044Sasami if ((argv = realloc(argv, 32513044Sasami sizeof(char *) * ++argc)) == NULL) { 32613044Sasami warnx("no memory to configure ccds"); 32713044Sasami return (1); 32813044Sasami } 32913044Sasami argv[argc - 1] = cp; 33013044Sasami /* 33113044Sasami * If our action is to unconfigure all, then pass 33213044Sasami * just the first token to do_single() and ignore 33313044Sasami * the rest. Since this will be encountered on 33413044Sasami * our first pass through the line, the Right 33513044Sasami * Thing will happen. 33613044Sasami */ 33713044Sasami if (action == CCD_UNCONFIGALL) { 33813044Sasami if (do_single(argc, argv, action)) 33913044Sasami rval = 1; 34013044Sasami goto end_of_line; 34113044Sasami } 34213044Sasami } 34313044Sasami if (argc != 0) 34413044Sasami if (do_single(argc, argv, action)) 34513044Sasami rval = 1; 34613044Sasami 34713044Sasami end_of_line: 34813044Sasami if (argv != NULL) 34913044Sasami free(argv); 35013044Sasami } 35113044Sasami 35213044Sasami (void)fclose(f); 35313044Sasami return (rval); 35413044Sasami} 35513044Sasami 35613044Sasamistatic int 35713044Sasamicheckdev(path) 35813044Sasami char *path; 35913044Sasami{ 36013044Sasami struct stat st; 36113044Sasami 36213044Sasami if (stat(path, &st) != 0) 36313044Sasami return (errno); 36413044Sasami 36513044Sasami if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) 36613044Sasami return (EINVAL); 36713044Sasami 36813044Sasami return (0); 36913044Sasami} 37013044Sasami 37113044Sasamistatic int 37213044Sasamipathtounit(path, unitp) 37313044Sasami char *path; 37413044Sasami int *unitp; 37513044Sasami{ 37613044Sasami struct stat st; 37713044Sasami int maxpartitions; 37813044Sasami 37913044Sasami if (stat(path, &st) != 0) 38013044Sasami return (errno); 38113044Sasami 38213044Sasami if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) 38313044Sasami return (EINVAL); 38413044Sasami 38513044Sasami if ((maxpartitions = getmaxpartitions()) < 0) 38613044Sasami return (errno); 38713044Sasami 38813044Sasami *unitp = minor(st.st_rdev) / maxpartitions; 38913044Sasami 39013044Sasami return (0); 39113044Sasami} 39213044Sasami 39313044Sasamistatic char * 39413044Sasamiresolve_ccdname(name) 39513044Sasami char *name; 39613044Sasami{ 39736628Scharnier char c, *path; 39813044Sasami size_t len, newlen; 39913044Sasami int rawpart; 40013044Sasami 40113044Sasami if (name[0] == '/' || name[0] == '.') { 40213044Sasami /* Assume they gave the correct pathname. */ 40313044Sasami return (strdup(name)); 40413044Sasami } 40513044Sasami 40613044Sasami len = strlen(name); 40713044Sasami c = name[len - 1]; 40813044Sasami 40913044Sasami newlen = len + 8; 41013044Sasami if ((path = malloc(newlen)) == NULL) 41113044Sasami return (NULL); 41213044Sasami bzero(path, newlen); 41313044Sasami 41413044Sasami if (isdigit(c)) { 41513044Sasami if ((rawpart = getrawpartition()) < 0) { 41613044Sasami free(path); 41713044Sasami return (NULL); 41813044Sasami } 41969793Sobrien (void)sprintf(path, "%s%s%c", _PATH_DEV, name, 'a' + rawpart); 42013044Sasami } else 42169793Sobrien (void)sprintf(path, "%s%s", _PATH_DEV, name); 42213044Sasami 42313044Sasami return (path); 42413044Sasami} 42513044Sasami 42613044Sasamistatic int 42713044Sasamido_io(path, cmd, cciop) 42813044Sasami char *path; 42913044Sasami u_long cmd; 43013044Sasami struct ccd_ioctl *cciop; 43113044Sasami{ 43213044Sasami int fd; 43313044Sasami char *cp; 43413044Sasami 43513044Sasami if ((fd = open(path, O_RDWR, 0640)) < 0) { 43613044Sasami warn("open: %s", path); 43713044Sasami return (1); 43813044Sasami } 43913044Sasami 44013044Sasami if (ioctl(fd, cmd, cciop) < 0) { 44113044Sasami switch (cmd) { 44213044Sasami case CCDIOCSET: 44313044Sasami cp = "CCDIOCSET"; 44413044Sasami break; 44513044Sasami 44613044Sasami case CCDIOCCLR: 44713044Sasami cp = "CCDIOCCLR"; 44813044Sasami break; 44913044Sasami 45082943Sphk case CCDCONFINFO: 45182943Sphk cp = "CCDCONFINFO"; 45282943Sphk break; 45382943Sphk 45482943Sphk case CCDCPPINFO: 45582943Sphk cp = "CCDCPPINFO"; 45682943Sphk break; 45782943Sphk 45813044Sasami default: 45913044Sasami cp = "unknown"; 46013044Sasami } 46113044Sasami warn("ioctl (%s): %s", cp, path); 46213044Sasami return (1); 46313044Sasami } 46413044Sasami 46513044Sasami return (0); 46613044Sasami} 46713044Sasami 46813044Sasamistatic int 46913044Sasamidump_ccd(argc, argv) 47013044Sasami int argc; 47113044Sasami char **argv; 47213044Sasami{ 47382943Sphk char *ccd, *cp; 47413044Sasami int i, error, numccd, numconfiged = 0; 47582943Sphk struct ccdconf conf; 47613044Sasami 47782943Sphk /* 47882943Sphk * Read the ccd configuration data from the kernel and dump 47982943Sphk * it to stdout. 48082943Sphk */ 48182943Sphk if ((ccd = resolve_ccdname("ccd0")) == NULL) { /* XXX */ 48282943Sphk warnx("invalid ccd name: %s", cp); 48313044Sasami return (1); 48413044Sasami } 48582943Sphk conf.size = 0; 48682943Sphk if (do_io(ccd, CCDCONFINFO, (struct ccd_ioctl *) &conf)) 48782943Sphk return (1); 48882943Sphk if (conf.size == 0) { 48982943Sphk printf("no concatenated disks configured\n"); 49082943Sphk return (0); 49113044Sasami } 49213044Sasami /* Allocate space for the configuration data. */ 49382943Sphk conf.buffer = alloca(conf.size); 49482943Sphk if (conf.buffer == NULL) { 49513044Sasami warnx("no memory for configuration data"); 49682943Sphk return (1); 49713044Sasami } 49882943Sphk if (do_io(ccd, CCDCONFINFO, (struct ccd_ioctl *) &conf)) 49982943Sphk return (1); 50013044Sasami 50182943Sphk numconfiged = conf.size / sizeof(struct ccd_s); 50213044Sasami 50313044Sasami if (argc == 0) { 50482943Sphk for (i = 0; i < numconfiged; i++) 50582943Sphk print_ccd_info(&(conf.buffer[i])); 50613044Sasami } else { 50713044Sasami while (argc) { 50813044Sasami cp = *argv++; --argc; 50913044Sasami if ((ccd = resolve_ccdname(cp)) == NULL) { 51013044Sasami warnx("invalid ccd name: %s", cp); 51113044Sasami continue; 51213044Sasami } 51382943Sphk if ((error = pathtounit(ccd, &numccd)) != 0) { 51413044Sasami warnx("%s: %s", ccd, strerror(error)); 51513044Sasami continue; 51613044Sasami } 51782943Sphk error = 1; 51882943Sphk for (i = 0; i < numconfiged; i++) { 51982943Sphk if (conf.buffer[i].sc_unit == numccd) { 52082943Sphk print_ccd_info(&(conf.buffer[i])); 52182943Sphk error = 0; 52282943Sphk break; 52382943Sphk } 52482943Sphk } 52582943Sphk if (error) { 52682943Sphk warnx("ccd%d not configured", numccd); 52713044Sasami continue; 52813044Sasami } 52913044Sasami } 53082943Sphk } 53113044Sasami 53213044Sasami return (0); 53313044Sasami} 53413044Sasami 53513044Sasamistatic void 53682943Sphkprint_ccd_info(cs) 53782943Sphk struct ccd_s *cs; 53813044Sasami{ 53982943Sphk char *cp, *ccd; 54013044Sasami static int header_printed = 0; 54182943Sphk struct ccdcpps cpps; 54213044Sasami 54382943Sphk /* Print out header if necessary*/ 54413044Sasami if (header_printed == 0 && verbose) { 54513044Sasami printf("# ccd\t\tileave\tflags\tcompnent devices\n"); 54613044Sasami header_printed = 1; 54713044Sasami } 54813044Sasami 54913044Sasami /* Dump out softc information. */ 55013044Sasami printf("ccd%d\t\t%d\t%d\t", cs->sc_unit, cs->sc_ileave, 55113044Sasami cs->sc_cflags & CCDF_USERMASK); 55213044Sasami fflush(stdout); 55313044Sasami 55413044Sasami /* Read in the component info. */ 55582943Sphk asprintf(&cp, "%s%d", cs->device_stats.device_name, 55682943Sphk cs->device_stats.unit_number); 55782943Sphk if (cp == NULL) { 55813044Sasami printf("\n"); 55982943Sphk warn("ccd%d: can't allocate memory", 56082943Sphk cs->sc_unit); 56182943Sphk return; 56282943Sphk } 56382943Sphk 56482943Sphk if ((ccd = resolve_ccdname(cp)) == NULL) { 56582943Sphk printf("\n"); 56682943Sphk warnx("can't read component info: invalid ccd name: %s", cp); 56782943Sphk return; 56882943Sphk } 56982943Sphk cpps.size = 0; 57082943Sphk if (do_io(ccd, CCDCPPINFO, (struct ccd_ioctl *) &cpps)) { 57182943Sphk printf("\n"); 57213044Sasami warnx("can't read component info"); 57382943Sphk return; 57413044Sasami } 57582943Sphk cpps.buffer = alloca(cpps.size); 57682943Sphk if (cpps.buffer == NULL) { 57782943Sphk printf("\n"); 57882943Sphk warn("ccd%d: can't allocate memory for component info", 57982943Sphk cs->sc_unit); 58082943Sphk return; 58182943Sphk } 58282943Sphk if (do_io(ccd, CCDCPPINFO, (struct ccd_ioctl *) &cpps)) { 58382943Sphk printf("\n"); 58482943Sphk warnx("can't read component info"); 58582943Sphk return; 58682943Sphk } 58713044Sasami 58882943Sphk /* Display component info. */ 58982943Sphk for (cp = cpps.buffer; cp - cpps.buffer < cpps.size; cp += strlen(cp) + 1) { 59082943Sphk printf((cp + strlen(cp) + 1) < (cpps.buffer + cpps.size) ? 59182943Sphk "%s " : "%s\n", cp); 59213044Sasami fflush(stdout); 59313044Sasami } 59482943Sphk return; 59513044Sasami} 59613044Sasami 59713044Sasamistatic int 59813044Sasamigetmaxpartitions() 59913044Sasami{ 60013052Sasami return (MAXPARTITIONS); 60113044Sasami} 60213044Sasami 60313044Sasamistatic int 60413044Sasamigetrawpartition() 60513044Sasami{ 60613052Sasami return (RAW_PART); 60713044Sasami} 60813044Sasami 60913044Sasamistatic int 61013044Sasamiflags_to_val(flags) 61113044Sasami char *flags; 61213044Sasami{ 61313044Sasami char *cp, *tok; 61413044Sasami int i, tmp, val = ~CCDF_USERMASK; 61513044Sasami size_t flagslen; 61613044Sasami 61713044Sasami /* 61813044Sasami * The most common case is that of NIL flags, so check for 61913044Sasami * those first. 62013044Sasami */ 62113044Sasami if (strcmp("none", flags) == 0 || strcmp("0x0", flags) == 0 || 62213044Sasami strcmp("0", flags) == 0) 62313044Sasami return (0); 62413044Sasami 62513044Sasami flagslen = strlen(flags); 62613044Sasami 62713044Sasami /* Check for values represented by strings. */ 62813044Sasami if ((cp = strdup(flags)) == NULL) 62913044Sasami err(1, "no memory to parse flags"); 63013044Sasami tmp = 0; 63113044Sasami for (tok = cp; (tok = strtok(tok, ",")) != NULL; tok = NULL) { 63213044Sasami for (i = 0; flagvaltab[i].fv_flag != NULL; ++i) 63313044Sasami if (strcmp(tok, flagvaltab[i].fv_flag) == 0) 63413044Sasami break; 63513044Sasami if (flagvaltab[i].fv_flag == NULL) { 63613044Sasami free(cp); 63713044Sasami goto bad_string; 63813044Sasami } 63913044Sasami tmp |= flagvaltab[i].fv_val; 64013044Sasami } 64113044Sasami 64213044Sasami /* If we get here, the string was ok. */ 64313044Sasami free(cp); 64413044Sasami val = tmp; 64513044Sasami goto out; 64613044Sasami 64713044Sasami bad_string: 64813044Sasami 64913044Sasami /* Check for values represented in hex. */ 65013044Sasami if (flagslen > 2 && flags[0] == '0' && flags[1] == 'x') { 65113044Sasami errno = 0; /* to check for ERANGE */ 65213044Sasami val = (int)strtol(&flags[2], &cp, 16); 65313044Sasami if ((errno == ERANGE) || (*cp != '\0')) 65413044Sasami return (-1); 65513044Sasami goto out; 65613044Sasami } 65713044Sasami 65813044Sasami /* Check for values represented in decimal. */ 65913044Sasami errno = 0; /* to check for ERANGE */ 66013044Sasami val = (int)strtol(flags, &cp, 10); 66113044Sasami if ((errno == ERANGE) || (*cp != '\0')) 66213044Sasami return (-1); 66313044Sasami 66413044Sasami out: 66513044Sasami return (((val & ~CCDF_USERMASK) == 0) ? val : -1); 66613044Sasami} 66713044Sasami 66813044Sasamistatic void 66913044Sasamiusage() 67013044Sasami{ 67126541Scharnier fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 67226541Scharnier "usage: ccdconfig [-cv] ccd ileave [flags] dev [...]", 67326541Scharnier " ccdconfig -C [-v] [-f config_file]", 67426541Scharnier " ccdconfig -u [-v] ccd [...]", 67526541Scharnier " ccdconfig -U [-v] [-f config_file]", 67682943Sphk " ccdconfig -g [ccd [...]]"); 67713044Sasami exit(1); 67813044Sasami} 67926541Scharnier 68013052Sasami/* Local Variables: */ 68113052Sasami/* c-argdecl-indent: 8 */ 68213052Sasami/* c-indent-level: 8 */ 68313052Sasami/* End: */ 684