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