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