1*c5591576SRob Johnston /*
2*c5591576SRob Johnston * This file and its contents are supplied under the terms of the
3*c5591576SRob Johnston * Common Development and Distribution License ("CDDL"), version 1.0.
4*c5591576SRob Johnston * You may only use this file in accordance with the terms of version
5*c5591576SRob Johnston * 1.0 of the CDDL.
6*c5591576SRob Johnston *
7*c5591576SRob Johnston * A full copy of the text of the CDDL should have accompanied this
8*c5591576SRob Johnston * source. A copy of the CDDL is also available via the Internet at
9*c5591576SRob Johnston * http://www.illumos.org/license/CDDL.
10*c5591576SRob Johnston */
11*c5591576SRob Johnston
12*c5591576SRob Johnston /*
13*c5591576SRob Johnston * Copyright 2020 Joyent, Inc.
14*c5591576SRob Johnston */
15*c5591576SRob Johnston
16*c5591576SRob Johnston /*
17*c5591576SRob Johnston * This file implements the following two routines for serializing and
18*c5591576SRob Johnston * deserializing digraphs to/from XML, respectively:
19*c5591576SRob Johnston *
20*c5591576SRob Johnston * topo_digraph_serialize()
21*c5591576SRob Johnston * topo_digraph_deserialize()
22*c5591576SRob Johnston *
23*c5591576SRob Johnston * Refer to the following file for the XML schema being used:
24*c5591576SRob Johnston * usr/src/lib/fm/topo/maps/common/digraph-topology.dtd.1
25*c5591576SRob Johnston */
26*c5591576SRob Johnston #include <time.h>
27*c5591576SRob Johnston #include <sys/utsname.h>
28*c5591576SRob Johnston #include <libxml/parser.h>
29*c5591576SRob Johnston #include <libtopo.h>
30*c5591576SRob Johnston
31*c5591576SRob Johnston #include <topo_digraph.h>
32*c5591576SRob Johnston #include <topo_digraph_xml.h>
33*c5591576SRob Johnston
34*c5591576SRob Johnston #define __STDC_FORMAT_MACROS
35*c5591576SRob Johnston #include <inttypes.h>
36*c5591576SRob Johnston
37*c5591576SRob Johnston extern int xmlattr_to_int(topo_mod_t *, xmlNodePtr, const char *, uint64_t *);
38*c5591576SRob Johnston static int serialize_nvpair(topo_hdl_t *thp, FILE *, uint_t, const char *,
39*c5591576SRob Johnston nvpair_t *);
40*c5591576SRob Johnston
41*c5591576SRob Johnston static void
tdg_xml_nvstring(FILE * fp,uint_t pad,const char * name,const char * value)42*c5591576SRob Johnston tdg_xml_nvstring(FILE *fp, uint_t pad, const char *name, const char *value)
43*c5591576SRob Johnston {
44*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%s' />\n", pad, "",
45*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_STRING,
46*c5591576SRob Johnston TDG_XML_VALUE, value);
47*c5591576SRob Johnston }
48*c5591576SRob Johnston
49*c5591576SRob Johnston static void
tdg_xml_nvlist(FILE * fp,uint_t pad,const char * name)50*c5591576SRob Johnston tdg_xml_nvlist(FILE *fp, uint_t pad, const char *name)
51*c5591576SRob Johnston {
52*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s'>\n", pad, "",
53*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_NVLIST);
54*c5591576SRob Johnston }
55*c5591576SRob Johnston
56*c5591576SRob Johnston static void
tdg_xml_nvuint8(FILE * fp,uint_t pad,const char * name,const uint8_t value)57*c5591576SRob Johnston tdg_xml_nvuint8(FILE *fp, uint_t pad, const char *name, const uint8_t value)
58*c5591576SRob Johnston {
59*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%u' />\n", pad, "",
60*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_UINT8,
61*c5591576SRob Johnston TDG_XML_VALUE, value);
62*c5591576SRob Johnston }
63*c5591576SRob Johnston
64*c5591576SRob Johnston static void
tdg_xml_nvint8(FILE * fp,uint_t pad,const char * name,const uint8_t value)65*c5591576SRob Johnston tdg_xml_nvint8(FILE *fp, uint_t pad, const char *name, const uint8_t value)
66*c5591576SRob Johnston {
67*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%d' />\n", pad, "",
68*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_INT8,
69*c5591576SRob Johnston TDG_XML_VALUE, value);
70*c5591576SRob Johnston }
71*c5591576SRob Johnston
72*c5591576SRob Johnston static void
tdg_xml_nvuint16(FILE * fp,uint_t pad,const char * name,const uint8_t value)73*c5591576SRob Johnston tdg_xml_nvuint16(FILE *fp, uint_t pad, const char *name, const uint8_t value)
74*c5591576SRob Johnston {
75*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%u' />\n", pad, "",
76*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_UINT16,
77*c5591576SRob Johnston TDG_XML_VALUE, value);
78*c5591576SRob Johnston }
79*c5591576SRob Johnston
80*c5591576SRob Johnston static void
tdg_xml_nvint16(FILE * fp,uint_t pad,const char * name,const uint8_t value)81*c5591576SRob Johnston tdg_xml_nvint16(FILE *fp, uint_t pad, const char *name, const uint8_t value)
82*c5591576SRob Johnston {
83*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%d' />\n", pad, "",
84*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_INT16,
85*c5591576SRob Johnston TDG_XML_VALUE, value);
86*c5591576SRob Johnston }
87*c5591576SRob Johnston
88*c5591576SRob Johnston static void
tdg_xml_nvuint32(FILE * fp,uint_t pad,const char * name,const uint32_t value)89*c5591576SRob Johnston tdg_xml_nvuint32(FILE *fp, uint_t pad, const char *name, const uint32_t value)
90*c5591576SRob Johnston {
91*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%u' />\n", pad, "",
92*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_UINT32,
93*c5591576SRob Johnston TDG_XML_VALUE, value);
94*c5591576SRob Johnston }
95*c5591576SRob Johnston
96*c5591576SRob Johnston static void
tdg_xml_nvint32(FILE * fp,uint_t pad,const char * name,const int32_t value)97*c5591576SRob Johnston tdg_xml_nvint32(FILE *fp, uint_t pad, const char *name, const int32_t value)
98*c5591576SRob Johnston {
99*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%d' />\n", pad, "",
100*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_UINT32,
101*c5591576SRob Johnston TDG_XML_VALUE, value);
102*c5591576SRob Johnston }
103*c5591576SRob Johnston
104*c5591576SRob Johnston static void
tdg_xml_nvuint64(FILE * fp,uint_t pad,const char * name,const uint64_t value)105*c5591576SRob Johnston tdg_xml_nvuint64(FILE *fp, uint_t pad, const char *name, const uint64_t value)
106*c5591576SRob Johnston {
107*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='0x%" PRIx64 "' />\n",
108*c5591576SRob Johnston pad, "", TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE,
109*c5591576SRob Johnston TDG_XML_UINT64, TDG_XML_VALUE, value);
110*c5591576SRob Johnston }
111*c5591576SRob Johnston
112*c5591576SRob Johnston static void
tdg_xml_nvint64(FILE * fp,uint_t pad,const char * name,const int64_t value)113*c5591576SRob Johnston tdg_xml_nvint64(FILE *fp, uint_t pad, const char *name, const int64_t value)
114*c5591576SRob Johnston {
115*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%" PRIi64 "' />\n", pad,
116*c5591576SRob Johnston "", TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE,
117*c5591576SRob Johnston TDG_XML_UINT64, TDG_XML_VALUE, value);
118*c5591576SRob Johnston }
119*c5591576SRob Johnston
120*c5591576SRob Johnston static void
tdg_xml_nvdbl(FILE * fp,uint_t pad,const char * name,const double value)121*c5591576SRob Johnston tdg_xml_nvdbl(FILE *fp, uint_t pad, const char *name, const double value)
122*c5591576SRob Johnston {
123*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s' %s='%lf' />\n", pad, ""
124*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, TDG_XML_UINT64,
125*c5591576SRob Johnston TDG_XML_VALUE, value);
126*c5591576SRob Johnston }
127*c5591576SRob Johnston
128*c5591576SRob Johnston static void
tdg_xml_nvarray(FILE * fp,uint_t pad,const char * name,const char * type)129*c5591576SRob Johnston tdg_xml_nvarray(FILE *fp, uint_t pad, const char *name, const char *type)
130*c5591576SRob Johnston {
131*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s'>\n", pad, "",
132*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE, type);
133*c5591576SRob Johnston }
134*c5591576SRob Johnston
135*c5591576SRob Johnston static void
tdg_xml_nvint32arr(FILE * fp,uint_t pad,const char * name,int32_t * val,uint_t nelems)136*c5591576SRob Johnston tdg_xml_nvint32arr(FILE *fp, uint_t pad, const char *name, int32_t *val,
137*c5591576SRob Johnston uint_t nelems)
138*c5591576SRob Johnston {
139*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s'>\n", pad, "",
140*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE,
141*c5591576SRob Johnston TDG_XML_INT32_ARR);
142*c5591576SRob Johnston
143*c5591576SRob Johnston for (uint_t i = 0; i < nelems; i++) {
144*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%d' />\n", (pad + 2), "",
145*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_VALUE, val[i]);
146*c5591576SRob Johnston }
147*c5591576SRob Johnston (void) fprintf(fp, "%*s</%s>\n", pad, "", TDG_XML_NVPAIR);
148*c5591576SRob Johnston }
149*c5591576SRob Johnston
150*c5591576SRob Johnston static void
tdg_xml_nvuint32arr(FILE * fp,uint_t pad,const char * name,uint32_t * val,uint_t nelems)151*c5591576SRob Johnston tdg_xml_nvuint32arr(FILE *fp, uint_t pad, const char *name, uint32_t *val,
152*c5591576SRob Johnston uint_t nelems)
153*c5591576SRob Johnston {
154*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s'>\n", pad, "",
155*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE,
156*c5591576SRob Johnston TDG_XML_UINT32_ARR);
157*c5591576SRob Johnston
158*c5591576SRob Johnston for (uint_t i = 0; i < nelems; i++) {
159*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%d' />\n", (pad + 2), "",
160*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_VALUE, val[i]);
161*c5591576SRob Johnston }
162*c5591576SRob Johnston (void) fprintf(fp, "%*s</%s>\n", pad, "", TDG_XML_NVPAIR);
163*c5591576SRob Johnston }
164*c5591576SRob Johnston
165*c5591576SRob Johnston static void
tdg_xml_nvint64arr(FILE * fp,uint_t pad,const char * name,int64_t * val,uint_t nelems)166*c5591576SRob Johnston tdg_xml_nvint64arr(FILE *fp, uint_t pad, const char *name, int64_t *val,
167*c5591576SRob Johnston uint_t nelems)
168*c5591576SRob Johnston {
169*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s'>\n", pad, "",
170*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE,
171*c5591576SRob Johnston TDG_XML_INT64_ARR);
172*c5591576SRob Johnston
173*c5591576SRob Johnston for (uint_t i = 0; i < nelems; i++) {
174*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%" PRIi64 "' />\n", (pad + 2),
175*c5591576SRob Johnston "", TDG_XML_NVPAIR, TDG_XML_VALUE, val[i]);
176*c5591576SRob Johnston }
177*c5591576SRob Johnston (void) fprintf(fp, "%*s</%s>\n", pad, "", TDG_XML_NVPAIR);
178*c5591576SRob Johnston }
179*c5591576SRob Johnston
180*c5591576SRob Johnston static void
tdg_xml_nvuint64arr(FILE * fp,uint_t pad,const char * name,uint64_t * val,uint_t nelems)181*c5591576SRob Johnston tdg_xml_nvuint64arr(FILE *fp, uint_t pad, const char *name, uint64_t *val,
182*c5591576SRob Johnston uint_t nelems)
183*c5591576SRob Johnston {
184*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' %s='%s'>\n", pad, "",
185*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_NAME, name, TDG_XML_TYPE,
186*c5591576SRob Johnston TDG_XML_UINT64_ARR);
187*c5591576SRob Johnston
188*c5591576SRob Johnston for (uint_t i = 0; i < nelems; i++) {
189*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='0x%" PRIx64 "' />\n", (pad + 2),
190*c5591576SRob Johnston "", TDG_XML_NVPAIR, TDG_XML_VALUE, val[i]);
191*c5591576SRob Johnston }
192*c5591576SRob Johnston (void) fprintf(fp, "%*s</%s>\n", pad, "", TDG_XML_NVPAIR);
193*c5591576SRob Johnston }
194*c5591576SRob Johnston
195*c5591576SRob Johnston static int
serialize_nvpair_nvlist(topo_hdl_t * thp,FILE * fp,uint_t pad,const char * name,nvlist_t * nvl)196*c5591576SRob Johnston serialize_nvpair_nvlist(topo_hdl_t *thp, FILE *fp, uint_t pad,
197*c5591576SRob Johnston const char *name, nvlist_t *nvl)
198*c5591576SRob Johnston {
199*c5591576SRob Johnston nvpair_t *elem = NULL;
200*c5591576SRob Johnston
201*c5591576SRob Johnston tdg_xml_nvlist(fp, pad, name);
202*c5591576SRob Johnston
203*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s>\n", pad, "", TDG_XML_NVLIST);
204*c5591576SRob Johnston
205*c5591576SRob Johnston while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
206*c5591576SRob Johnston char *nvname = nvpair_name(elem);
207*c5591576SRob Johnston
208*c5591576SRob Johnston if (serialize_nvpair(thp, fp, (pad + 2), nvname, elem) != 0) {
209*c5591576SRob Johnston /* errno set */
210*c5591576SRob Johnston return (-1);
211*c5591576SRob Johnston }
212*c5591576SRob Johnston }
213*c5591576SRob Johnston
214*c5591576SRob Johnston (void) fprintf(fp, "%*s</%s>\n", pad, "", TDG_XML_NVLIST);
215*c5591576SRob Johnston (void) fprintf(fp, "%*s</%s> <!-- %s -->\n", pad, "", TDG_XML_NVPAIR,
216*c5591576SRob Johnston name);
217*c5591576SRob Johnston
218*c5591576SRob Johnston return (0);
219*c5591576SRob Johnston }
220*c5591576SRob Johnston
221*c5591576SRob Johnston static int
serialize_nvpair(topo_hdl_t * thp,FILE * fp,uint_t pad,const char * pname,nvpair_t * nvp)222*c5591576SRob Johnston serialize_nvpair(topo_hdl_t *thp, FILE *fp, uint_t pad, const char *pname,
223*c5591576SRob Johnston nvpair_t *nvp)
224*c5591576SRob Johnston {
225*c5591576SRob Johnston data_type_t type = nvpair_type(nvp);
226*c5591576SRob Johnston
227*c5591576SRob Johnston switch (type) {
228*c5591576SRob Johnston case DATA_TYPE_INT8: {
229*c5591576SRob Johnston int8_t val;
230*c5591576SRob Johnston
231*c5591576SRob Johnston if (nvpair_value_int8(nvp, &val) != 0)
232*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
233*c5591576SRob Johnston
234*c5591576SRob Johnston tdg_xml_nvint8(fp, pad, pname, val);
235*c5591576SRob Johnston break;
236*c5591576SRob Johnston }
237*c5591576SRob Johnston case DATA_TYPE_UINT8: {
238*c5591576SRob Johnston uint8_t val;
239*c5591576SRob Johnston
240*c5591576SRob Johnston if (nvpair_value_uint8(nvp, &val) != 0)
241*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
242*c5591576SRob Johnston
243*c5591576SRob Johnston tdg_xml_nvuint8(fp, pad, pname, val);
244*c5591576SRob Johnston break;
245*c5591576SRob Johnston }
246*c5591576SRob Johnston case DATA_TYPE_INT16: {
247*c5591576SRob Johnston int16_t val;
248*c5591576SRob Johnston
249*c5591576SRob Johnston if (nvpair_value_int16(nvp, &val) != 0)
250*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
251*c5591576SRob Johnston
252*c5591576SRob Johnston tdg_xml_nvint16(fp, pad, pname, val);
253*c5591576SRob Johnston break;
254*c5591576SRob Johnston }
255*c5591576SRob Johnston case DATA_TYPE_UINT16: {
256*c5591576SRob Johnston uint16_t val;
257*c5591576SRob Johnston
258*c5591576SRob Johnston if (nvpair_value_uint16(nvp, &val) != 0)
259*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
260*c5591576SRob Johnston
261*c5591576SRob Johnston tdg_xml_nvuint16(fp, pad, pname, val);
262*c5591576SRob Johnston break;
263*c5591576SRob Johnston }
264*c5591576SRob Johnston case DATA_TYPE_INT32: {
265*c5591576SRob Johnston int32_t val;
266*c5591576SRob Johnston
267*c5591576SRob Johnston if (nvpair_value_int32(nvp, &val) != 0)
268*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
269*c5591576SRob Johnston
270*c5591576SRob Johnston tdg_xml_nvint32(fp, pad, pname, val);
271*c5591576SRob Johnston break;
272*c5591576SRob Johnston }
273*c5591576SRob Johnston case DATA_TYPE_UINT32: {
274*c5591576SRob Johnston uint32_t val;
275*c5591576SRob Johnston
276*c5591576SRob Johnston if (nvpair_value_uint32(nvp, &val) != 0)
277*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
278*c5591576SRob Johnston
279*c5591576SRob Johnston tdg_xml_nvuint32(fp, pad, pname, val);
280*c5591576SRob Johnston break;
281*c5591576SRob Johnston }
282*c5591576SRob Johnston case DATA_TYPE_INT64: {
283*c5591576SRob Johnston int64_t val;
284*c5591576SRob Johnston
285*c5591576SRob Johnston if (nvpair_value_int64(nvp, &val) != 0)
286*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
287*c5591576SRob Johnston
288*c5591576SRob Johnston tdg_xml_nvint64(fp, pad, pname, val);
289*c5591576SRob Johnston break;
290*c5591576SRob Johnston }
291*c5591576SRob Johnston case DATA_TYPE_UINT64: {
292*c5591576SRob Johnston uint64_t val;
293*c5591576SRob Johnston
294*c5591576SRob Johnston if (nvpair_value_uint64(nvp, &val) != 0)
295*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
296*c5591576SRob Johnston
297*c5591576SRob Johnston tdg_xml_nvuint64(fp, pad, pname, val);
298*c5591576SRob Johnston break;
299*c5591576SRob Johnston }
300*c5591576SRob Johnston case DATA_TYPE_DOUBLE: {
301*c5591576SRob Johnston double val;
302*c5591576SRob Johnston
303*c5591576SRob Johnston if (nvpair_value_double(nvp, &val) != 0)
304*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
305*c5591576SRob Johnston
306*c5591576SRob Johnston tdg_xml_nvdbl(fp, pad, pname, val);
307*c5591576SRob Johnston break;
308*c5591576SRob Johnston }
309*c5591576SRob Johnston case DATA_TYPE_STRING: {
310*c5591576SRob Johnston char *val;
311*c5591576SRob Johnston
312*c5591576SRob Johnston if (nvpair_value_string(nvp, &val) != 0)
313*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
314*c5591576SRob Johnston
315*c5591576SRob Johnston tdg_xml_nvstring(fp, pad, pname, val);
316*c5591576SRob Johnston break;
317*c5591576SRob Johnston }
318*c5591576SRob Johnston case DATA_TYPE_NVLIST: {
319*c5591576SRob Johnston nvlist_t *nvl;
320*c5591576SRob Johnston
321*c5591576SRob Johnston if (nvpair_value_nvlist(nvp, &nvl) != 0)
322*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
323*c5591576SRob Johnston
324*c5591576SRob Johnston if (serialize_nvpair_nvlist(thp, fp, pad + 2, pname,
325*c5591576SRob Johnston nvl) != 0) {
326*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
327*c5591576SRob Johnston }
328*c5591576SRob Johnston break;
329*c5591576SRob Johnston }
330*c5591576SRob Johnston case DATA_TYPE_INT32_ARRAY: {
331*c5591576SRob Johnston uint_t nelems;
332*c5591576SRob Johnston int32_t *val;
333*c5591576SRob Johnston
334*c5591576SRob Johnston if (nvpair_value_int32_array(nvp, &val, &nelems) != 0)
335*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
336*c5591576SRob Johnston
337*c5591576SRob Johnston tdg_xml_nvint32arr(fp, pad + 2, pname, val, nelems);
338*c5591576SRob Johnston
339*c5591576SRob Johnston break;
340*c5591576SRob Johnston }
341*c5591576SRob Johnston case DATA_TYPE_UINT32_ARRAY: {
342*c5591576SRob Johnston uint_t nelems;
343*c5591576SRob Johnston uint32_t *val;
344*c5591576SRob Johnston
345*c5591576SRob Johnston if (nvpair_value_uint32_array(nvp, &val, &nelems) != 0)
346*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
347*c5591576SRob Johnston
348*c5591576SRob Johnston tdg_xml_nvuint32arr(fp, pad + 2, pname, val, nelems);
349*c5591576SRob Johnston
350*c5591576SRob Johnston break;
351*c5591576SRob Johnston }
352*c5591576SRob Johnston case DATA_TYPE_INT64_ARRAY: {
353*c5591576SRob Johnston uint_t nelems;
354*c5591576SRob Johnston int64_t *val;
355*c5591576SRob Johnston
356*c5591576SRob Johnston if (nvpair_value_int64_array(nvp, &val, &nelems) != 0)
357*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
358*c5591576SRob Johnston
359*c5591576SRob Johnston tdg_xml_nvint64arr(fp, pad + 2, pname, val, nelems);
360*c5591576SRob Johnston
361*c5591576SRob Johnston break;
362*c5591576SRob Johnston }
363*c5591576SRob Johnston case DATA_TYPE_UINT64_ARRAY: {
364*c5591576SRob Johnston uint_t nelems;
365*c5591576SRob Johnston uint64_t *val;
366*c5591576SRob Johnston
367*c5591576SRob Johnston if (nvpair_value_uint64_array(nvp, &val, &nelems) != 0)
368*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
369*c5591576SRob Johnston
370*c5591576SRob Johnston tdg_xml_nvuint64arr(fp, pad + 2, pname, val, nelems);
371*c5591576SRob Johnston
372*c5591576SRob Johnston break;
373*c5591576SRob Johnston }
374*c5591576SRob Johnston case DATA_TYPE_STRING_ARRAY: {
375*c5591576SRob Johnston uint_t nelems;
376*c5591576SRob Johnston char **val;
377*c5591576SRob Johnston
378*c5591576SRob Johnston if (nvpair_value_string_array(nvp, &val, &nelems) != 0)
379*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
380*c5591576SRob Johnston
381*c5591576SRob Johnston tdg_xml_nvarray(fp, pad, pname, TDG_XML_STRING_ARR);
382*c5591576SRob Johnston for (uint_t i = 0; i < nelems; i++) {
383*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' />\n",
384*c5591576SRob Johnston (pad + 2), "", TDG_XML_NVPAIR,
385*c5591576SRob Johnston TDG_XML_VALUE, val[i]);
386*c5591576SRob Johnston }
387*c5591576SRob Johnston (void) fprintf(fp, "%*s</%s>\n", (pad + 2), "",
388*c5591576SRob Johnston TDG_XML_NVPAIR);
389*c5591576SRob Johnston
390*c5591576SRob Johnston break;
391*c5591576SRob Johnston }
392*c5591576SRob Johnston case DATA_TYPE_NVLIST_ARRAY: {
393*c5591576SRob Johnston uint_t nelems;
394*c5591576SRob Johnston nvlist_t **val;
395*c5591576SRob Johnston
396*c5591576SRob Johnston if (nvpair_value_nvlist_array(nvp, &val, &nelems) != 0)
397*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
398*c5591576SRob Johnston
399*c5591576SRob Johnston tdg_xml_nvarray(fp, pad, pname, TDG_XML_NVLIST_ARR);
400*c5591576SRob Johnston for (uint_t i = 0; i < nelems; i++) {
401*c5591576SRob Johnston nvpair_t *elem = NULL;
402*c5591576SRob Johnston
403*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s>\n", (pad + 2), "",
404*c5591576SRob Johnston TDG_XML_NVLIST);
405*c5591576SRob Johnston
406*c5591576SRob Johnston while ((elem = nvlist_next_nvpair(val[i],
407*c5591576SRob Johnston elem)) != NULL) {
408*c5591576SRob Johnston char *nvname = nvpair_name(elem);
409*c5591576SRob Johnston
410*c5591576SRob Johnston if (serialize_nvpair(thp, fp,
411*c5591576SRob Johnston (pad + 4), nvname, elem) != 0) {
412*c5591576SRob Johnston /* errno set */
413*c5591576SRob Johnston return (-1);
414*c5591576SRob Johnston }
415*c5591576SRob Johnston }
416*c5591576SRob Johnston
417*c5591576SRob Johnston (void) fprintf(fp, "%*s</%s>\n", (pad + 2), "",
418*c5591576SRob Johnston TDG_XML_NVLIST);
419*c5591576SRob Johnston }
420*c5591576SRob Johnston (void) fprintf(fp, "%*s</%s>\n", pad, "",
421*c5591576SRob Johnston TDG_XML_NVPAIR);
422*c5591576SRob Johnston
423*c5591576SRob Johnston break;
424*c5591576SRob Johnston }
425*c5591576SRob Johnston default:
426*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "Invalid nvpair data "
427*c5591576SRob Johnston "type: %d\n", type);
428*c5591576SRob Johnston (void) topo_hdl_seterrno(thp, ETOPO_MOD_XENUM);
429*c5591576SRob Johnston return (-1);
430*c5591576SRob Johnston }
431*c5591576SRob Johnston return (0);
432*c5591576SRob Johnston }
433*c5591576SRob Johnston
434*c5591576SRob Johnston static int
serialize_edge(topo_hdl_t * thp,topo_edge_t * edge,boolean_t last_edge,void * arg)435*c5591576SRob Johnston serialize_edge(topo_hdl_t *thp, topo_edge_t *edge, boolean_t last_edge,
436*c5591576SRob Johnston void *arg)
437*c5591576SRob Johnston {
438*c5591576SRob Johnston nvlist_t *fmri = NULL;
439*c5591576SRob Johnston char *fmristr;
440*c5591576SRob Johnston int err;
441*c5591576SRob Johnston tnode_t *tn;
442*c5591576SRob Johnston FILE *fp = (FILE *)arg;
443*c5591576SRob Johnston
444*c5591576SRob Johnston tn = topo_vertex_node(edge->tve_vertex);
445*c5591576SRob Johnston if (topo_node_resource(tn, &fmri, &err) != 0 ||
446*c5591576SRob Johnston topo_fmri_nvl2str(thp, fmri, &fmristr, &err) != 0) {
447*c5591576SRob Johnston /* errno set */
448*c5591576SRob Johnston nvlist_free(fmri);
449*c5591576SRob Johnston return (TOPO_WALK_ERR);
450*c5591576SRob Johnston }
451*c5591576SRob Johnston nvlist_free(fmri);
452*c5591576SRob Johnston
453*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s %s='%s' />\n", 4, "", TDG_XML_EDGE,
454*c5591576SRob Johnston TDG_XML_FMRI, fmristr);
455*c5591576SRob Johnston topo_hdl_strfree(thp, fmristr);
456*c5591576SRob Johnston
457*c5591576SRob Johnston return (TOPO_WALK_NEXT);
458*c5591576SRob Johnston }
459*c5591576SRob Johnston
460*c5591576SRob Johnston /*
461*c5591576SRob Johnston * Some node property values aren't available unless we go through the libtopo
462*c5591576SRob Johnston * API's topo_prop_get_* routines. We do that here to make sure the nodes have
463*c5591576SRob Johnston * all of their properties populated, then we vector off to type-specific
464*c5591576SRob Johnston * XML serialization functions.
465*c5591576SRob Johnston */
466*c5591576SRob Johnston static int
serialize_property(topo_hdl_t * thp,FILE * fp,uint_t pad,tnode_t * tn,topo_propval_t * pv,const char * pgname)467*c5591576SRob Johnston serialize_property(topo_hdl_t *thp, FILE *fp, uint_t pad, tnode_t *tn,
468*c5591576SRob Johnston topo_propval_t *pv, const char *pgname)
469*c5591576SRob Johnston {
470*c5591576SRob Johnston topo_type_t type = pv->tp_type;
471*c5591576SRob Johnston const char *pname = pv->tp_name;
472*c5591576SRob Johnston int err;
473*c5591576SRob Johnston char *name = TDG_XML_PROP_VALUE;
474*c5591576SRob Johnston
475*c5591576SRob Johnston switch (type) {
476*c5591576SRob Johnston case TOPO_TYPE_INT32: {
477*c5591576SRob Johnston int32_t val;
478*c5591576SRob Johnston
479*c5591576SRob Johnston if (topo_prop_get_int32(tn, pgname, pname, &val,
480*c5591576SRob Johnston &err) != 0)
481*c5591576SRob Johnston return (-1);
482*c5591576SRob Johnston
483*c5591576SRob Johnston tdg_xml_nvint32(fp, pad, name, val);
484*c5591576SRob Johnston break;
485*c5591576SRob Johnston }
486*c5591576SRob Johnston case TOPO_TYPE_UINT32: {
487*c5591576SRob Johnston uint32_t val;
488*c5591576SRob Johnston
489*c5591576SRob Johnston if (topo_prop_get_uint32(tn, pgname, pname, &val,
490*c5591576SRob Johnston &err) != 0)
491*c5591576SRob Johnston return (-1);
492*c5591576SRob Johnston
493*c5591576SRob Johnston tdg_xml_nvuint32(fp, pad, name, val);
494*c5591576SRob Johnston break;
495*c5591576SRob Johnston }
496*c5591576SRob Johnston case TOPO_TYPE_INT64: {
497*c5591576SRob Johnston int64_t val;
498*c5591576SRob Johnston
499*c5591576SRob Johnston if (topo_prop_get_int64(tn, pgname, pname, &val,
500*c5591576SRob Johnston &err) != 0)
501*c5591576SRob Johnston return (-1);
502*c5591576SRob Johnston
503*c5591576SRob Johnston tdg_xml_nvint64(fp, pad, name, val);
504*c5591576SRob Johnston break;
505*c5591576SRob Johnston }
506*c5591576SRob Johnston case TOPO_TYPE_UINT64: {
507*c5591576SRob Johnston uint64_t val;
508*c5591576SRob Johnston
509*c5591576SRob Johnston if (topo_prop_get_uint64(tn, pgname, pname, &val,
510*c5591576SRob Johnston &err) != 0)
511*c5591576SRob Johnston return (-1);
512*c5591576SRob Johnston
513*c5591576SRob Johnston tdg_xml_nvuint64(fp, pad, name, val);
514*c5591576SRob Johnston break;
515*c5591576SRob Johnston }
516*c5591576SRob Johnston case TOPO_TYPE_STRING: {
517*c5591576SRob Johnston char *val;
518*c5591576SRob Johnston
519*c5591576SRob Johnston if (topo_prop_get_string(tn, pgname, pname, &val,
520*c5591576SRob Johnston &err) != 0)
521*c5591576SRob Johnston return (-1);
522*c5591576SRob Johnston
523*c5591576SRob Johnston tdg_xml_nvstring(fp, pad, name, val);
524*c5591576SRob Johnston
525*c5591576SRob Johnston topo_hdl_strfree(thp, val);
526*c5591576SRob Johnston break;
527*c5591576SRob Johnston }
528*c5591576SRob Johnston case TOPO_TYPE_FMRI: {
529*c5591576SRob Johnston nvlist_t *nvl;
530*c5591576SRob Johnston
531*c5591576SRob Johnston if (topo_prop_get_fmri(tn, pgname, pname, &nvl,
532*c5591576SRob Johnston &err) != 0)
533*c5591576SRob Johnston return (-1);
534*c5591576SRob Johnston
535*c5591576SRob Johnston if (serialize_nvpair_nvlist(thp, fp, pad + 2, name,
536*c5591576SRob Johnston nvl) != 0) {
537*c5591576SRob Johnston nvlist_free(nvl);
538*c5591576SRob Johnston return (-1);
539*c5591576SRob Johnston }
540*c5591576SRob Johnston
541*c5591576SRob Johnston nvlist_free(nvl);
542*c5591576SRob Johnston break;
543*c5591576SRob Johnston }
544*c5591576SRob Johnston case TOPO_TYPE_INT32_ARRAY: {
545*c5591576SRob Johnston uint_t nelems;
546*c5591576SRob Johnston int32_t *val;
547*c5591576SRob Johnston
548*c5591576SRob Johnston if (topo_prop_get_int32_array(tn, pgname, pname, &val,
549*c5591576SRob Johnston &nelems, &err) != 0)
550*c5591576SRob Johnston return (-1);
551*c5591576SRob Johnston
552*c5591576SRob Johnston tdg_xml_nvint32arr(fp, pad, pname, val, nelems);
553*c5591576SRob Johnston topo_hdl_free(thp, val, (sizeof (int32_t) * nelems));
554*c5591576SRob Johnston break;
555*c5591576SRob Johnston }
556*c5591576SRob Johnston case TOPO_TYPE_UINT32_ARRAY: {
557*c5591576SRob Johnston uint_t nelems;
558*c5591576SRob Johnston uint32_t *val;
559*c5591576SRob Johnston
560*c5591576SRob Johnston if (topo_prop_get_uint32_array(tn, pgname, pname, &val,
561*c5591576SRob Johnston &nelems, &err) != 0)
562*c5591576SRob Johnston return (-1);
563*c5591576SRob Johnston
564*c5591576SRob Johnston tdg_xml_nvuint32arr(fp, pad, pname, val, nelems);
565*c5591576SRob Johnston topo_hdl_free(thp, val, (sizeof (uint32_t) * nelems));
566*c5591576SRob Johnston break;
567*c5591576SRob Johnston }
568*c5591576SRob Johnston case TOPO_TYPE_INT64_ARRAY: {
569*c5591576SRob Johnston uint_t nelems;
570*c5591576SRob Johnston int64_t *val;
571*c5591576SRob Johnston
572*c5591576SRob Johnston if (topo_prop_get_int64_array(tn, pgname, pname, &val,
573*c5591576SRob Johnston &nelems, &err) != 0)
574*c5591576SRob Johnston return (-1);
575*c5591576SRob Johnston
576*c5591576SRob Johnston tdg_xml_nvint64arr(fp, pad, pname, val, nelems);
577*c5591576SRob Johnston topo_hdl_free(thp, val, (sizeof (int64_t) * nelems));
578*c5591576SRob Johnston break;
579*c5591576SRob Johnston }
580*c5591576SRob Johnston case TOPO_TYPE_UINT64_ARRAY: {
581*c5591576SRob Johnston uint_t nelems;
582*c5591576SRob Johnston uint64_t *val;
583*c5591576SRob Johnston
584*c5591576SRob Johnston if (topo_prop_get_uint64_array(tn, pgname, pname, &val,
585*c5591576SRob Johnston &nelems, &err) != 0)
586*c5591576SRob Johnston return (-1);
587*c5591576SRob Johnston
588*c5591576SRob Johnston tdg_xml_nvuint64arr(fp, pad, pname, val, nelems);
589*c5591576SRob Johnston topo_hdl_free(thp, val, (sizeof (uint64_t) * nelems));
590*c5591576SRob Johnston break;
591*c5591576SRob Johnston }
592*c5591576SRob Johnston default:
593*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "Invalid nvpair data "
594*c5591576SRob Johnston "type: %d\n", type);
595*c5591576SRob Johnston (void) topo_hdl_seterrno(thp, ETOPO_MOD_XENUM);
596*c5591576SRob Johnston return (-1);
597*c5591576SRob Johnston }
598*c5591576SRob Johnston return (0);
599*c5591576SRob Johnston }
600*c5591576SRob Johnston
601*c5591576SRob Johnston static int
serialize_pgroups(topo_hdl_t * thp,FILE * fp,tnode_t * tn)602*c5591576SRob Johnston serialize_pgroups(topo_hdl_t *thp, FILE *fp, tnode_t *tn)
603*c5591576SRob Johnston {
604*c5591576SRob Johnston topo_pgroup_t *pg;
605*c5591576SRob Johnston uint_t npgs = 0;
606*c5591576SRob Johnston
607*c5591576SRob Johnston for (pg = topo_list_next(&tn->tn_pgroups); pg != NULL;
608*c5591576SRob Johnston pg = topo_list_next(pg)) {
609*c5591576SRob Johnston
610*c5591576SRob Johnston npgs++;
611*c5591576SRob Johnston }
612*c5591576SRob Johnston
613*c5591576SRob Johnston tdg_xml_nvarray(fp, 2, TDG_XML_PGROUPS, TDG_XML_NVLIST_ARR);
614*c5591576SRob Johnston
615*c5591576SRob Johnston for (pg = topo_list_next(&tn->tn_pgroups); pg != NULL;
616*c5591576SRob Johnston pg = topo_list_next(pg)) {
617*c5591576SRob Johnston
618*c5591576SRob Johnston topo_proplist_t *pvl;
619*c5591576SRob Johnston uint_t nprops = 0;
620*c5591576SRob Johnston
621*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s>\n", 4, "", TDG_XML_NVLIST);
622*c5591576SRob Johnston tdg_xml_nvstring(fp, 6, TOPO_PROP_GROUP_NAME,
623*c5591576SRob Johnston pg->tpg_info->tpi_name);
624*c5591576SRob Johnston
625*c5591576SRob Johnston for (pvl = topo_list_next(&pg->tpg_pvals); pvl != NULL;
626*c5591576SRob Johnston pvl = topo_list_next(pvl))
627*c5591576SRob Johnston nprops++;
628*c5591576SRob Johnston
629*c5591576SRob Johnston tdg_xml_nvarray(fp, 6, TDG_XML_PVALS, TDG_XML_NVLIST_ARR);
630*c5591576SRob Johnston
631*c5591576SRob Johnston for (pvl = topo_list_next(&pg->tpg_pvals); pvl != NULL;
632*c5591576SRob Johnston pvl = topo_list_next(pvl)) {
633*c5591576SRob Johnston
634*c5591576SRob Johnston topo_propval_t *pv = pvl->tp_pval;
635*c5591576SRob Johnston
636*c5591576SRob Johnston (void) fprintf(fp, "%*s<%s>\n", 8, "", TDG_XML_NVLIST);
637*c5591576SRob Johnston tdg_xml_nvstring(fp, 10, TDG_XML_PROP_NAME,
638*c5591576SRob Johnston pv->tp_name);
639*c5591576SRob Johnston tdg_xml_nvuint32(fp, 10, TDG_XML_PROP_TYPE,
640*c5591576SRob Johnston pv->tp_type);
641*c5591576SRob Johnston
642*c5591576SRob Johnston if (serialize_property(thp, fp, 10, tn, pv,
643*c5591576SRob Johnston pg->tpg_info->tpi_name) != 0) {
644*c5591576SRob Johnston /* errno set */
645*c5591576SRob Johnston return (-1);
646*c5591576SRob Johnston }
647*c5591576SRob Johnston (void) fprintf(fp, "%*s</%s>\n", 8, "",
648*c5591576SRob Johnston TDG_XML_NVLIST);
649*c5591576SRob Johnston }
650*c5591576SRob Johnston
651*c5591576SRob Johnston (void) fprintf(fp, "%*s</%s> <!-- %s -->\n", 6, "",
652*c5591576SRob Johnston TDG_XML_NVPAIR, TDG_XML_PVALS);
653*c5591576SRob Johnston (void) fprintf(fp, "%*s</%s>\n", 4, "", TDG_XML_NVLIST);
654*c5591576SRob Johnston }
655*c5591576SRob Johnston (void) fprintf(fp, "%*s</%s> <!-- %s -->\n", 2, "", TDG_XML_NVPAIR,
656*c5591576SRob Johnston TDG_XML_PGROUPS);
657*c5591576SRob Johnston
658*c5591576SRob Johnston return (0);
659*c5591576SRob Johnston }
660*c5591576SRob Johnston
661*c5591576SRob Johnston static int
serialize_vertex(topo_hdl_t * thp,topo_vertex_t * vtx,boolean_t last_vtx,void * arg)662*c5591576SRob Johnston serialize_vertex(topo_hdl_t *thp, topo_vertex_t *vtx, boolean_t last_vtx,
663*c5591576SRob Johnston void *arg)
664*c5591576SRob Johnston {
665*c5591576SRob Johnston nvlist_t *fmri = NULL;
666*c5591576SRob Johnston char *fmristr;
667*c5591576SRob Johnston tnode_t *tn;
668*c5591576SRob Johnston int err;
669*c5591576SRob Johnston FILE *fp = (FILE *)arg;
670*c5591576SRob Johnston
671*c5591576SRob Johnston tn = topo_vertex_node(vtx);
672*c5591576SRob Johnston if (topo_node_resource(tn, &fmri, &err) != 0 ||
673*c5591576SRob Johnston topo_fmri_nvl2str(thp, fmri, &fmristr, &err) != 0) {
674*c5591576SRob Johnston /* errno set */
675*c5591576SRob Johnston nvlist_free(fmri);
676*c5591576SRob Johnston return (TOPO_WALK_ERR);
677*c5591576SRob Johnston }
678*c5591576SRob Johnston nvlist_free(fmri);
679*c5591576SRob Johnston
680*c5591576SRob Johnston (void) fprintf(fp, "<%s %s='%s' %s='0x%" PRIx64 "' %s='%s'>\n",
681*c5591576SRob Johnston TDG_XML_VERTEX, TDG_XML_NAME, topo_node_name(tn),
682*c5591576SRob Johnston TDG_XML_INSTANCE, topo_node_instance(tn),
683*c5591576SRob Johnston TDG_XML_FMRI, fmristr);
684*c5591576SRob Johnston
685*c5591576SRob Johnston topo_hdl_strfree(thp, fmristr);
686*c5591576SRob Johnston
687*c5591576SRob Johnston if (serialize_pgroups(thp, fp, tn) != 0) {
688*c5591576SRob Johnston /* errno set */
689*c5591576SRob Johnston return (TOPO_WALK_ERR);
690*c5591576SRob Johnston }
691*c5591576SRob Johnston
692*c5591576SRob Johnston if (vtx->tvt_noutgoing != 0) {
693*c5591576SRob Johnston (void) fprintf(fp, " <%s>\n", TDG_XML_OUTEDGES);
694*c5591576SRob Johnston
695*c5591576SRob Johnston if (topo_edge_iter(thp, vtx, serialize_edge, fp) != 0) {
696*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "failed to iterate "
697*c5591576SRob Johnston "edges on %s=%" PRIx64 "\n", topo_node_name(tn),
698*c5591576SRob Johnston topo_node_instance(tn));
699*c5591576SRob Johnston /* errno set */
700*c5591576SRob Johnston return (TOPO_WALK_ERR);
701*c5591576SRob Johnston }
702*c5591576SRob Johnston (void) fprintf(fp, " </%s>\n", TDG_XML_OUTEDGES);
703*c5591576SRob Johnston }
704*c5591576SRob Johnston (void) fprintf(fp, "</%s>\n\n", TDG_XML_VERTEX);
705*c5591576SRob Johnston
706*c5591576SRob Johnston return (TOPO_WALK_NEXT);
707*c5591576SRob Johnston }
708*c5591576SRob Johnston
709*c5591576SRob Johnston /*
710*c5591576SRob Johnston * This function takes a topo_digraph_t and serializes it to XML.
711*c5591576SRob Johnston *
712*c5591576SRob Johnston * The schema is described in detail in:
713*c5591576SRob Johnston * usr/src/lib/fm/topo/maps/common/digraph-topology.dtd.1
714*c5591576SRob Johnston *
715*c5591576SRob Johnston * On success, this function writes the XML to the specified file and
716*c5591576SRob Johnston * returns 0.
717*c5591576SRob Johnston *
718*c5591576SRob Johnston * On failure, this function returns -1.
719*c5591576SRob Johnston */
720*c5591576SRob Johnston int
topo_digraph_serialize(topo_hdl_t * thp,topo_digraph_t * tdg,FILE * fp)721*c5591576SRob Johnston topo_digraph_serialize(topo_hdl_t *thp, topo_digraph_t *tdg, FILE *fp)
722*c5591576SRob Johnston {
723*c5591576SRob Johnston struct utsname uts = { 0 };
724*c5591576SRob Johnston time_t utc_time;
725*c5591576SRob Johnston char tstamp[64];
726*c5591576SRob Johnston int ret;
727*c5591576SRob Johnston
728*c5591576SRob Johnston if ((ret = uname(&uts)) < 0) {
729*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "uname failed (ret = %d)\n",
730*c5591576SRob Johnston ret);
731*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
732*c5591576SRob Johnston }
733*c5591576SRob Johnston
734*c5591576SRob Johnston if (time(&utc_time) < 0) {
735*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "uname failed (%s)\n",
736*c5591576SRob Johnston strerror(errno));
737*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
738*c5591576SRob Johnston }
739*c5591576SRob Johnston
740*c5591576SRob Johnston /*
741*c5591576SRob Johnston * strftime returns 0 if the size of the result is larger than the
742*c5591576SRob Johnston * buffer size passed in to it. We've sized tstamp to be pretty
743*c5591576SRob Johnston * large, so this really shouldn't happen.
744*c5591576SRob Johnston */
745*c5591576SRob Johnston if (strftime(tstamp, sizeof (tstamp), "%Y-%m-%dT%H:%M:%SZ",
746*c5591576SRob Johnston gmtime(&utc_time)) == 0) {
747*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "strftime failed\n");
748*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
749*c5591576SRob Johnston }
750*c5591576SRob Johnston
751*c5591576SRob Johnston (void) fprintf(fp, "<?xml version=\"1.0\"?>\n");
752*c5591576SRob Johnston (void) fprintf(fp, "<!DOCTYPE topology SYSTEM \"%s\">\n", TDG_DTD);
753*c5591576SRob Johnston (void) fprintf(fp, "<%s %s='%s' %s='%s' %s='%s' %s='%s' %s='%s'>\n",
754*c5591576SRob Johnston TDG_XML_TOPO_DIGRAPH, TDG_XML_SCHEME, tdg->tdg_scheme,
755*c5591576SRob Johnston TDG_XML_NODENAME, uts.nodename, TDG_XML_OSVERSION, uts.version,
756*c5591576SRob Johnston TDG_XML_PRODUCT, thp->th_product, TDG_XML_TSTAMP, tstamp);
757*c5591576SRob Johnston (void) fprintf(fp, "<%s>\n", TDG_XML_VERTICES);
758*c5591576SRob Johnston
759*c5591576SRob Johnston if (topo_vertex_iter(thp, tdg, serialize_vertex, fp) != 0) {
760*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "\nfailed to iterate "
761*c5591576SRob Johnston "vertices\n");
762*c5591576SRob Johnston /* errno set */
763*c5591576SRob Johnston return (-1);
764*c5591576SRob Johnston }
765*c5591576SRob Johnston
766*c5591576SRob Johnston (void) fprintf(fp, "</%s>\n", TDG_XML_VERTICES);
767*c5591576SRob Johnston (void) fprintf(fp, "</%s>\n", TDG_XML_TOPO_DIGRAPH);
768*c5591576SRob Johnston
769*c5591576SRob Johnston if (ferror(fp) != 0) {
770*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "An unknown error ocurrred "
771*c5591576SRob Johnston "while writing out the serialize topology.");
772*c5591576SRob Johnston return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
773*c5591576SRob Johnston }
774*c5591576SRob Johnston return (0);
775*c5591576SRob Johnston }
776*c5591576SRob Johnston
777*c5591576SRob Johnston static xmlNodePtr
get_child_by_name(xmlNodePtr xn,xmlChar * name)778*c5591576SRob Johnston get_child_by_name(xmlNodePtr xn, xmlChar *name)
779*c5591576SRob Johnston {
780*c5591576SRob Johnston for (xmlNodePtr cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next)
781*c5591576SRob Johnston if (xmlStrcmp(cn->name, name) == 0)
782*c5591576SRob Johnston return (cn);
783*c5591576SRob Johnston
784*c5591576SRob Johnston return (NULL);
785*c5591576SRob Johnston }
786*c5591576SRob Johnston
787*c5591576SRob Johnston static void
dump_xml_node(topo_hdl_t * thp,xmlNodePtr xn)788*c5591576SRob Johnston dump_xml_node(topo_hdl_t *thp, xmlNodePtr xn)
789*c5591576SRob Johnston {
790*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "node: %s", (char *)xn->name);
791*c5591576SRob Johnston for (xmlAttrPtr attr = xn->properties; attr != NULL; attr = attr->next)
792*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "attribute: %s",
793*c5591576SRob Johnston (char *)attr->name);
794*c5591576SRob Johnston
795*c5591576SRob Johnston for (xmlNodePtr cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next)
796*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "\tchild node: %s",
797*c5591576SRob Johnston (char *)cn->name);
798*c5591576SRob Johnston }
799*c5591576SRob Johnston
800*c5591576SRob Johnston struct edge_cb_arg {
801*c5591576SRob Johnston const char *from_fmri;
802*c5591576SRob Johnston const char *to_fmri;
803*c5591576SRob Johnston topo_vertex_t *from_vtx;
804*c5591576SRob Johnston topo_vertex_t *to_vtx;
805*c5591576SRob Johnston };
806*c5591576SRob Johnston
807*c5591576SRob Johnston static int
edge_cb(topo_hdl_t * thp,topo_vertex_t * vtx,boolean_t last_vtx,void * arg)808*c5591576SRob Johnston edge_cb(topo_hdl_t *thp, topo_vertex_t *vtx, boolean_t last_vtx, void *arg)
809*c5591576SRob Johnston {
810*c5591576SRob Johnston struct edge_cb_arg *cbarg = arg;
811*c5591576SRob Johnston tnode_t *tn;
812*c5591576SRob Johnston nvlist_t *fmri = NULL;
813*c5591576SRob Johnston char *fmristr = NULL;
814*c5591576SRob Johnston int err;
815*c5591576SRob Johnston
816*c5591576SRob Johnston tn = topo_vertex_node(vtx);
817*c5591576SRob Johnston if (topo_node_resource(tn, &fmri, &err) != 0 ||
818*c5591576SRob Johnston topo_fmri_nvl2str(thp, fmri, &fmristr, &err) != 0) {
819*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "failed to convert FMRI for "
820*c5591576SRob Johnston "%s=%" PRIx64 " to a string\n", topo_node_name(tn),
821*c5591576SRob Johnston topo_node_instance(tn));
822*c5591576SRob Johnston if (thp->th_debug & TOPO_DBG_XML)
823*c5591576SRob Johnston nvlist_print(stdout, fmri);
824*c5591576SRob Johnston nvlist_free(fmri);
825*c5591576SRob Johnston return (TOPO_WALK_ERR);
826*c5591576SRob Johnston }
827*c5591576SRob Johnston nvlist_free(fmri);
828*c5591576SRob Johnston
829*c5591576SRob Johnston if (strcmp(fmristr, cbarg->from_fmri) == 0)
830*c5591576SRob Johnston cbarg->from_vtx = vtx;
831*c5591576SRob Johnston else if (strcmp(fmristr, cbarg->to_fmri) == 0)
832*c5591576SRob Johnston cbarg->to_vtx = vtx;
833*c5591576SRob Johnston
834*c5591576SRob Johnston topo_hdl_strfree(thp, fmristr);
835*c5591576SRob Johnston if (cbarg->from_vtx != NULL && cbarg->to_vtx != NULL)
836*c5591576SRob Johnston return (TOPO_WALK_TERMINATE);
837*c5591576SRob Johnston else
838*c5591576SRob Johnston return (TOPO_WALK_NEXT);
839*c5591576SRob Johnston }
840*c5591576SRob Johnston
841*c5591576SRob Johnston static int
deserialize_edges(topo_hdl_t * thp,topo_mod_t * mod,topo_digraph_t * tdg,xmlChar * from_fmri,xmlNodePtr xn)842*c5591576SRob Johnston deserialize_edges(topo_hdl_t *thp, topo_mod_t *mod, topo_digraph_t *tdg,
843*c5591576SRob Johnston xmlChar *from_fmri, xmlNodePtr xn)
844*c5591576SRob Johnston {
845*c5591576SRob Johnston for (xmlNodePtr cn = xn->xmlChildrenNode; cn != NULL;
846*c5591576SRob Johnston cn = cn->next) {
847*c5591576SRob Johnston xmlChar *fmri;
848*c5591576SRob Johnston struct edge_cb_arg cbarg = { 0 };
849*c5591576SRob Johnston
850*c5591576SRob Johnston if (xmlStrcmp(cn->name, (xmlChar *)TDG_XML_EDGE) != 0)
851*c5591576SRob Johnston continue;
852*c5591576SRob Johnston
853*c5591576SRob Johnston if ((fmri = xmlGetProp(cn, (xmlChar *)TDG_XML_FMRI)) == NULL) {
854*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML,
855*c5591576SRob Johnston "error parsing %s element", (char *)cn->name);
856*c5591576SRob Johnston dump_xml_node(thp, cn);
857*c5591576SRob Johnston return (-1);
858*c5591576SRob Johnston }
859*c5591576SRob Johnston cbarg.from_fmri = (char *)from_fmri;
860*c5591576SRob Johnston cbarg.to_fmri = (char *)fmri;
861*c5591576SRob Johnston
862*c5591576SRob Johnston if (topo_vertex_iter(mod->tm_hdl, tdg, edge_cb, &cbarg) != 0) {
863*c5591576SRob Johnston xmlFree(fmri);
864*c5591576SRob Johnston return (-1);
865*c5591576SRob Johnston }
866*c5591576SRob Johnston xmlFree(fmri);
867*c5591576SRob Johnston
868*c5591576SRob Johnston if (cbarg.from_vtx == NULL || cbarg.to_vtx == NULL) {
869*c5591576SRob Johnston return (-1);
870*c5591576SRob Johnston }
871*c5591576SRob Johnston if (topo_edge_new(mod, cbarg.from_vtx, cbarg.to_vtx) != 0) {
872*c5591576SRob Johnston return (-1);
873*c5591576SRob Johnston }
874*c5591576SRob Johnston }
875*c5591576SRob Johnston
876*c5591576SRob Johnston return (0);
877*c5591576SRob Johnston }
878*c5591576SRob Johnston
879*c5591576SRob Johnston static int
add_edges(topo_hdl_t * thp,topo_mod_t * mod,topo_digraph_t * tdg,xmlNodePtr xn)880*c5591576SRob Johnston add_edges(topo_hdl_t *thp, topo_mod_t *mod, topo_digraph_t *tdg,
881*c5591576SRob Johnston xmlNodePtr xn)
882*c5591576SRob Johnston {
883*c5591576SRob Johnston int ret = -1;
884*c5591576SRob Johnston nvlist_t *props = NULL;
885*c5591576SRob Johnston xmlChar *name = NULL, *fmri = NULL;
886*c5591576SRob Johnston xmlNodePtr cn;
887*c5591576SRob Johnston uint64_t inst;
888*c5591576SRob Johnston
889*c5591576SRob Johnston if ((name = xmlGetProp(xn, (xmlChar *)TDG_XML_NAME)) == NULL ||
890*c5591576SRob Johnston (fmri = xmlGetProp(xn, (xmlChar *)TDG_XML_FMRI)) == NULL ||
891*c5591576SRob Johnston xmlattr_to_int(mod, xn, TDG_XML_INSTANCE, &inst) != 0) {
892*c5591576SRob Johnston goto fail;
893*c5591576SRob Johnston }
894*c5591576SRob Johnston
895*c5591576SRob Johnston if ((cn = get_child_by_name(xn, (xmlChar *)TDG_XML_OUTEDGES)) !=
896*c5591576SRob Johnston NULL) {
897*c5591576SRob Johnston if (deserialize_edges(thp, mod, tdg, fmri, cn) != 0)
898*c5591576SRob Johnston goto fail;
899*c5591576SRob Johnston }
900*c5591576SRob Johnston ret = 0;
901*c5591576SRob Johnston
902*c5591576SRob Johnston fail:
903*c5591576SRob Johnston if (ret != 0) {
904*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "%s: error parsing %s element",
905*c5591576SRob Johnston __func__, TDG_XML_VERTEX);
906*c5591576SRob Johnston dump_xml_node(thp, xn);
907*c5591576SRob Johnston }
908*c5591576SRob Johnston nvlist_free(props);
909*c5591576SRob Johnston if (name != NULL)
910*c5591576SRob Johnston xmlFree(name);
911*c5591576SRob Johnston if (fmri != NULL)
912*c5591576SRob Johnston xmlFree(fmri);
913*c5591576SRob Johnston
914*c5591576SRob Johnston return (ret);
915*c5591576SRob Johnston }
916*c5591576SRob Johnston
917*c5591576SRob Johnston static topo_pgroup_info_t pginfo = {
918*c5591576SRob Johnston NULL,
919*c5591576SRob Johnston TOPO_STABILITY_PRIVATE,
920*c5591576SRob Johnston TOPO_STABILITY_PRIVATE,
921*c5591576SRob Johnston 1
922*c5591576SRob Johnston };
923*c5591576SRob Johnston
924*c5591576SRob Johnston static int
add_props(topo_hdl_t * thp,topo_vertex_t * vtx,nvlist_t * pgroups)925*c5591576SRob Johnston add_props(topo_hdl_t *thp, topo_vertex_t *vtx, nvlist_t *pgroups)
926*c5591576SRob Johnston {
927*c5591576SRob Johnston tnode_t *tn;
928*c5591576SRob Johnston nvlist_t **pgs;
929*c5591576SRob Johnston uint_t npgs = 0;
930*c5591576SRob Johnston
931*c5591576SRob Johnston tn = topo_vertex_node(vtx);
932*c5591576SRob Johnston if (nvlist_lookup_nvlist_array(pgroups, TDG_XML_PGROUPS, &pgs,
933*c5591576SRob Johnston &npgs) != 0) {
934*c5591576SRob Johnston goto fail;
935*c5591576SRob Johnston }
936*c5591576SRob Johnston
937*c5591576SRob Johnston for (uint_t i = 0; i < npgs; i++) {
938*c5591576SRob Johnston char *pgname;
939*c5591576SRob Johnston nvlist_t **props;
940*c5591576SRob Johnston uint_t nprops;
941*c5591576SRob Johnston int err;
942*c5591576SRob Johnston
943*c5591576SRob Johnston if (nvlist_lookup_string(pgs[i], TDG_XML_PGROUP_NAME,
944*c5591576SRob Johnston &pgname) != 0 ||
945*c5591576SRob Johnston nvlist_lookup_nvlist_array(pgs[i], TDG_XML_PVALS, &props,
946*c5591576SRob Johnston &nprops) != 0) {
947*c5591576SRob Johnston goto fail;
948*c5591576SRob Johnston }
949*c5591576SRob Johnston pginfo.tpi_name = pgname;
950*c5591576SRob Johnston
951*c5591576SRob Johnston if (topo_pgroup_create(tn, &pginfo, &err) != 0) {
952*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "failed to create "
953*c5591576SRob Johnston "pgroup: %s", pgname);
954*c5591576SRob Johnston goto fail;
955*c5591576SRob Johnston }
956*c5591576SRob Johnston for (uint_t j = 0; j < nprops; j++) {
957*c5591576SRob Johnston if (topo_prop_setprop(tn, pgname, props[j],
958*c5591576SRob Johnston TOPO_PROP_IMMUTABLE, props[j], &err) != 0) {
959*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "failed to "
960*c5591576SRob Johnston "set properties in pgroup: %s", pgname);
961*c5591576SRob Johnston goto fail;
962*c5591576SRob Johnston }
963*c5591576SRob Johnston }
964*c5591576SRob Johnston }
965*c5591576SRob Johnston return (0);
966*c5591576SRob Johnston fail:
967*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "%s: error decoding properties for "
968*c5591576SRob Johnston "%s=%" PRIx64, __func__, topo_node_name(tn),
969*c5591576SRob Johnston topo_node_instance(tn));
970*c5591576SRob Johnston if (thp->th_debug & TOPO_DBG_XML)
971*c5591576SRob Johnston nvlist_print(stdout, pgroups);
972*c5591576SRob Johnston
973*c5591576SRob Johnston return (-1);
974*c5591576SRob Johnston }
975*c5591576SRob Johnston
976*c5591576SRob Johnston static void
free_nvlist_array(topo_hdl_t * thp,nvlist_t ** nvlarr,uint_t nelems)977*c5591576SRob Johnston free_nvlist_array(topo_hdl_t *thp, nvlist_t **nvlarr, uint_t nelems)
978*c5591576SRob Johnston {
979*c5591576SRob Johnston for (uint_t i = 0; i < nelems; i++) {
980*c5591576SRob Johnston if (nvlarr[i] != NULL)
981*c5591576SRob Johnston nvlist_free(nvlarr[i]);
982*c5591576SRob Johnston }
983*c5591576SRob Johnston topo_hdl_free(thp, nvlarr, nelems * sizeof (nvlist_t *));
984*c5591576SRob Johnston }
985*c5591576SRob Johnston
986*c5591576SRob Johnston static boolean_t
is_overflow(topo_hdl_t * thp,uint64_t val,uint_t nbits)987*c5591576SRob Johnston is_overflow(topo_hdl_t *thp, uint64_t val, uint_t nbits)
988*c5591576SRob Johnston {
989*c5591576SRob Johnston if ((val >> nbits) != 0) {
990*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "value exceeds %u bits", nbits);
991*c5591576SRob Johnston return (B_TRUE);
992*c5591576SRob Johnston }
993*c5591576SRob Johnston return (B_FALSE);
994*c5591576SRob Johnston }
995*c5591576SRob Johnston
996*c5591576SRob Johnston /*
997*c5591576SRob Johnston * Recursive function for parsing nvpair XML elements, which can contain
998*c5591576SRob Johnston * nested nvlist and nvpair elements.
999*c5591576SRob Johnston */
1000*c5591576SRob Johnston static int
deserialize_nvpair(topo_hdl_t * thp,topo_mod_t * mod,nvlist_t * nvl,xmlNodePtr xn)1001*c5591576SRob Johnston deserialize_nvpair(topo_hdl_t *thp, topo_mod_t *mod, nvlist_t *nvl,
1002*c5591576SRob Johnston xmlNodePtr xn)
1003*c5591576SRob Johnston {
1004*c5591576SRob Johnston int ret = -1;
1005*c5591576SRob Johnston xmlChar *name = NULL, *type = NULL, *sval = NULL;
1006*c5591576SRob Johnston uint64_t val;
1007*c5591576SRob Johnston
1008*c5591576SRob Johnston if ((name = xmlGetProp(xn, (xmlChar *)TDG_XML_NAME)) == NULL ||
1009*c5591576SRob Johnston (type = xmlGetProp(xn, (xmlChar *)TDG_XML_TYPE)) == NULL) {
1010*c5591576SRob Johnston goto fail;
1011*c5591576SRob Johnston }
1012*c5591576SRob Johnston
1013*c5591576SRob Johnston if (xmlStrcmp(type, (xmlChar *)TDG_XML_NVLIST) == 0) {
1014*c5591576SRob Johnston nvlist_t *cnvl = NULL;
1015*c5591576SRob Johnston
1016*c5591576SRob Johnston if (topo_hdl_nvalloc(thp, &cnvl, NV_UNIQUE_NAME) != 0) {
1017*c5591576SRob Johnston goto fail;
1018*c5591576SRob Johnston }
1019*c5591576SRob Johnston
1020*c5591576SRob Johnston for (xmlNodePtr cn = xn->xmlChildrenNode;
1021*c5591576SRob Johnston cn != NULL; cn = cn->next) {
1022*c5591576SRob Johnston
1023*c5591576SRob Johnston if (xmlStrcmp(cn->name, (xmlChar *)TDG_XML_NVLIST) != 0)
1024*c5591576SRob Johnston continue;
1025*c5591576SRob Johnston
1026*c5591576SRob Johnston for (xmlNodePtr gcn = cn->xmlChildrenNode;
1027*c5591576SRob Johnston gcn != NULL; gcn = gcn->next) {
1028*c5591576SRob Johnston
1029*c5591576SRob Johnston if (xmlStrcmp(gcn->name,
1030*c5591576SRob Johnston (xmlChar *)TDG_XML_NVPAIR) != 0)
1031*c5591576SRob Johnston continue;
1032*c5591576SRob Johnston if (deserialize_nvpair(thp, mod, cnvl, gcn) !=
1033*c5591576SRob Johnston 0) {
1034*c5591576SRob Johnston nvlist_free(cnvl);
1035*c5591576SRob Johnston goto fail;
1036*c5591576SRob Johnston }
1037*c5591576SRob Johnston }
1038*c5591576SRob Johnston if (nvlist_add_nvlist(nvl, (char *)name, cnvl) != 0) {
1039*c5591576SRob Johnston nvlist_free(cnvl);
1040*c5591576SRob Johnston goto fail;
1041*c5591576SRob Johnston }
1042*c5591576SRob Johnston nvlist_free(cnvl);
1043*c5591576SRob Johnston break;
1044*c5591576SRob Johnston }
1045*c5591576SRob Johnston } else if (xmlStrcmp(type, (xmlChar *)TDG_XML_INT8) == 0) {
1046*c5591576SRob Johnston if (xmlattr_to_int(mod, xn, TDG_XML_VALUE, &val) != 0 ||
1047*c5591576SRob Johnston is_overflow(thp, val, 8) ||
1048*c5591576SRob Johnston nvlist_add_int8(nvl, (char *)name, (int8_t)val) != 0) {
1049*c5591576SRob Johnston goto fail;
1050*c5591576SRob Johnston }
1051*c5591576SRob Johnston } else if (xmlStrcmp(type, (xmlChar *)TDG_XML_INT16) == 0) {
1052*c5591576SRob Johnston if (xmlattr_to_int(mod, xn, TDG_XML_VALUE, &val) != 0 ||
1053*c5591576SRob Johnston is_overflow(thp, val, 16) ||
1054*c5591576SRob Johnston nvlist_add_int16(nvl, (char *)name, (int16_t)val) != 0) {
1055*c5591576SRob Johnston goto fail;
1056*c5591576SRob Johnston }
1057*c5591576SRob Johnston } else if (xmlStrcmp(type, (xmlChar *)TDG_XML_INT32) == 0) {
1058*c5591576SRob Johnston if (xmlattr_to_int(mod, xn, TDG_XML_VALUE, &val) != 0 ||
1059*c5591576SRob Johnston is_overflow(thp, val, 32) ||
1060*c5591576SRob Johnston nvlist_add_int32(nvl, (char *)name, (int32_t)val) != 0) {
1061*c5591576SRob Johnston goto fail;
1062*c5591576SRob Johnston }
1063*c5591576SRob Johnston } else if (xmlStrcmp(type, (xmlChar *)TDG_XML_INT64) == 0) {
1064*c5591576SRob Johnston if (xmlattr_to_int(mod, xn, TDG_XML_VALUE, &val) != 0 ||
1065*c5591576SRob Johnston nvlist_add_int64(nvl, (char *)name, (int64_t)val) != 0) {
1066*c5591576SRob Johnston goto fail;
1067*c5591576SRob Johnston }
1068*c5591576SRob Johnston } else if (xmlStrcmp(type, (xmlChar *)TDG_XML_UINT8) == 0) {
1069*c5591576SRob Johnston if (xmlattr_to_int(mod, xn, TDG_XML_VALUE, &val) != 0 ||
1070*c5591576SRob Johnston is_overflow(thp, val, 8) ||
1071*c5591576SRob Johnston nvlist_add_uint8(nvl, (char *)name, (uint8_t)val) != 0) {
1072*c5591576SRob Johnston goto fail;
1073*c5591576SRob Johnston }
1074*c5591576SRob Johnston } else if (xmlStrcmp(type, (xmlChar *)TDG_XML_UINT16) == 0) {
1075*c5591576SRob Johnston if (xmlattr_to_int(mod, xn, TDG_XML_VALUE, &val) != 0 ||
1076*c5591576SRob Johnston is_overflow(thp, val, 16) ||
1077*c5591576SRob Johnston nvlist_add_uint16(nvl, (char *)name, (uint16_t)val) != 0) {
1078*c5591576SRob Johnston goto fail;
1079*c5591576SRob Johnston }
1080*c5591576SRob Johnston } else if (xmlStrcmp(type, (xmlChar *)TDG_XML_UINT32) == 0) {
1081*c5591576SRob Johnston if (xmlattr_to_int(mod, xn, TDG_XML_VALUE, &val) != 0 ||
1082*c5591576SRob Johnston is_overflow(thp, val, 32) ||
1083*c5591576SRob Johnston nvlist_add_uint32(nvl, (char *)name, (uint32_t)val) != 0) {
1084*c5591576SRob Johnston goto fail;
1085*c5591576SRob Johnston }
1086*c5591576SRob Johnston } else if (xmlStrcmp(type, (xmlChar *)TDG_XML_UINT64) == 0) {
1087*c5591576SRob Johnston if (xmlattr_to_int(mod, xn, TDG_XML_VALUE, &val) != 0 ||
1088*c5591576SRob Johnston nvlist_add_uint64(nvl, (char *)name, (uint64_t)val) != 0) {
1089*c5591576SRob Johnston goto fail;
1090*c5591576SRob Johnston }
1091*c5591576SRob Johnston } else if (xmlStrcmp(type, (xmlChar *)TDG_XML_STRING) == 0) {
1092*c5591576SRob Johnston if ((sval = xmlGetProp(xn, (xmlChar *)TDG_XML_VALUE)) == NULL ||
1093*c5591576SRob Johnston nvlist_add_string(nvl, (char *)name, (char *)sval) != 0) {
1094*c5591576SRob Johnston goto fail;
1095*c5591576SRob Johnston }
1096*c5591576SRob Johnston } else if (xmlStrcmp(type, (xmlChar *)TDG_XML_NVLIST_ARR) == 0) {
1097*c5591576SRob Johnston uint64_t nelem = 0;
1098*c5591576SRob Johnston nvlist_t **nvlarr = NULL;
1099*c5591576SRob Johnston uint_t i = 0;
1100*c5591576SRob Johnston xmlNodePtr cn = xn->xmlChildrenNode;
1101*c5591576SRob Johnston
1102*c5591576SRob Johnston /*
1103*c5591576SRob Johnston * Count the number of child nvlist elements
1104*c5591576SRob Johnston */
1105*c5591576SRob Johnston while (cn != NULL) {
1106*c5591576SRob Johnston if (xmlStrcmp(cn->name, (xmlChar *)TDG_XML_NVLIST) ==
1107*c5591576SRob Johnston 0) {
1108*c5591576SRob Johnston nelem++;
1109*c5591576SRob Johnston }
1110*c5591576SRob Johnston cn = cn->next;
1111*c5591576SRob Johnston }
1112*c5591576SRob Johnston
1113*c5591576SRob Johnston if ((nvlarr = topo_hdl_zalloc(thp,
1114*c5591576SRob Johnston (nelem * sizeof (nvlist_t *)))) == NULL) {
1115*c5591576SRob Johnston goto fail;
1116*c5591576SRob Johnston }
1117*c5591576SRob Johnston
1118*c5591576SRob Johnston for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1119*c5591576SRob Johnston if (xmlStrcmp(cn->name, (xmlChar *)TDG_XML_NVLIST) !=
1120*c5591576SRob Johnston 0)
1121*c5591576SRob Johnston continue;
1122*c5591576SRob Johnston
1123*c5591576SRob Johnston if (topo_hdl_nvalloc(thp, &nvlarr[i],
1124*c5591576SRob Johnston NV_UNIQUE_NAME) != 0) {
1125*c5591576SRob Johnston free_nvlist_array(thp, nvlarr, nelem);
1126*c5591576SRob Johnston goto fail;
1127*c5591576SRob Johnston }
1128*c5591576SRob Johnston
1129*c5591576SRob Johnston for (xmlNodePtr gcn = cn->xmlChildrenNode;
1130*c5591576SRob Johnston gcn != NULL; gcn = gcn->next) {
1131*c5591576SRob Johnston if (xmlStrcmp(gcn->name,
1132*c5591576SRob Johnston (xmlChar *)TDG_XML_NVPAIR) != 0)
1133*c5591576SRob Johnston continue;
1134*c5591576SRob Johnston if (deserialize_nvpair(thp, mod, nvlarr[i],
1135*c5591576SRob Johnston gcn) != 0) {
1136*c5591576SRob Johnston free_nvlist_array(thp, nvlarr, nelem);
1137*c5591576SRob Johnston goto fail;
1138*c5591576SRob Johnston }
1139*c5591576SRob Johnston }
1140*c5591576SRob Johnston i++;
1141*c5591576SRob Johnston }
1142*c5591576SRob Johnston if (nvlist_add_nvlist_array(nvl, (char *)name, nvlarr,
1143*c5591576SRob Johnston nelem) != 0) {
1144*c5591576SRob Johnston free_nvlist_array(thp, nvlarr, nelem);
1145*c5591576SRob Johnston goto fail;
1146*c5591576SRob Johnston }
1147*c5591576SRob Johnston free_nvlist_array(thp, nvlarr, nelem);
1148*c5591576SRob Johnston } else if (xmlStrcmp(type, (xmlChar *)TDG_XML_UINT32_ARR) == 0) {
1149*c5591576SRob Johnston uint64_t nelem = 0;
1150*c5591576SRob Johnston uint32_t *arr = NULL;
1151*c5591576SRob Johnston uint_t i = 0;
1152*c5591576SRob Johnston xmlNodePtr cn = xn->xmlChildrenNode;
1153*c5591576SRob Johnston
1154*c5591576SRob Johnston /*
1155*c5591576SRob Johnston * Count the number of child nvpair elements
1156*c5591576SRob Johnston */
1157*c5591576SRob Johnston while (cn != NULL) {
1158*c5591576SRob Johnston if (xmlStrcmp(cn->name, (xmlChar *)TDG_XML_NVPAIR) ==
1159*c5591576SRob Johnston 0) {
1160*c5591576SRob Johnston nelem++;
1161*c5591576SRob Johnston }
1162*c5591576SRob Johnston cn = cn->next;
1163*c5591576SRob Johnston }
1164*c5591576SRob Johnston
1165*c5591576SRob Johnston if ((arr = topo_hdl_zalloc(thp,
1166*c5591576SRob Johnston (nelem * sizeof (uint32_t)))) == NULL) {
1167*c5591576SRob Johnston goto fail;
1168*c5591576SRob Johnston }
1169*c5591576SRob Johnston
1170*c5591576SRob Johnston for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1171*c5591576SRob Johnston if (xmlStrcmp(cn->name, (xmlChar *)TDG_XML_NVPAIR) != 0)
1172*c5591576SRob Johnston continue;
1173*c5591576SRob Johnston
1174*c5591576SRob Johnston if (xmlattr_to_int(mod, cn, TDG_XML_VALUE, &val) != 0) {
1175*c5591576SRob Johnston topo_hdl_free(thp, arr,
1176*c5591576SRob Johnston (nelem * sizeof (uint32_t)));
1177*c5591576SRob Johnston goto fail;
1178*c5591576SRob Johnston }
1179*c5591576SRob Johnston
1180*c5591576SRob Johnston arr[i] = val;
1181*c5591576SRob Johnston i++;
1182*c5591576SRob Johnston }
1183*c5591576SRob Johnston if (nvlist_add_uint32_array(nvl, (char *)name, arr,
1184*c5591576SRob Johnston nelem) != 0) {
1185*c5591576SRob Johnston topo_hdl_free(thp, arr, (nelem * sizeof (uint32_t)));
1186*c5591576SRob Johnston goto fail;
1187*c5591576SRob Johnston }
1188*c5591576SRob Johnston topo_hdl_free(thp, arr, (nelem * sizeof (uint32_t)));
1189*c5591576SRob Johnston } else if (xmlStrcmp(type, (xmlChar *)TDG_XML_INT32_ARR) == 0) {
1190*c5591576SRob Johnston uint64_t nelem = 0;
1191*c5591576SRob Johnston int32_t *arr = NULL;
1192*c5591576SRob Johnston uint_t i = 0;
1193*c5591576SRob Johnston xmlNodePtr cn = xn->xmlChildrenNode;
1194*c5591576SRob Johnston
1195*c5591576SRob Johnston /*
1196*c5591576SRob Johnston * Count the number of child nvpair elements
1197*c5591576SRob Johnston */
1198*c5591576SRob Johnston while (cn != NULL) {
1199*c5591576SRob Johnston if (xmlStrcmp(cn->name, (xmlChar *)TDG_XML_NVPAIR) ==
1200*c5591576SRob Johnston 0) {
1201*c5591576SRob Johnston nelem++;
1202*c5591576SRob Johnston }
1203*c5591576SRob Johnston cn = cn->next;
1204*c5591576SRob Johnston }
1205*c5591576SRob Johnston
1206*c5591576SRob Johnston if ((arr = topo_hdl_zalloc(thp,
1207*c5591576SRob Johnston (nelem * sizeof (int32_t)))) == NULL) {
1208*c5591576SRob Johnston goto fail;
1209*c5591576SRob Johnston }
1210*c5591576SRob Johnston
1211*c5591576SRob Johnston for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1212*c5591576SRob Johnston if (xmlStrcmp(cn->name, (xmlChar *)TDG_XML_NVPAIR) != 0)
1213*c5591576SRob Johnston continue;
1214*c5591576SRob Johnston
1215*c5591576SRob Johnston if (xmlattr_to_int(mod, cn, TDG_XML_VALUE, &val) != 0) {
1216*c5591576SRob Johnston topo_hdl_free(thp, arr,
1217*c5591576SRob Johnston (nelem * sizeof (int32_t)));
1218*c5591576SRob Johnston goto fail;
1219*c5591576SRob Johnston }
1220*c5591576SRob Johnston
1221*c5591576SRob Johnston arr[i] = val;
1222*c5591576SRob Johnston i++;
1223*c5591576SRob Johnston }
1224*c5591576SRob Johnston if (nvlist_add_int32_array(nvl, (char *)name, arr,
1225*c5591576SRob Johnston nelem) != 0) {
1226*c5591576SRob Johnston topo_hdl_free(thp, arr, (nelem * sizeof (int32_t)));
1227*c5591576SRob Johnston goto fail;
1228*c5591576SRob Johnston }
1229*c5591576SRob Johnston topo_hdl_free(thp, arr, (nelem * sizeof (int32_t)));
1230*c5591576SRob Johnston } else if (xmlStrcmp(type, (xmlChar *)TDG_XML_UINT64_ARR) == 0) {
1231*c5591576SRob Johnston uint64_t nelem = 0, *arr = NULL;
1232*c5591576SRob Johnston uint_t i = 0;
1233*c5591576SRob Johnston xmlNodePtr cn = xn->xmlChildrenNode;
1234*c5591576SRob Johnston
1235*c5591576SRob Johnston /*
1236*c5591576SRob Johnston * Count the number of child nvpair elements
1237*c5591576SRob Johnston */
1238*c5591576SRob Johnston while (cn != NULL) {
1239*c5591576SRob Johnston if (xmlStrcmp(cn->name, (xmlChar *)TDG_XML_NVPAIR) ==
1240*c5591576SRob Johnston 0) {
1241*c5591576SRob Johnston nelem++;
1242*c5591576SRob Johnston }
1243*c5591576SRob Johnston cn = cn->next;
1244*c5591576SRob Johnston }
1245*c5591576SRob Johnston
1246*c5591576SRob Johnston if ((arr = topo_hdl_zalloc(thp,
1247*c5591576SRob Johnston (nelem * sizeof (uint64_t)))) == NULL) {
1248*c5591576SRob Johnston goto fail;
1249*c5591576SRob Johnston }
1250*c5591576SRob Johnston
1251*c5591576SRob Johnston for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1252*c5591576SRob Johnston if (xmlStrcmp(cn->name, (xmlChar *)TDG_XML_NVPAIR) != 0)
1253*c5591576SRob Johnston continue;
1254*c5591576SRob Johnston
1255*c5591576SRob Johnston if (xmlattr_to_int(mod, cn, TDG_XML_VALUE, &val) != 0) {
1256*c5591576SRob Johnston topo_hdl_free(thp, arr,
1257*c5591576SRob Johnston (nelem * sizeof (uint64_t)));
1258*c5591576SRob Johnston goto fail;
1259*c5591576SRob Johnston }
1260*c5591576SRob Johnston
1261*c5591576SRob Johnston arr[i] = val;
1262*c5591576SRob Johnston i++;
1263*c5591576SRob Johnston }
1264*c5591576SRob Johnston if (nvlist_add_uint64_array(nvl, (char *)name, arr,
1265*c5591576SRob Johnston nelem) != 0) {
1266*c5591576SRob Johnston topo_hdl_free(thp, arr, (nelem * sizeof (uint64_t)));
1267*c5591576SRob Johnston goto fail;
1268*c5591576SRob Johnston }
1269*c5591576SRob Johnston topo_hdl_free(thp, arr, (nelem * sizeof (uint64_t)));
1270*c5591576SRob Johnston } else if (xmlStrcmp(type, (xmlChar *)TDG_XML_INT64_ARR) == 0) {
1271*c5591576SRob Johnston uint64_t nelem = 0;
1272*c5591576SRob Johnston int64_t *arr = NULL;
1273*c5591576SRob Johnston uint_t i = 0;
1274*c5591576SRob Johnston xmlNodePtr cn = xn->xmlChildrenNode;
1275*c5591576SRob Johnston
1276*c5591576SRob Johnston /*
1277*c5591576SRob Johnston * Count the number of child nvpair elements
1278*c5591576SRob Johnston */
1279*c5591576SRob Johnston while (cn != NULL) {
1280*c5591576SRob Johnston if (xmlStrcmp(cn->name, (xmlChar *)TDG_XML_NVPAIR) ==
1281*c5591576SRob Johnston 0) {
1282*c5591576SRob Johnston nelem++;
1283*c5591576SRob Johnston }
1284*c5591576SRob Johnston cn = cn->next;
1285*c5591576SRob Johnston }
1286*c5591576SRob Johnston
1287*c5591576SRob Johnston if ((arr = topo_hdl_zalloc(thp,
1288*c5591576SRob Johnston (nelem * sizeof (int64_t)))) == NULL) {
1289*c5591576SRob Johnston goto fail;
1290*c5591576SRob Johnston }
1291*c5591576SRob Johnston
1292*c5591576SRob Johnston for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1293*c5591576SRob Johnston if (xmlStrcmp(cn->name, (xmlChar *)TDG_XML_NVPAIR) != 0)
1294*c5591576SRob Johnston continue;
1295*c5591576SRob Johnston
1296*c5591576SRob Johnston if (xmlattr_to_int(mod, cn, TDG_XML_VALUE, &val) != 0) {
1297*c5591576SRob Johnston topo_hdl_free(thp, arr,
1298*c5591576SRob Johnston (nelem * sizeof (int64_t)));
1299*c5591576SRob Johnston goto fail;
1300*c5591576SRob Johnston }
1301*c5591576SRob Johnston
1302*c5591576SRob Johnston arr[i] = val;
1303*c5591576SRob Johnston i++;
1304*c5591576SRob Johnston }
1305*c5591576SRob Johnston if (nvlist_add_int64_array(nvl, (char *)name, arr,
1306*c5591576SRob Johnston nelem) != 0) {
1307*c5591576SRob Johnston topo_hdl_free(thp, arr, (nelem * sizeof (int64_t)));
1308*c5591576SRob Johnston goto fail;
1309*c5591576SRob Johnston }
1310*c5591576SRob Johnston topo_hdl_free(thp, arr, (nelem * sizeof (int64_t)));
1311*c5591576SRob Johnston }
1312*c5591576SRob Johnston ret = 0;
1313*c5591576SRob Johnston fail:
1314*c5591576SRob Johnston if (ret != 0) {
1315*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "%s: error parsing %s "
1316*c5591576SRob Johnston "element: name: %s, type: %s, nvl: %p", __func__, xn->name,
1317*c5591576SRob Johnston (name != NULL) ? (char *)name : "MISSING!",
1318*c5591576SRob Johnston (type != NULL) ? (char *)type : "MISSING!", nvl);
1319*c5591576SRob Johnston dump_xml_node(thp, xn);
1320*c5591576SRob Johnston }
1321*c5591576SRob Johnston if (name != NULL)
1322*c5591576SRob Johnston xmlFree(name);
1323*c5591576SRob Johnston if (type != NULL)
1324*c5591576SRob Johnston xmlFree(type);
1325*c5591576SRob Johnston if (sval != NULL)
1326*c5591576SRob Johnston xmlFree(sval);
1327*c5591576SRob Johnston
1328*c5591576SRob Johnston return (ret);
1329*c5591576SRob Johnston }
1330*c5591576SRob Johnston
1331*c5591576SRob Johnston static int
deserialize_vertex(topo_hdl_t * thp,topo_mod_t * mod,topo_digraph_t * tdg,xmlNodePtr xn)1332*c5591576SRob Johnston deserialize_vertex(topo_hdl_t *thp, topo_mod_t *mod, topo_digraph_t *tdg,
1333*c5591576SRob Johnston xmlNodePtr xn)
1334*c5591576SRob Johnston {
1335*c5591576SRob Johnston int ret = -1;
1336*c5591576SRob Johnston topo_vertex_t *vtx = NULL;
1337*c5591576SRob Johnston nvlist_t *props = NULL;
1338*c5591576SRob Johnston xmlChar *name = NULL, *fmri = NULL;
1339*c5591576SRob Johnston uint64_t inst;
1340*c5591576SRob Johnston
1341*c5591576SRob Johnston if ((name = xmlGetProp(xn, (xmlChar *)TDG_XML_NAME)) == NULL ||
1342*c5591576SRob Johnston (fmri = xmlGetProp(xn, (xmlChar *)TDG_XML_FMRI)) == NULL ||
1343*c5591576SRob Johnston xmlattr_to_int(mod, xn, TDG_XML_INSTANCE, &inst) != 0) {
1344*c5591576SRob Johnston goto fail;
1345*c5591576SRob Johnston }
1346*c5591576SRob Johnston
1347*c5591576SRob Johnston if ((vtx = topo_vertex_new(mod, (char *)name, inst)) == NULL) {
1348*c5591576SRob Johnston goto fail;
1349*c5591576SRob Johnston }
1350*c5591576SRob Johnston
1351*c5591576SRob Johnston for (xmlNodePtr cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1352*c5591576SRob Johnston if (xmlStrcmp(cn->name, (xmlChar *)TDG_XML_NVPAIR) == 0) {
1353*c5591576SRob Johnston if (topo_hdl_nvalloc(thp, &props, NV_UNIQUE_NAME) != 0)
1354*c5591576SRob Johnston goto fail;
1355*c5591576SRob Johnston if (deserialize_nvpair(thp, mod, props, cn) != 0 ||
1356*c5591576SRob Johnston add_props(thp, vtx, props) != 0)
1357*c5591576SRob Johnston goto fail;
1358*c5591576SRob Johnston }
1359*c5591576SRob Johnston }
1360*c5591576SRob Johnston ret = 0;
1361*c5591576SRob Johnston
1362*c5591576SRob Johnston fail:
1363*c5591576SRob Johnston if (ret != 0) {
1364*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "%s: error parsing %s element",
1365*c5591576SRob Johnston __func__, TDG_XML_VERTEX);
1366*c5591576SRob Johnston dump_xml_node(thp, xn);
1367*c5591576SRob Johnston }
1368*c5591576SRob Johnston nvlist_free(props);
1369*c5591576SRob Johnston if (name != NULL)
1370*c5591576SRob Johnston xmlFree(name);
1371*c5591576SRob Johnston if (fmri != NULL)
1372*c5591576SRob Johnston xmlFree(fmri);
1373*c5591576SRob Johnston
1374*c5591576SRob Johnston return (ret);
1375*c5591576SRob Johnston }
1376*c5591576SRob Johnston
1377*c5591576SRob Johnston /*
1378*c5591576SRob Johnston * This function takes a buffer containing XML data describing a directed graph
1379*c5591576SRob Johnston * topology. This data is parsed to the original directed graph is rehydrated.
1380*c5591576SRob Johnston *
1381*c5591576SRob Johnston * On success, a pointer to a topo_digraph_t representing the graph is
1382*c5591576SRob Johnston * returned. The caller is responsible for destroying the graph via a call to
1383*c5591576SRob Johnston * topo_digraph_destroy()
1384*c5591576SRob Johnston *
1385*c5591576SRob Johnston * On failure, NULL is returned.
1386*c5591576SRob Johnston */
1387*c5591576SRob Johnston topo_digraph_t *
topo_digraph_deserialize(topo_hdl_t * thp,const char * xml,size_t sz)1388*c5591576SRob Johnston topo_digraph_deserialize(topo_hdl_t *thp, const char *xml, size_t sz)
1389*c5591576SRob Johnston {
1390*c5591576SRob Johnston xmlDocPtr doc;
1391*c5591576SRob Johnston xmlDtdPtr dtd = NULL;
1392*c5591576SRob Johnston xmlNodePtr root, vertices;
1393*c5591576SRob Johnston xmlChar *scheme = NULL;
1394*c5591576SRob Johnston topo_mod_t *mod;
1395*c5591576SRob Johnston topo_digraph_t *tdg, *ret = NULL;
1396*c5591576SRob Johnston
1397*c5591576SRob Johnston if ((doc = xmlReadMemory(xml, sz, "", NULL, 0)) == NULL) {
1398*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "Failed to parse XML");
1399*c5591576SRob Johnston goto fail;
1400*c5591576SRob Johnston }
1401*c5591576SRob Johnston
1402*c5591576SRob Johnston /*
1403*c5591576SRob Johnston * As a sanity check, extract the DTD from the XML and verify it
1404*c5591576SRob Johnston * matches the DTD for a digraph topology.
1405*c5591576SRob Johnston */
1406*c5591576SRob Johnston if ((dtd = xmlGetIntSubset(doc)) == NULL) {
1407*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "document has no DTD.\n");
1408*c5591576SRob Johnston goto fail;
1409*c5591576SRob Johnston }
1410*c5591576SRob Johnston
1411*c5591576SRob Johnston if (strcmp((const char *)dtd->SystemID, TDG_DTD) != 0) {
1412*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "unexpected DTD: %s",
1413*c5591576SRob Johnston dtd->SystemID);
1414*c5591576SRob Johnston goto fail;
1415*c5591576SRob Johnston }
1416*c5591576SRob Johnston
1417*c5591576SRob Johnston /*
1418*c5591576SRob Johnston * Verify the root element is what we're expecting and then grab the
1419*c5591576SRob Johnston * FMRI scheme from its attributes.
1420*c5591576SRob Johnston */
1421*c5591576SRob Johnston if ((root = xmlDocGetRootElement(doc)) == NULL) {
1422*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "document is empty.\n");
1423*c5591576SRob Johnston goto fail;
1424*c5591576SRob Johnston }
1425*c5591576SRob Johnston
1426*c5591576SRob Johnston if (xmlStrcmp(root->name, (xmlChar *)TDG_XML_TOPO_DIGRAPH) != 0 ||
1427*c5591576SRob Johnston (scheme = xmlGetProp(root, (xmlChar *)TDG_XML_SCHEME)) ==
1428*c5591576SRob Johnston NULL) {
1429*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML,
1430*c5591576SRob Johnston "failed to parse %s element", TDG_XML_TOPO_DIGRAPH);
1431*c5591576SRob Johnston goto fail;
1432*c5591576SRob Johnston }
1433*c5591576SRob Johnston
1434*c5591576SRob Johnston /*
1435*c5591576SRob Johnston * Load the topo module associated with this FMRI scheme.
1436*c5591576SRob Johnston */
1437*c5591576SRob Johnston if ((mod = topo_mod_lookup(thp, (const char *)scheme, 1)) == NULL) {
1438*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "failed to load %s module",
1439*c5591576SRob Johnston scheme);
1440*c5591576SRob Johnston goto fail;
1441*c5591576SRob Johnston }
1442*c5591576SRob Johnston /*
1443*c5591576SRob Johnston * If we have a builtin module for this scheme, then there will
1444*c5591576SRob Johnston * already be an empty digraph attached to the handle. Otherwise,
1445*c5591576SRob Johnston * create a new empty digraph and attach it to the handle.
1446*c5591576SRob Johnston */
1447*c5591576SRob Johnston tdg = topo_digraph_get(mod->tm_hdl, mod->tm_info->tmi_scheme);
1448*c5591576SRob Johnston if (tdg == NULL) {
1449*c5591576SRob Johnston if ((tdg = topo_digraph_new(thp, mod, (const char *)scheme)) ==
1450*c5591576SRob Johnston NULL) {
1451*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "failed to create new "
1452*c5591576SRob Johnston "digraph");
1453*c5591576SRob Johnston goto fail;
1454*c5591576SRob Johnston } else {
1455*c5591576SRob Johnston topo_list_append(&thp->th_digraphs, tdg);
1456*c5591576SRob Johnston }
1457*c5591576SRob Johnston }
1458*c5591576SRob Johnston
1459*c5591576SRob Johnston /*
1460*c5591576SRob Johnston * Iterate through the vertex XML elements to reconstruct the graph
1461*c5591576SRob Johnston */
1462*c5591576SRob Johnston vertices = get_child_by_name(root, (xmlChar *)TDG_XML_VERTICES);
1463*c5591576SRob Johnston if (vertices == NULL ||
1464*c5591576SRob Johnston xmlStrcmp(vertices->name, (xmlChar *)TDG_XML_VERTICES) != 0) {
1465*c5591576SRob Johnston topo_dprintf(thp, TOPO_DBG_XML, "failed to parse %s element",
1466*c5591576SRob Johnston TDG_XML_VERTICES);
1467*c5591576SRob Johnston dump_xml_node(thp, root);
1468*c5591576SRob Johnston goto fail;
1469*c5591576SRob Johnston }
1470*c5591576SRob Johnston
1471*c5591576SRob Johnston for (xmlNodePtr xn = vertices->xmlChildrenNode; xn != NULL;
1472*c5591576SRob Johnston xn = xn->next) {
1473*c5591576SRob Johnston if (xmlStrcmp(xn->name, (xmlChar *)TDG_XML_VERTEX) != 0)
1474*c5591576SRob Johnston continue;
1475*c5591576SRob Johnston if (deserialize_vertex(thp, mod, tdg, xn) != 0)
1476*c5591576SRob Johnston goto fail;
1477*c5591576SRob Johnston }
1478*c5591576SRob Johnston
1479*c5591576SRob Johnston /*
1480*c5591576SRob Johnston * Now that all of the vertices have been created, go back through
1481*c5591576SRob Johnston * the vertex XML elements and add the edges.
1482*c5591576SRob Johnston */
1483*c5591576SRob Johnston for (xmlNodePtr xn = vertices->xmlChildrenNode; xn != NULL;
1484*c5591576SRob Johnston xn = xn->next) {
1485*c5591576SRob Johnston if (xmlStrcmp(xn->name, (xmlChar *)TDG_XML_VERTEX) != 0)
1486*c5591576SRob Johnston continue;
1487*c5591576SRob Johnston if (add_edges(thp, mod, tdg, xn) != 0)
1488*c5591576SRob Johnston goto fail;
1489*c5591576SRob Johnston }
1490*c5591576SRob Johnston
1491*c5591576SRob Johnston ret = tdg;
1492*c5591576SRob Johnston
1493*c5591576SRob Johnston fail:
1494*c5591576SRob Johnston if (scheme != NULL)
1495*c5591576SRob Johnston xmlFree(scheme);
1496*c5591576SRob Johnston
1497*c5591576SRob Johnston if (doc != NULL)
1498*c5591576SRob Johnston xmlFreeDoc(doc);
1499*c5591576SRob Johnston
1500*c5591576SRob Johnston (void) topo_hdl_seterrno(thp, ETOPO_MOD_XENUM);
1501*c5591576SRob Johnston return (ret);
1502*c5591576SRob Johnston }
1503