[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 4/8] Moved SEXPR formatting functions to xenxs



---
 src/xen/xend_internal.c   |  876 ---------------------------------------------
 src/xen/xend_internal.h   |   12 -
 src/xenxs/xen_sxpr.c      |  850 +++++++++++++++++++++++++++++++++++++++++++-
 src/xenxs/xen_sxpr.h      |   32 ++
 src/xenxs/xenxs_private.h |   18 +
 tests/xml2sexprtest.c     |    1 +
 6 files changed, 900 insertions(+), 889 deletions(-)

diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index 70f6ac4..7e381e9 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -59,36 +59,9 @@
 #define XEN_SCHED_SEDF_NPARAM   6
 #define XEN_SCHED_CRED_NPARAM   2
 
-#ifdef WITH_RHEL5_API
-# define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 0
-# define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 2
-#else
-# define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 3
-# define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 3
-#endif
-
 #define XEND_RCV_BUF_MAX_LEN 65536
 
 static int
-xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
-                        virDomainDiskDefPtr def,
-                        virBufferPtr buf,
-                        int hvm,
-                        int xendConfigVersion,
-                        int isAttach);
-static int
-xenDaemonFormatSxprNet(virConnectPtr conn ATTRIBUTE_UNUSED,
-                       virDomainNetDefPtr def,
-                       virBufferPtr buf,
-                       int hvm,
-                       int xendConfigVersion,
-                       int isAttach);
-static int
-xenDaemonFormatSxprOnePCI(virDomainHostdevDefPtr def,
-                          virBufferPtr buf,
-                          int detach);
-
-static int
 virDomainXMLDevID(virDomainPtr domain,
                   virDomainDeviceDefPtr dev,
                   char *class,
@@ -3872,855 +3845,6 @@ struct xenUnifiedDriver xenDaemonDriver = {
     xenDaemonSetSchedulerParameters, /* domainSetSchedulerParameters */
 };
 
-/************************************************************************
- *									*
- * Converter functions to go from the XML tree to an S-Expr for Xen	*
- *									*
- ************************************************************************/
-
-
-/**
- * virtDomainParseXMLGraphicsDescVFB:
- * @conn: pointer to the hypervisor connection
- * @node: node containing graphics description
- * @buf: a buffer for the result S-Expr
- *
- * Parse the graphics part of the XML description and add it to the S-Expr
- * in buf.  This is a temporary interface as the S-Expr interface will be
- * replaced by XML-RPC in the future. However the XML format should stay
- * valid over time.
- *
- * Returns 0 in case of success, -1 in case of error
- */
-static int
-xenDaemonFormatSxprGraphicsNew(virDomainGraphicsDefPtr def,
-                               virBufferPtr buf)
-{
-    if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
-        def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
-        virXendError(VIR_ERR_INTERNAL_ERROR,
-                     _("unexpected graphics type %d"),
-                     def->type);
-        return -1;
-    }
-
-    virBufferAddLit(buf, "(device (vkbd))");
-    virBufferAddLit(buf, "(device (vfb ");
-
-    if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
-        virBufferAddLit(buf, "(type sdl)");
-        if (def->data.sdl.display)
-            virBufferVSprintf(buf, "(display '%s')", def->data.sdl.display);
-        if (def->data.sdl.xauth)
-            virBufferVSprintf(buf, "(xauthority '%s')", def->data.sdl.xauth);
-    } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
-        virBufferAddLit(buf, "(type vnc)");
-        if (def->data.vnc.autoport) {
-            virBufferAddLit(buf, "(vncunused 1)");
-        } else {
-            virBufferAddLit(buf, "(vncunused 0)");
-            virBufferVSprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900);
-        }
-
-        if (def->data.vnc.listenAddr)
-            virBufferVSprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr);
-        if (def->data.vnc.auth.passwd)
-            virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.auth.passwd);
-        if (def->data.vnc.keymap)
-            virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
-    }
-
-    virBufferAddLit(buf, "))");
-
-    return 0;
-}
-
-
-static int
-xenDaemonFormatSxprGraphicsOld(virDomainGraphicsDefPtr def,
-                               virBufferPtr buf,
-                               int xendConfigVersion)
-{
-    if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
-        def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
-        virXendError(VIR_ERR_INTERNAL_ERROR,
-                     _("unexpected graphics type %d"),
-                     def->type);
-        return -1;
-    }
-
-    if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
-        virBufferAddLit(buf, "(sdl 1)");
-        if (def->data.sdl.display)
-            virBufferVSprintf(buf, "(display '%s')", def->data.sdl.display);
-        if (def->data.sdl.xauth)
-            virBufferVSprintf(buf, "(xauthority '%s')", def->data.sdl.xauth);
-    } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
-        virBufferAddLit(buf, "(vnc 1)");
-        if (xendConfigVersion >= 2) {
-            if (def->data.vnc.autoport) {
-                virBufferAddLit(buf, "(vncunused 1)");
-            } else {
-                virBufferAddLit(buf, "(vncunused 0)");
-                virBufferVSprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900);
-            }
-
-            if (def->data.vnc.listenAddr)
-                virBufferVSprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr);
-            if (def->data.vnc.auth.passwd)
-                virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.auth.passwd);
-            if (def->data.vnc.keymap)
-                virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
-
-        }
-    }
-
-    return 0;
-}
-
-int
-xenDaemonFormatSxprChr(virDomainChrDefPtr def,
-                       virBufferPtr buf)
-{
-    const char *type = virDomainChrTypeToString(def->source.type);
-
-    if (!type) {
-        virXendError(VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("unexpected chr device type"));
-        return -1;
-    }
-
-    switch (def->source.type) {
-    case VIR_DOMAIN_CHR_TYPE_NULL:
-    case VIR_DOMAIN_CHR_TYPE_STDIO:
-    case VIR_DOMAIN_CHR_TYPE_VC:
-    case VIR_DOMAIN_CHR_TYPE_PTY:
-        virBufferVSprintf(buf, "%s", type);
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_FILE:
-    case VIR_DOMAIN_CHR_TYPE_PIPE:
-        virBufferVSprintf(buf, "%s:", type);
-        virBufferEscapeSexpr(buf, "%s", def->source.data.file.path);
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_DEV:
-        virBufferEscapeSexpr(buf, "%s", def->source.data.file.path);
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_TCP:
-        virBufferVSprintf(buf, "%s:%s:%s%s",
-                          (def->source.data.tcp.protocol
-                           == VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW ?
-                           "tcp" : "telnet"),
-                          (def->source.data.tcp.host ?
-                           def->source.data.tcp.host : ""),
-                          (def->source.data.tcp.service ?
-                           def->source.data.tcp.service : ""),
-                          (def->source.data.tcp.listen ?
-                           ",server,nowait" : ""));
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_UDP:
-        virBufferVSprintf(buf, "%s:%s:%s %s:%s", type,
-                          (def->source.data.udp.connectHost ?
-                           def->source.data.udp.connectHost : ""),
-                          (def->source.data.udp.connectService ?
-                           def->source.data.udp.connectService : ""),
-                          (def->source.data.udp.bindHost ?
-                           def->source.data.udp.bindHost : ""),
-                          (def->source.data.udp.bindService ?
-                           def->source.data.udp.bindService : ""));
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_UNIX:
-        virBufferVSprintf(buf, "%s:", type);
-        virBufferEscapeSexpr(buf, "%s", def->source.data.nix.path);
-        if (def->source.data.nix.listen)
-            virBufferAddLit(buf, ",server,nowait");
-        break;
-    }
-
-    if (virBufferError(buf)) {
-        virReportOOMError();
-        return -1;
-    }
-
-    return 0;
-}
-
-
-/**
- * virDomainParseXMLDiskDesc:
- * @node: node containing disk description
- * @conn: pointer to the hypervisor connection
- * @buf: a buffer for the result S-Expr
- * @xendConfigVersion: xend configuration file format
- *
- * Parse the one disk in the XML description and add it to the S-Expr in buf
- * This is a temporary interface as the S-Expr interface
- * will be replaced by XML-RPC in the future. However the XML format should
- * stay valid over time.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-static int
-xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
-                        virDomainDiskDefPtr def,
-                        virBufferPtr buf,
-                        int hvm,
-                        int xendConfigVersion,
-                        int isAttach)
-{
-    /* Xend (all versions) put the floppy device config
-     * under the hvm (image (os)) block
-     */
-    if (hvm &&
-        def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
-        if (isAttach) {
-            virXendError(VIR_ERR_INVALID_ARG,
-                     _("Cannot directly attach floppy %s"), def->src);
-            return -1;
-        }
-        return 0;
-    }
-
-    /* Xend <= 3.0.2 doesn't include cdrom config here */
-    if (hvm &&
-        def->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
-        xendConfigVersion == 1) {
-        if (isAttach) {
-            virXendError(VIR_ERR_INVALID_ARG,
-                     _("Cannot directly attach CDROM %s"), def->src);
-            return -1;
-        }
-        return 0;
-    }
-
-    if (!isAttach)
-        virBufferAddLit(buf, "(device ");
-
-    /* Normally disks are in a (device (vbd ...)) block
-     * but blktap disks ended up in a differently named
-     * (device (tap ....)) block.... */
-    if (def->driverName && STREQ(def->driverName, "tap")) {
-        virBufferAddLit(buf, "(tap ");
-    } else if (def->driverName && STREQ(def->driverName, "tap2")) {
-        virBufferAddLit(buf, "(tap2 ");
-    } else {
-        virBufferAddLit(buf, "(vbd ");
-    }
-
-    if (hvm) {
-        /* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */
-        if (xendConfigVersion == 1) {
-            virBufferEscapeSexpr(buf, "(dev 'ioemu:%s')", def->dst);
-        } else {
-            /* But newer does not */
-            virBufferEscapeSexpr(buf, "(dev '%s:", def->dst);
-            virBufferVSprintf(buf, "%s')",
-                              def->device == VIR_DOMAIN_DISK_DEVICE_CDROM ?
-                              "cdrom" : "disk");
-        }
-    } else if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
-        virBufferEscapeSexpr(buf, "(dev '%s:cdrom')", def->dst);
-    } else {
-        virBufferEscapeSexpr(buf, "(dev '%s')", def->dst);
-    }
-
-    if (def->src) {
-        if (def->driverName) {
-            if (STREQ(def->driverName, "tap") ||
-                STREQ(def->driverName, "tap2")) {
-                virBufferEscapeSexpr(buf, "(uname '%s:", def->driverName);
-                virBufferEscapeSexpr(buf, "%s:",
-                                     def->driverType ? def->driverType : "aio");
-                virBufferEscapeSexpr(buf, "%s')", def->src);
-            } else {
-                virBufferEscapeSexpr(buf, "(uname '%s:", def->driverName);
-                virBufferEscapeSexpr(buf, "%s')", def->src);
-            }
-        } else {
-            if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
-                virBufferEscapeSexpr(buf, "(uname 'file:%s')", def->src);
-            } else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) {
-                if (def->src[0] == '/')
-                    virBufferEscapeSexpr(buf, "(uname 'phy:%s')", def->src);
-                else
-                    virBufferEscapeSexpr(buf, "(uname 'phy:/dev/%s')",
-                                         def->src);
-            } else {
-                virXendError(VIR_ERR_CONFIG_UNSUPPORTED,
-                             _("unsupported disk type %s"),
-                             virDomainDiskTypeToString(def->type));
-                return -1;
-            }
-        }
-    }
-
-    if (def->readonly)
-        virBufferAddLit(buf, "(mode 'r')");
-    else if (def->shared)
-        virBufferAddLit(buf, "(mode 'w!')");
-    else
-        virBufferAddLit(buf, "(mode 'w')");
-
-    if (!isAttach)
-        virBufferAddLit(buf, ")");
-
-    virBufferAddLit(buf, ")");
-
-    return 0;
-}
-
-/**
- * xenDaemonFormatSxprNet
- * @conn: pointer to the hypervisor connection
- * @node: node containing the interface description
- * @buf: a buffer for the result S-Expr
- * @xendConfigVersion: xend configuration file format
- *
- * Parse the one interface the XML description and add it to the S-Expr in buf
- * This is a temporary interface as the S-Expr interface
- * will be replaced by XML-RPC in the future. However the XML format should
- * stay valid over time.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-static int
-xenDaemonFormatSxprNet(virConnectPtr conn,
-                       virDomainNetDefPtr def,
-                       virBufferPtr buf,
-                       int hvm,
-                       int xendConfigVersion,
-                       int isAttach)
-{
-    const char *script = DEFAULT_VIF_SCRIPT;
-
-    if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
-        def->type != VIR_DOMAIN_NET_TYPE_NETWORK &&
-        def->type != VIR_DOMAIN_NET_TYPE_ETHERNET) {
-        virXendError(VIR_ERR_INTERNAL_ERROR,
-                     _("unsupported network type %d"), def->type);
-        return -1;
-    }
-
-    if (!isAttach)
-        virBufferAddLit(buf, "(device ");
-
-    virBufferAddLit(buf, "(vif ");
-
-    virBufferVSprintf(buf,
-                      "(mac '%02x:%02x:%02x:%02x:%02x:%02x')",
-                      def->mac[0], def->mac[1], def->mac[2],
-                      def->mac[3], def->mac[4], def->mac[5]);
-
-    switch (def->type) {
-    case VIR_DOMAIN_NET_TYPE_BRIDGE:
-        virBufferEscapeSexpr(buf, "(bridge '%s')", def->data.bridge.brname);
-        if (def->data.bridge.script)
-            script = def->data.bridge.script;
-
-        virBufferEscapeSexpr(buf, "(script '%s')", script);
-        if (def->data.bridge.ipaddr != NULL)
-            virBufferEscapeSexpr(buf, "(ip '%s')", def->data.bridge.ipaddr);
-        break;
-
-    case VIR_DOMAIN_NET_TYPE_NETWORK:
-    {
-        virNetworkPtr network =
-            virNetworkLookupByName(conn, def->data.network.name);
-        char *bridge;
-
-        if (!network) {
-            virXendError(VIR_ERR_NO_NETWORK, "%s",
-                         def->data.network.name);
-            return -1;
-        }
-
-        bridge = virNetworkGetBridgeName(network);
-        virNetworkFree(network);
-        if (!bridge) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         _("network %s is not active"),
-                         def->data.network.name);
-            return -1;
-        }
-        virBufferEscapeSexpr(buf, "(bridge '%s')", bridge);
-        virBufferEscapeSexpr(buf, "(script '%s')", script);
-        VIR_FREE(bridge);
-    }
-    break;
-
-    case VIR_DOMAIN_NET_TYPE_ETHERNET:
-        if (def->data.ethernet.script)
-            virBufferEscapeSexpr(buf, "(script '%s')",
-                                 def->data.ethernet.script);
-        if (def->data.ethernet.ipaddr != NULL)
-            virBufferEscapeSexpr(buf, "(ip '%s')", def->data.ethernet.ipaddr);
-        break;
-
-    case VIR_DOMAIN_NET_TYPE_USER:
-    case VIR_DOMAIN_NET_TYPE_SERVER:
-    case VIR_DOMAIN_NET_TYPE_CLIENT:
-    case VIR_DOMAIN_NET_TYPE_MCAST:
-    case VIR_DOMAIN_NET_TYPE_INTERNAL:
-    case VIR_DOMAIN_NET_TYPE_DIRECT:
-    case VIR_DOMAIN_NET_TYPE_LAST:
-        break;
-    }
-
-    if (def->ifname != NULL &&
-        !STRPREFIX(def->ifname, "vif"))
-        virBufferEscapeSexpr(buf, "(vifname '%s')", def->ifname);
-
-    if (!hvm) {
-        if (def->model != NULL)
-            virBufferEscapeSexpr(buf, "(model '%s')", def->model);
-    }
-    else if (def->model == NULL) {
-        /*
-         * apparently (type ioemu) breaks paravirt drivers on HVM so skip
-         * this from XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU
-         */
-        if (xendConfigVersion <= XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU)
-            virBufferAddLit(buf, "(type ioemu)");
-    }
-    else if (STREQ(def->model, "netfront")) {
-        virBufferAddLit(buf, "(type netfront)");
-    }
-    else {
-        virBufferEscapeSexpr(buf, "(model '%s')", def->model);
-        virBufferAddLit(buf, "(type ioemu)");
-    }
-
-    if (!isAttach)
-        virBufferAddLit(buf, ")");
-
-    virBufferAddLit(buf, ")");
-
-    return 0;
-}
-
-
-static void
-xenDaemonFormatSxprPCI(virDomainHostdevDefPtr def,
-                       virBufferPtr buf)
-{
-    virBufferVSprintf(buf, "(dev (domain 0x%04x)(bus 0x%02x)(slot 0x%02x)(func 0x%x))",
-                      def->source.subsys.u.pci.domain,
-                      def->source.subsys.u.pci.bus,
-                      def->source.subsys.u.pci.slot,
-                      def->source.subsys.u.pci.function);
-}
-
-static int
-xenDaemonFormatSxprOnePCI(virDomainHostdevDefPtr def,
-                          virBufferPtr buf,
-                          int detach)
-{
-    if (def->managed) {
-        virXendError(VIR_ERR_NO_SUPPORT, "%s",
-                     _("managed PCI devices not supported with XenD"));
-        return -1;
-    }
-
-    virBufferAddLit(buf, "(pci ");
-    xenDaemonFormatSxprPCI(def, buf);
-    if (detach)
-        virBufferAddLit(buf, "(state 'Closing')");
-    else
-        virBufferAddLit(buf, "(state 'Initialising')");
-    virBufferAddLit(buf, ")");
-
-    return 0;
-}
-
-static int
-xenDaemonFormatSxprAllPCI(virDomainDefPtr def,
-                          virBufferPtr buf)
-{
-    int hasPCI = 0;
-    int i;
-
-    for (i = 0 ; i < def->nhostdevs ; i++)
-        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
-            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
-            hasPCI = 1;
-
-    if (!hasPCI)
-        return 0;
-
-    /*
-     * With the (domain ...) block we have the following odd setup
-     *
-     * (device
-     *    (pci
-     *       (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
-     *       (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
-     *    )
-     * )
-     *
-     * Normally there is one (device ...) block per device, but in the
-     * weird world of Xen PCI, one (device ...) covers multiple devices.
-     */
-
-    virBufferAddLit(buf, "(device (pci ");
-    for (i = 0 ; i < def->nhostdevs ; i++) {
-        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
-            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
-            if (def->hostdevs[i]->managed) {
-                virXendError(VIR_ERR_NO_SUPPORT, "%s",
-                             _("managed PCI devices not supported with XenD"));
-                return -1;
-            }
-
-            xenDaemonFormatSxprPCI(def->hostdevs[i], buf);
-        }
-    }
-    virBufferAddLit(buf, "))");
-
-    return 0;
-}
-
-int
-xenDaemonFormatSxprSound(virDomainDefPtr def,
-                         virBufferPtr buf)
-{
-    const char *str;
-    int i;
-
-    for (i = 0 ; i < def->nsounds ; i++) {
-        if (!(str = virDomainSoundModelTypeToString(def->sounds[i]->model))) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         _("unexpected sound model %d"),
-                         def->sounds[i]->model);
-            return -1;
-        }
-        if (i)
-            virBufferAddChar(buf, ',');
-        virBufferEscapeSexpr(buf, "%s", str);
-    }
-
-    if (virBufferError(buf)) {
-        virReportOOMError();
-        return -1;
-    }
-
-    return 0;
-}
-
-
-static int
-xenDaemonFormatSxprInput(virDomainInputDefPtr input,
-                         virBufferPtr buf)
-{
-    if (input->bus != VIR_DOMAIN_INPUT_BUS_USB)
-        return 0;
-
-    if (input->type != VIR_DOMAIN_INPUT_TYPE_MOUSE &&
-        input->type != VIR_DOMAIN_INPUT_TYPE_TABLET) {
-        virXendError(VIR_ERR_INTERNAL_ERROR,
-                     _("unexpected input type %d"), input->type);
-        return -1;
-    }
-
-    virBufferVSprintf(buf, "(usbdevice %s)",
-                      input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ?
-                      "mouse" : "tablet");
-
-    return 0;
-}
-
-
-/* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
-   either 32, or 64 on a platform where long is big enough.  */
-verify(MAX_VIRT_CPUS <= sizeof(1UL) * CHAR_BIT);
-
-/**
- * xenDaemonFormatSxpr:
- * @conn: pointer to the hypervisor connection
- * @def: domain config definition
- * @xendConfigVersion: xend configuration file format
- *
- * Generate an SEXPR representing the domain configuration.
- *
- * Returns the 0 terminated S-Expr string or NULL in case of error.
- *         the caller must free() the returned value.
- */
-char *
-xenDaemonFormatSxpr(virConnectPtr conn,
-                    virDomainDefPtr def,
-                    int xendConfigVersion)
-{
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
-    const char *tmp;
-    char *bufout;
-    int hvm = 0, i;
-
-    DEBUG0("Formatting domain sexpr");
-
-    virBufferAddLit(&buf, "(vm ");
-    virBufferEscapeSexpr(&buf, "(name '%s')", def->name);
-    virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)",
-                      VIR_DIV_UP(def->mem.cur_balloon, 1024),
-                      VIR_DIV_UP(def->mem.max_balloon, 1024));
-    virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus);
-    /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
-       either 32, or 64 on a platform where long is big enough.  */
-    if (def->vcpus < def->maxvcpus)
-        virBufferVSprintf(&buf, "(vcpu_avail %lu)", (1UL << def->vcpus) - 1);
-
-    if (def->cpumask) {
-        char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen);
-        if (ranges == NULL)
-            goto error;
-        virBufferEscapeSexpr(&buf, "(cpus '%s')", ranges);
-        VIR_FREE(ranges);
-    }
-
-    virUUIDFormat(def->uuid, uuidstr);
-    virBufferVSprintf(&buf, "(uuid '%s')", uuidstr);
-
-    if (def->description)
-        virBufferEscapeSexpr(&buf, "(description '%s')", def->description);
-
-    if (def->os.bootloader) {
-        if (def->os.bootloader[0])
-            virBufferEscapeSexpr(&buf, "(bootloader '%s')", def->os.bootloader);
-        else
-            virBufferAddLit(&buf, "(bootloader)");
-
-        if (def->os.bootloaderArgs)
-            virBufferEscapeSexpr(&buf, "(bootloader_args '%s')", def->os.bootloaderArgs);
-    }
-
-    if (!(tmp = virDomainLifecycleTypeToString(def->onPoweroff))) {
-        virXendError(VIR_ERR_INTERNAL_ERROR,
-                     _("unexpected lifecycle value %d"), def->onPoweroff);
-        goto error;
-    }
-    virBufferVSprintf(&buf, "(on_poweroff '%s')", tmp);
-
-    if (!(tmp = virDomainLifecycleTypeToString(def->onReboot))) {
-        virXendError(VIR_ERR_INTERNAL_ERROR,
-                     _("unexpected lifecycle value %d"), def->onReboot);
-        goto error;
-    }
-    virBufferVSprintf(&buf, "(on_reboot '%s')", tmp);
-
-    if (!(tmp = virDomainLifecycleCrashTypeToString(def->onCrash))) {
-        virXendError(VIR_ERR_INTERNAL_ERROR,
-                     _("unexpected lifecycle value %d"), def->onCrash);
-        goto error;
-    }
-    virBufferVSprintf(&buf, "(on_crash '%s')", tmp);
-
-    /* Set localtime here for current XenD (both PV & HVM) */
-    if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) {
-        if (def->clock.data.timezone) {
-            virXendError(VIR_ERR_CONFIG_UNSUPPORTED,
-                         "%s", _("configurable timezones are not supported"));
-            goto error;
-        }
-
-        virBufferAddLit(&buf, "(localtime 1)");
-    } else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) {
-        virXendError(VIR_ERR_CONFIG_UNSUPPORTED,
-                     _("unsupported clock offset '%s'"),
-                     virDomainClockOffsetTypeToString(def->clock.offset));
-        goto error;
-    }
-
-    if (!def->os.bootloader) {
-        if (STREQ(def->os.type, "hvm"))
-            hvm = 1;
-
-        if (hvm)
-            virBufferAddLit(&buf, "(image (hvm ");
-        else
-            virBufferAddLit(&buf, "(image (linux ");
-
-        if (hvm &&
-            def->os.loader == NULL) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         "%s",_("no HVM domain loader"));
-            goto error;
-        }
-
-        if (def->os.kernel)
-            virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.kernel);
-        if (def->os.initrd)
-            virBufferEscapeSexpr(&buf, "(ramdisk '%s')", def->os.initrd);
-        if (def->os.root)
-            virBufferEscapeSexpr(&buf, "(root '%s')", def->os.root);
-        if (def->os.cmdline)
-            virBufferEscapeSexpr(&buf, "(args '%s')", def->os.cmdline);
-
-        if (hvm) {
-            char bootorder[VIR_DOMAIN_BOOT_LAST+1];
-            if (def->os.kernel)
-                virBufferEscapeSexpr(&buf, "(loader '%s')", def->os.loader);
-            else
-                virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.loader);
-
-            virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus);
-            if (def->vcpus < def->maxvcpus)
-                virBufferVSprintf(&buf, "(vcpu_avail %lu)",
-                                  (1UL << def->vcpus) - 1);
-
-            for (i = 0 ; i < def->os.nBootDevs ; i++) {
-                switch (def->os.bootDevs[i]) {
-                case VIR_DOMAIN_BOOT_FLOPPY:
-                    bootorder[i] = 'a';
-                    break;
-                default:
-                case VIR_DOMAIN_BOOT_DISK:
-                    bootorder[i] = 'c';
-                    break;
-                case VIR_DOMAIN_BOOT_CDROM:
-                    bootorder[i] = 'd';
-                    break;
-                case VIR_DOMAIN_BOOT_NET:
-                    bootorder[i] = 'n';
-                    break;
-                }
-            }
-            if (def->os.nBootDevs == 0) {
-                bootorder[0] = 'c';
-                bootorder[1] = '\0';
-            } else {
-                bootorder[def->os.nBootDevs] = '\0';
-            }
-            virBufferVSprintf(&buf, "(boot %s)", bootorder);
-
-            /* some disk devices are defined here */
-            for (i = 0 ; i < def->ndisks ; i++) {
-                switch (def->disks[i]->device) {
-                case VIR_DOMAIN_DISK_DEVICE_CDROM:
-                    /* Only xend <= 3.0.2 wants cdrom config here */
-                    if (xendConfigVersion != 1)
-                        break;
-                    if (!STREQ(def->disks[i]->dst, "hdc") ||
-                        def->disks[i]->src == NULL)
-                        break;
-
-                    virBufferEscapeSexpr(&buf, "(cdrom '%s')",
-                                         def->disks[i]->src);
-                    break;
-
-                case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
-                    /* all xend versions define floppies here */
-                    virBufferEscapeSexpr(&buf, "(%s ", def->disks[i]->dst);
-                    virBufferEscapeSexpr(&buf, "'%s')", def->disks[i]->src);
-                    break;
-
-                default:
-                    break;
-                }
-            }
-
-            if (def->features & (1 << VIR_DOMAIN_FEATURE_ACPI))
-                virBufferAddLit(&buf, "(acpi 1)");
-            if (def->features & (1 << VIR_DOMAIN_FEATURE_APIC))
-                virBufferAddLit(&buf, "(apic 1)");
-            if (def->features & (1 << VIR_DOMAIN_FEATURE_PAE))
-                virBufferAddLit(&buf, "(pae 1)");
-            if (def->features & (1 << VIR_DOMAIN_FEATURE_HAP))
-                virBufferAddLit(&buf, "(hap 1)");
-
-            virBufferAddLit(&buf, "(usb 1)");
-
-            for (i = 0 ; i < def->ninputs ; i++)
-                if (xenDaemonFormatSxprInput(def->inputs[i], &buf) < 0)
-                    goto error;
-
-            if (def->parallels) {
-                virBufferAddLit(&buf, "(parallel ");
-                if (xenDaemonFormatSxprChr(def->parallels[0], &buf) < 0)
-                    goto error;
-                virBufferAddLit(&buf, ")");
-            } else {
-                virBufferAddLit(&buf, "(parallel none)");
-            }
-            if (def->serials) {
-                virBufferAddLit(&buf, "(serial ");
-                if (xenDaemonFormatSxprChr(def->serials[0], &buf) < 0)
-                    goto error;
-                virBufferAddLit(&buf, ")");
-            } else {
-                virBufferAddLit(&buf, "(serial none)");
-            }
-
-            /* Set localtime here to keep old XenD happy for HVM */
-            if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME)
-                virBufferAddLit(&buf, "(localtime 1)");
-
-            if (def->sounds) {
-                virBufferAddLit(&buf, "(soundhw '");
-                if (xenDaemonFormatSxprSound(def, &buf) < 0)
-                    goto error;
-                virBufferAddLit(&buf, "')");
-            }
-        }
-
-        /* get the device emulation model */
-        if (def->emulator && (hvm || xendConfigVersion >= 3))
-            virBufferEscapeSexpr(&buf, "(device_model '%s')", def->emulator);
-
-
-        /* PV graphics for xen <= 3.0.4, or HVM graphics for xen <= 3.1.0 */
-        if ((!hvm && xendConfigVersion < XEND_CONFIG_MIN_VERS_PVFB_NEWCONF) ||
-            (hvm && xendConfigVersion < 4)) {
-            if ((def->ngraphics == 1) &&
-                xenDaemonFormatSxprGraphicsOld(def->graphics[0],
-                                               &buf, xendConfigVersion) < 0)
-                goto error;
-        }
-
-        virBufferAddLit(&buf, "))");
-    }
-
-    for (i = 0 ; i < def->ndisks ; i++)
-        if (xenDaemonFormatSxprDisk(conn, def->disks[i],
-                                    &buf, hvm, xendConfigVersion, 0) < 0)
-            goto error;
-
-    for (i = 0 ; i < def->nnets ; i++)
-        if (xenDaemonFormatSxprNet(conn, def->nets[i],
-                                   &buf, hvm, xendConfigVersion, 0) < 0)
-            goto error;
-
-    if (xenDaemonFormatSxprAllPCI(def, &buf) < 0)
-        goto error;
-
-    /* New style PV graphics config xen >= 3.0.4,
-     * or HVM graphics config xen >= 3.0.5 */
-    if ((xendConfigVersion >= XEND_CONFIG_MIN_VERS_PVFB_NEWCONF && !hvm) ||
-        (xendConfigVersion >= 4 && hvm)) {
-        if ((def->ngraphics == 1) &&
-            xenDaemonFormatSxprGraphicsNew(def->graphics[0], &buf) < 0)
-            goto error;
-    }
-
-    virBufferAddLit(&buf, ")"); /* closes (vm */
-
-    if (virBufferError(&buf)) {
-        virReportOOMError();
-        goto error;
-    }
-
-    bufout = virBufferContentAndReset(&buf);
-    DEBUG("Formatted sexpr: \n%s", bufout);
-    return bufout;
-
-error:
-    virBufferFreeAndReset(&buf);
-    return NULL;
-}
-
-
 /**
  * virDomainXMLDevID:
  * @domain: pointer to domain object
diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h
index 8603a08..c90c572 100644
--- a/src/xen/xend_internal.h
+++ b/src/xen/xend_internal.h
@@ -91,18 +91,6 @@ xenDaemonDomainFetch(virConnectPtr xend,
                      const char *cpus);
 
 
-int
-xenDaemonFormatSxprChr(virDomainChrDefPtr def,
-                       virBufferPtr buf);
-int
-xenDaemonFormatSxprSound(virDomainDefPtr def,
-                         virBufferPtr buf);
-
-char *
-xenDaemonFormatSxpr(virConnectPtr conn,
-                    virDomainDefPtr def,
-                    int xendConfigVersion);
-
   int is_sound_model_valid(const char *model);
   int is_sound_model_conflict(const char *model, const char *soundstr);
 
diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c
index edd0fb4..97de017 100644
--- a/src/xenxs/xen_sxpr.c
+++ b/src/xenxs/xen_sxpr.c
@@ -1348,4 +1348,852 @@ xenDaemonParseSxprString(const char *sexpr,
     sexpr_free(root);
 
     return def;
-}
\ No newline at end of file
+}
+
+/************************************************************************
+ *                                                                      *
+ * Converter functions to go from the XML tree to an S-Expr for Xen     *
+ *                                                                      *
+ ************************************************************************/
+
+
+/**
+ * virtDomainParseXMLGraphicsDescVFB:
+ * @conn: pointer to the hypervisor connection
+ * @node: node containing graphics description
+ * @buf: a buffer for the result S-Expr
+ *
+ * Parse the graphics part of the XML description and add it to the S-Expr
+ * in buf.  This is a temporary interface as the S-Expr interface will be
+ * replaced by XML-RPC in the future. However the XML format should stay
+ * valid over time.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+static int
+xenDaemonFormatSxprGraphicsNew(virDomainGraphicsDefPtr def,
+                               virBufferPtr buf)
+{
+    if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
+        def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     _("unexpected graphics type %d"),
+                     def->type);
+        return -1;
+    }
+
+    virBufferAddLit(buf, "(device (vkbd))");
+    virBufferAddLit(buf, "(device (vfb ");
+
+    if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+        virBufferAddLit(buf, "(type sdl)");
+        if (def->data.sdl.display)
+            virBufferVSprintf(buf, "(display '%s')", def->data.sdl.display);
+        if (def->data.sdl.xauth)
+            virBufferVSprintf(buf, "(xauthority '%s')", def->data.sdl.xauth);
+    } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+        virBufferAddLit(buf, "(type vnc)");
+        if (def->data.vnc.autoport) {
+            virBufferAddLit(buf, "(vncunused 1)");
+        } else {
+            virBufferAddLit(buf, "(vncunused 0)");
+            virBufferVSprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900);
+        }
+
+        if (def->data.vnc.listenAddr)
+            virBufferVSprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr);
+        if (def->data.vnc.auth.passwd)
+            virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.auth.passwd);
+        if (def->data.vnc.keymap)
+            virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
+    }
+
+    virBufferAddLit(buf, "))");
+
+    return 0;
+}
+
+
+static int
+xenDaemonFormatSxprGraphicsOld(virDomainGraphicsDefPtr def,
+                               virBufferPtr buf,
+                               int xendConfigVersion)
+{
+    if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
+        def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     _("unexpected graphics type %d"),
+                     def->type);
+        return -1;
+    }
+
+    if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+        virBufferAddLit(buf, "(sdl 1)");
+        if (def->data.sdl.display)
+            virBufferVSprintf(buf, "(display '%s')", def->data.sdl.display);
+        if (def->data.sdl.xauth)
+            virBufferVSprintf(buf, "(xauthority '%s')", def->data.sdl.xauth);
+    } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+        virBufferAddLit(buf, "(vnc 1)");
+        if (xendConfigVersion >= 2) {
+            if (def->data.vnc.autoport) {
+                virBufferAddLit(buf, "(vncunused 1)");
+            } else {
+                virBufferAddLit(buf, "(vncunused 0)");
+                virBufferVSprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900);
+            }
+
+            if (def->data.vnc.listenAddr)
+                virBufferVSprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr);
+            if (def->data.vnc.auth.passwd)
+                virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.auth.passwd);
+            if (def->data.vnc.keymap)
+                virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
+
+        }
+    }
+
+    return 0;
+}
+
+int
+xenDaemonFormatSxprChr(virDomainChrDefPtr def,
+                       virBufferPtr buf)
+{
+    const char *type = virDomainChrTypeToString(def->source.type);
+
+    if (!type) {
+        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("unexpected chr device type"));
+        return -1;
+    }
+
+    switch (def->source.type) {
+    case VIR_DOMAIN_CHR_TYPE_NULL:
+    case VIR_DOMAIN_CHR_TYPE_STDIO:
+    case VIR_DOMAIN_CHR_TYPE_VC:
+    case VIR_DOMAIN_CHR_TYPE_PTY:
+        virBufferVSprintf(buf, "%s", type);
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_FILE:
+    case VIR_DOMAIN_CHR_TYPE_PIPE:
+        virBufferVSprintf(buf, "%s:", type);
+        virBufferEscapeSexpr(buf, "%s", def->source.data.file.path);
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_DEV:
+        virBufferEscapeSexpr(buf, "%s", def->source.data.file.path);
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_TCP:
+        virBufferVSprintf(buf, "%s:%s:%s%s",
+                          (def->source.data.tcp.protocol
+                           == VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW ?
+                           "tcp" : "telnet"),
+                          (def->source.data.tcp.host ?
+                           def->source.data.tcp.host : ""),
+                          (def->source.data.tcp.service ?
+                           def->source.data.tcp.service : ""),
+                          (def->source.data.tcp.listen ?
+                           ",server,nowait" : ""));
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_UDP:
+        virBufferVSprintf(buf, "%s:%s:%s %s:%s", type,
+                          (def->source.data.udp.connectHost ?
+                           def->source.data.udp.connectHost : ""),
+                          (def->source.data.udp.connectService ?
+                           def->source.data.udp.connectService : ""),
+                          (def->source.data.udp.bindHost ?
+                           def->source.data.udp.bindHost : ""),
+                          (def->source.data.udp.bindService ?
+                           def->source.data.udp.bindService : ""));
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_UNIX:
+        virBufferVSprintf(buf, "%s:", type);
+        virBufferEscapeSexpr(buf, "%s", def->source.data.nix.path);
+        if (def->source.data.nix.listen)
+            virBufferAddLit(buf, ",server,nowait");
+        break;
+    }
+
+    if (virBufferError(buf)) {
+        virReportOOMError();
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/**
+ * virDomainParseXMLDiskDesc:
+ * @node: node containing disk description
+ * @conn: pointer to the hypervisor connection
+ * @buf: a buffer for the result S-Expr
+ * @xendConfigVersion: xend configuration file format
+ *
+ * Parse the one disk in the XML description and add it to the S-Expr in buf
+ * This is a temporary interface as the S-Expr interface
+ * will be replaced by XML-RPC in the future. However the XML format should
+ * stay valid over time.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
+                        virDomainDiskDefPtr def,
+                        virBufferPtr buf,
+                        int hvm,
+                        int xendConfigVersion,
+                        int isAttach)
+{
+    /* Xend (all versions) put the floppy device config
+     * under the hvm (image (os)) block
+     */
+    if (hvm &&
+        def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
+        if (isAttach) {
+            XENXS_ERROR(VIR_ERR_INVALID_ARG,
+                     _("Cannot directly attach floppy %s"), def->src);
+            return -1;
+        }
+        return 0;
+    }
+
+    /* Xend <= 3.0.2 doesn't include cdrom config here */
+    if (hvm &&
+        def->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
+        xendConfigVersion == 1) {
+        if (isAttach) {
+            XENXS_ERROR(VIR_ERR_INVALID_ARG,
+                     _("Cannot directly attach CDROM %s"), def->src);
+            return -1;
+        }
+        return 0;
+    }
+
+    if (!isAttach)
+        virBufferAddLit(buf, "(device ");
+
+    /* Normally disks are in a (device (vbd ...)) block
+     * but blktap disks ended up in a differently named
+     * (device (tap ....)) block.... */
+    if (def->driverName && STREQ(def->driverName, "tap")) {
+        virBufferAddLit(buf, "(tap ");
+    } else if (def->driverName && STREQ(def->driverName, "tap2")) {
+        virBufferAddLit(buf, "(tap2 ");
+    } else {
+        virBufferAddLit(buf, "(vbd ");
+    }
+
+    if (hvm) {
+        /* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */
+        if (xendConfigVersion == 1) {
+            virBufferEscapeSexpr(buf, "(dev 'ioemu:%s')", def->dst);
+        } else {
+            /* But newer does not */
+            virBufferEscapeSexpr(buf, "(dev '%s:", def->dst);
+            virBufferVSprintf(buf, "%s')",
+                              def->device == VIR_DOMAIN_DISK_DEVICE_CDROM ?
+                              "cdrom" : "disk");
+        }
+    } else if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
+        virBufferEscapeSexpr(buf, "(dev '%s:cdrom')", def->dst);
+    } else {
+        virBufferEscapeSexpr(buf, "(dev '%s')", def->dst);
+    }
+
+    if (def->src) {
+        if (def->driverName) {
+            if (STREQ(def->driverName, "tap") ||
+                STREQ(def->driverName, "tap2")) {
+                virBufferEscapeSexpr(buf, "(uname '%s:", def->driverName);
+                virBufferEscapeSexpr(buf, "%s:",
+                                     def->driverType ? def->driverType : "aio");
+                virBufferEscapeSexpr(buf, "%s')", def->src);
+            } else {
+                virBufferEscapeSexpr(buf, "(uname '%s:", def->driverName);
+                virBufferEscapeSexpr(buf, "%s')", def->src);
+            }
+        } else {
+            if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
+                virBufferEscapeSexpr(buf, "(uname 'file:%s')", def->src);
+            } else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) {
+                if (def->src[0] == '/')
+                    virBufferEscapeSexpr(buf, "(uname 'phy:%s')", def->src);
+                else
+                    virBufferEscapeSexpr(buf, "(uname 'phy:/dev/%s')",
+                                         def->src);
+            } else {
+                XENXS_ERROR(VIR_ERR_CONFIG_UNSUPPORTED,
+                             _("unsupported disk type %s"),
+                             virDomainDiskTypeToString(def->type));
+                return -1;
+            }
+        }
+    }
+
+    if (def->readonly)
+        virBufferAddLit(buf, "(mode 'r')");
+    else if (def->shared)
+        virBufferAddLit(buf, "(mode 'w!')");
+    else
+        virBufferAddLit(buf, "(mode 'w')");
+
+    if (!isAttach)
+        virBufferAddLit(buf, ")");
+
+    virBufferAddLit(buf, ")");
+
+    return 0;
+}
+
+/**
+ * xenDaemonFormatSxprNet
+ * @conn: pointer to the hypervisor connection
+ * @node: node containing the interface description
+ * @buf: a buffer for the result S-Expr
+ * @xendConfigVersion: xend configuration file format
+ *
+ * Parse the one interface the XML description and add it to the S-Expr in buf
+ * This is a temporary interface as the S-Expr interface
+ * will be replaced by XML-RPC in the future. However the XML format should
+ * stay valid over time.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenDaemonFormatSxprNet(virConnectPtr conn,
+                       virDomainNetDefPtr def,
+                       virBufferPtr buf,
+                       int hvm,
+                       int xendConfigVersion,
+                       int isAttach)
+{
+    const char *script = DEFAULT_VIF_SCRIPT;
+
+    if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
+        def->type != VIR_DOMAIN_NET_TYPE_NETWORK &&
+        def->type != VIR_DOMAIN_NET_TYPE_ETHERNET) {
+        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     _("unsupported network type %d"), def->type);
+        return -1;
+    }
+
+    if (!isAttach)
+        virBufferAddLit(buf, "(device ");
+
+    virBufferAddLit(buf, "(vif ");
+
+    virBufferVSprintf(buf,
+                      "(mac '%02x:%02x:%02x:%02x:%02x:%02x')",
+                      def->mac[0], def->mac[1], def->mac[2],
+                      def->mac[3], def->mac[4], def->mac[5]);
+
+    switch (def->type) {
+    case VIR_DOMAIN_NET_TYPE_BRIDGE:
+        virBufferEscapeSexpr(buf, "(bridge '%s')", def->data.bridge.brname);
+        if (def->data.bridge.script)
+            script = def->data.bridge.script;
+
+        virBufferEscapeSexpr(buf, "(script '%s')", script);
+        if (def->data.bridge.ipaddr != NULL)
+            virBufferEscapeSexpr(buf, "(ip '%s')", def->data.bridge.ipaddr);
+        break;
+
+    case VIR_DOMAIN_NET_TYPE_NETWORK:
+    {
+        virNetworkPtr network =
+            virNetworkLookupByName(conn, def->data.network.name);
+        char *bridge;
+
+        if (!network) {
+            XENXS_ERROR(VIR_ERR_NO_NETWORK, "%s",
+                         def->data.network.name);
+            return -1;
+        }
+
+        bridge = virNetworkGetBridgeName(network);
+        virNetworkFree(network);
+        if (!bridge) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         _("network %s is not active"),
+                         def->data.network.name);
+            return -1;
+        }
+        virBufferEscapeSexpr(buf, "(bridge '%s')", bridge);
+        virBufferEscapeSexpr(buf, "(script '%s')", script);
+        VIR_FREE(bridge);
+    }
+    break;
+
+    case VIR_DOMAIN_NET_TYPE_ETHERNET:
+        if (def->data.ethernet.script)
+            virBufferEscapeSexpr(buf, "(script '%s')",
+                                 def->data.ethernet.script);
+        if (def->data.ethernet.ipaddr != NULL)
+            virBufferEscapeSexpr(buf, "(ip '%s')", def->data.ethernet.ipaddr);
+        break;
+
+    case VIR_DOMAIN_NET_TYPE_USER:
+    case VIR_DOMAIN_NET_TYPE_SERVER:
+    case VIR_DOMAIN_NET_TYPE_CLIENT:
+    case VIR_DOMAIN_NET_TYPE_MCAST:
+    case VIR_DOMAIN_NET_TYPE_INTERNAL:
+    case VIR_DOMAIN_NET_TYPE_DIRECT:
+    case VIR_DOMAIN_NET_TYPE_LAST:
+        break;
+    }
+
+    if (def->ifname != NULL &&
+        !STRPREFIX(def->ifname, "vif"))
+        virBufferEscapeSexpr(buf, "(vifname '%s')", def->ifname);
+
+    if (!hvm) {
+        if (def->model != NULL)
+            virBufferEscapeSexpr(buf, "(model '%s')", def->model);
+    }
+    else if (def->model == NULL) {
+        /*
+         * apparently (type ioemu) breaks paravirt drivers on HVM so skip
+         * this from XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU
+         */
+        if (xendConfigVersion <= XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU)
+            virBufferAddLit(buf, "(type ioemu)");
+    }
+    else if (STREQ(def->model, "netfront")) {
+        virBufferAddLit(buf, "(type netfront)");
+    }
+    else {
+        virBufferEscapeSexpr(buf, "(model '%s')", def->model);
+        virBufferAddLit(buf, "(type ioemu)");
+    }
+
+    if (!isAttach)
+        virBufferAddLit(buf, ")");
+
+    virBufferAddLit(buf, ")");
+
+    return 0;
+}
+
+
+static void
+xenDaemonFormatSxprPCI(virDomainHostdevDefPtr def,
+                       virBufferPtr buf)
+{
+    virBufferVSprintf(buf, "(dev (domain 0x%04x)(bus 0x%02x)(slot 0x%02x)(func 0x%x))",
+                      def->source.subsys.u.pci.domain,
+                      def->source.subsys.u.pci.bus,
+                      def->source.subsys.u.pci.slot,
+                      def->source.subsys.u.pci.function);
+}
+
+int
+xenDaemonFormatSxprOnePCI(virDomainHostdevDefPtr def,
+                          virBufferPtr buf,
+                          int detach)
+{
+    if (def->managed) {
+        XENXS_ERROR(VIR_ERR_NO_SUPPORT, "%s",
+                     _("managed PCI devices not supported with XenD"));
+        return -1;
+    }
+
+    virBufferAddLit(buf, "(pci ");
+    xenDaemonFormatSxprPCI(def, buf);
+    if (detach)
+        virBufferAddLit(buf, "(state 'Closing')");
+    else
+        virBufferAddLit(buf, "(state 'Initialising')");
+    virBufferAddLit(buf, ")");
+
+    return 0;
+}
+
+static int
+xenDaemonFormatSxprAllPCI(virDomainDefPtr def,
+                          virBufferPtr buf)
+{
+    int hasPCI = 0;
+    int i;
+
+    for (i = 0 ; i < def->nhostdevs ; i++)
+        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+            hasPCI = 1;
+
+    if (!hasPCI)
+        return 0;
+
+    /*
+     * With the (domain ...) block we have the following odd setup
+     *
+     * (device
+     *    (pci
+     *       (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
+     *       (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
+     *    )
+     * )
+     *
+     * Normally there is one (device ...) block per device, but in the
+     * weird world of Xen PCI, one (device ...) covers multiple devices.
+     */
+
+    virBufferAddLit(buf, "(device (pci ");
+    for (i = 0 ; i < def->nhostdevs ; i++) {
+        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+            if (def->hostdevs[i]->managed) {
+                XENXS_ERROR(VIR_ERR_NO_SUPPORT, "%s",
+                             _("managed PCI devices not supported with XenD"));
+                return -1;
+            }
+
+            xenDaemonFormatSxprPCI(def->hostdevs[i], buf);
+        }
+    }
+    virBufferAddLit(buf, "))");
+
+    return 0;
+}
+
+int
+xenDaemonFormatSxprSound(virDomainDefPtr def,
+                         virBufferPtr buf)
+{
+    const char *str;
+    int i;
+
+    for (i = 0 ; i < def->nsounds ; i++) {
+        if (!(str = virDomainSoundModelTypeToString(def->sounds[i]->model))) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         _("unexpected sound model %d"),
+                         def->sounds[i]->model);
+            return -1;
+        }
+        if (i)
+            virBufferAddChar(buf, ',');
+        virBufferEscapeSexpr(buf, "%s", str);
+    }
+
+    if (virBufferError(buf)) {
+        virReportOOMError();
+        return -1;
+    }
+
+    return 0;
+}
+
+
+static int
+xenDaemonFormatSxprInput(virDomainInputDefPtr input,
+                         virBufferPtr buf)
+{
+    if (input->bus != VIR_DOMAIN_INPUT_BUS_USB)
+        return 0;
+
+    if (input->type != VIR_DOMAIN_INPUT_TYPE_MOUSE &&
+        input->type != VIR_DOMAIN_INPUT_TYPE_TABLET) {
+        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     _("unexpected input type %d"), input->type);
+        return -1;
+    }
+
+    virBufferVSprintf(buf, "(usbdevice %s)",
+                      input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ?
+                      "mouse" : "tablet");
+
+    return 0;
+}
+
+
+/* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
+   either 32, or 64 on a platform where long is big enough.  */
+verify(MAX_VIRT_CPUS <= sizeof(1UL) * CHAR_BIT);
+
+/**
+ * xenDaemonFormatSxpr:
+ * @conn: pointer to the hypervisor connection
+ * @def: domain config definition
+ * @xendConfigVersion: xend configuration file format
+ *
+ * Generate an SEXPR representing the domain configuration.
+ *
+ * Returns the 0 terminated S-Expr string or NULL in case of error.
+ *         the caller must free() the returned value.
+ */
+char *
+xenDaemonFormatSxpr(virConnectPtr conn,
+                    virDomainDefPtr def,
+                    int xendConfigVersion)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+    const char *tmp;
+    char *bufout;
+    int hvm = 0, i;
+
+    DEBUG0("Formatting domain sexpr");
+
+    virBufferAddLit(&buf, "(vm ");
+    virBufferEscapeSexpr(&buf, "(name '%s')", def->name);
+    virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)",
+                      VIR_DIV_UP(def->mem.cur_balloon, 1024),
+                      VIR_DIV_UP(def->mem.max_balloon, 1024));
+    virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus);
+    /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
+       either 32, or 64 on a platform where long is big enough.  */
+    if (def->vcpus < def->maxvcpus)
+        virBufferVSprintf(&buf, "(vcpu_avail %lu)", (1UL << def->vcpus) - 1);
+
+    if (def->cpumask) {
+        char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen);
+        if (ranges == NULL)
+            goto error;
+        virBufferEscapeSexpr(&buf, "(cpus '%s')", ranges);
+        VIR_FREE(ranges);
+    }
+
+    virUUIDFormat(def->uuid, uuidstr);
+    virBufferVSprintf(&buf, "(uuid '%s')", uuidstr);
+
+    if (def->description)
+        virBufferEscapeSexpr(&buf, "(description '%s')", def->description);
+
+    if (def->os.bootloader) {
+        if (def->os.bootloader[0])
+            virBufferEscapeSexpr(&buf, "(bootloader '%s')", def->os.bootloader);
+        else
+            virBufferAddLit(&buf, "(bootloader)");
+
+        if (def->os.bootloaderArgs)
+            virBufferEscapeSexpr(&buf, "(bootloader_args '%s')", def->os.bootloaderArgs);
+    }
+
+    if (!(tmp = virDomainLifecycleTypeToString(def->onPoweroff))) {
+        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     _("unexpected lifecycle value %d"), def->onPoweroff);
+        goto error;
+    }
+    virBufferVSprintf(&buf, "(on_poweroff '%s')", tmp);
+
+    if (!(tmp = virDomainLifecycleTypeToString(def->onReboot))) {
+        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     _("unexpected lifecycle value %d"), def->onReboot);
+        goto error;
+    }
+    virBufferVSprintf(&buf, "(on_reboot '%s')", tmp);
+
+    if (!(tmp = virDomainLifecycleCrashTypeToString(def->onCrash))) {
+        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     _("unexpected lifecycle value %d"), def->onCrash);
+        goto error;
+    }
+    virBufferVSprintf(&buf, "(on_crash '%s')", tmp);
+
+    /* Set localtime here for current XenD (both PV & HVM) */
+    if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) {
+        if (def->clock.data.timezone) {
+            XENXS_ERROR(VIR_ERR_CONFIG_UNSUPPORTED,
+                         "%s", _("configurable timezones are not supported"));
+            goto error;
+        }
+
+        virBufferAddLit(&buf, "(localtime 1)");
+    } else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) {
+        XENXS_ERROR(VIR_ERR_CONFIG_UNSUPPORTED,
+                     _("unsupported clock offset '%s'"),
+                     virDomainClockOffsetTypeToString(def->clock.offset));
+        goto error;
+    }
+
+    if (!def->os.bootloader) {
+        if (STREQ(def->os.type, "hvm"))
+            hvm = 1;
+
+        if (hvm)
+            virBufferAddLit(&buf, "(image (hvm ");
+        else
+            virBufferAddLit(&buf, "(image (linux ");
+
+        if (hvm &&
+            def->os.loader == NULL) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         "%s",_("no HVM domain loader"));
+            goto error;
+        }
+
+        if (def->os.kernel)
+            virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.kernel);
+        if (def->os.initrd)
+            virBufferEscapeSexpr(&buf, "(ramdisk '%s')", def->os.initrd);
+        if (def->os.root)
+            virBufferEscapeSexpr(&buf, "(root '%s')", def->os.root);
+        if (def->os.cmdline)
+            virBufferEscapeSexpr(&buf, "(args '%s')", def->os.cmdline);
+
+        if (hvm) {
+            char bootorder[VIR_DOMAIN_BOOT_LAST+1];
+            if (def->os.kernel)
+                virBufferEscapeSexpr(&buf, "(loader '%s')", def->os.loader);
+            else
+                virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.loader);
+
+            virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus);
+            if (def->vcpus < def->maxvcpus)
+                virBufferVSprintf(&buf, "(vcpu_avail %lu)",
+                                  (1UL << def->vcpus) - 1);
+
+            for (i = 0 ; i < def->os.nBootDevs ; i++) {
+                switch (def->os.bootDevs[i]) {
+                case VIR_DOMAIN_BOOT_FLOPPY:
+                    bootorder[i] = 'a';
+                    break;
+                default:
+                case VIR_DOMAIN_BOOT_DISK:
+                    bootorder[i] = 'c';
+                    break;
+                case VIR_DOMAIN_BOOT_CDROM:
+                    bootorder[i] = 'd';
+                    break;
+                case VIR_DOMAIN_BOOT_NET:
+                    bootorder[i] = 'n';
+                    break;
+                }
+            }
+            if (def->os.nBootDevs == 0) {
+                bootorder[0] = 'c';
+                bootorder[1] = '\0';
+            } else {
+                bootorder[def->os.nBootDevs] = '\0';
+            }
+            virBufferVSprintf(&buf, "(boot %s)", bootorder);
+
+            /* some disk devices are defined here */
+            for (i = 0 ; i < def->ndisks ; i++) {
+                switch (def->disks[i]->device) {
+                case VIR_DOMAIN_DISK_DEVICE_CDROM:
+                    /* Only xend <= 3.0.2 wants cdrom config here */
+                    if (xendConfigVersion != 1)
+                        break;
+                    if (!STREQ(def->disks[i]->dst, "hdc") ||
+                        def->disks[i]->src == NULL)
+                        break;
+
+                    virBufferEscapeSexpr(&buf, "(cdrom '%s')",
+                                         def->disks[i]->src);
+                    break;
+
+                case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
+                    /* all xend versions define floppies here */
+                    virBufferEscapeSexpr(&buf, "(%s ", def->disks[i]->dst);
+                    virBufferEscapeSexpr(&buf, "'%s')", def->disks[i]->src);
+                    break;
+
+                default:
+                    break;
+                }
+            }
+
+            if (def->features & (1 << VIR_DOMAIN_FEATURE_ACPI))
+                virBufferAddLit(&buf, "(acpi 1)");
+            if (def->features & (1 << VIR_DOMAIN_FEATURE_APIC))
+                virBufferAddLit(&buf, "(apic 1)");
+            if (def->features & (1 << VIR_DOMAIN_FEATURE_PAE))
+                virBufferAddLit(&buf, "(pae 1)");
+            if (def->features & (1 << VIR_DOMAIN_FEATURE_HAP))
+                virBufferAddLit(&buf, "(hap 1)");
+
+            virBufferAddLit(&buf, "(usb 1)");
+
+            for (i = 0 ; i < def->ninputs ; i++)
+                if (xenDaemonFormatSxprInput(def->inputs[i], &buf) < 0)
+                    goto error;
+
+            if (def->parallels) {
+                virBufferAddLit(&buf, "(parallel ");
+                if (xenDaemonFormatSxprChr(def->parallels[0], &buf) < 0)
+                    goto error;
+                virBufferAddLit(&buf, ")");
+            } else {
+                virBufferAddLit(&buf, "(parallel none)");
+            }
+            if (def->serials) {
+                virBufferAddLit(&buf, "(serial ");
+                if (xenDaemonFormatSxprChr(def->serials[0], &buf) < 0)
+                    goto error;
+                virBufferAddLit(&buf, ")");
+            } else {
+                virBufferAddLit(&buf, "(serial none)");
+            }
+
+            /* Set localtime here to keep old XenD happy for HVM */
+            if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME)
+                virBufferAddLit(&buf, "(localtime 1)");
+
+            if (def->sounds) {
+                virBufferAddLit(&buf, "(soundhw '");
+                if (xenDaemonFormatSxprSound(def, &buf) < 0)
+                    goto error;
+                virBufferAddLit(&buf, "')");
+            }
+        }
+
+        /* get the device emulation model */
+        if (def->emulator && (hvm || xendConfigVersion >= 3))
+            virBufferEscapeSexpr(&buf, "(device_model '%s')", def->emulator);
+
+
+        /* PV graphics for xen <= 3.0.4, or HVM graphics for xen <= 3.1.0 */
+        if ((!hvm && xendConfigVersion < XEND_CONFIG_MIN_VERS_PVFB_NEWCONF) ||
+            (hvm && xendConfigVersion < 4)) {
+            if ((def->ngraphics == 1) &&
+                xenDaemonFormatSxprGraphicsOld(def->graphics[0],
+                                               &buf, xendConfigVersion) < 0)
+                goto error;
+        }
+
+        virBufferAddLit(&buf, "))");
+    }
+
+    for (i = 0 ; i < def->ndisks ; i++)
+        if (xenDaemonFormatSxprDisk(conn, def->disks[i],
+                                    &buf, hvm, xendConfigVersion, 0) < 0)
+            goto error;
+
+    for (i = 0 ; i < def->nnets ; i++)
+        if (xenDaemonFormatSxprNet(conn, def->nets[i],
+                                   &buf, hvm, xendConfigVersion, 0) < 0)
+            goto error;
+
+    if (xenDaemonFormatSxprAllPCI(def, &buf) < 0)
+        goto error;
+
+    /* New style PV graphics config xen >= 3.0.4,
+     * or HVM graphics config xen >= 3.0.5 */
+    if ((xendConfigVersion >= XEND_CONFIG_MIN_VERS_PVFB_NEWCONF && !hvm) ||
+        (xendConfigVersion >= 4 && hvm)) {
+        if ((def->ngraphics == 1) &&
+            xenDaemonFormatSxprGraphicsNew(def->graphics[0], &buf) < 0)
+            goto error;
+    }
+
+    virBufferAddLit(&buf, ")"); /* closes (vm */
+
+    if (virBufferError(&buf)) {
+        virReportOOMError();
+        goto error;
+    }
+
+    bufout = virBufferContentAndReset(&buf);
+    DEBUG("Formatted sexpr: \n%s", bufout);
+    return bufout;
+
+error:
+    virBufferFreeAndReset(&buf);
+    return NULL;
+}
diff --git a/src/xenxs/xen_sxpr.h b/src/xenxs/xen_sxpr.h
index c0c6a53..0861c4b 100644
--- a/src/xenxs/xen_sxpr.h
+++ b/src/xenxs/xen_sxpr.h
@@ -59,4 +59,36 @@ virDomainChrDefPtr
 xenDaemonParseSxprChar(const char *value,
                        const char *tty);
 
