* src/xml.[ch]: first patch to clean up XPath accesses with new

routines, only xml.c is cleaned up, other modules to follow.
Daniel
This commit is contained in:
Daniel Veillard 2007-04-06 12:28:24 +00:00
parent 18cd1a1e57
commit 4bdac20ad6
3 changed files with 370 additions and 177 deletions

View File

@ -1,3 +1,8 @@
Fri Apr 6 14:27:13 CEST 2007 Daniel Veillard <veillard@redhat.com>
* src/xml.[ch]: first patch to clean up XPath accesses with new
routines, only xml.c is cleaned up, other modules to follow.
Wed Apr 4 15:18:00 BST 2007 Richard W.M. Jones <rjones@redhat.com> Wed Apr 4 15:18:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
* src/xen_unified.c et al: Unified Xen driver. Architecture * src/xen_unified.c et al: Unified Xen driver. Architecture

521
src/xml.c
View File

@ -17,9 +17,6 @@
#ifdef WITH_XEN #ifdef WITH_XEN
#include <xs.h> #include <xs.h>
#endif #endif
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <math.h> /* for isnan() */ #include <math.h> /* for isnan() */
#include "internal.h" #include "internal.h"
#include "hash.h" #include "hash.h"
@ -27,6 +24,15 @@
#include "xml.h" #include "xml.h"
#include "xs_internal.h" /* for xenStoreDomainGetNetworkID */ #include "xs_internal.h" /* for xenStoreDomainGetNetworkID */
/**
* virXMLError:
* @conn: a connection if any
* @error: the error number
* @info: information/format string
* @value: extra integer parameter for the error string
*
* Report an error coming from the XML module.
*/
static void static void
virXMLError(virConnectPtr conn, virErrorNumber error, const char *info, int value) virXMLError(virConnectPtr conn, virErrorNumber error, const char *info, int value)
{ {
@ -40,6 +46,227 @@ virXMLError(virConnectPtr conn, virErrorNumber error, const char *info, int valu
errmsg, info, NULL, value, 0, errmsg, info, value); errmsg, info, NULL, value, 0, errmsg, info, value);
} }
#ifndef PROXY
/**
* virXPathString:
* @xpath: the XPath string to evaluate
* @ctxt: an XPath context
*
* Convenience function to evaluate an XPath string
*
* Returns a new string which must be deallocated by the caller or NULL
* if the evaluation failed.
*/
char *
virXPathString(const char *xpath, xmlXPathContextPtr ctxt) {
xmlXPathObjectPtr obj;
char *ret;
if ((ctxt == NULL) || (xpath == NULL)) {
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
"Invalid parameter to virXPathString()", 0);
return(NULL);
}
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
(obj->stringval == NULL) || (obj->stringval[0] == 0))
return(NULL);
ret = strdup((char *) obj->stringval);
xmlXPathFreeObject(obj);
if (ret == NULL) {
virXMLError(NULL, VIR_ERR_NO_MEMORY, "strdup", 0);
}
return(ret);
}
/**
* virXPathNumber:
* @xpath: the XPath string to evaluate
* @ctxt: an XPath context
* @value: the returned double value
*
* Convenience function to evaluate an XPath number
*
* Returns 0 in case of success in which case @value is set,
* or -1 if the evaluation failed.
*/
int
virXPathNumber(const char *xpath, xmlXPathContextPtr ctxt, double *value) {
xmlXPathObjectPtr obj;
if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) {
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
"Invalid parameter to virXPathNumber()", 0);
return(-1);
}
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
if ((obj == NULL) || (obj->type != XPATH_NUMBER) ||
(isnan(obj->floatval))) {
xmlXPathFreeObject(obj);
return(-1);
}
*value = obj->floatval;
xmlXPathFreeObject(obj);
return(0);
}
/**
* virXPathLong:
* @xpath: the XPath string to evaluate
* @ctxt: an XPath context
* @value: the returned long value
*
* Convenience function to evaluate an XPath number
*
* Returns 0 in case of success in which case @value is set,
* or -1 if the evaluation failed.
*/
int
virXPathLong(const char *xpath, xmlXPathContextPtr ctxt, long *value) {
xmlXPathObjectPtr obj;
int ret = 0;
if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) {
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
"Invalid parameter to virXPathNumber()", 0);
return(-1);
}
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
char *conv = NULL;
long val;
val = strtol((const char*)obj->stringval, &conv, 10);
if (conv == (const char*)obj->stringval) {
ret = -2;
} else {
*value = val;
}
} else if ((obj != NULL) && (obj->type == XPATH_NUMBER) &&
(!(isnan(obj->floatval)))) {
*value = (long) obj->floatval;
if (*value != obj->floatval) {
ret = -2;
}
} else {
ret = -1;
}
xmlXPathFreeObject(obj);
return(ret);
}
/**
* virXPathBoolean:
* @xpath: the XPath string to evaluate
* @ctxt: an XPath context
*
* Convenience function to evaluate an XPath boolean
*
* Returns 0 if false, 1 if true, or -1 if the evaluation failed.
*/
int
virXPathBoolean(const char *xpath, xmlXPathContextPtr ctxt) {
xmlXPathObjectPtr obj;
int ret;
if ((ctxt == NULL) || (xpath == NULL)) {
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
"Invalid parameter to virXPathBoolean()", 0);
return(-1);
}
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
if ((obj == NULL) || (obj->type != XPATH_BOOLEAN) ||
(obj->boolval < 0) || (obj->boolval > 1)) {
xmlXPathFreeObject(obj);
return(-1);
}
ret = obj->boolval;
xmlXPathFreeObject(obj);
return(ret);
}
/**
* virXPathNode:
* @xpath: the XPath string to evaluate
* @ctxt: an XPath context
*
* Convenience function to evaluate an XPath node set and returning
* only one node, the first one in the set if any
*
* Returns a pointer to the node or NULL if the evaluation failed.
*/
xmlNodePtr
virXPathNode(const char *xpath, xmlXPathContextPtr ctxt) {
xmlXPathObjectPtr obj;
xmlNodePtr ret;
if ((ctxt == NULL) || (xpath == NULL)) {
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
"Invalid parameter to virXPathNode()", 0);
return(NULL);
}
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
(obj->nodesetval == NULL) || (obj->nodesetval->nodeNr <= 0) ||
(obj->nodesetval->nodeTab == NULL)) {
xmlXPathFreeObject(obj);
return(NULL);
}
ret = obj->nodesetval->nodeTab[0];
xmlXPathFreeObject(obj);
return(ret);
}
/**
* virXPathNodeSet:
* @xpath: the XPath string to evaluate
* @ctxt: an XPath context
* @list: the returned list of nodes (or NULL if only count matters)
*
* Convenience function to evaluate an XPath node set
*
* Returns the number of nodes found in which case @list is set (and
* must be freed) or -1 if the evaluation failed.
*/
int
virXPathNodeSet(const char *xpath, xmlXPathContextPtr ctxt, xmlNodePtr **list) {
xmlXPathObjectPtr obj;
int ret;
if ((ctxt == NULL) || (xpath == NULL)) {
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
"Invalid parameter to virXPathNodeSet()", 0);
return(-1);
}
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
(obj->nodesetval == NULL) || (obj->nodesetval->nodeNr <= 0) ||
(obj->nodesetval->nodeTab == NULL)) {
xmlXPathFreeObject(obj);
if (list != NULL)
*list = NULL;
return(-1);
}
ret = obj->nodesetval->nodeNr;
if (list != NULL) {
*list = malloc(ret * sizeof(xmlNodePtr));
if (*list == NULL) {
virXMLError(NULL, VIR_ERR_NO_MEMORY,
_("allocate string array"), ret * sizeof(xmlNodePtr));
} else {
memcpy(*list, obj->nodesetval->nodeTab, ret * sizeof(xmlNodePtr));
}
}
xmlXPathFreeObject(obj);
return(ret);
}
#endif /* !PROXY */
/** /**
* virBufferGrow: * virBufferGrow:
* @buf: the buffer * @buf: the buffer
@ -360,12 +587,12 @@ static int virDomainParseXMLGraphicsDescVFB(virConnectPtr conn ATTRIBUTE_UNUSED,
static int static int
virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int vcpus, int xendConfigVersion) virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int vcpus, int xendConfigVersion)
{ {
xmlXPathObjectPtr obj = NULL;
xmlNodePtr cur, txt; xmlNodePtr cur, txt;
xmlChar *type = NULL; xmlChar *type = NULL;
xmlChar *loader = NULL; xmlChar *loader = NULL;
xmlChar *boot_dev = NULL; xmlChar *boot_dev = NULL;
int res; int res;
char *str;
cur = node->children; cur = node->children;
while (cur != NULL) { while (cur != NULL) {
@ -403,16 +630,13 @@ virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf
} }
/* get the device emulation model */ /* get the device emulation model */
obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt); str = virXPathString("string(/domain/devices/emulator[1])", ctxt);
if ((obj == NULL) || (obj->type != XPATH_STRING) || if (str == NULL) {
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
virXMLError(conn, VIR_ERR_NO_KERNEL, NULL, 0); /* TODO: error */ virXMLError(conn, VIR_ERR_NO_KERNEL, NULL, 0); /* TODO: error */
goto error; goto error;
} }
virBufferVSprintf(buf, "(device_model '%s')", virBufferVSprintf(buf, "(device_model '%s')", str);
(const char *) obj->stringval); xmlFree(str);
xmlXPathFreeObject(obj);
obj = NULL;
virBufferVSprintf(buf, "(vcpus %d)", vcpus); virBufferVSprintf(buf, "(vcpus %d)", vcpus);
@ -429,102 +653,78 @@ virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf
} }
/* get the 1st floppy device file */ /* get the 1st floppy device file */
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='floppy' and target/@dev='fda']/source", ctxt); cur = virXPathNode(
if ((obj != NULL) && (obj->type == XPATH_NODESET) && "/domain/devices/disk[@device='floppy' and target/@dev='fda']/source",
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) { ctxt);
cur = obj->nodesetval->nodeTab[0]; if (cur != NULL) {
virBufferVSprintf(buf, "(fda '%s')", xmlChar *fdfile;
(const char *) xmlGetProp(cur, BAD_CAST "file"));
cur = NULL; fdfile = xmlGetProp(cur, BAD_CAST "file");
} if (fdfile != NULL) {
if (obj) { virBufferVSprintf(buf, "(fda '%s')", fdfile);
xmlXPathFreeObject(obj); free(fdfile);
obj = NULL; }
} }
/* get the 2nd floppy device file */ /* get the 2nd floppy device file */
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='floppy' and target/@dev='fdb']/source", ctxt); cur = virXPathNode(
if ((obj != NULL) && (obj->type == XPATH_NODESET) && "/domain/devices/disk[@device='floppy' and target/@dev='fdb']/source",
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) { ctxt);
xmlChar *fdfile = NULL; if (cur != NULL) {
cur = obj->nodesetval->nodeTab[0]; xmlChar *fdfile;
fdfile = xmlGetProp(cur, BAD_CAST "file"); fdfile = xmlGetProp(cur, BAD_CAST "file");
virBufferVSprintf(buf, "(fdb '%s')", if (fdfile != NULL) {
(const char *) fdfile); virBufferVSprintf(buf, "(fdb '%s')", fdfile);
xmlFree(fdfile); free(fdfile);
cur = NULL; }
}
if (obj) {
xmlXPathFreeObject(obj);
obj = NULL;
} }
/* get the cdrom device file */ /* get the cdrom device file */
/* Only XenD <= 3.0.2 wants cdrom config here */ /* Only XenD <= 3.0.2 wants cdrom config here */
if (xendConfigVersion == 1) { if (xendConfigVersion == 1) {
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='cdrom' and target/@dev='hdc']/source", ctxt); cur = virXPathNode(
if ((obj != NULL) && (obj->type == XPATH_NODESET) && "/domain/devices/disk[@device='cdrom' and target/@dev='hdc']/source",
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) { ctxt);
xmlChar *cdfile = NULL; if (cur != NULL) {
cur = obj->nodesetval->nodeTab[0]; xmlChar *cdfile;
cdfile = xmlGetProp(cur, BAD_CAST "file"); cdfile = xmlGetProp(cur, BAD_CAST "file");
virBufferVSprintf(buf, "(cdrom '%s')", if (cdfile != NULL) {
(const char *)cdfile); virBufferVSprintf(buf, "(cdrom '%s')",
xmlFree(cdfile); (const char *)cdfile);
cur = NULL; xmlFree(cdfile);
} }
if (obj) {
xmlXPathFreeObject(obj);
obj = NULL;
} }
} }
obj = xmlXPathEval(BAD_CAST "/domain/features/acpi", ctxt); if (virXPathNode("/domain/features/acpi", ctxt) != NULL)
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
virBufferAdd(buf, "(acpi 1)", 8); virBufferAdd(buf, "(acpi 1)", 8);
} if (virXPathNode("/domain/features/apic", ctxt) != NULL)
if (obj)
xmlXPathFreeObject(obj);
obj = xmlXPathEval(BAD_CAST "/domain/features/apic", ctxt);
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
virBufferAdd(buf, "(apic 1)", 8); virBufferAdd(buf, "(apic 1)", 8);
} if (virXPathNode("/domain/features/pae", ctxt) != NULL)
if (obj)
xmlXPathFreeObject(obj);
obj = xmlXPathEval(BAD_CAST "/domain/features/pae", ctxt);
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
virBufferAdd(buf, "(pae 1)", 7); virBufferAdd(buf, "(pae 1)", 7);
}
if (obj)
xmlXPathFreeObject(obj);
obj = NULL;
} }
obj = xmlXPathEval(BAD_CAST "count(domain/devices/console) > 0", ctxt); res = virXPathBoolean("count(domain/devices/console) > 0", ctxt);
if ((obj == NULL) || (obj->type != XPATH_BOOLEAN)) { if (res < 0) {
virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0); virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0);
goto error; goto error;
} }
if (obj->boolval) { if (res) {
virBufferAdd(buf, "(serial pty)", 12); virBufferAdd(buf, "(serial pty)", 12);
} }
xmlXPathFreeObject(obj);
obj = NULL;
/* Is a graphics device specified? */ /* Is a graphics device specified? */
obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics[1]", ctxt); cur = virXPathNode("/domain/devices/graphics[1]", ctxt);
if ((obj != NULL) && (obj->type == XPATH_NODESET) && if (cur != NULL) {
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) { res = virDomainParseXMLGraphicsDescImage(conn, cur, buf,
res = virDomainParseXMLGraphicsDescImage(conn, obj->nodesetval->nodeTab[0], buf, xendConfigVersion); xendConfigVersion);
if (res != 0) { if (res != 0) {
goto error; goto error;
} }
} }
xmlXPathFreeObject(obj);
virBufferAdd(buf, "))", 2); virBufferAdd(buf, "))", 2);
@ -535,8 +735,6 @@ virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf
error: error:
if (boot_dev) if (boot_dev)
xmlFree(boot_dev); xmlFree(boot_dev);
if (obj != NULL)
xmlXPathFreeObject(obj);
return(-1); return(-1);
} }
@ -559,7 +757,6 @@ static int
virDomainParseXMLOSDescPV(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int xendConfigVersion) virDomainParseXMLOSDescPV(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int xendConfigVersion)
{ {
xmlNodePtr cur, txt; xmlNodePtr cur, txt;
xmlXPathObjectPtr obj = NULL;
const xmlChar *type = NULL; const xmlChar *type = NULL;
const xmlChar *root = NULL; const xmlChar *root = NULL;
const xmlChar *kernel = NULL; const xmlChar *kernel = NULL;
@ -626,15 +823,14 @@ virDomainParseXMLOSDescPV(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf,
/* Is a graphics device specified? */ /* Is a graphics device specified? */
/* Old style config before merge of PVFB */ /* Old style config before merge of PVFB */
if (xendConfigVersion < 3) { if (xendConfigVersion < 3) {
obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics[1]", ctxt); cur = virXPathNode("/domain/devices/graphics[1]", ctxt);
if ((obj != NULL) && (obj->type == XPATH_NODESET) && if (cur != NULL) {
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) { res = virDomainParseXMLGraphicsDescImage(conn, cur, buf,
res = virDomainParseXMLGraphicsDescImage(conn, obj->nodesetval->nodeTab[0], buf, xendConfigVersion); xendConfigVersion);
if (res != 0) { if (res != 0) {
goto error; goto error;
} }
} }
xmlXPathFreeObject(obj);
} }
error: error:
@ -958,14 +1154,16 @@ virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int
virBuffer buf; virBuffer buf;
xmlChar *prop; xmlChar *prop;
xmlParserCtxtPtr pctxt; xmlParserCtxtPtr pctxt;
xmlXPathObjectPtr obj = NULL;
xmlXPathObjectPtr tmpobj = NULL;
xmlXPathContextPtr ctxt = NULL; xmlXPathContextPtr ctxt = NULL;
int i, res; int i, res;
int bootloader = 0; int bootloader = 0;
int hvm = 0; int hvm = 0;
unsigned int vcpus = 1; unsigned int vcpus = 1;
unsigned long mem = 0, max_mem = 0; unsigned long mem = 0, max_mem = 0;
char *str;
double f;
xmlNodePtr *nodes;
int nb_nodes;
if (name != NULL) if (name != NULL)
*name = NULL; *name = NULL;
@ -1012,117 +1210,90 @@ virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int
/* /*
* extract some of the basics, name, memory, cpus ... * extract some of the basics, name, memory, cpus ...
*/ */
obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt); nam = virXPathString("string(/domain/name[1])", ctxt);
if ((obj == NULL) || (obj->type != XPATH_STRING) || if (nam == NULL) {
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
virXMLError(conn, VIR_ERR_NO_NAME, xmldesc, 0); virXMLError(conn, VIR_ERR_NO_NAME, xmldesc, 0);
goto error; goto error;
} }
virBufferVSprintf(&buf, "(name '%s')", obj->stringval); virBufferVSprintf(&buf, "(name '%s')", nam);
nam = strdup((const char *) obj->stringval);
if (nam == NULL) {
virXMLError(conn, VIR_ERR_NO_MEMORY, "copying name", 0);
goto error;
}
xmlXPathFreeObject(obj);
obj = xmlXPathEval(BAD_CAST "number(/domain/memory[1])", ctxt); if ((virXPathNumber("number(/domain/memory[1])", ctxt, &f) < 0) ||
if ((obj == NULL) || (obj->type != XPATH_NUMBER) || (f < MIN_XEN_GUEST_SIZE * 1024)) {
(isnan(obj->floatval)) || (obj->floatval < MIN_XEN_GUEST_SIZE * 1024)) {
max_mem = 128; max_mem = 128;
} else { } else {
max_mem = (obj->floatval / 1024); max_mem = (f / 1024);
} }
xmlXPathFreeObject(obj);
obj = xmlXPathEval(BAD_CAST "number(/domain/currentMemory[1])", ctxt); if ((virXPathNumber("number(/domain/currentMemory[1])", ctxt, &f) < 0) ||
if ((obj == NULL) || (obj->type != XPATH_NUMBER) || (f < MIN_XEN_GUEST_SIZE * 1024)) {
(isnan(obj->floatval)) || (obj->floatval < MIN_XEN_GUEST_SIZE * 1024)) {
mem = max_mem; mem = max_mem;
} else { } else {
mem = (obj->floatval / 1024); mem = (f / 1024);
if (mem > max_mem) { if (mem > max_mem) {
max_mem = mem; max_mem = mem;
} }
} }
xmlXPathFreeObject(obj);
virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", mem, max_mem); virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", mem, max_mem);
obj = xmlXPathEval(BAD_CAST "number(/domain/vcpu[1])", ctxt); if ((virXPathNumber("number(/domain/vcpu[1])", ctxt, &f) == 0) &&
if ((obj != NULL) && (obj->type == XPATH_NUMBER) && (f > 0)) {
(!isnan(obj->floatval)) && (obj->floatval > 0)) { vcpus = (unsigned int) f;
vcpus = (unsigned int) obj->floatval;
} }
virBufferVSprintf(&buf, "(vcpus %u)", vcpus); virBufferVSprintf(&buf, "(vcpus %u)", vcpus);
xmlXPathFreeObject(obj);
obj = xmlXPathEval(BAD_CAST "string(/domain/uuid[1])", ctxt); str = virXPathString("string(/domain/uuid[1])", ctxt);
if ((obj == NULL) || ((obj->type == XPATH_STRING) && if (str != NULL) {
(obj->stringval != NULL) && (obj->stringval[0] != 0))) { virBufferVSprintf(&buf, "(uuid '%s')", str);
virBufferVSprintf(&buf, "(uuid '%s')", obj->stringval); free(str);
} }
xmlXPathFreeObject(obj);
obj = xmlXPathEval(BAD_CAST "string(/domain/bootloader[1])", ctxt); str = virXPathString("string(/domain/bootloader[1])", ctxt);
if ((obj != NULL) && (obj->type == XPATH_STRING) && if (str != NULL) {
(obj->stringval != NULL) && (obj->stringval[0] != 0)) { virBufferVSprintf(&buf, "(bootloader '%s')", str);
virBufferVSprintf(&buf, "(bootloader '%s')", obj->stringval);
/* /*
* if using pygrub, the kernel and initrd strings are not * if using pygrub, the kernel and initrd strings are not
* significant and should be discarded * significant and should be discarded
*/ */
if (xmlStrstr(obj->stringval, BAD_CAST "pygrub")) if (strstr(str, "pygrub"))
bootloader = 2; bootloader = 2;
else else
bootloader = 1; bootloader = 1;
free(str);
} }
xmlXPathFreeObject(obj);
obj = xmlXPathEval(BAD_CAST "string(/domain/on_poweroff[1])", ctxt); str = virXPathString("string(/domain/on_poweroff[1])", ctxt);
if ((obj != NULL) && (obj->type == XPATH_STRING) && if (str != NULL) {
(obj->stringval != NULL) && (obj->stringval[0] != 0)) { virBufferVSprintf(&buf, "(on_poweroff '%s')", str);
virBufferVSprintf(&buf, "(on_poweroff '%s')", obj->stringval); free(str);
} }
xmlXPathFreeObject(obj);
obj = xmlXPathEval(BAD_CAST "string(/domain/on_reboot[1])", ctxt); str = virXPathString("string(/domain/on_reboot[1])", ctxt);
if ((obj != NULL) && (obj->type == XPATH_STRING) && if (str != NULL) {
(obj->stringval != NULL) && (obj->stringval[0] != 0)) { virBufferVSprintf(&buf, "(on_reboot '%s')", str);
virBufferVSprintf(&buf, "(on_reboot '%s')", obj->stringval); free(str);
} }
xmlXPathFreeObject(obj);
obj = xmlXPathEval(BAD_CAST "string(/domain/on_crash[1])", ctxt); str = virXPathString("string(/domain/on_crash[1])", ctxt);
if ((obj != NULL) && (obj->type == XPATH_STRING) && if (str != NULL) {
(obj->stringval != NULL) && (obj->stringval[0] != 0)) { virBufferVSprintf(&buf, "(on_crash '%s')", str);
virBufferVSprintf(&buf, "(on_crash '%s')", obj->stringval); free(str);
} }
xmlXPathFreeObject(obj);
if (bootloader != 2) { if (bootloader != 2) {
obj = xmlXPathEval(BAD_CAST "/domain/os[1]", ctxt); if ((node = virXPathNode("/domain/os[1]", ctxt)) != NULL) {
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
/* Analyze of the os description, based on HVM or PV. */ /* Analyze of the os description, based on HVM or PV. */
tmpobj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1])", ctxt); str = virXPathString("string(/domain/os/type[1])", ctxt);
if ((tmpobj != NULL) &&
((tmpobj->type != XPATH_STRING) || (tmpobj->stringval == NULL)
|| (tmpobj->stringval[0] == 0))) {
xmlXPathFreeObject(tmpobj);
virXMLError(conn, VIR_ERR_OS_TYPE, nam, 0);
goto error;
}
if ((tmpobj == NULL) if ((str == NULL) || (strcmp(str, "hvm"))) {
|| !xmlStrEqual(tmpobj->stringval, BAD_CAST "hvm")) { res = virDomainParseXMLOSDescPV(conn, node,
res = virDomainParseXMLOSDescPV(conn, obj->nodesetval->nodeTab[0],
&buf, ctxt, xendConfigVersion); &buf, ctxt, xendConfigVersion);
} else { } else {
hvm = 1; hvm = 1;
res = virDomainParseXMLOSDescHVM(conn, obj->nodesetval->nodeTab[0], res = virDomainParseXMLOSDescHVM(conn, node, &buf, ctxt,
&buf, ctxt, vcpus, xendConfigVersion); vcpus, xendConfigVersion);
} }
xmlXPathFreeObject(tmpobj); if (str != NULL) free(str);
if (res != 0) if (res != 0)
goto error; goto error;
@ -1130,49 +1301,49 @@ virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int
virXMLError(conn, VIR_ERR_NO_OS, nam, 0); virXMLError(conn, VIR_ERR_NO_OS, nam, 0);
goto error; goto error;
} }
xmlXPathFreeObject(obj);
} }
/* analyze of the devices */ /* analyze of the devices */
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt); nb_nodes = virXPathNodeSet("/domain/devices/disk", ctxt, &nodes);
if ((obj != NULL) && (obj->type == XPATH_NODESET) && if (nb_nodes > 0) {
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) { for (i = 0; i < nb_nodes; i++) {
for (i = 0; i < obj->nodesetval->nodeNr; i++) { res = virDomainParseXMLDiskDesc(conn, nodes[i], &buf,
res = virDomainParseXMLDiskDesc(conn, obj->nodesetval->nodeTab[i], &buf, hvm, xendConfigVersion); hvm, xendConfigVersion);
if (res != 0) { if (res != 0) {
free(nodes);
goto error; goto error;
} }
} }
free(nodes);
} }
xmlXPathFreeObject(obj);
obj = xmlXPathEval(BAD_CAST "/domain/devices/interface", ctxt); nb_nodes = virXPathNodeSet("/domain/devices/interface", ctxt, &nodes);
if ((obj != NULL) && (obj->type == XPATH_NODESET) && if (nb_nodes > 0) {
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) { for (i = 0; i < nb_nodes; i++) {
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
virBufferAdd(&buf, "(device ", 8); virBufferAdd(&buf, "(device ", 8);
res = virDomainParseXMLIfDesc(conn, obj->nodesetval->nodeTab[i], &buf, hvm); res = virDomainParseXMLIfDesc(conn, nodes[i], &buf, hvm);
if (res != 0) { if (res != 0) {
free(nodes);
goto error; goto error;
} }
virBufferAdd(&buf, ")", 1); virBufferAdd(&buf, ")", 1);
} }
free(nodes);
} }
xmlXPathFreeObject(obj);
/* New style PVFB config - 3.0.4 merge */ /* New style PVFB config - 3.0.4 merge */
if (xendConfigVersion >= 3 && !hvm) { if (xendConfigVersion >= 3 && !hvm) {
obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics", ctxt); nb_nodes = virXPathNodeSet("/domain/devices/graphics", ctxt, &nodes);
if ((obj != NULL) && (obj->type == XPATH_NODESET) && if (nb_nodes > 0) {
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) { for (i = 0; i < nb_nodes; i++) {
for (i = 0; i < obj->nodesetval->nodeNr; i++) { res = virDomainParseXMLGraphicsDescVFB(conn, nodes[i], &buf);
res = virDomainParseXMLGraphicsDescVFB(conn, obj->nodesetval->nodeTab[i], &buf);
if (res != 0) { if (res != 0) {
free(nodes);
goto error; goto error;
} }
} }
free(nodes);
} }
xmlXPathFreeObject(obj);
} }
@ -1195,8 +1366,6 @@ virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int
free(nam); free(nam);
if (name != NULL) if (name != NULL)
*name = NULL; *name = NULL;
if (obj != NULL)
xmlXPathFreeObject(obj);
if (ctxt != NULL) if (ctxt != NULL)
xmlXPathFreeContext(ctxt); xmlXPathFreeContext(ctxt);
if (xml != NULL) if (xml != NULL)

