root/opal/mca/hwloc/hwloc201/hwloc/hwloc/topology-xml-libxml.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hwloc_libxml2_error_callback
  2. hwloc_libxml2_init_once
  3. hwloc_libxml2_cleanup
  4. hwloc__libxml_import_next_attr
  5. hwloc__libxml_import_find_child
  6. hwloc__libxml_import_close_tag
  7. hwloc__libxml_import_close_child
  8. hwloc__libxml_import_get_content
  9. hwloc__libxml_import_close_content
  10. hwloc_libxml_look_init
  11. hwloc_libxml_free_buffers
  12. hwloc_libxml_look_done
  13. hwloc_libxml_import_diff
  14. hwloc_libxml_backend_exit
  15. hwloc_libxml_backend_init
  16. hwloc__libxml_export_new_child
  17. hwloc__libxml_export_new_prop
  18. hwloc__libxml_export_end_object
  19. hwloc__libxml_export_add_content
  20. hwloc__libxml2_prepare_export
  21. hwloc_libxml_export_file
  22. hwloc_libxml_export_buffer
  23. hwloc__libxml2_prepare_export_diff
  24. hwloc_libxml_export_diff_file
  25. hwloc_libxml_export_diff_buffer
  26. hwloc_libxml_free_buffer
  27. hwloc_xml_libxml_component_init

   1 /*
   2  * Copyright © 2009 CNRS
   3  * Copyright © 2009-2018 Inria.  All rights reserved.
   4  * Copyright © 2009-2011 Université Bordeaux
   5  * Copyright © 2009-2011 Cisco Systems, Inc.  All rights reserved.
   6  * See COPYING in top-level directory.
   7  */
   8 
   9 #include <private/autogen/config.h>
  10 #include <hwloc.h>
  11 #include <hwloc/plugins.h>
  12 
  13 /* private headers allowed because this plugin is built within hwloc */
  14 #include <private/xml.h>
  15 #include <private/debug.h>
  16 #include <private/misc.h>
  17 
  18 #include <libxml/parser.h>
  19 #include <libxml/tree.h>
  20 
  21 /*******************
  22  * Common routines *
  23  *******************/
  24 
  25 static void hwloc_libxml2_error_callback(void * ctx __hwloc_attribute_unused, const char * msg __hwloc_attribute_unused, ...) { /* do nothing */ }
  26 
  27 /* by default, do not cleanup to avoid issues with concurrent libxml users */
  28 static int hwloc_libxml2_needs_cleanup = 0;
  29 
  30 static void
  31 hwloc_libxml2_init_once(void)
  32 {
  33   static int checked = 0;
  34   if (!checked) {
  35     /* disable stderr warnings */
  36     xmlSetGenericErrorFunc(NULL, hwloc__xml_verbose() ? xmlGenericError : hwloc_libxml2_error_callback);
  37     /* enforce libxml2 cleanup ? */
  38     if (getenv("HWLOC_LIBXML_CLEANUP"))
  39       hwloc_libxml2_needs_cleanup = 1;
  40     checked = 1;
  41   }
  42 }
  43 
  44 static void
  45 hwloc_libxml2_cleanup(void)
  46 {
  47   if (hwloc_libxml2_needs_cleanup) {
  48     xmlCleanupParser();
  49   }
  50 }
  51 
  52 /*******************
  53  * Import routines *
  54  *******************/
  55 
  56 typedef struct hwloc__libxml_import_state_data_s {
  57   xmlNode *node; /* current libxml node, always valid */
  58   xmlNode *child; /* next processed child, or NULL if none yet */
  59   xmlAttr *attr; /* last processed attribute, or NULL if none yet */
  60 } __hwloc_attribute_may_alias * hwloc__libxml_import_state_data_t;
  61 
  62 static int
  63 hwloc__libxml_import_next_attr(hwloc__xml_import_state_t state, char **namep, char **valuep)
  64 {
  65   hwloc__libxml_import_state_data_t lstate = (void*) state->data;
  66 
  67   xmlAttr *attr;
  68   if (lstate->attr)
  69     attr = lstate->attr->next;
  70   else
  71     attr = lstate->node->properties;
  72   for (; attr; attr = attr->next)
  73     if (attr->type == XML_ATTRIBUTE_NODE) {
  74       /* use the first valid attribute content */
  75       xmlNode *subnode;
  76       for (subnode = attr->children; subnode; subnode = subnode->next) {
  77         if (subnode->type == XML_TEXT_NODE) {
  78           if (subnode->content) {
  79             *namep = (char *) attr->name;
  80             *valuep = (char *) subnode->content;
  81             lstate->attr = attr;
  82             return 0;
  83           }
  84         } else {
  85           if (hwloc__xml_verbose())
  86             fprintf(stderr, "%s: ignoring unexpected xml attr node type %u\n",
  87                     state->global->msgprefix, subnode->type);
  88         }
  89       }
  90     } else {
  91       if (hwloc__xml_verbose())
  92         fprintf(stderr, "%s: ignoring unexpected xml attr type %u\n",
  93                 state->global->msgprefix, attr->type);
  94     }
  95   return -1;
  96 }
  97 
  98 static int
  99 hwloc__libxml_import_find_child(hwloc__xml_import_state_t state,
 100                                 hwloc__xml_import_state_t childstate,
 101                                 char **tagp)
 102 {
 103   hwloc__libxml_import_state_data_t lstate = (void*) state->data;
 104   hwloc__libxml_import_state_data_t lchildstate = (void*) childstate->data;
 105   xmlNode *child;
 106   childstate->parent = state;
 107   childstate->global = state->global;
 108   if (!lstate->child)
 109     /* All children proceeded */
 110     return 0;
 111 
 112   child = lstate->child;
 113   if (child->type == XML_ELEMENT_NODE) {
 114     lstate->child = child->next;
 115     lchildstate->node = child;
 116     lchildstate->child = child->children;
 117     lchildstate->attr = NULL;
 118     *tagp = (char*) child->name;
 119     return 1;
 120   } else if (child->type == XML_TEXT_NODE) {
 121     if (child->content && child->content[0] != '\0' && child->content[0] != '\n')
 122       if (hwloc__xml_verbose())
 123         fprintf(stderr, "%s: ignoring object text content %s\n",
 124                 state->global->msgprefix, (const char*) child->content);
 125   } else if (child->type != XML_COMMENT_NODE) {
 126       if (hwloc__xml_verbose())
 127         fprintf(stderr, "%s: ignoring unexpected xml node type %u\n",
 128                 state->global->msgprefix, child->type);
 129   }
 130 
 131   return 0;
 132 }
 133 
 134 static int
 135 hwloc__libxml_import_close_tag(hwloc__xml_import_state_t state __hwloc_attribute_unused)
 136 {
 137   return 0;
 138 }
 139 
 140 static void
 141 hwloc__libxml_import_close_child(hwloc__xml_import_state_t state __hwloc_attribute_unused)
 142 {
 143   /* nothing to do */
 144 }
 145 
 146 static int
 147 hwloc__libxml_import_get_content(hwloc__xml_import_state_t state,
 148                                  char **beginp, size_t expected_length)
 149 {
 150   hwloc__libxml_import_state_data_t lstate = (void*) state->data;
 151   xmlNode *child;
 152   size_t length;
 153 
 154   child = lstate->node->children;
 155   if (!child || child->type != XML_TEXT_NODE) {
 156     if (expected_length)
 157       return -1;
 158     *beginp = (char *) "";
 159     return 0;
 160   }
 161 
 162   length = strlen((char *) child->content);
 163   if (length != expected_length)
 164     return -1;
 165   *beginp = (char *) child->content;
 166   return 1;
 167 }
 168 
 169 static void
 170 hwloc__libxml_import_close_content(hwloc__xml_import_state_t state __hwloc_attribute_unused)
 171 {
 172   /* nothing to do */
 173 }
 174 
 175 static int
 176 hwloc_libxml_look_init(struct hwloc_xml_backend_data_s *bdata,
 177                        struct hwloc__xml_import_state_s *state)
 178 {
 179   hwloc__libxml_import_state_data_t lstate = (void*) state->data;
 180   xmlNodePtr root_node;
 181   xmlDtdPtr dtd;
 182 
 183   HWLOC_BUILD_ASSERT(sizeof(*lstate) <= sizeof(state->data));
 184 
 185   dtd = xmlGetIntSubset((xmlDocPtr) bdata->data);
 186   if (!dtd) {
 187     if (hwloc__xml_verbose())
 188       fprintf(stderr, "%s: Loading XML topology without DTD\n",
 189               state->global->msgprefix);
 190   } else if (strcmp((char *) dtd->SystemID, "hwloc.dtd")
 191              && strcmp((char *) dtd->SystemID, "hwloc2.dtd")) {
 192     if (hwloc__xml_verbose())
 193       fprintf(stderr, "%s: Loading XML topology with wrong DTD SystemID (%s instead of %s)\n",
 194               state->global->msgprefix, (char *) dtd->SystemID, "hwloc.dtd or hwloc2.dtd");
 195   }
 196 
 197   root_node = xmlDocGetRootElement((xmlDocPtr) bdata->data);
 198 
 199   if (!strcmp((const char *) root_node->name, "root")) {
 200     bdata->version_major = 0;
 201     bdata->version_minor = 9;
 202   } else if (!strcmp((const char *) root_node->name, "topology")) {
 203     unsigned major, minor;
 204     xmlChar *version = xmlGetProp(root_node, (xmlChar*) "version");
 205     if (version && sscanf((const char *)version, "%u.%u", &major, &minor) == 2) {
 206       bdata->version_major = major;
 207       bdata->version_minor = minor;
 208     } else {
 209       bdata->version_major = 1;
 210       bdata->version_minor = 0;
 211     }
 212     xmlFree(version);
 213   } else {
 214     /* root node should be in "topology" class (or "root" if importing from < 1.0) */
 215     if (hwloc__xml_verbose())
 216       fprintf(stderr, "%s: ignoring object of class `%s' not at the top the xml hierarchy\n",
 217               state->global->msgprefix, (const char *) root_node->name);
 218     goto failed;
 219   }
 220 
 221   state->global->next_attr = hwloc__libxml_import_next_attr;
 222   state->global->find_child = hwloc__libxml_import_find_child;
 223   state->global->close_tag = hwloc__libxml_import_close_tag;
 224   state->global->close_child = hwloc__libxml_import_close_child;
 225   state->global->get_content = hwloc__libxml_import_get_content;
 226   state->global->close_content = hwloc__libxml_import_close_content;
 227   state->parent = NULL;
 228   lstate->node = root_node;
 229   lstate->child = root_node->children;
 230   lstate->attr = NULL;
 231   return 0; /* success */
 232 
 233  failed:
 234   return -1; /* failed */
 235 }
 236 
 237 /* can be called at the end of the import (to cleanup things early),
 238  * or by backend_exit() if load failed for other reasons.
 239  */
 240 static void
 241 hwloc_libxml_free_buffers(struct hwloc_xml_backend_data_s *bdata)
 242 {
 243   if (bdata->data) {
 244     xmlFreeDoc((xmlDoc*)bdata->data);
 245     bdata->data = NULL;
 246   }
 247 }
 248 
 249 static void
 250 hwloc_libxml_look_done(struct hwloc_xml_backend_data_s *bdata, int result __hwloc_attribute_unused)
 251 {
 252   hwloc_libxml_free_buffers(bdata);
 253 }
 254 
 255 static int
 256 hwloc_libxml_import_diff(struct hwloc__xml_import_state_s *state, const char *xmlpath, const char *xmlbuffer, int xmlbuflen, hwloc_topology_diff_t *firstdiffp, char **refnamep)
 257 {
 258   hwloc__libxml_import_state_data_t lstate = (void*) state->data;
 259   char *refname = NULL;
 260   xmlDoc *doc = NULL;
 261   xmlNode* root_node;
 262   xmlDtd *dtd;
 263   int ret;
 264 
 265   HWLOC_BUILD_ASSERT(sizeof(*lstate) <= sizeof(state->data));
 266 
 267   LIBXML_TEST_VERSION;
 268   hwloc_libxml2_init_once();
 269 
 270   errno = 0; /* set to 0 so that we know if libxml2 changed it */
 271 
 272   if (xmlpath)
 273     doc = xmlReadFile(xmlpath, NULL, XML_PARSE_NOBLANKS);
 274   else if (xmlbuffer)
 275     doc = xmlReadMemory(xmlbuffer, xmlbuflen, "", NULL, XML_PARSE_NOBLANKS);
 276 
 277   if (!doc) {
 278     if (!errno)
 279       /* libxml2 read the file fine, but it got an error during parsing */
 280       errno = EINVAL;
 281     hwloc_libxml2_cleanup();
 282     goto out;
 283   }
 284 
 285   dtd = xmlGetIntSubset(doc);
 286   if (!dtd) {
 287     if (hwloc__xml_verbose())
 288       fprintf(stderr, "%s: Loading XML topologydiff without DTD\n",
 289               state->global->msgprefix);
 290   } else if (strcmp((char *) dtd->SystemID, "hwloc2-diff.dtd")) {
 291     if (hwloc__xml_verbose())
 292       fprintf(stderr, "%s: Loading XML topologydiff with wrong DTD SystemID (%s instead of %s)\n",
 293               state->global->msgprefix, (char *) dtd->SystemID, "hwloc2-diff.dtd");
 294   }
 295 
 296   root_node = xmlDocGetRootElement(doc);
 297 
 298   if (strcmp((const char *) root_node->name, "topologydiff")) {
 299     /* root node should be in "topologydiff" class */
 300     if (hwloc__xml_verbose())
 301       fprintf(stderr, "%s: ignoring object of class `%s' not at the top the xml hierarchy\n",
 302               state->global->msgprefix, (const char *) root_node->name);
 303     goto out_with_doc;
 304   }
 305 
 306   state->global->next_attr = hwloc__libxml_import_next_attr;
 307   state->global->find_child = hwloc__libxml_import_find_child;
 308   state->global->close_tag = hwloc__libxml_import_close_tag;
 309   state->global->close_child = hwloc__libxml_import_close_child;
 310   state->global->get_content = hwloc__libxml_import_get_content;
 311   state->global->close_content = hwloc__libxml_import_close_content;
 312   state->parent = NULL;
 313   lstate->node = root_node;
 314   lstate->child = root_node->children;
 315   lstate->attr = NULL;
 316 
 317   while (1) {
 318     char *attrname, *attrvalue;
 319     if (state->global->next_attr(state, &attrname, &attrvalue) < 0)
 320       break;
 321     if (!strcmp(attrname, "refname")) {
 322       free(refname);
 323       refname = strdup(attrvalue);
 324     } else
 325       goto out_with_doc;
 326   }
 327 
 328   ret = hwloc__xml_import_diff(state, firstdiffp);
 329   if (refnamep && !ret)
 330     *refnamep = refname;
 331   else
 332     free(refname);
 333 
 334   xmlFreeDoc(doc);
 335   hwloc_libxml2_cleanup();
 336   return ret;
 337 
 338 out_with_doc:
 339   free(refname);
 340   xmlFreeDoc(doc);
 341   hwloc_libxml2_cleanup();
 342 out:
 343   return -1; /* failed */
 344 }
 345 
 346 /********************
 347  * Backend routines *
 348  ********************/
 349 
 350 static void
 351 hwloc_libxml_backend_exit(struct hwloc_xml_backend_data_s *bdata)
 352 {
 353   hwloc_libxml_free_buffers(bdata);
 354   hwloc_libxml2_cleanup();
 355 }
 356 
 357 static int
 358 hwloc_libxml_backend_init(struct hwloc_xml_backend_data_s *bdata,
 359                           const char *xmlpath, const char *xmlbuffer, int xmlbuflen)
 360 {
 361   xmlDoc *doc = NULL;
 362 
 363   LIBXML_TEST_VERSION;
 364   hwloc_libxml2_init_once();
 365 
 366   errno = 0; /* set to 0 so that we know if libxml2 changed it */
 367 
 368   if (xmlpath)
 369     doc = xmlReadFile(xmlpath, NULL, XML_PARSE_NOBLANKS);
 370   else if (xmlbuffer)
 371     doc = xmlReadMemory(xmlbuffer, xmlbuflen, "", NULL, XML_PARSE_NOBLANKS);
 372 
 373   if (!doc) {
 374     if (!errno)
 375       /* libxml2 read the file fine, but it got an error during parsing */
 376       errno = EINVAL;
 377     hwloc_libxml2_cleanup();
 378     return -1;
 379   }
 380 
 381   bdata->look_init = hwloc_libxml_look_init;
 382   bdata->look_done = hwloc_libxml_look_done;
 383   bdata->backend_exit = hwloc_libxml_backend_exit;
 384   bdata->data = doc;
 385   return 0;
 386 }
 387 
 388 /*******************
 389  * Export routines *
 390  *******************/
 391 
 392 typedef struct hwloc__libxml_export_state_data_s {
 393   xmlNodePtr current_node; /* current node to output */
 394 } __hwloc_attribute_may_alias * hwloc__libxml_export_state_data_t;
 395 
 396 static void
 397 hwloc__libxml_export_new_child(hwloc__xml_export_state_t parentstate,
 398                                hwloc__xml_export_state_t state,
 399                                const char *name)
 400 {
 401   hwloc__libxml_export_state_data_t lpdata = (void *) parentstate->data;
 402   hwloc__libxml_export_state_data_t ldata = (void *) state->data;
 403 
 404   state->parent = parentstate;
 405   state->new_child = parentstate->new_child;
 406   state->new_prop = parentstate->new_prop;
 407   state->add_content = parentstate->add_content;
 408   state->end_object = parentstate->end_object;
 409   state->global = parentstate->global;
 410 
 411   ldata->current_node = xmlNewChild(lpdata->current_node, NULL, BAD_CAST name, NULL);
 412 }
 413 
 414 static void
 415 hwloc__libxml_export_new_prop(hwloc__xml_export_state_t state, const char *name, const char *value)
 416 {
 417   hwloc__libxml_export_state_data_t ldata = (void *) state->data;
 418   xmlNewProp(ldata->current_node, BAD_CAST name, BAD_CAST value);
 419 }
 420 
 421 static void
 422 hwloc__libxml_export_end_object(hwloc__xml_export_state_t state __hwloc_attribute_unused, const char *name __hwloc_attribute_unused)
 423 {
 424   /* nothing to do */
 425 }
 426 
 427 static void
 428 hwloc__libxml_export_add_content(hwloc__xml_export_state_t state, const char *buffer, size_t length)
 429 {
 430   hwloc__libxml_export_state_data_t ldata = (void *) state->data;
 431   xmlNodeAddContentLen(ldata->current_node, BAD_CAST buffer, length);
 432 }
 433 
 434 static xmlDocPtr
 435 hwloc__libxml2_prepare_export(hwloc_topology_t topology, struct hwloc__xml_export_data_s *edata,
 436                               unsigned long flags)
 437 {
 438   struct hwloc__xml_export_state_s state;
 439   hwloc__libxml_export_state_data_t data = (void *) state.data;
 440   int v1export = flags & HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1;
 441   xmlDocPtr doc = NULL;       /* document pointer */
 442   xmlNodePtr root_node = NULL; /* root pointer */
 443 
 444   HWLOC_BUILD_ASSERT(sizeof(*data) <= sizeof(state.data));
 445 
 446   LIBXML_TEST_VERSION;
 447   hwloc_libxml2_init_once();
 448 
 449   /* Creates a new document, a node and set it as a root node. */
 450   doc = xmlNewDoc(BAD_CAST "1.0");
 451   root_node = xmlNewNode(NULL, BAD_CAST "topology");
 452   if (!(flags & HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1))
 453     xmlNewProp(root_node, BAD_CAST "version", BAD_CAST "2.0");
 454   xmlDocSetRootElement(doc, root_node);
 455 
 456   /* Creates a DTD declaration. Isn't mandatory. */
 457   (void) xmlCreateIntSubset(doc, BAD_CAST "topology", NULL, v1export ? BAD_CAST "hwloc.dtd" : BAD_CAST "hwloc2.dtd");
 458 
 459   state.new_child = hwloc__libxml_export_new_child;
 460   state.new_prop = hwloc__libxml_export_new_prop;
 461   state.add_content = hwloc__libxml_export_add_content;
 462   state.end_object = hwloc__libxml_export_end_object;
 463   state.global = edata;
 464 
 465   data->current_node = root_node;
 466 
 467   hwloc__xml_export_topology (&state, topology, flags);
 468 
 469   return doc;
 470 }
 471 
 472 static int
 473 hwloc_libxml_export_file(hwloc_topology_t topology, struct hwloc__xml_export_data_s *edata,
 474                          const char *filename, unsigned long flags)
 475 {
 476   xmlDocPtr doc;
 477   int ret;
 478 
 479   errno = 0; /* set to 0 so that we know if libxml2 changed it */
 480 
 481   doc = hwloc__libxml2_prepare_export(topology, edata, flags);
 482   ret = xmlSaveFormatFileEnc(filename, doc, "UTF-8", 1);
 483   xmlFreeDoc(doc);
 484   hwloc_libxml2_cleanup();
 485 
 486   if (ret < 0) {
 487     if (!errno)
 488       /* libxml2 likely got an error before doing I/O */
 489       errno = EINVAL;
 490     return ret;
 491   }
 492   return 0;
 493 }
 494 
 495 static int
 496 hwloc_libxml_export_buffer(hwloc_topology_t topology, struct hwloc__xml_export_data_s *edata,
 497                            char **xmlbuffer, int *buflen, unsigned long flags)
 498 {
 499   xmlDocPtr doc;
 500 
 501   doc = hwloc__libxml2_prepare_export(topology, edata, flags);
 502   xmlDocDumpFormatMemoryEnc(doc, (xmlChar **)xmlbuffer, buflen, "UTF-8", 1);
 503   xmlFreeDoc(doc);
 504   hwloc_libxml2_cleanup();
 505   return 0;
 506 }
 507 
 508 static xmlDocPtr
 509 hwloc__libxml2_prepare_export_diff(hwloc_topology_diff_t diff, const char *refname)
 510 {
 511   struct hwloc__xml_export_state_s state;
 512   hwloc__libxml_export_state_data_t data = (void *) state.data;
 513   xmlDocPtr doc = NULL;       /* document pointer */
 514   xmlNodePtr root_node = NULL; /* root pointer */
 515 
 516   HWLOC_BUILD_ASSERT(sizeof(*data) <= sizeof(state.data));
 517 
 518   LIBXML_TEST_VERSION;
 519   hwloc_libxml2_init_once();
 520 
 521   /* Creates a new document, a node and set it as a root node. */
 522   doc = xmlNewDoc(BAD_CAST "1.0");
 523   root_node = xmlNewNode(NULL, BAD_CAST "topologydiff");
 524   if (refname)
 525     xmlNewProp(root_node, BAD_CAST "refname", BAD_CAST refname);
 526   xmlDocSetRootElement(doc, root_node);
 527 
 528   /* Creates a DTD declaration. Isn't mandatory. */
 529   (void) xmlCreateIntSubset(doc, BAD_CAST "topologydiff", NULL, BAD_CAST "hwloc2-diff.dtd");
 530 
 531   state.new_child = hwloc__libxml_export_new_child;
 532   state.new_prop = hwloc__libxml_export_new_prop;
 533   state.add_content = hwloc__libxml_export_add_content;
 534   state.end_object = hwloc__libxml_export_end_object;
 535 
 536   data->current_node = root_node;
 537 
 538   hwloc__xml_export_diff (&state, diff);
 539 
 540   return doc;
 541 }
 542 
 543 static int
 544 hwloc_libxml_export_diff_file(hwloc_topology_diff_t diff, const char *refname, const char *filename)
 545 {
 546   xmlDocPtr doc;
 547   int ret;
 548 
 549   errno = 0; /* set to 0 so that we know if libxml2 changed it */
 550 
 551   doc = hwloc__libxml2_prepare_export_diff(diff, refname);
 552   ret = xmlSaveFormatFileEnc(filename, doc, "UTF-8", 1);
 553   xmlFreeDoc(doc);
 554   hwloc_libxml2_cleanup();
 555 
 556   if (ret < 0) {
 557     if (!errno)
 558       /* libxml2 likely got an error before doing I/O */
 559       errno = EINVAL;
 560     return ret;
 561   }
 562   return 0;
 563 }
 564 
 565 static int
 566 hwloc_libxml_export_diff_buffer(hwloc_topology_diff_t diff, const char *refname, char **xmlbuffer, int *buflen)
 567 {
 568   xmlDocPtr doc;
 569 
 570   doc = hwloc__libxml2_prepare_export_diff(diff, refname);
 571   xmlDocDumpFormatMemoryEnc(doc, (xmlChar **)xmlbuffer, buflen, "UTF-8", 1);
 572   xmlFreeDoc(doc);
 573   hwloc_libxml2_cleanup();
 574   return 0;
 575 }
 576 
 577 static void
 578 hwloc_libxml_free_buffer(void *xmlbuffer)
 579 {
 580   xmlFree(BAD_CAST xmlbuffer);
 581 }
 582 
 583 /*************
 584  * Callbacks *
 585  *************/
 586 
 587 static struct hwloc_xml_callbacks hwloc_xml_libxml_callbacks = {
 588   hwloc_libxml_backend_init,
 589   hwloc_libxml_export_file,
 590   hwloc_libxml_export_buffer,
 591   hwloc_libxml_free_buffer,
 592   hwloc_libxml_import_diff,
 593   hwloc_libxml_export_diff_file,
 594   hwloc_libxml_export_diff_buffer
 595 };
 596 
 597 static struct hwloc_xml_component hwloc_libxml_xml_component = {
 598   NULL,
 599   &hwloc_xml_libxml_callbacks
 600 };
 601 
 602 static int
 603 hwloc_xml_libxml_component_init(unsigned long flags)
 604 {
 605   if (flags)
 606     return -1;
 607   if (hwloc_plugin_check_namespace("xml_libxml", "hwloc__xml_verbose") < 0)
 608     return -1;
 609   return 0;
 610 }
 611 
 612 #ifdef HWLOC_INSIDE_PLUGIN
 613 HWLOC_DECLSPEC extern const struct hwloc_component hwloc_xml_libxml_component;
 614 #endif
 615 
 616 const struct hwloc_component hwloc_xml_libxml_component = {
 617   HWLOC_COMPONENT_ABI,
 618   hwloc_xml_libxml_component_init, NULL,
 619   HWLOC_COMPONENT_TYPE_XML,
 620   0,
 621   &hwloc_libxml_xml_component
 622 };

/* [<][>][^][v][top][bottom][index][help] */