Print this page
patch tsoome-feedback
6659 nvlist_free(NULL) is a no-op
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/fm/topo/libtopo/common/topo_xml.c
+++ new/usr/src/lib/fm/topo/libtopo/common/topo_xml.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
25 25 */
26 26
27 27 #include <libxml/parser.h>
28 28 #include <libxml/xinclude.h>
29 29 #include <sys/fm/protocol.h>
30 30 #include <assert.h>
31 31 #include <string.h>
32 32 #include <strings.h>
33 33 #include <ctype.h>
34 34 #include <errno.h>
35 35 #include <limits.h>
36 36 #include <fm/libtopo.h>
37 37 #include <unistd.h>
38 38 #include <sys/stat.h>
39 39 #include <fcntl.h>
40 40 #include <topo_file.h>
41 41 #include <topo_mod.h>
42 42 #include <topo_subr.h>
43 43 #include <topo_alloc.h>
44 44 #include <topo_parse.h>
45 45 #include <topo_error.h>
46 46
47 47 static tf_rdata_t *topo_xml_walk(topo_mod_t *, tf_info_t *, xmlNodePtr,
48 48 tnode_t *);
49 49 static tf_edata_t *enum_attributes_process(topo_mod_t *, xmlNodePtr);
50 50 static int enum_run(topo_mod_t *, tf_rdata_t *);
51 51 static int fac_enum_run(topo_mod_t *, tnode_t *, const char *);
52 52 static int fac_process(topo_mod_t *, xmlNodePtr, tf_rdata_t *, tnode_t *);
53 53 static int fac_enum_process(topo_mod_t *, xmlNodePtr, tnode_t *);
54 54 static int decorate_nodes(topo_mod_t *, tf_rdata_t *, xmlNodePtr, tnode_t *,
55 55 tf_pad_t **);
56 56
57 57
58 58 static void
59 59 strarr_free(topo_mod_t *mod, char **arr, uint_t nelems)
60 60 {
61 61 int i;
62 62
63 63 for (i = 0; i < nelems; i++)
64 64 topo_mod_strfree(mod, arr[i]);
65 65 topo_mod_free(mod, arr, (nelems * sizeof (char *)));
66 66 }
67 67
68 68 int
69 69 xmlattr_to_stab(topo_mod_t *mp, xmlNodePtr n, const char *stabname,
70 70 topo_stability_t *rs)
71 71 {
72 72 xmlChar *str;
73 73 int rv = 0;
74 74
75 75 if (n == NULL) {
76 76 /* If there is no Stability defined, we default to private */
77 77 *rs = TOPO_STABILITY_PRIVATE;
78 78 return (0);
79 79 }
80 80 if ((str = xmlGetProp(n, (xmlChar *)stabname)) == NULL) {
81 81 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
82 82 "attribute to stability:\n");
83 83 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
84 84 }
85 85
86 86 if (xmlStrcmp(str, (xmlChar *)Internal) == 0) {
87 87 *rs = TOPO_STABILITY_INTERNAL;
88 88 } else if (xmlStrcmp(str, (xmlChar *)Private) == 0) {
89 89 *rs = TOPO_STABILITY_PRIVATE;
90 90 } else if (xmlStrcmp(str, (xmlChar *)Obsolete) == 0) {
91 91 *rs = TOPO_STABILITY_OBSOLETE;
92 92 } else if (xmlStrcmp(str, (xmlChar *)External) == 0) {
93 93 *rs = TOPO_STABILITY_EXTERNAL;
94 94 } else if (xmlStrcmp(str, (xmlChar *)Unstable) == 0) {
95 95 *rs = TOPO_STABILITY_UNSTABLE;
96 96 } else if (xmlStrcmp(str, (xmlChar *)Evolving) == 0) {
97 97 *rs = TOPO_STABILITY_EVOLVING;
98 98 } else if (xmlStrcmp(str, (xmlChar *)Stable) == 0) {
99 99 *rs = TOPO_STABILITY_STABLE;
100 100 } else if (xmlStrcmp(str, (xmlChar *)Standard) == 0) {
101 101 *rs = TOPO_STABILITY_STANDARD;
102 102 } else {
103 103 xmlFree(str);
104 104 return (topo_mod_seterrno(mp, ETOPO_PRSR_BADSTAB));
105 105 }
106 106 xmlFree(str);
107 107 return (rv);
108 108 }
109 109
110 110 int
111 111 xmlattr_to_int(topo_mod_t *mp,
112 112 xmlNodePtr n, const char *propname, uint64_t *value)
113 113 {
114 114 xmlChar *str;
115 115 xmlChar *estr;
116 116
117 117 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xmlattr_to_int(propname=%s)\n",
118 118 propname);
119 119 if ((str = xmlGetProp(n, (xmlChar *)propname)) == NULL)
120 120 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
121 121 *value = strtoull((char *)str, (char **)&estr, 10);
122 122 if (estr == str) {
123 123 /* no conversion was done */
124 124 xmlFree(str);
125 125 return (topo_mod_seterrno(mp, ETOPO_PRSR_BADNUM));
126 126 }
127 127 xmlFree(str);
128 128 return (0);
129 129 }
130 130
131 131 static int
132 132 xmlattr_to_fmri(topo_mod_t *mp,
133 133 xmlNodePtr xn, const char *propname, nvlist_t **rnvl)
134 134 {
135 135 xmlChar *str;
136 136
137 137 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xmlattr_to_fmri(propname=%s)\n",
138 138 propname);
139 139 if ((str = xmlGetProp(xn, (xmlChar *)propname)) == NULL)
140 140 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
141 141 if (topo_mod_str2nvl(mp, (const char *)str, rnvl) < 0) {
142 142 xmlFree(str);
143 143 return (-1);
144 144 }
145 145 xmlFree(str);
146 146 return (0);
147 147 }
148 148
149 149 static topo_type_t
150 150 xmlattr_to_type(topo_mod_t *mp, xmlNodePtr xn, xmlChar *attr)
151 151 {
152 152 topo_type_t rv;
153 153 xmlChar *str;
154 154 if ((str = xmlGetProp(xn, (xmlChar *)attr)) == NULL) {
155 155 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "%s attribute missing",
156 156 attr);
157 157 (void) topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
158 158 return (TOPO_TYPE_INVALID);
159 159 }
160 160 if (xmlStrcmp(str, (xmlChar *)Int32) == 0) {
161 161 rv = TOPO_TYPE_INT32;
162 162 } else if (xmlStrcmp(str, (xmlChar *)UInt32) == 0) {
163 163 rv = TOPO_TYPE_UINT32;
164 164 } else if (xmlStrcmp(str, (xmlChar *)Int64) == 0) {
165 165 rv = TOPO_TYPE_INT64;
166 166 } else if (xmlStrcmp(str, (xmlChar *)UInt64) == 0) {
167 167 rv = TOPO_TYPE_UINT64;
168 168 } else if (xmlStrcmp(str, (xmlChar *)FMRI) == 0) {
169 169 rv = TOPO_TYPE_FMRI;
170 170 } else if (xmlStrcmp(str, (xmlChar *)String) == 0) {
171 171 rv = TOPO_TYPE_STRING;
172 172 } else if (xmlStrcmp(str, (xmlChar *)Int32_Arr) == 0) {
173 173 rv = TOPO_TYPE_INT32_ARRAY;
174 174 } else if (xmlStrcmp(str, (xmlChar *)UInt32_Arr) == 0) {
175 175 rv = TOPO_TYPE_UINT32_ARRAY;
176 176 } else if (xmlStrcmp(str, (xmlChar *)Int64_Arr) == 0) {
177 177 rv = TOPO_TYPE_INT64_ARRAY;
178 178 } else if (xmlStrcmp(str, (xmlChar *)UInt64_Arr) == 0) {
179 179 rv = TOPO_TYPE_UINT64_ARRAY;
180 180 } else if (xmlStrcmp(str, (xmlChar *)String_Arr) == 0) {
181 181 rv = TOPO_TYPE_STRING_ARRAY;
182 182 } else if (xmlStrcmp(str, (xmlChar *)FMRI_Arr) == 0) {
183 183 rv = TOPO_TYPE_FMRI_ARRAY;
184 184 } else {
185 185 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
186 186 "Unrecognized type attribute value '%s'.\n", str);
187 187 (void) topo_mod_seterrno(mp, ETOPO_PRSR_BADTYPE);
188 188 xmlFree(str);
189 189 return (TOPO_TYPE_INVALID);
190 190 }
191 191 xmlFree(str);
192 192 return (rv);
193 193 }
194 194
195 195 static int
196 196 xlate_common(topo_mod_t *mp, xmlNodePtr xn, topo_type_t ptype, nvlist_t *nvl,
197 197 const char *name)
198 198 {
199 199 int rv;
200 200 uint64_t ui;
201 201 uint_t i = 0, nelems = 0;
202 202 nvlist_t *fmri;
203 203 xmlChar *str;
204 204 char **strarrbuf;
205 205 void *arrbuf;
206 206 nvlist_t **nvlarrbuf;
207 207 xmlNodePtr cn;
208 208
209 209 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xlate_common(name=%s)\n", name);
210 210 switch (ptype) {
211 211 case TOPO_TYPE_INT32:
212 212 if (xmlattr_to_int(mp, xn, Value, &ui) < 0)
213 213 return (-1);
214 214 rv = nvlist_add_int32(nvl, name, (int32_t)ui);
215 215 break;
216 216 case TOPO_TYPE_UINT32:
217 217 if (xmlattr_to_int(mp, xn, Value, &ui) < 0)
218 218 return (-1);
219 219 rv = nvlist_add_uint32(nvl, name, (uint32_t)ui);
220 220 break;
221 221 case TOPO_TYPE_INT64:
222 222 if (xmlattr_to_int(mp, xn, Value, &ui) < 0)
223 223 return (-1);
224 224 rv = nvlist_add_int64(nvl, name, (int64_t)ui);
225 225 break;
226 226 case TOPO_TYPE_UINT64:
227 227 if (xmlattr_to_int(mp, xn, Value, &ui) < 0)
228 228 return (-1);
229 229 rv = nvlist_add_uint64(nvl, name, ui);
230 230 break;
231 231 case TOPO_TYPE_FMRI:
232 232 if (xmlattr_to_fmri(mp, xn, Value, &fmri) < 0)
233 233 return (-1);
234 234 rv = nvlist_add_nvlist(nvl, name, fmri);
235 235 nvlist_free(fmri);
236 236 break;
237 237 case TOPO_TYPE_STRING:
238 238 if ((str = xmlGetProp(xn, (xmlChar *)Value)) == NULL)
239 239 return (-1);
240 240 rv = nvlist_add_string(nvl, name, (char *)str);
241 241 xmlFree(str);
242 242 break;
243 243 case TOPO_TYPE_INT32_ARRAY:
244 244 case TOPO_TYPE_UINT32_ARRAY:
245 245 case TOPO_TYPE_INT64_ARRAY:
246 246 case TOPO_TYPE_UINT64_ARRAY:
247 247 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next)
248 248 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
249 249 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0))
250 250 nelems++;
251 251
252 252 if (nelems < 1) {
253 253 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "No <propitem> "
254 254 "or <argitem> elements found for array val");
255 255 return (-1);
256 256 }
257 257 if ((arrbuf = topo_mod_alloc(mp, (nelems * sizeof (uint64_t))))
258 258 == NULL)
259 259 return (topo_mod_seterrno(mp, ETOPO_NOMEM));
260 260 break;
261 261 case TOPO_TYPE_STRING_ARRAY:
262 262 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next)
263 263 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
264 264 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0))
265 265 nelems++;
266 266
267 267 if (nelems < 1) {
268 268 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "No <propitem> "
269 269 "or <argitem> elements found for array val");
270 270 return (-1);
271 271 }
272 272 if ((strarrbuf = topo_mod_alloc(mp, (nelems * sizeof (char *))))
273 273 == NULL)
274 274 return (topo_mod_seterrno(mp, ETOPO_NOMEM));
275 275 break;
276 276 case TOPO_TYPE_FMRI_ARRAY:
277 277 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next)
278 278 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
279 279 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0))
280 280 nelems++;
281 281
282 282 if (nelems < 1) {
283 283 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "No <propitem> "
284 284 "elements found for array prop");
285 285 return (-1);
286 286 }
287 287 if ((nvlarrbuf = topo_mod_alloc(mp, (nelems *
288 288 sizeof (nvlist_t *)))) == NULL)
289 289 return (topo_mod_seterrno(mp, ETOPO_NOMEM));
290 290 break;
291 291 default:
292 292 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
293 293 "Unrecognized type attribute (ptype = %d)\n", ptype);
294 294 return (topo_mod_seterrno(mp, ETOPO_PRSR_BADTYPE));
295 295 }
296 296
297 297 switch (ptype) {
298 298 case TOPO_TYPE_INT32_ARRAY:
299 299 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
300 300 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
301 301 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
302 302
303 303 if ((str = xmlGetProp(xn, (xmlChar *)Value))
304 304 == NULL)
305 305 return (-1);
306 306
307 307 ((int32_t *)arrbuf)[i++]
308 308 = atoi((const char *)str);
309 309 xmlFree(str);
310 310 }
311 311 }
312 312
313 313 rv = nvlist_add_int32_array(nvl, name, (int32_t *)arrbuf,
314 314 nelems);
315 315 free(arrbuf);
316 316 break;
317 317 case TOPO_TYPE_UINT32_ARRAY:
318 318 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
319 319 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
320 320 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
321 321
322 322 if ((str = xmlGetProp(xn, (xmlChar *)Value))
323 323 == NULL)
324 324 return (-1);
325 325
326 326 ((uint32_t *)arrbuf)[i++]
327 327 = atoi((const char *)str);
328 328 xmlFree(str);
329 329 }
330 330 }
331 331
332 332 rv = nvlist_add_uint32_array(nvl, name, (uint32_t *)arrbuf,
333 333 nelems);
334 334 free(arrbuf);
335 335 break;
336 336 case TOPO_TYPE_INT64_ARRAY:
337 337 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
338 338 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
339 339 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
340 340
341 341 if ((str = xmlGetProp(xn, (xmlChar *)Value))
342 342 == NULL)
343 343 return (-1);
344 344
345 345 ((int64_t *)arrbuf)[i++]
346 346 = atol((const char *)str);
347 347 xmlFree(str);
348 348 }
349 349 }
350 350
351 351 rv = nvlist_add_int64_array(nvl, name, (int64_t *)arrbuf,
352 352 nelems);
353 353 free(arrbuf);
354 354 break;
355 355 case TOPO_TYPE_UINT64_ARRAY:
356 356 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
357 357 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
358 358 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
359 359
360 360 if ((str = xmlGetProp(xn, (xmlChar *)Value))
361 361 == NULL)
362 362 return (-1);
363 363
364 364 ((uint64_t *)arrbuf)[i++]
365 365 = atol((const char *)str);
366 366 xmlFree(str);
367 367 }
368 368 }
369 369
370 370 rv = nvlist_add_uint64_array(nvl, name, arrbuf,
371 371 nelems);
372 372 free(arrbuf);
373 373 break;
374 374 case TOPO_TYPE_STRING_ARRAY:
375 375 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
376 376 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
377 377 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
378 378
379 379 if ((str = xmlGetProp(cn, (xmlChar *)Value))
380 380 == NULL)
381 381 return (-1);
382 382
383 383 strarrbuf[i++] =
384 384 topo_mod_strdup(mp, (const char *)str);
385 385 xmlFree(str);
386 386 }
387 387 }
388 388
389 389 rv = nvlist_add_string_array(nvl, name, strarrbuf, nelems);
390 390 strarr_free(mp, strarrbuf, nelems);
391 391 break;
392 392 case TOPO_TYPE_FMRI_ARRAY:
393 393 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
394 394 if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
395 395 (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
396 396
397 397 if ((str = xmlGetProp(xn, (xmlChar *)Value))
398 398 == NULL)
399 399 return (-1);
400 400
401 401 if (topo_mod_str2nvl(mp, (const char *)str,
402 402 &(nvlarrbuf[i++])) < 0) {
403 403 xmlFree(str);
404 404 return (-1);
405 405 }
406 406 xmlFree(str);
407 407 }
408 408 }
409 409
410 410 rv = nvlist_add_nvlist_array(nvl, name, nvlarrbuf,
411 411 nelems);
412 412 free(nvlarrbuf);
413 413 break;
414 414 }
415 415
416 416 if (rv != 0) {
417 417 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
418 418 "Nvlist construction failed.\n");
419 419 return (topo_mod_seterrno(mp, ETOPO_NOMEM));
420 420 } else
421 421 return (0);
422 422 }
423 423
424 424 static int
425 425 xmlprop_xlate(topo_mod_t *mp, xmlNodePtr xn, nvlist_t *nvl)
426 426 {
427 427 topo_type_t ptype;
428 428 xmlChar *str;
429 429
430 430 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xmlprop_xlate\n");
431 431 if ((str = xmlGetProp(xn, (xmlChar *)Immutable)) != NULL) {
432 432 if (xmlStrcmp(str, (xmlChar *)False) == 0)
433 433 (void) nvlist_add_boolean_value(nvl, INV_IMMUTE,
434 434 B_FALSE);
435 435 else
436 436 (void) nvlist_add_boolean_value(nvl, INV_IMMUTE,
437 437 B_TRUE);
438 438 xmlFree(str);
439 439 } else {
440 440 (void) nvlist_add_boolean_value(nvl, INV_IMMUTE, B_TRUE);
441 441 }
442 442
443 443 if ((ptype = xmlattr_to_type(mp, xn, (xmlChar *)Type))
444 444 == TOPO_TYPE_INVALID)
445 445 return (-1);
446 446
447 447 if (nvlist_add_int32(nvl, INV_PVALTYPE, ptype) != 0)
448 448 return (-1);
449 449
450 450 return (xlate_common(mp, xn, ptype, nvl, INV_PVAL));
451 451 }
452 452
453 453 static int
454 454 dependent_create(topo_mod_t *mp,
455 455 tf_info_t *xinfo, tf_pad_t *pad, xmlNodePtr dxn, tnode_t *ptn)
456 456 {
457 457 tf_rdata_t *rp, *pp, *np;
458 458 xmlChar *grptype;
459 459 int sibs = 0;
460 460
461 461 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "dependent_create\n");
462 462 if ((grptype = xmlGetProp(dxn, (xmlChar *)Grouping)) == NULL) {
463 463 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
464 464 "Dependents missing grouping attribute");
465 465 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
466 466 }
467 467
468 468 pp = NULL;
469 469 if (xmlStrcmp(grptype, (xmlChar *)Siblings) == 0) {
470 470 rp = pad->tpad_sibs;
471 471 sibs++;
472 472 } else if (xmlStrcmp(grptype, (xmlChar *)Children) == 0) {
473 473 rp = pad->tpad_child;
474 474 } else {
475 475 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
476 476 "Dependents have bogus grouping attribute");
477 477 xmlFree(grptype);
478 478 return (topo_mod_seterrno(mp, ETOPO_PRSR_BADGRP));
479 479 }
480 480 xmlFree(grptype);
481 481 /* Add processed dependents to the tail of the list */
482 482 while (rp != NULL) {
483 483 pp = rp;
484 484 rp = rp->rd_next;
485 485 }
486 486 if ((np = topo_xml_walk(mp, xinfo, dxn, ptn)) == NULL) {
487 487 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
488 488 "error within dependent .xml topology: "
489 489 "%s\n", topo_strerror(topo_mod_errno(mp)));
490 490 return (-1);
491 491 }
492 492 if (pp != NULL)
493 493 pp->rd_next = np;
494 494 else if (sibs == 1)
495 495 pad->tpad_sibs = np;
496 496 else
497 497 pad->tpad_child = np;
498 498 return (0);
499 499 }
500 500
501 501 static int
502 502 dependents_create(topo_mod_t *mp,
503 503 tf_info_t *xinfo, tf_pad_t *pad, xmlNodePtr pxn, tnode_t *ptn)
504 504 {
505 505 xmlNodePtr cn;
506 506
507 507 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "dependents_create\n");
508 508 for (cn = pxn->xmlChildrenNode; cn != NULL; cn = cn->next) {
509 509 if (xmlStrcmp(cn->name, (xmlChar *)Dependents) == 0) {
510 510 if (dependent_create(mp, xinfo, pad, cn, ptn) < 0)
511 511 return (-1);
512 512 }
513 513 }
514 514 return (0);
515 515 }
516 516
517 517 static int
518 518 prop_create(topo_mod_t *mp,
519 519 nvlist_t *pfmri, tnode_t *ptn, const char *gnm, const char *pnm,
520 520 topo_type_t ptype, int flag)
521 521 {
522 522 nvlist_t *fmri, **fmriarr;
523 523 uint32_t ui32, *ui32arr;
524 524 uint64_t ui64, *ui64arr;
525 525 int32_t i32, *i32arr;
526 526 int64_t i64, *i64arr;
527 527 uint_t nelem;
528 528 char *str, **strarr;
529 529 int err, e;
530 530
531 531 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "prop_create(pgrp = %s, "
532 532 "prop = %s)\n", gnm, pnm);
533 533 switch (ptype) {
534 534 case TOPO_TYPE_INT32:
535 535 e = nvlist_lookup_int32(pfmri, INV_PVAL, &i32);
536 536 break;
537 537 case TOPO_TYPE_UINT32:
538 538 e = nvlist_lookup_uint32(pfmri, INV_PVAL, &ui32);
539 539 break;
540 540 case TOPO_TYPE_INT64:
541 541 e = nvlist_lookup_int64(pfmri, INV_PVAL, &i64);
542 542 break;
543 543 case TOPO_TYPE_UINT64:
544 544 e = nvlist_lookup_uint64(pfmri, INV_PVAL, &ui64);
545 545 break;
546 546 case TOPO_TYPE_FMRI:
547 547 e = nvlist_lookup_nvlist(pfmri, INV_PVAL, &fmri);
548 548 break;
549 549 case TOPO_TYPE_STRING:
550 550 e = nvlist_lookup_string(pfmri, INV_PVAL, &str);
551 551 break;
552 552 case TOPO_TYPE_INT32_ARRAY:
553 553 e = nvlist_lookup_int32_array(pfmri, INV_PVAL, &i32arr, &nelem);
554 554 break;
555 555 case TOPO_TYPE_UINT32_ARRAY:
556 556 e = nvlist_lookup_uint32_array(pfmri, INV_PVAL, &ui32arr,
557 557 &nelem);
558 558 break;
559 559 case TOPO_TYPE_INT64_ARRAY:
560 560 e = nvlist_lookup_int64_array(pfmri, INV_PVAL, &i64arr,
561 561 &nelem);
562 562 break;
563 563 case TOPO_TYPE_UINT64_ARRAY:
564 564 e = nvlist_lookup_uint64_array(pfmri, INV_PVAL, &ui64arr,
565 565 &nelem);
566 566 break;
567 567 case TOPO_TYPE_STRING_ARRAY:
568 568 e = nvlist_lookup_string_array(pfmri, INV_PVAL, &strarr,
569 569 &nelem);
570 570 break;
571 571 case TOPO_TYPE_FMRI_ARRAY:
572 572 e = nvlist_lookup_nvlist_array(pfmri, INV_PVAL, &fmriarr,
573 573 &nelem);
574 574 break;
575 575 default:
576 576 e = ETOPO_PRSR_BADTYPE;
577 577 }
578 578 if (e != 0) {
579 579 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
580 580 "prop_create: prop value lookup failed.\n");
581 581 return (topo_mod_seterrno(mp, e));
582 582 }
583 583 switch (ptype) {
584 584 case TOPO_TYPE_INT32:
585 585 e = topo_prop_set_int32(ptn, gnm, pnm, flag, i32, &err);
586 586 break;
587 587 case TOPO_TYPE_UINT32:
588 588 e = topo_prop_set_uint32(ptn, gnm, pnm, flag, ui32, &err);
589 589 break;
590 590 case TOPO_TYPE_INT64:
591 591 e = topo_prop_set_int64(ptn, gnm, pnm, flag, i64, &err);
592 592 break;
593 593 case TOPO_TYPE_UINT64:
594 594 e = topo_prop_set_uint64(ptn, gnm, pnm, flag, ui64, &err);
595 595 break;
596 596 case TOPO_TYPE_FMRI:
597 597 e = topo_prop_set_fmri(ptn, gnm, pnm, flag, fmri, &err);
598 598 break;
599 599 case TOPO_TYPE_STRING:
600 600 e = topo_prop_set_string(ptn, gnm, pnm, flag, str, &err);
601 601 break;
602 602 case TOPO_TYPE_INT32_ARRAY:
603 603 e = topo_prop_set_int32_array(ptn, gnm, pnm, flag, i32arr,
604 604 nelem, &err);
605 605 break;
606 606 case TOPO_TYPE_UINT32_ARRAY:
607 607 e = topo_prop_set_uint32_array(ptn, gnm, pnm, flag, ui32arr,
608 608 nelem, &err);
609 609 break;
610 610 case TOPO_TYPE_INT64_ARRAY:
611 611 e = topo_prop_set_int64_array(ptn, gnm, pnm, flag, i64arr,
612 612 nelem, &err);
613 613 break;
614 614 case TOPO_TYPE_UINT64_ARRAY:
615 615 e = topo_prop_set_uint64_array(ptn, gnm, pnm, flag, ui64arr,
616 616 nelem, &err);
617 617 break;
618 618 case TOPO_TYPE_STRING_ARRAY:
619 619 e = topo_prop_set_string_array(ptn, gnm, pnm, flag,
620 620 (const char **)strarr, nelem, &err);
621 621 break;
622 622 case TOPO_TYPE_FMRI_ARRAY:
623 623 e = topo_prop_set_fmri_array(ptn, gnm, pnm, flag,
624 624 (const nvlist_t **)fmriarr, nelem, &err);
625 625 break;
626 626 }
627 627 if (e != 0 && err != ETOPO_PROP_DEFD) {
628 628
629 629 /*
630 630 * Some properties may have already been set
631 631 * in topo_node_bind() or topo_prop_inherit if we are
632 632 * enumerating from a static .xml file
633 633 */
634 634 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "prop set "
635 635 "failed %s/%s:%s\n", gnm, pnm, topo_strerror(err));
636 636 return (topo_mod_seterrno(mp, err));
637 637 }
638 638 return (0);
639 639 }
640 640
641 641 static int
642 642 props_create(topo_mod_t *mp,
643 643 tnode_t *ptn, const char *gnm, nvlist_t **props, int nprops)
644 644 {
645 645 topo_type_t ptype;
646 646 boolean_t pim;
647 647 char *pnm;
648 648 int32_t i32;
649 649 int flag;
650 650 int pn;
651 651 int e;
652 652
653 653 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "props_create(pgrp = %s)\n",
654 654 gnm);
655 655 for (pn = 0; pn < nprops; pn++) {
656 656 e = nvlist_lookup_string(props[pn], INV_PNAME, &pnm);
657 657 if (e != 0) {
658 658 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
659 659 "props create lookup (%s) failure: %s",
660 660 INV_PNAME, strerror(e));
661 661 return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
662 662 }
663 663 e = nvlist_lookup_boolean_value(props[pn], INV_IMMUTE, &pim);
664 664 if (e != 0) {
665 665 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
666 666 "props create lookup (%s) failure: %s",
667 667 INV_IMMUTE, strerror(e));
668 668 return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
669 669 }
670 670 flag = (pim == B_TRUE) ?
671 671 TOPO_PROP_IMMUTABLE : TOPO_PROP_MUTABLE;
672 672
673 673 e = nvlist_lookup_int32(props[pn], INV_PVALTYPE, &i32);
674 674 if (e != 0) {
675 675 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
676 676 "props create lookup (%s) failure: %s",
677 677 INV_PVALTYPE, strerror(e));
678 678 return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
679 679 }
680 680 ptype = (topo_type_t)i32;
681 681 if (prop_create(mp, props[pn], ptn, gnm, pnm, ptype, flag) < 0)
682 682 return (-1);
683 683 }
684 684 return (0);
685 685 }
686 686
687 687 static int
688 688 pgroups_create(topo_mod_t *mp, tf_pad_t *pad, tnode_t *ptn)
689 689 {
690 690 topo_pgroup_info_t pgi;
691 691 nvlist_t **props;
692 692 char *gnm;
693 693 char *nmstab, *dstab;
694 694 uint32_t rnprops, nprops;
695 695 uint32_t gv;
696 696 int pg;
697 697 int e;
698 698
699 699 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroups_create: %s=%d\n",
700 700 topo_node_name(ptn), topo_node_instance(ptn));
701 701 for (pg = 0; pg < pad->tpad_pgcnt; pg++) {
702 702 e = nvlist_lookup_string(pad->tpad_pgs[pg],
703 703 INV_PGRP_NAME, &gnm);
704 704 if (e != 0) {
705 705 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
706 706 "pad lookup (%s) failed (%s).\n",
707 707 INV_PGRP_NAME, strerror(errno));
708 708 return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
709 709 }
710 710 e = nvlist_lookup_string(pad->tpad_pgs[pg],
711 711 INV_PGRP_NMSTAB, &nmstab);
712 712 if (e != 0) {
713 713 if (e != ENOENT) {
714 714 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
715 715 "pad lookup (%s) "
716 716 "failed.\n", INV_PGRP_NMSTAB);
717 717 return (topo_mod_seterrno(mp,
718 718 ETOPO_PRSR_NVPROP));
719 719 } else {
720 720 nmstab = TOPO_STABSTR_PRIVATE;
721 721 }
722 722 }
723 723 e = nvlist_lookup_string(pad->tpad_pgs[pg],
724 724 INV_PGRP_DSTAB, &dstab);
725 725 if (e != 0) {
726 726 if (e != ENOENT) {
727 727 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
728 728 "pad lookup (%s) failed.\n",
729 729 INV_PGRP_DSTAB);
730 730 return (topo_mod_seterrno(mp,
731 731 ETOPO_PRSR_NVPROP));
732 732 } else {
733 733 dstab = TOPO_STABSTR_PRIVATE;
734 734 }
735 735 }
736 736 e = nvlist_lookup_uint32(pad->tpad_pgs[pg],
737 737 INV_PGRP_VER, &gv);
738 738 if (e != 0) {
739 739 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
740 740 "pad lookup (%s) failed.\n",
741 741 INV_PGRP_VER);
742 742 return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
743 743 }
744 744 pgi.tpi_name = gnm;
745 745 pgi.tpi_namestab = topo_name2stability(nmstab);
746 746 pgi.tpi_datastab = topo_name2stability(dstab);
747 747 pgi.tpi_version = gv;
748 748 if (topo_pgroup_create(ptn, &pgi, &e) != 0) {
749 749 if (e != ETOPO_PROP_DEFD) {
750 750 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
751 751 "pgroups create failure: %s\n",
752 752 topo_strerror(e));
753 753 return (-1);
754 754 }
755 755 }
756 756 e = nvlist_lookup_uint32(pad->tpad_pgs[pg],
757 757 INV_PGRP_NPROP, &rnprops);
758 758 /*
759 759 * The number of properties could be zero if the property
760 760 * group only contains propmethod declarations
761 761 */
762 762 if (rnprops > 0) {
763 763 e |= nvlist_lookup_nvlist_array(pad->tpad_pgs[pg],
764 764 INV_PGRP_ALLPROPS, &props, &nprops);
765 765 if (rnprops != nprops) {
766 766 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
767 767 "recorded number of props %d does not "
768 768 "match number of props recorded %d.\n",
769 769 rnprops, nprops);
770 770 }
771 771 if (props_create(mp, ptn, gnm, props, nprops) < 0)
772 772 return (-1);
773 773 }
774 774 }
775 775 return (0);
776 776 }
777 777
778 778 static nvlist_t *
779 779 pval_record(topo_mod_t *mp, xmlNodePtr xn)
780 780 {
781 781 nvlist_t *pnvl = NULL;
782 782 xmlChar *pname;
783 783
784 784 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pval_record\n");
785 785 if ((pname = xmlGetProp(xn, (xmlChar *)Name)) == NULL) {
786 786 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
787 787 "propval lacks a name\n");
788 788 (void) topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
789 789 return (NULL);
790 790 }
791 791 if (topo_mod_nvalloc(mp, &pnvl, NV_UNIQUE_NAME) < 0) {
792 792 xmlFree(pname);
793 793 return (NULL);
794 794 }
795 795 if (nvlist_add_string(pnvl, INV_PNAME, (char *)pname) < 0) {
796 796 xmlFree(pname);
797 797 nvlist_free(pnvl);
798 798 return (NULL);
799 799 }
800 800 xmlFree(pname);
801 801 /* FMXXX stability of the property name */
802 802
803 803 if (xmlprop_xlate(mp, xn, pnvl) < 0) {
804 804 nvlist_free(pnvl);
805 805 return (NULL);
806 806 }
807 807 return (pnvl);
808 808 }
809 809
810 810
811 811 struct propmeth_data {
812 812 const char *pg_name;
813 813 const char *prop_name;
814 814 topo_type_t prop_type;
815 815 const char *meth_name;
816 816 topo_version_t meth_ver;
817 817 nvlist_t *arg_nvl;
818 818 };
819 819
820 820 static int
821 821 register_method(topo_mod_t *mp, tnode_t *ptn, struct propmeth_data *meth)
822 822 {
823 823 int err;
824 824
825 825 if (topo_prop_method_version_register(ptn, meth->pg_name,
826 826 meth->prop_name, meth->prop_type, meth->meth_name, meth->meth_ver,
827 827 meth->arg_nvl, &err) != 0) {
828 828
829 829 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "failed to register "
830 830 "propmethod %s for property \"%s\" in propgrp %s on node "
831 831 "%s=%d (%s)\n",
832 832 meth->meth_name, meth->prop_name, meth->pg_name,
833 833 topo_node_name(ptn), topo_node_instance(ptn),
834 834 topo_strerror(err));
835 835 return (-1);
836 836 }
837 837 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
838 838 "registered method %s on %s=%d\n",
839 839 meth->meth_name, topo_node_name(ptn), topo_node_instance(ptn));
840 840
841 841 return (0);
842 842 }
843 843
844 844 static int
845 845 pmeth_record(topo_mod_t *mp, const char *pg_name, xmlNodePtr xn, tnode_t *tn,
846 846 const char *rname, const char *ppgrp_name)
847 847 {
848 848 nvlist_t *arg_nvl = NULL;
849 849 xmlNodePtr cn;
850 850 xmlChar *meth_name = NULL, *prop_name = NULL;
851 851 xmlChar *arg_name = NULL;
852 852 uint64_t meth_ver, is_mutable = 0, is_nonvolatile = 0;
853 853 topo_type_t prop_type;
854 854 struct propmeth_data meth;
855 855 int ret = 0, err;
856 856 topo_type_t ptype;
857 857 tnode_t *tmp;
858 858
859 859 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pmeth_record: %s=%d "
860 860 "(pgrp=%s)\n", topo_node_name(tn), topo_node_instance(tn), pg_name);
861 861
862 862 /*
863 863 * Get propmethod attribute values
864 864 */
865 865 if ((meth_name = xmlGetProp(xn, (xmlChar *)Name)) == NULL) {
866 866 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
867 867 "propmethod element lacks a name attribute\n");
868 868 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
869 869 }
870 870 if (xmlattr_to_int(mp, xn, Version, &meth_ver) < 0) {
871 871 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
872 872 "propmethod element lacks version attribute\n");
873 873 ret = topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
874 874 goto pmr_done;
875 875 }
876 876 /*
877 877 * The "mutable" and "nonvoltile" attributes are optional. If not
878 878 * specified we default to false (0)
879 879 */
880 880 (void) xmlattr_to_int(mp, xn, Mutable, &is_mutable);
881 881 (void) xmlattr_to_int(mp, xn, Nonvolatile, &is_nonvolatile);
882 882
883 883 if ((prop_name = xmlGetProp(xn, (xmlChar *)Propname)) == NULL) {
884 884 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
885 885 "propmethod element lacks propname attribute\n");
886 886 ret = topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
887 887 goto pmr_done;
888 888 }
889 889 if ((prop_type = xmlattr_to_type(mp, xn, (xmlChar *)Proptype))
890 890 == TOPO_TYPE_INVALID) {
891 891 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
892 892 "error decoding proptype attribute\n");
893 893 ret = topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
894 894 goto pmr_done;
895 895 }
896 896
897 897 /*
898 898 * Allocate method argument nvlist
899 899 */
900 900 if (topo_mod_nvalloc(mp, &arg_nvl, NV_UNIQUE_NAME) < 0) {
901 901 ret = topo_mod_seterrno(mp, ETOPO_NOMEM);
902 902 goto pmr_done;
903 903 }
904 904
905 905 /*
906 906 * Iterate through the argval nodes and build the argval nvlist
907 907 */
908 908 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
909 909 if (xmlStrcmp(cn->name, (xmlChar *)Argval) == 0) {
910 910 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
911 911 "found argval element\n");
912 912 if ((arg_name = xmlGetProp(cn, (xmlChar *)Name))
913 913 == NULL) {
914 914 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
915 915 "argval element lacks a name attribute\n");
916 916 ret = topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
917 917 goto pmr_done;
918 918 }
919 919 if ((ptype = xmlattr_to_type(mp, cn, (xmlChar *)Type))
920 920 == TOPO_TYPE_INVALID) {
921 921 ret = topo_mod_seterrno(mp, ETOPO_PRSR_BADTYPE);
922 922 xmlFree(arg_name);
923 923 break;
924 924 }
925 925 if (xlate_common(mp, cn, ptype, arg_nvl,
926 926 (const char *)arg_name) != 0) {
927 927 ret = topo_mod_seterrno(mp, ETOPO_PRSR_BADTYPE);
928 928 xmlFree(arg_name);
929 929 break;
930 930 }
931 931 }
932 932 if (arg_name) {
933 933 xmlFree(arg_name);
934 934 arg_name = NULL;
935 935 }
936 936 }
937 937
938 938 if (ret != 0)
939 939 goto pmr_done;
940 940
941 941 /*
942 942 * Register the prop method for all of the nodes in our range
943 943 */
944 944 meth.pg_name = (const char *)pg_name;
945 945 meth.prop_name = (const char *)prop_name;
946 946 meth.prop_type = prop_type;
947 947 meth.meth_name = (const char *)meth_name;
948 948 meth.meth_ver = meth_ver;
949 949 meth.arg_nvl = arg_nvl;
950 950
951 951 /*
952 952 * If the propgroup element is under a range element, we'll apply
953 953 * the method to all of the topo nodes at this level with the same
954 954 * range name.
955 955 *
956 956 * Otherwise, if the propgroup element is under a node element
957 957 * then we'll simply register the method for this node.
958 958 */
959 959 if (strcmp(ppgrp_name, Range) == 0) {
960 960 for (tmp = tn; tmp != NULL; tmp = topo_child_next(NULL, tmp)) {
961 961 if (strcmp(rname, topo_node_name(tmp)) == 0) {
962 962 if (register_method(mp, tmp, &meth) != 0) {
963 963 ret = topo_mod_seterrno(mp,
964 964 ETOPO_PRSR_REGMETH);
965 965 goto pmr_done;
966 966 }
967 967 if (is_mutable) {
968 968 if (topo_prop_setmutable(tmp,
969 969 meth.pg_name, meth.prop_name, &err)
970 970 != 0) {
971 971 ret = topo_mod_seterrno(mp,
972 972 ETOPO_PRSR_REGMETH);
973 973 goto pmr_done;
974 974 }
975 975 }
976 976 if (is_nonvolatile) {
977 977 if (topo_prop_setnonvolatile(tmp,
978 978 meth.pg_name, meth.prop_name, &err)
979 979 != 0) {
980 980 ret = topo_mod_seterrno(mp,
981 981 ETOPO_PRSR_REGMETH);
982 982 goto pmr_done;
983 983 }
984 984 }
985 985 }
986 986 }
987 987 } else {
988 988 if (register_method(mp, tn, &meth) != 0) {
989 989 ret = topo_mod_seterrno(mp, ETOPO_PRSR_REGMETH);
990 990 goto pmr_done;
991 991 }
992 992 if (is_mutable) {
993 993 if (topo_prop_setmutable(tn, meth.pg_name,
994 994 meth.prop_name, &err) != 0) {
995 995 ret = topo_mod_seterrno(mp,
996 996 ETOPO_PRSR_REGMETH);
997 997 goto pmr_done;
998 998 }
999 999 }
1000 1000 if (is_nonvolatile) {
1001 1001 if (topo_prop_setnonvolatile(tn, meth.pg_name,
1002 1002 meth.prop_name, &err) != 0) {
1003 1003 ret = topo_mod_seterrno(mp,
1004 1004 ETOPO_PRSR_REGMETH);
↓ open down ↓ |
1004 lines elided |
↑ open up ↑ |
1005 1005 goto pmr_done;
1006 1006 }
1007 1007 }
1008 1008 }
1009 1009
1010 1010 pmr_done:
1011 1011 if (meth_name)
1012 1012 xmlFree(meth_name);
1013 1013 if (prop_name)
1014 1014 xmlFree(prop_name);
1015 - if (arg_nvl)
1016 - nvlist_free(arg_nvl);
1015 + nvlist_free(arg_nvl);
1017 1016 return (ret);
1018 1017 }
1019 1018
1020 1019
1021 1020 static int
1022 1021 pgroup_record(topo_mod_t *mp, xmlNodePtr pxn, tnode_t *tn, const char *rname,
1023 1022 tf_pad_t *rpad, int pi, const char *ppgrp_name)
1024 1023 {
1025 1024 topo_stability_t nmstab, dstab;
1026 1025 uint64_t ver;
1027 1026 xmlNodePtr cn;
1028 1027 xmlChar *name;
1029 1028 nvlist_t **apl = NULL;
1030 1029 nvlist_t *pgnvl = NULL;
1031 1030 int pcnt = 0;
1032 1031 int ai = 0;
1033 1032 int e;
1034 1033
1035 1034 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroup_record\n");
1036 1035 if ((name = xmlGetProp(pxn, (xmlChar *)Name)) == NULL) {
1037 1036 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1038 1037 "propgroup lacks a name\n");
1039 1038 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
1040 1039 }
1041 1040 if (xmlattr_to_int(mp, pxn, Version, &ver) < 0) {
1042 1041 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1043 1042 "propgroup lacks a version\n");
1044 1043 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
1045 1044 }
1046 1045 if (xmlattr_to_stab(mp, pxn, Namestab, &nmstab) < 0) {
1047 1046 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1048 1047 "propgroup lacks name-stability\n");
1049 1048 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
1050 1049 }
1051 1050 if (xmlattr_to_stab(mp, pxn, Datastab, &dstab) < 0) {
1052 1051 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1053 1052 "propgroup lacks data-stability\n");
1054 1053 return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
1055 1054 }
1056 1055
1057 1056 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroup %s\n", (char *)name);
1058 1057 for (cn = pxn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1059 1058 if (xmlStrcmp(cn->name, (xmlChar *)Propval) == 0)
1060 1059 pcnt++;
1061 1060 }
1062 1061
1063 1062 if (topo_mod_nvalloc(mp, &pgnvl, NV_UNIQUE_NAME) < 0) {
1064 1063 xmlFree(name);
1065 1064 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1066 1065 "failed to allocate propgroup nvlist\n");
1067 1066 return (topo_mod_seterrno(mp, ETOPO_NOMEM));
1068 1067 }
1069 1068
1070 1069 e = nvlist_add_string(pgnvl, INV_PGRP_NAME, (char *)name);
1071 1070 e |= nvlist_add_uint32(pgnvl, INV_PGRP_NMSTAB, nmstab);
1072 1071 e |= nvlist_add_uint32(pgnvl, INV_PGRP_DSTAB, dstab);
1073 1072 e |= nvlist_add_uint32(pgnvl, INV_PGRP_VER, ver);
1074 1073 e |= nvlist_add_uint32(pgnvl, INV_PGRP_NPROP, pcnt);
1075 1074 if (pcnt > 0)
1076 1075 if (e != 0 ||
1077 1076 (apl = topo_mod_zalloc(mp, pcnt * sizeof (nvlist_t *)))
1078 1077 == NULL) {
1079 1078 xmlFree(name);
1080 1079 nvlist_free(pgnvl);
1081 1080 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1082 1081 "failed to allocate nvlist array for properties"
1083 1082 "(e=%d)\n", e);
1084 1083 return (topo_mod_seterrno(mp, ETOPO_NOMEM));
1085 1084 }
1086 1085 for (cn = pxn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1087 1086 if (xmlStrcmp(cn->name, (xmlChar *)Propval) == 0) {
1088 1087 if (ai < pcnt) {
1089 1088 if ((apl[ai] = pval_record(mp, cn)) == NULL)
1090 1089 break;
1091 1090 }
1092 1091 ai++;
1093 1092 } else if (xmlStrcmp(cn->name, (xmlChar *)Prop_meth) == 0) {
1094 1093 if (pmeth_record(mp, (const char *)name, cn, tn, rname,
↓ open down ↓ |
68 lines elided |
↑ open up ↑ |
1095 1094 ppgrp_name) < 0)
1096 1095 break;
1097 1096 }
1098 1097 }
1099 1098 xmlFree(name);
1100 1099 if (pcnt > 0) {
1101 1100 e |= (ai != pcnt);
1102 1101 e |= nvlist_add_nvlist_array(pgnvl, INV_PGRP_ALLPROPS, apl,
1103 1102 pcnt);
1104 1103 for (ai = 0; ai < pcnt; ai++)
1105 - if (apl[ai] != NULL)
1106 - nvlist_free(apl[ai]);
1104 + nvlist_free(apl[ai]);
1107 1105 topo_mod_free(mp, apl, pcnt * sizeof (nvlist_t *));
1108 1106 if (e != 0) {
1109 1107 nvlist_free(pgnvl);
1110 1108 return (-1);
1111 1109 }
1112 1110 }
1113 1111 rpad->tpad_pgs[pi] = pgnvl;
1114 1112 return (0);
1115 1113 }
1116 1114
1117 1115 static int
1118 1116 pgroups_record(topo_mod_t *mp, xmlNodePtr pxn, tnode_t *tn, const char *rname,
1119 1117 tf_pad_t *rpad, const char *ppgrp)
1120 1118 {
1121 1119 xmlNodePtr cn;
1122 1120 int pi = 0;
1123 1121
1124 1122 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroups_record: pxn->name=%s\n",
1125 1123 pxn->name);
1126 1124 for (cn = pxn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1127 1125 if (xmlStrcmp(cn->name, (xmlChar *)Propgrp) == 0) {
1128 1126 if (pgroup_record(mp, cn, tn, rname, rpad, pi++, ppgrp)
1129 1127 < 0)
1130 1128 return (-1);
1131 1129 }
1132 1130 }
1133 1131 return (0);
1134 1132 }
1135 1133
1136 1134 /*
1137 1135 * psn: pointer to a "set" XML node
1138 1136 * key: string to search the set for
1139 1137 *
1140 1138 * returns: 1, if the set contains key
1141 1139 * 0, otherwise
1142 1140 */
1143 1141 static int
1144 1142 set_contains(topo_mod_t *mp, char *key, char *set)
1145 1143 {
1146 1144 char *prod;
1147 1145 int rv = 0;
1148 1146
1149 1147 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "set_contains(key = %s, "
1150 1148 "setlist = %s)\n", key, set);
1151 1149
1152 1150 prod = strtok((char *)set, "|");
1153 1151 if (prod && (strcmp(key, prod) == 0))
1154 1152 return (1);
1155 1153
1156 1154 while ((prod = strtok(NULL, "|")))
1157 1155 if (strcmp(key, prod) == 0)
1158 1156 return (1);
1159 1157
1160 1158 return (rv);
1161 1159 }
1162 1160
1163 1161
1164 1162 /*
1165 1163 * Process the property group and dependents xmlNode children of
1166 1164 * parent xmlNode pxn.
1167 1165 */
1168 1166 static int
1169 1167 pad_process(topo_mod_t *mp, tf_rdata_t *rd, xmlNodePtr pxn, tnode_t *ptn,
1170 1168 tf_pad_t **rpad)
1171 1169 {
1172 1170 xmlNodePtr cn, gcn, psn, ecn, target;
1173 1171 xmlNodePtr def_set = NULL;
1174 1172 tnode_t *ct;
1175 1173 tf_pad_t *new = *rpad;
1176 1174 tf_rdata_t tmp_rd;
1177 1175 int pgcnt = 0;
1178 1176 int dcnt = 0;
1179 1177 int ecnt = 0;
1180 1178 int joined_set = 0, inst;
1181 1179 xmlChar *set;
1182 1180 char *key;
1183 1181
1184 1182 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1185 1183 "pad_process beneath %s=%d\n", topo_node_name(ptn),
1186 1184 topo_node_instance(ptn));
1187 1185 if (new == NULL) {
1188 1186 for (cn = pxn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1189 1187 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1190 1188 "cn->name is %s \n", (char *)cn->name);
1191 1189 /*
1192 1190 * We're iterating through the XML children looking for
1193 1191 * four types of elements:
1194 1192 * 1) dependents elements
1195 1193 * 2) unconstrained pgroup elements
1196 1194 * 3) pgroup elements constrained by set elements
1197 1195 * 4) enum-method elements for the case that we want
1198 1196 * to post-process a statically defined node
1199 1197 */
1200 1198 if (xmlStrcmp(cn->name, (xmlChar *)Dependents) == 0)
1201 1199 dcnt++;
1202 1200 else if (xmlStrcmp(cn->name, (xmlChar *)Propgrp) == 0)
1203 1201 pgcnt++;
1204 1202 else if (xmlStrcmp(cn->name, (xmlChar *)Enum_meth)
1205 1203 == 0) {
1206 1204 ecn = cn;
1207 1205 ecnt++;
1208 1206 } else if (xmlStrcmp(cn->name, (xmlChar *)Set) == 0) {
1209 1207 if (joined_set)
1210 1208 continue;
1211 1209 set = xmlGetProp(cn, (xmlChar *)Setlist);
1212 1210
1213 1211 if (mp->tm_hdl->th_product)
1214 1212 key = mp->tm_hdl->th_product;
1215 1213 else
1216 1214 key = mp->tm_hdl->th_platform;
1217 1215
1218 1216 /*
1219 1217 * If it's the default set then we'll store
1220 1218 * a pointer to it so that if none of the other
1221 1219 * sets apply to our product we can fall
1222 1220 * back to this one.
1223 1221 */
1224 1222 if (strcmp((char *)set, "default") == 0)
1225 1223 def_set = cn;
1226 1224 else if (set_contains(mp, key, (char *)set)) {
1227 1225 psn = cn;
1228 1226 joined_set = 1;
1229 1227 for (gcn = cn->xmlChildrenNode;
1230 1228 gcn != NULL; gcn = gcn->next) {
1231 1229 if (xmlStrcmp(gcn->name,
1232 1230 (xmlChar *)Propgrp) == 0)
1233 1231 pgcnt++;
1234 1232 }
1235 1233 }
1236 1234 xmlFree(set);
1237 1235 }
1238 1236 }
1239 1237 /*
1240 1238 * If we haven't found a set that contains our product AND
1241 1239 * a default set exists, then we'll process it.
1242 1240 */
1243 1241 if (!joined_set && def_set) {
1244 1242 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1245 1243 "Falling back to default set\n");
1246 1244 joined_set = 1;
1247 1245 psn = def_set;
1248 1246 for (gcn = psn->xmlChildrenNode; gcn != NULL;
1249 1247 gcn = gcn->next) {
1250 1248 if (xmlStrcmp(gcn->name, (xmlChar *)Propgrp)
1251 1249 == 0)
1252 1250 pgcnt++;
1253 1251 }
1254 1252 }
1255 1253 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1256 1254 "pad_process: dcnt=%d, pgcnt=%d, ecnt=%d, joined_set=%d\n",
1257 1255 dcnt, pgcnt, ecnt, joined_set);
1258 1256 /*
1259 1257 * If an enum-method element was found, AND we're a child of a
1260 1258 * node element, then we invoke the enumerator so that it can do
1261 1259 * post-processing of the node.
1262 1260 */
1263 1261 if (ecnt && (strcmp((const char *)pxn->name, Node) == 0)) {
1264 1262 if ((tmp_rd.rd_einfo = enum_attributes_process(mp, ecn))
1265 1263 == NULL)
1266 1264 return (-1);
1267 1265 tmp_rd.rd_mod = mp;
1268 1266 tmp_rd.rd_name = rd->rd_name;
1269 1267 tmp_rd.rd_min = rd->rd_min;
1270 1268 tmp_rd.rd_max = rd->rd_max;
1271 1269 tmp_rd.rd_pn = ptn;
1272 1270 if (enum_run(mp, &tmp_rd) < 0) {
1273 1271 /*
1274 1272 * Note the failure but continue on
1275 1273 */
1276 1274 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1277 1275 "pad_process: enumeration failed.\n");
1278 1276 }
1279 1277 tf_edata_free(mp, tmp_rd.rd_einfo);
1280 1278 }
1281 1279 /*
1282 1280 * Here we allocate an element in an intermediate data structure
1283 1281 * which keeps track property groups and dependents of the range
1284 1282 * currently being processed.
1285 1283 *
1286 1284 * This structure is referenced in pgroups_record() to create
1287 1285 * the actual property groups in the topo tree
1288 1286 */
1289 1287 if ((new = tf_pad_new(mp, pgcnt, dcnt)) == NULL)
1290 1288 return (-1);
1291 1289
1292 1290 if (pgcnt > 0) {
1293 1291 new->tpad_pgs =
1294 1292 topo_mod_zalloc(mp, pgcnt * sizeof (nvlist_t *));
1295 1293 if (new->tpad_pgs == NULL) {
1296 1294 tf_pad_free(mp, new);
1297 1295 return (-1);
1298 1296 }
1299 1297 }
1300 1298 /*
1301 1299 * If the property groups are contained within a set
1302 1300 * then they will be one level lower in the XML tree.
1303 1301 */
1304 1302 if (joined_set)
1305 1303 target = psn;
1306 1304 else
1307 1305 target = pxn;
1308 1306
1309 1307 /*
1310 1308 * If there is no "node" element under the "range"
1311 1309 * element, then we need to attach the facility node to
1312 1310 * each node in this range.
1313 1311 *
1314 1312 * Otherwise we only attach it to the current node
1315 1313 */
1316 1314 if (xmlStrcmp(target->name, (xmlChar *)Range) == 0 ||
1317 1315 xmlStrcmp(target->name, (xmlChar *)Set) == 0) {
1318 1316 for (ct = topo_child_first(rd->rd_pn);
1319 1317 ct != NULL;
1320 1318 ct = topo_child_next(rd->rd_pn, ct)) {
1321 1319
1322 1320 if (strcmp(topo_node_name(ct),
1323 1321 rd->rd_name) != 0)
1324 1322 continue;
1325 1323
1326 1324 inst = topo_node_instance(ct);
1327 1325 if (inst < rd->rd_min || inst > rd->rd_max)
1328 1326 continue;
1329 1327
1330 1328 if (fac_enum_process(mp, target, ct) < 0)
1331 1329 return (-1);
1332 1330
1333 1331 if (fac_process(mp, target, rd, ct) < 0)
1334 1332 return (-1);
1335 1333 }
1336 1334 } else {
1337 1335 if (fac_enum_process(mp, target, ptn) < 0)
1338 1336 return (-1);
1339 1337 if (fac_process(mp, target, rd, ptn) < 0)
1340 1338 return (-1);
1341 1339 }
1342 1340 if (pgcnt > 0 && pgroups_record(mp, target, ptn, rd->rd_name,
1343 1341 new, (const char *)pxn->name) < 0) {
1344 1342 tf_pad_free(mp, new);
1345 1343 return (-1);
1346 1344 }
1347 1345 *rpad = new;
1348 1346 }
1349 1347
1350 1348 if (new->tpad_dcnt > 0)
1351 1349 if (dependents_create(mp, rd->rd_finfo, new, pxn, ptn) < 0)
1352 1350 return (-1);
1353 1351
1354 1352 if (new->tpad_pgcnt > 0)
1355 1353 if (pgroups_create(mp, new, ptn) < 0)
1356 1354 return (-1);
1357 1355
1358 1356 return (0);
1359 1357 }
1360 1358
1361 1359
1362 1360 static int
1363 1361 fac_enum_process(topo_mod_t *mp, xmlNodePtr pn, tnode_t *ptn)
1364 1362 {
1365 1363 xmlNodePtr cn;
1366 1364 xmlChar *fprov = NULL;
1367 1365 int rv = 0;
1368 1366
1369 1367 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1370 1368 "fac_enum_process() called for %s=%d\n", topo_node_name(ptn),
1371 1369 topo_node_instance(ptn));
1372 1370
1373 1371 for (cn = pn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1374 1372
1375 1373 if (xmlStrcmp(cn->name, (xmlChar *)"fac-enum") != 0)
1376 1374 continue;
1377 1375
1378 1376 if ((fprov = xmlGetProp(cn, (xmlChar *)Provider)) == NULL)
1379 1377 goto fenumdone;
1380 1378 /*
1381 1379 * Invoke enum entry point in facility provider which will
1382 1380 * cause the facility enumeration node method to be
1383 1381 * registered.
1384 1382 */
1385 1383 if (fac_enum_run(mp, ptn, (const char *)fprov) != 0) {
1386 1384 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1387 1385 "fac_enum_process: enum entry point failed!\n");
1388 1386 goto fenumdone;
1389 1387 }
1390 1388 xmlFree(fprov);
1391 1389 }
1392 1390 return (0);
1393 1391 fenumdone:
1394 1392 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "fac-enum processing failed\n");
1395 1393
1396 1394 if (fprov != NULL)
1397 1395 xmlFree(fprov);
1398 1396
1399 1397 return (rv);
1400 1398 }
1401 1399
1402 1400
1403 1401 static int
1404 1402 fac_process(topo_mod_t *mp, xmlNodePtr pn, tf_rdata_t *rd, tnode_t *ptn)
1405 1403 {
1406 1404 xmlNodePtr cn;
1407 1405 xmlChar *fname = NULL, *ftype = NULL, *provider = NULL;
1408 1406 tnode_t *ntn = NULL;
1409 1407 tf_idata_t *newi;
1410 1408 int err;
1411 1409 topo_pgroup_info_t pgi;
1412 1410
1413 1411 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1414 1412 "fac_process() called for %s=%d\n", topo_node_name(ptn),
1415 1413 topo_node_instance(ptn));
1416 1414
1417 1415 for (cn = pn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1418 1416
1419 1417 if (xmlStrcmp(cn->name, (xmlChar *)Facility) != 0)
1420 1418 continue;
1421 1419
1422 1420 if ((fname = xmlGetProp(cn, (xmlChar *)Name)) == NULL)
1423 1421 goto facdone;
1424 1422
1425 1423 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1426 1424 "processing facility node '%s'\n", fname);
1427 1425
1428 1426 if ((ftype = xmlGetProp(cn, (xmlChar *)Type)) == NULL)
1429 1427 goto facdone;
1430 1428
1431 1429 if ((provider = xmlGetProp(cn, (xmlChar *)Provider)) == NULL)
1432 1430 goto facdone;
1433 1431
1434 1432 if (xmlStrcmp(ftype, (xmlChar *)Sensor) != 0 &&
1435 1433 xmlStrcmp(ftype, (xmlChar *)Indicator) != 0)
1436 1434 goto facdone;
1437 1435
1438 1436 if ((ntn = topo_node_facbind(mp, ptn, (char *)fname,
1439 1437 (char *)ftype)) == NULL)
1440 1438 goto facdone;
1441 1439
1442 1440 pgi.tpi_name = TOPO_PGROUP_FACILITY;
1443 1441 pgi.tpi_namestab = TOPO_STABILITY_PRIVATE;
1444 1442 pgi.tpi_datastab = TOPO_STABILITY_PRIVATE;
1445 1443 pgi.tpi_version = 1;
1446 1444 if (topo_pgroup_create(ntn, &pgi, &err) != 0) {
1447 1445 if (err != ETOPO_PROP_DEFD) {
1448 1446 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1449 1447 "pgroups create failure: %s\n",
1450 1448 topo_strerror(err));
1451 1449 return (-1);
1452 1450 }
1453 1451 }
1454 1452 /*
1455 1453 * Invoke enum entry point in the facility provider module,
1456 1454 * which will cause the provider methods to be registered on
1457 1455 * this node
1458 1456 */
1459 1457 if (fac_enum_run(mp, ntn, (const char *)provider) != 0) {
1460 1458 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "fac_process: "
1461 1459 "enum entry point failed for provider %s!\n",
1462 1460 provider);
1463 1461 goto facdone;
1464 1462 }
1465 1463
1466 1464 if ((newi = tf_idata_new(mp, 0, ntn)) == NULL)
1467 1465 goto facdone;
1468 1466
1469 1467 if (tf_idata_insert(&rd->rd_instances, newi) < 0)
1470 1468 goto facdone;
1471 1469
1472 1470 if (pad_process(mp, rd, cn, ntn, &newi->ti_pad) < 0)
1473 1471 goto facdone;
1474 1472
1475 1473 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "done with "
1476 1474 "facility %s=%s.\n", ftype, fname);
1477 1475
1478 1476 xmlFree(ftype);
1479 1477 xmlFree(fname);
1480 1478 xmlFree(provider);
1481 1479 }
1482 1480
1483 1481 return (0);
1484 1482
1485 1483 facdone:
1486 1484 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "facility processing failed\n");
1487 1485
1488 1486 if (ftype != NULL)
1489 1487 xmlFree(ftype);
1490 1488 if (fname != NULL)
1491 1489 xmlFree(fname);
1492 1490 if (provider != NULL)
1493 1491 xmlFree(provider);
1494 1492 if (ntn != NULL)
1495 1493 topo_node_unbind(ntn);
1496 1494
1497 1495 return (0);
1498 1496 }
1499 1497
1500 1498 static int
1501 1499 node_process(topo_mod_t *mp, xmlNodePtr nn, tf_rdata_t *rd)
1502 1500 {
1503 1501 xmlChar *str;
1504 1502 topo_instance_t inst;
1505 1503 tf_idata_t *newi;
1506 1504 tnode_t *ntn;
1507 1505 uint64_t ui;
1508 1506 int rv = -1;
1509 1507 int s = 0;
1510 1508
1511 1509 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1512 1510 "node_process %s\n", rd->rd_name);
1513 1511
1514 1512 if (xmlattr_to_int(mp, nn, Instance, &ui) < 0)
1515 1513 goto nodedone;
1516 1514 inst = (topo_instance_t)ui;
1517 1515
1518 1516 if ((str = xmlGetProp(nn, (xmlChar *)Static)) != NULL) {
1519 1517 if (xmlStrcmp(str, (xmlChar *)True) == 0)
1520 1518 s = 1;
1521 1519 xmlFree(str);
1522 1520 }
1523 1521
1524 1522 if (s == 0) {
1525 1523 if (topo_mod_enumerate(rd->rd_mod, rd->rd_pn,
1526 1524 rd->rd_finfo->tf_scheme, rd->rd_name, inst, inst,
1527 1525 s == 1 ? &s : NULL) < 0)
1528 1526 goto nodedone;
1529 1527 }
1530 1528 ntn = topo_node_lookup(rd->rd_pn, rd->rd_name, inst);
1531 1529
1532 1530 if (ntn == NULL) {
1533 1531
1534 1532 /*
1535 1533 * If this is a static node declaration, we can
1536 1534 * ignore the lookup failure and continue
1537 1535 * processing. Otherwise, something
1538 1536 * went wrong during enumeration
1539 1537 */
1540 1538 if (s == 1)
1541 1539 rv = 0;
1542 1540 goto nodedone;
1543 1541 }
1544 1542 if ((newi = tf_idata_new(mp, inst, ntn)) == NULL) {
1545 1543 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1546 1544 "node_process: tf_idata_new failed.\n");
1547 1545 goto nodedone;
1548 1546 }
1549 1547 if (tf_idata_insert(&rd->rd_instances, newi) < 0) {
1550 1548 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1551 1549 "node_process: tf_idata_insert failed.\n");
1552 1550 goto nodedone;
1553 1551 }
1554 1552 if (pad_process(mp, rd, nn, ntn, &newi->ti_pad) < 0)
1555 1553 goto nodedone;
1556 1554 if (fac_process(mp, nn, rd, ntn) < 0)
1557 1555 goto nodedone;
1558 1556 rv = 0;
1559 1557 nodedone:
1560 1558 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "done with node %s.\n",
1561 1559 rd->rd_name);
1562 1560 return (rv);
1563 1561 }
1564 1562
1565 1563 static tf_edata_t *
1566 1564 enum_attributes_process(topo_mod_t *mp, xmlNodePtr en)
1567 1565 {
1568 1566 tf_edata_t *einfo;
1569 1567 uint64_t ui;
1570 1568
1571 1569 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "enum_attributes_process\n");
1572 1570 if ((einfo = topo_mod_zalloc(mp, sizeof (tf_edata_t))) == NULL) {
1573 1571 (void) topo_mod_seterrno(mp, ETOPO_NOMEM);
1574 1572 return (NULL);
1575 1573 }
1576 1574 einfo->te_name = (char *)xmlGetProp(en, (xmlChar *)Name);
1577 1575 if (einfo->te_name == NULL) {
1578 1576 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1579 1577 "Enumerator name attribute missing.\n");
1580 1578 (void) topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
1581 1579 goto enodedone;
1582 1580 }
1583 1581
1584 1582 /*
1585 1583 * Check for recursive enumeration
1586 1584 */
1587 1585 if (strcmp(einfo->te_name, mp->tm_name) == 0) {
1588 1586 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1589 1587 "Recursive enumeration detected for %s\n",
1590 1588 einfo->te_name);
1591 1589 (void) topo_mod_seterrno(mp, ETOPO_ENUM_RECURS);
1592 1590 goto enodedone;
1593 1591 }
1594 1592 if (xmlattr_to_int(mp, en, Version, &ui) < 0)
1595 1593 goto enodedone;
1596 1594 einfo->te_vers = (int)ui;
1597 1595
1598 1596 return (einfo);
1599 1597
1600 1598 enodedone:
1601 1599 if (einfo->te_name != NULL)
1602 1600 xmlFree(einfo->te_name);
1603 1601 topo_mod_free(mp, einfo, sizeof (tf_edata_t));
1604 1602 return (NULL);
1605 1603 }
1606 1604
1607 1605 static int
1608 1606 enum_run(topo_mod_t *mp, tf_rdata_t *rd)
1609 1607 {
1610 1608 topo_hdl_t *thp = mp->tm_hdl;
1611 1609 int e = -1;
1612 1610
1613 1611 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "enum_run\n");
1614 1612 /*
1615 1613 * Check if the enumerator module is already loaded.
1616 1614 * Module loading is single-threaded at this point so there's
1617 1615 * no need to worry about the module going away or bumping the
1618 1616 * ref count.
1619 1617 */
1620 1618 if ((rd->rd_mod = topo_mod_lookup(thp, rd->rd_einfo->te_name,
1621 1619 0)) == NULL) {
1622 1620 if ((rd->rd_mod = topo_mod_load(mp, rd->rd_einfo->te_name,
1623 1621 rd->rd_einfo->te_vers)) == NULL) {
1624 1622 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1625 1623 "enum_run: mod_load of %s failed: %s.\n",
1626 1624 rd->rd_einfo->te_name,
1627 1625 topo_strerror(topo_mod_errno(mp)));
1628 1626 (void) topo_hdl_seterrno(thp, topo_mod_errno(mp));
1629 1627 return (e);
1630 1628 }
1631 1629 }
1632 1630 /*
1633 1631 * We're live, so let's enumerate.
1634 1632 */
1635 1633 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "enumerate request. (%s)\n",
1636 1634 rd->rd_einfo->te_name);
1637 1635 e = topo_mod_enumerate(rd->rd_mod, rd->rd_pn, rd->rd_einfo->te_name,
1638 1636 rd->rd_name, rd->rd_min, rd->rd_max, NULL);
1639 1637 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "back from enumeration. %d\n",
1640 1638 e);
1641 1639 if (e != 0) {
1642 1640 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1643 1641 "Enumeration failed (%s)\n",
1644 1642 topo_strerror(topo_mod_errno(mp)));
1645 1643 (void) topo_hdl_seterrno(thp, EMOD_PARTIAL_ENUM);
1646 1644 return (topo_mod_seterrno(mp, EMOD_PARTIAL_ENUM));
1647 1645 }
1648 1646 return (e);
1649 1647 }
1650 1648
1651 1649 static int
1652 1650 fac_enum_run(topo_mod_t *mp, tnode_t *node, const char *name)
1653 1651 {
1654 1652 topo_hdl_t *thp = mp->tm_hdl;
1655 1653 topo_mod_t *fmod;
1656 1654 int e = -1;
1657 1655
1658 1656 topo_dprintf(thp, TOPO_DBG_XML, "fac_enum_run\n");
1659 1657 /*
1660 1658 * Check if the enumerator module is already loaded.
1661 1659 * Module loading is single-threaded at this point so there's
1662 1660 * no need to worry about the module going away or bumping the
1663 1661 * ref count.
1664 1662 */
1665 1663 if ((fmod = topo_mod_lookup(thp, name, 0)) == NULL) {
1666 1664 if ((fmod = topo_mod_load(mp, name, TOPO_VERSION)) == NULL) {
1667 1665 topo_dprintf(thp, TOPO_DBG_ERR,
1668 1666 "fac_enum_run: mod_load of %s failed: %s.\n",
1669 1667 name, topo_strerror(topo_mod_errno(mp)));
1670 1668 (void) topo_hdl_seterrno(thp, topo_mod_errno(mp));
1671 1669 return (e);
1672 1670 }
1673 1671 }
1674 1672 /*
1675 1673 * We're live, so let's enumerate.
1676 1674 */
1677 1675 topo_dprintf(thp, TOPO_DBG_XML, "fac enumerate request. (%s)\n", name);
1678 1676 e = topo_mod_enumerate(fmod, node, name, name, 0, 0, NULL);
1679 1677 topo_dprintf(thp, TOPO_DBG_XML, "back from enumeration. %d\n", e);
1680 1678 if (e != 0) {
1681 1679 topo_dprintf(thp, TOPO_DBG_ERR,
1682 1680 "Facility provider enumeration failed (%s)\n",
1683 1681 topo_strerror(topo_mod_errno(mp)));
1684 1682 (void) topo_hdl_seterrno(thp, EMOD_PARTIAL_ENUM);
1685 1683 return (topo_mod_seterrno(mp, EMOD_PARTIAL_ENUM));
1686 1684 }
1687 1685 return (e);
1688 1686 }
1689 1687
1690 1688 int
1691 1689 decorate_nodes(topo_mod_t *mp, tf_rdata_t *rd, xmlNodePtr pxn, tnode_t *ptn,
1692 1690 tf_pad_t **rpad)
1693 1691 {
1694 1692 tnode_t *ctn;
1695 1693
1696 1694 ctn = topo_child_first(ptn);
1697 1695 while (ctn != NULL) {
1698 1696 /* Only care about instances within the range */
1699 1697 if (strcmp(topo_node_name(ctn), rd->rd_name) != 0) {
1700 1698 ctn = topo_child_next(ptn, ctn);
1701 1699 continue;
1702 1700 }
1703 1701 if (pad_process(mp, rd, pxn, ctn, rpad) < 0)
1704 1702 return (-1);
1705 1703 if (decorate_nodes(mp, rd, pxn, ctn, rpad) < 0)
1706 1704 return (-1);
1707 1705 ctn = topo_child_next(ptn, ctn);
1708 1706 }
1709 1707 return (0);
1710 1708 }
1711 1709
1712 1710 int
1713 1711 topo_xml_range_process(topo_mod_t *mp, xmlNodePtr rn, tf_rdata_t *rd)
1714 1712 {
1715 1713 /*
1716 1714 * The range may have several children xmlNodes, that may
1717 1715 * represent the enumeration method, property groups,
1718 1716 * dependents, nodes or services.
1719 1717 */
1720 1718 xmlNodePtr cn, enum_node = NULL, pmap_node = NULL;
1721 1719 xmlChar *pmap_name;
1722 1720 tnode_t *ct;
1723 1721 int e, ccnt = 0;
1724 1722
1725 1723 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "topo_xml_range_process\n"
1726 1724 "process %s range beneath %s\n", rd->rd_name,
1727 1725 topo_node_name(rd->rd_pn));
1728 1726
1729 1727 e = topo_node_range_create(mp,
1730 1728 rd->rd_pn, rd->rd_name, rd->rd_min, rd->rd_max);
1731 1729 if (e != 0 && topo_mod_errno(mp) != EMOD_NODE_DUP) {
1732 1730 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1733 1731 "Range create failed due to %s.\n",
1734 1732 topo_strerror(topo_mod_errno(mp)));
1735 1733 return (-1);
1736 1734 }
1737 1735
1738 1736 /*
1739 1737 * Before we process any of the other child xmlNodes, we iterate through
1740 1738 * the children and looking for either enum-method or propmap elements.
1741 1739 */
1742 1740 for (cn = rn->xmlChildrenNode; cn != NULL; cn = cn->next)
1743 1741 if (xmlStrcmp(cn->name, (xmlChar *)Enum_meth) == 0)
1744 1742 enum_node = cn;
1745 1743 else if (xmlStrcmp(cn->name, (xmlChar *)Propmap) == 0)
1746 1744 pmap_node = cn;
1747 1745
1748 1746 /*
1749 1747 * If we found an enum-method element, process it first
1750 1748 */
1751 1749 if (enum_node != NULL) {
1752 1750 if ((rd->rd_einfo = enum_attributes_process(mp, enum_node))
1753 1751 == NULL)
1754 1752 return (-1);
1755 1753 if (enum_run(mp, rd) < 0) {
1756 1754 /*
1757 1755 * Note the failure but continue on
1758 1756 */
1759 1757 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1760 1758 "Enumeration failed.\n");
1761 1759 }
1762 1760 }
1763 1761
1764 1762 /*
1765 1763 * Next, check if a propmap element was found and if so, load it in
1766 1764 * and parse it.
1767 1765 */
1768 1766 if (pmap_node != NULL) {
1769 1767 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "found a propmap "
1770 1768 "element\n");
1771 1769 if ((pmap_name = xmlGetProp(pmap_node, (xmlChar *)Name))
1772 1770 == NULL) {
1773 1771 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1774 1772 "propmap element missing name attribute.\n");
1775 1773 } else {
1776 1774 if (topo_file_load(mp, rd->rd_pn,
1777 1775 (const char *)pmap_name,
1778 1776 rd->rd_finfo->tf_scheme, 1) < 0) {
1779 1777
1780 1778 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1781 1779 "topo_xml_range_process: topo_file_load"
1782 1780 "failed: %s.\n",
1783 1781 topo_strerror(topo_mod_errno(mp)));
1784 1782 }
1785 1783 xmlFree(pmap_name);
1786 1784 }
1787 1785 }
1788 1786
1789 1787 /* Now look for nodes, i.e., hard instances */
1790 1788 for (cn = rn->xmlChildrenNode; cn != NULL; cn = cn->next) {
1791 1789 if (xmlStrcmp(cn->name, (xmlChar *)Node) == 0) {
1792 1790 if (node_process(mp, cn, rd) < 0) {
1793 1791 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
1794 1792 "node processing failed: %s.\n",
1795 1793 topo_strerror(topo_mod_errno(mp)));
1796 1794 return (topo_mod_seterrno(mp,
1797 1795 EMOD_PARTIAL_ENUM));
1798 1796 }
1799 1797 ccnt++;
1800 1798 }
1801 1799 }
1802 1800
1803 1801 /*
1804 1802 * Finally, process the property groups and dependents
1805 1803 *
1806 1804 * If the TF_PROPMAP flag is set for the XML file we're currently
1807 1805 * processing, then this XML file was loaded via propmap. In that case
1808 1806 * we call a special routine to recursively apply the propgroup settings
1809 1807 * to all of nodes in this range
1810 1808 */
1811 1809 if (rd->rd_finfo->tf_flags & TF_PROPMAP)
1812 1810 (void) decorate_nodes(mp, rd, rn, rd->rd_pn, &rd->rd_pad);
1813 1811 else {
1814 1812 ct = topo_child_first(rd->rd_pn);
1815 1813 while (ct != NULL) {
1816 1814 /* Only care about instances within the range */
1817 1815 if (strcmp(topo_node_name(ct), rd->rd_name) != 0) {
1818 1816 ct = topo_child_next(rd->rd_pn, ct);
1819 1817 continue;
1820 1818 }
1821 1819 if (pad_process(mp, rd, rn, ct, &rd->rd_pad)
1822 1820 < 0)
1823 1821 return (-1);
1824 1822
1825 1823 if (fac_process(mp, rn, rd, ct) < 0)
1826 1824 return (-1);
1827 1825
1828 1826 ct = topo_child_next(rd->rd_pn, ct);
1829 1827 ccnt++;
1830 1828 }
1831 1829 }
1832 1830
1833 1831 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "topo_xml_range_process: end "
1834 1832 "range process %s\n", rd->rd_name);
1835 1833
1836 1834 return (0);
1837 1835 }
1838 1836
1839 1837 static tf_rdata_t *
1840 1838 topo_xml_walk(topo_mod_t *mp,
1841 1839 tf_info_t *xinfo, xmlNodePtr croot, tnode_t *troot)
1842 1840 {
1843 1841 xmlNodePtr curr, def_set = NULL;
1844 1842 tf_rdata_t *rr, *pr, *rdp;
1845 1843 xmlChar *set;
1846 1844 char *key;
1847 1845 int joined_set = 0;
1848 1846
1849 1847 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "topo_xml_walk\n");
1850 1848 rr = pr = NULL;
1851 1849 /*
1852 1850 * First iterate through all the XML nodes at this level to look for
1853 1851 * set nodes.
1854 1852 */
1855 1853 for (curr = croot->xmlChildrenNode; curr != NULL; curr = curr->next) {
1856 1854 if (curr->name == NULL) {
1857 1855 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1858 1856 "topo_xml_walk: Ignoring nameless xmlnode\n");
1859 1857 continue;
1860 1858 }
1861 1859 if (xmlStrcmp(curr->name, (xmlChar *)Set) == 0) {
1862 1860 if (joined_set)
1863 1861 continue;
1864 1862
1865 1863 set = xmlGetProp(curr, (xmlChar *)Setlist);
1866 1864
1867 1865 if (mp->tm_hdl->th_product)
1868 1866 key = mp->tm_hdl->th_product;
1869 1867 else
1870 1868 key = mp->tm_hdl->th_platform;
1871 1869
1872 1870 /*
1873 1871 * If it's the default set then we'll store
1874 1872 * a pointer to it so that if none of the other
1875 1873 * sets apply to our product we can fall
1876 1874 * back to this one.
1877 1875 */
1878 1876 if (strcmp((char *)set, "default") == 0)
1879 1877 def_set = curr;
1880 1878 else if (set_contains(mp, key, (char *)set)) {
1881 1879 joined_set = 1;
1882 1880 if ((rdp = topo_xml_walk(mp, xinfo, curr,
1883 1881 troot)) == NULL) {
1884 1882 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1885 1883 "topo_xml_walk: failed1\n");
1886 1884 } else {
1887 1885 if (pr == NULL) {
1888 1886 rr = pr = rdp;
1889 1887 } else {
1890 1888 pr->rd_next = rdp;
1891 1889 pr = rdp;
1892 1890 }
1893 1891 rr->rd_cnt++;
1894 1892 }
1895 1893 }
1896 1894 xmlFree(set);
1897 1895 }
1898 1896 }
1899 1897 /*
1900 1898 * If we haven't found a set that contains our product AND a default set
1901 1899 * exists, then we'll process it.
1902 1900 */
1903 1901 if (!joined_set && def_set) {
1904 1902 if ((rdp = topo_xml_walk(mp, xinfo, def_set, troot)) == NULL) {
1905 1903 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1906 1904 "topo_xml_walk: failed2\n");
1907 1905 }
1908 1906 if (pr == NULL) {
1909 1907 rr = pr = rdp;
1910 1908 } else {
1911 1909 pr->rd_next = rdp;
1912 1910 pr = rdp;
1913 1911 }
1914 1912 rr->rd_cnt++;
1915 1913 }
1916 1914 /*
1917 1915 * Now we're interested in children xmlNodes of croot tagged
1918 1916 * as 'ranges'. These define what topology nodes may exist, and need
1919 1917 * to be verified.
1920 1918 */
1921 1919 for (curr = croot->xmlChildrenNode; curr != NULL; curr = curr->next) {
1922 1920 if (curr->name == NULL) {
1923 1921 topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
1924 1922 "topo_xml_walk: Ignoring nameless xmlnode\n");
1925 1923 continue;
1926 1924 }
1927 1925 if (xmlStrcmp(curr->name, (xmlChar *)Range) != 0)
1928 1926 continue;
1929 1927 if ((rdp = tf_rdata_new(mp, xinfo, curr, troot)) == NULL) {
1930 1928 /*
1931 1929 * Range processing error, continue walk
1932 1930 */
1933 1931 continue;
1934 1932 }
1935 1933 if (pr == NULL) {
1936 1934 rr = pr = rdp;
1937 1935 } else {
1938 1936 pr->rd_next = rdp;
1939 1937 pr = rdp;
1940 1938 }
1941 1939 rr->rd_cnt++;
1942 1940 }
1943 1941
1944 1942 return (rr);
1945 1943 }
1946 1944
1947 1945 /*
1948 1946 * Convert parsed xml topology description into topology nodes
1949 1947 */
1950 1948 int
1951 1949 topo_xml_enum(topo_mod_t *tmp, tf_info_t *xinfo, tnode_t *troot)
1952 1950 {
1953 1951 xmlNodePtr xroot;
1954 1952
1955 1953 topo_dprintf(tmp->tm_hdl, TOPO_DBG_XML, "topo_xml_enum\n");
1956 1954
1957 1955 if ((xroot = xmlDocGetRootElement(xinfo->tf_xdoc)) == NULL) {
1958 1956 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
1959 1957 "Couldn't get root xmlNode.\n");
1960 1958 return (-1);
1961 1959 }
1962 1960 if ((xinfo->tf_rd = topo_xml_walk(tmp, xinfo, xroot, troot)) == NULL) {
1963 1961 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
1964 1962 "error within .xml topology: %s\n",
1965 1963 topo_strerror(topo_mod_errno(tmp)));
1966 1964 return (-1);
1967 1965 }
1968 1966 return (0);
1969 1967 }
1970 1968
1971 1969 /*
1972 1970 * Load an XML tree from filename and read it into a DOM parse tree.
1973 1971 */
1974 1972 static tf_info_t *
1975 1973 txml_file_parse(topo_mod_t *tmp,
1976 1974 int fd, const char *filenm, const char *escheme)
1977 1975 {
1978 1976 xmlValidCtxtPtr vcp;
1979 1977 xmlNodePtr cursor;
1980 1978 xmlDocPtr document;
1981 1979 xmlDtdPtr dtd = NULL;
1982 1980 xmlChar *scheme = NULL;
1983 1981 char *dtdpath = NULL;
1984 1982 int readflags = 0;
1985 1983 tf_info_t *r;
1986 1984 int e, validate = 0;
1987 1985
1988 1986 topo_dprintf(tmp->tm_hdl, TOPO_DBG_XML,
1989 1987 "txml_file_parse(filenm=%s, escheme=%s)\n", filenm, escheme);
1990 1988
1991 1989 /*
1992 1990 * Since topologies can XInclude other topologies, and libxml2
1993 1991 * doesn't do DTD-based validation with XInclude, by default
1994 1992 * we don't validate topology files. One can force
1995 1993 * validation, though, by creating a TOPOXML_VALIDATE
1996 1994 * environment variable and creating a TOPO_DTD environment
1997 1995 * variable with the path to the DTD against which to validate.
1998 1996 */
1999 1997 if (getenv("TOPOXML_VALIDATE") != NULL) {
2000 1998 dtdpath = getenv("TOPO_DTD");
2001 1999 if (dtdpath != NULL)
2002 2000 xmlLoadExtDtdDefaultValue = 0;
2003 2001 validate = 1;
2004 2002 }
2005 2003
2006 2004 /*
2007 2005 * Splat warnings and errors related to parsing the topology
2008 2006 * file if the TOPOXML_PERROR environment variable exists.
2009 2007 */
2010 2008 if (getenv("TOPOXML_PERROR") == NULL)
2011 2009 readflags = XML_PARSE_NOERROR | XML_PARSE_NOWARNING;
2012 2010
2013 2011 if ((document = xmlReadFd(fd, filenm, NULL, readflags)) == NULL) {
2014 2012 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2015 2013 "txml_file_parse: couldn't parse document.\n");
2016 2014 return (NULL);
2017 2015 }
2018 2016
2019 2017 /*
2020 2018 * Verify that this is a document type we understand.
2021 2019 */
2022 2020 if ((dtd = xmlGetIntSubset(document)) == NULL) {
2023 2021 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2024 2022 "document has no DTD.\n");
2025 2023 xmlFreeDoc(document);
2026 2024 return (NULL);
2027 2025 }
2028 2026
2029 2027 if (strcmp((const char *)dtd->SystemID, TOPO_DTD_PATH) != 0) {
2030 2028 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2031 2029 "document DTD unknown; bad topology file\n");
2032 2030 xmlFreeDoc(document);
2033 2031 return (NULL);
2034 2032 }
2035 2033
2036 2034 if ((cursor = xmlDocGetRootElement(document)) == NULL) {
2037 2035 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR, "document is empty.\n");
2038 2036 xmlFreeDoc(document);
2039 2037 return (NULL);
2040 2038 }
2041 2039
2042 2040 /*
2043 2041 * Make sure we're looking at a topology description in the
2044 2042 * expected scheme.
2045 2043 */
2046 2044 if (xmlStrcmp(cursor->name, (xmlChar *)Topology) != 0) {
2047 2045 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2048 2046 "document is not a topology description.\n");
2049 2047 xmlFreeDoc(document);
2050 2048 return (NULL);
2051 2049 }
2052 2050 if ((scheme = xmlGetProp(cursor, (xmlChar *)Scheme)) == NULL) {
2053 2051 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2054 2052 "topology lacks a scheme.\n");
2055 2053 (void) topo_mod_seterrno(tmp, ETOPO_PRSR_NOATTR);
2056 2054 xmlFreeDoc(document);
2057 2055 return (NULL);
2058 2056 }
2059 2057 if (xmlStrcmp(scheme, (xmlChar *)escheme) != 0) {
2060 2058 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2061 2059 "topology in unrecognized scheme, %s, expecting %s\n",
2062 2060 scheme, escheme);
2063 2061 (void) topo_mod_seterrno(tmp, ETOPO_PRSR_BADSCH);
2064 2062 xmlFree(scheme);
2065 2063 xmlFreeDoc(document);
2066 2064 return (NULL);
2067 2065 }
2068 2066
2069 2067 if (dtdpath != NULL) {
2070 2068 dtd = xmlParseDTD(NULL, (xmlChar *)dtdpath);
2071 2069 if (dtd == NULL) {
2072 2070 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2073 2071 "Could not parse DTD \"%s\".\n",
2074 2072 dtdpath);
2075 2073 xmlFree(scheme);
2076 2074 xmlFreeDoc(document);
2077 2075 return (NULL);
2078 2076 }
2079 2077
2080 2078 if (document->extSubset != NULL)
2081 2079 xmlFreeDtd(document->extSubset);
2082 2080
2083 2081 document->extSubset = dtd;
2084 2082 }
2085 2083
2086 2084 if (xmlXIncludeProcessFlags(document, XML_PARSE_XINCLUDE) == -1) {
2087 2085 xmlFree(scheme);
2088 2086 xmlFreeDoc(document);
2089 2087 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2090 2088 "couldn't handle XInclude statements in document\n");
2091 2089 return (NULL);
2092 2090 }
2093 2091
2094 2092 if (validate) {
2095 2093 if ((vcp = xmlNewValidCtxt()) == NULL) {
2096 2094 xmlFree(scheme);
2097 2095 xmlFreeDoc(document);
2098 2096 return (NULL);
2099 2097 }
2100 2098 vcp->warning = xmlParserValidityWarning;
2101 2099 vcp->error = xmlParserValidityError;
2102 2100
2103 2101 e = xmlValidateDocument(vcp, document);
2104 2102
2105 2103 xmlFreeValidCtxt(vcp);
2106 2104
2107 2105 if (e == 0)
2108 2106 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2109 2107 "Document is not valid.\n");
2110 2108 }
2111 2109
2112 2110 if ((r = tf_info_new(tmp, document, scheme)) == NULL) {
2113 2111 xmlFree(scheme);
2114 2112 xmlFreeDoc(document);
2115 2113 return (NULL);
2116 2114 }
2117 2115
2118 2116 xmlFree(scheme);
2119 2117 scheme = NULL;
2120 2118 return (r);
2121 2119 }
2122 2120
2123 2121 tf_info_t *
2124 2122 topo_xml_read(topo_mod_t *tmp, const char *path, const char *escheme)
2125 2123 {
2126 2124 int fd;
2127 2125 tf_info_t *tip;
2128 2126
2129 2127 if ((fd = open(path, O_RDONLY)) < 0) {
2130 2128 topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
2131 2129 "failed to open %s for reading\n", path);
2132 2130 return (NULL);
2133 2131 }
2134 2132 tip = txml_file_parse(tmp, fd, path, escheme);
2135 2133 (void) close(fd);
2136 2134 return (tip);
2137 2135 }
↓ open down ↓ |
1021 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX