geom_xml2tree.c revision 126786
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: head/lib/libgeom/geom_xml2tree.c 126786 2004-03-09 21:14:18Z jhb $ 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; 59110603Sphk}; 60110603Sphk 61110603Sphkstatic void 62110603SphkStartElement(void *userData, const char *name, const char **attr) 63110603Sphk{ 64110603Sphk struct mystate *mt; 65110603Sphk void *id; 66110603Sphk void *ref; 67110603Sphk int i; 68110603Sphk 69110603Sphk mt = userData; 70110603Sphk mt->level++; 71110603Sphk mt->sbuf[mt->level] = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); 72110603Sphk id = NULL; 73126786Sjhb ref = NULL; 74110603Sphk for (i = 0; attr[i] != NULL; i += 2) { 75110603Sphk if (!strcmp(attr[i], "id")) { 76110603Sphk id = (void *)strtoul(attr[i + 1], NULL, 0); 77110603Sphk mt->nident++; 78110603Sphk } else if (!strcmp(attr[i], "ref")) { 79110603Sphk ref = (void *)strtoul(attr[i + 1], NULL, 0); 80110603Sphk } else 81110603Sphk printf("%*.*s[%s = %s]\n", 82110603Sphk mt->level + 1, mt->level + 1, "", 83110603Sphk attr[i], attr[i + 1]); 84110603Sphk } 85110603Sphk if (!strcmp(name, "class") && mt->class == NULL) { 86110603Sphk mt->class = calloc(1, sizeof *mt->class); 87126786Sjhb mt->class->lg_id = id; 88126786Sjhb LIST_INSERT_HEAD(&mt->mesh->lg_class, mt->class, lg_class); 89126786Sjhb LIST_INIT(&mt->class->lg_geom); 90126786Sjhb LIST_INIT(&mt->class->lg_config); 91110603Sphk return; 92110603Sphk } 93110603Sphk if (!strcmp(name, "geom") && mt->geom == NULL) { 94110603Sphk mt->geom = calloc(1, sizeof *mt->geom); 95126786Sjhb mt->geom->lg_id = id; 96126786Sjhb LIST_INSERT_HEAD(&mt->class->lg_geom, mt->geom, lg_geom); 97126786Sjhb LIST_INIT(&mt->geom->lg_provider); 98126786Sjhb LIST_INIT(&mt->geom->lg_consumer); 99126786Sjhb LIST_INIT(&mt->geom->lg_config); 100110603Sphk return; 101110603Sphk } 102110603Sphk if (!strcmp(name, "class") && mt->geom != NULL) { 103126786Sjhb mt->geom->lg_class = ref; 104110603Sphk return; 105110603Sphk } 106110603Sphk if (!strcmp(name, "consumer") && mt->consumer == NULL) { 107110603Sphk mt->consumer = calloc(1, sizeof *mt->consumer); 108126786Sjhb mt->consumer->lg_id = id; 109126786Sjhb LIST_INSERT_HEAD(&mt->geom->lg_consumer, mt->consumer, 110126786Sjhb lg_consumer); 111126786Sjhb LIST_INIT(&mt->consumer->lg_config); 112110603Sphk return; 113110603Sphk } 114110603Sphk if (!strcmp(name, "geom") && mt->consumer != NULL) { 115126786Sjhb mt->consumer->lg_geom = ref; 116110603Sphk return; 117110603Sphk } 118110603Sphk if (!strcmp(name, "provider") && mt->consumer != NULL) { 119126786Sjhb mt->consumer->lg_provider = ref; 120110603Sphk return; 121110603Sphk } 122110603Sphk if (!strcmp(name, "provider") && mt->provider == NULL) { 123110603Sphk mt->provider = calloc(1, sizeof *mt->provider); 124126786Sjhb mt->provider->lg_id = id; 125126786Sjhb LIST_INSERT_HEAD(&mt->geom->lg_provider, mt->provider, 126126786Sjhb lg_provider); 127126786Sjhb LIST_INIT(&mt->provider->lg_consumers); 128126786Sjhb LIST_INIT(&mt->provider->lg_config); 129110603Sphk return; 130110603Sphk } 131110603Sphk if (!strcmp(name, "geom") && mt->provider != NULL) { 132126786Sjhb mt->provider->lg_geom = ref; 133110603Sphk return; 134110603Sphk } 135110603Sphk if (!strcmp(name, "config")) { 136110603Sphk if (mt->provider != NULL) { 137126786Sjhb mt->config = &mt->provider->lg_config; 138110603Sphk return; 139110603Sphk } 140110603Sphk if (mt->consumer != NULL) { 141126786Sjhb mt->config = &mt->consumer->lg_config; 142110603Sphk return; 143110603Sphk } 144110603Sphk if (mt->geom != NULL) { 145126786Sjhb mt->config = &mt->geom->lg_config; 146110603Sphk return; 147110603Sphk } 148110603Sphk if (mt->class != NULL) { 149126786Sjhb mt->config = &mt->class->lg_config; 150110603Sphk return; 151110603Sphk } 152110603Sphk } 153110603Sphk} 154110603Sphk 155110603Sphkstatic void 156110603SphkEndElement(void *userData, const char *name) 157110603Sphk{ 158110603Sphk struct mystate *mt; 159110603Sphk struct gconfig *gc; 160110603Sphk char *p; 161110603Sphk 162110603Sphk mt = userData; 163110603Sphk sbuf_finish(mt->sbuf[mt->level]); 164110603Sphk p = strdup(sbuf_data(mt->sbuf[mt->level])); 165110603Sphk sbuf_delete(mt->sbuf[mt->level]); 166110603Sphk mt->sbuf[mt->level] = NULL; 167110603Sphk mt->level--; 168110603Sphk if (strlen(p) == 0) { 169110603Sphk free(p); 170110603Sphk p = NULL; 171110603Sphk } 172110603Sphk 173110603Sphk if (!strcmp(name, "name")) { 174110603Sphk if (mt->provider != NULL) { 175126786Sjhb mt->provider->lg_name = p; 176110603Sphk return; 177110603Sphk } else if (mt->geom != NULL) { 178126786Sjhb mt->geom->lg_name = p; 179110603Sphk return; 180110603Sphk } else if (mt->class != NULL) { 181126786Sjhb mt->class->lg_name = p; 182110603Sphk return; 183110603Sphk } 184110603Sphk } 185110603Sphk if (!strcmp(name, "rank") && mt->geom != NULL) { 186126786Sjhb mt->geom->lg_rank = strtoul(p, NULL, 0); 187110603Sphk free(p); 188110603Sphk return; 189110603Sphk } 190110603Sphk if (!strcmp(name, "mode") && mt->provider != NULL) { 191126786Sjhb mt->provider->lg_mode = p; 192110603Sphk return; 193110603Sphk } 194110603Sphk if (!strcmp(name, "mode") && mt->consumer != NULL) { 195126786Sjhb mt->consumer->lg_mode = p; 196110603Sphk return; 197110603Sphk } 198110603Sphk if (!strcmp(name, "mediasize") && mt->provider != NULL) { 199126786Sjhb mt->provider->lg_mediasize = strtoumax(p, NULL, 0); 200110603Sphk free(p); 201110603Sphk return; 202110603Sphk } 203110603Sphk if (!strcmp(name, "sectorsize") && mt->provider != NULL) { 204126786Sjhb mt->provider->lg_sectorsize = strtoul(p, NULL, 0); 205110603Sphk free(p); 206110603Sphk return; 207110603Sphk } 208110603Sphk 209110603Sphk if (!strcmp(name, "config")) { 210110603Sphk mt->config = NULL; 211110603Sphk return; 212110603Sphk } 213110603Sphk 214110603Sphk if (mt->config != NULL) { 215110603Sphk gc = calloc(sizeof *gc, 1); 216126786Sjhb gc->lg_name = strdup(name); 217126786Sjhb gc->lg_val = p; 218126786Sjhb LIST_INSERT_HEAD(mt->config, gc, lg_config); 219110603Sphk return; 220110603Sphk } 221110603Sphk 222110603Sphk if (p != NULL) { 223112340Sphk printf("Unexpected XML: name=%s data=\"%s\"\n", name, p); 224110603Sphk free(p); 225110603Sphk } 226110603Sphk 227110603Sphk if (!strcmp(name, "consumer") && mt->consumer != NULL) { 228110603Sphk mt->consumer = NULL; 229110603Sphk return; 230110603Sphk } 231110603Sphk if (!strcmp(name, "provider") && mt->provider != NULL) { 232110603Sphk mt->provider = NULL; 233110603Sphk return; 234110603Sphk } 235110603Sphk if (!strcmp(name, "geom") && mt->consumer != NULL) { 236110603Sphk return; 237110603Sphk } 238110603Sphk if (!strcmp(name, "geom") && mt->provider != NULL) { 239110603Sphk return; 240110603Sphk } 241110603Sphk if (!strcmp(name, "geom") && mt->geom != NULL) { 242110603Sphk mt->geom = NULL; 243110603Sphk return; 244110603Sphk } 245110603Sphk if (!strcmp(name, "class") && mt->geom != NULL) { 246110603Sphk return; 247110603Sphk } 248110603Sphk if (!strcmp(name, "class") && mt->class != NULL) { 249110603Sphk mt->class = NULL; 250110603Sphk return; 251110603Sphk } 252110603Sphk} 253110603Sphk 254110603Sphkstatic void 255110603SphkCharData(void *userData , const XML_Char *s , int len) 256110603Sphk{ 257110603Sphk struct mystate *mt; 258110603Sphk const char *b, *e; 259110603Sphk 260110603Sphk mt = userData; 261110603Sphk 262110603Sphk b = s; 263110603Sphk e = s + len - 1; 264110603Sphk while (isspace(*b) && b < e) 265110603Sphk b++; 266110603Sphk while (isspace(*e) && e > b) 267110603Sphk e--; 268110603Sphk if (e != b || (*b && !isspace(*b))) 269110603Sphk sbuf_bcat(mt->sbuf[mt->level], b, e - b + 1); 270110603Sphk} 271110603Sphk 272110603Sphkstruct gident * 273112340Sphkgeom_lookupid(struct gmesh *gmp, const void *id) 274110603Sphk{ 275110603Sphk struct gident *gip; 276110603Sphk 277126786Sjhb for (gip = gmp->lg_ident; gip->lg_id != NULL; gip++) 278126786Sjhb if (gip->lg_id == id) 279110603Sphk return (gip); 280110603Sphk return (NULL); 281110603Sphk} 282110603Sphk 283110603Sphkint 284110603Sphkgeom_xml2tree(struct gmesh *gmp, char *p) 285110603Sphk{ 286110603Sphk XML_Parser parser; 287110603Sphk struct mystate *mt; 288110603Sphk struct gclass *cl; 289110603Sphk struct ggeom *ge; 290110603Sphk struct gprovider *pr; 291110603Sphk struct gconsumer *co; 292110603Sphk int i; 293110603Sphk 294110603Sphk memset(gmp, 0, sizeof *gmp); 295126786Sjhb LIST_INIT(&gmp->lg_class); 296110603Sphk parser = XML_ParserCreate(NULL); 297110603Sphk mt = calloc(1, sizeof *mt); 298110603Sphk if (mt == NULL) 299110603Sphk return (ENOMEM); 300110603Sphk mt->mesh = gmp; 301110603Sphk XML_SetUserData(parser, mt); 302110603Sphk XML_SetElementHandler(parser, StartElement, EndElement); 303110603Sphk XML_SetCharacterDataHandler(parser, CharData); 304110603Sphk i = XML_Parse(parser, p, strlen(p), 1); 305110603Sphk if (i != 1) 306110603Sphk return (-1); 307110603Sphk XML_ParserFree(parser); 308126786Sjhb gmp->lg_ident = calloc(sizeof *gmp->lg_ident, mt->nident + 1); 309126786Sjhb if (gmp->lg_ident == NULL) 310110603Sphk return (ENOMEM); 311110603Sphk free(mt); 312110603Sphk i = 0; 313110603Sphk /* Collect all identifiers */ 314126786Sjhb LIST_FOREACH(cl, &gmp->lg_class, lg_class) { 315126786Sjhb gmp->lg_ident[i].lg_id = cl->lg_id; 316126786Sjhb gmp->lg_ident[i].lg_ptr = cl; 317126786Sjhb gmp->lg_ident[i].lg_what = ISCLASS; 318110603Sphk i++; 319126786Sjhb LIST_FOREACH(ge, &cl->lg_geom, lg_geom) { 320126786Sjhb gmp->lg_ident[i].lg_id = ge->lg_id; 321126786Sjhb gmp->lg_ident[i].lg_ptr = ge; 322126786Sjhb gmp->lg_ident[i].lg_what = ISGEOM; 323110603Sphk i++; 324126786Sjhb LIST_FOREACH(pr, &ge->lg_provider, lg_provider) { 325126786Sjhb gmp->lg_ident[i].lg_id = pr->lg_id; 326126786Sjhb gmp->lg_ident[i].lg_ptr = pr; 327126786Sjhb gmp->lg_ident[i].lg_what = ISPROVIDER; 328110603Sphk i++; 329110603Sphk } 330126786Sjhb LIST_FOREACH(co, &ge->lg_consumer, lg_consumer) { 331126786Sjhb gmp->lg_ident[i].lg_id = co->lg_id; 332126786Sjhb gmp->lg_ident[i].lg_ptr = co; 333126786Sjhb gmp->lg_ident[i].lg_what = ISCONSUMER; 334110603Sphk i++; 335110603Sphk } 336110603Sphk } 337110603Sphk } 338110603Sphk /* Substitute all identifiers */ 339126786Sjhb LIST_FOREACH(cl, &gmp->lg_class, lg_class) { 340126786Sjhb LIST_FOREACH(ge, &cl->lg_geom, lg_geom) { 341126786Sjhb ge->lg_class = 342126786Sjhb geom_lookupid(gmp, ge->lg_class)->lg_ptr; 343126786Sjhb LIST_FOREACH(pr, &ge->lg_provider, lg_provider) { 344126786Sjhb pr->lg_geom = 345126786Sjhb geom_lookupid(gmp, pr->lg_geom)->lg_ptr; 346110603Sphk } 347126786Sjhb LIST_FOREACH(co, &ge->lg_consumer, lg_consumer) { 348126786Sjhb co->lg_geom = 349126786Sjhb geom_lookupid(gmp, co->lg_geom)->lg_ptr; 350126786Sjhb if (co->lg_provider != NULL) { 351126786Sjhb co->lg_provider = 352126786Sjhb geom_lookupid(gmp, 353126786Sjhb co->lg_provider)->lg_ptr; 354126748Sphk LIST_INSERT_HEAD( 355126786Sjhb &co->lg_provider->lg_consumers, 356126786Sjhb co, lg_consumers); 357126748Sphk } 358110603Sphk } 359110603Sphk } 360110603Sphk } 361110603Sphk return (0); 362110603Sphk} 363110603Sphk 364110603Sphkint 365110603Sphkgeom_gettree(struct gmesh *gmp) 366110603Sphk{ 367110603Sphk char *p; 368110603Sphk int error; 369110603Sphk 370110603Sphk p = geom_getxml(); 371110603Sphk error = geom_xml2tree(gmp, p); 372110603Sphk free(p); 373110603Sphk return (error); 374110603Sphk} 375110603Sphk 376110603Sphkstatic void 377110603Sphkdelete_config(struct gconf *gp) 378110603Sphk{ 379110603Sphk struct gconfig *cf; 380110603Sphk 381110603Sphk for (;;) { 382110603Sphk cf = LIST_FIRST(gp); 383110603Sphk if (cf == NULL) 384110603Sphk return; 385126786Sjhb LIST_REMOVE(cf, lg_config); 386126786Sjhb free(cf->lg_name); 387126786Sjhb free(cf->lg_val); 388110603Sphk free(cf); 389110603Sphk } 390110603Sphk} 391110603Sphk 392110603Sphkvoid 393110603Sphkgeom_deletetree(struct gmesh *gmp) 394110603Sphk{ 395110603Sphk struct gclass *cl; 396110603Sphk struct ggeom *ge; 397110603Sphk struct gprovider *pr; 398110603Sphk struct gconsumer *co; 399110603Sphk 400126786Sjhb free(gmp->lg_ident); 401126786Sjhb gmp->lg_ident = NULL; 402110603Sphk for (;;) { 403126786Sjhb cl = LIST_FIRST(&gmp->lg_class); 404110603Sphk if (cl == NULL) 405110603Sphk break; 406126786Sjhb LIST_REMOVE(cl, lg_class); 407126786Sjhb delete_config(&cl->lg_config); 408126786Sjhb if (cl->lg_name) free(cl->lg_name); 409110603Sphk for (;;) { 410126786Sjhb ge = LIST_FIRST(&cl->lg_geom); 411110603Sphk if (ge == NULL) 412110603Sphk break; 413126786Sjhb LIST_REMOVE(ge, lg_geom); 414126786Sjhb delete_config(&ge->lg_config); 415126786Sjhb if (ge->lg_name) free(ge->lg_name); 416110603Sphk for (;;) { 417126786Sjhb pr = LIST_FIRST(&ge->lg_provider); 418110603Sphk if (pr == NULL) 419110603Sphk break; 420126786Sjhb LIST_REMOVE(pr, lg_provider); 421126786Sjhb delete_config(&pr->lg_config); 422126786Sjhb if (pr->lg_name) free(pr->lg_name); 423126786Sjhb if (pr->lg_mode) free(pr->lg_mode); 424110603Sphk free(pr); 425110603Sphk } 426110603Sphk for (;;) { 427126786Sjhb co = LIST_FIRST(&ge->lg_consumer); 428110603Sphk if (co == NULL) 429110603Sphk break; 430126786Sjhb LIST_REMOVE(co, lg_consumer); 431126786Sjhb delete_config(&co->lg_config); 432126786Sjhb if (co->lg_mode) free(co->lg_mode); 433110603Sphk free(co); 434110603Sphk } 435110603Sphk free(ge); 436110603Sphk } 437110603Sphk free(cl); 438110603Sphk } 439110603Sphk} 440