On Thu, Jan 08, 2015 at 15:48:14 +0000, Daniel Berrange wrote:
Add a helper method that can validate an XML document against
an RNG schema
---
include/libvirt/virterror.h | 1 +
src/internal.h | 4 +++
src/libvirt_private.syms | 1 +
src/util/virerror.c | 6 ++++
src/util/virxml.c | 74 +++++++++++++++++++++++++++++++++++++++++++++
src/util/virxml.h | 5 +++
6 files changed, 91 insertions(+)
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index 85dd74c..3d3d80a 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -304,6 +304,7 @@ typedef enum {
VIR_ERR_STORAGE_VOL_EXIST = 90, /* the storage vol already exists */
VIR_ERR_CPU_INCOMPATIBLE = 91, /* given CPU is incompatible with host
CPU*/
+ VIR_ERR_XML_INVALID_SCHEMA = 92, /* XML document doens't validate against
schema */
} virErrorNumber;
/**
diff --git a/src/internal.h b/src/internal.h
index 30445c1..9855c49 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -234,11 +234,15 @@
# define VIR_WARNINGS_NO_CAST_ALIGN \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wcast-align\"")
+# define VIR_WARNINGS_NO_PRINTF \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored
\"-Wsuggest-attribute=format\"")
# define VIR_WARNINGS_RESET \
_Pragma ("GCC diagnostic pop")
# else
# define VIR_WARNINGS_NO_CAST_ALIGN
+# define VIR_WARNINGS_NO_PRINTF
# define VIR_WARNINGS_RESET
# endif
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index fb5d003..a376e2d 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2251,6 +2251,7 @@ virXMLParseHelper;
virXMLPickShellSafeComment;
virXMLPropString;
virXMLSaveFile;
+virXMLValidateAgainstSchema;
virXPathBoolean;
virXPathInt;
virXPathLong;
diff --git a/src/util/virerror.c b/src/util/virerror.c
index 4aa6d04..f5d7f54 100644
--- a/src/util/virerror.c
+++ b/src/util/virerror.c
@@ -1285,6 +1285,12 @@ virErrorMsg(virErrorNumber error, const char *info)
else
errmsg = _("the CPU is incompatible with host CPU: %s");
break;
+ case VIR_ERR_XML_INVALID_SCHEMA:
+ if (info == NULL)
+ errmsg = _("XML document failed to validate against schema");
+ else
+ errmsg = _("XML document failed to validate against schema:
%s");
+ break;
}
return errmsg;
}
diff --git a/src/util/virxml.c b/src/util/virxml.c
index 93f8590..f2c63aa 100644
--- a/src/util/virxml.c
+++ b/src/util/virxml.c
@@ -1082,3 +1082,77 @@ virXMLInjectNamespace(xmlNodePtr node,
return 0;
}
+
+static void catchRNGError(void *ctx,
+ const char *msg,
+ ...)
+{
+ virBufferPtr buf = ctx;
+ va_list args;
+
+ va_start(args, msg);
+ VIR_WARNINGS_NO_PRINTF;
+ virBufferVasprintf(buf, msg, args);
+ VIR_WARNINGS_RESET;
+ va_end(args);
+}
+
+
+static void ignoreRNGError(void *ctx ATTRIBUTE_UNUSED,
+ const char *msg ATTRIBUTE_UNUSED,
+ ...)
+{}
+
+
+int
+virXMLValidateAgainstSchema(const char *schemafile,
+ xmlDocPtr doc)
+{
+ xmlRelaxNGParserCtxtPtr rngParser = NULL;
+ xmlRelaxNGPtr rng = NULL;
+ xmlRelaxNGValidCtxtPtr rngValid = NULL;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ int ret = -1;
+
+ if (!(rngParser = xmlRelaxNGNewParserCtxt(schemafile))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to create RNG parser for %s"),
+ schemafile);
+ goto cleanup;
+ }
+
+ if (!(rng = xmlRelaxNGParse(rngParser))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to parse RNG %s"),
+ schemafile);
+ goto cleanup;
+ }
Do xmlRelaxNGNewParserCtxt and xmlRelaxNGParse functions provide any
usable error messages so that we can report some details about why
parsing RNG failed? For example, if the schema file is missing,
unreadable...
Jirka