1110603Sphk/*- 2110603Sphk * Copyright (c) 2003 Poul-Henning Kamp 3110603Sphk * All rights reserved. 4110603Sphk * 5110603Sphk * Redistribution and use in source and binary forms, with or without 6110603Sphk * modification, are permitted provided that the following conditions 7110603Sphk * are met: 8110603Sphk * 1. Redistributions of source code must retain the above copyright 9110603Sphk * notice, this list of conditions and the following disclaimer. 10110603Sphk * 2. Redistributions in binary form must reproduce the above copyright 11110603Sphk * notice, this list of conditions and the following disclaimer in the 12110603Sphk * documentation and/or other materials provided with the distribution. 13110603Sphk * 3. The names of the authors may not be used to endorse or promote 14110603Sphk * products derived from this software without specific prior written 15110603Sphk * permission. 16110603Sphk * 17110603Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18110603Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19110603Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20110603Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21110603Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22110603Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23110603Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24110603Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25110603Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26110603Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27110603Sphk * SUCH DAMAGE. 28110603Sphk * 29110603Sphk * $FreeBSD$ 30110603Sphk */ 31110603Sphk 32110603Sphk#include <stdio.h> 33110603Sphk#include <inttypes.h> 34110603Sphk#include <stdlib.h> 35110603Sphk#include <string.h> 36110603Sphk#include <unistd.h> 37110603Sphk#include <errno.h> 38110603Sphk#include <fcntl.h> 39110603Sphk#include <ctype.h> 40110603Sphk#include <sys/stat.h> 41110603Sphk#include <sys/mman.h> 42110603Sphk#include <sys/queue.h> 43110603Sphk#include <sys/sbuf.h> 44110603Sphk#include <sys/sysctl.h> 45110603Sphk#include <err.h> 46110603Sphk#include <bsdxml.h> 47110603Sphk#include <libgeom.h> 48110603Sphk 49110603Sphkstruct mystate { 50110603Sphk struct gmesh *mesh; 51110603Sphk struct gclass *class; 52110603Sphk struct ggeom *geom; 53110603Sphk struct gprovider *provider; 54110603Sphk struct gconsumer *consumer; 55110603Sphk int level; 56110603Sphk struct sbuf *sbuf[20]; 57110603Sphk struct gconf *config; 58110603Sphk int nident; 59244208Sjh XML_Parser parser; 60244208Sjh int error; 61110603Sphk}; 62110603Sphk 63110603Sphkstatic void 64110603SphkStartElement(void *userData, const char *name, const char **attr) 65110603Sphk{ 66110603Sphk struct mystate *mt; 67110603Sphk void *id; 68110603Sphk void *ref; 69110603Sphk int i; 70110603Sphk 71110603Sphk mt = userData; 72110603Sphk mt->level++; 73181463Sdes mt->sbuf[mt->level] = sbuf_new_auto(); 74110603Sphk id = NULL; 75126786Sjhb ref = NULL; 76110603Sphk for (i = 0; attr[i] != NULL; i += 2) { 77110603Sphk if (!strcmp(attr[i], "id")) { 78110603Sphk id = (void *)strtoul(attr[i + 1], NULL, 0); 79110603Sphk mt->nident++; 80110603Sphk } else if (!strcmp(attr[i], "ref")) { 81110603Sphk ref = (void *)strtoul(attr[i + 1], NULL, 0); 82110603Sphk } else 83110603Sphk printf("%*.*s[%s = %s]\n", 84110603Sphk mt->level + 1, mt->level + 1, "", 85110603Sphk attr[i], attr[i + 1]); 86110603Sphk } 87110603Sphk if (!strcmp(name, "class") && mt->class == NULL) { 88110603Sphk mt->class = calloc(1, sizeof *mt->class); 89180369Slulf if (mt->class == NULL) { 90244208Sjh mt->error = errno; 91244208Sjh XML_StopParser(mt->parser, 0); 92180369Slulf warn("Cannot allocate memory during processing of '%s' " 93180369Slulf "element", name); 94180369Slulf return; 95180369Slulf } 96126786Sjhb mt->class->lg_id = id; 97126786Sjhb LIST_INSERT_HEAD(&mt->mesh->lg_class, mt->class, lg_class); 98126786Sjhb LIST_INIT(&mt->class->lg_geom); 99126786Sjhb LIST_INIT(&mt->class->lg_config); 100110603Sphk return; 101110603Sphk } 102110603Sphk if (!strcmp(name, "geom") && mt->geom == NULL) { 103110603Sphk mt->geom = calloc(1, sizeof *mt->geom); 104180369Slulf if (mt->geom == NULL) { 105244208Sjh mt->error = errno; 106244208Sjh XML_StopParser(mt->parser, 0); 107180369Slulf warn("Cannot allocate memory during processing of '%s' " 108180369Slulf "element", name); 109180369Slulf return; 110180369Slulf } 111126786Sjhb mt->geom->lg_id = id; 112126786Sjhb LIST_INSERT_HEAD(&mt->class->lg_geom, mt->geom, lg_geom); 113126786Sjhb LIST_INIT(&mt->geom->lg_provider); 114126786Sjhb LIST_INIT(&mt->geom->lg_consumer); 115126786Sjhb LIST_INIT(&mt->geom->lg_config); 116110603Sphk return; 117110603Sphk } 118110603Sphk if (!strcmp(name, "class") && mt->geom != NULL) { 119126786Sjhb mt->geom->lg_class = ref; 120110603Sphk return; 121110603Sphk } 122110603Sphk if (!strcmp(name, "consumer") && mt->consumer == NULL) { 123110603Sphk mt->consumer = calloc(1, sizeof *mt->consumer); 124180369Slulf if (mt->consumer == NULL) { 125244208Sjh mt->error = errno; 126244208Sjh XML_StopParser(mt->parser, 0); 127180369Slulf warn("Cannot allocate memory during processing of '%s' " 128180369Slulf "element", name); 129180369Slulf return; 130180369Slulf } 131126786Sjhb mt->consumer->lg_id = id; 132126786Sjhb LIST_INSERT_HEAD(&mt->geom->lg_consumer, mt->consumer, 133126786Sjhb lg_consumer); 134126786Sjhb LIST_INIT(&mt->consumer->lg_config); 135110603Sphk return; 136110603Sphk } 137110603Sphk if (!strcmp(name, "geom") && mt->consumer != NULL) { 138126786Sjhb mt->consumer->lg_geom = ref; 139110603Sphk return; 140110603Sphk } 141110603Sphk if (!strcmp(name, "provider") && mt->consumer != NULL) { 142126786Sjhb mt->consumer->lg_provider = ref; 143110603Sphk return; 144110603Sphk } 145110603Sphk if (!strcmp(name, "provider") && mt->provider == NULL) { 146110603Sphk mt->provider = calloc(1, sizeof *mt->provider); 147180369Slulf if (mt->provider == NULL) { 148244208Sjh mt->error = errno; 149244208Sjh XML_StopParser(mt->parser, 0); 150180369Slulf warn("Cannot allocate memory during processing of '%s' " 151180369Slulf "element", name); 152180369Slulf return; 153180369Slulf } 154126786Sjhb mt->provider->lg_id = id; 155126786Sjhb LIST_INSERT_HEAD(&mt->geom->lg_provider, mt->provider, 156126786Sjhb lg_provider); 157126786Sjhb LIST_INIT(&mt->provider->lg_consumers); 158126786Sjhb LIST_INIT(&mt->provider->lg_config); 159110603Sphk return; 160110603Sphk } 161110603Sphk if (!strcmp(name, "geom") && mt->provider != NULL) { 162126786Sjhb mt->provider->lg_geom = ref; 163110603Sphk return; 164110603Sphk } 165110603Sphk if (!strcmp(name, "config")) { 166110603Sphk if (mt->provider != NULL) { 167126786Sjhb mt->config = &mt->provider->lg_config; 168110603Sphk return; 169110603Sphk } 170110603Sphk if (mt->consumer != NULL) { 171126786Sjhb mt->config = &mt->consumer->lg_config; 172110603Sphk return; 173110603Sphk } 174110603Sphk if (mt->geom != NULL) { 175126786Sjhb mt->config = &mt->geom->lg_config; 176110603Sphk return; 177110603Sphk } 178110603Sphk if (mt->class != NULL) { 179126786Sjhb mt->config = &mt->class->lg_config; 180110603Sphk return; 181110603Sphk } 182110603Sphk } 183110603Sphk} 184110603Sphk 185110603Sphkstatic void 186110603SphkEndElement(void *userData, const char *name) 187110603Sphk{ 188110603Sphk struct mystate *mt; 189110603Sphk struct gconfig *gc; 190110603Sphk char *p; 191110603Sphk 192110603Sphk mt = userData; 193244208Sjh p = NULL; 194244208Sjh if (sbuf_finish(mt->sbuf[mt->level]) == 0) 195244208Sjh p = strdup(sbuf_data(mt->sbuf[mt->level])); 196244208Sjh sbuf_delete(mt->sbuf[mt->level]); 197244208Sjh mt->sbuf[mt->level] = NULL; 198244208Sjh mt->level--; 199180369Slulf if (p == NULL) { 200244208Sjh mt->error = errno; 201244208Sjh XML_StopParser(mt->parser, 0); 202180369Slulf warn("Cannot allocate memory during processing of '%s' " 203180369Slulf "element", name); 204180369Slulf return; 205180369Slulf } 206110603Sphk if (strlen(p) == 0) { 207110603Sphk free(p); 208110603Sphk p = NULL; 209110603Sphk } 210110603Sphk 211110603Sphk if (!strcmp(name, "name")) { 212110603Sphk if (mt->provider != NULL) { 213126786Sjhb mt->provider->lg_name = p; 214110603Sphk return; 215110603Sphk } else if (mt->geom != NULL) { 216126786Sjhb mt->geom->lg_name = p; 217110603Sphk return; 218110603Sphk } else if (mt->class != NULL) { 219126786Sjhb mt->class->lg_name = p; 220110603Sphk return; 221110603Sphk } 222110603Sphk } 223110603Sphk if (!strcmp(name, "rank") && mt->geom != NULL) { 224126786Sjhb mt->geom->lg_rank = strtoul(p, NULL, 0); 225110603Sphk free(p); 226110603Sphk return; 227110603Sphk } 228110603Sphk if (!strcmp(name, "mode") && mt->provider != NULL) { 229126786Sjhb mt->provider->lg_mode = p; 230110603Sphk return; 231110603Sphk } 232110603Sphk if (!strcmp(name, "mode") && mt->consumer != NULL) { 233126786Sjhb mt->consumer->lg_mode = p; 234110603Sphk return; 235110603Sphk } 236110603Sphk if (!strcmp(name, "mediasize") && mt->provider != NULL) { 237126786Sjhb mt->provider->lg_mediasize = strtoumax(p, NULL, 0); 238110603Sphk free(p); 239110603Sphk return; 240110603Sphk } 241110603Sphk if (!strcmp(name, "sectorsize") && mt->provider != NULL) { 242126786Sjhb mt->provider->lg_sectorsize = strtoul(p, NULL, 0); 243110603Sphk free(p); 244110603Sphk return; 245110603Sphk } 246202454Sdelphij if (!strcmp(name, "stripesize") && mt->provider != NULL) { 247202454Sdelphij mt->provider->lg_stripesize = strtoumax(p, NULL, 0); 248202454Sdelphij free(p); 249202454Sdelphij return; 250202454Sdelphij } 251202454Sdelphij if (!strcmp(name, "stripeoffset") && mt->provider != NULL) { 252202454Sdelphij mt->provider->lg_stripeoffset = strtoumax(p, NULL, 0); 253202454Sdelphij free(p); 254202454Sdelphij return; 255202454Sdelphij } 256110603Sphk 257110603Sphk if (!strcmp(name, "config")) { 258110603Sphk mt->config = NULL; 259110603Sphk return; 260110603Sphk } 261110603Sphk 262110603Sphk if (mt->config != NULL) { 263180369Slulf gc = calloc(1, sizeof *gc); 264180369Slulf if (gc == NULL) { 265244208Sjh mt->error = errno; 266244208Sjh XML_StopParser(mt->parser, 0); 267180369Slulf warn("Cannot allocate memory during processing of '%s' " 268180369Slulf "element", name); 269180369Slulf return; 270180369Slulf } 271126786Sjhb gc->lg_name = strdup(name); 272180369Slulf if (gc->lg_name == NULL) { 273244208Sjh mt->error = errno; 274244208Sjh XML_StopParser(mt->parser, 0); 275180369Slulf warn("Cannot allocate memory during processing of '%s' " 276180369Slulf "element", name); 277180369Slulf return; 278180369Slulf } 279126786Sjhb gc->lg_val = p; 280126786Sjhb LIST_INSERT_HEAD(mt->config, gc, lg_config); 281110603Sphk return; 282110603Sphk } 283110603Sphk 284110603Sphk if (p != NULL) { 285112340Sphk printf("Unexpected XML: name=%s data=\"%s\"\n", name, p); 286110603Sphk free(p); 287110603Sphk } 288110603Sphk 289110603Sphk if (!strcmp(name, "consumer") && mt->consumer != NULL) { 290110603Sphk mt->consumer = NULL; 291110603Sphk return; 292110603Sphk } 293110603Sphk if (!strcmp(name, "provider") && mt->provider != NULL) { 294110603Sphk mt->provider = NULL; 295110603Sphk return; 296110603Sphk } 297110603Sphk if (!strcmp(name, "geom") && mt->consumer != NULL) { 298110603Sphk return; 299110603Sphk } 300110603Sphk if (!strcmp(name, "geom") && mt->provider != NULL) { 301110603Sphk return; 302110603Sphk } 303110603Sphk if (!strcmp(name, "geom") && mt->geom != NULL) { 304110603Sphk mt->geom = NULL; 305110603Sphk return; 306110603Sphk } 307110603Sphk if (!strcmp(name, "class") && mt->geom != NULL) { 308110603Sphk return; 309110603Sphk } 310110603Sphk if (!strcmp(name, "class") && mt->class != NULL) { 311110603Sphk mt->class = NULL; 312110603Sphk return; 313110603Sphk } 314110603Sphk} 315110603Sphk 316110603Sphkstatic void 317110603SphkCharData(void *userData , const XML_Char *s , int len) 318110603Sphk{ 319110603Sphk struct mystate *mt; 320110603Sphk const char *b, *e; 321110603Sphk 322110603Sphk mt = userData; 323110603Sphk 324110603Sphk b = s; 325110603Sphk e = s + len - 1; 326110603Sphk while (isspace(*b) && b < e) 327110603Sphk b++; 328110603Sphk while (isspace(*e) && e > b) 329110603Sphk e--; 330110603Sphk if (e != b || (*b && !isspace(*b))) 331110603Sphk sbuf_bcat(mt->sbuf[mt->level], b, e - b + 1); 332110603Sphk} 333110603Sphk 334110603Sphkstruct gident * 335112340Sphkgeom_lookupid(struct gmesh *gmp, const void *id) 336110603Sphk{ 337110603Sphk struct gident *gip; 338110603Sphk 339126786Sjhb for (gip = gmp->lg_ident; gip->lg_id != NULL; gip++) 340126786Sjhb if (gip->lg_id == id) 341110603Sphk return (gip); 342110603Sphk return (NULL); 343110603Sphk} 344110603Sphk 345110603Sphkint 346110603Sphkgeom_xml2tree(struct gmesh *gmp, char *p) 347110603Sphk{ 348110603Sphk XML_Parser parser; 349110603Sphk struct mystate *mt; 350110603Sphk struct gclass *cl; 351110603Sphk struct ggeom *ge; 352110603Sphk struct gprovider *pr; 353110603Sphk struct gconsumer *co; 354244208Sjh int error, i; 355110603Sphk 356110603Sphk memset(gmp, 0, sizeof *gmp); 357126786Sjhb LIST_INIT(&gmp->lg_class); 358110603Sphk parser = XML_ParserCreate(NULL); 359213451Semaste if (parser == NULL) 360213451Semaste return (ENOMEM); 361110603Sphk mt = calloc(1, sizeof *mt); 362213451Semaste if (mt == NULL) { 363213451Semaste XML_ParserFree(parser); 364110603Sphk return (ENOMEM); 365213451Semaste } 366110603Sphk mt->mesh = gmp; 367244208Sjh mt->parser = parser; 368244208Sjh error = 0; 369110603Sphk XML_SetUserData(parser, mt); 370110603Sphk XML_SetElementHandler(parser, StartElement, EndElement); 371110603Sphk XML_SetCharacterDataHandler(parser, CharData); 372110603Sphk i = XML_Parse(parser, p, strlen(p), 1); 373244208Sjh if (mt->error != 0) 374244208Sjh error = mt->error; 375244208Sjh else if (i != 1) { 376244208Sjh error = XML_GetErrorCode(parser) == XML_ERROR_NO_MEMORY ? 377244208Sjh ENOMEM : EILSEQ; 378244208Sjh } 379213451Semaste XML_ParserFree(parser); 380244208Sjh if (error != 0) { 381213451Semaste free(mt); 382244208Sjh return (error); 383213451Semaste } 384126786Sjhb gmp->lg_ident = calloc(sizeof *gmp->lg_ident, mt->nident + 1); 385213451Semaste free(mt); 386126786Sjhb if (gmp->lg_ident == NULL) 387110603Sphk return (ENOMEM); 388110603Sphk i = 0; 389110603Sphk /* Collect all identifiers */ 390126786Sjhb LIST_FOREACH(cl, &gmp->lg_class, lg_class) { 391126786Sjhb gmp->lg_ident[i].lg_id = cl->lg_id; 392126786Sjhb gmp->lg_ident[i].lg_ptr = cl; 393126786Sjhb gmp->lg_ident[i].lg_what = ISCLASS; 394110603Sphk i++; 395126786Sjhb LIST_FOREACH(ge, &cl->lg_geom, lg_geom) { 396126786Sjhb gmp->lg_ident[i].lg_id = ge->lg_id; 397126786Sjhb gmp->lg_ident[i].lg_ptr = ge; 398126786Sjhb gmp->lg_ident[i].lg_what = ISGEOM; 399110603Sphk i++; 400126786Sjhb LIST_FOREACH(pr, &ge->lg_provider, lg_provider) { 401126786Sjhb gmp->lg_ident[i].lg_id = pr->lg_id; 402126786Sjhb gmp->lg_ident[i].lg_ptr = pr; 403126786Sjhb gmp->lg_ident[i].lg_what = ISPROVIDER; 404110603Sphk i++; 405110603Sphk } 406126786Sjhb LIST_FOREACH(co, &ge->lg_consumer, lg_consumer) { 407126786Sjhb gmp->lg_ident[i].lg_id = co->lg_id; 408126786Sjhb gmp->lg_ident[i].lg_ptr = co; 409126786Sjhb gmp->lg_ident[i].lg_what = ISCONSUMER; 410110603Sphk i++; 411110603Sphk } 412110603Sphk } 413110603Sphk } 414110603Sphk /* Substitute all identifiers */ 415126786Sjhb LIST_FOREACH(cl, &gmp->lg_class, lg_class) { 416126786Sjhb LIST_FOREACH(ge, &cl->lg_geom, lg_geom) { 417126786Sjhb ge->lg_class = 418126786Sjhb geom_lookupid(gmp, ge->lg_class)->lg_ptr; 419126786Sjhb LIST_FOREACH(pr, &ge->lg_provider, lg_provider) { 420126786Sjhb pr->lg_geom = 421126786Sjhb geom_lookupid(gmp, pr->lg_geom)->lg_ptr; 422110603Sphk } 423126786Sjhb LIST_FOREACH(co, &ge->lg_consumer, lg_consumer) { 424126786Sjhb co->lg_geom = 425126786Sjhb geom_lookupid(gmp, co->lg_geom)->lg_ptr; 426126786Sjhb if (co->lg_provider != NULL) { 427126786Sjhb co->lg_provider = 428126786Sjhb geom_lookupid(gmp, 429126786Sjhb co->lg_provider)->lg_ptr; 430126748Sphk LIST_INSERT_HEAD( 431126786Sjhb &co->lg_provider->lg_consumers, 432126786Sjhb co, lg_consumers); 433126748Sphk } 434110603Sphk } 435110603Sphk } 436110603Sphk } 437110603Sphk return (0); 438110603Sphk} 439110603Sphk 440110603Sphkint 441110603Sphkgeom_gettree(struct gmesh *gmp) 442110603Sphk{ 443110603Sphk char *p; 444110603Sphk int error; 445110603Sphk 446110603Sphk p = geom_getxml(); 447146561Sphk if (p == NULL) 448146561Sphk return (errno); 449110603Sphk error = geom_xml2tree(gmp, p); 450110603Sphk free(p); 451110603Sphk return (error); 452110603Sphk} 453110603Sphk 454110603Sphkstatic void 455110603Sphkdelete_config(struct gconf *gp) 456110603Sphk{ 457110603Sphk struct gconfig *cf; 458110603Sphk 459110603Sphk for (;;) { 460110603Sphk cf = LIST_FIRST(gp); 461110603Sphk if (cf == NULL) 462110603Sphk return; 463126786Sjhb LIST_REMOVE(cf, lg_config); 464126786Sjhb free(cf->lg_name); 465126786Sjhb free(cf->lg_val); 466110603Sphk free(cf); 467110603Sphk } 468110603Sphk} 469110603Sphk 470110603Sphkvoid 471110603Sphkgeom_deletetree(struct gmesh *gmp) 472110603Sphk{ 473110603Sphk struct gclass *cl; 474110603Sphk struct ggeom *ge; 475110603Sphk struct gprovider *pr; 476110603Sphk struct gconsumer *co; 477110603Sphk 478126786Sjhb free(gmp->lg_ident); 479126786Sjhb gmp->lg_ident = NULL; 480110603Sphk for (;;) { 481126786Sjhb cl = LIST_FIRST(&gmp->lg_class); 482110603Sphk if (cl == NULL) 483110603Sphk break; 484126786Sjhb LIST_REMOVE(cl, lg_class); 485126786Sjhb delete_config(&cl->lg_config); 486126786Sjhb if (cl->lg_name) free(cl->lg_name); 487110603Sphk for (;;) { 488126786Sjhb ge = LIST_FIRST(&cl->lg_geom); 489110603Sphk if (ge == NULL) 490110603Sphk break; 491126786Sjhb LIST_REMOVE(ge, lg_geom); 492126786Sjhb delete_config(&ge->lg_config); 493126786Sjhb if (ge->lg_name) free(ge->lg_name); 494110603Sphk for (;;) { 495126786Sjhb pr = LIST_FIRST(&ge->lg_provider); 496110603Sphk if (pr == NULL) 497110603Sphk break; 498126786Sjhb LIST_REMOVE(pr, lg_provider); 499126786Sjhb delete_config(&pr->lg_config); 500126786Sjhb if (pr->lg_name) free(pr->lg_name); 501126786Sjhb if (pr->lg_mode) free(pr->lg_mode); 502110603Sphk free(pr); 503110603Sphk } 504110603Sphk for (;;) { 505126786Sjhb co = LIST_FIRST(&ge->lg_consumer); 506110603Sphk if (co == NULL) 507110603Sphk break; 508126786Sjhb LIST_REMOVE(co, lg_consumer); 509126786Sjhb delete_config(&co->lg_config); 510126786Sjhb if (co->lg_mode) free(co->lg_mode); 511110603Sphk free(co); 512110603Sphk } 513110603Sphk free(ge); 514110603Sphk } 515110603Sphk free(cl); 516110603Sphk } 517110603Sphk} 518