[PATCH 5/9] lib: Add libxml2 support

Cyril Bur cyril.bur at au1.ibm.com
Wed Dec 16 11:54:40 AEDT 2015


On Tue, 15 Dec 2015 14:15:26 +1100
Samuel Mendoza-Jonas <sam.mj at au1.ibm.com> wrote:

> Attribute override functionality on BMC machines will require parsing a
> Hostboot-provided XML file on startup. This adds generic libxml2 support
> in order to parse these files.
> 

I didn't really go into the nitty gritty of it, I'm sure it works but xml makes
be die a little bit inside every time.

Copyright headers though?

Reviewed-by: Cyril Bur <cyril.bur at au1.ibm.com>

> Signed-off-by: Samuel Mendoza-Jonas <sam.mj at au1.ibm.com>
> ---
>  lib/Makefile.am |   7 ++-
>  lib/xml/xml.c   | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/xml/xml.h   |  19 +++++++
>  3 files changed, 177 insertions(+), 1 deletion(-)
>  create mode 100644 lib/xml/xml.c
>  create mode 100644 lib/xml/xml.h
> 
> diff --git a/lib/Makefile.am b/lib/Makefile.am
> index a3ae943..ea6e5c7 100644
> --- a/lib/Makefile.am
> +++ b/lib/Makefile.am
> @@ -49,20 +49,25 @@ lib_libpbcore_la_SOURCES = \
>  	lib/url/url.h \
>  	lib/util/util.c \
>  	lib/util/util.h \
> +	lib/xml/xml.h \
>  	lib/flash/config.h \
>  	lib/flash/flash.h
>  
>  if ENABLE_MTD
>  lib_libpbcore_la_SOURCES += \
> +	lib/xml/xml.c \
>  	lib/flash/flash.c
>  
>  lib_libpbcore_la_CPPFLAGS += \
> +	`xml2-config --cflags` \
>  	$(AM_CPPFLAGS)
>  
>  lib_libpbcore_la_LDFLAGS = \
> +	`xml2-config --libs` \
>  	$(AM_LDFLAGS) \
>  	-l:libflash.so
>  
>  lib_libpbcore_la_SOURCES += \
> -	lib/flash/flash.c
> +	lib/flash/flash.c \
> +	lib/xml/xml.c
>  endif
> diff --git a/lib/xml/xml.c b/lib/xml/xml.c
> new file mode 100644
> index 0000000..057914b
> --- /dev/null
> +++ b/lib/xml/xml.c
> @@ -0,0 +1,152 @@
> +#include <libxml/parser.h>
> +#include <libxml/tree.h>
> +#include <string.h>
> +
> +#include <talloc/talloc.h>
> +#include <log/log.h>
> +
> +#include "xml/xml.h"
> +
> +xmlDocPtr readXMLFile(const char *path)
> +{
> +	xmlParserCtxtPtr ctxt;
> +	xmlDocPtr doc = NULL;
> +
> +	if (!path)
> +		goto out;
> +
> +	LIBXML_TEST_VERSION;
> +
> +	ctxt = xmlNewParserCtxt();
> +	if (!ctxt)
> +		goto out;
> +
> +	/* TODO Incorporate DTD when/if available
> +	 * doc = xmlCtxtReadFile(ctxt, path, NULL, XML_PARSE_DTDVALID);
> +	 */
> +	doc = xmlCtxtReadFile(ctxt, path, NULL, 0);
> +	if (!doc) {
> +		pb_log("Failed to parse XML file '%s'\n", path);
> +		goto out;
> +	}
> +
> +	if (!ctxt->valid) {
> +		pb_log("XML file '%s' failed DTD check\n", path);
> +		xmlFreeDoc(doc);
> +		doc = NULL;
> +	}
> +
> +	xmlFreeParserCtxt(ctxt);
> +out:
> +	return doc;
> +}
> +
> +xmlNodePtr findXMLRoot(xmlDocPtr doc, const char *name)
> +{
> +	xmlNodePtr node, root = NULL;
> +
> +	for (node = xmlDocGetRootElement(doc); node; node = node->next)
> +		if (node->type == XML_ELEMENT_NODE)
> +			if (!xmlStrcmp(node->name, (const xmlChar *)name)) {
> +				root = node;
> +				break;
> +			}
> +	return root;
> +}
> +
> +
> +/* Return first child node matching name */
> +xmlNodePtr findChildNode(xmlNodePtr root, xmlElementType type,
> +			 const char *name)
> +{
> +	xmlNodePtr cur;
> +
> +	for (cur = root->children; cur; cur = cur->next)
> +		if (!type || cur->type == type)
> +			if (!xmlStrcmp(cur->name, (const xmlChar *)name))
> +			    return cur;
> +	return NULL;
> +}
> +
> +/*
> + * We probably won't end up looping through attributes like we do with
> + * elements since they will be fairly specific, but here's an
> + * illustrative example
> + */
> +void printAttrs(xmlDocPtr doc, xmlNodePtr node, const char *prefix)
> +{
> +	xmlAttrPtr attr;
> +	xmlChar *key = NULL;
> +
> +	for (attr = node->properties; attr; attr = attr->next) {
> +		key = xmlNodeListGetString(doc, attr->xmlChildrenNode, 1);
> +		pb_log("%s'%s'->'%s'\n", prefix, attr->name, key);
> +		xmlFree(key);
> +	}
> +}
> +
> +char *nodeAttribute(void *ctx, xmlNodePtr node, const char *name)
> +{
> +	xmlChar *tmp;
> +	char *attr;
> +
> +	tmp = xmlGetProp(node, (xmlChar *) name);
> +	attr = talloc_strdup(ctx, (char *) tmp);
> +
> +	xmlFree(tmp);
> +	return attr;
> +}
> +
> +
> +/* Allocate content under context, return NULL for whitespace-only results */
> +char *nodeContent(void *ctx, xmlDocPtr doc, xmlNodePtr node)
> +{
> +	char *content;
> +	xmlChar *tmp = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
> +	/* xmlNodeGetContent aggregates empty fields */
> +
> +	content = talloc_strdup(ctx, (char *)tmp);
> +	xmlFree(tmp);
> +
> +	return content;
> +}
> +
> +bool hasChildren(xmlNodePtr node, xmlElementType type)
> +{
> +	xmlNodePtr cur;
> +	int n = 0;
> +
> +	for (cur = node->children; cur; cur = cur->next)
> +		if (!type || cur->type == type)
> +			n++;
> +
> +	return n;
> +}
> +
> +/* Return child nodes, optionally filtering by type */
> +int nodeChildren(void *ctx, xmlNodePtr **nodes, xmlNodePtr node,
> +		 xmlElementType type)
> +{
> +	xmlNodePtr cur, *children = NULL;
> +	int n = 0;
> +
> +	for (cur = node->children; cur; cur = cur->next) {
> +		if (!type || cur->type == type) {
> +			children = talloc_realloc(ctx, children,
> +						xmlNodePtr, n + 1);
> +			children[n++] = cur;
> +		}
> +	}
> +
> +	*nodes = children;
> +	return n;
> +}
> +
> +/*
> + * This should only be called once we are completely finished with the library.
> + */
> +void finaliseXML(xmlDocPtr doc)
> +{
> +	xmlFreeDoc(doc);
> +	xmlCleanupParser();
> +}
> diff --git a/lib/xml/xml.h b/lib/xml/xml.h
> new file mode 100644
> index 0000000..91cc8d3
> --- /dev/null
> +++ b/lib/xml/xml.h
> @@ -0,0 +1,19 @@
> +#ifndef _XML_H
> +#define _XML_H
> +
> +#include <libxml/tree.h>
> +
> +xmlDocPtr readXMLFile(const char *path);
> +xmlNodePtr findXMLRoot(xmlDocPtr doc, const char *root_name);
> +xmlNodePtr findChildNode(xmlNodePtr root, xmlElementType type,
> +			 const char *name);
> +int nodeChildren(void *ctx, xmlNodePtr **nodes, xmlNodePtr node,
> +		 xmlElementType type);
> +bool hasChildren(xmlNodePtr node, xmlElementType type);
> +
> +char *nodeContent(void *ctx, xmlDocPtr doc, xmlNodePtr node);
> +char *nodeAttribute(void *ctx, xmlNodePtr node, const char *name);
> +void printAttrs(xmlDocPtr doc, xmlNodePtr node, const char *prefix);
> +void finaliseXML(xmlDocPtr doc);
> +
> +#endif /* _XML_H */



More information about the Petitboot mailing list