|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Copyright © 2009 CNRS
|
|
Packit Service |
c5cf8c |
* Copyright © 2009-2018 Inria. All rights reserved.
|
|
Packit Service |
c5cf8c |
* Copyright © 2009-2011 Université Bordeaux
|
|
Packit Service |
c5cf8c |
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
|
Packit Service |
c5cf8c |
* See COPYING in top-level directory.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include <private/autogen/config.h>
|
|
Packit Service |
c5cf8c |
#include <hwloc.h>
|
|
Packit Service |
c5cf8c |
#include <hwloc/plugins.h>
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* private headers allowed because this plugin is built within hwloc */
|
|
Packit Service |
c5cf8c |
#include <private/xml.h>
|
|
Packit Service |
c5cf8c |
#include <private/debug.h>
|
|
Packit Service |
c5cf8c |
#include <private/misc.h>
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include <libxml/parser.h>
|
|
Packit Service |
c5cf8c |
#include <libxml/tree.h>
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*******************
|
|
Packit Service |
c5cf8c |
* Common routines *
|
|
Packit Service |
c5cf8c |
*******************/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void hwloc_libxml2_error_callback(void * ctx __hwloc_attribute_unused, const char * msg __hwloc_attribute_unused, ...) { /* do nothing */ }
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* by default, do not cleanup to avoid issues with concurrent libxml users */
|
|
Packit Service |
c5cf8c |
static int hwloc_libxml2_needs_cleanup = 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_init_once(void)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
static int checked = 0;
|
|
Packit Service |
c5cf8c |
if (!checked) {
|
|
Packit Service |
c5cf8c |
/* disable stderr warnings */
|
|
Packit Service |
c5cf8c |
xmlSetGenericErrorFunc(NULL, hwloc__xml_verbose() ? xmlGenericError : hwloc_libxml2_error_callback);
|
|
Packit Service |
c5cf8c |
/* enforce libxml2 cleanup ? */
|
|
Packit Service |
c5cf8c |
if (getenv("HWLOC_LIBXML_CLEANUP"))
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_needs_cleanup = 1;
|
|
Packit Service |
c5cf8c |
checked = 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_cleanup(void)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
if (hwloc_libxml2_needs_cleanup) {
|
|
Packit Service |
c5cf8c |
xmlCleanupParser();
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*******************
|
|
Packit Service |
c5cf8c |
* Import routines *
|
|
Packit Service |
c5cf8c |
*******************/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
typedef struct hwloc__libxml_import_state_data_s {
|
|
Packit Service |
c5cf8c |
xmlNode *node; /* current libxml node, always valid */
|
|
Packit Service |
c5cf8c |
xmlNode *child; /* next processed child, or NULL if none yet */
|
|
Packit Service |
c5cf8c |
xmlAttr *attr; /* last processed attribute, or NULL if none yet */
|
|
Packit Service |
c5cf8c |
} __hwloc_attribute_may_alias * hwloc__libxml_import_state_data_t;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int
|
|
Packit Service |
c5cf8c |
hwloc__libxml_import_next_attr(hwloc__xml_import_state_t state, char **namep, char **valuep)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
hwloc__libxml_import_state_data_t lstate = (void*) state->data;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
xmlAttr *attr;
|
|
Packit Service |
c5cf8c |
if (lstate->attr)
|
|
Packit Service |
c5cf8c |
attr = lstate->attr->next;
|
|
Packit Service |
c5cf8c |
else
|
|
Packit Service |
c5cf8c |
attr = lstate->node->properties;
|
|
Packit Service |
c5cf8c |
for (; attr; attr = attr->next)
|
|
Packit Service |
c5cf8c |
if (attr->type == XML_ATTRIBUTE_NODE) {
|
|
Packit Service |
c5cf8c |
/* use the first valid attribute content */
|
|
Packit Service |
c5cf8c |
xmlNode *subnode;
|
|
Packit Service |
c5cf8c |
for (subnode = attr->children; subnode; subnode = subnode->next) {
|
|
Packit Service |
c5cf8c |
if (subnode->type == XML_TEXT_NODE) {
|
|
Packit Service |
c5cf8c |
if (subnode->content) {
|
|
Packit Service |
c5cf8c |
*namep = (char *) attr->name;
|
|
Packit Service |
c5cf8c |
*valuep = (char *) subnode->content;
|
|
Packit Service |
c5cf8c |
lstate->attr = attr;
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
if (hwloc__xml_verbose())
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "%s: ignoring unexpected xml attr node type %u\n",
|
|
Packit Service |
c5cf8c |
state->global->msgprefix, subnode->type);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
if (hwloc__xml_verbose())
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "%s: ignoring unexpected xml attr type %u\n",
|
|
Packit Service |
c5cf8c |
state->global->msgprefix, attr->type);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
return -1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int
|
|
Packit Service |
c5cf8c |
hwloc__libxml_import_find_child(hwloc__xml_import_state_t state,
|
|
Packit Service |
c5cf8c |
hwloc__xml_import_state_t childstate,
|
|
Packit Service |
c5cf8c |
char **tagp)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
hwloc__libxml_import_state_data_t lstate = (void*) state->data;
|
|
Packit Service |
c5cf8c |
hwloc__libxml_import_state_data_t lchildstate = (void*) childstate->data;
|
|
Packit Service |
c5cf8c |
xmlNode *child;
|
|
Packit Service |
c5cf8c |
childstate->parent = state;
|
|
Packit Service |
c5cf8c |
childstate->global = state->global;
|
|
Packit Service |
c5cf8c |
if (!lstate->child)
|
|
Packit Service |
c5cf8c |
/* All children proceeded */
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
child = lstate->child;
|
|
Packit Service |
c5cf8c |
if (child->type == XML_ELEMENT_NODE) {
|
|
Packit Service |
c5cf8c |
lstate->child = child->next;
|
|
Packit Service |
c5cf8c |
lchildstate->node = child;
|
|
Packit Service |
c5cf8c |
lchildstate->child = child->children;
|
|
Packit Service |
c5cf8c |
lchildstate->attr = NULL;
|
|
Packit Service |
c5cf8c |
*tagp = (char*) child->name;
|
|
Packit Service |
c5cf8c |
return 1;
|
|
Packit Service |
c5cf8c |
} else if (child->type == XML_TEXT_NODE) {
|
|
Packit Service |
c5cf8c |
if (child->content && child->content[0] != '\0' && child->content[0] != '\n')
|
|
Packit Service |
c5cf8c |
if (hwloc__xml_verbose())
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "%s: ignoring object text content %s\n",
|
|
Packit Service |
c5cf8c |
state->global->msgprefix, (const char*) child->content);
|
|
Packit Service |
c5cf8c |
} else if (child->type != XML_COMMENT_NODE) {
|
|
Packit Service |
c5cf8c |
if (hwloc__xml_verbose())
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "%s: ignoring unexpected xml node type %u\n",
|
|
Packit Service |
c5cf8c |
state->global->msgprefix, child->type);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int
|
|
Packit Service |
c5cf8c |
hwloc__libxml_import_close_tag(hwloc__xml_import_state_t state __hwloc_attribute_unused)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void
|
|
Packit Service |
c5cf8c |
hwloc__libxml_import_close_child(hwloc__xml_import_state_t state __hwloc_attribute_unused)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
/* nothing to do */
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int
|
|
Packit Service |
c5cf8c |
hwloc__libxml_import_get_content(hwloc__xml_import_state_t state,
|
|
Packit Service |
c5cf8c |
char **beginp, size_t expected_length)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
hwloc__libxml_import_state_data_t lstate = (void*) state->data;
|
|
Packit Service |
c5cf8c |
xmlNode *child;
|
|
Packit Service |
c5cf8c |
size_t length;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
child = lstate->node->children;
|
|
Packit Service |
c5cf8c |
if (!child || child->type != XML_TEXT_NODE) {
|
|
Packit Service |
c5cf8c |
if (expected_length)
|
|
Packit Service |
c5cf8c |
return -1;
|
|
Packit Service |
c5cf8c |
*beginp = (char *) "";
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
length = strlen((char *) child->content);
|
|
Packit Service |
c5cf8c |
if (length != expected_length)
|
|
Packit Service |
c5cf8c |
return -1;
|
|
Packit Service |
c5cf8c |
*beginp = (char *) child->content;
|
|
Packit Service |
c5cf8c |
return 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void
|
|
Packit Service |
c5cf8c |
hwloc__libxml_import_close_content(hwloc__xml_import_state_t state __hwloc_attribute_unused)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
/* nothing to do */
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int
|
|
Packit Service |
c5cf8c |
hwloc_libxml_look_init(struct hwloc_xml_backend_data_s *bdata,
|
|
Packit Service |
c5cf8c |
struct hwloc__xml_import_state_s *state)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
hwloc__libxml_import_state_data_t lstate = (void*) state->data;
|
|
Packit Service |
c5cf8c |
xmlNodePtr root_node;
|
|
Packit Service |
c5cf8c |
xmlDtdPtr dtd;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
HWLOC_BUILD_ASSERT(sizeof(*lstate) <= sizeof(state->data));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
dtd = xmlGetIntSubset((xmlDocPtr) bdata->data);
|
|
Packit Service |
c5cf8c |
if (!dtd) {
|
|
Packit Service |
c5cf8c |
if (hwloc__xml_verbose())
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "%s: Loading XML topology without DTD\n",
|
|
Packit Service |
c5cf8c |
state->global->msgprefix);
|
|
Packit Service |
c5cf8c |
} else if (strcmp((char *) dtd->SystemID, "hwloc.dtd")
|
|
Packit Service |
c5cf8c |
&& strcmp((char *) dtd->SystemID, "hwloc2.dtd")) {
|
|
Packit Service |
c5cf8c |
if (hwloc__xml_verbose())
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "%s: Loading XML topology with wrong DTD SystemID (%s instead of %s)\n",
|
|
Packit Service |
c5cf8c |
state->global->msgprefix, (char *) dtd->SystemID, "hwloc.dtd or hwloc2.dtd");
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
root_node = xmlDocGetRootElement((xmlDocPtr) bdata->data);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!strcmp((const char *) root_node->name, "root")) {
|
|
Packit Service |
c5cf8c |
bdata->version_major = 0;
|
|
Packit Service |
c5cf8c |
bdata->version_minor = 9;
|
|
Packit Service |
c5cf8c |
} else if (!strcmp((const char *) root_node->name, "topology")) {
|
|
Packit Service |
c5cf8c |
unsigned major, minor;
|
|
Packit Service |
c5cf8c |
xmlChar *version = xmlGetProp(root_node, (xmlChar*) "version");
|
|
Packit Service |
c5cf8c |
if (version && sscanf((const char *)version, "%u.%u", &major, &minor) == 2) {
|
|
Packit Service |
c5cf8c |
bdata->version_major = major;
|
|
Packit Service |
c5cf8c |
bdata->version_minor = minor;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
bdata->version_major = 1;
|
|
Packit Service |
c5cf8c |
bdata->version_minor = 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
xmlFree(version);
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
/* root node should be in "topology" class (or "root" if importing from < 1.0) */
|
|
Packit Service |
c5cf8c |
if (hwloc__xml_verbose())
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "%s: ignoring object of class `%s' not at the top the xml hierarchy\n",
|
|
Packit Service |
c5cf8c |
state->global->msgprefix, (const char *) root_node->name);
|
|
Packit Service |
c5cf8c |
goto failed;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
state->global->next_attr = hwloc__libxml_import_next_attr;
|
|
Packit Service |
c5cf8c |
state->global->find_child = hwloc__libxml_import_find_child;
|
|
Packit Service |
c5cf8c |
state->global->close_tag = hwloc__libxml_import_close_tag;
|
|
Packit Service |
c5cf8c |
state->global->close_child = hwloc__libxml_import_close_child;
|
|
Packit Service |
c5cf8c |
state->global->get_content = hwloc__libxml_import_get_content;
|
|
Packit Service |
c5cf8c |
state->global->close_content = hwloc__libxml_import_close_content;
|
|
Packit Service |
c5cf8c |
state->parent = NULL;
|
|
Packit Service |
c5cf8c |
lstate->node = root_node;
|
|
Packit Service |
c5cf8c |
lstate->child = root_node->children;
|
|
Packit Service |
c5cf8c |
lstate->attr = NULL;
|
|
Packit Service |
c5cf8c |
return 0; /* success */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
failed:
|
|
Packit Service |
c5cf8c |
return -1; /* failed */
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* can be called at the end of the import (to cleanup things early),
|
|
Packit Service |
c5cf8c |
* or by backend_exit() if load failed for other reasons.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
static void
|
|
Packit Service |
c5cf8c |
hwloc_libxml_free_buffers(struct hwloc_xml_backend_data_s *bdata)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
if (bdata->data) {
|
|
Packit Service |
c5cf8c |
xmlFreeDoc((xmlDoc*)bdata->data);
|
|
Packit Service |
c5cf8c |
bdata->data = NULL;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void
|
|
Packit Service |
c5cf8c |
hwloc_libxml_look_done(struct hwloc_xml_backend_data_s *bdata, int result __hwloc_attribute_unused)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
hwloc_libxml_free_buffers(bdata);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int
|
|
Packit Service |
c5cf8c |
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)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
hwloc__libxml_import_state_data_t lstate = (void*) state->data;
|
|
Packit Service |
c5cf8c |
char *refname = NULL;
|
|
Packit Service |
c5cf8c |
xmlDoc *doc = NULL;
|
|
Packit Service |
c5cf8c |
xmlNode* root_node;
|
|
Packit Service |
c5cf8c |
xmlDtd *dtd;
|
|
Packit Service |
c5cf8c |
int ret;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
HWLOC_BUILD_ASSERT(sizeof(*lstate) <= sizeof(state->data));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
LIBXML_TEST_VERSION;
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_init_once();
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
errno = 0; /* set to 0 so that we know if libxml2 changed it */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (xmlpath)
|
|
Packit Service |
c5cf8c |
doc = xmlReadFile(xmlpath, NULL, XML_PARSE_NOBLANKS);
|
|
Packit Service |
c5cf8c |
else if (xmlbuffer)
|
|
Packit Service |
c5cf8c |
doc = xmlReadMemory(xmlbuffer, xmlbuflen, "", NULL, XML_PARSE_NOBLANKS);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!doc) {
|
|
Packit Service |
c5cf8c |
if (!errno)
|
|
Packit Service |
c5cf8c |
/* libxml2 read the file fine, but it got an error during parsing */
|
|
Packit Service |
c5cf8c |
errno = EINVAL;
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_cleanup();
|
|
Packit Service |
c5cf8c |
goto out;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
dtd = xmlGetIntSubset(doc);
|
|
Packit Service |
c5cf8c |
if (!dtd) {
|
|
Packit Service |
c5cf8c |
if (hwloc__xml_verbose())
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "%s: Loading XML topologydiff without DTD\n",
|
|
Packit Service |
c5cf8c |
state->global->msgprefix);
|
|
Packit Service |
c5cf8c |
} else if (strcmp((char *) dtd->SystemID, "hwloc2-diff.dtd")) {
|
|
Packit Service |
c5cf8c |
if (hwloc__xml_verbose())
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "%s: Loading XML topologydiff with wrong DTD SystemID (%s instead of %s)\n",
|
|
Packit Service |
c5cf8c |
state->global->msgprefix, (char *) dtd->SystemID, "hwloc2-diff.dtd");
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
root_node = xmlDocGetRootElement(doc);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (strcmp((const char *) root_node->name, "topologydiff")) {
|
|
Packit Service |
c5cf8c |
/* root node should be in "topologydiff" class */
|
|
Packit Service |
c5cf8c |
if (hwloc__xml_verbose())
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "%s: ignoring object of class `%s' not at the top the xml hierarchy\n",
|
|
Packit Service |
c5cf8c |
state->global->msgprefix, (const char *) root_node->name);
|
|
Packit Service |
c5cf8c |
goto out_with_doc;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
state->global->next_attr = hwloc__libxml_import_next_attr;
|
|
Packit Service |
c5cf8c |
state->global->find_child = hwloc__libxml_import_find_child;
|
|
Packit Service |
c5cf8c |
state->global->close_tag = hwloc__libxml_import_close_tag;
|
|
Packit Service |
c5cf8c |
state->global->close_child = hwloc__libxml_import_close_child;
|
|
Packit Service |
c5cf8c |
state->global->get_content = hwloc__libxml_import_get_content;
|
|
Packit Service |
c5cf8c |
state->global->close_content = hwloc__libxml_import_close_content;
|
|
Packit Service |
c5cf8c |
state->parent = NULL;
|
|
Packit Service |
c5cf8c |
lstate->node = root_node;
|
|
Packit Service |
c5cf8c |
lstate->child = root_node->children;
|
|
Packit Service |
c5cf8c |
lstate->attr = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
while (1) {
|
|
Packit Service |
c5cf8c |
char *attrname, *attrvalue;
|
|
Packit Service |
c5cf8c |
if (state->global->next_attr(state, &attrname, &attrvalue) < 0)
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
if (!strcmp(attrname, "refname")) {
|
|
Packit Service |
c5cf8c |
free(refname);
|
|
Packit Service |
c5cf8c |
refname = strdup(attrvalue);
|
|
Packit Service |
c5cf8c |
} else
|
|
Packit Service |
c5cf8c |
goto out_with_doc;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
ret = hwloc__xml_import_diff(state, firstdiffp);
|
|
Packit Service |
c5cf8c |
if (refnamep && !ret)
|
|
Packit Service |
c5cf8c |
*refnamep = refname;
|
|
Packit Service |
c5cf8c |
else
|
|
Packit Service |
c5cf8c |
free(refname);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
xmlFreeDoc(doc);
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_cleanup();
|
|
Packit Service |
c5cf8c |
return ret;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
out_with_doc:
|
|
Packit Service |
c5cf8c |
free(refname);
|
|
Packit Service |
c5cf8c |
xmlFreeDoc(doc);
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_cleanup();
|
|
Packit Service |
c5cf8c |
out:
|
|
Packit Service |
c5cf8c |
return -1; /* failed */
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/********************
|
|
Packit Service |
c5cf8c |
* Backend routines *
|
|
Packit Service |
c5cf8c |
********************/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void
|
|
Packit Service |
c5cf8c |
hwloc_libxml_backend_exit(struct hwloc_xml_backend_data_s *bdata)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
hwloc_libxml_free_buffers(bdata);
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_cleanup();
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int
|
|
Packit Service |
c5cf8c |
hwloc_libxml_backend_init(struct hwloc_xml_backend_data_s *bdata,
|
|
Packit Service |
c5cf8c |
const char *xmlpath, const char *xmlbuffer, int xmlbuflen)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
xmlDoc *doc = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
LIBXML_TEST_VERSION;
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_init_once();
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
errno = 0; /* set to 0 so that we know if libxml2 changed it */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (xmlpath)
|
|
Packit Service |
c5cf8c |
doc = xmlReadFile(xmlpath, NULL, XML_PARSE_NOBLANKS);
|
|
Packit Service |
c5cf8c |
else if (xmlbuffer)
|
|
Packit Service |
c5cf8c |
doc = xmlReadMemory(xmlbuffer, xmlbuflen, "", NULL, XML_PARSE_NOBLANKS);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!doc) {
|
|
Packit Service |
c5cf8c |
if (!errno)
|
|
Packit Service |
c5cf8c |
/* libxml2 read the file fine, but it got an error during parsing */
|
|
Packit Service |
c5cf8c |
errno = EINVAL;
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_cleanup();
|
|
Packit Service |
c5cf8c |
return -1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
bdata->look_init = hwloc_libxml_look_init;
|
|
Packit Service |
c5cf8c |
bdata->look_done = hwloc_libxml_look_done;
|
|
Packit Service |
c5cf8c |
bdata->backend_exit = hwloc_libxml_backend_exit;
|
|
Packit Service |
c5cf8c |
bdata->data = doc;
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*******************
|
|
Packit Service |
c5cf8c |
* Export routines *
|
|
Packit Service |
c5cf8c |
*******************/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
typedef struct hwloc__libxml_export_state_data_s {
|
|
Packit Service |
c5cf8c |
xmlNodePtr current_node; /* current node to output */
|
|
Packit Service |
c5cf8c |
} __hwloc_attribute_may_alias * hwloc__libxml_export_state_data_t;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void
|
|
Packit Service |
c5cf8c |
hwloc__libxml_export_new_child(hwloc__xml_export_state_t parentstate,
|
|
Packit Service |
c5cf8c |
hwloc__xml_export_state_t state,
|
|
Packit Service |
c5cf8c |
const char *name)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
hwloc__libxml_export_state_data_t lpdata = (void *) parentstate->data;
|
|
Packit Service |
c5cf8c |
hwloc__libxml_export_state_data_t ldata = (void *) state->data;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
state->parent = parentstate;
|
|
Packit Service |
c5cf8c |
state->new_child = parentstate->new_child;
|
|
Packit Service |
c5cf8c |
state->new_prop = parentstate->new_prop;
|
|
Packit Service |
c5cf8c |
state->add_content = parentstate->add_content;
|
|
Packit Service |
c5cf8c |
state->end_object = parentstate->end_object;
|
|
Packit Service |
c5cf8c |
state->global = parentstate->global;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
ldata->current_node = xmlNewChild(lpdata->current_node, NULL, BAD_CAST name, NULL);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void
|
|
Packit Service |
c5cf8c |
hwloc__libxml_export_new_prop(hwloc__xml_export_state_t state, const char *name, const char *value)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
hwloc__libxml_export_state_data_t ldata = (void *) state->data;
|
|
Packit Service |
c5cf8c |
xmlNewProp(ldata->current_node, BAD_CAST name, BAD_CAST value);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void
|
|
Packit Service |
c5cf8c |
hwloc__libxml_export_end_object(hwloc__xml_export_state_t state __hwloc_attribute_unused, const char *name __hwloc_attribute_unused)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
/* nothing to do */
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void
|
|
Packit Service |
c5cf8c |
hwloc__libxml_export_add_content(hwloc__xml_export_state_t state, const char *buffer, size_t length)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
hwloc__libxml_export_state_data_t ldata = (void *) state->data;
|
|
Packit Service |
c5cf8c |
xmlNodeAddContentLen(ldata->current_node, BAD_CAST buffer, length);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static xmlDocPtr
|
|
Packit Service |
c5cf8c |
hwloc__libxml2_prepare_export(hwloc_topology_t topology, struct hwloc__xml_export_data_s *edata,
|
|
Packit Service |
c5cf8c |
unsigned long flags)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
struct hwloc__xml_export_state_s state;
|
|
Packit Service |
c5cf8c |
hwloc__libxml_export_state_data_t data = (void *) state.data;
|
|
Packit Service |
c5cf8c |
int v1export = flags & HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1;
|
|
Packit Service |
c5cf8c |
xmlDocPtr doc = NULL; /* document pointer */
|
|
Packit Service |
c5cf8c |
xmlNodePtr root_node = NULL; /* root pointer */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
HWLOC_BUILD_ASSERT(sizeof(*data) <= sizeof(state.data));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
LIBXML_TEST_VERSION;
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_init_once();
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Creates a new document, a node and set it as a root node. */
|
|
Packit Service |
c5cf8c |
doc = xmlNewDoc(BAD_CAST "1.0");
|
|
Packit Service |
c5cf8c |
root_node = xmlNewNode(NULL, BAD_CAST "topology");
|
|
Packit Service |
c5cf8c |
if (!(flags & HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1))
|
|
Packit Service |
c5cf8c |
xmlNewProp(root_node, BAD_CAST "version", BAD_CAST "2.0");
|
|
Packit Service |
c5cf8c |
xmlDocSetRootElement(doc, root_node);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Creates a DTD declaration. Isn't mandatory. */
|
|
Packit Service |
c5cf8c |
(void) xmlCreateIntSubset(doc, BAD_CAST "topology", NULL, v1export ? BAD_CAST "hwloc.dtd" : BAD_CAST "hwloc2.dtd");
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
state.new_child = hwloc__libxml_export_new_child;
|
|
Packit Service |
c5cf8c |
state.new_prop = hwloc__libxml_export_new_prop;
|
|
Packit Service |
c5cf8c |
state.add_content = hwloc__libxml_export_add_content;
|
|
Packit Service |
c5cf8c |
state.end_object = hwloc__libxml_export_end_object;
|
|
Packit Service |
c5cf8c |
state.global = edata;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
data->current_node = root_node;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
hwloc__xml_export_topology (&state, topology, flags);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return doc;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int
|
|
Packit Service |
c5cf8c |
hwloc_libxml_export_file(hwloc_topology_t topology, struct hwloc__xml_export_data_s *edata,
|
|
Packit Service |
c5cf8c |
const char *filename, unsigned long flags)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
xmlDocPtr doc;
|
|
Packit Service |
c5cf8c |
int ret;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
errno = 0; /* set to 0 so that we know if libxml2 changed it */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
doc = hwloc__libxml2_prepare_export(topology, edata, flags);
|
|
Packit Service |
c5cf8c |
ret = xmlSaveFormatFileEnc(filename, doc, "UTF-8", 1);
|
|
Packit Service |
c5cf8c |
xmlFreeDoc(doc);
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_cleanup();
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (ret < 0) {
|
|
Packit Service |
c5cf8c |
if (!errno)
|
|
Packit Service |
c5cf8c |
/* libxml2 likely got an error before doing I/O */
|
|
Packit Service |
c5cf8c |
errno = EINVAL;
|
|
Packit Service |
c5cf8c |
return ret;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int
|
|
Packit Service |
c5cf8c |
hwloc_libxml_export_buffer(hwloc_topology_t topology, struct hwloc__xml_export_data_s *edata,
|
|
Packit Service |
c5cf8c |
char **xmlbuffer, int *buflen, unsigned long flags)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
xmlDocPtr doc;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
doc = hwloc__libxml2_prepare_export(topology, edata, flags);
|
|
Packit Service |
c5cf8c |
xmlDocDumpFormatMemoryEnc(doc, (xmlChar **)xmlbuffer, buflen, "UTF-8", 1);
|
|
Packit Service |
c5cf8c |
xmlFreeDoc(doc);
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_cleanup();
|
|
Packit Service |
c5cf8c |
if (!*xmlbuffer) {
|
|
Packit Service |
c5cf8c |
*buflen = 0;
|
|
Packit Service |
c5cf8c |
return -1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
*buflen += 1; /* ending \0 was added but not counted in the length */
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static xmlDocPtr
|
|
Packit Service |
c5cf8c |
hwloc__libxml2_prepare_export_diff(hwloc_topology_diff_t diff, const char *refname)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
struct hwloc__xml_export_state_s state;
|
|
Packit Service |
c5cf8c |
hwloc__libxml_export_state_data_t data = (void *) state.data;
|
|
Packit Service |
c5cf8c |
xmlDocPtr doc = NULL; /* document pointer */
|
|
Packit Service |
c5cf8c |
xmlNodePtr root_node = NULL; /* root pointer */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
HWLOC_BUILD_ASSERT(sizeof(*data) <= sizeof(state.data));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
LIBXML_TEST_VERSION;
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_init_once();
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Creates a new document, a node and set it as a root node. */
|
|
Packit Service |
c5cf8c |
doc = xmlNewDoc(BAD_CAST "1.0");
|
|
Packit Service |
c5cf8c |
root_node = xmlNewNode(NULL, BAD_CAST "topologydiff");
|
|
Packit Service |
c5cf8c |
if (refname)
|
|
Packit Service |
c5cf8c |
xmlNewProp(root_node, BAD_CAST "refname", BAD_CAST refname);
|
|
Packit Service |
c5cf8c |
xmlDocSetRootElement(doc, root_node);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Creates a DTD declaration. Isn't mandatory. */
|
|
Packit Service |
c5cf8c |
(void) xmlCreateIntSubset(doc, BAD_CAST "topologydiff", NULL, BAD_CAST "hwloc2-diff.dtd");
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
state.new_child = hwloc__libxml_export_new_child;
|
|
Packit Service |
c5cf8c |
state.new_prop = hwloc__libxml_export_new_prop;
|
|
Packit Service |
c5cf8c |
state.add_content = hwloc__libxml_export_add_content;
|
|
Packit Service |
c5cf8c |
state.end_object = hwloc__libxml_export_end_object;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
data->current_node = root_node;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
hwloc__xml_export_diff (&state, diff);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return doc;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int
|
|
Packit Service |
c5cf8c |
hwloc_libxml_export_diff_file(hwloc_topology_diff_t diff, const char *refname, const char *filename)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
xmlDocPtr doc;
|
|
Packit Service |
c5cf8c |
int ret;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
errno = 0; /* set to 0 so that we know if libxml2 changed it */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
doc = hwloc__libxml2_prepare_export_diff(diff, refname);
|
|
Packit Service |
c5cf8c |
ret = xmlSaveFormatFileEnc(filename, doc, "UTF-8", 1);
|
|
Packit Service |
c5cf8c |
xmlFreeDoc(doc);
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_cleanup();
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (ret < 0) {
|
|
Packit Service |
c5cf8c |
if (!errno)
|
|
Packit Service |
c5cf8c |
/* libxml2 likely got an error before doing I/O */
|
|
Packit Service |
c5cf8c |
errno = EINVAL;
|
|
Packit Service |
c5cf8c |
return ret;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int
|
|
Packit Service |
c5cf8c |
hwloc_libxml_export_diff_buffer(hwloc_topology_diff_t diff, const char *refname, char **xmlbuffer, int *buflen)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
xmlDocPtr doc;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
doc = hwloc__libxml2_prepare_export_diff(diff, refname);
|
|
Packit Service |
c5cf8c |
xmlDocDumpFormatMemoryEnc(doc, (xmlChar **)xmlbuffer, buflen, "UTF-8", 1);
|
|
Packit Service |
c5cf8c |
xmlFreeDoc(doc);
|
|
Packit Service |
c5cf8c |
hwloc_libxml2_cleanup();
|
|
Packit Service |
c5cf8c |
if (!*xmlbuffer) {
|
|
Packit Service |
c5cf8c |
*buflen = 0;
|
|
Packit Service |
c5cf8c |
return -1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
*buflen += 1; /* ending \0 was added but not counted in the length */
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void
|
|
Packit Service |
c5cf8c |
hwloc_libxml_free_buffer(void *xmlbuffer)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
xmlFree(BAD_CAST xmlbuffer);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*************
|
|
Packit Service |
c5cf8c |
* Callbacks *
|
|
Packit Service |
c5cf8c |
*************/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static struct hwloc_xml_callbacks hwloc_xml_libxml_callbacks = {
|
|
Packit Service |
c5cf8c |
hwloc_libxml_backend_init,
|
|
Packit Service |
c5cf8c |
hwloc_libxml_export_file,
|
|
Packit Service |
c5cf8c |
hwloc_libxml_export_buffer,
|
|
Packit Service |
c5cf8c |
hwloc_libxml_free_buffer,
|
|
Packit Service |
c5cf8c |
hwloc_libxml_import_diff,
|
|
Packit Service |
c5cf8c |
hwloc_libxml_export_diff_file,
|
|
Packit Service |
c5cf8c |
hwloc_libxml_export_diff_buffer
|
|
Packit Service |
c5cf8c |
};
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static struct hwloc_xml_component hwloc_libxml_xml_component = {
|
|
Packit Service |
c5cf8c |
NULL,
|
|
Packit Service |
c5cf8c |
&hwloc_xml_libxml_callbacks
|
|
Packit Service |
c5cf8c |
};
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int
|
|
Packit Service |
c5cf8c |
hwloc_xml_libxml_component_init(unsigned long flags)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
if (flags)
|
|
Packit Service |
c5cf8c |
return -1;
|
|
Packit Service |
c5cf8c |
if (hwloc_plugin_check_namespace("xml_libxml", "hwloc__xml_verbose") < 0)
|
|
Packit Service |
c5cf8c |
return -1;
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#ifdef HWLOC_INSIDE_PLUGIN
|
|
Packit Service |
c5cf8c |
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_xml_libxml_component;
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
const struct hwloc_component hwloc_xml_libxml_component = {
|
|
Packit Service |
c5cf8c |
HWLOC_COMPONENT_ABI,
|
|
Packit Service |
c5cf8c |
hwloc_xml_libxml_component_init, NULL,
|
|
Packit Service |
c5cf8c |
HWLOC_COMPONENT_TYPE_XML,
|
|
Packit Service |
c5cf8c |
0,
|
|
Packit Service |
c5cf8c |
&hwloc_libxml_xml_component
|
|
Packit Service |
c5cf8c |
};
|