+int
+xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
+                        virDomainDiskDefPtr def,
+                        virBufferPtr buf,
+                        int hvm,
+                        int xendConfigVersion,
+                        int isAttach);
+int
+xenDaemonFormatSxprNet(virConnectPtr conn ATTRIBUTE_UNUSED,
+                       virDomainNetDefPtr def,
+                       virBufferPtr buf,
+                       int hvm,
+                       int xendConfigVersion,
+                       int isAttach);
+
+int
+xenDaemonFormatSxprOnePCI(virDomainHostdevDefPtr def,
+                          virBufferPtr buf,
+                          int detach);
+
+int
+xenDaemonFormatSxprChr(virDomainChrDefPtr def,
+                       virBufferPtr buf);
+int
+xenDaemonFormatSxprSound(virDomainDefPtr def,
+                         virBufferPtr buf);
+
+char *
+xenDaemonFormatSxpr(virConnectPtr conn,
+                    virDomainDefPtr def,
+                    int xendConfigVersion);
+
 #endif /* __VIR_XEN_SXPR_H__ */
diff --git a/src/xenxs/xenxs_private.h b/src/xenxs/xenxs_private.h
index 02fd1a3..edc1880 100644
--- a/src/xenxs/xenxs_private.h
+++ b/src/xenxs/xenxs_private.h
@@ -27,6 +27,24 @@
 
 # include "internal.h"
 
+# include <stdint.h>
+# include <xen/xen.h>
+
+/* xen-unstable changeset 19788 removed MAX_VIRT_CPUS from public
+ * headers.  Its semantic was retained with XEN_LEGACY_MAX_VCPUS.
+ * Ensure MAX_VIRT_CPUS is defined accordingly.
+ */
+# if !defined(MAX_VIRT_CPUS) && defined(XEN_LEGACY_MAX_VCPUS)
+#  define MAX_VIRT_CPUS XEN_LEGACY_MAX_VCPUS
+# endif
+
+#ifdef WITH_RHEL5_API
+# define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 0
+# define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 2
+#else
+# define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 3
+# define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 3
+#endif
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 
diff --git a/tests/xml2sexprtest.c b/tests/xml2sexprtest.c
index 8a5d115..05fc676 100644
--- a/tests/xml2sexprtest.c
+++ b/tests/xml2sexprtest.c
@@ -10,6 +10,7 @@
 
 #include "internal.h"
 #include "xen/xend_internal.h"
+#include "xenxs/xen_sxpr.h"
 #include "testutils.h"
 #include "testutilsxen.h"
 

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]