geom_xml2tree.c revision 181463
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 181463 2008-08-09 11:14:05Z des $ 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++; 71181463Sdes mt->sbuf[mt->level] = sbuf_new_auto(); 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); 87180369Slulf if (mt->class == NULL) { 88180369Slulf warn("Cannot allocate memory during processing of '%s' " 89180369Slulf "element", name); 90180369Slulf return; 91180369Slulf } 92126786Sjhb mt->class->lg_id = id; 93126786Sjhb LIST_INSERT_HEAD(&mt->mesh->lg_class, mt->class, lg_class); 94126786Sjhb LIST_INIT(&mt->class->lg_geom); 95126786Sjhb LIST_INIT(&mt->class->lg_config); 96110603Sphk return; 97110603Sphk } 98110603Sphk if (!strcmp(name, "geom") && mt->geom == NULL) { 99110603Sphk mt->geom = calloc(1, sizeof *mt->geom); 100180369Slulf if (mt->geom == NULL) { 101180369Slulf warn("Cannot allocate memory during processing of '%s' " 102180369Slulf "element", name); 103180369Slulf return; 104180369Slulf } 105126786Sjhb mt->geom->lg_id = id; 106126786Sjhb LIST_INSERT_HEAD(&mt->class->lg_geom, mt->geom, lg_geom); 107126786Sjhb LIST_INIT(&mt->geom->lg_provider); 108126786Sjhb LIST_INIT(&mt->geom->lg_consumer); 109126786Sjhb LIST_INIT(&mt->geom->lg_config); 110110603Sphk return; 111110603Sphk } 112110603Sphk if (!strcmp(name, "class") && mt->geom != NULL) { 113126786Sjhb mt->geom->lg_class = ref; 114110603Sphk return; 115110603Sphk } 116110603Sphk if (!strcmp(name, "consumer") && mt->consumer == NULL) { 117110603Sphk mt->consumer = calloc(1, sizeof *mt->consumer); 118180369Slulf if (mt->consumer == NULL) { 119180369Slulf warn("Cannot allocate memory during processing of '%s' " 120180369Slulf "element", name); 121180369Slulf return; 122180369Slulf } 123126786Sjhb mt->consumer->lg_id = id; 124126786Sjhb LIST_INSERT_HEAD(&mt->geom->lg_consumer, mt->consumer, 125126786Sjhb lg_consumer); 126126786Sjhb LIST_INIT(&mt->consumer->lg_config); 127110603Sphk return; 128110603Sphk } 129110603Sphk if (!strcmp(name, "geom") && mt->consumer != NULL) { 130126786Sjhb mt->consumer->lg_geom = ref; 131110603Sphk return; 132110603Sphk } 133110603Sphk if (!strcmp(name, "provider") && mt->consumer != NULL) { 134126786Sjhb mt->consumer->lg_provider = ref; 135110603Sphk return; 136110603Sphk } 137110603Sphk if (!strcmp(name, "provider") && mt->provider == NULL) { 138110603Sphk mt->provider = calloc(1, sizeof *mt->provider); 139180369Slulf if (mt->provider == NULL) { 140180369Slulf warn("Cannot allocate memory during processing of '%s' " 141180369Slulf "element", name); 142180369Slulf return; 143180369Slulf } 144126786Sjhb mt->provider->lg_id = id; 145126786Sjhb LIST_INSERT_HEAD(&mt->geom->lg_provider, mt->provider, 146126786Sjhb lg_provider); 147126786Sjhb LIST_INIT(&mt->provider->lg_consumers); 148126786Sjhb LIST_INIT(&mt->provider->lg_config); 149110603Sphk return; 150110603Sphk } 151110603Sphk if (!strcmp(name, "geom") && mt->provider != NULL) { 152126786Sjhb mt->provider->lg_geom = ref; 153110603Sphk return; 154110603Sphk } 155110603Sphk if (!strcmp(name, "config")) { 156110603Sphk if (mt->provider != NULL) { 157126786Sjhb mt->config = &mt->provider->lg_config; 158110603Sphk return; 159110603Sphk } 160110603Sphk if (mt->consumer != NULL) { 161126786Sjhb mt->config = &mt->consumer->lg_config; 162110603Sphk return; 163110603Sphk } 164110603Sphk if (mt->geom != NULL) { 165126786Sjhb mt->config = &mt->geom->lg_config; 166110603Sphk return; 167110603Sphk } 168110603Sphk if (mt->class != NULL) { 169126786Sjhb mt->config = &mt->class->lg_config; 170110603Sphk return; 171110603Sphk } 172110603Sphk } 173110603Sphk} 174110603Sphk 175110603Sphkstatic void 176110603SphkEndElement(void *userData, const char *name) 177110603Sphk{ 178110603Sphk struct mystate *mt; 179110603Sphk struct gconfig *gc; 180110603Sphk char *p; 181110603Sphk 182110603Sphk mt = userData; 183110603Sphk sbuf_finish(mt->sbuf[mt->level]); 184110603Sphk p = strdup(sbuf_data(mt->sbuf[mt->level])); 185180369Slulf if (p == NULL) { 186180369Slulf warn("Cannot allocate memory during processing of '%s' " 187180369Slulf "element", name); 188180369Slulf return; 189180369Slulf } 190110603Sphk sbuf_delete(mt->sbuf[mt->level]); 191110603Sphk mt->sbuf[mt->level] = NULL; 192110603Sphk mt->level--; 193110603Sphk if (strlen(p) == 0) { 194110603Sphk free(p); 195110603Sphk p = NULL; 196110603Sphk } 197110603Sphk 198110603Sphk if (!strcmp(name, "name")) { 199110603Sphk if (mt->provider != NULL) { 200126786Sjhb mt->provider->lg_name = p; 201110603Sphk return; 202110603Sphk } else if (mt->geom != NULL) { 203126786Sjhb mt->geom->lg_name = p; 204110603Sphk return; 205110603Sphk } else if (mt->class != NULL) { 206126786Sjhb mt->class->lg_name = p; 207110603Sphk return; 208110603Sphk } 209110603Sphk } 210110603Sphk if (!strcmp(name, "rank") && mt->geom != NULL) { 211126786Sjhb mt->geom->lg_rank = strtoul(p, NULL, 0); 212110603Sphk free(p); 213110603Sphk return; 214110603Sphk } 215110603Sphk if (!strcmp(name, "mode") && mt->provider != NULL) { 216126786Sjhb mt->provider->lg_mode = p; 217110603Sphk return; 218110603Sphk } 219110603Sphk if (!strcmp(name, "mode") && mt->consumer != NULL) { 220126786Sjhb mt->consumer->lg_mode = p; 221110603Sphk return; 222110603Sphk } 223110603Sphk if (!strcmp(name, "mediasize") && mt->provider != NULL) { 224126786Sjhb mt->provider->lg_mediasize = strtoumax(p, NULL, 0); 225110603Sphk free(p); 226110603Sphk return; 227110603Sphk } 228110603Sphk if (!strcmp(name, "sectorsize") && mt->provider != NULL) { 229126786Sjhb mt->provider->lg_sectorsize = strtoul(p, NULL, 0); 230110603Sphk free(p); 231110603Sphk return; 232110603Sphk } 233110603Sphk 234110603Sphk if (!strcmp(name, "config")) { 235110603Sphk mt->config = NULL; 236110603Sphk return; 237110603Sphk } 238110603Sphk 239110603Sphk if (mt->config != NULL) { 240180369Slulf gc = calloc(1, sizeof *gc); 241180369Slulf if (gc == NULL) { 242180369Slulf warn("Cannot allocate memory during processing of '%s' " 243180369Slulf "element", name); 244180369Slulf return; 245180369Slulf } 246126786Sjhb gc->lg_name = strdup(name); 247180369Slulf if (gc->lg_name == NULL) { 248180369Slulf warn("Cannot allocate memory during processing of '%s' " 249180369Slulf "element", name); 250180369Slulf return; 251180369Slulf } 252126786Sjhb gc->lg_val = p; 253126786Sjhb LIST_INSERT_HEAD(mt->config, gc, lg_config); 254110603Sphk return; 255110603Sphk } 256110603Sphk 257110603Sphk if (p != NULL) { 258112340Sphk printf("Unexpected XML: name=%s data=\"%s\"\n", name, p); 259110603Sphk free(p); 260110603Sphk } 261110603Sphk 262110603Sphk if (!strcmp(name, "consumer") && mt->consumer != NULL) { 263110603Sphk mt->consumer = NULL; 264110603Sphk return; 265110603Sphk } 266110603Sphk if (!strcmp(name, "provider") && mt->provider != NULL) { 267110603Sphk mt->provider = NULL; 268110603Sphk return; 269110603Sphk } 270110603Sphk if (!strcmp(name, "geom") && mt->consumer != NULL) { 271110603Sphk return; 272110603Sphk } 273110603Sphk if (!strcmp(name, "geom") && mt->provider != NULL) { 274110603Sphk return; 275110603Sphk } 276110603Sphk if (!strcmp(name, "geom") && mt->geom != NULL) { 277110603Sphk mt->geom = NULL; 278110603Sphk return; 279110603Sphk } 280110603Sphk if (!strcmp(name, "class") && mt->geom != NULL) { 281110603Sphk return; 282110603Sphk } 283110603Sphk if (!strcmp(name, "class") && mt->class != NULL) { 284110603Sphk mt->class = NULL; 285110603Sphk return; 286110603Sphk } 287110603Sphk} 288110603Sphk 289110603Sphkstatic void 290110603SphkCharData(void *userData , const XML_Char *s , int len) 291110603Sphk{ 292110603Sphk struct mystate *mt; 293110603Sphk const char *b, *e; 294110603Sphk 295110603Sphk mt = userData; 296110603Sphk 297110603Sphk b = s; 298110603Sphk e = s + len - 1; 299110603Sphk while (isspace(*b) && b < e) 300110603Sphk b++; 301110603Sphk while (isspace(*e) && e > b) 302110603Sphk e--; 303110603Sphk if (e != b || (*b && !isspace(*b))) 304110603Sphk sbuf_bcat(mt->sbuf[mt->level], b, e - b + 1); 305110603Sphk} 306110603Sphk 307110603Sphkstruct gident * 308112340Sphkgeom_lookupid(struct gmesh *gmp, const void *id) 309110603Sphk{ 310110603Sphk struct gident *gip; 311110603Sphk 312126786Sjhb for (gip = gmp->lg_ident; gip->lg_id != NULL; gip++) 313126786Sjhb if (gip->lg_id == id) 314110603Sphk return (gip); 315110603Sphk return (NULL); 316110603Sphk} 317110603Sphk 318110603Sphkint 319110603Sphkgeom_xml2tree(struct gmesh *gmp, char *p) 320110603Sphk{ 321110603Sphk XML_Parser parser; 322110603Sphk struct mystate *mt; 323110603Sphk struct gclass *cl; 324110603Sphk struct ggeom *ge; 325110603Sphk struct gprovider *pr; 326110603Sphk struct gconsumer *co; 327110603Sphk int i; 328110603Sphk 329110603Sphk memset(gmp, 0, sizeof *gmp); 330126786Sjhb LIST_INIT(&gmp->lg_class); 331110603Sphk parser = XML_ParserCreate(NULL); 332110603Sphk mt = calloc(1, sizeof *mt); 333110603Sphk if (mt == NULL) 334110603Sphk return (ENOMEM); 335110603Sphk mt->mesh = gmp; 336110603Sphk XML_SetUserData(parser, mt); 337110603Sphk XML_SetElementHandler(parser, StartElement, EndElement); 338110603Sphk XML_SetCharacterDataHandler(parser, CharData); 339110603Sphk i = XML_Parse(parser, p, strlen(p), 1); 340110603Sphk if (i != 1) 341110603Sphk return (-1); 342110603Sphk XML_ParserFree(parser); 343126786Sjhb gmp->lg_ident = calloc(sizeof *gmp->lg_ident, mt->nident + 1); 344126786Sjhb if (gmp->lg_ident == NULL) 345110603Sphk return (ENOMEM); 346110603Sphk free(mt); 347110603Sphk i = 0; 348110603Sphk /* Collect all identifiers */ 349126786Sjhb LIST_FOREACH(cl, &gmp->lg_class, lg_class) { 350126786Sjhb gmp->lg_ident[i].lg_id = cl->lg_id; 351126786Sjhb gmp->lg_ident[i].lg_ptr = cl; 352126786Sjhb gmp->lg_ident[i].lg_what = ISCLASS; 353110603Sphk i++; 354126786Sjhb LIST_FOREACH(ge, &cl->lg_geom, lg_geom) { 355126786Sjhb gmp->lg_ident[i].lg_id = ge->lg_id; 356126786Sjhb gmp->lg_ident[i].lg_ptr = ge; 357126786Sjhb gmp->lg_ident[i].lg_what = ISGEOM; 358110603Sphk i++; 359126786Sjhb LIST_FOREACH(pr, &ge->lg_provider, lg_provider) { 360126786Sjhb gmp->lg_ident[i].lg_id = pr->lg_id; 361126786Sjhb gmp->lg_ident[i].lg_ptr = pr; 362126786Sjhb gmp->lg_ident[i].lg_what = ISPROVIDER; 363110603Sphk i++; 364110603Sphk } 365126786Sjhb LIST_FOREACH(co, &ge->lg_consumer, lg_consumer) { 366126786Sjhb gmp->lg_ident[i].lg_id = co->lg_id; 367126786Sjhb gmp->lg_ident[i].lg_ptr = co; 368126786Sjhb gmp->lg_ident[i].lg_what = ISCONSUMER; 369110603Sphk i++; 370110603Sphk } 371110603Sphk } 372110603Sphk } 373110603Sphk /* Substitute all identifiers */ 374126786Sjhb LIST_FOREACH(cl, &gmp->lg_class, lg_class) { 375126786Sjhb LIST_FOREACH(ge, &cl->lg_geom, lg_geom) { 376126786Sjhb ge->lg_class = 377126786Sjhb geom_lookupid(gmp, ge->lg_class)->lg_ptr; 378126786Sjhb LIST_FOREACH(pr, &ge->lg_provider, lg_provider) { 379126786Sjhb pr->lg_geom = 380126786Sjhb geom_lookupid(gmp, pr->lg_geom)->lg_ptr; 381110603Sphk } 382126786Sjhb LIST_FOREACH(co, &ge->lg_consumer, lg_consumer) { 383126786Sjhb co->lg_geom = 384126786Sjhb geom_lookupid(gmp, co->lg_geom)->lg_ptr; 385126786Sjhb if (co->lg_provider != NULL) { 386126786Sjhb co->lg_provider = 387126786Sjhb geom_lookupid(gmp, 388126786Sjhb co->lg_provider)->lg_ptr; 389126748Sphk LIST_INSERT_HEAD( 390126786Sjhb &co->lg_provider->lg_consumers, 391126786Sjhb co, lg_consumers); 392126748Sphk } 393110603Sphk } 394110603Sphk } 395110603Sphk } 396110603Sphk return (0); 397110603Sphk} 398110603Sphk 399110603Sphkint 400110603Sphkgeom_gettree(struct gmesh *gmp) 401110603Sphk{ 402110603Sphk char *p; 403110603Sphk int error; 404110603Sphk 405110603Sphk p = geom_getxml(); 406146561Sphk if (p == NULL) 407146561Sphk return (errno); 408110603Sphk error = geom_xml2tree(gmp, p); 409110603Sphk free(p); 410110603Sphk return (error); 411110603Sphk} 412110603Sphk 413110603Sphkstatic void 414110603Sphkdelete_config(struct gconf *gp) 415110603Sphk{ 416110603Sphk struct gconfig *cf; 417110603Sphk 418110603Sphk for (;;) { 419110603Sphk cf = LIST_FIRST(gp); 420110603Sphk if (cf == NULL) 421110603Sphk return; 422126786Sjhb LIST_REMOVE(cf, lg_config); 423126786Sjhb free(cf->lg_name); 424126786Sjhb free(cf->lg_val); 425110603Sphk free(cf); 426110603Sphk } 427110603Sphk} 428110603Sphk 429110603Sphkvoid 430110603Sphkgeom_deletetree(struct gmesh *gmp) 431110603Sphk{ 432110603Sphk struct gclass *cl; 433110603Sphk struct ggeom *ge; 434110603Sphk struct gprovider *pr; 435110603Sphk struct gconsumer *co; 436110603Sphk 437126786Sjhb free(gmp->lg_ident); 438126786Sjhb gmp->lg_ident = NULL; 439110603Sphk for (;;) { 440126786Sjhb cl = LIST_FIRST(&gmp->lg_class); 441110603Sphk if (cl == NULL) 442110603Sphk break; 443126786Sjhb LIST_REMOVE(cl, lg_class); 444126786Sjhb delete_config(&cl->lg_config); 445126786Sjhb if (cl->lg_name) free(cl->lg_name); 446110603Sphk for (;;) { 447126786Sjhb ge = LIST_FIRST(&cl->lg_geom); 448110603Sphk if (ge == NULL) 449110603Sphk break; 450126786Sjhb LIST_REMOVE(ge, lg_geom); 451126786Sjhb delete_config(&ge->lg_config); 452126786Sjhb if (ge->lg_name) free(ge->lg_name); 453110603Sphk for (;;) { 454126786Sjhb pr = LIST_FIRST(&ge->lg_provider); 455110603Sphk if (pr == NULL) 456110603Sphk break; 457126786Sjhb LIST_REMOVE(pr, lg_provider); 458126786Sjhb delete_config(&pr->lg_config); 459126786Sjhb if (pr->lg_name) free(pr->lg_name); 460126786Sjhb if (pr->lg_mode) free(pr->lg_mode); 461110603Sphk free(pr); 462110603Sphk } 463110603Sphk for (;;) { 464126786Sjhb co = LIST_FIRST(&ge->lg_consumer); 465110603Sphk if (co == NULL) 466110603Sphk break; 467126786Sjhb LIST_REMOVE(co, lg_consumer); 468126786Sjhb delete_config(&co->lg_config); 469126786Sjhb if (co->lg_mode) free(co->lg_mode); 470110603Sphk free(co); 471110603Sphk } 472110603Sphk free(ge); 473110603Sphk } 474110603Sphk free(cl); 475110603Sphk } 476110603Sphk} 477