From 892a8c388150248da4a30e0b557a2a42c00a8420 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Wed, 8 Nov 2006 16:55:20 +0000 Subject: [PATCH] * include/libvirt/virterror.h src/virterror.c src/xend_internal.c src/xml.c: give proper indication of the failures raised by the XML parser on not well formed XML, should fix rhbz#208545 Daniel --- ChangeLog | 6 ++++++ include/libvirt/virterror.h | 3 ++- src/virterror.c | 15 ++++++++++++++- src/xend_internal.c | 5 +++-- src/xml.c | 35 ++++++++++++++++++++++++++++++++--- 5 files changed, 57 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index a103c59398..324a5ccdcc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Wed Nov 8 16:58:56 CET 2006 Daniel Veillard + + * include/libvirt/virterror.h src/virterror.c src/xend_internal.c + src/xml.c: give proper indication of the failures raised by the + XML parser on not well formed XML, should fix rhbz#208545 + Wed Nov 8 14:01:11 CET 2006 Daniel Veillard * src/libvirt.c src/proxy_internal.c src/xs_internal.c: fix the diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 5c07cbef49..e2d5369195 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -112,7 +112,8 @@ typedef enum { VIR_ERR_READ_FAILED, /* failed to read a conf file */ VIR_ERR_PARSE_FAILED, /* failed to parse a conf file */ VIR_ERR_CONF_SYNTAX, /* failed to parse the syntax of a conf file */ - VIR_ERR_WRITE_FAILED /* failed to write a conf file */ + VIR_ERR_WRITE_FAILED, /* failed to write a conf file */ + VIR_ERR_XML_DETAIL /* detail of an XML error */ } virErrorNumber; /** diff --git a/src/virterror.c b/src/virterror.c index f365b3d761..5d3a99a3c1 100644 --- a/src/virterror.c +++ b/src/virterror.c @@ -253,6 +253,9 @@ virDefaultErrorFunc(virErrorPtr err) case VIR_FROM_XEN: dom = "Xen "; break; + case VIR_FROM_XML: + dom = "XML "; + break; case VIR_FROM_XEND: dom = "Xen Daemon "; break; @@ -270,7 +273,11 @@ virDefaultErrorFunc(virErrorPtr err) domain = err->dom->name; } len = strlen(err->message); - if ((len == 0) || (err->message[len - 1] != '\n')) + if ((err->domain == VIR_FROM_XML) && (err->code == VIR_ERR_XML_DETAIL) && + (err->int1 != 0)) + fprintf(stderr, "libvir: %s%s %s: line %d: %s", + dom, lvl, domain, err->int1, err->message); + else if ((len == 0) || (err->message[len - 1] != '\n')) fprintf(stderr, "libvir: %s%s %s: %s\n", dom, lvl, domain, err->message); else @@ -569,6 +576,12 @@ __virErrorMsg(virErrorNumber error, const char *info) else errmsg = _("failed to write configuration file: %s"); break; + case VIR_ERR_XML_DETAIL: + if (info == NULL) + errmsg = _("parser error"); + else + errmsg = "%s"; + break; } return (errmsg); } diff --git a/src/xend_internal.c b/src/xend_internal.c index c1006cec6a..28f2ca121c 100644 --- a/src/xend_internal.c +++ b/src/xend_internal.c @@ -2870,13 +2870,14 @@ xenDaemonCreateLinux(virConnectPtr conn, const char *xmlDesc, } if ((xendConfigVersion = xend_get_config_version(conn)) < 0) { - virXendError(conn, VIR_ERR_INTERNAL_ERROR, "cannot determine xend config version"); + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + "cannot determine xend config version"); return (NULL); } sexpr = virDomainParseXMLDesc(xmlDesc, &name, xendConfigVersion); if ((sexpr == NULL) || (name == NULL)) { - virXendError(conn, VIR_ERR_XML_ERROR, "Failed to parse the XML domain description"); + virXendError(conn, VIR_ERR_XML_ERROR, "domain"); if (sexpr != NULL) free(sexpr); if (name != NULL) diff --git a/src/xml.c b/src/xml.c index df8c8dc627..21cc4fe2ce 100644 --- a/src/xml.c +++ b/src/xml.c @@ -910,6 +910,27 @@ virDomainParseXMLOSDescPV(xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr return (0); } +/** + * virCatchXMLParseError: + * @ctx: the context + * @msg: the error message + * @...: extra arguments + * + * SAX callback on parsing errors, act as a gate for libvirt own + * error reporting. + */ +static void +virCatchXMLParseError(void *ctx, const char *msg, ...) { + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + + if ((ctxt != NULL) && + (ctxt->lastError.level == XML_ERR_FATAL) && + (ctxt->lastError.message != NULL)) { + virXMLError(VIR_ERR_XML_DETAIL, ctxt->lastError.message, + ctxt->lastError.line); + } +} + /** * virDomainParseXMLDiskDesc: * @node: node containing disk description @@ -1168,6 +1189,7 @@ virDomainParseXMLDesc(const char *xmldesc, char **name, int xendConfigVersion) char *ret = NULL, *nam = NULL; virBuffer buf; xmlChar *prop; + xmlParserCtxtPtr pctxt; xmlXPathObjectPtr obj = NULL; xmlXPathObjectPtr tmpobj = NULL; xmlXPathContextPtr ctxt = NULL; @@ -1184,9 +1206,16 @@ virDomainParseXMLDesc(const char *xmldesc, char **name, int xendConfigVersion) buf.size = 1000; buf.use = 0; - xml = xmlReadDoc((const xmlChar *) xmldesc, "domain.xml", NULL, - XML_PARSE_NOENT | XML_PARSE_NONET | - XML_PARSE_NOERROR | XML_PARSE_NOWARNING); + pctxt = xmlNewParserCtxt(); + if ((pctxt == NULL) || (pctxt->sax == NULL)) { + goto error; + } + + pctxt->sax->error = virCatchXMLParseError; + + xml = xmlCtxtReadDoc(pctxt, (const xmlChar *) xmldesc, "domain.xml", NULL, + XML_PARSE_NOENT | XML_PARSE_NONET | + XML_PARSE_NOWARNING); if (xml == NULL) { goto error; }