geom_xml2tree.c revision 281303
1214478Srpaulo/*- 2190203Srpaulo * Copyright (c) 2003 Poul-Henning Kamp 3190203Srpaulo * All rights reserved. 4190203Srpaulo * 5190203Srpaulo * Redistribution and use in source and binary forms, with or without 6190203Srpaulo * modification, are permitted provided that the following conditions 7190203Srpaulo * are met: 8190203Srpaulo * 1. Redistributions of source code must retain the above copyright 9190203Srpaulo * notice, this list of conditions and the following disclaimer. 10190203Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 11190203Srpaulo * notice, this list of conditions and the following disclaimer in the 12190203Srpaulo * documentation and/or other materials provided with the distribution. 13190203Srpaulo * 3. The names of the authors may not be used to endorse or promote 14190203Srpaulo * products derived from this software without specific prior written 15190203Srpaulo * permission. 16190203Srpaulo * 17190203Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18190203Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19190203Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20190203Srpaulo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21190203Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22190203Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23190203Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24190203Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25190203Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26190203Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27190203Srpaulo * SUCH DAMAGE. 28190203Srpaulo * 29190203Srpaulo * $FreeBSD: stable/10/lib/libgeom/geom_xml2tree.c 281303 2015-04-09 10:10:05Z mav $ 30190203Srpaulo */ 31190203Srpaulo 32190203Srpaulo#include <stdio.h> 33190203Srpaulo#include <inttypes.h> 34190203Srpaulo#include <stdlib.h> 35190203Srpaulo#include <string.h> 36190203Srpaulo#include <unistd.h> 37190203Srpaulo#include <errno.h> 38190203Srpaulo#include <fcntl.h> 39190203Srpaulo#include <ctype.h> 40190203Srpaulo#include <sys/stat.h> 41190203Srpaulo#include <sys/mman.h> 42190203Srpaulo#include <sys/queue.h> 43190203Srpaulo#include <sys/sbuf.h> 44190203Srpaulo#include <sys/sysctl.h> 45190203Srpaulo#include <err.h> 46190203Srpaulo#include <bsdxml.h> 47190203Srpaulo#include <libgeom.h> 48190203Srpaulo 49190203Srpaulostruct mystate { 50190203Srpaulo struct gmesh *mesh; 51190203Srpaulo struct gclass *class; 52190203Srpaulo struct ggeom *geom; 53190203Srpaulo struct gprovider *provider; 54190203Srpaulo struct gconsumer *consumer; 55190203Srpaulo int level; 56190203Srpaulo struct sbuf *sbuf[20]; 57190203Srpaulo struct gconf *config; 58190203Srpaulo int nident; 59190203Srpaulo XML_Parser parser; 60190203Srpaulo int error; 61190203Srpaulo}; 62190203Srpaulo 63190203Srpaulostatic void 64190203SrpauloStartElement(void *userData, const char *name, const char **attr) 65190203Srpaulo{ 66190203Srpaulo struct mystate *mt; 67190203Srpaulo void *id; 68190203Srpaulo void *ref; 69190203Srpaulo int i; 70190203Srpaulo 71190203Srpaulo mt = userData; 72190203Srpaulo mt->level++; 73190203Srpaulo mt->sbuf[mt->level] = sbuf_new_auto(); 74190203Srpaulo id = NULL; 75190203Srpaulo ref = NULL; 76190203Srpaulo for (i = 0; attr[i] != NULL; i += 2) { 77190203Srpaulo if (!strcmp(attr[i], "id")) { 78190203Srpaulo id = (void *)strtoul(attr[i + 1], NULL, 0); 79190203Srpaulo mt->nident++; 80190203Srpaulo } else if (!strcmp(attr[i], "ref")) { 81190203Srpaulo ref = (void *)strtoul(attr[i + 1], NULL, 0); 82190203Srpaulo } else 83190203Srpaulo printf("%*.*s[%s = %s]\n", 84190203Srpaulo mt->level + 1, mt->level + 1, "", 85190203Srpaulo attr[i], attr[i + 1]); 86190203Srpaulo } 87190203Srpaulo if (!strcmp(name, "class") && mt->class == NULL) { 88190203Srpaulo mt->class = calloc(1, sizeof *mt->class); 89190203Srpaulo if (mt->class == NULL) { 90190203Srpaulo mt->error = errno; 91190203Srpaulo XML_StopParser(mt->parser, 0); 92190203Srpaulo warn("Cannot allocate memory during processing of '%s' " 93190203Srpaulo "element", name); 94190203Srpaulo return; 95190203Srpaulo } 96190203Srpaulo mt->class->lg_id = id; 97190203Srpaulo LIST_INSERT_HEAD(&mt->mesh->lg_class, mt->class, lg_class); 98190203Srpaulo LIST_INIT(&mt->class->lg_geom); 99190203Srpaulo LIST_INIT(&mt->class->lg_config); 100190203Srpaulo return; 101190203Srpaulo } 102190203Srpaulo if (!strcmp(name, "geom") && mt->geom == NULL) { 103190203Srpaulo mt->geom = calloc(1, sizeof *mt->geom); 104190203Srpaulo if (mt->geom == NULL) { 105190203Srpaulo mt->error = errno; 106190203Srpaulo XML_StopParser(mt->parser, 0); 107190203Srpaulo warn("Cannot allocate memory during processing of '%s' " 108190203Srpaulo "element", name); 109190203Srpaulo return; 110190203Srpaulo } 111190203Srpaulo mt->geom->lg_id = id; 112190203Srpaulo LIST_INSERT_HEAD(&mt->class->lg_geom, mt->geom, lg_geom); 113190203Srpaulo LIST_INIT(&mt->geom->lg_provider); 114190203Srpaulo LIST_INIT(&mt->geom->lg_consumer); 115190203Srpaulo LIST_INIT(&mt->geom->lg_config); 116190203Srpaulo return; 117190203Srpaulo } 118190203Srpaulo if (!strcmp(name, "class") && mt->geom != NULL) { 119190203Srpaulo mt->geom->lg_class = ref; 120190203Srpaulo return; 121190203Srpaulo } 122190203Srpaulo if (!strcmp(name, "consumer") && mt->consumer == NULL) { 123190203Srpaulo mt->consumer = calloc(1, sizeof *mt->consumer); 124190203Srpaulo if (mt->consumer == NULL) { 125190203Srpaulo mt->error = errno; 126190203Srpaulo XML_StopParser(mt->parser, 0); 127190203Srpaulo warn("Cannot allocate memory during processing of '%s' " 128190203Srpaulo "element", name); 129190203Srpaulo return; 130190203Srpaulo } 131190203Srpaulo mt->consumer->lg_id = id; 132190203Srpaulo LIST_INSERT_HEAD(&mt->geom->lg_consumer, mt->consumer, 133190203Srpaulo lg_consumer); 134190203Srpaulo LIST_INIT(&mt->consumer->lg_config); 135190203Srpaulo return; 136190203Srpaulo } 137190203Srpaulo if (!strcmp(name, "geom") && mt->consumer != NULL) { 138190203Srpaulo mt->consumer->lg_geom = ref; 139190203Srpaulo return; 140190203Srpaulo } 141190203Srpaulo if (!strcmp(name, "provider") && mt->consumer != NULL) { 142190203Srpaulo mt->consumer->lg_provider = ref; 143190203Srpaulo return; 144190203Srpaulo } 145190203Srpaulo if (!strcmp(name, "provider") && mt->provider == NULL) { 146190203Srpaulo mt->provider = calloc(1, sizeof *mt->provider); 147190203Srpaulo if (mt->provider == NULL) { 148190203Srpaulo mt->error = errno; 149190203Srpaulo XML_StopParser(mt->parser, 0); 150190203Srpaulo warn("Cannot allocate memory during processing of '%s' " 151190203Srpaulo "element", name); 152190203Srpaulo return; 153190203Srpaulo } 154190203Srpaulo mt->provider->lg_id = id; 155190203Srpaulo LIST_INSERT_HEAD(&mt->geom->lg_provider, mt->provider, 156190203Srpaulo lg_provider); 157190203Srpaulo LIST_INIT(&mt->provider->lg_consumers); 158190203Srpaulo LIST_INIT(&mt->provider->lg_config); 159190203Srpaulo return; 160190203Srpaulo } 161190203Srpaulo if (!strcmp(name, "geom") && mt->provider != NULL) { 162190203Srpaulo mt->provider->lg_geom = ref; 163190203Srpaulo return; 164190203Srpaulo } 165190203Srpaulo if (!strcmp(name, "config")) { 166190203Srpaulo if (mt->provider != NULL) { 167190203Srpaulo mt->config = &mt->provider->lg_config; 168190203Srpaulo return; 169190203Srpaulo } 170190203Srpaulo if (mt->consumer != NULL) { 171190203Srpaulo mt->config = &mt->consumer->lg_config; 172190203Srpaulo return; 173190203Srpaulo } 174190203Srpaulo if (mt->geom != NULL) { 175190203Srpaulo mt->config = &mt->geom->lg_config; 176190203Srpaulo return; 177190203Srpaulo } 178190203Srpaulo if (mt->class != NULL) { 179190203Srpaulo mt->config = &mt->class->lg_config; 180190203Srpaulo return; 181190203Srpaulo } 182190203Srpaulo } 183190203Srpaulo} 184190203Srpaulo 185190203Srpaulostatic void 186190203SrpauloEndElement(void *userData, const char *name) 187190203Srpaulo{ 188190203Srpaulo struct mystate *mt; 189190203Srpaulo struct gconf *c; 190190203Srpaulo struct gconfig *gc; 191190203Srpaulo char *p; 192190203Srpaulo 193190203Srpaulo mt = userData; 194190203Srpaulo p = NULL; 195190203Srpaulo if (sbuf_finish(mt->sbuf[mt->level]) == 0) 196190203Srpaulo p = strdup(sbuf_data(mt->sbuf[mt->level])); 197190203Srpaulo sbuf_delete(mt->sbuf[mt->level]); 198190203Srpaulo mt->sbuf[mt->level] = NULL; 199190203Srpaulo mt->level--; 200190203Srpaulo if (p == NULL) { 201190203Srpaulo mt->error = errno; 202190203Srpaulo XML_StopParser(mt->parser, 0); 203190203Srpaulo warn("Cannot allocate memory during processing of '%s' " 204190203Srpaulo "element", name); 205190203Srpaulo return; 206190203Srpaulo } 207190203Srpaulo if (strlen(p) == 0) { 208190203Srpaulo free(p); 209190203Srpaulo p = NULL; 210190203Srpaulo } 211190203Srpaulo 212190203Srpaulo if (!strcmp(name, "name")) { 213190203Srpaulo if (mt->provider != NULL) { 214190203Srpaulo mt->provider->lg_name = p; 215190203Srpaulo return; 216190203Srpaulo } else if (mt->geom != NULL) { 217190203Srpaulo mt->geom->lg_name = p; 218190203Srpaulo return; 219190203Srpaulo } else if (mt->class != NULL) { 220190203Srpaulo mt->class->lg_name = p; 221190203Srpaulo return; 222190203Srpaulo } 223190203Srpaulo } 224214478Srpaulo if (!strcmp(name, "rank") && mt->geom != NULL) { 225190203Srpaulo mt->geom->lg_rank = strtoul(p, NULL, 0); 226190203Srpaulo free(p); 227190203Srpaulo return; 228190203Srpaulo } 229190203Srpaulo if (!strcmp(name, "mode") && mt->provider != NULL) { 230190203Srpaulo mt->provider->lg_mode = p; 231190203Srpaulo return; 232190203Srpaulo } 233190203Srpaulo if (!strcmp(name, "mode") && mt->consumer != NULL) { 234190203Srpaulo mt->consumer->lg_mode = p; 235190203Srpaulo return; 236190203Srpaulo } 237190203Srpaulo if (!strcmp(name, "mediasize") && mt->provider != NULL) { 238190203Srpaulo mt->provider->lg_mediasize = strtoumax(p, NULL, 0); 239190203Srpaulo free(p); 240190203Srpaulo return; 241190203Srpaulo } 242190203Srpaulo if (!strcmp(name, "sectorsize") && mt->provider != NULL) { 243190203Srpaulo mt->provider->lg_sectorsize = strtoul(p, NULL, 0); 244190203Srpaulo free(p); 245190203Srpaulo return; 246190203Srpaulo } 247190203Srpaulo if (!strcmp(name, "stripesize") && mt->provider != NULL) { 248190203Srpaulo mt->provider->lg_stripesize = strtoumax(p, NULL, 0); 249190203Srpaulo free(p); 250190203Srpaulo return; 251190203Srpaulo } 252190203Srpaulo if (!strcmp(name, "stripeoffset") && mt->provider != NULL) { 253190203Srpaulo mt->provider->lg_stripeoffset = strtoumax(p, NULL, 0); 254190203Srpaulo free(p); 255190203Srpaulo return; 256 } 257 258 if (!strcmp(name, "config")) { 259 mt->config = NULL; 260 return; 261 } 262 263 if (mt->config != NULL || (!strcmp(name, "wither") && 264 (mt->provider != NULL || mt->geom != NULL))) { 265 if (mt->config != NULL) 266 c = mt->config; 267 else if (mt->provider != NULL) 268 c = &mt->provider->lg_config; 269 else 270 c = &mt->geom->lg_config; 271 gc = calloc(1, sizeof *gc); 272 if (gc == NULL) { 273 mt->error = errno; 274 XML_StopParser(mt->parser, 0); 275 warn("Cannot allocate memory during processing of '%s' " 276 "element", name); 277 return; 278 } 279 gc->lg_name = strdup(name); 280 if (gc->lg_name == NULL) { 281 free(gc); 282 mt->error = errno; 283 XML_StopParser(mt->parser, 0); 284 warn("Cannot allocate memory during processing of '%s' " 285 "element", name); 286 return; 287 } 288 gc->lg_val = p ? p : strdup("1"); 289 LIST_INSERT_HEAD(c, gc, lg_config); 290 return; 291 } 292 293 if (p != NULL) { 294#if DEBUG_LIBGEOM > 0 295 printf("Unexpected XML: name=%s data=\"%s\"\n", name, p); 296#endif 297 free(p); 298 } 299 300 if (!strcmp(name, "consumer") && mt->consumer != NULL) { 301 mt->consumer = NULL; 302 return; 303 } 304 if (!strcmp(name, "provider") && mt->provider != NULL) { 305 mt->provider = NULL; 306 return; 307 } 308 if (!strcmp(name, "geom") && mt->consumer != NULL) { 309 return; 310 } 311 if (!strcmp(name, "geom") && mt->provider != NULL) { 312 return; 313 } 314 if (!strcmp(name, "geom") && mt->geom != NULL) { 315 mt->geom = NULL; 316 return; 317 } 318 if (!strcmp(name, "class") && mt->geom != NULL) { 319 return; 320 } 321 if (!strcmp(name, "class") && mt->class != NULL) { 322 mt->class = NULL; 323 return; 324 } 325} 326 327static void 328CharData(void *userData , const XML_Char *s , int len) 329{ 330 struct mystate *mt; 331 const char *b, *e; 332 333 mt = userData; 334 335 b = s; 336 e = s + len - 1; 337 while (isspace(*b) && b < e) 338 b++; 339 while (isspace(*e) && e > b) 340 e--; 341 if (e != b || (*b && !isspace(*b))) 342 sbuf_bcat(mt->sbuf[mt->level], b, e - b + 1); 343} 344 345struct gident * 346geom_lookupid(struct gmesh *gmp, const void *id) 347{ 348 struct gident *gip; 349 350 for (gip = gmp->lg_ident; gip->lg_id != NULL; gip++) 351 if (gip->lg_id == id) 352 return (gip); 353 return (NULL); 354} 355 356int 357geom_xml2tree(struct gmesh *gmp, char *p) 358{ 359 XML_Parser parser; 360 struct mystate *mt; 361 struct gclass *cl; 362 struct ggeom *ge; 363 struct gprovider *pr; 364 struct gconsumer *co; 365 int error, i; 366 367 memset(gmp, 0, sizeof *gmp); 368 LIST_INIT(&gmp->lg_class); 369 parser = XML_ParserCreate(NULL); 370 if (parser == NULL) 371 return (ENOMEM); 372 mt = calloc(1, sizeof *mt); 373 if (mt == NULL) { 374 XML_ParserFree(parser); 375 return (ENOMEM); 376 } 377 mt->mesh = gmp; 378 mt->parser = parser; 379 error = 0; 380 XML_SetUserData(parser, mt); 381 XML_SetElementHandler(parser, StartElement, EndElement); 382 XML_SetCharacterDataHandler(parser, CharData); 383 i = XML_Parse(parser, p, strlen(p), 1); 384 if (mt->error != 0) 385 error = mt->error; 386 else if (i != 1) { 387 error = XML_GetErrorCode(parser) == XML_ERROR_NO_MEMORY ? 388 ENOMEM : EILSEQ; 389 } 390 XML_ParserFree(parser); 391 if (error != 0) { 392 free(mt); 393 return (error); 394 } 395 gmp->lg_ident = calloc(sizeof *gmp->lg_ident, mt->nident + 1); 396 free(mt); 397 if (gmp->lg_ident == NULL) 398 return (ENOMEM); 399 i = 0; 400 /* Collect all identifiers */ 401 LIST_FOREACH(cl, &gmp->lg_class, lg_class) { 402 gmp->lg_ident[i].lg_id = cl->lg_id; 403 gmp->lg_ident[i].lg_ptr = cl; 404 gmp->lg_ident[i].lg_what = ISCLASS; 405 i++; 406 LIST_FOREACH(ge, &cl->lg_geom, lg_geom) { 407 gmp->lg_ident[i].lg_id = ge->lg_id; 408 gmp->lg_ident[i].lg_ptr = ge; 409 gmp->lg_ident[i].lg_what = ISGEOM; 410 i++; 411 LIST_FOREACH(pr, &ge->lg_provider, lg_provider) { 412 gmp->lg_ident[i].lg_id = pr->lg_id; 413 gmp->lg_ident[i].lg_ptr = pr; 414 gmp->lg_ident[i].lg_what = ISPROVIDER; 415 i++; 416 } 417 LIST_FOREACH(co, &ge->lg_consumer, lg_consumer) { 418 gmp->lg_ident[i].lg_id = co->lg_id; 419 gmp->lg_ident[i].lg_ptr = co; 420 gmp->lg_ident[i].lg_what = ISCONSUMER; 421 i++; 422 } 423 } 424 } 425 /* Substitute all identifiers */ 426 LIST_FOREACH(cl, &gmp->lg_class, lg_class) { 427 LIST_FOREACH(ge, &cl->lg_geom, lg_geom) { 428 ge->lg_class = 429 geom_lookupid(gmp, ge->lg_class)->lg_ptr; 430 LIST_FOREACH(pr, &ge->lg_provider, lg_provider) { 431 pr->lg_geom = 432 geom_lookupid(gmp, pr->lg_geom)->lg_ptr; 433 } 434 LIST_FOREACH(co, &ge->lg_consumer, lg_consumer) { 435 co->lg_geom = 436 geom_lookupid(gmp, co->lg_geom)->lg_ptr; 437 if (co->lg_provider != NULL) { 438 co->lg_provider = 439 geom_lookupid(gmp, 440 co->lg_provider)->lg_ptr; 441 LIST_INSERT_HEAD( 442 &co->lg_provider->lg_consumers, 443 co, lg_consumers); 444 } 445 } 446 } 447 } 448 return (0); 449} 450 451int 452geom_gettree(struct gmesh *gmp) 453{ 454 char *p; 455 int error; 456 457 p = geom_getxml(); 458 if (p == NULL) 459 return (errno); 460 error = geom_xml2tree(gmp, p); 461 free(p); 462 return (error); 463} 464 465static void 466delete_config(struct gconf *gp) 467{ 468 struct gconfig *cf; 469 470 for (;;) { 471 cf = LIST_FIRST(gp); 472 if (cf == NULL) 473 return; 474 LIST_REMOVE(cf, lg_config); 475 free(cf->lg_name); 476 free(cf->lg_val); 477 free(cf); 478 } 479} 480 481void 482geom_deletetree(struct gmesh *gmp) 483{ 484 struct gclass *cl; 485 struct ggeom *ge; 486 struct gprovider *pr; 487 struct gconsumer *co; 488 489 free(gmp->lg_ident); 490 gmp->lg_ident = NULL; 491 for (;;) { 492 cl = LIST_FIRST(&gmp->lg_class); 493 if (cl == NULL) 494 break; 495 LIST_REMOVE(cl, lg_class); 496 delete_config(&cl->lg_config); 497 if (cl->lg_name) free(cl->lg_name); 498 for (;;) { 499 ge = LIST_FIRST(&cl->lg_geom); 500 if (ge == NULL) 501 break; 502 LIST_REMOVE(ge, lg_geom); 503 delete_config(&ge->lg_config); 504 if (ge->lg_name) free(ge->lg_name); 505 for (;;) { 506 pr = LIST_FIRST(&ge->lg_provider); 507 if (pr == NULL) 508 break; 509 LIST_REMOVE(pr, lg_provider); 510 delete_config(&pr->lg_config); 511 if (pr->lg_name) free(pr->lg_name); 512 if (pr->lg_mode) free(pr->lg_mode); 513 free(pr); 514 } 515 for (;;) { 516 co = LIST_FIRST(&ge->lg_consumer); 517 if (co == NULL) 518 break; 519 LIST_REMOVE(co, lg_consumer); 520 delete_config(&co->lg_config); 521 if (co->lg_mode) free(co->lg_mode); 522 free(co); 523 } 524 free(ge); 525 } 526 free(cl); 527 } 528} 529