static int hwloc__libxml_import_find_child(hwloc__xml_import_state_t state, hwloc__xml_import_state_t childstate, char **tagp) { hwloc__libxml_import_state_data_t lstate = (void*) state->data; hwloc__libxml_import_state_data_t lchildstate = (void*) childstate->data; xmlNode *child; childstate->parent = state; childstate->global = state->global; if (!lstate->child) return 0; child = lstate->child->next; for (; child; child = child->next) if (child->type == XML_ELEMENT_NODE) { lstate->child = lchildstate->node = child; lchildstate->child = child->children; lchildstate->attr = NULL; *tagp = (char*) child->name; return 1; } else if (child->type == XML_TEXT_NODE) { if (child->content && child->content[0] != '\0' && child->content[0] != '\n') if (hwloc__xml_verbose()) fprintf(stderr, "ignoring object text content %s\n", (const char*) child->content); } else if (child->type != XML_COMMENT_NODE) { if (hwloc__xml_verbose()) fprintf(stderr, "ignoring unexpected xml node type %u\n", child->type); } return 0; }
static int hwloc__libxml_import_next_attr(hwloc__xml_import_state_t state, char **namep, char **valuep) { hwloc__libxml_import_state_data_t lstate = (void*) state->data; xmlAttr *attr; if (lstate->attr) attr = lstate->attr->next; else attr = lstate->node->properties; for (; attr; attr = attr->next) if (attr->type == XML_ATTRIBUTE_NODE) { /* use the first valid attribute content */ xmlNode *subnode; for (subnode = attr->children; subnode; subnode = subnode->next) { if (subnode->type == XML_TEXT_NODE) { if (subnode->content && subnode->content[0] != '\0' && subnode->content[0] != '\n') { *namep = (char *) attr->name; *valuep = (char *) subnode->content; lstate->attr = attr; return 0; } } else { if (hwloc__xml_verbose()) fprintf(stderr, "ignoring unexpected xml attr node type %u\n", subnode->type); } } } else { if (hwloc__xml_verbose()) fprintf(stderr, "ignoring unexpected xml attr type %u\n", attr->type); } return -1; }
static void hwloc_nolibxml_look_done(struct hwloc_xml_backend_data_s *bdata, int result) { hwloc_nolibxml_free_buffers(bdata); if (result < 0 && hwloc__xml_verbose()) fprintf(stderr, "Failed to parse XML input with the minimalistic parser. If it was not\n" "generated by hwloc, try enabling full XML support with libxml2.\n"); }
static void hwloc_libxml2_disable_stderrwarnings(void) { static int first = 1; if (first) { xmlSetGenericErrorFunc(NULL, hwloc__xml_verbose() ? xmlGenericError : hwloc_libxml2_error_callback); first = 0; } }
static int hwloc_libxml_look_init(struct hwloc_xml_backend_data_s *bdata, struct hwloc__xml_import_state_s *state) { hwloc__libxml_import_state_data_t lstate = (void*) state->data; xmlNode* root_node; xmlDtd *dtd; assert(sizeof(*lstate) <= sizeof(state->data)); dtd = xmlGetIntSubset((xmlDoc*) bdata->data); if (!dtd) { if (hwloc__xml_verbose()) fprintf(stderr, "Loading XML topology without DTD\n"); } else if (strcmp((char *) dtd->SystemID, "hwloc.dtd")) { if (hwloc__xml_verbose()) fprintf(stderr, "Loading XML topology with wrong DTD SystemID (%s instead of %s)\n", (char *) dtd->SystemID, "hwloc.dtd"); } root_node = xmlDocGetRootElement((xmlDoc*) bdata->data); if (strcmp((const char *) root_node->name, "topology") && strcmp((const char *) root_node->name, "root")) { /* root node should be in "topology" class (or "root" if importing from < 1.0) */ if (hwloc__xml_verbose()) fprintf(stderr, "ignoring object of class `%s' not at the top the xml hierarchy\n", (const char *) root_node->name); goto failed; } state->global->next_attr = hwloc__libxml_import_next_attr; state->global->find_child = hwloc__libxml_import_find_child; state->global->close_tag = hwloc__libxml_import_close_tag; state->global->close_child = hwloc__libxml_import_close_child; state->global->get_content = hwloc__libxml_import_get_content; state->global->close_content = hwloc__libxml_import_close_content; state->parent = NULL; lstate->node = root_node; lstate->child = root_node->children; lstate->attr = NULL; return 0; /* success */ failed: return -1; /* failed */ }
static void hwloc_libxml2_init_once(void) { static int checked = 0; if (!checked) { /* disable stderr warnings */ xmlSetGenericErrorFunc(NULL, hwloc__xml_verbose() ? xmlGenericError : hwloc_libxml2_error_callback); /* enforce libxml2 cleanup ? */ if (getenv("HWLOC_LIBXML_CLEANUP")) hwloc_libxml2_needs_cleanup = 1; checked = 1; } }
static int hwloc_nolibxml_look_init(struct hwloc_xml_backend_data_s *bdata, struct hwloc__xml_import_state_s *state) { hwloc__nolibxml_import_state_data_t nstate = (void*) state->data; struct hwloc__nolibxml_backend_data_s *nbdata = bdata->data; char *buffer; HWLOC_BUILD_ASSERT(sizeof(*nstate) <= sizeof(state->data)); /* use a copy in the temporary buffer, we may modify during parsing */ buffer = nbdata->copy; memcpy(buffer, nbdata->buffer, nbdata->buflen); /* skip headers */ while (!strncmp(buffer, "<?xml ", 6) || !strncmp(buffer, "<!DOCTYPE ", 10)) { buffer = strchr(buffer, '\n'); if (!buffer) goto failed; buffer++; } /* find topology tag */ if (strncmp(buffer, "<topology>", 10)) { if (hwloc__xml_verbose()) { if (!strncmp(buffer, "<topology version=", 18)) fprintf(stderr, "%s: hwloc v1.x cannot import topology version >= 2.\n", state->global->msgprefix); else fprintf(stderr, "%s: failed to find starting tag <topology>\n", state->global->msgprefix); } goto failed; } state->global->next_attr = hwloc__nolibxml_import_next_attr; state->global->find_child = hwloc__nolibxml_import_find_child; state->global->close_tag = hwloc__nolibxml_import_close_tag; state->global->close_child = hwloc__nolibxml_import_close_child; state->global->get_content = hwloc__nolibxml_import_get_content; state->global->close_content = hwloc__nolibxml_import_close_content; state->parent = NULL; nstate->closed = 0; nstate->tagbuffer = buffer+10; nstate->tagname = (char *) "topology"; nstate->attrbuffer = NULL; return 0; /* success */ failed: return -1; /* failed */ }
static int 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) { hwloc__libxml_import_state_data_t lstate = (void*) state->data; char *refname = NULL; xmlDoc *doc = NULL; xmlNode* root_node; xmlDtd *dtd; int ret; assert(sizeof(*lstate) <= sizeof(state->data)); LIBXML_TEST_VERSION; hwloc_libxml2_init_once(); errno = 0; /* set to 0 so that we know if libxml2 changed it */ if (xmlpath) doc = xmlReadFile(xmlpath, NULL, 0); else if (xmlbuffer) doc = xmlReadMemory(xmlbuffer, xmlbuflen, "", NULL, 0); if (!doc) { if (!errno) /* libxml2 read the file fine, but it got an error during parsing */ errno = EINVAL; goto out; } dtd = xmlGetIntSubset(doc); if (!dtd) { if (hwloc__xml_verbose()) fprintf(stderr, "Loading XML topologydiff without DTD\n"); } else if (strcmp((char *) dtd->SystemID, "hwloc.dtd")) { if (hwloc__xml_verbose()) fprintf(stderr, "Loading XML topologydiff with wrong DTD SystemID (%s instead of %s)\n", (char *) dtd->SystemID, "hwloc.dtd"); } root_node = xmlDocGetRootElement(doc); if (strcmp((const char *) root_node->name, "topologydiff")) { /* root node should be in "topologydiff" class */ if (hwloc__xml_verbose()) fprintf(stderr, "ignoring object of class `%s' not at the top the xml hierarchy\n", (const char *) root_node->name); goto out_with_doc; } state->global->next_attr = hwloc__libxml_import_next_attr; state->global->find_child = hwloc__libxml_import_find_child; state->global->close_tag = hwloc__libxml_import_close_tag; state->global->close_child = hwloc__libxml_import_close_child; state->global->get_content = hwloc__libxml_import_get_content; state->global->close_content = hwloc__libxml_import_close_content; state->parent = NULL; lstate->node = root_node; lstate->child = root_node->children; lstate->attr = NULL; while (1) { char *attrname, *attrvalue; if (state->global->next_attr(state, &attrname, &attrvalue) < 0) break; if (!strcmp(attrname, "refname")) { free(refname); refname = strdup(attrvalue); } else goto out_with_doc; } ret = hwloc__xml_import_diff(state, firstdiffp); if (refnamep && !ret) *refnamep = refname; else free(refname); xmlFreeDoc(doc); hwloc_libxml2_cleanup(); return ret; out_with_doc: free(refname); xmlFreeDoc(doc); hwloc_libxml2_cleanup(); out: return -1; /* failed */ }