[PATCH 5/9] lib: Add libxml2 support

Samuel Mendoza-Jonas sam.mj at au1.ibm.com
Tue Dec 15 14:15:26 AEDT 2015


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.

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 */
-- 
2.6.3



More information about the Petitboot mailing list