View File

@ -1,5 +1,5 @@
/* /*
* internal.h: internal definitions just used by code from the library * xml.h: internal definitions used for XML parsing routines.
*/ */
#ifndef __VIR_XML_H__ #ifndef __VIR_XML_H__
@ -8,6 +8,9 @@
#include "libvirt/libvirt.h" #include "libvirt/libvirt.h"
#include "internal.h" #include "internal.h"
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -32,6 +35,22 @@ int virBufferVSprintf(virBufferPtr buf, const char *format, ...)
ATTRIBUTE_FORMAT(printf, 2, 3); ATTRIBUTE_FORMAT(printf, 2, 3);
int virBufferStrcat(virBufferPtr buf, ...); int virBufferStrcat(virBufferPtr buf, ...);
int virXPathBoolean (const char *xpath,
xmlXPathContextPtr ctxt);
char * virXPathString (const char *xpath,
xmlXPathContextPtr ctxt);
int virXPathNumber (const char *xpath,
xmlXPathContextPtr ctxt,
double *value);
int virXPathLong (const char *xpath,
xmlXPathContextPtr ctxt,
long *value);
xmlNodePtr virXPathNode (const char *xpath,
xmlXPathContextPtr ctxt);
int virXPathNodeSet (const char *xpath,
xmlXPathContextPtr ctxt,
xmlNodePtr **list);
char *virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int xendConfigVersion); char *virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int xendConfigVersion);
unsigned char *virParseUUID(char **ptr, const char *uuid); unsigned char *virParseUUID(char **ptr, const char *uuid);
char *virParseXMLDevice(virConnectPtr conn, char *xmldesc, int hvm, int xendConfigVersion); char *virParseXMLDevice(virConnectPtr conn, char *xmldesc, int hvm, int xendConfigVersion);