[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