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