[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