geom_xml2tree.c revision 126786
11558Srgrimes/*- 2187814Srwatson * Copyright (c) 2003 Poul-Henning Kamp 3187814Srwatson * All rights reserved. 4187814Srwatson * 5187814Srwatson * Redistribution and use in source and binary forms, with or without 6187814Srwatson * modification, are permitted provided that the following conditions 7187814Srwatson * are met: 898542Smckusick * 1. Redistributions of source code must retain the above copyright 998542Smckusick * notice, this list of conditions and the following disclaimer. 1098542Smckusick * 2. Redistributions in binary form must reproduce the above copyright 1198542Smckusick * notice, this list of conditions and the following disclaimer in the 1298542Smckusick * documentation and/or other materials provided with the distribution. 1398542Smckusick * 3. The names of the authors may not be used to endorse or promote 1498542Smckusick * products derived from this software without specific prior written 15110884Smckusick * permission. 1698542Smckusick * 171558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 181558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 211558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271558Srgrimes * SUCH DAMAGE. 281558Srgrimes * 291558Srgrimes * $FreeBSD: head/lib/libgeom/geom_xml2tree.c 126786 2004-03-09 21:14:18Z jhb $ 301558Srgrimes */ 311558Srgrimes 321558Srgrimes#include <stdio.h> 331558Srgrimes#include <inttypes.h> 341558Srgrimes#include <stdlib.h> 351558Srgrimes#include <string.h> 361558Srgrimes#include <unistd.h> 371558Srgrimes#include <errno.h> 381558Srgrimes#include <fcntl.h> 391558Srgrimes#include <ctype.h> 401558Srgrimes#include <sys/stat.h> 411558Srgrimes#include <sys/mman.h> 421558Srgrimes#include <sys/queue.h> 431558Srgrimes#include <sys/sbuf.h> 441558Srgrimes#include <sys/sysctl.h> 451558Srgrimes#include <err.h> 4636998Scharnier#include <bsdxml.h> 471558Srgrimes#include <libgeom.h> 481558Srgrimes 491558Srgrimesstruct mystate { 501558Srgrimes struct gmesh *mesh; 511558Srgrimes struct gclass *class; 5236998Scharnier struct ggeom *geom; 5323673Speter struct gprovider *provider; 5436998Scharnier struct gconsumer *consumer; 5536998Scharnier int level; 5650476Speter struct sbuf *sbuf[20]; 571558Srgrimes struct gconf *config; 581558Srgrimes int nident; 591558Srgrimes}; 601558Srgrimes 6196478Sphkstatic void 621558SrgrimesStartElement(void *userData, const char *name, const char **attr) 6398542Smckusick{ 641558Srgrimes struct mystate *mt; 651558Srgrimes void *id; 6623673Speter void *ref; 67105741Sjmallett int i; 681558Srgrimes 691558Srgrimes mt = userData; 7099826Sjmallett mt->level++; 71224025Sdelphij mt->sbuf[mt->level] = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); 72109525Sjmallett id = NULL; 731558Srgrimes ref = NULL; 741558Srgrimes for (i = 0; attr[i] != NULL; i += 2) { 7523673Speter if (!strcmp(attr[i], "id")) { 761558Srgrimes id = (void *)strtoul(attr[i + 1], NULL, 0); 7799826Sjmallett mt->nident++; 78109510Sjmallett } else if (!strcmp(attr[i], "ref")) { 791558Srgrimes ref = (void *)strtoul(attr[i + 1], NULL, 0); 8099826Sjmallett } else 811558Srgrimes printf("%*.*s[%s = %s]\n", 8292839Simp mt->level + 1, mt->level + 1, "", 83224004Sdelphij attr[i], attr[i + 1]); 84109519Sjmallett } 85187814Srwatson if (!strcmp(name, "class") && mt->class == NULL) { 86187814Srwatson mt->class = calloc(1, sizeof *mt->class); 87109525Sjmallett mt->class->lg_id = id; 8892839Simp LIST_INSERT_HEAD(&mt->mesh->lg_class, mt->class, lg_class); 89187814Srwatson LIST_INIT(&mt->class->lg_geom); 90109525Sjmallett LIST_INIT(&mt->class->lg_config); 9192839Simp return; 921558Srgrimes } 931558Srgrimes if (!strcmp(name, "geom") && mt->geom == NULL) { 9492839Simp mt->geom = calloc(1, sizeof *mt->geom); 951558Srgrimes mt->geom->lg_id = id; 96109525Sjmallett LIST_INSERT_HEAD(&mt->class->lg_geom, mt->geom, lg_geom); 97224004Sdelphij LIST_INIT(&mt->geom->lg_provider); 981558Srgrimes LIST_INIT(&mt->geom->lg_consumer); 99224004Sdelphij LIST_INIT(&mt->geom->lg_config); 100109507Sjmallett return; 101224004Sdelphij } 102109525Sjmallett if (!strcmp(name, "class") && mt->geom != NULL) { 103187814Srwatson mt->geom->lg_class = ref; 104187814Srwatson return; 105187814Srwatson } 106109525Sjmallett if (!strcmp(name, "consumer") && mt->consumer == NULL) { 107109525Sjmallett mt->consumer = calloc(1, sizeof *mt->consumer); 108109525Sjmallett mt->consumer->lg_id = id; 109224004Sdelphij LIST_INSERT_HEAD(&mt->geom->lg_consumer, mt->consumer, 110224004Sdelphij lg_consumer); 111224004Sdelphij LIST_INIT(&mt->consumer->lg_config); 112109525Sjmallett return; 113109525Sjmallett } 114109525Sjmallett if (!strcmp(name, "geom") && mt->consumer != NULL) { 115109525Sjmallett mt->consumer->lg_geom = ref; 116109525Sjmallett return; 1171558Srgrimes } 1181558Srgrimes if (!strcmp(name, "provider") && mt->consumer != NULL) { 1191558Srgrimes mt->consumer->lg_provider = ref; 1201558Srgrimes return; 1211558Srgrimes } 122187814Srwatson if (!strcmp(name, "provider") && mt->provider == NULL) { 123187814Srwatson mt->provider = calloc(1, sizeof *mt->provider); 124187814Srwatson mt->provider->lg_id = id; 125187814Srwatson LIST_INSERT_HEAD(&mt->geom->lg_provider, mt->provider, 1261558Srgrimes lg_provider); 127109525Sjmallett LIST_INIT(&mt->provider->lg_consumers); 128109525Sjmallett LIST_INIT(&mt->provider->lg_config); 129109525Sjmallett return; 130109525Sjmallett } 131109525Sjmallett if (!strcmp(name, "geom") && mt->provider != NULL) { 132109525Sjmallett mt->provider->lg_geom = ref; 133187814Srwatson return; 134187814Srwatson } 135187814Srwatson if (!strcmp(name, "config")) { 136109525Sjmallett if (mt->provider != NULL) { 137224004Sdelphij mt->config = &mt->provider->lg_config; 138224004Sdelphij return; 139109525Sjmallett } 140109525Sjmallett if (mt->consumer != NULL) { 141109525Sjmallett mt->config = &mt->consumer->lg_config; 142109525Sjmallett return; 1431558Srgrimes } 1441558Srgrimes if (mt->geom != NULL) { 1451558Srgrimes mt->config = &mt->geom->lg_config; 1461558Srgrimes return; 147224004Sdelphij } 148224004Sdelphij if (mt->class != NULL) { 149224004Sdelphij mt->config = &mt->class->lg_config; 150224025Sdelphij return; 151224004Sdelphij } 152224004Sdelphij } 153224004Sdelphij} 154224004Sdelphij 15592839Simpstatic void 1561558SrgrimesEndElement(void *userData, const char *name) 157109532Sjmallett{ 15898542Smckusick struct mystate *mt; 159109767Snjl struct gconfig *gc; 16099827Sjmallett char *p; 1611558Srgrimes 162101688Sjmallett mt = userData; 163101688Sjmallett sbuf_finish(mt->sbuf[mt->level]); 16498542Smckusick p = strdup(sbuf_data(mt->sbuf[mt->level])); 165109532Sjmallett sbuf_delete(mt->sbuf[mt->level]); 16698542Smckusick mt->sbuf[mt->level] = NULL; 167109532Sjmallett mt->level--; 168122670Sjohan if (strlen(p) == 0) { 169122670Sjohan free(p); 170122670Sjohan p = NULL; 171122670Sjohan } 172101688Sjmallett 173101688Sjmallett if (!strcmp(name, "name")) { 17498542Smckusick if (mt->provider != NULL) { 175109532Sjmallett mt->provider->lg_name = p; 17698542Smckusick return; 177109532Sjmallett } else if (mt->geom != NULL) { 178201647Sgavin mt->geom->lg_name = p; 179122670Sjohan return; 180122670Sjohan } else if (mt->class != NULL) { 181101688Sjmallett mt->class->lg_name = p; 182101688Sjmallett return; 183109532Sjmallett } 18498542Smckusick } 1851558Srgrimes if (!strcmp(name, "rank") && mt->geom != NULL) { 1861558Srgrimes mt->geom->lg_rank = strtoul(p, NULL, 0); 1871558Srgrimes free(p); 1881558Srgrimes return; 1891558Srgrimes } 1901558Srgrimes if (!strcmp(name, "mode") && mt->provider != NULL) { 19198542Smckusick mt->provider->lg_mode = p; 1921558Srgrimes return; 19398542Smckusick } 194101688Sjmallett if (!strcmp(name, "mode") && mt->consumer != NULL) { 195101688Sjmallett mt->consumer->lg_mode = p; 19698542Smckusick return; 19798542Smckusick } 19898542Smckusick if (!strcmp(name, "mediasize") && mt->provider != NULL) { 199122670Sjohan mt->provider->lg_mediasize = strtoumax(p, NULL, 0); 200122670Sjohan free(p); 201122670Sjohan return; 202122670Sjohan } 203122670Sjohan if (!strcmp(name, "sectorsize") && mt->provider != NULL) { 204163844Spjd mt->provider->lg_sectorsize = strtoul(p, NULL, 0); 205163844Spjd free(p); 206163844Spjd return; 207122670Sjohan } 208122670Sjohan 209122670Sjohan if (!strcmp(name, "config")) { 210109532Sjmallett mt->config = NULL; 211109532Sjmallett return; 212109532Sjmallett } 213101688Sjmallett 214101688Sjmallett if (mt->config != NULL) { 21598542Smckusick gc = calloc(sizeof *gc, 1); 21698542Smckusick gc->lg_name = strdup(name); 21798542Smckusick gc->lg_val = p; 21898542Smckusick LIST_INSERT_HEAD(mt->config, gc, lg_config); 21998542Smckusick return; 22098542Smckusick } 22198542Smckusick 22298542Smckusick if (p != NULL) { 223122670Sjohan printf("Unexpected XML: name=%s data=\"%s\"\n", name, p); 22498542Smckusick free(p); 225122670Sjohan } 22698542Smckusick 22798542Smckusick if (!strcmp(name, "consumer") && mt->consumer != NULL) { 22898542Smckusick mt->consumer = NULL; 22998542Smckusick return; 23098542Smckusick } 23198542Smckusick if (!strcmp(name, "provider") && mt->provider != NULL) { 23298542Smckusick mt->provider = NULL; 23398542Smckusick return; 23498542Smckusick } 23598542Smckusick if (!strcmp(name, "geom") && mt->consumer != NULL) { 236101688Sjmallett return; 237101688Sjmallett } 238109532Sjmallett if (!strcmp(name, "geom") && mt->provider != NULL) { 23998542Smckusick return; 2401558Srgrimes } 2411558Srgrimes if (!strcmp(name, "geom") && mt->geom != NULL) { 2422154Sdg mt->geom = NULL; 2432154Sdg return; 244123219Struckman } 245123219Struckman if (!strcmp(name, "class") && mt->geom != NULL) { 24648875Smpp return; 247109767Snjl } 248109767Snjl if (!strcmp(name, "class") && mt->class != NULL) { 249109767Snjl mt->class = NULL; 250109767Snjl return; 251109767Snjl } 25248875Smpp} 253109767Snjl 254109767Snjlstatic void 255109767SnjlCharData(void *userData , const XML_Char *s , int len) 256207141Sjeff{ 257109767Snjl struct mystate *mt; 258109767Snjl const char *b, *e; 259109767Snjl 260109767Snjl mt = userData; 261109767Snjl 262109767Snjl b = s; 263109767Snjl e = s + len - 1; 264109767Snjl while (isspace(*b) && b < e) 265163844Spjd b++; 266163844Spjd while (isspace(*e) && e > b) 267109767Snjl e--; 268109767Snjl if (e != b || (*b && !isspace(*b))) 269200796Strasz sbuf_bcat(mt->sbuf[mt->level], b, e - b + 1); 270200796Strasz} 271216798Skib 272216798Skibstruct gident * 273109767Snjlgeom_lookupid(struct gmesh *gmp, const void *id) 274200796Strasz{ 275216798Skib struct gident *gip; 276109767Snjl 277109767Snjl for (gip = gmp->lg_ident; gip->lg_id != NULL; gip++) 27848875Smpp if (gip->lg_id == id) 279110174Sgordon return (gip); 280122670Sjohan return (NULL); 281122670Sjohan} 2821558Srgrimes 28371073Siedowseint 284101688Sjmallettgeom_xml2tree(struct gmesh *gmp, char *p) 28598542Smckusick{ 2861558Srgrimes XML_Parser parser; 2871558Srgrimes struct mystate *mt; 2881558Srgrimes struct gclass *cl; 2891558Srgrimes struct ggeom *ge; 2901558Srgrimes struct gprovider *pr; 2911558Srgrimes struct gconsumer *co; 2921558Srgrimes int i; 2931558Srgrimes 29498542Smckusick memset(gmp, 0, sizeof *gmp); 295101688Sjmallett LIST_INIT(&gmp->lg_class); 29698542Smckusick parser = XML_ParserCreate(NULL); 29798542Smckusick mt = calloc(1, sizeof *mt); 29898542Smckusick if (mt == NULL) 299109532Sjmallett return (ENOMEM); 300109532Sjmallett mt->mesh = gmp; 3011558Srgrimes XML_SetUserData(parser, mt); 302109519Sjmallett XML_SetElementHandler(parser, StartElement, EndElement); 303109519Sjmallett XML_SetCharacterDataHandler(parser, CharData); 3041558Srgrimes i = XML_Parse(parser, p, strlen(p), 1); 305109519Sjmallett if (i != 1) 3061558Srgrimes return (-1); 3071558Srgrimes XML_ParserFree(parser); 308109525Sjmallett gmp->lg_ident = calloc(sizeof *gmp->lg_ident, mt->nident + 1); 3091558Srgrimes if (gmp->lg_ident == NULL) 31099827Sjmallett return (ENOMEM); 3111558Srgrimes free(mt); 3121558Srgrimes i = 0; 313109519Sjmallett /* Collect all identifiers */ 3141558Srgrimes LIST_FOREACH(cl, &gmp->lg_class, lg_class) { 315109532Sjmallett gmp->lg_ident[i].lg_id = cl->lg_id; 3161558Srgrimes gmp->lg_ident[i].lg_ptr = cl; 3171558Srgrimes gmp->lg_ident[i].lg_what = ISCLASS; 3181558Srgrimes i++; 319109519Sjmallett LIST_FOREACH(ge, &cl->lg_geom, lg_geom) { 320109519Sjmallett gmp->lg_ident[i].lg_id = ge->lg_id; 321101688Sjmallett gmp->lg_ident[i].lg_ptr = ge; 322101688Sjmallett gmp->lg_ident[i].lg_what = ISGEOM; 323109532Sjmallett i++; 324122670Sjohan LIST_FOREACH(pr, &ge->lg_provider, lg_provider) { 325122670Sjohan gmp->lg_ident[i].lg_id = pr->lg_id; 326163844Spjd gmp->lg_ident[i].lg_ptr = pr; 327163844Spjd gmp->lg_ident[i].lg_what = ISPROVIDER; 328163844Spjd i++; 329101688Sjmallett } 330101688Sjmallett LIST_FOREACH(co, &ge->lg_consumer, lg_consumer) { 331109532Sjmallett gmp->lg_ident[i].lg_id = co->lg_id; 332122670Sjohan gmp->lg_ident[i].lg_ptr = co; 333122670Sjohan gmp->lg_ident[i].lg_what = ISCONSUMER; 33498542Smckusick i++; 33598542Smckusick } 33698542Smckusick } 337101688Sjmallett } 338101688Sjmallett /* Substitute all identifiers */ 339101688Sjmallett LIST_FOREACH(cl, &gmp->lg_class, lg_class) { 34098542Smckusick LIST_FOREACH(ge, &cl->lg_geom, lg_geom) { 3411558Srgrimes ge->lg_class = 3421558Srgrimes geom_lookupid(gmp, ge->lg_class)->lg_ptr; 3431558Srgrimes LIST_FOREACH(pr, &ge->lg_provider, lg_provider) { 3441558Srgrimes pr->lg_geom = 3451558Srgrimes geom_lookupid(gmp, pr->lg_geom)->lg_ptr; 3461558Srgrimes } 3471558Srgrimes LIST_FOREACH(co, &ge->lg_consumer, lg_consumer) { 3481558Srgrimes co->lg_geom = 3491558Srgrimes geom_lookupid(gmp, co->lg_geom)->lg_ptr; 3501558Srgrimes if (co->lg_provider != NULL) { 3511558Srgrimes co->lg_provider = 3521558Srgrimes geom_lookupid(gmp, 3531558Srgrimes co->lg_provider)->lg_ptr; 3541558Srgrimes LIST_INSERT_HEAD( 3551558Srgrimes &co->lg_provider->lg_consumers, 3561558Srgrimes co, lg_consumers); 3571558Srgrimes } 3581558Srgrimes } 3591558Srgrimes } 3601558Srgrimes } 3611558Srgrimes return (0); 3621558Srgrimes} 3631558Srgrimes 3641558Srgrimesint 3651558Srgrimesgeom_gettree(struct gmesh *gmp) 36698542Smckusick{ 3671558Srgrimes char *p; 36898542Smckusick int error; 3691558Srgrimes 3701558Srgrimes p = geom_getxml(); 37199827Sjmallett error = geom_xml2tree(gmp, p); 3721558Srgrimes free(p); 373109525Sjmallett return (error); 374187814Srwatson} 375187814Srwatson 376187814Srwatsonstatic void 377187814Srwatsondelete_config(struct gconf *gp) 378187814Srwatson{ 379187814Srwatson struct gconfig *cf; 380187814Srwatson 381187814Srwatson for (;;) { 382187814Srwatson cf = LIST_FIRST(gp); 383187814Srwatson if (cf == NULL) 384187814Srwatson return; 385187814Srwatson LIST_REMOVE(cf, lg_config); 386187814Srwatson free(cf->lg_name); 387187814Srwatson free(cf->lg_val); 388187814Srwatson free(cf); 389187814Srwatson } 390187814Srwatson} 391187814Srwatson 392187814Srwatsonvoid 393187814Srwatsongeom_deletetree(struct gmesh *gmp) 394187814Srwatson{ 395187814Srwatson struct gclass *cl; 396187814Srwatson struct ggeom *ge; 397187814Srwatson struct gprovider *pr; 398109525Sjmallett struct gconsumer *co; 399109525Sjmallett 400109525Sjmallett free(gmp->lg_ident); 401109525Sjmallett gmp->lg_ident = NULL; 402109525Sjmallett for (;;) { 403109525Sjmallett cl = LIST_FIRST(&gmp->lg_class); 404109525Sjmallett if (cl == NULL) 405109525Sjmallett break; 406116083Sjmallett LIST_REMOVE(cl, lg_class); 407116083Sjmallett delete_config(&cl->lg_config); 408109525Sjmallett if (cl->lg_name) free(cl->lg_name); 409109525Sjmallett for (;;) { 410109525Sjmallett ge = LIST_FIRST(&cl->lg_geom); 411109525Sjmallett if (ge == NULL) 412109525Sjmallett break; 413109525Sjmallett LIST_REMOVE(ge, lg_geom); 414109525Sjmallett delete_config(&ge->lg_config); 415109525Sjmallett if (ge->lg_name) free(ge->lg_name); 416109525Sjmallett for (;;) { 417109525Sjmallett pr = LIST_FIRST(&ge->lg_provider); 418109525Sjmallett if (pr == NULL) 419109525Sjmallett break; 420219899Sjmallett LIST_REMOVE(pr, lg_provider); 421219899Sjmallett delete_config(&pr->lg_config); 422219899Sjmallett if (pr->lg_name) free(pr->lg_name); 423109525Sjmallett if (pr->lg_mode) free(pr->lg_mode); 424109525Sjmallett free(pr); 425109525Sjmallett } 426109525Sjmallett for (;;) { 427109525Sjmallett co = LIST_FIRST(&ge->lg_consumer); 428109525Sjmallett if (co == NULL) 429109525Sjmallett break; 430109525Sjmallett LIST_REMOVE(co, lg_consumer); 431109525Sjmallett delete_config(&co->lg_config); 432109525Sjmallett if (co->lg_mode) free(co->lg_mode); 433109525Sjmallett free(co); 434109525Sjmallett } 435109525Sjmallett free(ge); 436109525Sjmallett } 437109525Sjmallett free(cl); 438198231Sru } 439219899Sjmallett} 440219899Sjmallett