WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-4.0-testing] libxl: Backported stuff from unstable

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-4.0-testing] libxl: Backported stuff from unstable
From: "Xen patchbot-4.0-testing" <patchbot-4.0-testing@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 08 Jul 2010 02:11:09 -0700
Delivery-date: Thu, 08 Jul 2010 02:19:05 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1278431341 -3600
# Node ID b1321a50f62668ad8d3d9e721d38a10627e92d44
# Parent  1952867c5c92e7e4eef9ba4205995973de01aae0
libxl: Backported stuff from unstable

Signed-off-by: Gianni Tedesco <gianni.tedesco@xxxxxxxxxx>
---
 tools/libxl/Makefile         |   28 
 tools/libxl/bash-completion  |   21 
 tools/libxl/libxl.c          | 1038 +++++++++-
 tools/libxl/libxl.h          |  193 +
 tools/libxl/libxl_device.c   |   78 
 tools/libxl/libxl_dom.c      |  194 +
 tools/libxl/libxl_exec.c     |   34 
 tools/libxl/libxl_internal.c |   13 
 tools/libxl/libxl_internal.h |   24 
 tools/libxl/libxl_paths.c    |   61 
 tools/libxl/libxl_utils.c    |  297 ++-
 tools/libxl/libxl_utils.h    |   45 
 tools/libxl/libxl_xshelp.c   |    6 
 tools/libxl/libxlu_cfg.c     |   37 
 tools/libxl/libxlutil.h      |    3 
 tools/libxl/xenguest.c       |   18 
 tools/libxl/xl.c             | 1749 -----------------
 tools/libxl/xl.h             |   81 
 tools/libxl/xl_cmdimpl.c     | 4243 +++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/xl_cmdtable.c    |  322 +++
 tools/xenstore/xs.c          |   52 
 tools/xenstore/xs.h          |    3 
 22 files changed, 6561 insertions(+), 1979 deletions(-)

diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/Makefile
--- a/tools/libxl/Makefile      Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/Makefile      Tue Jul 06 16:49:01 2010 +0100
@@ -11,13 +11,13 @@ XLUMAJOR = 1.0
 XLUMAJOR = 1.0
 XLUMINOR = 0
 
-#CFLAGS += -Werror
+CFLAGS += -Werror
 CFLAGS += -I. -fPIC
 CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) $(CFLAGS_libxenstore)
 
 LIBS = $(LDFLAGS_libxenctrl) $(LDFLAGS_libxenguest) $(LDFLAGS_libxenstore)
 
-LIBXL_OBJS-y = osdeps.o
+LIBXL_OBJS-y = osdeps.o libxl_paths.o
 LIBXL_OBJS = flexarray.o libxl.o libxl_dom.o libxl_exec.o libxl_xshelp.o 
libxl_device.o libxl_internal.o xenguest.o libxl_utils.o $(LIBXL_OBJS-y)
 
 AUTOINCS= libxlu_cfg_y.h libxlu_cfg_l.h
@@ -42,6 +42,15 @@ all: $(CLIENTS) libxenlight.so libxenlig
 
 %.c: %.l
        $(FLEX) --header-file=$*.h --outfile=$@ $<
+
+genpath-target = $(call buildmakevars2file,_libxl_paths.h)
+$(eval $(genpath-target))
+
+_libxl_paths.h: genpath
+       sed -e "s/\([^=]*\)=\(.*\)/#define \1 \2/g" $@ >_$@
+       mv _$@ $@
+
+libxl_paths.c: _libxl_paths.h
 
 libxenlight.so: libxenlight.so.$(MAJOR)
        ln -sf $< $@
@@ -70,11 +79,21 @@ xl.o: xl.c
 xl.o: xl.c
        $(CC) $(CFLAGS) -c xl.c
 
-$(CLIENTS): xl.o libxlutil.so libxenlight.so
+xl_cmdimpl.o: xl_cmdimpl.c
+       $(CC) $(CFLAGS) -c xl_cmdimpl.c
+
+xl_cmdtable.o: xl_cmdtable.c
+       $(CC) $(CFLAGS) -c xl_cmdtable.c
+
+$(CLIENTS): xl.o xl_cmdimpl.o xl_cmdtable.o libxlutil.so libxenlight.so
        $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
 
 .PHONY: install
 install: all
+       $(INSTALL_DIR) $(DESTDIR)$(SBINDIR)
+       $(INSTALL_DIR) $(DESTDIR)$(LIBDIR)
+       $(INSTALL_DIR) $(DESTDIR)$(INCLUDEDIR)
+       $(INSTALL_DIR) $(DESTDIR)$(BASH_COMPLETION_DIR)
        $(INSTALL_PROG) xl $(DESTDIR)$(SBINDIR)
        $(INSTALL_PROG) libxenlight.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)
        ln -sf libxenlight.so.$(MAJOR).$(MINOR) 
$(DESTDIR)$(LIBDIR)/libxenlight.so.$(MAJOR)
@@ -85,10 +104,11 @@ install: all
        ln -sf libxlutil.so.$(XLUMAJOR) $(DESTDIR)$(LIBDIR)/libxlutil.so
        $(INSTALL_DATA) libxlutil.a $(DESTDIR)$(LIBDIR)
        $(INSTALL_DATA) libxl.h $(DESTDIR)$(INCLUDEDIR)
+       $(INSTALL_DATA) bash-completion $(DESTDIR)$(BASH_COMPLETION_DIR)/xl.sh
 
 .PHONY: clean
 clean:
-       $(RM) -f *.o *.so* *.a $(CLIENTS) $(DEPS)
+       $(RM) -f _*.h *.o *.so* *.a $(CLIENTS) $(DEPS)
 #      $(RM) -f $(AUTOSRCS) $(AUTOINCS)
 
 distclean: clean
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/bash-completion
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/bash-completion       Tue Jul 06 16:49:01 2010 +0100
@@ -0,0 +1,21 @@
+#!/bin/bash
+# Copy this file to /etc/bash_completion.d/xl.sh
+
+_xl()
+{
+       local IFS=$'\n,'
+
+       local cur opts xl
+       COMPREPLY=()
+       cur="${COMP_WORDS[COMP_CWORD]}"
+       xl=xl
+
+       if [[ $COMP_CWORD == 1 ]] ; then
+               opts=`${xl} help 2>/dev/null | sed '1,4d' | awk '{print $1}' | 
sed 's/$/ ,/g'` && COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+               return 0
+       fi
+
+       return 0
+}
+
+complete -F _xl -o nospace -o default xl
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c       Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/libxl.c       Tue Jul 06 16:49:01 2010 +0100
@@ -45,6 +45,7 @@ int libxl_ctx_init(struct libxl_ctx *ctx
     ctx->alloc_ptrs = calloc(ctx->alloc_maxsize, sizeof(void *));
     if (!ctx->alloc_ptrs)
         return ERROR_NOMEM;
+    memset(&ctx->version_info, 0, sizeof(libxl_version_info));
 
     ctx->xch = xc_interface_open();
     if (ctx->xch == -1) {
@@ -66,7 +67,7 @@ int libxl_ctx_free(struct libxl_ctx *ctx
     libxl_free_all(ctx);
     free(ctx->alloc_ptrs);
     xc_interface_close(ctx->xch);
-    xs_daemon_close(ctx->xsh); 
+    if (ctx->xsh) xs_daemon_close(ctx->xsh); 
     return 0;
 }
 
@@ -82,7 +83,7 @@ int libxl_domain_make(struct libxl_ctx *
 int libxl_domain_make(struct libxl_ctx *ctx, libxl_domain_create_info *info,
                        uint32_t *domid)
 {
-    int flags, ret, i;
+    int flags, ret, i, rc;
     char *uuid_string;
     char *rw_paths[] = { "device", "device/suspend/event-channel" , "data"};
     char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers",
@@ -93,14 +94,12 @@ int libxl_domain_make(struct libxl_ctx *
     xs_transaction_t t;
     xen_domain_handle_t handle;
 
-    uuid_string = string_of_uuid(ctx, info->uuid);
-    if (!uuid_string) {
-        XL_LOG(ctx, XL_LOG_ERROR, "cannot allocate uuid string");
-        return ERROR_FAIL;
-    }
+    uuid_string = libxl_uuid2string(ctx, info->uuid);
+    if (!uuid_string) return ERROR_NOMEM;
 
     flags = info->hvm ? XEN_DOMCTL_CDF_hvm_guest : 0;
     flags |= info->hap ? XEN_DOMCTL_CDF_hap : 0;
+    flags |= info->oos ? 0 : XEN_DOMCTL_CDF_oos_off;
     *domid = -1;
 
     /* Ultimately, handle is an array of 16 uint8_t, same as uuid */
@@ -146,7 +145,8 @@ retry_transaction:
 
     xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vm", dom_path), vm_path, 
strlen(vm_path));
     xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vss", dom_path), vss_path, 
strlen(vss_path));
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/name", dom_path), info->name, 
strlen(info->name));
+    rc = libxl_domain_rename(ctx, *domid, 0, info->name, t);
+    if (rc) return rc;
 
     for (i = 0; i < ARRAY_SIZE(rw_paths); i++) {
         char *path = libxl_sprintf(ctx, "%s/%s", dom_path, rw_paths[i]);
@@ -175,33 +175,118 @@ retry_transaction:
     return 0;
 }
 
+int libxl_domain_rename(struct libxl_ctx *ctx, uint32_t domid,
+                        const char *old_name, const char *new_name,
+                        xs_transaction_t trans) {
+    char *dom_path = 0;
+    const char *name_path;
+    char *got_old_name;
+    unsigned int got_old_len;
+    xs_transaction_t our_trans = 0;
+    int rc;
+
+    dom_path = libxl_xs_get_dompath(ctx, domid);
+    if (!dom_path) goto x_nomem;
+
+    name_path= libxl_sprintf(ctx, "%s/name", dom_path);
+    if (!name_path) goto x_nomem;
+
+ retry_transaction:
+    if (!trans) {
+        trans = our_trans = xs_transaction_start(ctx->xsh);
+        if (!our_trans) {
+            XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno,
+                            "create xs transaction for domain (re)name");
+            goto x_fail;
+        }
+    }
+
+    if (old_name) {
+        got_old_name = xs_read(ctx->xsh, trans, name_path, &got_old_len);
+        if (!got_old_name) {
+            XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno, "check old name"
+                            " for domain %"PRIu32" allegedly named `%s'",
+                            domid, old_name);
+            goto x_fail;
+        }
+        if (strcmp(old_name, got_old_name)) {
+            XL_LOG(ctx, XL_LOG_ERROR, "domain %"PRIu32" allegedly named "
+                   "`%s' is actually named `%s' - racing ?",
+                   domid, old_name, got_old_name);
+            free(got_old_name);
+            goto x_fail;
+        }
+        free(got_old_name);
+    }
+    if (!xs_write(ctx->xsh, trans, name_path,
+                  new_name, strlen(new_name))) {
+        XL_LOG(ctx, XL_LOG_ERROR, "failed to write new name `%s'"
+               " for domain %"PRIu32" previously named `%s'",
+               new_name, domid, old_name);
+        goto x_fail;
+    }
+
+    if (our_trans) {
+        if (!xs_transaction_end(ctx->xsh, our_trans, 0)) {
+            trans = our_trans = 0;
+            if (errno != EAGAIN) {
+                XL_LOG(ctx, XL_LOG_ERROR, "failed to commit new name `%s'"
+                       " for domain %"PRIu32" previously named `%s'",
+                       new_name, domid, old_name);
+                goto x_fail;
+            }
+            XL_LOG(ctx, XL_LOG_DEBUG, "need to retry rename transaction"
+                   " for domain %"PRIu32" (name_path=\"%s\", new_name=\"%s\")",
+                   domid, name_path, new_name);
+            goto retry_transaction;
+        }
+        our_trans = 0;
+    }
+
+    rc = 0;
+ x_rc:
+    if (dom_path) libxl_free(ctx, dom_path);
+    if (our_trans) xs_transaction_end(ctx->xsh, our_trans, 1);
+    return rc;
+
+ x_fail:  rc = ERROR_FAIL;  goto x_rc;
+ x_nomem: rc = ERROR_NOMEM; goto x_rc;
+}
+
 int libxl_domain_build(struct libxl_ctx *ctx, libxl_domain_build_info *info, 
uint32_t domid, libxl_domain_build_state *state)
 {
     char **vments = NULL, **localents = NULL;
+    struct timeval start_time;
     int i, ret;
 
     ret = build_pre(ctx, domid, info, state);
     if (ret) goto out;
+
+    gettimeofday(&start_time, NULL);
 
     if (info->hvm) {
         ret = build_hvm(ctx, domid, info, state);
         if (ret) goto out;
 
-        vments = libxl_calloc(ctx, 5, sizeof(char *));
+        vments = libxl_calloc(ctx, 7, sizeof(char *));
         vments[0] = "rtc/timeoffset";
         vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
         vments[2] = "image/ostype";
         vments[3] = "hvm";
+        vments[4] = "start_time";
+        vments[5] = libxl_sprintf(ctx, "%lu.%02d", 
start_time.tv_sec,(int)start_time.tv_usec/10000);
     } else {
         ret = build_pv(ctx, domid, info, state);
         if (ret) goto out;
 
-        vments = libxl_calloc(ctx, 9, sizeof(char *));
+        vments = libxl_calloc(ctx, 11, sizeof(char *));
         i = 0;
         vments[i++] = "image/ostype";
         vments[i++] = "linux";
         vments[i++] = "image/kernel";
         vments[i++] = (char*) info->kernel;
+        vments[i++] = "start_time";
+        vments[i++] = libxl_sprintf(ctx, "%lu.%02d", 
start_time.tv_sec,(int)start_time.tv_usec/10000);
         if (info->u.pv.ramdisk) {
             vments[i++] = "image/ramdisk";
             vments[i++] = (char*) info->u.pv.ramdisk;
@@ -221,7 +306,8 @@ int libxl_domain_restore(struct libxl_ct
                          libxl_device_model_info *dm_info)
 {
     char **vments = NULL, **localents = NULL;
-    int i, ret;
+    struct timeval start_time;
+    int i, ret, esave, flags;
 
     ret = build_pre(ctx, domid, info, state);
     if (ret) goto out;
@@ -229,19 +315,25 @@ int libxl_domain_restore(struct libxl_ct
     ret = restore_common(ctx, domid, info, state, fd);
     if (ret) goto out;
 
+    gettimeofday(&start_time, NULL);
+
     if (info->hvm) {
-        vments = libxl_calloc(ctx, 5, sizeof(char *));
+        vments = libxl_calloc(ctx, 7, sizeof(char *));
         vments[0] = "rtc/timeoffset";
         vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
         vments[2] = "image/ostype";
         vments[3] = "hvm";
+        vments[4] = "start_time";
+        vments[5] = libxl_sprintf(ctx, "%lu.%02d", 
start_time.tv_sec,(int)start_time.tv_usec/10000);
     } else {
-        vments = libxl_calloc(ctx, 9, sizeof(char *));
+        vments = libxl_calloc(ctx, 11, sizeof(char *));
         i = 0;
         vments[i++] = "image/ostype";
         vments[i++] = "linux";
         vments[i++] = "image/kernel";
         vments[i++] = (char*) info->kernel;
+        vments[i++] = "start_time";
+        vments[i++] = libxl_sprintf(ctx, "%lu.%02d", 
start_time.tv_sec,(int)start_time.tv_usec/10000);
         if (info->u.pv.ramdisk) {
             vments[i++] = "image/ramdisk";
             vments[i++] = (char*) info->u.pv.ramdisk;
@@ -254,11 +346,27 @@ int libxl_domain_restore(struct libxl_ct
     ret = build_post(ctx, domid, info, state, vments, localents);
     if (ret) goto out;
 
-    if (info->hvm)
-        asprintf(&(dm_info->saved_state), "/var/lib/xen/qemu-save.%d", domid);
-    else
-        dm_info->saved_state = NULL;
+    dm_info->saved_state = NULL;
+    if (info->hvm) {
+        ret = asprintf(&dm_info->saved_state,
+                       "/var/lib/xen/qemu-save.%d", domid);
+        ret = (ret < 0) ? ERROR_FAIL : 0;
+    }
+
 out:
+    esave = errno;
+
+    flags = fcntl(fd, F_GETFL);
+    if (flags == -1) {
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unable to get flags on restore fd");
+    } else {
+        flags &= ~O_NONBLOCK;
+        if (fcntl(fd, F_SETFL, flags) == -1)
+            XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unable to put restore fd"
+                         " back to blocking mode");
+    }
+
+    errno = esave;
     return ret;
 }
 
@@ -284,6 +392,24 @@ int libxl_domain_resume(struct libxl_ctx
     return 0;
 }
 
+static void xcinfo2xlinfo(const xc_domaininfo_t *xcinfo,
+                          struct libxl_dominfo *xlinfo) {
+    memcpy(&(xlinfo->uuid), xcinfo->handle, sizeof(xen_domain_handle_t));
+    xlinfo->domid = xcinfo->domain;
+
+    if (xcinfo->flags & XEN_DOMINF_dying)
+        xlinfo->dying = 1;
+    else if (xcinfo->flags & XEN_DOMINF_paused)
+        xlinfo->paused = 1;
+    else if (xcinfo->flags & XEN_DOMINF_blocked ||
+             xcinfo->flags & XEN_DOMINF_running)
+        xlinfo->running = 1;
+    xlinfo->max_memkb = PAGE_TO_MEMKB(xcinfo->tot_pages);
+    xlinfo->cpu_time = xcinfo->cpu_time;
+    xlinfo->vcpu_max_id = xcinfo->max_vcpu_id;
+    xlinfo->vcpu_online = xcinfo->nr_online_vcpus;
+}
+
 struct libxl_dominfo * libxl_list_domain(struct libxl_ctx *ctx, int *nb_domain)
 {
     struct libxl_dominfo *ptr;
@@ -292,27 +418,29 @@ struct libxl_dominfo * libxl_list_domain
     int size = 1024;
 
     ptr = calloc(size, sizeof(struct libxl_dominfo));
-    if (!ptr)
-        return NULL;
+    if (!ptr) return NULL;
 
     ret = xc_domain_getinfolist(ctx->xch, 0, 1024, info);
+    if (ret<0) return NULL;
+
     for (i = 0; i < ret; i++) {
-        memcpy(&(ptr[i].uuid), info[i].handle, sizeof(xen_domain_handle_t));
-        ptr[i].domid = info[i].domain;
-
-        if (info[i].flags & XEN_DOMINF_dying)
-            ptr[i].dying = 1;
-        else if (info[i].flags & XEN_DOMINF_paused)
-            ptr[i].paused = 1;
-        else if (info[i].flags & XEN_DOMINF_blocked || info[i].flags & 
XEN_DOMINF_running)
-            ptr[i].running = 1;
-        ptr[i].max_memkb = PAGE_TO_MEMKB(info[i].tot_pages);
-        ptr[i].cpu_time = info[i].cpu_time;
-        ptr[i].vcpu_max_id = info[i].max_vcpu_id;
-        ptr[i].vcpu_online = info[i].nr_online_vcpus;
+        xcinfo2xlinfo(&info[i], &ptr[i]);
     }
     *nb_domain = ret;
     return ptr;
+}
+
+int libxl_domain_info(struct libxl_ctx *ctx, struct libxl_dominfo *info_r,
+                      uint32_t domid) {
+    xc_domaininfo_t xcinfo;
+    int ret;
+
+    ret = xc_domain_getinfolist(ctx->xch, domid, 1, &xcinfo);
+    if (ret<0) return ERROR_FAIL;
+    if (ret==0 || xcinfo.domain != domid) return ERROR_INVAL;
+
+    xcinfo2xlinfo(&xcinfo, info_r);
+    return 0;
 }
 
 /* this API call only list VM running on this host. a VM can be an aggregate 
of multiple domains. */
@@ -345,11 +473,11 @@ int libxl_domain_suspend(struct libxl_ct
 {
     int hvm = is_hvm(ctx, domid);
     int live = info != NULL && info->flags & XL_SUSPEND_LIVE;
-    int debug = info != NULL && info->flags & XL_SUSPEND_LIVE;
+    int debug = info != NULL && info->flags & XL_SUSPEND_DEBUG;
 
     core_suspend(ctx, domid, fd, hvm, live, debug);
     if (hvm)
-        save_device_model(ctx, domid, fd);
+        return save_device_model(ctx, domid, fd);
     return 0;
 }
 
@@ -400,12 +528,12 @@ int libxl_domain_shutdown(struct libxl_c
     shutdown_path = libxl_sprintf(ctx, "%s/control/shutdown", dom_path);
 
     xs_write(ctx->xsh, XBT_NULL, shutdown_path, req_table[req], 
strlen(req_table[req]));
-    if (/* hvm */ 0) {
+    if (is_hvm(ctx,domid)) {
         unsigned long acpi_s_state = 0;
         unsigned long pvdriver = 0;
         xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_ACPI_S_STATE, 
&acpi_s_state);
         xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
-        if (!pvdriver && acpi_s_state != 0)
+        if (!pvdriver || acpi_s_state != 0)
             xc_domain_shutdown(ctx->xch, domid, req);
     }
     return 0;
@@ -420,7 +548,8 @@ int libxl_wait_for_domain_death(struct l
 int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, 
libxl_waiter *waiter)
 {
     waiter->path = strdup("@releaseDomain");
-    asprintf(&(waiter->token), "%d", DOMAIN_DEATH);
+    if (asprintf(&(waiter->token), "%d", DOMAIN_DEATH) < 0)
+        return -1;
     if (!xs_watch(ctx->xsh, waiter->path, waiter->token))
         return -1;
     return 0;
@@ -435,8 +564,12 @@ int libxl_wait_for_disk_ejects(struct li
         domid = guest_domid;
 
     for (i = 0; i < num_disks; i++) {
-        asprintf(&(waiter[i].path), "%s/device/vbd/%d/eject", 
libxl_xs_get_dompath(ctx, domid), device_disk_dev_number(disks[i].virtpath));
-        asprintf(&(waiter[i].token), "%d", DISK_EJECT);
+        if (asprintf(&(waiter[i].path), "%s/device/vbd/%d/eject",
+                     libxl_xs_get_dompath(ctx, domid),
+                     device_disk_dev_number(disks[i].virtpath)) < 0)
+            return -1;
+        if (asprintf(&(waiter[i].token), "%d", DISK_EJECT) < 0)
+            return -1;
         xs_watch(ctx->xsh, waiter->path, waiter->token);
     }
     return 0;
@@ -616,6 +749,8 @@ int libxl_domain_destroy(struct libxl_ct
         if (!xs_rm(ctx->xsh, XBT_NULL, xapi_path))
             XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", xapi_path);
 
+    libxl__userdata_destroyall(ctx, domid);
+
     rc = xc_domain_destroy(ctx->xch, domid);
     if (rc < 0) {
         XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_destroy failed for 
%d", domid);
@@ -626,16 +761,9 @@ int libxl_domain_destroy(struct libxl_ct
 
 int libxl_console_attach(struct libxl_ctx *ctx, uint32_t domid, int cons_num)
 {
-    struct stat st;
-    const char *XENCONSOLE = "/usr/lib/xen/bin/xenconsole";
-    char *cmd;
-
-    if (stat(XENCONSOLE, &st) != 0) {
-        XL_LOG(ctx, XL_LOG_ERROR, "could not access %s", XENCONSOLE);
-        return ERROR_FAIL;
-    }
-
-    cmd = libxl_sprintf(ctx, "%s %d --num %d", XENCONSOLE, domid, cons_num);
+    char *cmd = libxl_sprintf(
+        ctx, "%s/xenconsole %d --num %d",
+        libxl_private_bindir_path(), domid, cons_num);
     return (system(cmd) != 0) ? ERROR_FAIL : 0;
 }
 
@@ -663,7 +791,12 @@ static char ** libxl_build_device_model_
         flexarray_set(dm_args, num++, "-vnc");
         if (info->vncdisplay) {
             if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
-                flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s:%d", 
info->vnclisten, info->vncdisplay));
+                flexarray_set(
+                    dm_args, num++,
+                    libxl_sprintf(ctx, "%s:%d%s",
+                                  info->vnclisten,
+                                  info->vncdisplay,
+                                  info->vncpasswd ? ",password" : ""));
             } else {
                 flexarray_set(dm_args, num++, libxl_sprintf(ctx, 
"127.0.0.1:%d", info->vncdisplay));
             }
@@ -680,7 +813,7 @@ static char ** libxl_build_device_model_
             flexarray_set(dm_args, num++, "-vncunused");
         }
     }
-    if (info->sdl || info->opengl) {
+    if (info->sdl) {
         flexarray_set(dm_args, num++, "-sdl");
         if (info->opengl) {
             flexarray_set(dm_args, num++, "-disable-opengl");
@@ -698,6 +831,8 @@ static char ** libxl_build_device_model_
         flexarray_set(dm_args, num++, info->serial);
     }
     if (info->type == XENFV) {
+        int ioemu_vifs = 0;
+
         if (info->videoram) {
             flexarray_set(dm_args, num++, "-videoram");
             flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", 
info->videoram));
@@ -719,6 +854,14 @@ static char ** libxl_build_device_model_
         }
         if (info->apic) {
             flexarray_set(dm_args, num++, "-acpi");
+        }
+        if (info->vcpus > 1) {
+            flexarray_set(dm_args, num++, "-vcpus");
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", 
info->vcpus));
+        }
+        if (info->vcpu_avail) {
+            flexarray_set(dm_args, num++, "-vcpu_avail");
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "0x%x", 
info->vcpu_avail));
         }
         for (i = 0; i < num_vifs; i++) {
             if (vifs[i].nictype == NICTYPE_IOEMU) {
@@ -733,7 +876,13 @@ static char ** libxl_build_device_model_
                 flexarray_set(dm_args, num++, "-net");
                 flexarray_set(dm_args, num++, libxl_sprintf(ctx, 
"tap,vlan=%d,ifname=%s,bridge=%s",
                             vifs[i].devid, vifs[i].ifname, vifs[i].bridge));
+                ioemu_vifs++;
             }
+        }
+        /* If we have no emulated nics, tell qemu not to create any */
+        if ( ioemu_vifs == 0 ) {
+            flexarray_set(dm_args, num++, "-net");
+            flexarray_set(dm_args, num++, "none");
         }
     }
     if (info->saved_state) {
@@ -763,7 +912,8 @@ void dm_xenstore_record_pid(void *for_sp
     /* we mustn't use the parent's handle in the child */
 
     kvs[0] = "image/device-model-pid";
-    asprintf(&kvs[1], "%d", innerchild);
+    if (asprintf(&kvs[1], "%d", innerchild) < 0)
+        return;
     kvs[2] = NULL;
 
     rc = xs_writev(xsh, XBT_NULL, starting->dom_path, kvs);
@@ -786,6 +936,7 @@ static int libxl_vfb_and_vkb_from_device
     vfb->vnclisten = info->vnclisten;
     vfb->vncdisplay = info->vncdisplay;
     vfb->vncunused = info->vncunused;
+    vfb->vncpasswd = info->vncpasswd;
     vfb->keymap = info->keymap;
     vfb->sdl = info->sdl;
     vfb->opengl = info->opengl;
@@ -875,7 +1026,7 @@ static int libxl_create_stubdom(struct l
     b_info.max_vcpus = 1;
     b_info.max_memkb = 32 * 1024;
     b_info.target_memkb = b_info.max_memkb;
-    b_info.kernel = "/usr/lib/xen/boot/ioemu-stubdom.gz";
+    b_info.kernel = libxl_abs_path(ctx, "ioemu-stubdom.gz", 
libxl_xenfirmwaredir_path());
     b_info.u.pv.cmdline = libxl_sprintf(ctx, " -d %d", info->domid);
     b_info.u.pv.ramdisk = "";
     b_info.u.pv.features = "";
@@ -976,6 +1127,9 @@ int libxl_create_device_model(struct lib
     int rc;
     char **args;
     struct libxl_device_model_starting buf_starting, *p;
+    xs_transaction_t t;
+    char *vm_path;
+    char **pass_stuff;
 
     if (strstr(info->device_model, "stubdom-dm")) {
         libxl_device_vfb vfb;
@@ -991,6 +1145,7 @@ int libxl_create_device_model(struct lib
 
     path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid);
     xs_mkdir(ctx->xsh, XBT_NULL, path);
+    libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/disable_pf", path), 
"%d", !info->xen_platform_pci);
 
     libxl_create_logfile(ctx, libxl_sprintf(ctx, "qemu-dm-%s", 
info->dom_name), &logfile);
     logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644);
@@ -1012,11 +1167,29 @@ int libxl_create_device_model(struct lib
     p->dom_path = libxl_xs_get_dompath(ctx, info->domid);
     if (!p->dom_path) { libxl_free(ctx, p); return ERROR_FAIL; }
 
+    if (info->vncpasswd) {
+    retry_transaction:
+        /* Find uuid and the write the vnc password to xenstore for qemu. */
+        t = xs_transaction_start(ctx->xsh);
+        vm_path = libxl_xs_read(ctx,t,libxl_sprintf(ctx, "%s/vm", 
p->dom_path));
+        if (vm_path) {
+            /* Now write the vncpassword into it. */
+            pass_stuff = libxl_calloc(ctx, 2, sizeof(char *));
+            pass_stuff[0] = "vncpasswd";
+            pass_stuff[1] = info->vncpasswd;
+            libxl_xs_writev(ctx,t,vm_path,pass_stuff);
+            if (!xs_transaction_end(ctx->xsh, t, 0))
+                if (errno == EAGAIN)
+                    goto retry_transaction;
+        }
+    }
+
     rc = libxl_spawn_spawn(ctx, p, "device model", dm_xenstore_record_pid);
     if (rc < 0) goto xit;
     if (!rc) { /* inner child */
         libxl_exec(null, logfile_w, logfile_w,
-                   info->device_model, args);
+                   libxl_abs_path(ctx, info->device_model, 
libxl_private_bindir_path()),
+                   args);
     }
 
     rc = 0;
@@ -1078,7 +1251,8 @@ static char *get_blktap2_device(struct l
 
     
     while (!feof(f)) {
-        fscanf(f, "%d %s", &devnum, buf);
+        if (fscanf(f, "%d %s", &devnum, buf) != 2)
+            continue;
         p = strchr(buf, ':');
         if (p == NULL)
             continue;
@@ -1146,15 +1320,9 @@ int libxl_device_disk_add(struct libxl_c
                 char buf[1024], *dev;
                 dev = get_blktap2_device(ctx, disk->physpath, 
device_disk_string_of_phystype(disk->phystype));
                 if (dev == NULL) {
-                    if (pipe(p) < 0) {
-                        XL_LOG(ctx, XL_LOG_ERROR, "Failed to create a pipe");
-                        return -1;
-                    }
-                    rc = fork();
-                    if (rc < 0) {
-                        XL_LOG(ctx, XL_LOG_ERROR, "Failed to fork a new 
process");
-                        return -1;
-                    } else if (!rc) { /* child */
+                    rc= libxl_pipe(ctx, p);  if (rc==-1) return -1;
+                    rc= libxl_fork(ctx);  if (rc==-1) return -1;
+                    if (!rc) { /* child */
                         int null_r, null_w;
                         char *args[4];
                         args[0] = "tapdisk2";
@@ -1164,7 +1332,10 @@ int libxl_device_disk_add(struct libxl_c
 
                         null_r = open("/dev/null", O_RDONLY);
                         null_w = open("/dev/null", O_WRONLY);
-                        libxl_exec(null_r, p[1], null_w, "/usr/sbin/tapdisk2", 
args);
+                        libxl_exec(null_r, p[1], null_w,
+                                   libxl_abs_path(ctx, "tapdisk2",
+                                                  libxl_sbindir_path()),
+                                   args);
                         XL_LOG(ctx, XL_LOG_ERROR, "Error execing tapdisk2");
                     }
                     close(p[1]);
@@ -1262,6 +1433,8 @@ int libxl_device_nic_add(struct libxl_ct
     unsigned int boffset = 0;
     unsigned int foffset = 0;
     libxl_device device;
+    char *dompath, **l;
+    unsigned int nb;
 
     front = flexarray_make(16, 1);
     if (!front)
@@ -1269,6 +1442,19 @@ int libxl_device_nic_add(struct libxl_ct
     back = flexarray_make(16, 1);
     if (!back)
         return ERROR_NOMEM;
+
+    if (nic->devid == -1) {
+        if (!(dompath = libxl_xs_get_dompath(ctx, domid))) {
+            return ERROR_FAIL;
+        }
+        if (!(l = libxl_xs_directory(ctx, XBT_NULL,
+                                     libxl_sprintf(ctx, "%s/device/vif", 
dompath), &nb))) {
+            nic->devid = 0;
+        } else {
+            nic->devid = strtoul(l[nb - 1], NULL, 10) + 1;
+            libxl_free(ctx, l);
+        }
+    }
 
     device.backend_devid = nic->devid;
     device.backend_domid = nic->backend_domid;
@@ -1289,6 +1475,8 @@ int libxl_device_nic_add(struct libxl_ct
     flexarray_set(back, boffset++, libxl_sprintf(ctx, 
"%02x:%02x:%02x:%02x:%02x:%02x",
                                                  nic->mac[0], nic->mac[1], 
nic->mac[2],
                                                  nic->mac[3], nic->mac[4], 
nic->mac[5]));
+    flexarray_set(back, boffset++, "bridge");
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", nic->bridge));
     flexarray_set(back, boffset++, "handle");
     flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->devid));
 
@@ -1331,6 +1519,66 @@ int libxl_device_nic_del(struct libxl_ct
 
     return libxl_device_del(ctx, &device, wait);
 }
+
+libxl_nicinfo *libxl_list_nics(struct libxl_ctx *ctx, uint32_t domid, unsigned 
int *nb)
+{
+    char *dompath, *nic_path_fe;
+    char **l;
+    char *val, *tok;
+    unsigned int nb_nics, i;
+    libxl_nicinfo *res, *nics;
+
+    dompath = libxl_xs_get_dompath(ctx, domid);
+    if (!dompath) {
+        return NULL;
+    }
+    l = libxl_xs_directory(ctx, XBT_NULL,
+                           libxl_sprintf(ctx, "%s/device/vif", dompath), 
&nb_nics);
+    if (!l) {
+        return NULL;
+    }
+    res = libxl_calloc(ctx, nb_nics, sizeof (libxl_device_nic));
+    if (!res) {
+        libxl_free(ctx, l);
+        return NULL;
+    }
+    nics = res;
+    for (*nb = nb_nics; nb_nics > 0; --nb_nics, ++l, ++nics) {
+        nic_path_fe = libxl_sprintf(ctx, "%s/device/vif/%s", dompath, *l);
+
+        nics->backend = libxl_xs_read(ctx, XBT_NULL,
+                                      libxl_sprintf(ctx, "%s/backend", 
nic_path_fe));
+        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", 
nic_path_fe));
+        nics->backend_id = val ? strtoul(val, NULL, 10) : -1;
+
+        nics->devid = strtoul(*l, NULL, 10);
+        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/state", 
nic_path_fe));
+        nics->state = val ? strtoul(val, NULL, 10) : -1;
+        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/mac", 
nic_path_fe));
+        for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
+             ++i, tok = strtok(NULL, ":")) {
+            nics->mac[i] = strtoul(tok, NULL, 16);
+        }
+        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/event-channel", nic_path_fe));
+        nics->evtch = val ? strtol(val, NULL, 10) : -1;
+        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/tx-ring-ref", nic_path_fe));
+        nics->rref_tx = val ? strtol(val, NULL, 10) : -1;
+        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/rx-ring-ref", nic_path_fe));
+        nics->rref_rx = val ? strtol(val, NULL, 10) : -1;
+        nics->frontend = libxl_xs_read(ctx, XBT_NULL,
+                                       libxl_sprintf(ctx, "%s/frontend", 
nics->backend));
+        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/frontend-id", nics->backend));
+        nics->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+        nics->script = libxl_xs_read(ctx, XBT_NULL,
+                                     libxl_sprintf(ctx, "%s/script", 
nics->backend));
+
+        libxl_free(ctx, nic_path_fe);
+    }
+
+    libxl_free(ctx, l);
+    return res;
+}
+
 
 
/******************************************************************************/
 int libxl_device_console_add(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_console *console)
@@ -1470,57 +1718,90 @@ libxl_device_disk *libxl_device_disk_lis
 libxl_device_disk *libxl_device_disk_list(struct libxl_ctx *ctx, uint32_t 
domid, int *num)
 {
     char *be_path_tap, *be_path_vbd;
-    libxl_device_disk *disks = NULL;
-    char **l = NULL;
+    libxl_device_disk *dend, *disks, *ret = NULL;
+    char **b, **l = NULL;
     unsigned int numl;
-    int num_disks = 0, i;
     char *type;
 
     be_path_vbd = libxl_sprintf(ctx, "%s/backend/vbd/%d", 
libxl_xs_get_dompath(ctx, 0), domid);
     be_path_tap = libxl_sprintf(ctx, "%s/backend/tap/%d", 
libxl_xs_get_dompath(ctx, 0), domid);
 
-    l = libxl_xs_directory(ctx, XBT_NULL, be_path_vbd, &numl);
+    b = l = libxl_xs_directory(ctx, XBT_NULL, be_path_vbd, &numl);
     if (l) {
-        num_disks += numl;
-        disks = realloc(disks, sizeof(libxl_device_disk) * num_disks);
-        for (i = 0; i < numl; i++) {
-            disks[i].backend_domid = 0;
-            disks[i].domid = domid;
-            disks[i].physpath = libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/params", be_path_vbd, l[i]));
-            libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/type", be_path_vbd, l[i])), &(disks[i].phystype));
-            disks[i].virtpath = libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/dev", be_path_vbd, l[i]));
-            disks[i].unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/removable", be_path_vbd, l[i])));
-            if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/mode", be_path_vbd, l[i])), "w"))
-                disks[i].readwrite = 1;
+        ret = realloc(ret, sizeof(libxl_device_disk) * numl);
+        disks = ret;
+        *num = numl;
+        dend = ret + *num;
+        for (; disks < dend; ++disks, ++l) {
+            disks->backend_domid = 0;
+            disks->domid = domid;
+            disks->physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/params", be_path_vbd, *l));
+            libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/type", be_path_vbd, *l)), &(disks->phystype));
+            disks->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/dev", be_path_vbd, *l));
+            disks->unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/removable", be_path_vbd, *l)));
+            if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/mode", be_path_vbd, *l)), "w"))
+                disks->readwrite = 1;
             else
-                disks[i].readwrite = 0;
-            type = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/device-type", libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/frontend", be_path_vbd, l[i]))));
-            disks[i].is_cdrom = !strcmp(type, "cdrom");
-        }
-        free(l);
-    }
-    l = libxl_xs_directory(ctx, XBT_NULL, be_path_tap, &numl);
+                disks->readwrite = 0;
+            type = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/device-type", libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/frontend", be_path_vbd, *l))));
+            disks->is_cdrom = !strcmp(type, "cdrom");
+        }
+        libxl_free(ctx, b);
+    }
+    b = l = libxl_xs_directory(ctx, XBT_NULL, be_path_tap, &numl);
     if (l) {
-        num_disks += numl;
-        disks = realloc(disks, sizeof(libxl_device_disk) * num_disks);
-        for (i = 0; i < numl; i++) {
-            disks[i].backend_domid = 0;
-            disks[i].domid = domid;
-            disks[i].physpath = libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/params", be_path_tap, l[i]));
-            libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/type", be_path_tap, l[i])), &(disks[i].phystype));
-            disks[i].virtpath = libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/dev", be_path_tap, l[i]));
-            disks[i].unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/removable", be_path_tap, l[i])));
-            if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/mode", be_path_tap, l[i])), "w"))
-                disks[i].readwrite = 1;
+        ret = realloc(ret, sizeof(libxl_device_disk) * (*num + numl));
+        disks = ret + *num;
+        *num += numl;
+        for (dend = ret + *num; disks < dend; ++disks, ++l) {
+            disks->backend_domid = 0;
+            disks->domid = domid;
+            disks->physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/params", be_path_tap, *l));
+            libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/type", be_path_tap, *l)), &(disks->phystype));
+            disks->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/dev", be_path_tap, *l));
+            disks->unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/removable", be_path_tap, *l)));
+            if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/mode", be_path_tap, *l)), "w"))
+                disks->readwrite = 1;
             else
-                disks[i].readwrite = 0;
-            type = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/device-type", libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/frontend", be_path_vbd, l[i]))));
-            disks[i].is_cdrom = !strcmp(type, "cdrom");
-        }
-        free(l);
-    }
-    *num = num_disks;
-    return disks;
+                disks->readwrite = 0;
+            type = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/device-type", libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/frontend", be_path_tap, *l))));
+            disks->is_cdrom = !strcmp(type, "cdrom");
+        }
+        libxl_free(ctx, b);
+    }
+    return ret;
+}
+
+int libxl_device_disk_getinfo(struct libxl_ctx *ctx, uint32_t domid,
+                              libxl_device_disk *disk, libxl_diskinfo 
*diskinfo)
+{
+    char *dompath, *diskpath;
+    char *val;
+
+    dompath = libxl_xs_get_dompath(ctx, domid);
+    diskinfo->devid = device_disk_dev_number(disk->virtpath);
+
+    /* tap devices entries in xenstore are written as vbd devices. */
+    diskpath = libxl_sprintf(ctx, "%s/device/vbd/%d", dompath, 
diskinfo->devid);
+    diskinfo->backend = libxl_xs_read(ctx, XBT_NULL,
+                                      libxl_sprintf(ctx, "%s/backend", 
diskpath));
+    if (!diskinfo->backend) {
+        return ERROR_FAIL;
+    }
+    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", 
diskpath));
+    diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/state", 
diskpath));
+    diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
+    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/event-channel", 
diskpath));
+    diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
+    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/ring-ref", 
diskpath));
+    diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
+    diskinfo->frontend = libxl_xs_read(ctx, XBT_NULL,
+                                       libxl_sprintf(ctx, "%s/frontend", 
diskinfo->backend));
+    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend-id", 
diskinfo->backend));
+    diskinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    return 0;
 }
 
 int libxl_cdrom_insert(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_disk *disk)
@@ -1571,6 +1852,8 @@ static int libxl_build_xenpv_qemu_args(s
         info->vnclisten = libxl_sprintf(ctx, "%s", vfb->vnclisten);
     info->vncdisplay = vfb->vncdisplay;
     info->vncunused = vfb->vncunused;
+    if (vfb->vncpasswd)
+        info->vncpasswd = vfb->vncpasswd;
     if (vfb->keymap)
         info->keymap = libxl_sprintf(ctx, "%s", vfb->keymap);
     info->sdl = vfb->sdl;
@@ -1602,7 +1885,7 @@ static int libxl_build_xenpv_qemu_args(s
     }
     info->domid = vfb->domid;
     info->dom_name = libxl_domid_to_name(ctx, vfb->domid);
-    info->device_model = "/usr/lib/xen/bin/qemu-dm";
+    info->device_model = libxl_abs_path(ctx, "qemu-dm", libxl_libexec_path());
     info->type = XENPV;
     return 0;
 }
@@ -1652,6 +1935,8 @@ int libxl_device_vfb_add(struct libxl_ct
     flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vnc));
     flexarray_set(back, boffset++, "vnclisten");
     flexarray_set(back, boffset++, vfb->vnclisten);
+    flexarray_set(back, boffset++, "vncpasswd");
+    flexarray_set(back, boffset++, vfb->vncpasswd);
     flexarray_set(back, boffset++, "vncdisplay");
     flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncdisplay));
     flexarray_set(back, boffset++, "vncunused");
@@ -1939,7 +2224,7 @@ int libxl_device_pci_add(struct libxl_ct
 
     /* TODO: check if the device can be assigned */
 
-    libxl_device_pci_flr(ctx, pcidev->domain, pcidev->bus, pcidev->dev, 
pcidev->func);
+    libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, 
pcidev->func);
 
     stubdomid = libxl_get_stubdom_id(ctx, domid);
     if (stubdomid != 0) {
@@ -1974,7 +2259,7 @@ int libxl_device_pci_add(struct libxl_ct
         char *sysfs_path = libxl_sprintf(ctx, 
SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
                                          pcidev->bus, pcidev->dev, 
pcidev->func);
         FILE *f = fopen(sysfs_path, "r");
-        unsigned int start = 0, end = 0, flags = 0, size = 0;
+        unsigned long long start = 0, end = 0, flags = 0, size = 0;
         int irq = 0;
         int i;
 
@@ -1983,18 +2268,19 @@ int libxl_device_pci_add(struct libxl_ct
             return -1;
         }
         for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
-            fscanf(f, "0x%x 0x%x 0x%x", &start, &end, &flags);
+            if (fscanf(f, "0x%llx 0x%llx 0x%llx\n", &start, &end, &flags) != 3)
+                continue;
             size = end - start + 1;
             if (start) {
                 if (flags & PCI_BAR_IO) {
                     rc = xc_domain_ioport_permission(ctx->xch, domid, start, 
size, 1);
                     if (rc < 0)
-                        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: 
xc_domain_ioport_permission error 0x%x/0x%x", start, size);
+                        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: 
xc_domain_ioport_permission error 0x%llx/0x%llx", start, size);
                 } else {
                     rc = xc_domain_iomem_permission(ctx->xch, domid, 
start>>XC_PAGE_SHIFT,
                                                     
(size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 1);
                     if (rc < 0)
-                        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: 
xc_domain_iomem_permission error 0x%x/0x%x", start, size);
+                        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: 
xc_domain_iomem_permission error 0x%llx/0x%llx", start, size);
                 }
             }
         }
@@ -2006,8 +2292,7 @@ int libxl_device_pci_add(struct libxl_ct
             XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
             goto out;
         }
-        fscanf(f, "%u", &irq);
-        if (irq) {
+        if ((fscanf(f, "%u", &irq) == 1) && irq) {
             rc = xc_physdev_map_pirq(ctx->xch, domid, irq, &irq);
             if (rc < 0) {
                 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: 
xc_physdev_map_pirq irq=%d", irq);
@@ -2071,7 +2356,8 @@ int libxl_device_pci_remove(struct libxl
             goto skip1;
         }
         for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
-            fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags);
+            if (fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags) != 3)
+                continue;
             size = end - start + 1;
             if (start) {
                 if (flags & PCI_BAR_IO) {
@@ -2095,8 +2381,7 @@ skip1:
             XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
             goto out;
         }
-        fscanf(f, "%u", &irq);
-        if (irq) {
+        if ((fscanf(f, "%u", &irq) == 1) && irq) {
             rc = xc_physdev_unmap_pirq(ctx->xch, domid, irq);
             if (rc < 0) {
                 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_physdev_map_pirq 
irq=%d", irq);
@@ -2109,7 +2394,7 @@ skip1:
         fclose(f);
     }
 out:
-    libxl_device_pci_flr(ctx, pcidev->domain, pcidev->bus, pcidev->dev, 
pcidev->func);
+    libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, 
pcidev->func);
 
     if (!libxl_is_stubdom(ctx, domid, NULL)) {
         rc = xc_deassign_device(ctx->xch, domid, pcidev->value);
@@ -2184,20 +2469,80 @@ int libxl_device_pci_shutdown(struct lib
     return 0;
 }
 
-int libxl_set_memory_target(struct libxl_ctx *ctx, uint32_t domid, uint32_t 
target_memkb)
+int libxl_domain_setmaxmem(struct libxl_ctx *ctx, uint32_t domid, uint32_t 
max_memkb)
+{
+    char *mem, *endptr;
+    uint32_t memorykb;
+    char *dompath = libxl_xs_get_dompath(ctx, domid);
+
+    mem = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/target", 
dompath));
+    if (!mem) {
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot get memory info from 
%s/memory/target\n", dompath);
+        return 1;
+    }
+    memorykb = strtoul(mem, &endptr, 10);
+    if (*endptr != '\0') {
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "invalid memory %s from 
%s/memory/target\n", mem, dompath);
+        return 1;
+    }
+
+    if (max_memkb < memorykb) {
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "memory_static_max must be greater 
than or or equal to memory_dynamic_max\n");
+        return 1;
+    }
+
+    if (domid != 0)
+        libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/memory/static-max", dompath), "%lu", max_memkb);
+
+    return 0;
+}
+
+int libxl_set_memory_target(struct libxl_ctx *ctx, uint32_t domid, uint32_t 
target_memkb, int enforce)
 {
     int rc = 0;
-    uint32_t videoram;
-    char *videoram_s = NULL;
+    uint32_t memorykb = 0, videoram = 0;
+    char *memmax, *endptr, *videoram_s = NULL;
     char *dompath = libxl_xs_get_dompath(ctx, domid);
+    xc_domaininfo_t info;
+    struct libxl_dominfo ptr;
+    char *uuid;
+
+    if (domid) {
+        memmax = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/memory/static-max", dompath));
+        if (!memmax) {
+            XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
+                "cannot get memory info from %s/memory/static-max\n", dompath);
+            return 1;
+        }
+        memorykb = strtoul(memmax, &endptr, 10);
+        if (*endptr != '\0') {
+            XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
+                "invalid max memory %s from %s/memory/static-max\n", memmax, 
dompath);
+            return 1;
+        }
+
+        if (target_memkb > memorykb) {
+            XL_LOG(ctx, XL_LOG_ERROR,
+                "memory_dynamic_max must be less than or equal to 
memory_static_max\n");
+            return 1;
+        }
+    }
 
     videoram_s = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/memory/videoram", dompath));
-    if (!videoram_s)
-        return -1;
-    videoram = atoi(videoram_s);
+    videoram = videoram_s ? atoi(videoram_s) : 0;
 
     libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/target", 
dompath), "%lu", target_memkb);
-    rc = xc_domain_setmaxmem(ctx->xch, domid, target_memkb + 
LIBXL_MAXMEM_CONSTANT);
+
+    rc = xc_domain_getinfolist(ctx->xch, domid, 1, &info);
+    if (rc != 1 || info.domain != domid)
+        return rc;
+    xcinfo2xlinfo(&info, &ptr);
+    uuid = libxl_uuid2string(ctx, ptr.uuid);
+    libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "/vm/%s/memory", uuid), 
"%lu", target_memkb / 1024);
+
+    if (enforce || !domid)
+        memorykb = target_memkb;
+    rc = xc_domain_setmaxmem(ctx->xch, domid, memorykb + 
LIBXL_MAXMEM_CONSTANT);
     if (rc != 0)
         return rc;
     rc = xc_domain_memory_set_pod_target(ctx->xch, domid, (target_memkb - 
videoram) / 4, NULL, NULL, NULL);
@@ -2221,3 +2566,446 @@ int libxl_button_press(struct libxl_ctx 
 
     return rc;
 }
+
+int libxl_get_physinfo(struct libxl_ctx *ctx, struct libxl_physinfo *physinfo)
+{
+    xc_physinfo_t xcphysinfo = { 0 };
+    int rc;
+
+    rc = xc_physinfo(ctx->xch, &xcphysinfo);
+    if (rc != 0) {
+        return rc;
+    }
+    physinfo->threads_per_core = xcphysinfo.threads_per_core;
+    physinfo->cores_per_socket = xcphysinfo.cores_per_socket;
+    physinfo->max_cpu_id = xcphysinfo.max_cpu_id;
+    physinfo->nr_cpus = xcphysinfo.nr_cpus;
+    physinfo->cpu_khz = xcphysinfo.cpu_khz;
+    physinfo->total_pages = xcphysinfo.total_pages;
+    physinfo->free_pages = xcphysinfo.free_pages;
+    physinfo->scrub_pages = xcphysinfo.scrub_pages;
+    memcpy(physinfo->hw_cap,xcphysinfo.hw_cap, sizeof(physinfo->hw_cap));
+    physinfo->phys_cap = xcphysinfo.capabilities;
+
+    return 0;
+}
+
+const libxl_version_info* libxl_get_version_info(struct libxl_ctx *ctx)
+{
+    union {
+        xen_extraversion_t xen_extra;
+        xen_compile_info_t xen_cc;
+        xen_changeset_info_t xen_chgset;
+        xen_capabilities_info_t xen_caps;
+        xen_platform_parameters_t p_parms;
+        xen_commandline_t xen_commandline;
+    } u;
+    long xen_version;
+    libxl_version_info *info = &ctx->version_info;
+
+    if (info->xen_version_extra != NULL)
+        return info;
+
+    xen_version = xc_version(ctx->xch, XENVER_version, NULL);
+    info->xen_version_major = xen_version >> 16;
+    info->xen_version_minor = xen_version & 0xFF;
+    xc_version(ctx->xch, XENVER_extraversion, &u.xen_extra);
+    info->xen_version_extra = libxl_sprintf(ctx, "%s", u.xen_extra);
+
+    xc_version(ctx->xch, XENVER_compile_info, &u.xen_cc);
+    info->compiler = libxl_sprintf(ctx, "%s", u.xen_cc.compiler);
+    info->compile_by = libxl_sprintf(ctx, "%s", u.xen_cc.compile_by);
+    info->compile_domain = libxl_sprintf(ctx, "%s", u.xen_cc.compile_domain);
+    info->compile_date = libxl_sprintf(ctx, "%s", u.xen_cc.compile_date);
+
+    xc_version(ctx->xch, XENVER_capabilities, &u.xen_caps);
+    info->capabilities = libxl_sprintf(ctx, "%s", u.xen_caps);
+
+    xc_version(ctx->xch, XENVER_changeset, &u.xen_chgset);
+    info->changeset = libxl_sprintf(ctx, "%s", u.xen_chgset);
+
+    xc_version(ctx->xch, XENVER_platform_parameters, &u.p_parms);
+    info->virt_start = u.p_parms.virt_start;
+
+    info->pagesize = xc_version(ctx->xch, XENVER_pagesize, NULL);
+
+    xc_version(ctx->xch, XENVER_commandline, &u.xen_commandline);
+    info->commandline = libxl_sprintf(ctx, "%s", u.xen_commandline);
+
+    return info;
+}
+
+struct libxl_vcpuinfo *libxl_list_vcpu(struct libxl_ctx *ctx, uint32_t domid,
+                                       int *nb_vcpu, int *cpusize)
+{
+    struct libxl_vcpuinfo *ptr, *ret;
+    xc_domaininfo_t domaininfo;
+    xc_vcpuinfo_t vcpuinfo;
+    xc_physinfo_t physinfo = { 0 };
+
+    if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
+        return NULL;
+    }
+    if (xc_physinfo(ctx->xch, &physinfo) == -1) {
+        return NULL;
+    }
+    *cpusize = physinfo.max_cpu_id + 1;
+    ptr = libxl_calloc(ctx, domaininfo.max_vcpu_id + 1, sizeof (struct 
libxl_vcpuinfo));
+    if (!ptr) {
+        return NULL;
+    }
+
+    ret = ptr;
+    for (*nb_vcpu = 0; *nb_vcpu <= domaininfo.max_vcpu_id; ++*nb_vcpu, ++ptr) {
+        ptr->cpumap = libxl_calloc(ctx, (*cpusize + 63) / 64, sizeof 
(uint64_t));
+        if (!ptr->cpumap) {
+            return NULL;
+        }
+        if (xc_vcpu_getinfo(ctx->xch, domid, *nb_vcpu, &vcpuinfo) == -1) {
+            return NULL;
+        }
+        if (xc_vcpu_getaffinity(ctx->xch, domid, *nb_vcpu, ptr->cpumap, 
*cpusize) == -1) {
+            return NULL;
+        }
+        ptr->vcpuid = *nb_vcpu;
+        ptr->cpu = vcpuinfo.cpu;
+        ptr->online = !!vcpuinfo.online;
+        ptr->blocked = !!vcpuinfo.blocked;
+        ptr->running = !!vcpuinfo.running;
+        ptr->vcpu_time = vcpuinfo.cpu_time;
+    }
+    return ret;
+}
+
+int libxl_set_vcpuaffinity(struct libxl_ctx *ctx, uint32_t domid, uint32_t 
vcpuid,
+                           uint64_t *cpumap, int cpusize)
+{
+    return (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid, cpumap, cpusize));
+}
+
+int libxl_set_vcpucount(struct libxl_ctx *ctx, uint32_t domid, uint32_t count)
+{
+    xc_domaininfo_t domaininfo;
+    char *dompath;
+    int i;
+
+    if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
+        return ERROR_FAIL;
+    }
+    if (!count || ((domaininfo.max_vcpu_id + 1) < count)) {
+        return ERROR_INVAL;
+    }
+    if (!(dompath = libxl_xs_get_dompath(ctx, domid)))
+        return ERROR_FAIL;
+
+    for (i = 0; i <= domaininfo.max_vcpu_id; ++i) {
+        libxl_xs_write(ctx, XBT_NULL,
+                       libxl_sprintf(ctx, "%s/cpu/%u/availability", dompath, 
i),
+                       "%s", ((1 << i) & ((1 << count) - 1)) ? "online" : 
"offline");
+    }
+    return 0;
+}
+
+/*
+ * returns one of the XEN_SCHEDULER_* constants from public/domctl.h
+ * or -1 if an error occured.
+ */
+int libxl_get_sched_id(struct libxl_ctx *ctx)
+{
+    int sched, ret;
+
+    if ((ret = xc_sched_id(ctx->xch, &sched)) != 0)
+        return ret;
+    return sched;
+}
+
+int libxl_sched_credit_domain_get(struct libxl_ctx *ctx, uint32_t domid, 
struct libxl_sched_credit *scinfo)
+{
+    struct xen_domctl_sched_credit sdom;
+    int rc;
+
+    rc = xc_sched_credit_domain_get(ctx->xch, domid, &sdom);
+    if (rc != 0)
+        return rc;
+
+    scinfo->weight = sdom.weight;
+    scinfo->cap = sdom.cap;
+
+    return 0;
+}
+
+int libxl_sched_credit_domain_set(struct libxl_ctx *ctx, uint32_t domid, 
struct libxl_sched_credit *scinfo)
+{
+    struct xen_domctl_sched_credit sdom;
+    xc_domaininfo_t domaininfo;
+    int rc;
+
+    rc = xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo);
+    if (rc != 1 || domaininfo.domain != domid)
+        return rc;
+
+
+    if (scinfo->weight < 1 || scinfo->weight > 65535) {
+        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
+            "Cpu weight out of range, valid values are within range from 1 to 
65535");
+        return -1;
+    }
+
+    if (scinfo->cap < 0 || scinfo->cap > (domaininfo.max_vcpu_id + 1) * 100) {
+        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
+            "Cpu cap out of range, valid range is from 0 to %d for specified 
number of vcpus",
+            ((domaininfo.max_vcpu_id + 1) * 100));
+        return -1;
+    }
+
+    sdom.weight = scinfo->weight;
+    sdom.cap = scinfo->cap;
+
+    rc = xc_sched_credit_domain_set(ctx->xch, domid, &sdom);
+    if (rc != 0)
+        return rc;
+
+    return 0;
+}
+
+static int trigger_type_from_string(char *trigger_name)
+{
+    if (!strcmp(trigger_name, "nmi"))
+        return XEN_DOMCTL_SENDTRIGGER_NMI;
+    else if (!strcmp(trigger_name, "reset"))
+        return XEN_DOMCTL_SENDTRIGGER_RESET;
+    else if (!strcmp(trigger_name, "init"))
+        return XEN_DOMCTL_SENDTRIGGER_INIT;
+    else if (!strcmp(trigger_name, "power"))
+        return XEN_DOMCTL_SENDTRIGGER_POWER;
+    else if (!strcmp(trigger_name, "sleep"))
+        return XEN_DOMCTL_SENDTRIGGER_SLEEP;
+    else
+        return -1;
+}
+
+int libxl_send_trigger(struct libxl_ctx *ctx, uint32_t domid, char 
*trigger_name, uint32_t vcpuid)
+{
+    int rc = -1;
+    int trigger_type = trigger_type_from_string(trigger_name);
+
+    if (trigger_type == -1) {
+        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
+            "Invalid trigger, valid triggers are 
<nmi|reset|init|power|sleep>");
+        return -1;
+    }
+
+    rc = xc_domain_send_trigger(ctx->xch, domid, trigger_type, vcpuid);
+    if (rc != 0)
+        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
+            "Send trigger '%s' failed", trigger_name);
+
+    return rc;
+}
+
+int libxl_send_sysrq(struct libxl_ctx *ctx, uint32_t domid, char sysrq)
+{
+    char *dompath = libxl_xs_get_dompath(ctx, domid);
+
+    libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/control/sysrq", 
dompath), "%c", sysrq);
+
+    return 0;
+}
+
+int libxl_send_debug_keys(struct libxl_ctx *ctx, char *keys)
+{
+    return xc_send_debug_keys(ctx->xch, keys);
+}
+
+struct libxl_xen_console_reader *
+    libxl_xen_console_read_start(struct libxl_ctx *ctx, int clear)
+{
+    struct libxl_xen_console_reader *cr;
+    unsigned int size = 16384;
+    char *buf = malloc(size);
+
+    if (!buf) {
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot malloc buffer for 
libxl_xen_console_reader,"
+            " size is %u", size);
+        return NULL;
+    }
+
+    cr = malloc(sizeof(struct libxl_xen_console_reader));
+    if (!cr) {
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot malloc 
libxl_xen_console_reader");
+        return NULL;
+    }
+
+    memset(cr, 0, sizeof(struct libxl_xen_console_reader));
+    cr->buffer = buf;
+    cr->size = size;
+    cr->count = size;
+    cr->clear = clear;
+    cr->incremental = 1;
+
+    return cr;
+}
+
+/* return values:                                          *line_r
+ *   1          success, whole line obtained from buffer    non-0
+ *   0          no more lines available right now           0
+ *   negative   error code ERROR_*                          0
+ * On success *line_r is updated to point to a nul-terminated
+ * string which is valid until the next call on the same console
+ * reader.  The libxl caller may overwrite parts of the string
+ * if it wishes. */
+int libxl_xen_console_read_line(struct libxl_ctx *ctx,
+                                struct libxl_xen_console_reader *cr,
+                                char **line_r)
+{
+    int ret;
+
+    memset(cr->buffer, 0, cr->size);
+    ret = xc_readconsolering(ctx->xch, &cr->buffer, &cr->count,
+                             cr->clear, cr->incremental, &cr->index);
+    if (!ret) {
+        if (cr->count) {
+            *line_r = cr->buffer;
+            ret = 1;
+        } else {
+            *line_r = NULL;
+            ret = 0;
+        }
+    }
+
+    return ret;
+}
+
+void libxl_xen_console_read_finish(struct libxl_ctx *ctx,
+                                   struct libxl_xen_console_reader *cr)
+{
+    free(cr->buffer);
+    free(cr);
+}
+
+uint32_t libxl_vm_get_start_time(struct libxl_ctx *ctx, uint32_t domid)
+{
+    char *dompath = libxl_xs_get_dompath(ctx, domid);
+    char *vm_path, *start_time;
+
+    vm_path = libxl_xs_read(
+        ctx, XBT_NULL, libxl_sprintf(ctx, "%s/vm", dompath));
+    start_time = libxl_xs_read(
+        ctx, XBT_NULL, libxl_sprintf(ctx, "%s/start_time", vm_path));
+    if (start_time == NULL) {
+        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
+                        "Can't get start time of domain '%d'", domid);
+        return -1;
+    }
+
+    return strtoul(start_time, NULL, 10);
+}
+
+char *libxl_tmem_list(struct libxl_ctx *ctx, uint32_t domid, int use_long)
+{
+    int rc;
+    char _buf[32768];
+
+    rc = xc_tmem_control(ctx->xch, -1, TMEMC_LIST, domid, 32768, use_long,
+                         0, _buf);
+    if (rc < 0) {
+        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
+            "Can not get tmem list");
+        return NULL;
+    }
+
+    return strdup(_buf);
+}
+
+int libxl_tmem_freeze(struct libxl_ctx *ctx, uint32_t domid)
+{
+    int rc;
+
+    rc = xc_tmem_control(ctx->xch, -1, TMEMC_FREEZE, domid, 0, 0,
+                         0, NULL);
+    if (rc < 0) {
+        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
+            "Can not freeze tmem pools");
+        return -1;
+    }
+
+    return rc;
+}
+
+int libxl_tmem_destroy(struct libxl_ctx *ctx, uint32_t domid)
+{
+    int rc;
+
+    rc = xc_tmem_control(ctx->xch, -1, TMEMC_DESTROY, domid, 0, 0,
+                         0, NULL);
+    if (rc < 0) {
+        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
+            "Can not destroy tmem pools");
+        return -1;
+    }
+
+    return rc;
+}
+
+int libxl_tmem_thaw(struct libxl_ctx *ctx, uint32_t domid)
+{
+    int rc;
+
+    rc = xc_tmem_control(ctx->xch, -1, TMEMC_THAW, domid, 0, 0,
+                         0, NULL);
+    if (rc < 0) {
+        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
+            "Can not thaw tmem pools");
+        return -1;
+    }
+
+    return rc;
+}
+
+static int32_t tmem_setop_from_string(char *set_name)
+{
+    if (!strcmp(set_name, "weight"))
+        return TMEMC_SET_WEIGHT;
+    else if (!strcmp(set_name, "cap"))
+        return TMEMC_SET_CAP;
+    else if (!strcmp(set_name, "compress"))
+        return TMEMC_SET_COMPRESS;
+    else
+        return -1;
+}
+
+int libxl_tmem_set(struct libxl_ctx *ctx, uint32_t domid, char* name, uint32_t 
set)
+{
+    int rc;
+    int32_t subop = tmem_setop_from_string(name);
+
+    if (subop == -1) {
+        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
+            "Invalid set, valid sets are <weight|cap|compress>");
+        return -1;
+    }
+    rc = xc_tmem_control(ctx->xch, -1, subop, domid, set, 0, 0, NULL);
+    if (rc < 0) {
+        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
+            "Can not set tmem %s", name);
+        return -1;
+    }
+
+    return rc;
+}
+
+int libxl_tmem_shared_auth(struct libxl_ctx *ctx, uint32_t domid,
+                           char* uuid, int auth)
+{
+    int rc;
+
+    rc = xc_tmem_auth(ctx->xch, domid, uuid, auth);
+    if (rc < 0) {
+        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
+            "Can not set tmem shared auth");
+        return -1;
+    }
+
+    return rc;
+}
+
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h       Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/libxl.h       Tue Jul 06 16:49:01 2010 +0100
@@ -41,6 +41,21 @@ struct libxl_vminfo {
     uint32_t domid;
 };
 
+typedef struct {
+    int xen_version_major;
+    int xen_version_minor;
+    char *xen_version_extra;
+    char *compiler;
+    char *compile_by;
+    char *compile_domain;
+    char *compile_date;
+    char *capabilities;
+    char *changeset;
+    unsigned long virt_start;
+    unsigned long pagesize;
+    char *commandline;
+} libxl_version_info;
+
 struct libxl_ctx {
     int xch;
     struct xs_handle *xsh;
@@ -56,11 +71,15 @@ struct libxl_ctx {
      * set this after libxl_init and before any other call - or
      * may leave them untouched */
     int (*waitpid_instead)(pid_t pid, int *status, int flags);
-};
+    libxl_version_info version_info;
+};
+
+const libxl_version_info* libxl_get_version_info(struct libxl_ctx *ctx);
 
 typedef struct {
     bool hvm;
     bool hap;
+    bool oos;
     int ssidref;
     char *name;
     uint8_t uuid[16];
@@ -74,6 +93,7 @@ typedef struct {
     int vpt_align;
     int max_vcpus;
     int cur_vcpus;
+    int tsc_mode;
     uint32_t max_memkb;
     uint32_t target_memkb;
     uint32_t video_memkb;
@@ -128,6 +148,7 @@ typedef struct {
     bool stdvga; /* stdvga enabled or disabled */
     bool vnc; /* vnc enabled or disabled */
     char *vnclisten; /* address:port that should be listened on for the VNC 
server if vnc is set */
+    char *vncpasswd; /* the VNC password */
     int vncdisplay; /* set VNC display number */
     bool vncunused; /* try to find an unused port for the VNC server */
     char *keymap; /* set keyboard layout, default is en-us keyboard */
@@ -139,6 +160,9 @@ typedef struct {
     bool usb; /* usb support enabled or disabled */
     char *usbdevice; /* enable usb mouse: tablet for absolute mouse, mouse for 
PS/2 protocol relative mouse */
     bool apic; /* apic enabled or disabled */
+    int vcpus; /* max number of vcpus */
+    int vcpu_avail; /* vcpus actually available */
+    int xen_platform_pci; /* enable/disable the xen platform pci device */
     char **extra; /* extra parameters pass directly to qemu, NULL terminated */
     /* Network is missing */
 } libxl_device_model_info;
@@ -149,6 +173,7 @@ typedef struct {
     int devid;
     bool vnc; /* vnc enabled or disabled */
     char *vnclisten; /* address:port that should be listened on for the VNC 
server if vnc is set */
+    char *vncpasswd; /* the VNC password */
     int vncdisplay; /* set VNC display number */
     bool vncunused; /* try to find an unused port for the VNC server */
     char *keymap; /* set keyboard layout, default is en-us keyboard */
@@ -241,6 +266,7 @@ enum {
     ERROR_NI = -3,
     ERROR_NOMEM = -4,
     ERROR_INVAL = -5,
+    ERROR_BADFAIL = -6,
 };
 
 #define LIBXL_VERSION 0
@@ -249,6 +275,7 @@ int libxl_ctx_init(struct libxl_ctx *ctx
 int libxl_ctx_init(struct libxl_ctx *ctx, int version);
 int libxl_ctx_free(struct libxl_ctx *ctx);
 int libxl_ctx_set_log(struct libxl_ctx *ctx, libxl_log_callback log_callback, 
void *log_data);
+int libxl_ctx_postfork(struct libxl_ctx *ctx);
 
 /* domain related functions */
 int libxl_domain_make(struct libxl_ctx *ctx, libxl_domain_create_info *info, 
uint32_t *domid);
@@ -262,6 +289,9 @@ int libxl_domain_shutdown(struct libxl_c
 int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req);
 int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force);
 
+char *libxl_uuid2string(struct libxl_ctx *ctx, uint8_t uuid[16]);
+  /* 0 means ERROR_ENOMEM, which we have logged */
+
 /* events handling */
 
 typedef enum {
@@ -296,15 +326,24 @@ int libxl_event_get_domain_death_info(st
 int libxl_event_get_domain_death_info(struct libxl_ctx *ctx, uint32_t domid, 
libxl_event *event, xc_domaininfo_t *info);
 int libxl_event_get_disk_eject_info(struct libxl_ctx *ctx, uint32_t domid, 
libxl_event *event, libxl_device_disk *disk);
 
+int libxl_domain_rename(struct libxl_ctx *ctx, uint32_t domid,
+                        const char *old_name, const char *new_name,
+                        xs_transaction_t trans);
+  /* if old_name is NULL, any old name is OK; otherwise we check
+   * transactionally that the domain has the old old name; if
+   * trans is not 0 we use caller's transaction and caller must do retries */
 
 int libxl_domain_pause(struct libxl_ctx *ctx, uint32_t domid);
 int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid);
 
-int libxl_set_memory_target(struct libxl_ctx *ctx, uint32_t domid, uint32_t 
target_memkb);
+int libxl_domain_setmaxmem(struct libxl_ctx *ctx, uint32_t domid, uint32_t 
target_memkb);
+int libxl_set_memory_target(struct libxl_ctx *ctx, uint32_t domid, uint32_t 
target_memkb, int enforce);
 
 int libxl_console_attach(struct libxl_ctx *ctx, uint32_t domid, int cons_num);
 
-struct libxl_dominfo * libxl_list_domain(struct libxl_ctx *ctx, int 
*nb_domain);
+int libxl_domain_info(struct libxl_ctx*, struct libxl_dominfo *info_r,
+                      uint32_t domid);
+struct libxl_dominfo * libxl_list_domain(struct libxl_ctx*, int *nb_domain);
 struct libxl_vminfo * libxl_list_vm(struct libxl_ctx *ctx, int *nb_vm);
 
 typedef struct libxl_device_model_starting libxl_device_model_starting;
@@ -325,13 +364,41 @@ int libxl_detach_device_model(struct lib
                               libxl_device_model_starting *starting);
   /* DM is detached even if error is returned */
 
+typedef struct {
+    char *backend;
+    uint32_t backend_id;
+    char *frontend;
+    uint32_t frontend_id;
+    int devid;
+    int state;
+    int evtch;
+    int rref;
+} libxl_diskinfo;
+
 int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_disk *disk);
 int libxl_device_disk_del(struct libxl_ctx *ctx, libxl_device_disk *disk, int 
wait);
 libxl_device_disk *libxl_device_disk_list(struct libxl_ctx *ctx, uint32_t 
domid, int *num);
+int libxl_device_disk_getinfo(struct libxl_ctx *ctx, uint32_t domid,
+                              libxl_device_disk *disk, libxl_diskinfo 
*diskinfo);
 int libxl_cdrom_insert(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_disk *disk);
+
+typedef struct {
+    char *backend;
+    uint32_t backend_id;
+    char *frontend;
+    uint32_t frontend_id;
+    int devid;
+    int state;
+    char *script;
+    uint8_t mac[6];
+    int evtch;
+    int rref_tx;
+    int rref_rx;
+} libxl_nicinfo;
 
 int libxl_device_nic_add(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_nic *nic);
 int libxl_device_nic_del(struct libxl_ctx *ctx, libxl_device_nic *nic, int 
wait);
+libxl_nicinfo *libxl_list_nics(struct libxl_ctx *ctx, uint32_t domid, unsigned 
int *nb);
 
 int libxl_device_console_add(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_console *console);
 
@@ -353,6 +420,37 @@ int libxl_device_pci_init(libxl_device_p
                           unsigned int bus, unsigned int dev,
                           unsigned int func, unsigned int vdevfn);
 
+/*
+ * Functions for allowing users of libxl to store private data
+ * relating to a domain.  The data is an opaque sequence of bytes and
+ * is not interpreted or used by libxl.
+ *
+ * Data is indexed by the userdata userid, which is a short printable
+ * ASCII string.  The following list is a registry of userdata userids
+ * (the registry may be updated by posting a patch to xen-devel):
+ *
+ *  userid      Data contents
+ *   "xl"        domain config file in xl format, Unix line endings
+ *
+ * libxl does not enforce the registration of userdata userids or the
+ * semantics of the data.  For specifications of the data formats
+ * see the code or documentation for the libxl caller in question.
+ */
+int libxl_userdata_store(struct libxl_ctx *ctx, uint32_t domid,
+                              const char *userdata_userid,
+                              const uint8_t *data, int datalen);
+  /* If datalen==0, data is not used and the user data for
+   * that domain and userdata_userid is deleted. */
+int libxl_userdata_retrieve(struct libxl_ctx *ctx, uint32_t domid,
+                                 const char *userdata_userid,
+                                 uint8_t **data_r, int *datalen_r);
+  /* On successful return, *data_r is from malloc.
+   * If there is no data for that domain and userdata_userid,
+   * *data_r and *datalen_r will be set to 0.
+   * data_r and datalen_r may be 0.
+   * On error return, *data_r and *datalen_r are undefined.
+   */
+
 typedef enum {
     POWER_BUTTON,
     SLEEP_BUTTON
@@ -360,5 +458,94 @@ typedef enum {
 
 int libxl_button_press(struct libxl_ctx *ctx, uint32_t domid, libxl_button 
button);
 
+struct libxl_vcpuinfo {
+    uint32_t vcpuid; /* vcpu's id */
+    uint32_t cpu; /* current mapping */
+    uint8_t online:1; /* currently online (not hotplugged)? */
+    uint8_t blocked:1; /* blocked waiting for an event? */
+    uint8_t running:1; /* currently scheduled on its CPU? */
+    uint64_t vcpu_time; /* total vcpu time ran (ns) */
+    uint64_t *cpumap; /* current cpu's affinities */
+};
+
+struct libxl_physinfo {
+    uint32_t threads_per_core;
+    uint32_t cores_per_socket;
+
+    uint32_t max_cpu_id;
+    uint32_t nr_cpus;
+    uint32_t cpu_khz;
+
+    uint64_t total_pages;
+    uint64_t free_pages;
+    uint64_t scrub_pages;
+
+    uint32_t hw_cap[8];
+    uint32_t phys_cap;
+};
+
+int libxl_get_physinfo(struct libxl_ctx *ctx, struct libxl_physinfo *physinfo);
+struct libxl_vcpuinfo *libxl_list_vcpu(struct libxl_ctx *ctx, uint32_t domid,
+                                       int *nb_vcpu, int *cpusize);
+int libxl_set_vcpuaffinity(struct libxl_ctx *ctx, uint32_t domid, uint32_t 
vcpuid,
+                           uint64_t *cpumap, int cpusize);
+int libxl_set_vcpucount(struct libxl_ctx *ctx, uint32_t domid, uint32_t count);
+
+int libxl_get_sched_id(struct libxl_ctx *ctx);
+
+
+struct libxl_sched_credit {
+    int weight;
+    int cap;
+};
+
+int libxl_sched_credit_domain_get(struct libxl_ctx *ctx, uint32_t domid,
+                                  struct libxl_sched_credit *scinfo);
+int libxl_sched_credit_domain_set(struct libxl_ctx *ctx, uint32_t domid,
+                                  struct libxl_sched_credit *scinfo);
+int libxl_send_trigger(struct libxl_ctx *ctx, uint32_t domid,
+                       char *trigger_name, uint32_t vcpuid);
+int libxl_send_sysrq(struct libxl_ctx *ctx, uint32_t domid, char sysrq);
+int libxl_send_debug_keys(struct libxl_ctx *ctx, char *keys);
+
+struct libxl_xen_console_reader {
+    char *buffer;
+    unsigned int size;
+    unsigned int count;
+    unsigned int clear;
+    unsigned int incremental;
+    unsigned int index;
+};
+
+struct libxl_xen_console_reader *
+    libxl_xen_console_read_start(struct libxl_ctx *ctx, int clear);
+int libxl_xen_console_read_line(struct libxl_ctx *ctx,
+                                struct libxl_xen_console_reader *cr,
+                                char **line_r);
+void libxl_xen_console_read_finish(struct libxl_ctx *ctx,
+                                   struct libxl_xen_console_reader *cr);
+
+uint32_t libxl_vm_get_start_time(struct libxl_ctx *ctx, uint32_t domid);
+
+char *libxl_tmem_list(struct libxl_ctx *ctx, uint32_t domid, int use_long);
+int libxl_tmem_freeze(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_tmem_destroy(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_tmem_thaw(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_tmem_set(struct libxl_ctx *ctx, uint32_t domid, char* name,
+                   uint32_t set);
+int libxl_tmem_shared_auth(struct libxl_ctx *ctx, uint32_t domid, char* uuid,
+                           int auth);
+
+/* libxl_paths.c */
+const char *libxl_sbindir_path(void);
+const char *libxl_bindir_path(void);
+const char *libxl_libexec_path(void);
+const char *libxl_libdir_path(void);
+const char *libxl_sharedir_path(void);
+const char *libxl_private_bindir_path(void);
+const char *libxl_xenfirmwaredir_path(void);
+const char *libxl_xen_config_dir_path(void);
+const char *libxl_xen_script_dir_path(void);
+
 #endif /* LIBXL_H */
 
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/libxl_device.c
--- a/tools/libxl/libxl_device.c        Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/libxl_device.c        Tue Jul 06 16:49:01 2010 +0100
@@ -22,6 +22,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <fcntl.h>
 
 #include "libxl.h"
 #include "libxl_internal.h"
@@ -301,7 +302,7 @@ int libxl_devices_destroy(struct libxl_c
     if (!l1) {
         XL_LOG(&clone, XL_LOG_ERROR, "%s is empty", path);
         libxl_ctx_free(&clone);
-        return -1;
+        return 0;
     }
     for (i = 0; i < num1; i++) {
         if (!strcmp("vfs", l1[i]))
@@ -388,22 +389,36 @@ int libxl_device_del(struct libxl_ctx *c
     return 0;
 }
 
-int libxl_device_pci_flr(struct libxl_ctx *ctx, unsigned int domain, unsigned 
int bus,
+int libxl_device_pci_reset(struct libxl_ctx *ctx, unsigned int domain, 
unsigned int bus,
                          unsigned int dev, unsigned int func)
 {
-    char *do_flr = "/sys/bus/pci/drivers/pciback/do_flr";
-    FILE *fd;
-
-    fd = fopen(do_flr, "w");
-    if (fd != NULL) {
-        fprintf(fd, PCI_BDF, domain, bus, dev, func);
-        fclose(fd);
-        return 0;
+    char *reset = "/sys/bus/pci/drivers/pciback/do_flr";
+    int fd, rc;
+
+    fd = open(reset, O_WRONLY);
+    if (fd > 0) {
+        char *buf = libxl_sprintf(ctx, PCI_BDF, domain, bus, dev, func);
+        rc = write(fd, buf, strlen(buf));
+        if (rc < 0)
+            XL_LOG(ctx, XL_LOG_ERROR, "write to %s returned %d", reset, rc);
+        close(fd);
+        return rc < 0 ? rc : 0;
+    }
+    if (errno != ENOENT)
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Failed to access pciback path %s", 
reset);
+    reset = libxl_sprintf(ctx, "/sys/bus/pci/devices/"PCI_BDF"/reset", domain, 
bus, dev, func);
+    fd = open(reset, O_WRONLY);
+    if (fd > 0) {
+        rc = write(fd, "1", 1);
+        if (rc < 0)
+            XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "write to %s returned %d", reset, 
rc);
+        close(fd);
+        return rc < 0 ? rc : 0;
     }
     if (errno == ENOENT) {
-        XL_LOG(ctx, XL_LOG_ERROR, "Pciback doesn't support do_flr, cannot flr 
the device");
+        XL_LOG(ctx, XL_LOG_ERROR, "The kernel doesn't support PCI device reset 
from sysfs");
     } else {
-        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Failed to access pciback path %s", 
do_flr);
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Failed to access reset path %s", 
reset);
     }
     return -1;
 }
@@ -417,7 +432,7 @@ int libxl_wait_for_device_model(struct l
     char *path;
     char *p;
     unsigned int len;
-    int rc;
+    int rc = 0;
     struct xs_handle *xsh;
     int nfds;
     fd_set rfds;
@@ -431,28 +446,29 @@ int libxl_wait_for_device_model(struct l
     tv.tv_sec = LIBXL_DEVICE_MODEL_START_TIMEOUT;
     tv.tv_usec = 0;
     nfds = xs_fileno(xsh) + 1;
-    while (tv.tv_sec > 0) {
+    while (rc > 0 || (!rc && tv.tv_sec > 0)) {
+        p = xs_read(xsh, XBT_NULL, path, &len);
+        if (p && (!state || !strcmp(state, p))) {
+            free(p);
+            xs_unwatch(xsh, path, path);
+            xs_daemon_close(xsh);
+            if (check_callback) {
+                rc = check_callback(ctx, check_callback_userdata);
+                if (rc) return rc;
+            }
+            return 0;
+        }
+        free(p);
+again:
         FD_ZERO(&rfds);
         FD_SET(xs_fileno(xsh), &rfds);
-        if (select(nfds, &rfds, NULL, NULL, &tv) > 0) {
+        rc = select(nfds, &rfds, NULL, NULL, &tv);
+        if (rc > 0) {
             l = xs_read_watch(xsh, &num);
-            if (l != NULL) {
+            if (l != NULL)
                 free(l);
-                p = xs_read(xsh, XBT_NULL, path, &len);
-                if (!p)
-                    continue;
-                if (!state || !strcmp(state, p)) {
-                    free(p);
-                    xs_unwatch(xsh, path, path);
-                    xs_daemon_close(xsh);
-                    if (check_callback) {
-                        rc = check_callback(ctx, check_callback_userdata);
-                        if (rc) return rc;
-                    }
-                    return 0;
-                }
-                free(p);
-            }
+            else
+                goto again;
         }
     }
     xs_unwatch(xsh, path, path);
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/libxl_dom.c
--- a/tools/libxl/libxl_dom.c   Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/libxl_dom.c   Tue Jul 06 16:49:01 2010 +0100
@@ -16,6 +16,8 @@
 #include "libxl_osdeps.h"
 
 #include <stdio.h>
+#include <assert.h>
+#include <glob.h>
 #include <inttypes.h>
 #include <string.h>
 #include <sys/time.h> /* for struct timeval */
@@ -72,6 +74,7 @@ int build_pre(struct libxl_ctx *ctx, uin
     xc_domain_set_memmap_limit(ctx->xch, domid, 
             (info->hvm) ? info->max_memkb : 
             (info->max_memkb + info->u.pv.slack_memkb));
+    xc_domain_set_tsc_info(ctx->xch, domid, info->tsc_mode, 0, 0, 0);
 
     if (info->hvm) {
         unsigned long shadow;
@@ -97,22 +100,22 @@ int build_post(struct libxl_ctx *ctx, ui
     xc_cpuid_apply_policy(ctx->xch, domid);
 #endif
 
-    ents = libxl_calloc(ctx, (10 + info->max_vcpus) * 2, sizeof(char *));
+    ents = libxl_calloc(ctx, 12 + (info->max_vcpus * 2) + 2, sizeof(char *));
     ents[0] = "memory/static-max";
     ents[1] = libxl_sprintf(ctx, "%d", info->max_memkb);
     ents[2] = "memory/target";
     ents[3] = libxl_sprintf(ctx, "%d", info->target_memkb);
-    ents[2] = "memory/videoram";
-    ents[3] = libxl_sprintf(ctx, "%d", info->video_memkb);
-    ents[4] = "domid";
-    ents[5] = libxl_sprintf(ctx, "%d", domid);
-    ents[6] = "store/port";
-    ents[7] = libxl_sprintf(ctx, "%"PRIu32, state->store_port);
-    ents[8] = "store/ring-ref";
-    ents[9] = libxl_sprintf(ctx, "%lu", state->store_mfn);
+    ents[4] = "memory/videoram";
+    ents[5] = libxl_sprintf(ctx, "%d", info->video_memkb);
+    ents[6] = "domid";
+    ents[7] = libxl_sprintf(ctx, "%d", domid);
+    ents[8] = "store/port";
+    ents[9] = libxl_sprintf(ctx, "%"PRIu32, state->store_port);
+    ents[10] = "store/ring-ref";
+    ents[11] = libxl_sprintf(ctx, "%lu", state->store_mfn);
     for (i = 0; i < info->max_vcpus; i++) {
-        ents[10+(i*2)]   = libxl_sprintf(ctx, "cpu/%d/availability", i);
-        ents[10+(i*2)+1] = (i && info->cur_vcpus && (i >= info->cur_vcpus))
+        ents[12+(i*2)]   = libxl_sprintf(ctx, "cpu/%d/availability", i);
+        ents[12+(i*2)+1] = (i && info->cur_vcpus && !(info->cur_vcpus & (1 << 
i)))
                             ? "offline" : "online";
     }
 
@@ -168,15 +171,19 @@ int build_hvm(struct libxl_ctx *ctx, uin
 {
     int ret;
 
-    ret = xc_hvm_build_target_mem(ctx->xch, domid, (info->max_memkb - 
info->video_memkb) / 1024, (info->target_memkb - info->video_memkb) / 1024, 
info->kernel);
+    ret = xc_hvm_build_target_mem(
+        ctx->xch,
+        domid,
+        (info->max_memkb - info->video_memkb) / 1024,
+        (info->target_memkb - info->video_memkb) / 1024,
+        libxl_abs_path(ctx, (char *)info->kernel,
+                       libxl_xenfirmwaredir_path()));
     if (ret) {
         XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "hvm building failed");
         return ERROR_FAIL;
     }
-    ret = hvm_build_set_params(ctx->xch, domid, info->u.hvm.apic, 
info->u.hvm.acpi,
-                               info->u.hvm.pae, info->u.hvm.nx, 
info->u.hvm.viridian,
-                               info->max_vcpus,
-                               state->store_port, &state->store_mfn);
+    ret = hvm_build_set_params(ctx->xch, domid, info, state->store_port,
+                               &state->store_mfn);
     if (ret) {
         XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "hvm build set params failed");
         return ERROR_FAIL;
@@ -189,11 +196,10 @@ int restore_common(struct libxl_ctx *ctx
                    int fd)
 {
     /* read signature */
-    xc_domain_restore(ctx->xch, fd, domid,
-                      state->store_port, &state->store_mfn,
-                      state->console_port, &state->console_mfn,
-                      info->hvm, info->u.hvm.pae, 0);
-    return 0;
+    return xc_domain_restore(ctx->xch, fd, domid,
+                             state->store_port, &state->store_mfn,
+                             state->console_port, &state->console_mfn,
+                             info->hvm, info->u.hvm.pae, 0);
 }
 
 struct suspendinfo {
@@ -340,12 +346,154 @@ int save_device_model(struct libxl_ctx *
     libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, 
"/local/domain/0/device-model/%d/command", domid), "save", strlen("save"));
     libxl_wait_for_device_model(ctx, domid, "paused", NULL, NULL);
 
-    write(fd, QEMU_SIGNATURE, strlen(QEMU_SIGNATURE));
+    c = libxl_write_exactly(ctx, fd, QEMU_SIGNATURE, strlen(QEMU_SIGNATURE),
+                            "saved-state file", "qemu signature");
+    if (c)
+        return c;
     fd2 = open(filename, O_RDONLY);
     while ((c = read(fd2, buf, sizeof(buf))) != 0) {
-        write(fd, buf, c);
+        if (c < 0) {
+            if (errno == EINTR)
+                continue;
+            return errno;
+        }
+        c = libxl_write_exactly(
+            ctx, fd, buf, c, "saved-state file", "qemu state");
+        if (c)
+            return c;
     }
     close(fd2);
     unlink(filename);
     return 0;
 }
+
+char *libxl_uuid2string(struct libxl_ctx *ctx, uint8_t uuid[16]) {
+    char *s = string_of_uuid(ctx, uuid);
+    if (!s) XL_LOG(ctx, XL_LOG_ERROR, "cannot allocate for uuid");
+    return s;
+}
+
+static const char *userdata_path(struct libxl_ctx *ctx, uint32_t domid,
+                                      const char *userdata_userid,
+                                      const char *wh) {
+    char *path, *uuid_string;
+    struct libxl_dominfo info;
+    int rc;
+
+    rc = libxl_domain_info(ctx, &info, domid);
+    if (rc) {
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unable to find domain info"
+                     " for domain %"PRIu32, domid);
+        return 0;
+    }
+    uuid_string = string_of_uuid(ctx, info.uuid);
+
+    path = libxl_sprintf(ctx, "/var/lib/xen/"
+                         "userdata-%s.%s.%s",
+                         wh, uuid_string, userdata_userid);
+    if (!path)
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unable to allocate for"
+                     " userdata path");
+    return path;
+}
+
+static int userdata_delete(struct libxl_ctx *ctx, const char *path) {
+    int r;
+    r = unlink(path);
+    if (r) {
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "remove failed for %s", path);
+        return errno;
+    }
+    return 0;
+}
+
+void libxl__userdata_destroyall(struct libxl_ctx *ctx, uint32_t domid) {
+    const char *pattern;
+    glob_t gl;
+    int r, i;
+
+    pattern = userdata_path(ctx, domid, "*", "?");
+    if (!pattern) return;
+
+    gl.gl_pathc = 0;
+    gl.gl_pathv = 0;
+    gl.gl_offs = 0;
+    r = glob(pattern, GLOB_ERR|GLOB_NOSORT|GLOB_MARK, 0, &gl);
+    if (r == GLOB_NOMATCH) return;
+    if (r) XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "glob failed for %s", pattern);
+
+    for (i=0; i<gl.gl_pathc; i++) {
+        userdata_delete(ctx, gl.gl_pathv[i]);
+    }
+    globfree(&gl);
+}
+
+int libxl_userdata_store(struct libxl_ctx *ctx, uint32_t domid,
+                              const char *userdata_userid,
+                              const uint8_t *data, int datalen) {
+    const char *filename;
+    const char *newfilename;
+    int e;
+    int fd = -1;
+    FILE *f = 0;
+    size_t rs;
+
+    filename = userdata_path(ctx, domid, userdata_userid, "d");
+    if (!filename) return ENOMEM;
+
+    if (!datalen)
+        return userdata_delete(ctx, filename);
+
+    newfilename = userdata_path(ctx, domid, userdata_userid, "n");
+    if (!newfilename) return ENOMEM;
+
+    fd= open(newfilename, O_RDWR|O_CREAT|O_TRUNC, 0600);
+    if (fd<0) goto xe;
+
+    f= fdopen(fd, "wb");
+    if (!f) goto xe;
+    fd = -1;
+
+    rs = fwrite(data, 1, datalen, f);
+    if (rs != datalen) { assert(ferror(f)); goto xe; }
+
+    if (fclose(f)) goto xe;
+    f = 0;
+
+    if (rename(newfilename,filename)) goto xe;
+
+    return 0;
+
+ xe:
+    e = errno;
+    if (f) fclose(f);
+    if (fd>=0) close(fd);
+
+    XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot write %s for %s",
+                 newfilename, filename);
+    return e;
+}
+
+int libxl_userdata_retrieve(struct libxl_ctx *ctx, uint32_t domid,
+                                 const char *userdata_userid,
+                                 uint8_t **data_r, int *datalen_r) {
+    const char *filename;
+    int e;
+    int datalen = 0;
+    void *data = 0;
+
+    filename = userdata_path(ctx, domid, userdata_userid, "d");
+    if (!filename) return ENOMEM;
+
+    e = libxl_read_file_contents(ctx, filename, data_r ? &data : 0, &datalen);
+
+    if (!e && !datalen) {
+        XL_LOG(ctx, XL_LOG_ERROR, "userdata file %s is empty", filename);
+        if (data_r) assert(!*data_r);
+        return EPROTO;
+    }
+
+    if (data_r) *data_r = data;
+    if (datalen_r) *datalen_r = datalen;
+    return 0;
+}
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/libxl_exec.c
--- a/tools/libxl/libxl_exec.c  Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/libxl_exec.c  Tue Jul 06 16:49:01 2010 +0100
@@ -30,19 +30,6 @@
 #include "libxl.h"
 #include "libxl_internal.h"
 
-static pid_t libxl_fork(struct libxl_ctx *ctx)
-{
-    pid_t pid;
-
-    pid = fork();
-    if (pid == -1) {
-        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "fork failed");
-        return -1;
-    }
-
-    return pid;
-}
-
 static int call_waitpid(pid_t (*waitpid_cb)(pid_t, int *, int), pid_t pid, int 
*status, int options)
 {
     return (waitpid_cb) ? waitpid_cb(pid, status, options) : waitpid(pid, 
status, options);
@@ -61,38 +48,41 @@ void libxl_exec(int stdinfd, int stdoutf
         dup2(stderrfd, STDERR_FILENO);
     for (i = 4; i < 256; i++)
         close(i);
+
+    signal(SIGPIPE, SIG_DFL);
+    /* in case our caller set it to IGN.  subprocesses are entitled
+     * to assume they got DFL. */
+
     execv(arg0, args);
     _exit(-1);
 }
 
-void libxl_report_child_exitstatus(struct libxl_ctx *ctx,
+void libxl_report_child_exitstatus(struct libxl_ctx *ctx, int level,
                                    const char *what, pid_t pid, int status)
 {
-    /* treats all exit statuses as errors; if that's not what you want,
-     * check status yourself first */
 
     if (WIFEXITED(status)) {
         int st = WEXITSTATUS(status);
         if (st)
-            XL_LOG(ctx, XL_LOG_ERROR, "%s [%ld] exited"
+            XL_LOG(ctx, level, "%s [%ld] exited"
                    " with error status %d", what, (unsigned long)pid, st);
         else
-            XL_LOG(ctx, XL_LOG_ERROR, "%s [%ld] unexpectedly"
+            XL_LOG(ctx, level, "%s [%ld] unexpectedly"
                    " exited status zero", what, (unsigned long)pid);
     } else if (WIFSIGNALED(status)) {
         int sig = WTERMSIG(status);
         const char *str = strsignal(sig);
         const char *coredump = WCOREDUMP(status) ? " (core dumped)" : "";
         if (str)
-            XL_LOG(ctx, XL_LOG_ERROR, "%s [%ld] died due to"
+            XL_LOG(ctx, level, "%s [%ld] died due to"
                    " fatal signal %s%s", what, (unsigned long)pid,
                    str, coredump);
         else
-            XL_LOG(ctx, XL_LOG_ERROR, "%s [%ld] died due to unknown"
+            XL_LOG(ctx, level, "%s [%ld] died due to unknown"
                    " fatal signal number %d%s", what, (unsigned long)pid,
                    sig, coredump);
     } else {
-        XL_LOG(ctx, XL_LOG_ERROR, "%s [%ld] gave unknown"
+        XL_LOG(ctx, level, "%s [%ld] gave unknown"
                " wait status 0x%x", what, (unsigned long)pid, status);
     }
 }
@@ -153,7 +143,7 @@ static void report_spawn_intermediate_st
         char *intermediate_what = libxl_sprintf(ctx,
                           "%s intermediate process (startup monitor)",
                           for_spawn->what);
-        libxl_report_child_exitstatus(ctx, intermediate_what,
+        libxl_report_child_exitstatus(ctx, XL_LOG_ERROR, intermediate_what,
                                       for_spawn->intermediate, status);
     }
 }
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/libxl_internal.c
--- a/tools/libxl/libxl_internal.c      Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/libxl_internal.c      Tue Jul 06 16:49:01 2010 +0100
@@ -156,10 +156,12 @@ void xl_logv(struct libxl_ctx *ctx, int 
 {
     char *enomem = "[out of memory formatting log message]";
     char *s;
-    int rc;
+    int rc, esave;
 
     if (!ctx->log_callback)
         return;
+
+    esave = errno;
 
     rc = vasprintf(&s, fmt, ap);
     if (rc<0) { s = enomem; goto x; }
@@ -180,6 +182,7 @@ void xl_logv(struct libxl_ctx *ctx, int 
     ctx->log_callback(ctx->log_userdata, loglevel, file, line, func, s);
     if (s != enomem)
         free(s);
+    errno = esave;
 }
 
 void xl_log(struct libxl_ctx *ctx, int loglevel, int errnoval,
@@ -191,3 +194,11 @@ void xl_log(struct libxl_ctx *ctx, int l
     xl_logv(ctx, loglevel, errnoval, file, line, func, fmt, ap);
     va_end(ap);
 }
+
+char *libxl_abs_path(struct libxl_ctx *ctx, char *s, const char *path)
+{
+    if (!s || s[0] == '/')
+        return s;
+    return libxl_sprintf(ctx, "%s/%s", path, s);
+}
+
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h      Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/libxl_internal.h      Tue Jul 06 16:49:01 2010 +0100
@@ -41,21 +41,18 @@
 #ifdef XL_LOGGING_ENABLED
 #define XL_LOG(ctx, loglevel, _f, _a...)   xl_log(ctx, loglevel, -1, __FILE__, 
__LINE__, __func__, _f, ##_a)
 #define XL_LOG_ERRNO(ctx, loglevel, _f, _a...)   xl_log(ctx, loglevel, errno, 
__FILE__, __LINE__, __func__, _f, ##_a)
-#define XL_LOG_ERRNOVAL(ctx, errnoval, loglevel, _f, _a...)   xl_log(ctx, 
loglevel, errnoval, __FILE__, __LINE__, __func__, _f, ##_a)
+#define XL_LOG_ERRNOVAL(ctx, loglevel, errnoval, _f, _a...)   xl_log(ctx, 
loglevel, errnoval, __FILE__, __LINE__, __func__, _f, ##_a)
 #else
 #define XL_LOG(ctx, loglevel, _f, _a...)
 #define XL_LOG_ERRNO(ctx, loglevel, _f, _a...)
 #define XL_LOG_ERRNOVAL(ctx, loglevel, errnoval, _f, _a...)
 #endif
-
-#define XL_LOG_DEBUG 3
-#define XL_LOG_INFO 2
-#define XL_LOG_WARNING 1
-#define XL_LOG_ERROR 0
+  /* all of these macros preserve errno (saving and restoring) */
 
 /* logging */
 void xl_logv(struct libxl_ctx *ctx, int errnoval, int loglevel, const char 
*file, int line, const char *func, char *fmt, va_list al);
 void xl_log(struct libxl_ctx *ctx, int errnoval, int loglevel, const char 
*file, int line, const char *func, char *fmt, ...);
+  /* these functions preserve errno (saving and restoring) */
 
 
 typedef enum {
@@ -133,6 +130,7 @@ int restore_common(struct libxl_ctx *ctx
                    libxl_domain_build_info *info, libxl_domain_build_state 
*state, int fd);
 int core_suspend(struct libxl_ctx *ctx, uint32_t domid, int fd, int hvm, int 
live, int debug);
 int save_device_model(struct libxl_ctx *ctx, uint32_t domid, int fd);
+void libxl__userdata_destroyall(struct libxl_ctx *ctx, uint32_t domid);
 
 /* from xl_device */
 char *device_disk_backend_type_of_phystype(libxl_disk_phystype phystype);
@@ -152,13 +150,13 @@ int libxl_wait_for_device_model(struct l
                                                       void *userdata),
                                 void *check_callback_userdata);
 int libxl_wait_for_backend(struct libxl_ctx *ctx, char *be_path, char *state);
-int libxl_device_pci_flr(struct libxl_ctx *ctx, unsigned int domain, unsigned 
int bus,
-                         unsigned int dev, unsigned int func);
+int libxl_device_pci_reset(struct libxl_ctx *ctx, unsigned int domain, 
unsigned int bus,
+                           unsigned int dev, unsigned int func);
 
 /* from xenguest (helper */
 int hvm_build_set_params(int handle, uint32_t domid,
-                         int apic, int acpi, int pae, int nx, int viridian,
-                         int vcpus, int store_evtchn, unsigned long 
*store_mfn);
+                         libxl_domain_build_info *info,
+                         int store_evtchn, unsigned long *store_mfn);
 
 /* xl_exec */
 
@@ -183,8 +181,8 @@ int libxl_spawn_spawn(struct libxl_ctx *
                       void (*intermediate_hook)(void *for_spawn, pid_t 
innerchild));
   /* Logs errors.  A copy of "what" is taken.  Return values:
    *  < 0   error, for_spawn need not be detached
-   *   +1   caller is now the inner child, should probably call libxl_exec
-   *    0   caller is the parent, must call detach on *for_spawn eventually
+   *   +1   caller is the parent, must call detach on *for_spawn eventually
+   *    0   caller is now the inner child, should probably call libxl_exec
    * Caller, may pass 0 for for_spawn, in which case no need to detach.
    */
 int libxl_spawn_detach(struct libxl_ctx *ctx,
@@ -204,5 +202,7 @@ void libxl_log_child_exitstatus(struct l
 void libxl_log_child_exitstatus(struct libxl_ctx *ctx,
                                 const char *what, pid_t pid, int status);
 
+char *libxl_abs_path(struct libxl_ctx *ctx, char *s, const char *path);
+
 #endif
 
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/libxl_paths.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_paths.c Tue Jul 06 16:49:01 2010 +0100
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010      Citrix Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "_libxl_paths.h"
+
+const char *libxl_sbindir_path(void)
+{
+    return SBINDIR;
+}
+
+const char *libxl_bindir_path(void)
+{
+    return BINDIR;
+}
+
+const char *libxl_libexec_path(void)
+{
+    return LIBEXEC;
+}
+
+const char *libxl_libdir_path(void)
+{
+    return LIBDIR;
+}
+
+const char *libxl_sharedir_path(void)
+{
+    return SHAREDIR;
+}
+
+const char *libxl_private_bindir_path(void)
+{
+    return PRIVATE_BINDIR;
+}
+
+const char *libxl_xenfirmwaredir_path(void)
+{
+    return XENFIRMWAREDIR;
+}
+
+const char *libxl_xen_config_dir_path(void)
+{
+    return XEN_CONFIG_DIR;
+}
+
+const char *libxl_xen_script_dir_path(void)
+{
+    return XEN_SCRIPT_DIR;
+}
+
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/libxl_utils.c
--- a/tools/libxl/libxl_utils.c Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/libxl_utils.c Tue Jul 06 16:49:01 2010 +0100
@@ -26,6 +26,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <assert.h>
 
 #include "libxl_utils.h"
 #include "libxl_internal.h"
@@ -54,7 +55,8 @@ char *libxl_domid_to_name(struct libxl_c
     return s;
 }
 
-int libxl_name_to_domid(struct libxl_ctx *ctx, char *name, uint32_t *domid)
+int libxl_name_to_domid(struct libxl_ctx *ctx, const char *name,
+                        uint32_t *domid)
 {
     int i, nb_domains;
     char *domname;
@@ -74,6 +76,20 @@ int libxl_name_to_domid(struct libxl_ctx
         }
     }
     return -1;
+}
+
+char *libxl_poolid_to_name(struct libxl_ctx *ctx, uint32_t poolid)
+{
+    unsigned int len;
+    char path[strlen("/local/pool") + 12];
+    char *s;
+
+    if (poolid == 0)
+        return "Pool-0";
+    snprintf(path, sizeof(path), "/local/pool/%d/name", poolid);
+    s = xs_read(ctx->xsh, XBT_NULL, path, &len);
+    libxl_ptr_add(ctx, s);
+    return s;
 }
 
 int libxl_get_stubdom_id(struct libxl_ctx *ctx, int guest_domid)
@@ -101,11 +117,25 @@ int libxl_is_stubdom(struct libxl_ctx *c
     return 1;
 }
 
+static int logrename(struct libxl_ctx *ctx, const char *old, const char *new) {
+    int r;
+
+    r = rename(old, new);
+    if (r) {
+        if (errno == ENOENT) return 0; /* ok */
+
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to rotate logfile - could not"
+                     " rename %s to %s", old, new);
+        return ERROR_FAIL;
+    }
+    return 0;
+}
+
 int libxl_create_logfile(struct libxl_ctx *ctx, char *name, char **full_name)
 {
     struct stat stat_buf;
     char *logfile, *logfile_new;
-    int i;
+    int i, rc;
 
     logfile = libxl_sprintf(ctx, "/var/log/xen/%s.log", name);
     if (stat(logfile, &stat_buf) == 0) {
@@ -115,11 +145,19 @@ int libxl_create_logfile(struct libxl_ct
         for (i = 9; i > 0; i--) {
             logfile = libxl_sprintf(ctx, "/var/log/xen/%s.log.%d", name, i);
             logfile_new = libxl_sprintf(ctx, "/var/log/xen/%s.log.%d", name, i 
+ 1);
-            rename(logfile, logfile_new);
+            rc = logrename(ctx, logfile, logfile_new);
+            if (rc) return rc;
         }
         logfile = libxl_sprintf(ctx, "/var/log/xen/%s.log", name);
         logfile_new = libxl_sprintf(ctx, "/var/log/xen/%s.log.1", name);
-        rename(logfile, logfile_new);
+
+        rc = logrename(ctx, logfile, logfile_new);
+        if (rc) return rc;
+    } else {
+        if (errno != ENOENT)
+            XL_LOG_ERRNO(ctx, XL_LOG_WARNING, "problem checking existence of"
+                         " logfile %s, which might have needed to be rotated",
+                         name);
     }
     *full_name = strdup(logfile);
     return 0;
@@ -155,3 +193,254 @@ out:
     return rc;
 }
 
+int libxl_read_file_contents(struct libxl_ctx *ctx, const char *filename,
+                             void **data_r, int *datalen_r) {
+    FILE *f = 0;
+    uint8_t *data = 0;
+    int datalen = 0;
+    int e;
+    struct stat stab;
+    ssize_t rs;
+
+    f = fopen(filename, "r");
+    if (!f) {
+        if (errno == ENOENT) return ENOENT;
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to open %s", filename);
+        goto xe;
+    }
+
+    if (fstat(fileno(f), &stab)) {
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to fstat %s", filename);
+        goto xe;
+    }
+
+    if (!S_ISREG(stab.st_mode)) {
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "%s is not a plain file", filename);
+        errno = ENOTTY;
+        goto xe;
+    }
+
+    if (stab.st_size > INT_MAX) {
+        XL_LOG(ctx, XL_LOG_ERROR, "file %s is far too large", filename);
+        errno = EFBIG;
+        goto xe;
+    }
+
+    datalen = stab.st_size;
+
+    if (stab.st_size && data_r) {
+        data = malloc(datalen);
+        if (!data) goto xe;
+
+        rs = fread(data, 1, datalen, f);
+        if (rs != datalen) {
+            if (ferror(f))
+                XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to read %s", filename);
+            else if (feof(f))
+                XL_LOG(ctx, XL_LOG_ERROR, "%s changed size while we"
+                       " were reading it", filename);
+            else
+                abort();
+            goto xe;
+        }
+    }
+
+    if (fclose(f)) {
+        f = 0;
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to close %s", filename);
+        goto xe;
+    }
+
+    if (data_r) *data_r = data;
+    if (datalen_r) *datalen_r = datalen;
+
+    return 0;
+
+ xe:
+    e = errno;
+    assert(e != ENOENT);
+    if (f) fclose(f);
+    if (data) free(data);
+    return e;
+}
+
+#define READ_WRITE_EXACTLY(rw, zero_is_eof, constdata)                    \
+                                                                          \
+  int libxl_##rw##_exactly(struct libxl_ctx *ctx, int fd,                 \
+                           constdata void *data, ssize_t sz,              \
+                           const char *filename, const char *what) {      \
+      ssize_t got;                                                        \
+                                                                          \
+      while (sz > 0) {                                                    \
+          got = rw(fd, data, sz);                                         \
+          if (got == -1) {                                                \
+              if (errno == EINTR) continue;                               \
+              if (!ctx) return errno;                                     \
+              XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to " #rw " %s%s%s", \
+                           what?what:"", what?" from ":"", filename);     \
+              return errno;                                               \
+          }                                                               \
+          if (got == 0) {                                                 \
+              if (!ctx) return EPROTO;                                    \
+              XL_LOG(ctx, XL_LOG_ERROR,                                   \
+                     zero_is_eof                                          \
+                     ? "file/stream truncated reading %s%s%s"             \
+                     : "file/stream write returned 0! writing %s%s%s",    \
+                     what?what:"", what?" from ":"", filename);           \
+              return EPROTO;                                              \
+          }                                                               \
+          sz -= got;                                                      \
+          data = (char*)data + got;                                       \
+      }                                                                   \
+      return 0;                                                           \
+  }
+
+READ_WRITE_EXACTLY(read, 1, /* */)
+READ_WRITE_EXACTLY(write, 0, const)
+
+
+int libxl_ctx_postfork(struct libxl_ctx *ctx) {
+    if (ctx->xsh) xs_daemon_destroy_postfork(ctx->xsh);
+    ctx->xsh = xs_daemon_open();
+    if (!ctx->xsh) return ERROR_FAIL;
+    return 0;
+}
+
+pid_t libxl_fork(struct libxl_ctx *ctx)
+{
+    pid_t pid;
+
+    pid = fork();
+    if (pid == -1) {
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "fork failed");
+        return -1;
+    }
+
+    if (!pid) {
+        if (ctx->xsh) xs_daemon_destroy_postfork(ctx->xsh);
+        ctx->xsh = 0;
+        /* This ensures that anyone who forks but doesn't exec,
+         * and doesn't reinitialise the libxl_ctx, is OK.
+         * It also means they can safely call libxl_ctx_free. */
+    }
+
+    return pid;
+}
+
+int libxl_pipe(struct libxl_ctx *ctx, int pipes[2])
+{
+    if (pipe(pipes) < 0) {
+        XL_LOG(ctx, XL_LOG_ERROR, "Failed to create a pipe");
+        return -1;
+    }
+    return 0;
+}
+
+int libxl_mac_to_device_nic(struct libxl_ctx *ctx, uint32_t domid,
+                            const char *mac, libxl_device_nic *nic)
+{
+    libxl_nicinfo *nics;
+    unsigned int nb, i;
+    uint8_t mac_n[6];
+    uint8_t *a, *b;
+    const char *tok;
+    char *endptr;
+
+    nics = libxl_list_nics(ctx, domid, &nb);
+    if (!nics) {
+        return ERROR_FAIL;
+    }
+
+    for (i = 0, tok = mac; *tok && (i < 6); ++i, tok += 3) {
+        mac_n[i] = strtol(tok, &endptr, 16);
+        if (endptr != (tok + 2)) {
+            return ERROR_INVAL;
+        }
+    }
+    memset(nic, 0, sizeof (libxl_device_nic));
+    for (; nb; --nb, ++nics) {
+        for (i = 0, a = nics->mac, b = mac_n;
+             (b < mac_n + 6) && (*a == *b); ++a, ++b)
+            ;
+        if ((b >= mac_n + 6) && (*a == *b)) {
+            nic->backend_domid = nics->backend_id;
+            nic->domid = nics->frontend_id;
+            nic->devid = nics->devid;
+            memcpy(nic->mac, nics->mac, sizeof (nic->mac));
+            nic->script = nics->script;
+            libxl_free(ctx, nics);
+            return 0;
+        }
+    }
+
+    libxl_free(ctx, nics);
+    return 0;
+}
+
+int libxl_devid_to_device_nic(struct libxl_ctx *ctx, uint32_t domid,
+                              const char *devid, libxl_device_nic *nic)
+{
+    char *tok, *val;
+    char *dompath, *nic_path_fe, *nic_path_be;
+    unsigned int i;
+
+    memset(nic, 0, sizeof (libxl_device_nic));
+    dompath = libxl_xs_get_dompath(ctx, domid);
+    if (!dompath) {
+        return ERROR_FAIL;
+    }
+    nic_path_fe = libxl_sprintf(ctx, "%s/device/vif/%s", dompath, devid);
+    nic_path_be = libxl_xs_read(ctx, XBT_NULL,
+                                libxl_sprintf(ctx, "%s/backend", nic_path_fe));
+    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", 
nic_path_fe));
+    nic->backend_domid = strtoul(val, NULL, 10);
+    nic->devid = strtoul(devid, NULL, 10);
+    libxl_free(ctx, val);
+
+    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/mac", 
nic_path_fe));
+    for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
+         ++i, tok = strtok(NULL, ":")) {
+        nic->mac[i] = strtoul(tok, NULL, 16);
+    }
+    libxl_free(ctx, val);
+    nic->script = libxl_xs_read(ctx, XBT_NULL,
+                                libxl_sprintf(ctx, "%s/script", nic_path_be));
+    libxl_free(ctx, nic_path_fe);
+    libxl_free(ctx, nic_path_be);
+    return 0;
+}
+
+int libxl_devid_to_device_disk(struct libxl_ctx *ctx, uint32_t domid,
+                               const char *devid, libxl_device_disk *disk)
+{
+    char *endptr, *val;
+    char *dompath, *diskpath, *be_path;
+    unsigned int devid_n;
+
+    devid_n = strtoul(devid, &endptr, 10);
+    if (devid == endptr) {
+        return ERROR_INVAL;
+    }
+    dompath = libxl_xs_get_dompath(ctx, domid);
+    diskpath = libxl_sprintf(ctx, "%s/device/vbd/%s", dompath, devid);
+    if (!diskpath) {
+        return ERROR_FAIL;
+    }
+
+    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", 
diskpath));
+    disk->backend_domid = strtoul(val, NULL, 10);
+    disk->domid = domid;
+    be_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend", 
diskpath));
+    disk->physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/params", be_path));
+    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/type", be_path));
+    libxl_string_to_phystype(ctx, val, &(disk->phystype));
+    disk->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev", 
be_path));
+    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/removable", 
be_path));
+    disk->unpluggable = !strcmp(val, "1");
+    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/mode", be_path));
+    disk->readwrite = !!strcmp(val, "w");
+    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/device-type", 
diskpath));
+    disk->is_cdrom = !strcmp(val, "cdrom");
+
+    return 0;
+}
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/libxl_utils.h
--- a/tools/libxl/libxl_utils.h Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/libxl_utils.h Tue Jul 06 16:49:01 2010 +0100
@@ -19,12 +19,55 @@
 #include "libxl.h"
 
 unsigned long libxl_get_required_shadow_memory(unsigned long maxmem_kb, 
unsigned int smp_cpus);
-int libxl_name_to_domid(struct libxl_ctx *ctx, char *name, uint32_t *domid);
+int libxl_name_to_domid(struct libxl_ctx *ctx, const char *name, uint32_t 
*domid);
 char *libxl_domid_to_name(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_name_to_poolid(struct libxl_ctx *ctx, const char *name, uint32_t 
*poolid);
+char *libxl_poolid_to_name(struct libxl_ctx *ctx, uint32_t poolid);
 int libxl_get_stubdom_id(struct libxl_ctx *ctx, int guest_domid);
 int libxl_is_stubdom(struct libxl_ctx *ctx, uint32_t domid, uint32_t 
*target_domid);
 int libxl_create_logfile(struct libxl_ctx *ctx, char *name, char **full_name);
 int libxl_string_to_phystype(struct libxl_ctx *ctx, char *s, 
libxl_disk_phystype *phystype);
 
+int libxl_read_file_contents(struct libxl_ctx *ctx, const char *filename,
+                             void **data_r, int *datalen_r);
+  /* Reads the contents of the plain file filename into a mallocd
+   * buffer.  Returns 0 or errno.  Any errors other than ENOENT are logged.
+   * If the file is empty, *data_r and *datalen_r are set to 0.
+   * On error, *data_r and *datalen_r are undefined.
+   * data_r and/or datalen_r may be 0.
+   */
+
+int libxl_read_exactly(struct libxl_ctx *ctx, int fd, void *data, ssize_t sz,
+                       const char *filename, const char *what);
+int libxl_write_exactly(struct libxl_ctx *ctx, int fd, const void *data,
+                        ssize_t sz, const char *filename, const char *what);
+  /* Returns 0 or errno.  If file is truncated on reading, returns
+   * EPROTO and you have no way to tell how much was read.  Errors are
+   * logged using filename (which is only used for logging) and what
+   * (which may be 0). */
+
+pid_t libxl_fork(struct libxl_ctx *ctx);
+int libxl_pipe(struct libxl_ctx *ctx, int pipes[2]);
+  /* Just like fork(2), pipe(2), but log errors. */
+
+void libxl_report_child_exitstatus(struct libxl_ctx *ctx, int level,
+                                   const char *what, pid_t pid, int status);
+    /* treats all exit statuses as errors; if that's not what you want,
+     * check status yourself first */
+
+int libxl_mac_to_device_nic(struct libxl_ctx *ctx, uint32_t domid,
+                            const char *mac, libxl_device_nic *nic);
+int libxl_devid_to_device_nic(struct libxl_ctx *ctx, uint32_t domid,
+                              const char *devid, libxl_device_nic *nic);
+
+int libxl_devid_to_device_disk(struct libxl_ctx *ctx, uint32_t domid,
+                               const char *devid, libxl_device_disk *disk);
+
+/* log levels: */
+#define XL_LOG_DEBUG 3
+#define XL_LOG_INFO 2
+#define XL_LOG_WARNING 1
+#define XL_LOG_ERROR 0
+
 #endif
 
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/libxl_xshelp.c
--- a/tools/libxl/libxl_xshelp.c        Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/libxl_xshelp.c        Tue Jul 06 16:49:01 2010 +0100
@@ -19,6 +19,7 @@
 #include <stddef.h>
 #include <stdio.h>
 #include <stdarg.h>
+#include <inttypes.h>
 
 #include "libxl.h"
 #include "libxl_internal.h"
@@ -32,7 +33,8 @@ int xs_writev(struct xs_handle *xsh, xs_
         return 0;
 
     for (i = 0; kvs[i] != NULL; i += 2) {
-        asprintf(&path, "%s/%s", dir, kvs[i]);
+        if (asprintf(&path, "%s/%s", dir, kvs[i]) < 0)
+            return -1;
         if (path && kvs[i + 1]) {
             int length = strlen(kvs[i + 1]);
             xs_write(xsh, t, path, kvs[i + 1], length);
@@ -118,7 +120,7 @@ char *libxl_xs_get_dompath(struct libxl_
 {
     char *s = xs_get_domain_path(ctx->xsh, domid);
     if (!s) {
-        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to get dompath for %lu",
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to get dompath for %" PRIu32,
                      domid);
         return NULL;
     }
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/libxlu_cfg.c
--- a/tools/libxl/libxlu_cfg.c  Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/libxlu_cfg.c  Tue Jul 06 16:49:01 2010 +0100
@@ -49,6 +49,43 @@ int xlu_cfg_readfile(XLU_Config *cfg, co
 
     xlu__cfg_yylex_destroy(ctx.scanner);
     fclose(f);
+
+    return ctx.err;
+}
+
+int xlu_cfg_readdata(XLU_Config *cfg, const char *data, int length) {
+    CfgParseContext ctx;
+    int e, r;
+    YY_BUFFER_STATE buf= 0;
+
+    ctx.scanner= 0;
+    ctx.cfg= cfg;
+    ctx.err= 0;
+    ctx.lexerrlineno= -1;
+
+    e= xlu__cfg_yylex_init_extra(&ctx, &ctx.scanner);
+    if (e) {
+        fprintf(cfg->report,"%s: unable to create scanner: %s\n",
+                cfg->filename, strerror(e));
+        ctx.err= e;
+        ctx.scanner= 0;
+        goto xe;
+    }
+
+    buf = xlu__cfg_yy_scan_bytes(data, length, ctx.scanner);
+    if (!buf) {
+        fprintf(cfg->report,"%s: unable to allocate scanner buffer\n",
+                cfg->filename);
+        ctx.err= ENOMEM;
+        goto xe;
+    }
+
+    r= xlu__cfg_yyparse(&ctx);
+    if (r) assert(ctx.err);
+
+ xe:
+    if (buf) xlu__cfg_yy_delete_buffer(buf, ctx.scanner);
+    if (ctx.scanner) xlu__cfg_yylex_destroy(ctx.scanner);
 
     return ctx.err;
 }
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/libxlutil.h
--- a/tools/libxl/libxlutil.h   Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/libxlutil.h   Tue Jul 06 16:49:01 2010 +0100
@@ -30,7 +30,8 @@ XLU_Config *xlu_cfg_init(FILE *report, c
    *  until the Config is destroyed. */
 
 int xlu_cfg_readfile(XLU_Config*, const char *real_filename);
-  /* If this fails, then it is undefined behaviour to call xlu_cfg_get_...
+int xlu_cfg_readdata(XLU_Config*, const char *data, int length);
+  /* If these fail, then it is undefined behaviour to call xlu_cfg_get_...
    * functions.  You have to just xlu_cfg_destroy. */
  
 void xlu_cfg_destroy(XLU_Config*);
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/xenguest.c
--- a/tools/libxl/xenguest.c    Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/xenguest.c    Tue Jul 06 16:49:01 2010 +0100
@@ -17,10 +17,13 @@
 #include <xenguest.h>
 #include <sys/mman.h>
 #include <xen/hvm/hvm_info_table.h>
+#include <string.h>
+
+#include "libxl.h"
 
 int hvm_build_set_params(int handle, uint32_t domid,
-                         int apic, int acpi, int pae, int nx, int viridian,
-                         int vcpus, int store_evtchn, unsigned long *store_mfn)
+                         libxl_domain_build_info *info,
+                         int store_evtchn, unsigned long *store_mfn)
 {
     struct hvm_info_table *va_hvm;
     uint8_t *va_map, sum;
@@ -33,18 +36,19 @@ int hvm_build_set_params(int handle, uin
         return -1;
 
     va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET);
-    va_hvm->acpi_enabled = acpi;
-    va_hvm->apic_mode = apic;
-    va_hvm->nr_vcpus = vcpus;
+    va_hvm->acpi_enabled = info->u.hvm.acpi;
+    va_hvm->apic_mode = info->u.hvm.apic;
+    va_hvm->nr_vcpus = info->max_vcpus;
+    memcpy(va_hvm->vcpu_online, &info->cur_vcpus, sizeof(info->cur_vcpus));
     for (i = 0, sum = 0; i < va_hvm->length; i++)
         sum += ((uint8_t *) va_hvm)[i];
     va_hvm->checksum -= sum;
     munmap(va_map, XC_PAGE_SIZE);
 
     xc_get_hvm_param(handle, domid, HVM_PARAM_STORE_PFN, store_mfn);
-    xc_set_hvm_param(handle, domid, HVM_PARAM_PAE_ENABLED, pae);
+    xc_set_hvm_param(handle, domid, HVM_PARAM_PAE_ENABLED, info->u.hvm.pae);
 #if defined(__i386__) || defined(__x86_64__)
-    xc_set_hvm_param(handle, domid, HVM_PARAM_VIRIDIAN, viridian);
+    xc_set_hvm_param(handle, domid, HVM_PARAM_VIRIDIAN, info->u.hvm.viridian);
 #endif
     xc_set_hvm_param(handle, domid, HVM_PARAM_STORE_EVTCHN, store_evtchn);
     return 0;
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/xl.c
--- a/tools/libxl/xl.c  Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/libxl/xl.c  Tue Jul 06 16:49:01 2010 +0100
@@ -21,1752 +21,55 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/time.h> /* for time */
-#include <getopt.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <arpa/inet.h>
-#include <xenctrl.h>
 #include <ctype.h>
+#include <inttypes.h>
 
 #include "libxl.h"
 #include "libxl_utils.h"
-#include "libxlutil.h"
+#include "xl.h"
 
-#define UUID_FMT 
"%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
+extern struct libxl_ctx ctx;
+extern int logfile;
 
-int logfile = 2;
-
-void log_callback(void *userdata, int loglevel, const char *file, int line, 
const char *func, char *s)
+void log_callback(
+    void *userdata, int loglevel, const char *file,
+    int line, const char *func, char *s)
 {
     char str[1024];
 
-    snprintf(str, sizeof(str), "[%d] %s:%d:%s: %s\n", loglevel, file, line, 
func, s);
-    write(logfile, str, strlen(str));
-}
-
-static int domain_qualifier_to_domid(struct libxl_ctx *ctx, char *p, uint32_t 
*domid)
-{
-    int i, alldigit;
-
-    alldigit = 1;
-    for (i = 0; p[i]; i++) {
-        if (!isdigit((uint8_t)p[i])) {
-            alldigit = 0;
-            break;
-        }
-    }
-
-    if (i > 0 && alldigit) {
-        *domid = strtoul(p, NULL, 10);
-        return 0;
-    } else {
-        /* check here if it's a uuid and do proper conversion */
-    }
-    return libxl_name_to_domid(ctx, p, domid);
-}
-
-#define LOG(_f, _a...)   dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
-
-void dolog(const char *file, int line, const char *func, char *fmt, ...)
-{
-    va_list ap;
-    char *s;
-    int rc;
-
-    va_start(ap, fmt);
-    rc = vasprintf(&s, fmt, ap);
-    va_end(ap);
-    if (rc >= 0)
-        write(logfile, s, rc);
-}
-
-static void init_create_info(libxl_domain_create_info *c_info)
-{
-    memset(c_info, '\0', sizeof(*c_info));
-    c_info->xsdata = NULL;
-    c_info->platformdata = NULL;
-    c_info->hvm = 1;
-    c_info->ssidref = 0;
-}
-
-static void init_build_info(libxl_domain_build_info *b_info, 
libxl_domain_create_info *c_info)
-{
-    memset(b_info, '\0', sizeof(*b_info));
-    b_info->timer_mode = -1;
-    b_info->hpet = 1;
-    b_info->vpt_align = -1;
-    b_info->max_vcpus = 1;
-    b_info->max_memkb = 32 * 1024;
-    b_info->target_memkb = b_info->max_memkb;
-    if (c_info->hvm) {
-        b_info->shadow_memkb = 
libxl_get_required_shadow_memory(b_info->max_memkb, b_info->max_vcpus);
-        b_info->video_memkb = 8 * 1024;
-        b_info->kernel = "/usr/lib/xen/boot/hvmloader";
-        b_info->hvm = 1;
-        b_info->u.hvm.pae = 1;
-        b_info->u.hvm.apic = 1;
-        b_info->u.hvm.acpi = 1;
-        b_info->u.hvm.nx = 1;
-        b_info->u.hvm.viridian = 0;
-    } else {
-        b_info->u.pv.slack_memkb = 8 * 1024;
-    }
-}
-
-static void init_dm_info(libxl_device_model_info *dm_info,
-        libxl_domain_create_info *c_info, libxl_domain_build_info *b_info)
-{
-    int i;
-    memset(dm_info, '\0', sizeof(*dm_info));
-
-    for (i = 0; i < 16; i++) {
-        dm_info->uuid[i] = rand();
-    }
-
-    dm_info->dom_name = c_info->name;
-    dm_info->device_model = "/usr/lib/xen/bin/qemu-dm";
-    dm_info->videoram = b_info->video_memkb / 1024;
-    dm_info->apic = b_info->u.hvm.apic;
-
-    dm_info->stdvga = 0;
-    dm_info->vnc = 1;
-    dm_info->vnclisten = "127.0.0.1";
-    dm_info->vncdisplay = 0;
-    dm_info->vncunused = 0;
-    dm_info->keymap = NULL;
-    dm_info->sdl = 0;
-    dm_info->opengl = 0;
-    dm_info->nographic = 0;
-    dm_info->serial = NULL;
-    dm_info->boot = "cda";
-    dm_info->usb = 0;
-    dm_info->usbdevice = NULL;
-}
-
-static void init_nic_info(libxl_device_nic *nic_info, int devnum)
-{
-    memset(nic_info, '\0', sizeof(*nic_info));
-
-    nic_info->backend_domid = 0;
-    nic_info->domid = 0;
-    nic_info->devid = devnum;
-    nic_info->mtu = 1492;
-    nic_info->model = "e1000";
-    nic_info->mac[0] = 0x00;
-    nic_info->mac[1] = 0x16;
-    nic_info->mac[2] = 0x3e;
-    nic_info->mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
-    nic_info->mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
-    nic_info->mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
-    nic_info->ifname = NULL;
-    nic_info->bridge = "xenbr0";
-    nic_info->script = "/etc/xen/scripts/vif-bridge";
-    nic_info->nictype = NICTYPE_IOEMU;
-}
-
-static void init_vfb_info(libxl_device_vfb *vfb, int dev_num)
-{
-    memset(vfb, 0x00, sizeof(libxl_device_vfb));
-    vfb->devid = dev_num;
-    vfb->vnc = 1;
-    vfb->vnclisten = "127.0.0.1";
-    vfb->vncdisplay = 0;
-    vfb->vncunused = 1;
-    vfb->keymap = NULL;
-    vfb->sdl = 0;
-    vfb->opengl = 0;
-}
-
-static void init_vkb_info(libxl_device_vkb *vkb, int dev_num)
-{
-    memset(vkb, 0x00, sizeof(libxl_device_vkb));
-    vkb->devid = dev_num;
-}
-
-static void init_console_info(libxl_device_console *console, int dev_num, 
libxl_domain_build_state *state)
-{
-    memset(console, 0x00, sizeof(libxl_device_console));
-    console->devid = dev_num;
-    console->constype = CONSTYPE_XENCONSOLED;
-    if (state)
-        console->build_state = state;
-}
-
-static void printf_info(libxl_domain_create_info *c_info,
-                        libxl_domain_build_info *b_info,
-                        libxl_device_disk *disks,
-                        int num_disks,
-                        libxl_device_nic *vifs,
-                        int num_vifs,
-                        libxl_device_pci *pcidevs,
-                        int num_pcidevs,
-                        libxl_device_vfb *vfbs,
-                        int num_vfbs,
-                        libxl_device_vkb *vkb,
-                        int num_vkbs,
-                        libxl_device_model_info *dm_info)
-{
-    int i;
-    printf("*** domain_create_info ***\n");
-    printf("hvm: %d\n", c_info->hvm);
-    printf("hap: %d\n", c_info->hap);
-    printf("ssidref: %d\n", c_info->ssidref);
-    printf("name: %s\n", c_info->name);
-    printf("uuid: " UUID_FMT "\n",
-           (c_info->uuid)[0], (c_info->uuid)[1], (c_info->uuid)[2], 
(c_info->uuid)[3],
-           (c_info->uuid)[4], (c_info->uuid)[5], (c_info->uuid)[6], 
(c_info->uuid)[7],
-           (c_info->uuid)[8], (c_info->uuid)[9], (c_info->uuid)[10], 
(c_info->uuid)[11],
-           (c_info->uuid)[12], (c_info->uuid)[13], (c_info->uuid)[14], 
(c_info->uuid)[15]);
-    if (c_info->xsdata)
-        printf("xsdata: contains data\n");
-    else
-        printf("xsdata: (null)\n");
-    if (c_info->platformdata)
-        printf("platformdata: contains data\n");
-    else
-        printf("platformdata: (null)\n");
-
-
-    printf("\n\n\n*** domain_build_info ***\n");
-    printf("timer_mode: %d\n", b_info->timer_mode);
-    printf("hpet: %d\n", b_info->hpet);
-    printf("vpt_align: %d\n", b_info->vpt_align);
-    printf("max_vcpus: %d\n", b_info->max_vcpus);
-    printf("max_memkb: %d\n", b_info->max_memkb);
-    printf("target_memkb: %d\n", b_info->target_memkb);
-    printf("kernel: %s\n", b_info->kernel);
-    printf("hvm: %d\n", b_info->hvm);
-
-    if (c_info->hvm) {
-        printf("video_memkb: %d\n", b_info->video_memkb);
-        printf("shadow_memkb: %d\n", b_info->shadow_memkb);
-        printf("    pae: %d\n", b_info->u.hvm.pae);
-        printf("    apic: %d\n", b_info->u.hvm.apic);
-        printf("    acpi: %d\n", b_info->u.hvm.acpi);
-        printf("    nx: %d\n", b_info->u.hvm.nx);
-        printf("    viridian: %d\n", b_info->u.hvm.viridian);
-    } else {
-        printf("cmdline: %s\n", b_info->u.pv.cmdline);
-        printf("ramdisk: %s\n", b_info->u.pv.ramdisk);
-    }
-
-    for (i = 0; i < num_disks; i++) {
-        printf("\n\n\n*** disks_info: %d ***\n", i);
-        printf("backend_domid %d\n", disks[i].backend_domid);
-        printf("domid %d\n", disks[i].domid);
-        printf("physpath %s\n", disks[i].physpath);
-        printf("phystype %d\n", disks[i].phystype);
-        printf("virtpath %s\n", disks[i].virtpath);
-        printf("unpluggable %d\n", disks[i].unpluggable);
-        printf("readwrite %d\n", disks[i].readwrite);
-        printf("is_cdrom %d\n", disks[i].is_cdrom);
-    }
-
-    for (i = 0; i < num_vifs; i++) {
-        printf("\n\n\n*** vifs_info: %d ***\n", i);
-        printf("backend_domid %d\n", vifs[i].backend_domid);
-        printf("domid %d\n", vifs[i].domid);
-        printf("devid %d\n", vifs[i].devid);
-        printf("mtu %d\n", vifs[i].mtu);
-        printf("model %s\n", vifs[i].model);
-        printf("mac %02x:%02x:%02x:%02x:%02x:%02x\n", vifs[i].mac[0], 
vifs[i].mac[1], vifs[i].mac[2], vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
-    }
-
-    for (i = 0; i < num_pcidevs; i++) {
-        printf("\n\n\n*** pcidevs_info: %d ***\n", i);
-        printf("pci dev "PCI_BDF_VDEVFN"\n", pcidevs[i].domain, 
pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func, pcidevs[i].vdevfn);
-        printf("opts msitranslate %d power_mgmt %d\n", 
pcidevs[i].msitranslate, pcidevs[i].power_mgmt);
-    }
-
-    for (i = 0; i < num_vfbs; i++) {
-        printf("\n\n\n*** vfbs_info: %d ***\n", i);
-        printf("backend_domid %d\n", vfbs[i].backend_domid);
-        printf("domid %d\n", vfbs[i].domid);
-        printf("devid %d\n", vfbs[i].devid);
-        printf("vnc: %d\n", vfbs[i].vnc);
-        printf("vnclisten: %s\n", vfbs[i].vnclisten);
-        printf("vncdisplay: %d\n", vfbs[i].vncdisplay);
-        printf("vncunused: %d\n", vfbs[i].vncunused);
-        printf("keymap: %s\n", vfbs[i].keymap);
-        printf("sdl: %d\n", vfbs[i].sdl);
-        printf("opengl: %d\n", vfbs[i].opengl);
-        printf("display: %s\n", vfbs[i].display);
-        printf("xauthority: %s\n", vfbs[i].xauthority);
-    }
-
-    if (c_info->hvm) {
-        printf("\n\n\n*** device_model_info ***\n");
-        printf("domid: %d\n", dm_info->domid);
-        printf("dom_name: %s\n", dm_info->dom_name);
-        printf("device_model: %s\n", dm_info->device_model);
-        printf("videoram: %d\n", dm_info->videoram);
-        printf("stdvga: %d\n", dm_info->stdvga);
-        printf("vnc: %d\n", dm_info->vnc);
-        printf("vnclisten: %s\n", dm_info->vnclisten);
-        printf("vncdisplay: %d\n", dm_info->vncdisplay);
-        printf("vncunused: %d\n", dm_info->vncunused);
-        printf("keymap: %s\n", dm_info->keymap);
-        printf("sdl: %d\n", dm_info->sdl);
-        printf("opengl: %d\n", dm_info->opengl);
-        printf("nographic: %d\n", dm_info->nographic);
-        printf("serial: %s\n", dm_info->serial);
-        printf("boot: %s\n", dm_info->boot);
-        printf("usb: %d\n", dm_info->usb);
-        printf("usbdevice: %s\n", dm_info->usbdevice);
-        printf("apic: %d\n", dm_info->apic);
-    }
-}
-
-static void parse_config_file(const char *filename,
-                              libxl_domain_create_info *c_info,
-                              libxl_domain_build_info *b_info,
-                              libxl_device_disk **disks,
-                              int *num_disks,
-                              libxl_device_nic **vifs,
-                              int *num_vifs,
-                              libxl_device_pci **pcidevs,
-                              int *num_pcidevs,
-                              libxl_device_vfb **vfbs,
-                              int *num_vfbs,
-                              libxl_device_vkb **vkbs,
-                              int *num_vkbs,
-                              libxl_device_model_info *dm_info)
-{
-    const char *buf;
-    long l;
-    XLU_Config *config;
-    XLU_ConfigList *vbds, *nics, *pcis, *cvfbs;
-    int pci_power_mgmt = 0;
-    int pci_msitranslate = 1;
-    int i, e;
-
-    config= xlu_cfg_init(stderr, filename);
-    if (!config) {
-        fprintf(stderr, "Failed to allocate for configuration\n");
-        exit(1);
-    }
-
-    e= xlu_cfg_readfile (config, filename);
-    if (e) {
-        fprintf(stderr, "Failed to parse config file: %s\n", strerror(e));
-        exit(1);
-    }
-
-    init_create_info(c_info);
-
-    c_info->hvm = 0;
-    if (!xlu_cfg_get_string (config, "builder", &buf) &&
-        !strncmp(buf, "hvm", strlen(buf)))
-        c_info->hvm = 1;
-
-    /* hap is missing */
-    if (!xlu_cfg_get_string (config, "name", &buf))
-        c_info->name = strdup(buf);
-    else
-        c_info->name = "test";
-    for (i = 0; i < 16; i++) {
-        c_info->uuid[i] = rand();
-    }
-
-    init_build_info(b_info, c_info);
-
-    /* the following is the actual config parsing with overriding values in 
the structures */
-    if (!xlu_cfg_get_long (config, "vcpus", &l))
-        b_info->max_vcpus = l;
-
-    if (!xlu_cfg_get_long (config, "memory", &l)) {
-        b_info->max_memkb = l * 1024;
-        b_info->target_memkb = b_info->max_memkb;
-    }
-
-    if (!xlu_cfg_get_long (config, "shadow_memory", &l))
-        b_info->shadow_memkb = l * 1024;
-
-    if (!xlu_cfg_get_long (config, "videoram", &l))
-        b_info->video_memkb = l * 1024;
-
-    if (!xlu_cfg_get_string (config, "kernel", &buf))
-        b_info->kernel = strdup(buf);
-
-    if (c_info->hvm == 1) {
-        if (!xlu_cfg_get_long (config, "pae", &l))
-            b_info->u.hvm.pae = l;
-        if (!xlu_cfg_get_long (config, "apic", &l))
-            b_info->u.hvm.apic = l;
-        if (!xlu_cfg_get_long (config, "acpi", &l))
-            b_info->u.hvm.acpi = l;
-        if (!xlu_cfg_get_long (config, "nx", &l))
-            b_info->u.hvm.nx = l;
-        if (!xlu_cfg_get_long (config, "viridian", &l))
-            b_info->u.hvm.viridian = l;
-    } else {
-        char *cmdline;
-        if (!xlu_cfg_get_string (config, "root", &buf)) {
-            asprintf(&cmdline, "root=%s", buf);
-            b_info->u.pv.cmdline = cmdline;
-        }
-        if (!xlu_cfg_get_string (config, "ramdisk", &buf))
-            b_info->u.pv.ramdisk = strdup(buf);
-    }
-
-    if (!xlu_cfg_get_list (config, "disk", &vbds, 0)) {
-        *num_disks = 0;
-        *disks = NULL;
-        while ((buf = xlu_cfg_get_listitem (vbds, *num_disks)) != NULL) {
-            char *buf2 = strdup(buf);
-            char *p, *p2;
-            *disks = (libxl_device_disk *) realloc(*disks, sizeof 
(libxl_device_disk) * ((*num_disks) + 1));
-            (*disks)[*num_disks].backend_domid = 0;
-            (*disks)[*num_disks].domid = 0;
-            (*disks)[*num_disks].unpluggable = 0;
-            p = strtok(buf2, ",:");
-            while (*p == ' ')
-                p++;
-            if (!strcmp(p, "phy")) {
-                (*disks)[*num_disks].phystype = PHYSTYPE_PHY;
-            } else if (!strcmp(p, "file")) {
-                (*disks)[*num_disks].phystype = PHYSTYPE_FILE;
-            } else if (!strcmp(p, "tap")) {
-                p = strtok(NULL, ":");
-                if (!strcmp(p, "aio")) {
-                    (*disks)[*num_disks].phystype = PHYSTYPE_AIO;
-                } else if (!strcmp(p, "vhd")) {
-                    (*disks)[*num_disks].phystype = PHYSTYPE_VHD;
-                } else if (!strcmp(p, "qcow")) {
-                    (*disks)[*num_disks].phystype = PHYSTYPE_QCOW;
-                } else if (!strcmp(p, "qcow2")) {
-                    (*disks)[*num_disks].phystype = PHYSTYPE_QCOW2;
-                }
-            }
-            p = strtok(NULL, ",");
-            while (*p == ' ')
-                p++;
-            (*disks)[*num_disks].physpath= strdup(p);
-            p = strtok(NULL, ",");
-            while (*p == ' ')
-                p++;
-            p2 = strchr(p, ':');
-            if (p2 == NULL) {
-                (*disks)[*num_disks].virtpath = strdup(p);
-                (*disks)[*num_disks].is_cdrom = 0;
-                (*disks)[*num_disks].unpluggable = 1;
-            } else {
-                *p2 = '\0';
-                (*disks)[*num_disks].virtpath = strdup(p);
-                if (!strcmp(p2 + 1, "cdrom")) {
-                    (*disks)[*num_disks].is_cdrom = 1;
-                    (*disks)[*num_disks].unpluggable = 1;
-                } else
-                    (*disks)[*num_disks].is_cdrom = 0;
-            }
-            p = strtok(NULL, ",");
-            while (*p == ' ')
-                p++;
-            (*disks)[*num_disks].readwrite = (p[0] == 'w') ? 1 : 0;
-            free(buf2);
-            *num_disks = (*num_disks) + 1;
-        }
-    }
-
-    if (!xlu_cfg_get_list (config, "vif", &nics, 0)) {
-        *num_vifs = 0;
-        *vifs = NULL;
-        while ((buf = xlu_cfg_get_listitem (nics, *num_vifs)) != NULL) {
-            char *buf2 = strdup(buf);
-            char *p, *p2;
-            *vifs = (libxl_device_nic *) realloc(*vifs, sizeof 
(libxl_device_nic) * ((*num_vifs) + 1));
-            init_nic_info((*vifs) + (*num_vifs), (*num_vifs) + 1);
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip;
-            do {
-                while (*p == ' ')
-                    p++;
-                if ((p2 = strchr(p, '=')) == NULL)
-                    break;
-                *p2 = '\0';
-                if (!strcmp(p, "model")) {
-                    (*vifs)[*num_vifs].model = strdup(p2 + 1);
-                } else if (!strcmp(p, "mac")) {
-                    char *p3 = p2 + 1;
-                    *(p3 + 2) = '\0';
-                    (*vifs)[*num_vifs].mac[0] = strtol(p3, NULL, 16);
-                    p3 = p3 + 3;
-                    *(p3 + 2) = '\0';
-                    (*vifs)[*num_vifs].mac[1] = strtol(p3, NULL, 16);
-                    p3 = p3 + 3;
-                    *(p3 + 2) = '\0';
-                    (*vifs)[*num_vifs].mac[2] = strtol(p3, NULL, 16);
-                    p3 = p3 + 3;
-                    *(p3 + 2) = '\0';
-                    (*vifs)[*num_vifs].mac[3] = strtol(p3, NULL, 16);
-                    p3 = p3 + 3;
-                    *(p3 + 2) = '\0';
-                    (*vifs)[*num_vifs].mac[4] = strtol(p3, NULL, 16);
-                    p3 = p3 + 3;
-                    *(p3 + 2) = '\0';
-                    (*vifs)[*num_vifs].mac[5] = strtol(p3, NULL, 16);
-                } else if (!strcmp(p, "bridge")) {
-                    (*vifs)[*num_vifs].bridge = strdup(p2 + 1);
-                } else if (!strcmp(p, "type")) {
-                    if (!strcmp(p2 + 1, "ioemu"))
-                        (*vifs)[*num_vifs].nictype = NICTYPE_IOEMU;
-                    else
-                        (*vifs)[*num_vifs].nictype = NICTYPE_VIF;
-                } else if (!strcmp(p, "ip")) {
-                    inet_pton(AF_INET, p2 + 1, &((*vifs)[*num_vifs].ip));
-                } else if (!strcmp(p, "script")) {
-                    (*vifs)[*num_vifs].script = strdup(p2 + 1);
-                } else if (!strcmp(p, "vifname")) {
-                    (*vifs)[*num_vifs].ifname = strdup(p2 + 1);
-                } else if (!strcmp(p, "rate")) {
-                    fprintf(stderr, "the rate parameter for vifs is currently 
not supported\n");
-                } else if (!strcmp(p, "accel")) {
-                    fprintf(stderr, "the accel parameter for vifs is currently 
not supported\n");
-                }
-            } while ((p = strtok(NULL, ",")) != NULL);
-skip:
-            free(buf2);
-            *num_vifs = (*num_vifs) + 1;
-        }
-    }
-
-    if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0)) {
-        *num_vfbs = 0;
-        *num_vkbs = 0;
-        *vfbs = NULL;
-        *vkbs = NULL;
-        while ((buf = xlu_cfg_get_listitem (cvfbs, *num_vfbs)) != NULL) {
-            char *buf2 = strdup(buf);
-            char *p, *p2;
-            *vfbs = (libxl_device_vfb *) realloc(*vfbs, 
sizeof(libxl_device_vfb) * ((*num_vfbs) + 1));
-            init_vfb_info((*vfbs) + (*num_vfbs), (*num_vfbs));
-
-            *vkbs = (libxl_device_vkb *) realloc(*vkbs, 
sizeof(libxl_device_vkb) * ((*num_vkbs) + 1));
-            init_vkb_info((*vkbs) + (*num_vkbs), (*num_vkbs));
-
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_vfb;
-            do {
-                while (*p == ' ')
-                    p++;
-                if ((p2 = strchr(p, '=')) == NULL)
-                    break;
-                *p2 = '\0';
-                if (!strcmp(p, "vnc")) {
-                    (*vfbs)[*num_vfbs].vnc = atoi(p2 + 1);
-                } else if (!strcmp(p, "vnclisten")) {
-                    (*vfbs)[*num_vfbs].vnclisten = strdup(p2 + 1);
-                } else if (!strcmp(p, "vncdisplay")) {
-                    (*vfbs)[*num_vfbs].vncdisplay = atoi(p2 + 1);
-                } else if (!strcmp(p, "vncunused")) {
-                    (*vfbs)[*num_vfbs].vncunused = atoi(p2 + 1);
-                } else if (!strcmp(p, "keymap")) {
-                    (*vfbs)[*num_vfbs].keymap = strdup(p2 + 1);
-                } else if (!strcmp(p, "sdl")) {
-                    (*vfbs)[*num_vfbs].sdl = atoi(p2 + 1);
-                } else if (!strcmp(p, "opengl")) {
-                    (*vfbs)[*num_vfbs].opengl = atoi(p2 + 1);
-                } else if (!strcmp(p, "display")) {
-                    (*vfbs)[*num_vfbs].display = strdup(p2 + 1);
-                } else if (!strcmp(p, "xauthority")) {
-                    (*vfbs)[*num_vfbs].xauthority = strdup(p2 + 1);
-                }
-            } while ((p = strtok(NULL, ",")) != NULL);
-skip_vfb:
-            free(buf2);
-            *num_vfbs = (*num_vfbs) + 1;
-            *num_vkbs = (*num_vkbs) + 1;
-        }
-    }
-
-    if (!xlu_cfg_get_long (config, "pci_msitranslate", &l))
-        pci_msitranslate = l;
-
-    if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l))
-        pci_power_mgmt = l;
-
-    if (!xlu_cfg_get_list (config, "pci", &pcis, 0)) {
-        *num_pcidevs = 0;
-        *pcidevs = NULL;
-        while ((buf = xlu_cfg_get_listitem (pcis, *num_pcidevs)) != NULL) {
-            unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
-            char *buf2 = strdup(buf);
-            char *p;
-            *pcidevs = (libxl_device_pci *) realloc(*pcidevs, sizeof 
(libxl_device_pci) * ((*num_pcidevs) + 1));
-            memset(*pcidevs + *num_pcidevs, 0x00, sizeof(libxl_device_pci));
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_pci;
-            if (!sscanf(p, PCI_BDF_VDEVFN, &domain, &bus, &dev, &func, 
&vdevfn)) {
-                sscanf(p, "%02x:%02x.%01x@%02x", &bus, &dev, &func, &vdevfn);
-                domain = 0;
-            }
-            libxl_device_pci_init(*pcidevs + *num_pcidevs, domain, bus, dev, 
func, vdevfn);
-            (*pcidevs)[*num_pcidevs].msitranslate = pci_msitranslate;
-            (*pcidevs)[*num_pcidevs].power_mgmt = pci_power_mgmt;
-            while ((p = strtok(NULL, ",=")) != NULL) {
-                while (*p == ' ')
-                    p++;
-                if (!strcmp(p, "msitranslate")) {
-                    p = strtok(NULL, ",=");
-                    (*pcidevs)[*num_pcidevs].msitranslate = atoi(p);
-                } else if (!strcmp(p, "power_mgmt")) {
-                    p = strtok(NULL, ",=");
-                    (*pcidevs)[*num_pcidevs].power_mgmt = atoi(p);
-                }
-            }
-            *num_pcidevs = (*num_pcidevs) + 1;
-skip_pci:
-            free(buf2);
-        }
-    }
-
-    if (c_info->hvm == 1) {
-        /* init dm from c and b */
-        init_dm_info(dm_info, c_info, b_info);
-
-        /* then process config related to dm */
-        if (!xlu_cfg_get_string (config, "device_model", &buf))
-            dm_info->device_model = strdup(buf);
-        if (!xlu_cfg_get_long (config, "stdvga", &l))
-            dm_info->stdvga = l;
-        if (!xlu_cfg_get_long (config, "vnc", &l))
-            dm_info->vnc = l;
-        if (!xlu_cfg_get_string (config, "vnclisten", &buf))
-            dm_info->vnclisten = strdup(buf);
-        if (!xlu_cfg_get_long (config, "vncdisplay", &l))
-            dm_info->vncdisplay = l;
-        if (!xlu_cfg_get_long (config, "vncunused", &l))
-            dm_info->vncunused = l;
-        if (!xlu_cfg_get_string (config, "keymap", &buf))
-            dm_info->keymap = strdup(buf);
-        if (!xlu_cfg_get_long (config, "sdl", &l))
-            dm_info->sdl = l;
-        if (!xlu_cfg_get_long (config, "opengl", &l))
-            dm_info->opengl = l;
-        if (!xlu_cfg_get_long (config, "nographic", &l))
-            dm_info->nographic = l;
-        if (!xlu_cfg_get_string (config, "serial", &buf))
-            dm_info->serial = strdup(buf);
-        if (!xlu_cfg_get_string (config, "boot", &buf))
-            dm_info->boot = strdup(buf);
-        if (!xlu_cfg_get_long (config, "usb", &l))
-            dm_info->usb = l;
-        if (!xlu_cfg_get_string (config, "usbdevice", &buf))
-            dm_info->usbdevice = strdup(buf);
-    }
-
-    dm_info->type = c_info->hvm ? XENFV : XENPV;
-
-    xlu_cfg_destroy(config);
-}
-
-#define MUST( call ) ({                                                 \
-        int must_rc = (call);                                           \
-        if (must_rc) {                                                  \
-            fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n",       \
-                    __FILE__,__LINE__, must_rc, #call);                 \
-            exit(-must_rc);                                             \
-        }                                                               \
-    })
-
-static void create_domain(int debug, int daemonize, const char *config_file, 
const char *restore_file, int paused)
-{
-    struct libxl_ctx ctx;
-    uint32_t domid;
-    libxl_domain_create_info info1;
-    libxl_domain_build_info info2;
-    libxl_domain_build_state state;
-    libxl_device_model_info dm_info;
-    libxl_device_disk *disks = NULL;
-    libxl_device_nic *vifs = NULL;
-    libxl_device_pci *pcidevs = NULL;
-    libxl_device_vfb *vfbs = NULL;
-    libxl_device_vkb *vkbs = NULL;
-    libxl_device_console console;
-    int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 
0;
-    int i, fd;
-    int need_daemon = 1;
-    int ret;
-    libxl_device_model_starting *dm_starting = 0;
-    libxl_waiter *w1 = NULL, *w2 = NULL;
-    memset(&dm_info, 0x00, sizeof(dm_info));
-
-    printf("Parsing config file %s\n", config_file);
-    parse_config_file(config_file, &info1, &info2, &disks, &num_disks, &vifs, 
&num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, 
&dm_info);
-    if (debug)
-        printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, pcidevs, 
num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
-
-start:
-    domid = 0;
-
-    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
-        fprintf(stderr, "cannot init xl context\n");
-        return;
-    }
-
-    libxl_ctx_set_log(&ctx, log_callback, NULL);
-
-    ret = libxl_domain_make(&ctx, &info1, &domid);
-    if (ret) {
-        fprintf(stderr, "cannot make domain: %d\n", ret);
-        return;
-    }
-
-    if (!restore_file || !need_daemon) {
-        if (dm_info.saved_state) {
-            free(dm_info.saved_state);
-            dm_info.saved_state = NULL;
-        }
-        ret = libxl_domain_build(&ctx, &info2, domid, &state);
-    } else {
-        int restore_fd;
-
-        restore_fd = open(restore_file, O_RDONLY);
-        ret = libxl_domain_restore(&ctx, &info2, domid, restore_fd, &state, 
&dm_info);
-        close(restore_fd);
-    }
-
-    if (ret) {
-        fprintf(stderr, "cannot (re-)build domain: %d\n", ret);
-        return;
-    }
-
-    for (i = 0; i < num_disks; i++) {
-        disks[i].domid = domid;
-        ret = libxl_device_disk_add(&ctx, domid, &disks[i]);
-        if (ret) {
-            fprintf(stderr, "cannot add disk %d to domain: %d\n", i, ret);
-            return;
-        }
-    }
-    for (i = 0; i < num_vifs; i++) {
-        vifs[i].domid = domid;
-        ret = libxl_device_nic_add(&ctx, domid, &vifs[i]);
-        if (ret) {
-            fprintf(stderr, "cannot add nic %d to domain: %d\n", i, ret);
-            return;
-        }
-    }
-    if (info1.hvm) {
-        dm_info.domid = domid;
-        MUST( libxl_create_device_model(&ctx, &dm_info, disks, num_disks,
-                                        vifs, num_vifs, &dm_starting) );
-    } else {
-        for (i = 0; i < num_vfbs; i++) {
-            vfbs[i].domid = domid;
-            libxl_device_vfb_add(&ctx, domid, &vfbs[i]);
-            vkbs[i].domid = domid;
-            libxl_device_vkb_add(&ctx, domid, &vkbs[i]);
-        }
-        init_console_info(&console, 0, &state);
-        console.domid = domid;
-        if (num_vfbs)
-            console.constype = CONSTYPE_IOEMU;
-        libxl_device_console_add(&ctx, domid, &console);
-        if (num_vfbs)
-            libxl_create_xenpv_qemu(&ctx, vfbs, 1, &console, &dm_starting);
-    }
-
-    if (dm_starting)
-        MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) );
-    for (i = 0; i < num_pcidevs; i++)
-        libxl_device_pci_add(&ctx, domid, &pcidevs[i]);
-
-    if (!paused)
-        libxl_domain_unpause(&ctx, domid);
-
-    if (!daemonize)
-        exit(0);
-
-    if (need_daemon) {
-        char *fullname, *name;
-
-        asprintf(&name, "xl-%s", info1.name);
-        libxl_create_logfile(&ctx, name, &fullname);
-        logfile = open(fullname, O_WRONLY|O_CREAT, 0644);
-        free(fullname);
-        free(name);
-
-        daemon(0, 0);
-        need_daemon = 0;
-    }
-    LOG("Waiting for domain %s (domid %d) to die", info1.name, domid);
-    w1 = (libxl_waiter*) malloc(sizeof(libxl_waiter) * num_disks);
-    w2 = (libxl_waiter*) malloc(sizeof(libxl_waiter));
-    libxl_wait_for_disk_ejects(&ctx, domid, disks, num_disks, w1);
-    libxl_wait_for_domain_death(&ctx, domid, w2);
-    libxl_get_wait_fd(&ctx, &fd);
-    while (1) {
-        int ret;
-        fd_set rfds;
-        xc_domaininfo_t info;
-        libxl_event event;
-        libxl_device_disk disk;
-        memset(&info, 0x00, sizeof(xc_dominfo_t));
-
-        FD_ZERO(&rfds);
-        FD_SET(fd, &rfds);
-
-        ret = select(fd + 1, &rfds, NULL, NULL, NULL);
-        if (!ret)
-            continue;
-        libxl_get_event(&ctx, &event);
-        switch (event.type) {
-            case DOMAIN_DEATH:
-                if (libxl_event_get_domain_death_info(&ctx, domid, &event, 
&info)) {
-                    LOG("Domain %d is dead", domid);
-                    if (info.flags & XEN_DOMINF_dying || (info.flags & 
XEN_DOMINF_shutdown && (((info.flags >> XEN_DOMINF_shutdownshift) & 
XEN_DOMINF_shutdownmask) != SHUTDOWN_suspend))) {
-                        LOG("Domain %d needs to be clean: destroying the 
domain", domid);
-                        libxl_domain_destroy(&ctx, domid, 0);
-                        if (info.flags & XEN_DOMINF_shutdown &&
-                            (((info.flags >> XEN_DOMINF_shutdownshift) & 
XEN_DOMINF_shutdownmask) == SHUTDOWN_reboot)) {
-                            libxl_free_waiter(w1);
-                            libxl_free_waiter(w2);
-                            free(w1);
-                            free(w2);
-                            libxl_ctx_free(&ctx);
-                            LOG("Done. Rebooting now");
-                            goto start;
-                        }
-                        LOG("Done. Exiting now");
-                    }
-                    LOG("Domain %d does not need to be clean, exiting now", 
domid);
-                    exit(0);
-                }
-                break;
-            case DISK_EJECT:
-                if (libxl_event_get_disk_eject_info(&ctx, domid, &event, 
&disk))
-                    libxl_cdrom_insert(&ctx, domid, &disk);
-                break;
-        }
-        libxl_free_event(&event);
-    }
-
-    close(logfile);
-    free(disks);
-    free(vifs);
-    free(vfbs);
-    free(vkbs);
-    free(pcidevs);
-}
-
-static void help(char *command)
-{
-    if (!command || !strcmp(command, "help")) {
-        printf("Usage xl <subcommand> [args]\n\n");
-        printf("xl full list of subcommands:\n\n");
-        printf(" create                        create a domain from config 
file <filename>\n\n");
-        printf(" list                          list information about all 
domains\n\n");
-        printf(" destroy                       terminate a domain 
immediately\n\n");
-        printf(" pci-attach                    insert a new pass-through pci 
device\n\n");
-        printf(" pci-detach                    remove a domain's pass-through 
pci device\n\n");
-        printf(" pci-list                      list pass-through pci devices 
for a domain\n\n");
-        printf(" pause                         pause execution of a 
domain\n\n");
-        printf(" unpause                       unpause a paused domain\n\n");
-        printf(" console                       attach to domain's 
console\n\n");
-        printf(" save                          save a domain state to restore 
later\n\n");
-        printf(" restore                       restore a domain from a saved 
state\n\n");
-        printf(" cd-insert                     insert a cdrom into a guest's 
cd drive\n\n");
-        printf(" cd-eject                      eject a cdrom from a guest's cd 
drive\n\n");
-        printf(" mem-set                       set the current memory usage 
for a domain\n\n");
-        printf(" button-press                  indicate an ACPI button press 
to the domain\n\n");
-    } else if(!strcmp(command, "create")) {
-        printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
-        printf("Create a domain based on <ConfigFile>.\n\n");
-        printf("Options:\n\n");
-        printf("-h                     Print this help.\n");
-        printf("-d                     Enable debug messages.\n");
-        printf("-e                     Do not wait in the background for the 
death of the domain.\n");
-    } else if(!strcmp(command, "list")) {
-        printf("Usage: xl list [Domain]\n\n");
-        printf("List information about all/some domains.\n\n");
-    } else if(!strcmp(command, "pci-attach")) {
-        printf("Usage: xl pci-attach <Domain> <BDF> [Virtual Slot]\n\n");
-        printf("Insert a new pass-through pci device.\n\n");
-    } else if(!strcmp(command, "pci-detach")) {
-        printf("Usage: xl pci-detach <Domain> <BDF>\n\n");
-        printf("Remove a domain's pass-through pci device.\n\n");
-    } else if(!strcmp(command, "pci-list")) {
-        printf("Usage: xl pci-list <Domain>\n\n");
-        printf("List pass-through pci devices for a domain.\n\n");
-    } else if(!strcmp(command, "pause")) {
-        printf("Usage: xl pause <Domain>\n\n");
-        printf("Pause execution of a domain.\n\n");
-    } else if(!strcmp(command, "unpause")) {
-        printf("Usage: xl unpause <Domain>\n\n");
-        printf("Unpause a paused domain.\n\n");
-    } else if(!strcmp(command, "save")) {
-        printf("Usage: xl save [options] <Domain> <CheckpointFile>\n\n");
-        printf("Save a domain state to restore later.\n\n");
-        printf("Options:\n\n");
-        printf("-h                     Print this help.\n");
-        printf("-c                     Leave domain running after creating the 
snapshot.\n");
-    } else if(!strcmp(command, "restore")) {
-        printf("Usage: xl restore [options] <ConfigFile> 
<CheckpointFile>\n\n");
-        printf("Restore a domain from a saved state.\n\n");
-        printf("Options:\n\n");
-        printf("-h                     Print this help.\n");
-        printf("-p                     Do not unpause domain after restoring 
it.\n");
-        printf("-e                     Do not wait in the background for the 
death of the domain.\n");
-    } else if(!strcmp(command, "destroy")) {
-        printf("Usage: xl destroy <Domain>\n\n");
-        printf("Terminate a domain immediately.\n\n");
-    } else if (!strcmp(command, "console")) {
-        printf("Usage: xl console <Domain>\n\n");
-        printf("Attach to domain's console.\n\n");
-    } else if (!strcmp(command, "cd-insert")) {
-        printf("Usage: xl cd-insert <Domain> <VirtualDevice> <type:path>\n\n");
-        printf("Insert a cdrom into a guest's cd drive.\n\n");
-    } else if (!strcmp(command, "cd-eject")) {
-        printf("Usage: xl cd-eject <Domain> <VirtualDevice>\n\n");
-        printf("Eject a cdrom from a guest's cd drive.\n\n");
-    } else if (!strcmp(command, "mem-set")) {
-        printf("Usage: xl mem-set <Domain> <MemKB>\n\n");
-        printf("Set the current memory usage for a domain.\n\n");
-    } else if (!strcmp(command, "button-press")) {
-        printf("Usage: xl button-press <Domain> <Button>\n\n");
-        printf("Indicate <Button> press to a domain.\n");
-        printf("<Button> may be 'power' or 'sleep'.\n\n");
-    }
-}
-
-void set_memory_target(char *p, char *mem)
-{
-    struct libxl_ctx ctx;
-    uint32_t domid;
-    uint32_t memorykb;
-    char *endptr;
-
-    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
-        fprintf(stderr, "cannot init xl context\n");
-        return;
-    }
-    libxl_ctx_set_log(&ctx, log_callback, NULL);
-
-    if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", p);
-        exit(2);
-    }
-    memorykb = strtoul(mem, &endptr, 10);
-    if (*endptr != '\0') {
-        fprintf(stderr, "invalid memory size: %s\n", mem);
-        exit(3);
-    }
-    printf("setting domid %d memory to : %d\n", domid, memorykb);
-    libxl_set_memory_target(&ctx, domid, memorykb);
-}
-
-int main_memset(int argc, char **argv)
-{
-    int opt = 0;
-    char *p = NULL, *mem;
-
-    while ((opt = getopt(argc, argv, "h:")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("mem-set");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc - 1) {
-        help("mem-set");
-        exit(2);
-    }
-
-    p = argv[optind];
-    mem = argv[optind + 1];
-
-    set_memory_target(p, mem);
-    exit(0);
-}
-
-void console(char *p, int cons_num)
-{
-    struct libxl_ctx ctx;
-    uint32_t domid;
-
-    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
-        fprintf(stderr, "cannot init xl context\n");
-        return;
-    }
-    libxl_ctx_set_log(&ctx, log_callback, NULL);
-
-    if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", p);
-        exit(2);
-    }
-    libxl_console_attach(&ctx, domid, cons_num);
-}
-
-void cd_insert(char *dom, char *virtdev, char *phys)
-{
-    struct libxl_ctx ctx;
-    uint32_t domid;
-    libxl_device_disk disk;
-    char *p;
-
-    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
-        fprintf(stderr, "cannot init xl context\n");
-        return;
-    }
-    libxl_ctx_set_log(&ctx, log_callback, NULL);
-
-    if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", dom);
-        exit(2);
-    }
-
-    disk.backend_domid = 0;
-    disk.domid = domid;
-    if (phys) {
-        p = strchr(phys, ':');
-        if (!p) {
-            fprintf(stderr, "No type specified, ");
-            disk.physpath = phys;
-            if (!strncmp(phys, "/dev", 4)) {
-                fprintf(stderr, "assuming phy:\n");
-                disk.phystype = PHYSTYPE_PHY;
-            } else {
-                fprintf(stderr, "assuming file:\n");
-                disk.phystype = PHYSTYPE_FILE;
-            }
-        } else {
-            *p = '\0';
-            p++;
-            disk.physpath = p;
-            libxl_string_to_phystype(&ctx, phys, &disk.phystype);
-        }
-    } else {
-            disk.physpath = NULL;
-            disk.phystype = 0;
-    }
-    disk.virtpath = virtdev;
-    disk.unpluggable = 1;
-    disk.readwrite = 0;
-    disk.is_cdrom = 1;
-
-    libxl_cdrom_insert(&ctx, domid, &disk);
-}
-
-int main_cd_eject(int argc, char **argv)
-{
-    int opt = 0;
-    char *p = NULL, *virtdev;
-
-    while ((opt = getopt(argc, argv, "hn:")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("cd-eject");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc - 1) {
-        help("cd-eject");
-        exit(2);
-    }
-
-    p = argv[optind];
-    virtdev = argv[optind + 1];
-
-    cd_insert(p, virtdev, NULL);
-    exit(0);
-}
-
-int main_cd_insert(int argc, char **argv)
-{
-    int opt = 0;
-    char *p = NULL, *file = NULL, *virtdev;
-
-    while ((opt = getopt(argc, argv, "hn:")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("cd-insert");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc - 2) {
-        help("cd-insert");
-        exit(2);
-    }
-
-    p = argv[optind];
-    virtdev = argv[optind + 1];
-    file = argv[optind + 2];
-
-    cd_insert(p, virtdev, file);
-    exit(0);
-}
-
-int main_console(int argc, char **argv)
-{
-    int opt = 0, cons_num = 0;
-    char *p = NULL;
-
-    while ((opt = getopt(argc, argv, "hn:")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("console");
-            exit(0);
-        case 'n':
-            if (optarg) {
-                cons_num = strtol(optarg, NULL, 10);
-            }
-            break;
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc) {
-        help("console");
-        exit(2);
-    }
-
-    p = argv[optind];
-
-    console(p, cons_num);
-    exit(0);
-}
-
-void pcilist(char *dom)
-{
-    struct libxl_ctx ctx;
-    uint32_t domid;
-    libxl_device_pci *pcidevs;
-    int num, i;
-
-    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
-        fprintf(stderr, "cannot init xl context\n");
-        return;
-    }
-    libxl_ctx_set_log(&ctx, log_callback, NULL);
-
-    if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", dom);
-        exit(2);
-    }
-    pcidevs = libxl_device_pci_list(&ctx, domid, &num);
-    if (!num)
-        return;
-    printf("VFn  domain bus  slot func\n");
-    for (i = 0; i < num; i++) {
-        printf("0x%02x 0x%04x 0x%02x 0x%02x 0x%01x\n", pcidevs[i].vdevfn, 
pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
-    }
-    free(pcidevs);
-}
-
-int main_pcilist(int argc, char **argv)
-{
-    int opt;
-    char *domname = NULL;
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("pci-list");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc) {
-        help("pci-list");
-        exit(2);
-    }
-
-    domname = argv[optind];
-
-    pcilist(domname);
-    exit(0);
-}
-
-void pcidetach(char *dom, char *bdf)
-{
-    struct libxl_ctx ctx;
-    uint32_t domid;
-    libxl_device_pci pcidev;
-    unsigned int domain, bus, dev, func;
-
-    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
-        fprintf(stderr, "cannot init xl context\n");
-        return;
-    }
-    libxl_ctx_set_log(&ctx, log_callback, NULL);
-
-    if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", dom);
-        exit(2);
-    }
-    memset(&pcidev, 0x00, sizeof(pcidev));
-    sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
-    libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
-    libxl_device_pci_remove(&ctx, domid, &pcidev);
-}
-
-int main_pcidetach(int argc, char **argv)
-{
-    int opt;
-    char *domname = NULL, *bdf = NULL;
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("pci-attach");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc - 1) {
-        help("pci-detach");
-        exit(2);
-    }
-
-    domname = argv[optind];
-    bdf = argv[optind + 1];
-
-    pcidetach(domname, bdf);
-    exit(0);
-}
-void pciattach(char *dom, char *bdf, char *vs)
-{
-    struct libxl_ctx ctx;
-    uint32_t domid;
-    libxl_device_pci pcidev;
-    unsigned int domain, bus, dev, func;
-
-    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
-        fprintf(stderr, "cannot init xl context\n");
-        return;
-    }
-    libxl_ctx_set_log(&ctx, log_callback, NULL);
-
-    if (domain_qualifier_to_domid(&ctx, dom, &domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", dom);
-        exit(2);
-    }
-    memset(&pcidev, 0x00, sizeof(pcidev));
-    sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func);
-    libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
-    libxl_device_pci_add(&ctx, domid, &pcidev);
-}
-
-int main_pciattach(int argc, char **argv)
-{
-    int opt;
-    char *domname = NULL, *bdf = NULL, *vs = NULL;
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("pci-attach");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc - 1) {
-        help("pci-attach");
-        exit(2);
-    }
-
-    domname = argv[optind];
-    bdf = argv[optind + 1];
-
-    if (optind + 1 < argc)
-        vs = argv[optind + 2];
-
-    pciattach(domname, bdf, vs);
-    exit(0);
-}
-
-void pause_domain(char *p)
-{
-    struct libxl_ctx ctx;
-    uint32_t domid;
-
-    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
-        fprintf(stderr, "cannot init xl context\n");
-        return;
-    }
-    libxl_ctx_set_log(&ctx, log_callback, NULL);
-
-    if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", p);
-        exit(2);
-    }
-    libxl_domain_pause(&ctx, domid);
-}
-
-void unpause_domain(char *p)
-{
-    struct libxl_ctx ctx;
-    uint32_t domid;
-
-    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
-        fprintf(stderr, "cannot init xl context\n");
-        return;
-    }
-    libxl_ctx_set_log(&ctx, log_callback, NULL);
-
-    if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", p);
-        exit(2);
-    }
-    libxl_domain_unpause(&ctx, domid);
-}
-
-void destroy_domain(char *p)
-{
-    struct libxl_ctx ctx;
-    uint32_t domid;
-
-    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
-        fprintf(stderr, "cannot init xl context\n");
-        return;
-    }
-    libxl_ctx_set_log(&ctx, log_callback, NULL);
-
-    if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", p);
-        exit(2);
-    }
-    libxl_domain_destroy(&ctx, domid, 0);
-}
-
-void list_domains(void)
-{
-    struct libxl_ctx ctx;
-    struct libxl_dominfo *info;
-    int nb_domain, i;
-
-    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
-        fprintf(stderr, "cannot init xl context\n");
-        return;
-    }
-    libxl_ctx_set_log(&ctx, log_callback, NULL);
-
-    info = libxl_list_domain(&ctx, &nb_domain);
-
-    if (info < 0) {
-        fprintf(stderr, "libxl_domain_infolist failed.\n");
-        exit(1);
-    }
-    printf("Name                                        ID   Mem 
VCPUs\tState\tTime(s)\n");
-    for (i = 0; i < nb_domain; i++) {
-        printf("%-40s %5d %5lu %5d        %c%c%c %8.1f\n",
-                libxl_domid_to_name(&ctx, info[i].domid),
-                info[i].domid,
-                (unsigned long) (info[i].max_memkb / 1024),
-                info[i].vcpu_online,
-                info[i].running ? 'r' : '-',
-                info[i].paused ? 'p' : '-',
-                info[i].dying ? 'd' : '-',
-                ((float)info[i].cpu_time / 1e9));
-    }
-    free(info);
-}
-
-void list_vm(void)
-{
-    struct libxl_ctx ctx;
-    struct libxl_vminfo *info;
-    int nb_vm, i;
-
-    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
-        fprintf(stderr, "cannot init xl context\n");
-        return;
-    }
-    libxl_ctx_set_log(&ctx, log_callback, NULL);
-
-    info = libxl_list_vm(&ctx, &nb_vm);
-
-    if (info < 0) {
-        fprintf(stderr, "libxl_domain_infolist failed.\n");
-        exit(1);
-    }
-    printf("UUID                                  ID    name\n");
-    for (i = 0; i < nb_vm; i++) {
-        printf(UUID_FMT "  %d    %-30s\n",
-            info[i].uuid[0], info[i].uuid[1], info[i].uuid[2], info[i].uuid[3],
-            info[i].uuid[4], info[i].uuid[5], info[i].uuid[6], info[i].uuid[7],
-            info[i].uuid[8], info[i].uuid[9], info[i].uuid[10], 
info[i].uuid[11],
-            info[i].uuid[12], info[i].uuid[13], info[i].uuid[14], 
info[i].uuid[15],
-            info[i].domid, libxl_domid_to_name(&ctx, info[i].domid));
-    }
-    free(info);
-}
-
-int save_domain(char *p, char *filename, int checkpoint)
-{
-    struct libxl_ctx ctx;
-    uint32_t domid;
-    int fd;
-
-    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
-        fprintf(stderr, "cannot init xl context\n");
-        exit(2);
-    }
-    libxl_ctx_set_log(&ctx, log_callback, NULL);
-
-    if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", p);
-        exit(2);
-    }
-    fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
-    if (fd < 0) {
-        fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
-        exit(2);
-    }
-    libxl_domain_suspend(&ctx, NULL, domid, fd);
-    close(fd);
-
-    if (checkpoint)
-        libxl_domain_unpause(&ctx, domid);
-    else
-        libxl_domain_destroy(&ctx, domid, 0);
-
-    exit(0);
-}
-
-int main_restore(int argc, char **argv)
-{
-    char *checkpoint_file = NULL;
-    char *config_file = NULL;
-    int paused = 0, debug = 0, daemonize = 1;
-    int opt;
-
-    while ((opt = getopt(argc, argv, "hpde")) != -1) {
-        switch (opt) {
-        case 'p':
-            paused = 1;
-            break;
-        case 'd':
-            debug = 1;
-            break;
-        case 'e':
-            daemonize = 0;
-            break;
-        case 'h':
-            help("restore");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-
-    if (optind >= argc - 1) {
-        help("restore");
-        exit(2);
-    }
-
-    config_file = argv[optind];
-    checkpoint_file = argv[optind + 1];
-    create_domain(debug, daemonize, config_file, checkpoint_file, paused);
-    exit(0);
-}
-
-int main_save(int argc, char **argv)
-{
-    char *filename = NULL, *p = NULL;
-    int checkpoint = 0;
-    int opt;
-
-    while ((opt = getopt(argc, argv, "hc")) != -1) {
-        switch (opt) {
-        case 'c':
-            checkpoint = 1;
-            break;
-        case 'h':
-            help("save");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-
-    if (optind >= argc - 1) {
-        help("save");
-        exit(2);
-    }
-
-    p = argv[optind];
-    filename = argv[optind + 1];
-    save_domain(p, filename, checkpoint);
-    exit(0);
-}
-
-int main_pause(int argc, char **argv)
-{
-    int opt;
-    char *p;
-    
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("pause");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc) {
-        help("pause");
-        exit(2);
-    }
-
-    p = argv[optind];
-
-    pause_domain(p);
-    exit(0);
-}
-
-int main_unpause(int argc, char **argv)
-{
-    int opt;
-    char *p;
-    
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("unpause");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc) {
-        help("unpause");
-        exit(2);
-    }
-
-    p = argv[optind];
-
-    unpause_domain(p);
-    exit(0);
-}
-
-int main_destroy(int argc, char **argv)
-{
-    int opt;
-    char *p;
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("destroy");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc) {
-        help("destroy");
-        exit(2);
-    }
-
-    p = argv[optind];
-
-    destroy_domain(p);
-    exit(0);
-}
-
-int main_list(int argc, char **argv)
-{
-    int opt;
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("list");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-
-    list_domains();
-    exit(0);
-}
-
-int main_list_vm(int argc, char **argv)
-{
-    int opt;
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("list-vm");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-
-    list_vm();
-    exit(0);
-}
-
-int main_create(int argc, char **argv)
-{
-    char *filename = NULL;
-    int debug = 0, daemonize = 1;
-    int opt;
-
-    while ((opt = getopt(argc, argv, "hde")) != -1) {
-        switch (opt) {
-        case 'd':
-            debug = 1;
-            break;
-        case 'e':
-            daemonize = 0;
-            break;
-        case 'h':
-            help("create");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-
-    if (optind >= argc) {
-        help("create");
-        exit(2);
-    }
-
-    filename = argv[optind];
-    create_domain(debug, daemonize, filename, NULL, 0);
-    exit(0);
-}
-
-void button_press(char *p, char *b)
-{
-    struct libxl_ctx ctx;
-    uint32_t domid;
-    libxl_button button;
-
-    libxl_ctx_init(&ctx, LIBXL_VERSION);
-    libxl_ctx_set_log(&ctx, log_callback, NULL);
-
-    if (domain_qualifier_to_domid(&ctx, p, &domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", p);
-        exit(2);
-    }
-
-    if (!strcmp(b, "power")) {
-        button = POWER_BUTTON;
-    } else if (!strcmp(b, "sleep")) {
-        button = SLEEP_BUTTON;
-    } else {
-        fprintf(stderr, "%s is an invalid button identifier\n", b);
-        exit(2);
-    }
-
-    libxl_button_press(&ctx, domid, button);
-}
-
-int main_button_press(int argc, char **argv)
-{
-    int opt;
-    char *p;
-    char *b;
-
-    while ((opt = getopt(argc, argv, "h")) != -1) {
-        switch (opt) {
-        case 'h':
-            help("button-press");
-            exit(0);
-        default:
-            fprintf(stderr, "option not supported\n");
-            break;
-        }
-    }
-    if (optind >= argc - 1) {
-        help("button-press");
-        exit(2);
-    }
-
-    p = argv[optind];
-    b = argv[optind + 1];
-
-    button_press(p, b);
-    exit(0);
+    snprintf(str, sizeof(str), "[%d] %s:%d:%s: %s\n",
+             loglevel, file, line, func, s);
+    libxl_write_exactly(NULL, logfile, str, strlen(str), NULL, NULL);
 }
 
 int main(int argc, char **argv)
 {
+    struct cmd_spec *cspec;
+
     if (argc < 2) {
         help(NULL);
         exit(1);
     }
 
+    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
+        fprintf(stderr, "cannot init xl context\n");
+        exit(1);
+    }
+    if (libxl_ctx_set_log(&ctx, log_callback, NULL)) {
+        fprintf(stderr, "cannot set xl log callback\n");
+        exit(-ERROR_FAIL);
+    }
+
     srand(time(0));
 
-    if (!strcmp(argv[1], "create")) {
-        main_create(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "list")) {
-        main_list(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "list-vm")) {
-        main_list_vm(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "destroy")) {
-        main_destroy(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "pci-attach")) {
-        main_pciattach(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "pci-detach")) {
-        main_pcidetach(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "pci-list")) {
-        main_pcilist(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "pause")) {
-        main_pause(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "unpause")) {
-        main_unpause(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "console")) {
-        main_console(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "save")) {
-        main_save(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "restore")) {
-        main_restore(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "cd-insert")) {
-        main_cd_insert(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "cd-eject")) {
-        main_cd_eject(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "mem-set")) {
-        main_memset(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "button-press")) {
-        main_button_press(argc - 1, argv + 1);
-    } else if (!strcmp(argv[1], "help")) {
-        if (argc > 2)
-            help(argv[2]);
-        else
-            help(NULL);
+    cspec = cmdtable_lookup(argv[1]);
+    if (cspec)
+        return cspec->cmd_impl(argc, argv);
+    else if (!strcmp(argv[1], "help")) {
+        help(argv[optind]);
         exit(0);
     } else {
         fprintf(stderr, "command not implemented\n");
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/xl.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/xl.h  Tue Jul 06 16:49:01 2010 +0100
@@ -0,0 +1,81 @@
+/*
+ * Author Yang Hongyang <yanghy@xxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#ifndef XL_H
+#define XL_H
+
+struct cmd_spec {
+    char *cmd_name;
+    int (*cmd_impl)(int argc, char **argv);
+    char *cmd_desc;
+    char *cmd_usage;
+    char *cmd_option;
+};
+
+int main_vcpulist(int argc, char **argv);
+int main_info(int argc, char **argv);
+int main_cd_eject(int argc, char **argv);
+int main_cd_insert(int argc, char **argv);
+int main_console(int argc, char **argv);
+int main_pcilist(int argc, char **argv);
+int main_pcidetach(int argc, char **argv);
+int main_pciattach(int argc, char **argv);
+int main_restore(int argc, char **argv);
+int main_migrate_receive(int argc, char **argv);
+int main_save(int argc, char **argv);
+int main_migrate(int argc, char **argv);
+int main_pause(int argc, char **argv);
+int main_unpause(int argc, char **argv);
+int main_destroy(int argc, char **argv);
+int main_shutdown(int argc, char **argv);
+int main_reboot(int argc, char **argv);
+int main_list(int argc, char **argv);
+int main_list_vm(int argc, char **argv);
+int main_create(int argc, char **argv);
+int main_button_press(int argc, char **argv);
+int main_vcpupin(int argc, char **argv);
+int main_vcpuset(int argc, char **argv);
+int main_memmax(int argc, char **argv);
+int main_memset(int argc, char **argv);
+int main_sched_credit(int argc, char **argv);
+int main_domid(int argc, char **argv);
+int main_domname(int argc, char **argv);
+int main_rename(int argc, char **argv);
+int main_trigger(int argc, char **argv);
+int main_sysrq(int argc, char **argv);
+int main_debug_keys(int argc, char **argv);
+int main_dmesg(int argc, char **argv);
+int main_top(int argc, char **argv);
+int main_networkattach(int argc, char **argv);
+int main_networklist(int argc, char **argv);
+int main_networkdetach(int argc, char **argv);
+int main_blockattach(int argc, char **argv);
+int main_blocklist(int argc, char **argv);
+int main_blockdetach(int argc, char **argv);
+int main_uptime(int argc, char **argv);
+int main_tmem_list(int argc, char **argv);
+int main_tmem_freeze(int argc, char **argv);
+int main_tmem_destroy(int argc, char **argv);
+int main_tmem_thaw(int argc, char **argv);
+int main_tmem_set(int argc, char **argv);
+int main_tmem_shared_auth(int argc, char **argv);
+
+void help(char *command);
+
+/* Look up a command in the table, allowing unambiguous truncation */
+struct cmd_spec *cmdtable_lookup(const char *s);
+extern struct cmd_spec cmd_table[];
+extern int cmdtable_len;
+
+#endif /* XL_H */
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/xl_cmdimpl.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/xl_cmdimpl.c  Tue Jul 06 16:49:01 2010 +0100
@@ -0,0 +1,4243 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h> /* for time */
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <arpa/inet.h>
+#include <sys/utsname.h> /* for utsname in xl info */
+#include <xenctrl.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+#include "libxl.h"
+#include "libxl_utils.h"
+#include "libxlutil.h"
+#include "xl.h"
+
+#define UUID_FMT 
"%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
+
+#define CHK_ERRNO( call ) ({                                            \
+        int chk_errno = (call);                                         \
+        if (chk_errno < 0) {                                                \
+            fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n",          \
+                    __FILE__,__LINE__, strerror(chk_errno), #call);     \
+            exit(-ERROR_FAIL);                                          \
+        }                                                               \
+    })
+
+#define MUST( call ) ({                                                 \
+        int must_rc = (call);                                           \
+        if (must_rc < 0) {                                                  \
+            fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n",       \
+                    __FILE__,__LINE__, must_rc, #call);                 \
+            exit(-must_rc);                                             \
+        }                                                               \
+    })
+
+
+int logfile = 2;
+
+/* every libxl action in xl uses this same libxl context */
+struct libxl_ctx ctx;
+
+/* when we operate on a domain, it is this one: */
+static uint32_t domid;
+static const char *common_domname;
+
+
+static const char savefileheader_magic[32]=
+    "Xen saved domain, xl format\n \0 \r";
+
+static const char migrate_receiver_banner[]=
+    "xl migration receiver ready, send binary domain data.\n";
+static const char migrate_receiver_ready[]=
+    "domain received, ready to unpause";
+static const char migrate_permission_to_go[]=
+    "domain is yours, you are cleared to unpause";
+static const char migrate_report[]=
+    "my copy unpause results are as follows";
+  /* followed by one byte:
+   *     0: everything went well, domain is running
+   *            next thing is we all exit
+   * non-0: things went badly
+   *            next thing should be a migrate_permission_to_go
+   *            from target to source
+   */
+
+struct save_file_header {
+    char magic[32]; /* savefileheader_magic */
+    /* All uint32_ts are in domain's byte order. */
+    uint32_t byteorder; /* SAVEFILE_BYTEORDER_VALUE */
+    uint32_t mandatory_flags; /* unknown flags => reject restore */
+    uint32_t optional_flags; /* unknown flags => reject restore */
+    uint32_t optional_data_len; /* skip, or skip tail, if not understood */
+};
+
+/* Optional data, in order:
+ *   4 bytes uint32_t  config file size
+ *   n bytes           config file in Unix text file format
+ */
+
+#define SAVEFILE_BYTEORDER_VALUE ((uint32_t)0x01020304UL)
+
+static int qualifier_to_id(const char *p, uint32_t *id_r)
+{
+    int i, alldigit;
+
+    alldigit = 1;
+    for (i = 0; p[i]; i++) {
+        if (!isdigit((uint8_t)p[i])) {
+            alldigit = 0;
+            break;
+        }
+    }
+
+    if (i > 0 && alldigit) {
+        *id_r = strtoul(p, NULL, 10);
+        return 0;
+    } else {
+        /* check here if it's a uuid and do proper conversion */
+    }
+    return 1;
+}
+
+static int domain_qualifier_to_domid(const char *p, uint32_t *domid_r,
+                                     int *was_name_r)
+{
+    int was_name;
+
+    was_name = qualifier_to_id(p, domid_r);
+    if (was_name_r) *was_name_r = was_name;
+    return was_name ? libxl_name_to_domid(&ctx, p, domid_r) : 0;
+}
+
+static void find_domain(const char *p)
+{
+    int rc, was_name;
+
+    rc = domain_qualifier_to_domid(p, &domid, &was_name);
+    if (rc) {
+        fprintf(stderr, "%s is an invalid domain identifier (rc=%d)\n", p, rc);
+        exit(2);
+    }
+    common_domname = was_name ? p : libxl_domid_to_name(&ctx, domid);
+}
+
+#define LOG(_f, _a...)   dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
+
+void dolog(const char *file, int line, const char *func, char *fmt, ...)
+{
+    va_list ap;
+    char *s;
+    int rc;
+
+    va_start(ap, fmt);
+    rc = vasprintf(&s, fmt, ap);
+    va_end(ap);
+    if (rc >= 0)
+        libxl_write_exactly(NULL, logfile, s, rc, NULL, NULL);
+}
+
+static void init_create_info(libxl_domain_create_info *c_info)
+{
+    memset(c_info, '\0', sizeof(*c_info));
+    c_info->xsdata = NULL;
+    c_info->platformdata = NULL;
+    c_info->hap = 1;
+    c_info->hvm = 1;
+    c_info->oos = 1;
+    c_info->ssidref = 0;
+}
+
+static void init_build_info(libxl_domain_build_info *b_info, 
libxl_domain_create_info *c_info)
+{
+    memset(b_info, '\0', sizeof(*b_info));
+    b_info->timer_mode = -1;
+    b_info->hpet = 1;
+    b_info->vpt_align = -1;
+    b_info->max_vcpus = 1;
+    b_info->max_memkb = 32 * 1024;
+    b_info->target_memkb = b_info->max_memkb;
+    if (c_info->hvm) {
+        b_info->shadow_memkb = 0; /* Set later */
+        b_info->video_memkb = 8 * 1024;
+        b_info->kernel = "hvmloader";
+        b_info->hvm = 1;
+        b_info->u.hvm.pae = 1;
+        b_info->u.hvm.apic = 1;
+        b_info->u.hvm.acpi = 1;
+        b_info->u.hvm.nx = 1;
+        b_info->u.hvm.viridian = 0;
+    } else {
+        b_info->u.pv.slack_memkb = 8 * 1024;
+    }
+}
+
+static void init_dm_info(libxl_device_model_info *dm_info,
+        libxl_domain_create_info *c_info, libxl_domain_build_info *b_info)
+{
+    int i;
+    memset(dm_info, '\0', sizeof(*dm_info));
+
+    for (i = 0; i < 16; i++) {
+        dm_info->uuid[i] = rand();
+    }
+
+    dm_info->dom_name = c_info->name;
+    dm_info->device_model = "qemu-dm";
+    dm_info->videoram = b_info->video_memkb / 1024;
+    dm_info->apic = b_info->u.hvm.apic;
+    dm_info->vcpus = b_info->max_vcpus;
+    dm_info->vcpu_avail = b_info->cur_vcpus;
+
+    dm_info->stdvga = 0;
+    dm_info->vnc = 1;
+    dm_info->vnclisten = "127.0.0.1";
+    dm_info->vncdisplay = 0;
+    dm_info->vncunused = 1;
+    dm_info->keymap = NULL;
+    dm_info->sdl = 0;
+    dm_info->opengl = 0;
+    dm_info->nographic = 0;
+    dm_info->serial = NULL;
+    dm_info->boot = "cda";
+    dm_info->usb = 0;
+    dm_info->usbdevice = NULL;
+    dm_info->xen_platform_pci = 1;
+}
+
+static void init_nic_info(libxl_device_nic *nic_info, int devnum)
+{
+    memset(nic_info, '\0', sizeof(*nic_info));
+
+    nic_info->backend_domid = 0;
+    nic_info->domid = 0;
+    nic_info->devid = devnum;
+    nic_info->mtu = 1492;
+    nic_info->model = "e1000";
+    nic_info->mac[0] = 0x00;
+    nic_info->mac[1] = 0x16;
+    nic_info->mac[2] = 0x3e;
+    nic_info->mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
+    nic_info->mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
+    nic_info->mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
+    nic_info->ifname = NULL;
+    nic_info->bridge = "xenbr0";
+    CHK_ERRNO( asprintf(&nic_info->script, "%s/vif-bridge",
+               libxl_xen_script_dir_path()) );
+    nic_info->nictype = NICTYPE_IOEMU;
+}
+
+static void init_vfb_info(libxl_device_vfb *vfb, int dev_num)
+{
+    memset(vfb, 0x00, sizeof(libxl_device_vfb));
+    vfb->devid = dev_num;
+    vfb->vnc = 1;
+    vfb->vnclisten = "127.0.0.1";
+    vfb->vncdisplay = 0;
+    vfb->vncunused = 1;
+    vfb->keymap = NULL;
+    vfb->sdl = 0;
+    vfb->opengl = 0;
+}
+
+static void init_vkb_info(libxl_device_vkb *vkb, int dev_num)
+{
+    memset(vkb, 0x00, sizeof(libxl_device_vkb));
+    vkb->devid = dev_num;
+}
+
+static void init_console_info(libxl_device_console *console, int dev_num, 
libxl_domain_build_state *state)
+{
+    memset(console, 0x00, sizeof(libxl_device_console));
+    console->devid = dev_num;
+    console->constype = CONSTYPE_XENCONSOLED;
+    if (state)
+        console->build_state = state;
+}
+
+static void printf_info(int domid,
+                        libxl_domain_create_info *c_info,
+                        libxl_domain_build_info *b_info,
+                        libxl_device_disk *disks,
+                        int num_disks,
+                        libxl_device_nic *vifs,
+                        int num_vifs,
+                        libxl_device_pci *pcidevs,
+                        int num_pcidevs,
+                        libxl_device_vfb *vfbs,
+                        int num_vfbs,
+                        libxl_device_vkb *vkb,
+                        int num_vkbs,
+                        libxl_device_model_info *dm_info)
+{
+    int i;
+    printf("(domain\n\t(domid %d)\n", domid);
+    printf("\t(domain_create_info)\n");
+    printf("\t(hvm %d)\n", c_info->hvm);
+    printf("\t(hap %d)\n", c_info->hap);
+    printf("\t(oos %d)\n", c_info->oos);
+    printf("\t(ssidref %d)\n", c_info->ssidref);
+    printf("\t(name %s)\n", c_info->name);
+    printf("\t(uuid " UUID_FMT ")\n",
+           (c_info->uuid)[0], (c_info->uuid)[1], (c_info->uuid)[2], 
(c_info->uuid)[3],
+           (c_info->uuid)[4], (c_info->uuid)[5], (c_info->uuid)[6], 
(c_info->uuid)[7],
+           (c_info->uuid)[8], (c_info->uuid)[9], (c_info->uuid)[10], 
(c_info->uuid)[11],
+           (c_info->uuid)[12], (c_info->uuid)[13], (c_info->uuid)[14], 
(c_info->uuid)[15]);
+    if (c_info->xsdata)
+        printf("\t(xsdata contains data)\n");
+    else
+        printf("\t(xsdata (null))\n");
+    if (c_info->platformdata)
+        printf("\t(platformdata contains data)\n");
+    else
+        printf("\t(platformdata (null))\n");
+
+
+    printf("\t(domain_build_info)\n");
+    printf("\t(timer_mode %d)\n", b_info->timer_mode);
+    printf("\t(hpet %d)\n", b_info->hpet);
+    printf("\t(vpt_align %d)\n", b_info->vpt_align);
+    printf("\t(max_vcpus %d)\n", b_info->max_vcpus);
+    printf("\t(tsc_mode %d)\n", b_info->tsc_mode);
+    printf("\t(max_memkb %d)\n", b_info->max_memkb);
+    printf("\t(target_memkb %d)\n", b_info->target_memkb);
+
+    printf("\t(image\n");
+    if (c_info->hvm) {
+        printf("\t\t(hvm\n");
+        printf("\t\t\t(loader %s)\n", b_info->kernel);
+        printf("\t\t\t(video_memkb %d)\n", b_info->video_memkb);
+        printf("\t\t\t(shadow_memkb %d)\n", b_info->shadow_memkb);
+        printf("\t\t\t(pae %d)\n", b_info->u.hvm.pae);
+        printf("\t\t\t(apic %d)\n", b_info->u.hvm.apic);
+        printf("\t\t\t(acpi %d)\n", b_info->u.hvm.acpi);
+        printf("\t\t\t(nx %d)\n", b_info->u.hvm.nx);
+        printf("\t\t\t(viridian %d)\n", b_info->u.hvm.viridian);
+
+        printf("\t\t\t(device_model %s)\n", dm_info->device_model);
+        printf("\t\t\t(videoram %d)\n", dm_info->videoram);
+        printf("\t\t\t(stdvga %d)\n", dm_info->stdvga);
+        printf("\t\t\t(vnc %d)\n", dm_info->vnc);
+        printf("\t\t\t(vnclisten %s)\n", dm_info->vnclisten);
+        printf("\t\t\t(vncdisplay %d)\n", dm_info->vncdisplay);
+        printf("\t\t\t(vncunused %d)\n", dm_info->vncunused);
+        printf("\t\t\t(keymap %s)\n", dm_info->keymap);
+        printf("\t\t\t(sdl %d)\n", dm_info->sdl);
+        printf("\t\t\t(opengl %d)\n", dm_info->opengl);
+        printf("\t\t\t(nographic %d)\n", dm_info->nographic);
+        printf("\t\t\t(serial %s)\n", dm_info->serial);
+        printf("\t\t\t(boot %s)\n", dm_info->boot);
+        printf("\t\t\t(usb %d)\n", dm_info->usb);
+        printf("\t\t\t(usbdevice %s)\n", dm_info->usbdevice);
+        printf("\t\t\t(apic %d)\n", dm_info->apic);
+        printf("\t\t)\n");
+    } else {
+        printf("\t\t(linux %d)\n", b_info->hvm);
+        printf("\t\t\t(kernel %s)\n", b_info->kernel);
+        printf("\t\t\t(cmdline %s)\n", b_info->u.pv.cmdline);
+        printf("\t\t\t(ramdisk %s)\n", b_info->u.pv.ramdisk);
+        printf("\t\t)\n");
+    }
+    printf("\t)\n");
+
+    for (i = 0; i < num_disks; i++) {
+        printf("\t(device\n");
+        printf("\t\t(tap\n");
+        printf("\t\t\t(backend_domid %d)\n", disks[i].backend_domid);
+        printf("\t\t\t(domid %d)\n", disks[i].domid);
+        printf("\t\t\t(physpath %s)\n", disks[i].physpath);
+        printf("\t\t\t(phystype %d)\n", disks[i].phystype);
+        printf("\t\t\t(virtpath %s)\n", disks[i].virtpath);
+        printf("\t\t\t(unpluggable %d)\n", disks[i].unpluggable);
+        printf("\t\t\t(readwrite %d)\n", disks[i].readwrite);
+        printf("\t\t\t(is_cdrom %d)\n", disks[i].is_cdrom);
+        printf("\t\t)\n");
+        printf("\t)\n");
+    }
+
+    for (i = 0; i < num_vifs; i++) {
+        printf("\t(device\n");
+        printf("\t\t(vif\n");
+        printf("\t\t\t(backend_domid %d)\n", vifs[i].backend_domid);
+        printf("\t\t\t(domid %d)\n", vifs[i].domid);
+        printf("\t\t\t(devid %d)\n", vifs[i].devid);
+        printf("\t\t\t(mtu %d)\n", vifs[i].mtu);
+        printf("\t\t\t(model %s)\n", vifs[i].model);
+        printf("\t\t\t(mac %02x%02x%02x%02x%02x%02x)\n", vifs[i].mac[0], 
vifs[i].mac[1], vifs[i].mac[2], vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
+        printf("\t\t)\n");
+        printf("\t)\n");
+    }
+
+    for (i = 0; i < num_pcidevs; i++) {
+        printf("\t(device\n");
+        printf("\t\t(pci\n");
+        printf("\t\t\t(pci dev "PCI_BDF_VDEVFN")\n", pcidevs[i].domain, 
pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func, pcidevs[i].vdevfn);
+        printf("\t\t\t(opts msitranslate %d power_mgmt %d)\n", 
pcidevs[i].msitranslate, pcidevs[i].power_mgmt);
+        printf("\t\t)\n");
+        printf("\t)\n");
+    }
+
+    for (i = 0; i < num_vfbs; i++) {
+        printf("\t(device\n");
+        printf("\t\t(vfb\n");
+        printf("\t\t\t(backend_domid %d)\n", vfbs[i].backend_domid);
+        printf("\t\t\t(domid %d)\n", vfbs[i].domid);
+        printf("\t\t\t(devid %d)\n", vfbs[i].devid);
+        printf("\t\t\t(vnc %d)\n", vfbs[i].vnc);
+        printf("\t\t\t(vnclisten %s)\n", vfbs[i].vnclisten);
+        printf("\t\t\t(vncdisplay %d)\n", vfbs[i].vncdisplay);
+        printf("\t\t\t(vncunused %d)\n", vfbs[i].vncunused);
+        printf("\t\t\t(keymap %s)\n", vfbs[i].keymap);
+        printf("\t\t\t(sdl %d)\n", vfbs[i].sdl);
+        printf("\t\t\t(opengl %d)\n", vfbs[i].opengl);
+        printf("\t\t\t(display %s)\n", vfbs[i].display);
+        printf("\t\t\t(xauthority %s)\n", vfbs[i].xauthority);
+        printf("\t\t)\n");
+        printf("\t)\n");
+    }
+       printf(")\n");
+}
+
+static void parse_config_data(const char *configfile_filename_report,
+                              const char *configfile_data,
+                              int configfile_len,
+                              libxl_domain_create_info *c_info,
+                              libxl_domain_build_info *b_info,
+                              libxl_device_disk **disks,
+                              int *num_disks,
+                              libxl_device_nic **vifs,
+                              int *num_vifs,
+                              libxl_device_pci **pcidevs,
+                              int *num_pcidevs,
+                              libxl_device_vfb **vfbs,
+                              int *num_vfbs,
+                              libxl_device_vkb **vkbs,
+                              int *num_vkbs,
+                              libxl_device_model_info *dm_info)
+{
+    const char *buf;
+    long l;
+    XLU_Config *config;
+    XLU_ConfigList *vbds, *nics, *pcis, *cvfbs;
+    int pci_power_mgmt = 0;
+    int pci_msitranslate = 1;
+    int i, e;
+
+    config= xlu_cfg_init(stderr, configfile_filename_report);
+    if (!config) {
+        fprintf(stderr, "Failed to allocate for configuration\n");
+        exit(1);
+    }
+
+    e= xlu_cfg_readdata(config, configfile_data, configfile_len);
+    if (e) {
+        fprintf(stderr, "Failed to parse config file: %s\n", strerror(e));
+        exit(1);
+    }
+
+    init_create_info(c_info);
+
+    c_info->hvm = 0;
+    if (!xlu_cfg_get_string (config, "builder", &buf) &&
+        !strncmp(buf, "hvm", strlen(buf)))
+        c_info->hvm = 1;
+
+    if (!xlu_cfg_get_long (config, "hap", &l))
+        c_info->hap = l;
+
+    if (!xlu_cfg_get_string (config, "name", &buf))
+        c_info->name = strdup(buf);
+    else
+        c_info->name = "test";
+    for (i = 0; i < 16; i++) {
+        c_info->uuid[i] = rand();
+    }
+
+    if (!xlu_cfg_get_long(config, "oos", &l))
+        c_info->oos = l;
+
+    init_build_info(b_info, c_info);
+
+    /* the following is the actual config parsing with overriding values in 
the structures */
+    if (!xlu_cfg_get_long (config, "vcpus", &l)) {
+        b_info->max_vcpus = l;
+        b_info->cur_vcpus = (1 << l) - 1;
+    }
+
+    if (!xlu_cfg_get_long (config, "memory", &l)) {
+        b_info->max_memkb = l * 1024;
+        b_info->target_memkb = b_info->max_memkb;
+    }
+
+    /* libxl_get_required_shadow_memory() must be called after final values
+     * (default or specified) for vcpus and memory are set, because the
+     * calculation depends on those values. */
+    b_info->shadow_memkb = !xlu_cfg_get_long(config, "shadow_memory", &l)
+        ? l * 1024
+        : libxl_get_required_shadow_memory(b_info->max_memkb,
+                                           b_info->max_vcpus);
+
+    if (!xlu_cfg_get_long(config, "tsc_mode", &l))
+        b_info->tsc_mode = l;
+
+    if (!xlu_cfg_get_long (config, "videoram", &l))
+        b_info->video_memkb = l * 1024;
+
+    if (!xlu_cfg_get_string (config, "kernel", &buf))
+        b_info->kernel = strdup(buf);
+
+    if (c_info->hvm == 1) {
+        if (!xlu_cfg_get_long (config, "pae", &l))
+            b_info->u.hvm.pae = l;
+        if (!xlu_cfg_get_long (config, "apic", &l))
+            b_info->u.hvm.apic = l;
+        if (!xlu_cfg_get_long (config, "acpi", &l))
+            b_info->u.hvm.acpi = l;
+        if (!xlu_cfg_get_long (config, "nx", &l))
+            b_info->u.hvm.nx = l;
+        if (!xlu_cfg_get_long (config, "viridian", &l))
+            b_info->u.hvm.viridian = l;
+    } else {
+        char *cmdline = NULL;
+        const char *root = NULL, *extra = "";
+
+        xlu_cfg_get_string (config, "root", &root);
+        xlu_cfg_get_string (config, "extra", &extra);
+
+        if (root) {
+            if (asprintf(&cmdline, "root=%s %s", root, extra) == -1)
+                cmdline = NULL;
+        } else {
+            cmdline = strdup(extra);
+        }
+
+        if ((root || extra) && !cmdline) {
+            fprintf(stderr, "Failed to allocate memory for cmdline\n");
+            exit(1);
+        }
+
+        b_info->u.pv.cmdline = cmdline;
+        if (!xlu_cfg_get_string (config, "ramdisk", &buf))
+            b_info->u.pv.ramdisk = strdup(buf);
+    }
+
+    if (!xlu_cfg_get_list (config, "disk", &vbds, 0)) {
+        *num_disks = 0;
+        *disks = NULL;
+        while ((buf = xlu_cfg_get_listitem (vbds, *num_disks)) != NULL) {
+            char *buf2 = strdup(buf);
+            char *p, *p2;
+            *disks = (libxl_device_disk *) realloc(*disks, sizeof 
(libxl_device_disk) * ((*num_disks) + 1));
+            (*disks)[*num_disks].backend_domid = 0;
+            (*disks)[*num_disks].domid = 0;
+            (*disks)[*num_disks].unpluggable = 0;
+            p = strtok(buf2, ",:");
+            while (*p == ' ')
+                p++;
+            if (!strcmp(p, "phy")) {
+                (*disks)[*num_disks].phystype = PHYSTYPE_PHY;
+            } else if (!strcmp(p, "file")) {
+                (*disks)[*num_disks].phystype = PHYSTYPE_FILE;
+            } else if (!strcmp(p, "tap")) {
+                p = strtok(NULL, ":");
+                if (!strcmp(p, "aio")) {
+                    (*disks)[*num_disks].phystype = PHYSTYPE_AIO;
+                } else if (!strcmp(p, "vhd")) {
+                    (*disks)[*num_disks].phystype = PHYSTYPE_VHD;
+                } else if (!strcmp(p, "qcow")) {
+                    (*disks)[*num_disks].phystype = PHYSTYPE_QCOW;
+                } else if (!strcmp(p, "qcow2")) {
+                    (*disks)[*num_disks].phystype = PHYSTYPE_QCOW2;
+                }
+            }
+            p = strtok(NULL, ",");
+            while (*p == ' ')
+                p++;
+            (*disks)[*num_disks].physpath= strdup(p);
+            p = strtok(NULL, ",");
+            while (*p == ' ')
+                p++;
+            p2 = strchr(p, ':');
+            if (p2 == NULL) {
+                (*disks)[*num_disks].virtpath = strdup(p);
+                (*disks)[*num_disks].is_cdrom = 0;
+                (*disks)[*num_disks].unpluggable = 1;
+            } else {
+                *p2 = '\0';
+                (*disks)[*num_disks].virtpath = strdup(p);
+                if (!strcmp(p2 + 1, "cdrom")) {
+                    (*disks)[*num_disks].is_cdrom = 1;
+                    (*disks)[*num_disks].unpluggable = 1;
+                } else
+                    (*disks)[*num_disks].is_cdrom = 0;
+            }
+            p = strtok(NULL, ",");
+            while (*p == ' ')
+                p++;
+            (*disks)[*num_disks].readwrite = (p[0] == 'w') ? 1 : 0;
+            free(buf2);
+            *num_disks = (*num_disks) + 1;
+        }
+    }
+
+    if (!xlu_cfg_get_list (config, "vif", &nics, 0)) {
+        *num_vifs = 0;
+        *vifs = NULL;
+        while ((buf = xlu_cfg_get_listitem (nics, *num_vifs)) != NULL) {
+            char *buf2 = strdup(buf);
+            char *p, *p2;
+            *vifs = (libxl_device_nic *) realloc(*vifs, sizeof 
(libxl_device_nic) * ((*num_vifs) + 1));
+            init_nic_info((*vifs) + (*num_vifs), (*num_vifs) + 1);
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip;
+            do {
+                while (*p == ' ')
+                    p++;
+                if ((p2 = strchr(p, '=')) == NULL)
+                    break;
+                *p2 = '\0';
+                if (!strcmp(p, "model")) {
+                    (*vifs)[*num_vifs].model = strdup(p2 + 1);
+                } else if (!strcmp(p, "mac")) {
+                    char *p3 = p2 + 1;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[0] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[1] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[2] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[3] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[4] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[5] = strtol(p3, NULL, 16);
+                } else if (!strcmp(p, "bridge")) {
+                    (*vifs)[*num_vifs].bridge = strdup(p2 + 1);
+                } else if (!strcmp(p, "type")) {
+                    if (!strcmp(p2 + 1, "ioemu"))
+                        (*vifs)[*num_vifs].nictype = NICTYPE_IOEMU;
+                    else
+                        (*vifs)[*num_vifs].nictype = NICTYPE_VIF;
+                } else if (!strcmp(p, "ip")) {
+                    inet_pton(AF_INET, p2 + 1, &((*vifs)[*num_vifs].ip));
+                } else if (!strcmp(p, "script")) {
+                    (*vifs)[*num_vifs].script = strdup(p2 + 1);
+                } else if (!strcmp(p, "vifname")) {
+                    (*vifs)[*num_vifs].ifname = strdup(p2 + 1);
+                } else if (!strcmp(p, "rate")) {
+                    fprintf(stderr, "the rate parameter for vifs is currently 
not supported\n");
+                } else if (!strcmp(p, "accel")) {
+                    fprintf(stderr, "the accel parameter for vifs is currently 
not supported\n");
+                }
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip:
+            free(buf2);
+            *num_vifs = (*num_vifs) + 1;
+        }
+    }
+
+    if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0)) {
+        *num_vfbs = 0;
+        *num_vkbs = 0;
+        *vfbs = NULL;
+        *vkbs = NULL;
+        while ((buf = xlu_cfg_get_listitem (cvfbs, *num_vfbs)) != NULL) {
+            char *buf2 = strdup(buf);
+            char *p, *p2;
+            *vfbs = (libxl_device_vfb *) realloc(*vfbs, 
sizeof(libxl_device_vfb) * ((*num_vfbs) + 1));
+            init_vfb_info((*vfbs) + (*num_vfbs), (*num_vfbs));
+
+            *vkbs = (libxl_device_vkb *) realloc(*vkbs, 
sizeof(libxl_device_vkb) * ((*num_vkbs) + 1));
+            init_vkb_info((*vkbs) + (*num_vkbs), (*num_vkbs));
+
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_vfb;
+            do {
+                while (*p == ' ')
+                    p++;
+                if ((p2 = strchr(p, '=')) == NULL)
+                    break;
+                *p2 = '\0';
+                if (!strcmp(p, "vnc")) {
+                    (*vfbs)[*num_vfbs].vnc = atoi(p2 + 1);
+                } else if (!strcmp(p, "vnclisten")) {
+                    (*vfbs)[*num_vfbs].vnclisten = strdup(p2 + 1);
+                } else if (!strcmp(p, "vncpasswd")) {
+                    (*vfbs)[*num_vfbs].vncpasswd = strdup(p2 + 1);
+                } else if (!strcmp(p, "vncdisplay")) {
+                    (*vfbs)[*num_vfbs].vncdisplay = atoi(p2 + 1);
+                } else if (!strcmp(p, "vncunused")) {
+                    (*vfbs)[*num_vfbs].vncunused = atoi(p2 + 1);
+                } else if (!strcmp(p, "keymap")) {
+                    (*vfbs)[*num_vfbs].keymap = strdup(p2 + 1);
+                } else if (!strcmp(p, "sdl")) {
+                    (*vfbs)[*num_vfbs].sdl = atoi(p2 + 1);
+                } else if (!strcmp(p, "opengl")) {
+                    (*vfbs)[*num_vfbs].opengl = atoi(p2 + 1);
+                } else if (!strcmp(p, "display")) {
+                    (*vfbs)[*num_vfbs].display = strdup(p2 + 1);
+                } else if (!strcmp(p, "xauthority")) {
+                    (*vfbs)[*num_vfbs].xauthority = strdup(p2 + 1);
+                }
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip_vfb:
+            free(buf2);
+            *num_vfbs = (*num_vfbs) + 1;
+            *num_vkbs = (*num_vkbs) + 1;
+        }
+    }
+
+    if (!xlu_cfg_get_long (config, "pci_msitranslate", &l))
+        pci_msitranslate = l;
+
+    if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l))
+        pci_power_mgmt = l;
+
+    if (!xlu_cfg_get_list (config, "pci", &pcis, 0)) {
+        *num_pcidevs = 0;
+        *pcidevs = NULL;
+        while ((buf = xlu_cfg_get_listitem (pcis, *num_pcidevs)) != NULL) {
+            unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
+            char *buf2 = strdup(buf);
+            char *p;
+            *pcidevs = (libxl_device_pci *) realloc(*pcidevs, sizeof 
(libxl_device_pci) * ((*num_pcidevs) + 1));
+            memset(*pcidevs + *num_pcidevs, 0x00, sizeof(libxl_device_pci));
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_pci;
+            if (!sscanf(p, PCI_BDF_VDEVFN, &domain, &bus, &dev, &func, 
&vdevfn)) {
+                sscanf(p, "%02x:%02x.%01x@%02x", &bus, &dev, &func, &vdevfn);
+                domain = 0;
+            }
+            libxl_device_pci_init(*pcidevs + *num_pcidevs, domain, bus, dev, 
func, vdevfn);
+            (*pcidevs)[*num_pcidevs].msitranslate = pci_msitranslate;
+            (*pcidevs)[*num_pcidevs].power_mgmt = pci_power_mgmt;
+            while ((p = strtok(NULL, ",=")) != NULL) {
+                while (*p == ' ')
+                    p++;
+                if (!strcmp(p, "msitranslate")) {
+                    p = strtok(NULL, ",=");
+                    (*pcidevs)[*num_pcidevs].msitranslate = atoi(p);
+                } else if (!strcmp(p, "power_mgmt")) {
+                    p = strtok(NULL, ",=");
+                    (*pcidevs)[*num_pcidevs].power_mgmt = atoi(p);
+                }
+            }
+            *num_pcidevs = (*num_pcidevs) + 1;
+skip_pci:
+            free(buf2);
+        }
+    }
+
+    if (c_info->hvm == 1) {
+        /* init dm from c and b */
+        init_dm_info(dm_info, c_info, b_info);
+
+        /* then process config related to dm */
+        if (!xlu_cfg_get_string (config, "device_model", &buf))
+            dm_info->device_model = strdup(buf);
+        if (!xlu_cfg_get_long (config, "stdvga", &l))
+            dm_info->stdvga = l;
+        if (!xlu_cfg_get_long (config, "vnc", &l))
+            dm_info->vnc = l;
+        if (!xlu_cfg_get_string (config, "vnclisten", &buf))
+            dm_info->vnclisten = strdup(buf);
+        if (!xlu_cfg_get_string (config, "vncpasswd", &buf))
+            dm_info->vncpasswd = strdup(buf);
+        if (!xlu_cfg_get_long (config, "vncdisplay", &l))
+            dm_info->vncdisplay = l;
+        if (!xlu_cfg_get_long (config, "vncunused", &l))
+            dm_info->vncunused = l;
+        if (!xlu_cfg_get_string (config, "keymap", &buf))
+            dm_info->keymap = strdup(buf);
+        if (!xlu_cfg_get_long (config, "sdl", &l))
+            dm_info->sdl = l;
+        if (!xlu_cfg_get_long (config, "opengl", &l))
+            dm_info->opengl = l;
+        if (!xlu_cfg_get_long (config, "nographic", &l))
+            dm_info->nographic = l;
+        if (!xlu_cfg_get_string (config, "serial", &buf))
+            dm_info->serial = strdup(buf);
+        if (!xlu_cfg_get_string (config, "boot", &buf))
+            dm_info->boot = strdup(buf);
+        if (!xlu_cfg_get_long (config, "usb", &l))
+            dm_info->usb = l;
+        if (!xlu_cfg_get_string (config, "usbdevice", &buf))
+            dm_info->usbdevice = strdup(buf);
+        if (!xlu_cfg_get_long (config, "xen_platform_pci", &l))
+            dm_info->xen_platform_pci = l;
+    }
+
+    dm_info->type = c_info->hvm ? XENFV : XENPV;
+
+    xlu_cfg_destroy(config);
+}
+
+static void *xmalloc(size_t sz) {
+    void *r;
+    r = malloc(sz);
+    if (!r) { fprintf(stderr,"xl: Unable to malloc %lu bytes.\n",
+                      (unsigned long)sz); exit(-ERROR_FAIL); }
+    return r;
+}
+
+static void *xrealloc(void *ptr, size_t sz) {
+    void *r;
+    if (!sz) { free(ptr); return 0; }
+      /* realloc(non-0, 0) has a useless return value;
+       * but xrealloc(anything, 0) is like free
+       */
+    r = realloc(ptr, sz);
+    if (!r) { fprintf(stderr,"xl: Unable to realloc to %lu bytes.\n",
+                      (unsigned long)sz); exit(-ERROR_FAIL); }
+    return r;
+}
+
+struct domain_create {
+    int debug;
+    int daemonize;
+    int paused;
+    int dryrun;
+    int quiet;
+    const char *config_file;
+    const char *extra_config; /* extra config string */
+    const char *restore_file;
+    int migrate_fd; /* -1 means none */
+    char **migration_domname_r;
+};
+
+static int create_domain(struct domain_create *dom_info)
+{
+    libxl_domain_create_info info1;
+    libxl_domain_build_info info2;
+    libxl_domain_build_state state;
+    libxl_device_model_info dm_info;
+    libxl_device_disk *disks = NULL;
+    libxl_device_nic *vifs = NULL;
+    libxl_device_pci *pcidevs = NULL;
+    libxl_device_vfb *vfbs = NULL;
+    libxl_device_vkb *vkbs = NULL;
+    libxl_device_console console;
+
+    int debug = dom_info->debug;
+    int daemonize = dom_info->daemonize;
+    int paused = dom_info->paused;
+    const char *config_file = dom_info->config_file;
+    const char *extra_config = dom_info->extra_config;
+    const char *restore_file = dom_info->restore_file;
+    int migrate_fd = dom_info->migrate_fd;
+    char **migration_domname_r = dom_info->migration_domname_r;
+
+    int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 
0;
+    int i, fd;
+    int need_daemon = 1;
+    int ret, rc;
+    libxl_device_model_starting *dm_starting = 0;
+    libxl_waiter *w1 = NULL, *w2 = NULL;
+    void *config_data = 0;
+    int config_len = 0;
+    int restore_fd = -1;
+    struct save_file_header hdr;
+
+    memset(&dm_info, 0x00, sizeof(dm_info));
+
+    if (restore_file) {
+        uint8_t *optdata_begin = 0;
+        const uint8_t *optdata_here = 0;
+        union { uint32_t u32; char b[4]; } u32buf;
+        uint32_t badflags;
+
+        restore_fd = migrate_fd >= 0 ? migrate_fd :
+            open(restore_file, O_RDONLY);
+
+        CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, &hdr,
+                   sizeof(hdr), restore_file, "header") );
+        if (memcmp(hdr.magic, savefileheader_magic, sizeof(hdr.magic))) {
+            fprintf(stderr, "File has wrong magic number -"
+                    " corrupt or for a different tool?\n");
+            return ERROR_INVAL;
+        }
+        if (hdr.byteorder != SAVEFILE_BYTEORDER_VALUE) {
+            fprintf(stderr, "File has wrong byte order\n");
+            return ERROR_INVAL;
+        }
+        fprintf(stderr, "Loading new save file %s"
+                " (new xl fmt info"
+                " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
+                restore_file, hdr.mandatory_flags, hdr.optional_flags,
+                hdr.optional_data_len);
+
+        badflags = hdr.mandatory_flags & ~( 0 /* none understood yet */ );
+        if (badflags) {
+            fprintf(stderr, "Savefile has mandatory flag(s) 0x%"PRIx32" "
+                    "which are not supported; need newer xl\n",
+                    badflags);
+            return ERROR_INVAL;
+        }
+        if (hdr.optional_data_len) {
+            optdata_begin = xmalloc(hdr.optional_data_len);
+            CHK_ERRNO( libxl_read_exactly(&ctx, restore_fd, optdata_begin,
+                   hdr.optional_data_len, restore_file, "optdata") );
+        }
+
+#define OPTDATA_LEFT  (hdr.optional_data_len - (optdata_here - optdata_begin))
+#define WITH_OPTDATA(amt, body)                                 \
+            if (OPTDATA_LEFT < (amt)) {                         \
+                fprintf(stderr, "Savefile truncated.\n");       \
+                return ERROR_INVAL;                             \
+            } else {                                            \
+                body;                                           \
+                optdata_here += (amt);                          \
+            }
+
+        optdata_here = optdata_begin;
+
+        if (OPTDATA_LEFT) {
+            fprintf(stderr, " Savefile contains xl domain config\n");
+            WITH_OPTDATA(4, {
+                memcpy(u32buf.b, optdata_here, 4);
+                config_len = u32buf.u32;
+            });
+            WITH_OPTDATA(config_len, {
+                config_data = xmalloc(config_len);
+                memcpy(config_data, optdata_here, config_len);
+            });
+        }
+
+    }
+
+    if (config_file) {
+        free(config_data);  config_data = 0;
+        ret = libxl_read_file_contents(&ctx, config_file,
+                                       &config_data, &config_len);
+        if (ret) { fprintf(stderr, "Failed to read config file: %s: %s\n",
+                           config_file, strerror(errno)); return ERROR_FAIL; }
+        if (!restore_file && extra_config
+            && strlen(extra_config)) {
+            if (config_len > INT_MAX - (strlen(extra_config) + 2)) {
+                fprintf(stderr, "Failed to attach extra configration\n");
+                return ERROR_FAIL;
+            }
+            config_data = realloc(config_data, config_len
+                + strlen(extra_config) + 2);
+            if (!config_data) {
+                fprintf(stderr, "Failed to realloc config_data\n");
+                return ERROR_FAIL;
+            }
+            strcat(config_data, "\n");
+            strcat(config_data, extra_config);
+            strcat(config_data, "\n");
+            config_len += (strlen(extra_config) + 2);
+        }
+    } else {
+        if (!config_data) {
+            fprintf(stderr, "Config file not specified and"
+                    " none in save file\n");
+            return ERROR_INVAL;
+        }
+        config_file = "<saved>";
+    }
+
+    if (!dom_info->quiet)
+        printf("Parsing config file %s\n", config_file);
+
+    parse_config_data(config_file, config_data, config_len, &info1, &info2, 
&disks, &num_disks, &vifs, &num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, 
&vkbs, &num_vkbs, &dm_info);
+
+    if (dom_info->dryrun)
+        return 0;
+
+    if (migrate_fd >= 0) {
+        if (info1.name) {
+            /* when we receive a domain we get its name from the config
+             * file; and we receive it to a temporary name */
+            assert(!common_domname);
+            common_domname = info1.name;
+            if (asprintf(migration_domname_r, "%s--incoming", info1.name) < 0) 
{
+                fprintf(stderr, "Failed to allocate memory in asprintf\n");
+                exit(1);
+            }
+            info1.name = *migration_domname_r;
+        }
+    }
+
+    if (debug)
+        printf_info(-1, &info1, &info2, disks, num_disks, vifs, num_vifs, 
pcidevs, num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
+
+start:
+    domid = 0;
+
+    ret = libxl_domain_make(&ctx, &info1, &domid);
+    if (ret) {
+        fprintf(stderr, "cannot make domain: %d\n", ret);
+        ret = ERROR_FAIL;
+        goto error_out;
+    }
+
+    ret = libxl_userdata_store(&ctx, domid, "xl",
+                                    config_data, config_len);
+    if (ret) {
+        perror("cannot save config file");
+        ret = ERROR_FAIL;
+        goto error_out;
+    }
+
+    if (!restore_file || !need_daemon) {
+        if (dm_info.saved_state) {
+            free(dm_info.saved_state);
+            dm_info.saved_state = NULL;
+        }
+        ret = libxl_domain_build(&ctx, &info2, domid, &state);
+    } else {
+        ret = libxl_domain_restore(&ctx, &info2, domid, restore_fd, &state, 
&dm_info);
+    }
+
+    if (ret) {
+        fprintf(stderr, "cannot (re-)build domain: %d\n", ret);
+        ret = ERROR_FAIL;
+        goto error_out;
+    }
+
+    for (i = 0; i < num_disks; i++) {
+        disks[i].domid = domid;
+        ret = libxl_device_disk_add(&ctx, domid, &disks[i]);
+        if (ret) {
+            fprintf(stderr, "cannot add disk %d to domain: %d\n", i, ret);
+            ret = ERROR_FAIL;
+            goto error_out;
+        }
+    }
+    for (i = 0; i < num_vifs; i++) {
+        vifs[i].domid = domid;
+        ret = libxl_device_nic_add(&ctx, domid, &vifs[i]);
+        if (ret) {
+            fprintf(stderr, "cannot add nic %d to domain: %d\n", i, ret);
+            ret = ERROR_FAIL;
+            goto error_out;
+        }
+    }
+    if (info1.hvm) {
+        dm_info.domid = domid;
+        MUST( libxl_create_device_model(&ctx, &dm_info, disks, num_disks,
+                                        vifs, num_vifs, &dm_starting) );
+    } else {
+        for (i = 0; i < num_vfbs; i++) {
+            vfbs[i].domid = domid;
+            libxl_device_vfb_add(&ctx, domid, &vfbs[i]);
+            vkbs[i].domid = domid;
+            libxl_device_vkb_add(&ctx, domid, &vkbs[i]);
+        }
+        init_console_info(&console, 0, &state);
+        console.domid = domid;
+        if (num_vfbs)
+            console.constype = CONSTYPE_IOEMU;
+        libxl_device_console_add(&ctx, domid, &console);
+        if (num_vfbs)
+            libxl_create_xenpv_qemu(&ctx, vfbs, 1, &console, &dm_starting);
+    }
+
+    if (dm_starting)
+        MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) );
+    for (i = 0; i < num_pcidevs; i++)
+        libxl_device_pci_add(&ctx, domid, &pcidevs[i]);
+
+    if (!paused)
+        libxl_domain_unpause(&ctx, domid);
+
+    if (!daemonize)
+        return domid; /* caller gets success in parent */
+
+    if (need_daemon) {
+        char *fullname, *name;
+        pid_t child1, got_child;
+        int nullfd;
+
+        child1 = libxl_fork(&ctx);
+        if (child1) {
+            int status;
+            for (;;) {
+                got_child = waitpid(child1, &status, 0);
+                if (got_child == child1) break;
+                assert(got_child == -1);
+                if (errno != EINTR) {
+                    perror("failed to wait for daemonizing child");
+                    ret = ERROR_FAIL;
+                    goto error_out;
+                }
+            }
+            if (status) {
+                libxl_report_child_exitstatus(&ctx, XL_LOG_ERROR,
+                           "daemonizing child", child1, status);
+                ret = ERROR_FAIL;
+                goto error_out;
+            }
+            return domid; /* caller gets success in parent */
+        }
+
+        rc = libxl_ctx_postfork(&ctx);
+        if (rc) {
+            LOG("failed to reinitialise context after fork");
+            exit(-1);
+        }
+
+        if (asprintf(&name, "xl-%s", info1.name) < 0) {
+            LOG("Failed to allocate memory in asprintf");
+            exit(1);
+        }
+        rc = libxl_create_logfile(&ctx, name, &fullname);
+        if (rc) {
+            LOG("failed to open logfile %s",fullname,strerror(errno));
+            exit(-1);
+        }
+
+        CHK_ERRNO(( logfile = open(fullname, O_WRONLY|O_CREAT, 0644) )<0);
+        free(fullname);
+        free(name);
+
+        CHK_ERRNO(( nullfd = open("/dev/null", O_RDONLY) )<0);
+        dup2(nullfd, 0);
+        dup2(logfile, 1);
+        dup2(logfile, 2);
+
+        CHK_ERRNO(daemon(0, 1) < 0);
+        need_daemon = 0;
+    }
+    LOG("Waiting for domain %s (domid %d) to die [pid %ld]",
+        info1.name, domid, (long)getpid());
+    w1 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter) * num_disks);
+    w2 = (libxl_waiter*) xmalloc(sizeof(libxl_waiter));
+    libxl_wait_for_disk_ejects(&ctx, domid, disks, num_disks, w1);
+    libxl_wait_for_domain_death(&ctx, domid, w2);
+    libxl_get_wait_fd(&ctx, &fd);
+    while (1) {
+        int ret;
+        fd_set rfds;
+        xc_domaininfo_t info;
+        libxl_event event;
+        libxl_device_disk disk;
+        memset(&info, 0x00, sizeof(xc_domaininfo_t));
+
+        FD_ZERO(&rfds);
+        FD_SET(fd, &rfds);
+
+        ret = select(fd + 1, &rfds, NULL, NULL, NULL);
+        if (!ret)
+            continue;
+        libxl_get_event(&ctx, &event);
+        switch (event.type) {
+            case DOMAIN_DEATH:
+                if (libxl_event_get_domain_death_info(&ctx, domid, &event, 
&info)) {
+                    LOG("Domain %d is dead", domid);
+                    if (info.flags & XEN_DOMINF_dying || (info.flags & 
XEN_DOMINF_shutdown && (((info.flags >> XEN_DOMINF_shutdownshift) & 
XEN_DOMINF_shutdownmask) != SHUTDOWN_suspend))) {
+                        LOG("Domain %d needs to be clean: destroying the 
domain", domid);
+                        libxl_domain_destroy(&ctx, domid, 0);
+                        if (info.flags & XEN_DOMINF_shutdown &&
+                            (((info.flags >> XEN_DOMINF_shutdownshift) & 
XEN_DOMINF_shutdownmask) == SHUTDOWN_reboot)) {
+                            libxl_free_waiter(w1);
+                            libxl_free_waiter(w2);
+                            free(w1);
+                            free(w2);
+                            LOG("Done. Rebooting now");
+                            /*
+                             * XXX FIXME: If this sleep is not there then
+                             * domain re-creation fails sometimes.
+                             */
+                            sleep(2);
+                            goto start;
+                        }
+                        LOG("Done. Exiting now");
+                    }
+                    LOG("Domain %d does not need to be clean, exiting now", 
domid);
+                    exit(0);
+                }
+                break;
+            case DISK_EJECT:
+                if (libxl_event_get_disk_eject_info(&ctx, domid, &event, 
&disk))
+                    libxl_cdrom_insert(&ctx, domid, &disk);
+                break;
+        }
+        libxl_free_event(&event);
+    }
+
+    close(logfile);
+    exit(0);
+
+error_out:
+    if (domid)
+        libxl_domain_destroy(&ctx, domid, 0);
+    return ret;
+}
+
+void help(char *command)
+{
+    int i;
+    struct cmd_spec *cmd;
+
+    if (!command || !strcmp(command, "help")) {
+        printf("Usage xl [-v] <subcommand> [args]\n\n");
+        printf("xl full list of subcommands:\n\n");
+        for (i = 0; i < cmdtable_len; i++)
+            printf(" %-20s%s\n",
+                   cmd_table[i].cmd_name, cmd_table[i].cmd_desc);
+    } else {
+        cmd = cmdtable_lookup(command);
+        if (cmd) {
+            printf("Usage: xl [-v] %s %s\n\n%s.\n\n",
+                   cmd->cmd_name,
+                   cmd->cmd_usage,
+                   cmd->cmd_desc);
+            if (cmd->cmd_option)
+                printf("Options:\n\n%s\n", cmd->cmd_option);
+        }
+        else {
+            printf("command \"%s\" not implemented\n", command);
+        }
+    }
+}
+
+static int64_t parse_mem_size_kb(char *mem)
+{
+    char *endptr;
+    int64_t kbytes;
+
+    kbytes = strtoll(mem, &endptr, 10);
+
+    if (strlen(endptr) > 1)
+        return -1;
+
+    switch (tolower((uint8_t)*endptr)) {
+    case 't':
+        kbytes <<= 10;
+    case 'g':
+        kbytes <<= 10;
+    case '\0':
+    case 'm':
+        kbytes <<= 10;
+    case 'k':
+        break;
+    case 'b':
+        kbytes >>= 10;
+        break;
+    default:
+        return -1;
+    }
+
+    return kbytes;
+}
+
+int set_memory_max(char *p, char *mem)
+{
+    int64_t memorykb;
+    int rc;
+
+    find_domain(p);
+
+    memorykb = parse_mem_size_kb(mem);
+    if (memorykb == -1) {
+        fprintf(stderr, "invalid memory size: %s\n", mem);
+        exit(3);
+    }
+
+    rc = libxl_domain_setmaxmem(&ctx, domid, memorykb);
+
+    return rc;
+}
+
+int main_memmax(int argc, char **argv)
+{
+    int opt = 0;
+    char *p = NULL, *mem;
+    int rc;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("mem-max");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 1) {
+        help("mem-max");
+        exit(2);
+    }
+
+    p = argv[optind];
+    mem = argv[optind + 1];
+
+    rc = set_memory_max(p, mem);
+    if (rc) {
+        fprintf(stderr, "cannot set domid %d static max memory to : %s\n", 
domid, mem);
+        exit(1);
+    }
+
+    exit(0);
+}
+
+void set_memory_target(char *p, char *mem)
+{
+    long long int memorykb;
+
+    find_domain(p);
+
+    memorykb = parse_mem_size_kb(mem);
+    if (memorykb == -1)  {
+        fprintf(stderr, "invalid memory size: %s\n", mem);
+        exit(3);
+    }
+
+    libxl_set_memory_target(&ctx, domid, memorykb, /* enforce */ 1);
+}
+
+int main_memset(int argc, char **argv)
+{
+    int opt = 0;
+    char *p = NULL, *mem;
+
+    while ((opt = getopt(argc, argv, "h:")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("mem-set");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 1) {
+        help("mem-set");
+        exit(2);
+    }
+
+    p = argv[optind];
+    mem = argv[optind + 1];
+
+    set_memory_target(p, mem);
+    exit(0);
+}
+
+void console(char *p, int cons_num)
+{
+    find_domain(p);
+    libxl_console_attach(&ctx, domid, cons_num);
+}
+
+void cd_insert(char *dom, char *virtdev, char *phys)
+{
+    libxl_device_disk disk;
+    char *p;
+
+    find_domain(dom);
+
+    disk.backend_domid = 0;
+    disk.domid = domid;
+    if (phys) {
+        p = strchr(phys, ':');
+        if (!p) {
+            fprintf(stderr, "No type specified, ");
+            disk.physpath = phys;
+            if (!strncmp(phys, "/dev", 4)) {
+                fprintf(stderr, "assuming phy:\n");
+                disk.phystype = PHYSTYPE_PHY;
+            } else {
+                fprintf(stderr, "assuming file:\n");
+                disk.phystype = PHYSTYPE_FILE;
+            }
+        } else {
+            *p = '\0';
+            p++;
+            disk.physpath = p;
+            libxl_string_to_phystype(&ctx, phys, &disk.phystype);
+        }
+    } else {
+            disk.physpath = NULL;
+            disk.phystype = 0;
+    }
+    disk.virtpath = virtdev;
+    disk.unpluggable = 1;
+    disk.readwrite = 0;
+    disk.is_cdrom = 1;
+
+    libxl_cdrom_insert(&ctx, domid, &disk);
+}
+
+int main_cd_eject(int argc, char **argv)
+{
+    int opt = 0;
+    char *p = NULL, *virtdev;
+
+    while ((opt = getopt(argc, argv, "hn:")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("cd-eject");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 1) {
+        help("cd-eject");
+        exit(2);
+    }
+
+    p = argv[optind];
+    virtdev = argv[optind + 1];
+
+    cd_insert(p, virtdev, NULL);
+    exit(0);
+}
+
+int main_cd_insert(int argc, char **argv)
+{
+    int opt = 0;
+    char *p = NULL, *file = NULL, *virtdev;
+
+    while ((opt = getopt(argc, argv, "hn:")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("cd-insert");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 2) {
+        help("cd-insert");
+        exit(2);
+    }
+
+    p = argv[optind];
+    virtdev = argv[optind + 1];
+    file = argv[optind + 2];
+
+    cd_insert(p, virtdev, file);
+    exit(0);
+}
+
+int main_console(int argc, char **argv)
+{
+    int opt = 0, cons_num = 0;
+    char *p = NULL;
+
+    while ((opt = getopt(argc, argv, "hn:")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("console");
+            exit(0);
+        case 'n':
+            if (optarg) {
+                cons_num = strtol(optarg, NULL, 10);
+            }
+            break;
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc) {
+        help("console");
+        exit(2);
+    }
+
+    p = argv[optind];
+
+    console(p, cons_num);
+    exit(0);
+}
+
+void pcilist(char *dom)
+{
+    libxl_device_pci *pcidevs;
+    int num, i;
+
+    find_domain(dom);
+
+    pcidevs = libxl_device_pci_list(&ctx, domid, &num);
+    if (!num)
+        return;
+    printf("VFn  domain bus  slot func\n");
+    for (i = 0; i < num; i++) {
+        printf("0x%02x 0x%04x 0x%02x 0x%02x 0x%01x\n", pcidevs[i].vdevfn, 
pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
+    }
+    free(pcidevs);
+}
+
+int main_pcilist(int argc, char **argv)
+{
+    int opt;
+    char *domname = NULL;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("pci-list");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc) {
+        help("pci-list");
+        exit(2);
+    }
+
+    domname = argv[optind];
+
+    pcilist(domname);
+    exit(0);
+}
+
+void pcidetach(char *dom, char *bdf)
+{
+    libxl_device_pci pcidev;
+    unsigned int domain, bus, dev, func;
+
+    find_domain(dom);
+
+    memset(&pcidev, 0x00, sizeof(pcidev));
+    if (sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func) != 4) {
+        fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", 
bdf);
+        exit(2);
+    }
+    libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
+    libxl_device_pci_remove(&ctx, domid, &pcidev);
+}
+
+int main_pcidetach(int argc, char **argv)
+{
+    int opt;
+    char *domname = NULL, *bdf = NULL;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("pci-detach");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 1) {
+        help("pci-detach");
+        exit(2);
+    }
+
+    domname = argv[optind];
+    bdf = argv[optind + 1];
+
+    pcidetach(domname, bdf);
+    exit(0);
+}
+void pciattach(char *dom, char *bdf, char *vs)
+{
+    libxl_device_pci pcidev;
+    unsigned int domain, bus, dev, func;
+
+    find_domain(dom);
+
+    memset(&pcidev, 0x00, sizeof(pcidev));
+    if (sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func) != 4) {
+        fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", 
bdf);
+        exit(2);
+    }
+    libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
+    libxl_device_pci_add(&ctx, domid, &pcidev);
+}
+
+int main_pciattach(int argc, char **argv)
+{
+    int opt;
+    char *domname = NULL, *bdf = NULL, *vs = NULL;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("pci-attach");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 1) {
+        help("pci-attach");
+        exit(2);
+    }
+
+    domname = argv[optind];
+    bdf = argv[optind + 1];
+
+    if (optind + 1 < argc)
+        vs = argv[optind + 2];
+
+    pciattach(domname, bdf, vs);
+    exit(0);
+}
+
+void pause_domain(char *p)
+{
+    find_domain(p);
+    libxl_domain_pause(&ctx, domid);
+}
+
+void unpause_domain(char *p)
+{
+    find_domain(p);
+    libxl_domain_unpause(&ctx, domid);
+}
+
+void destroy_domain(char *p)
+{
+    int rc;
+    find_domain(p);
+    if (domid == 0) {
+        fprintf(stderr, "Cannot destroy privileged domain 0.\n\n");
+        exit(-1);
+    }
+    rc = libxl_domain_destroy(&ctx, domid, 0);
+    if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n.",rc); exit(-1); }
+}
+
+void shutdown_domain(char *p)
+{
+    int rc;
+    find_domain(p);
+    rc=libxl_domain_shutdown(&ctx, domid, 0);
+    if (rc) { fprintf(stderr,"shutdown failed (rc=%d)\n.",rc);exit(-1); }
+}
+
+void reboot_domain(char *p)
+{
+    int rc;
+    find_domain(p);
+    rc=libxl_domain_shutdown(&ctx, domid, 1);
+    if (rc) { fprintf(stderr,"reboot failed (rc=%d)\n.",rc);exit(-1); }
+}
+
+void list_domains_details(void)
+{
+    struct libxl_dominfo *info;
+    char *config_file;
+    uint8_t *data;
+    int nb_domain, i, len, rc;
+    int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 
0;
+    libxl_domain_create_info info1;
+    libxl_domain_build_info info2;
+    libxl_device_model_info dm_info;
+    libxl_device_disk *disks = NULL;
+    libxl_device_nic *vifs = NULL;
+
+    libxl_device_pci *pcidevs = NULL;
+    libxl_device_vfb *vfbs = NULL;
+    libxl_device_vkb *vkbs = NULL;
+
+    info = libxl_list_domain(&ctx, &nb_domain);
+
+    if (!info) {
+        fprintf(stderr, "libxl_domain_infolist failed.\n");
+        exit(1);
+    }
+    for (i = 0; i < nb_domain; i++) {
+        rc = libxl_userdata_retrieve(&ctx, info[i].domid, "xl", &data, &len);
+        if (rc)
+            continue;
+        CHK_ERRNO(asprintf(&config_file, "<domid %d data>", info[i].domid));
+        parse_config_data(config_file, (char *)data, len, &info1, &info2, 
&disks, &num_disks, &vifs, &num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, 
&vkbs, &num_vkbs, &dm_info);
+        printf_info(info[i].domid, &info1, &info2, disks, num_disks, vifs, 
num_vifs, pcidevs, num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
+        free(data);
+        free(config_file);
+    }
+    free(info);
+}
+
+void list_domains(int verbose)
+{
+    struct libxl_dominfo *info;
+    int nb_domain, i;
+
+    info = libxl_list_domain(&ctx, &nb_domain);
+
+    if (!info) {
+        fprintf(stderr, "libxl_domain_infolist failed.\n");
+        exit(1);
+    }
+    printf("Name                                        ID   Mem 
VCPUs\tState\tTime(s)\n");
+    for (i = 0; i < nb_domain; i++) {
+        printf("%-40s %5d %5lu %5d        %c%c%c %8.1f",
+                libxl_domid_to_name(&ctx, info[i].domid),
+                info[i].domid,
+                (unsigned long) (info[i].max_memkb / 1024),
+                info[i].vcpu_online,
+                info[i].running ? 'r' : '-',
+                info[i].paused ? 'p' : '-',
+                info[i].dying ? 'd' : '-',
+                ((float)info[i].cpu_time / 1e9));
+        if (verbose) {
+            char *uuid = libxl_uuid2string(&ctx, info[i].uuid);
+            printf(" %s", uuid);
+        }
+        putchar('\n');
+    }
+    free(info);
+}
+
+void list_vm(void)
+{
+    struct libxl_vminfo *info;
+    int nb_vm, i;
+
+    info = libxl_list_vm(&ctx, &nb_vm);
+
+    if (info < 0) {
+        fprintf(stderr, "libxl_domain_infolist failed.\n");
+        exit(1);
+    }
+    printf("UUID                                  ID    name\n");
+    for (i = 0; i < nb_vm; i++) {
+        printf(UUID_FMT "  %d    %-30s\n",
+            info[i].uuid[0], info[i].uuid[1], info[i].uuid[2], info[i].uuid[3],
+            info[i].uuid[4], info[i].uuid[5], info[i].uuid[6], info[i].uuid[7],
+            info[i].uuid[8], info[i].uuid[9], info[i].uuid[10], 
info[i].uuid[11],
+            info[i].uuid[12], info[i].uuid[13], info[i].uuid[14], 
info[i].uuid[15],
+            info[i].domid, libxl_domid_to_name(&ctx, info[i].domid));
+    }
+    free(info);
+}
+
+static void save_domain_core_begin(char *domain_spec,
+                                   const char *override_config_file,
+                                   uint8_t **config_data_r,
+                                   int *config_len_r)
+{
+    int rc;
+
+    find_domain(domain_spec);
+
+    /* configuration file in optional data: */
+
+    if (override_config_file) {
+        void *config_v = 0;
+        rc = libxl_read_file_contents(&ctx, override_config_file,
+                                      &config_v, config_len_r);
+        *config_data_r = config_v;
+    } else {
+        rc = libxl_userdata_retrieve(&ctx, domid, "xl",
+                                     config_data_r, config_len_r);
+    }
+    if (rc) {
+        fputs("Unable to get config file\n",stderr);
+        exit(2);
+    }
+}
+
+void save_domain_core_writeconfig(int fd, const char *filename,
+                                  const uint8_t *config_data, int config_len)
+{
+    struct save_file_header hdr;
+    uint8_t *optdata_begin;
+    union { uint32_t u32; char b[4]; } u32buf;
+
+    memset(&hdr, 0, sizeof(hdr));
+    memcpy(hdr.magic, savefileheader_magic, sizeof(hdr.magic));
+    hdr.byteorder = SAVEFILE_BYTEORDER_VALUE;
+
+    optdata_begin= 0;
+
+#define ADD_OPTDATA(ptr, len) ({                                            \
+    if ((len)) {                                                        \
+        hdr.optional_data_len += (len);                                 \
+        optdata_begin = xrealloc(optdata_begin, hdr.optional_data_len); \
+        memcpy(optdata_begin + hdr.optional_data_len - (len),           \
+               (ptr), (len));                                           \
+    }                                                                   \
+                          })
+
+    u32buf.u32 = config_len;
+    ADD_OPTDATA(u32buf.b,    4);
+    ADD_OPTDATA(config_data, config_len);
+
+    /* that's the optional data */
+
+    CHK_ERRNO( libxl_write_exactly(&ctx, fd,
+        &hdr, sizeof(hdr), filename, "header") );
+    CHK_ERRNO( libxl_write_exactly(&ctx, fd,
+        optdata_begin, hdr.optional_data_len, filename, "header") );
+
+    fprintf(stderr, "Saving to %s new xl format (info"
+            " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
+            filename, hdr.mandatory_flags, hdr.optional_flags,
+            hdr.optional_data_len);
+}
+
+int save_domain(char *p, char *filename, int checkpoint,
+                const char *override_config_file)
+{
+    int fd;
+    uint8_t *config_data;
+    int config_len;
+
+    save_domain_core_begin(p, override_config_file, &config_data, &config_len);
+
+    if (!config_len) {
+        fputs(" Savefile will not contain xl domain config\n", stderr);
+    }
+
+    fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+    if (fd < 0) {
+        fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
+        exit(2);
+    }
+
+    save_domain_core_writeconfig(fd, filename, config_data, config_len);
+
+    CHK_ERRNO(libxl_domain_suspend(&ctx, NULL, domid, fd));
+    close(fd);
+
+    if (checkpoint)
+        libxl_domain_unpause(&ctx, domid);
+    else
+        libxl_domain_destroy(&ctx, domid, 0);
+
+    exit(0);
+}
+
+static int migrate_read_fixedmessage(int fd, const void *msg, int msgsz,
+                                     const char *what, const char *rune) {
+    char buf[msgsz];
+    const char *stream;
+    int rc;
+
+    stream = rune ? "migration receiver stream" : "migration stream";
+    rc = libxl_read_exactly(&ctx, fd, buf, msgsz, stream, what);
+    if (rc) return ERROR_FAIL;
+
+    if (memcmp(buf, msg, msgsz)) {
+        fprintf(stderr, "%s contained unexpected data instead of %s\n",
+                stream, what);
+        if (rune)
+            fprintf(stderr, "(command run was: %s )\n", rune);
+        return ERROR_FAIL;
+    }
+    return 0;
+}
+
+static void migration_child_report(pid_t migration_child, int recv_fd) {
+    pid_t child;
+    int status, sr;
+    struct timeval now, waituntil, timeout;
+    static const struct timeval pollinterval = { 0, 1000 }; /* 1ms */
+
+    if (!migration_child) return;
+
+    CHK_ERRNO( gettimeofday(&waituntil, 0) );
+    waituntil.tv_sec += 2;
+
+    for (;;) {
+        child = waitpid(migration_child, &status, WNOHANG);
+
+        if (child == migration_child) {
+            if (status)
+                libxl_report_child_exitstatus(&ctx, XL_LOG_INFO,
+                                              "migration target process",
+                                              migration_child, status);
+            break;
+        }
+        if (child == -1) {
+            if (errno == EINTR) continue;
+            fprintf(stderr, "wait for migration child [%ld] failed: %s\n",
+                    (long)migration_child, strerror(errno));
+            break;
+        }
+        assert(child == 0);
+
+        CHK_ERRNO( gettimeofday(&now, 0) );
+        if (timercmp(&now, &waituntil, >)) {
+            fprintf(stderr, "migration child [%ld] not exiting, no longer"
+                    " waiting (exit status will be unreported)\n",
+                    (long)migration_child);
+            break;
+        }
+        timersub(&waituntil, &now, &timeout);
+
+        if (recv_fd >= 0) {
+            fd_set readfds, exceptfds;
+            FD_ZERO(&readfds);
+            FD_ZERO(&exceptfds);
+            FD_SET(recv_fd, &readfds);
+            FD_SET(recv_fd, &exceptfds);
+            sr = select(recv_fd+1, &readfds,0,&exceptfds, &timeout);
+        } else {
+            if (timercmp(&timeout, &pollinterval, >))
+                timeout = pollinterval;
+            sr = select(0,0,0,0, &timeout);
+        }
+        if (sr > 0) {
+            recv_fd = -1;
+        } else if (sr == 0) {
+        } else if (sr == -1) {
+            if (errno != EINTR) {
+                fprintf(stderr, "migration child [%ld] exit wait select"
+                        " failed unexpectedly: %s\n",
+                        (long)migration_child, strerror(errno));
+                break;
+            }
+        }
+    }
+    migration_child = 0;
+}
+
+static void migrate_domain(char *domain_spec, const char *rune,
+                           const char *override_config_file)
+{
+    pid_t child = -1;
+    int rc;
+    int sendpipe[2], recvpipe[2];
+    int send_fd, recv_fd;
+    libxl_domain_suspend_info suspinfo;
+    char *away_domname;
+    char rc_buf;
+    uint8_t *config_data;
+    int config_len;
+
+    save_domain_core_begin(domain_spec, override_config_file,
+                           &config_data, &config_len);
+
+    if (!config_len) {
+        fprintf(stderr, "No config file stored for running domain and "
+                "none supplied - cannot migrate.\n");
+        exit(1);
+    }
+
+    MUST( libxl_pipe(&ctx, sendpipe) );
+    MUST( libxl_pipe(&ctx, recvpipe) );
+
+    child = libxl_fork(&ctx);
+    if (child==-1) exit(1);
+
+    if (!child) {
+        dup2(sendpipe[0], 0);
+        dup2(recvpipe[1], 1);
+        close(sendpipe[0]); close(sendpipe[1]);
+        close(recvpipe[0]); close(recvpipe[1]);
+        execlp("sh","sh","-c",rune,(char*)0);
+        perror("failed to exec sh");
+        exit(-1);
+    }
+
+    close(sendpipe[0]);
+    close(recvpipe[1]);
+    send_fd = sendpipe[1];
+    recv_fd = recvpipe[0];
+
+    signal(SIGPIPE, SIG_IGN);
+    /* if receiver dies, we get an error and can clean up
+       rather than just dying */
+
+    rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_banner,
+                                   sizeof(migrate_receiver_banner)-1,
+                                   "banner", rune);
+    if (rc) {
+        close(send_fd);
+        migration_child_report(child, recv_fd);
+        exit(-rc);
+    }
+
+    save_domain_core_writeconfig(send_fd, "migration stream",
+                                 config_data, config_len);
+
+    memset(&suspinfo, 0, sizeof(suspinfo));
+    suspinfo.flags |= XL_SUSPEND_LIVE;
+    rc = libxl_domain_suspend(&ctx, &suspinfo, domid, send_fd);
+    if (rc) {
+        fprintf(stderr, "migration sender: libxl_domain_suspend failed"
+                " (rc=%d)\n", rc);
+        goto failed_resume;
+    }
+
+    //fprintf(stderr, "migration sender: Transfer complete.\n");
+    // Should only be printed when debugging as it's a bit messy with
+    // progress indication.
+
+    rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_ready,
+                                   sizeof(migrate_receiver_ready),
+                                   "ready message", rune);
+    if (rc) goto failed_resume;
+
+
+
+    /* right, at this point we are about give the destination
+     * permission to rename and resume, so we must first rename the
+     * domain away ourselves */
+
+    fprintf(stderr, "migration sender: Target has acknowledged transfer.\n");
+
+    if (common_domname) {
+        if (asprintf(&away_domname, "%s--migratedaway", common_domname) < 0)
+            goto failed_resume;
+        rc = libxl_domain_rename(&ctx, domid,
+                                 common_domname, away_domname, 0);
+        if (rc) goto failed_resume;
+    }
+
+    /* point of no return - as soon as we have tried to say
+     * "go" to the receiver, it's not safe to carry on.  We leave
+     * the domain renamed to %s--migratedaway in case that's helpful.
+     */
+
+    fprintf(stderr, "migration sender: Giving target permission to start.\n");
+
+    rc = libxl_write_exactly(&ctx, send_fd,
+                             migrate_permission_to_go,
+                             sizeof(migrate_permission_to_go),
+                             "migration stream", "GO message");
+    if (rc) goto failed_badly;
+
+    rc = migrate_read_fixedmessage(recv_fd, migrate_report,
+                                   sizeof(migrate_report),
+                                   "success/failure report message", rune);
+    if (rc) goto failed_badly;
+
+    rc = libxl_read_exactly(&ctx, recv_fd,
+                            &rc_buf, 1,
+                            "migration ack stream", "success/failure status");
+    if (rc) goto failed_badly;
+
+    if (rc_buf) {
+        fprintf(stderr, "migration sender: Target reports startup failure"
+                " (status code %d).\n", rc_buf);
+
+        rc = migrate_read_fixedmessage(recv_fd, migrate_permission_to_go,
+                                       sizeof(migrate_permission_to_go),
+                                       "permission for sender to resume",
+                                       rune);
+        if (rc) goto failed_badly;
+
+        fprintf(stderr, "migration sender: Trying to resume at our end.\n");
+
+        if (common_domname) {
+            libxl_domain_rename(&ctx, domid,
+                                away_domname, common_domname, 0);
+        }
+        rc = libxl_domain_resume(&ctx, domid);
+        if (!rc) fprintf(stderr, "migration sender: Resumed OK.\n");
+
+        fprintf(stderr, "Migration failed due to problems at target.\n");
+        exit(-ERROR_FAIL);
+    }
+
+    fprintf(stderr, "migration sender: Target reports successful startup.\n");
+    libxl_domain_destroy(&ctx, domid, 1); /* bang! */
+    fprintf(stderr, "Migration successful.\n");
+    exit(0);
+
+ failed_resume:
+    close(send_fd);
+    migration_child_report(child, recv_fd);
+    fprintf(stderr, "Migration failed, resuming at sender.\n");
+    libxl_domain_resume(&ctx, domid);
+    exit(-ERROR_FAIL);
+
+ failed_badly:
+    fprintf(stderr,
+ "** Migration failed during final handshake **\n"
+ "Domain state is now undefined !\n"
+ "Please CHECK AT BOTH ENDS for running instances, before renaming and\n"
+ " resuming at most one instance.  Two simultaneous instances of the domain\n"
+ " would probably result in SEVERE DATA LOSS and it is now your\n"
+ " responsibility to avoid that.  Sorry.\n");
+
+    close(send_fd);
+    migration_child_report(child, recv_fd);
+    exit(-ERROR_BADFAIL);
+}
+
+static void migrate_receive(int debug, int daemonize)
+{
+    int rc, rc2;
+    char rc_buf;
+    char *migration_domname;
+    struct domain_create dom_info;
+
+    signal(SIGPIPE, SIG_IGN);
+    /* if we get SIGPIPE we'd rather just have it as an error */
+
+    fprintf(stderr, "migration target: Ready to receive domain.\n");
+
+    CHK_ERRNO( libxl_write_exactly(&ctx, 1,
+                                   migrate_receiver_banner,
+                                   sizeof(migrate_receiver_banner)-1,
+                                   "migration ack stream",
+                                   "banner") );
+
+    memset(&dom_info, 0, sizeof(dom_info));
+    dom_info.debug = debug;
+    dom_info.daemonize = daemonize;
+    dom_info.paused = 1;
+    dom_info.restore_file = "incoming migration stream";
+    dom_info.migration_domname_r = &migration_domname;
+
+    rc = create_domain(&dom_info);
+    if (rc < 0) {
+        fprintf(stderr, "migration target: Domain creation failed"
+                " (code %d).\n", rc);
+        exit(-rc);
+    }
+
+    fprintf(stderr, "migration target: Transfer complete,"
+            " requesting permission to start domain.\n");
+
+    rc = libxl_write_exactly(&ctx, 1,
+                             migrate_receiver_ready,
+                             sizeof(migrate_receiver_ready),
+                             "migration ack stream", "ready message");
+    if (rc) exit(-rc);
+
+    rc = migrate_read_fixedmessage(0, migrate_permission_to_go,
+                                   sizeof(migrate_permission_to_go),
+                                   "GO message", 0);
+    if (rc) goto perhaps_destroy_notify_rc;
+
+    fprintf(stderr, "migration target: Got permission, starting domain.\n");
+
+    if (migration_domname) {
+        rc = libxl_domain_rename(&ctx, domid,
+                                 migration_domname, common_domname, 0);
+        if (rc) goto perhaps_destroy_notify_rc;
+    }
+
+    rc = libxl_domain_unpause(&ctx, domid);
+    if (rc) goto perhaps_destroy_notify_rc;
+
+    fprintf(stderr, "migration target: Domain started successsfully.\n");
+    rc = 0;
+
+ perhaps_destroy_notify_rc:
+    rc2 = libxl_write_exactly(&ctx, 1,
+                              migrate_report, sizeof(migrate_report),
+                              "migration ack stream",
+                              "success/failure report");
+    if (rc2) exit(-ERROR_BADFAIL);
+
+    rc_buf = -rc;
+    assert(!!rc_buf == !!rc);
+    rc2 = libxl_write_exactly(&ctx, 1, &rc_buf, 1,
+                              "migration ack stream",
+                              "success/failure code");
+    if (rc2) exit(-ERROR_BADFAIL);
+
+    if (rc) {
+        fprintf(stderr, "migration target: Failure, destroying our copy.\n");
+
+        rc2 = libxl_domain_destroy(&ctx, domid, 1);
+        if (rc2) {
+            fprintf(stderr, "migration target: Failed to destroy our copy"
+                    " (code %d).\n", rc2);
+            exit(-ERROR_BADFAIL);
+        }
+
+        fprintf(stderr, "migration target: Cleanup OK, granting sender"
+                " permission to resume.\n");
+
+        rc2 = libxl_write_exactly(&ctx, 1,
+                                  migrate_permission_to_go,
+                                  sizeof(migrate_permission_to_go),
+                                  "migration ack stream",
+                                  "permission to sender to have domain back");
+        if (rc2) exit(-ERROR_BADFAIL);
+    }
+
+    exit(0);
+}
+
+int main_restore(int argc, char **argv)
+{
+    char *checkpoint_file = NULL;
+    char *config_file = NULL;
+    struct domain_create dom_info;
+    int paused = 0, debug = 0, daemonize = 1;
+    int opt, rc;
+
+    while ((opt = getopt(argc, argv, "hpde")) != -1) {
+        switch (opt) {
+        case 'p':
+            paused = 1;
+            break;
+        case 'd':
+            debug = 1;
+            break;
+        case 'e':
+            daemonize = 0;
+            break;
+        case 'h':
+            help("restore");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    if (argc-optind == 1) {
+        checkpoint_file = argv[optind];
+    } else if (argc-optind == 2) {
+        config_file = argv[optind];
+        checkpoint_file = argv[optind + 1];
+    } else {
+        help("restore");
+        exit(2);
+    }
+
+    memset(&dom_info, 0, sizeof(dom_info));
+    dom_info.debug = debug;
+    dom_info.daemonize = daemonize;
+    dom_info.paused = paused;
+    dom_info.config_file = config_file;
+    dom_info.restore_file = checkpoint_file;
+    dom_info.migrate_fd = -1;
+
+    rc = create_domain(&dom_info);
+    if (rc < 0)
+        exit(-rc);
+
+    exit(0);
+}
+
+int main_migrate_receive(int argc, char **argv)
+{
+    int debug = 0, daemonize = 1;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "hed")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("migrate-receive");
+            exit(2);
+            break;
+        case 'e':
+            daemonize = 0;
+            break;
+        case 'd':
+            debug = 1;
+            break;
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    if (argc-optind != 0) {
+        help("migrate-receive");
+        exit(2);
+    }
+    migrate_receive(debug, daemonize);
+    exit(0);
+}
+
+int main_save(int argc, char **argv)
+{
+    char *filename = NULL, *p = NULL;
+    const char *config_filename;
+    int checkpoint = 0;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "hc")) != -1) {
+        switch (opt) {
+        case 'c':
+            checkpoint = 1;
+            break;
+        case 'h':
+            help("save");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    if (argc-optind < 1 || argc-optind > 3) {
+        help("save");
+        exit(2);
+    }
+
+    p = argv[optind];
+    filename = argv[optind + 1];
+    config_filename = argv[optind + 2];
+    save_domain(p, filename, checkpoint, config_filename);
+    exit(0);
+}
+
+int main_migrate(int argc, char **argv)
+{
+    char *p = NULL;
+    const char *config_filename = NULL;
+    const char *ssh_command = "ssh";
+    char *rune = NULL;
+    char *host;
+    int opt, daemonize = 1, debug = 0;
+
+    while ((opt = getopt(argc, argv, "hC:s:ed")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("migrate");
+            exit(0);
+        case 'C':
+            config_filename = optarg;
+            break;
+        case 's':
+            ssh_command = optarg;
+            break;
+        case 'e':
+            daemonize = 0;
+            break;
+        case 'd':
+            debug = 1;
+            break;
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    if (argc-optind < 2 || argc-optind > 2) {
+        help("migrate");
+        exit(2);
+    }
+
+    p = argv[optind];
+    host = argv[optind + 1];
+
+    if (!ssh_command[0]) {
+        rune= host;
+    } else {
+        if (asprintf(&rune, "exec %s %s xl migrate-receive%s%s",
+                     ssh_command, host,
+                     daemonize ? "" : " -e",
+                     debug ? " -d" : "") < 0)
+            exit(1);
+    }
+
+    migrate_domain(p, rune, config_filename);
+    exit(0);
+}
+
+int main_pause(int argc, char **argv)
+{
+    int opt;
+    char *p;
+
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("pause");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc) {
+        help("pause");
+        exit(2);
+    }
+
+    p = argv[optind];
+
+    pause_domain(p);
+    exit(0);
+}
+
+int main_unpause(int argc, char **argv)
+{
+    int opt;
+    char *p;
+
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("unpause");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc) {
+        help("unpause");
+        exit(2);
+    }
+
+    p = argv[optind];
+
+    unpause_domain(p);
+    exit(0);
+}
+
+int main_destroy(int argc, char **argv)
+{
+    int opt;
+    char *p;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("destroy");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc) {
+        help("destroy");
+        exit(2);
+    }
+
+    p = argv[optind];
+
+    destroy_domain(p);
+    exit(0);
+}
+
+int main_shutdown(int argc, char **argv)
+{
+    int opt;
+    char *p;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("shutdown");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc) {
+        help("shutdown");
+        exit(2);
+    }
+
+    p = argv[optind];
+
+    shutdown_domain(p);
+    exit(0);
+}
+
+int main_reboot(int argc, char **argv)
+{
+    int opt;
+    char *p;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("reboot");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc) {
+        help("reboot");
+        exit(2);
+    }
+
+    p = argv[optind];
+
+    reboot_domain(p);
+    exit(0);
+}
+int main_list(int argc, char **argv)
+{
+    int opt, verbose = 0;
+    int details = 0;
+    int option_index = 0;
+    static struct option long_options[] = {
+        {"long", 0, 0, 'l'},
+        {"help", 0, 0, 'h'},
+        {"verbose", 0, 0, 'v'},
+        {0, 0, 0, 0}
+    };
+
+    while (1) {
+        opt = getopt_long(argc, argv, "lvh", long_options, &option_index);
+        if (opt == -1)
+            break;
+
+        switch (opt) {
+        case 'l':
+            details = 1;
+            break;
+        case 'h':
+            help("list");
+            exit(0);
+        case 'v':
+            verbose = 1;
+            break;
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    if (details)
+        list_domains_details();
+    else
+        list_domains(verbose);
+    exit(0);
+}
+
+int main_list_vm(int argc, char **argv)
+{
+    int opt;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("list-vm");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    list_vm();
+    exit(0);
+}
+
+int main_create(int argc, char **argv)
+{
+    char *filename = NULL;
+    char *p, extra_config[1024];
+    struct domain_create dom_info;
+    char dom[10]; /* long enough */
+    int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0,
+        dryrun = 0, quite = 0;
+    int opt, rc;
+    int option_index = 0;
+    static struct option long_options[] = {
+        {"dryrun", 0, 0, 'n'},
+        {"quiet", 0, 0, 'q'},
+        {"help", 0, 0, 'h'},
+        {"defconfig", 1, 0, 'f'},
+        {0, 0, 0, 0}
+    };
+
+    while (1) {
+        opt = getopt_long(argc, argv, "hnqf:pcde", long_options, 
&option_index);
+        if (opt == -1)
+            break;
+
+        switch (opt) {
+        case 'f':
+            filename = optarg;
+            break;
+        case 'p':
+            paused = 1;
+            break;
+        case 'c':
+            console_autoconnect = 1;
+            break;
+        case 'd':
+            debug = 1;
+            break;
+        case 'e':
+            daemonize = 0;
+            break;
+        case 'h':
+            help("create");
+            exit(0);
+        case 'n':
+            dryrun = 1;
+            break;
+        case 'q':
+            quite = 1;
+            break;
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    memset(extra_config, 0, sizeof(extra_config));
+    while (optind < argc) {
+        if ((p = strchr(argv[optind], '='))) {
+            if (strlen(extra_config) + 1 < sizeof(extra_config)) {
+                if (strlen(extra_config))
+                    strcat(extra_config, "\n");
+                strcat(extra_config, argv[optind]);
+            }
+        } else if (!filename) {
+            filename = argv[optind];
+        } else {
+            help("create");
+            exit(2);
+        }
+        optind++;
+    }
+
+    memset(&dom_info, 0, sizeof(dom_info));
+    dom_info.debug = debug;
+    dom_info.daemonize = daemonize;
+    dom_info.paused = paused;
+    dom_info.dryrun = dryrun;
+    dom_info.quiet = quite;
+    dom_info.config_file = filename;
+    dom_info.extra_config = extra_config;
+    dom_info.migrate_fd = -1;
+
+    rc = create_domain(&dom_info);
+    if (rc < 0)
+        exit(-rc);
+
+    if (console_autoconnect) {
+        snprintf(dom, sizeof(dom), "%d", rc);
+        console(dom, 0);
+    }
+
+    exit(0);
+}
+
+void button_press(char *p, char *b)
+{
+    libxl_button button;
+
+    find_domain(p);
+
+    if (!strcmp(b, "power")) {
+        button = POWER_BUTTON;
+    } else if (!strcmp(b, "sleep")) {
+        button = SLEEP_BUTTON;
+    } else {
+        fprintf(stderr, "%s is an invalid button identifier\n", b);
+        exit(2);
+    }
+
+    libxl_button_press(&ctx, domid, button);
+}
+
+int main_button_press(int argc, char **argv)
+{
+    int opt;
+    char *p;
+    char *b;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("button-press");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 1) {
+        help("button-press");
+        exit(2);
+    }
+
+    p = argv[optind];
+    b = argv[optind + 1];
+
+    button_press(p, b);
+    exit(0);
+}
+
+static void print_vcpuinfo(uint32_t tdomid,
+                           const struct libxl_vcpuinfo *vcpuinfo,
+                           uint32_t nr_cpus)
+{
+    int i, l;
+    uint64_t *cpumap;
+    uint64_t pcpumap;
+
+    /*      NAME  ID  VCPU */
+    printf("%-32s %5u %5u",
+           libxl_domid_to_name(&ctx, tdomid), tdomid, vcpuinfo->vcpuid);
+    if (!vcpuinfo->online) {
+        /*      CPU STA */
+        printf("%5c %3c%cp ", '-', '-', '-');
+    } else {
+        /*      CPU STA */
+        printf("%5u %3c%c- ", vcpuinfo->cpu,
+               vcpuinfo->running ? 'r' : '-',
+               vcpuinfo->blocked ? 'b' : '-');
+    }
+    /*      TIM */
+    printf("%9.1f  ", ((float)vcpuinfo->vcpu_time / 1e9));
+    /* CPU AFFINITY */
+    pcpumap = nr_cpus > 64 ? -1 : ((1 << nr_cpus) - 1);
+    for (cpumap = vcpuinfo->cpumap; nr_cpus; ++cpumap) {
+        if (*cpumap < pcpumap) {
+            break;
+        }
+        if (nr_cpus > 64) {
+            pcpumap = -1;
+            nr_cpus -= 64;
+        } else {
+            pcpumap = ((1 << nr_cpus) - 1);
+            nr_cpus = 0;
+        }
+    }
+    if (!nr_cpus) {
+        printf("any cpu\n");
+    } else {
+        for (cpumap = vcpuinfo->cpumap; nr_cpus; ++cpumap) {
+            pcpumap = *cpumap;
+            for (i = 0; !(pcpumap & 1); ++i, pcpumap >>= 1)
+                ;
+            printf("%u", i);
+            for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, pcpumap 
>>= 1)
+                ;
+            if (l < i) {
+                printf("-%u", i);
+            }
+            for (++i; pcpumap; ++i, pcpumap >>= 1) {
+                if (pcpumap & 1) {
+                    printf(",%u", i);
+                    for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, 
pcpumap >>= 1)
+                        ;
+                    if (l < i) {
+                        printf("-%u", i);
+                    }
+                    ++i;
+                }
+            }
+            printf("\n");
+            nr_cpus = nr_cpus > 64 ? nr_cpus - 64 : 0;
+        }
+    }
+}
+
+void vcpulist(int argc, char **argv)
+{
+    struct libxl_dominfo *dominfo;
+    struct libxl_vcpuinfo *vcpuinfo;
+    struct libxl_physinfo physinfo;
+    int nb_vcpu, nb_domain, cpusize;
+
+    if (libxl_get_physinfo(&ctx, &physinfo) != 0) {
+        fprintf(stderr, "libxl_physinfo failed.\n");
+        goto vcpulist_out;
+    }
+    printf("%-32s %5s %5s %5s %5s %9s %s\n",
+           "Name", "ID", "VCPU", "CPU", "State", "Time(s)", "CPU Affinity");
+    if (!argc) {
+        if (!(dominfo = libxl_list_domain(&ctx, &nb_domain))) {
+            fprintf(stderr, "libxl_list_domain failed.\n");
+            goto vcpulist_out;
+        }
+        for (; nb_domain > 0; --nb_domain, ++dominfo) {
+            if (!(vcpuinfo = libxl_list_vcpu(&ctx, dominfo->domid, &nb_vcpu, 
&cpusize))) {
+                fprintf(stderr, "libxl_list_vcpu failed.\n");
+                goto vcpulist_out;
+            }
+            for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
+                print_vcpuinfo(dominfo->domid, vcpuinfo, physinfo.nr_cpus);
+            }
+        }
+    } else {
+        for (; argc > 0; ++argv, --argc) {
+            if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
+                fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+            }
+            if (!(vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, 
&cpusize))) {
+                fprintf(stderr, "libxl_list_vcpu failed.\n");
+                goto vcpulist_out;
+            }
+            for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
+                print_vcpuinfo(domid, vcpuinfo, physinfo.nr_cpus);
+            }
+        }
+    }
+  vcpulist_out:
+    ;
+}
+
+int main_vcpulist(int argc, char **argv)
+{
+    int opt;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("vcpu-list");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    vcpulist(argc - 2, argv + 2);
+    exit(0);
+}
+
+void vcpupin(char *d, const char *vcpu, char *cpu)
+{
+    struct libxl_vcpuinfo *vcpuinfo;
+    struct libxl_physinfo physinfo;
+    uint64_t *cpumap = NULL;
+
+    uint32_t vcpuid, cpuida, cpuidb;
+    char *endptr, *toka, *tokb;
+    int i, nb_vcpu, cpusize;
+
+    vcpuid = strtoul(vcpu, &endptr, 10);
+    if (vcpu == endptr) {
+        if (strcmp(vcpu, "all")) {
+            fprintf(stderr, "Error: Invalid argument.\n");
+            return;
+        }
+        vcpuid = -1;
+    }
+
+    find_domain(d);
+
+    if (libxl_get_physinfo(&ctx, &physinfo) != 0) {
+        fprintf(stderr, "libxl_get_physinfo failed.\n");
+        goto vcpupin_out1;
+    }
+
+    cpumap = calloc(physinfo.max_cpu_id + 1, sizeof (uint64_t));
+    if (!cpumap) {
+        goto vcpupin_out1;
+    }
+    if (strcmp(cpu, "all")) {
+        for (toka = strtok(cpu, ","), i = 0; toka; toka = strtok(NULL, ","), 
++i) {
+            cpuida = strtoul(toka, &endptr, 10);
+            if (toka == endptr) {
+                fprintf(stderr, "Error: Invalid argument.\n");
+                goto vcpupin_out;
+            }
+            if (*endptr == '-') {
+                tokb = endptr + 1;
+                cpuidb = strtoul(tokb, &endptr, 10);
+                if ((tokb == endptr) || (cpuida > cpuidb)) {
+                    fprintf(stderr, "Error: Invalid argument.\n");
+                    goto vcpupin_out;
+                }
+                while (cpuida <= cpuidb) {
+                    cpumap[cpuida / 64] |= (1 << (cpuida % 64));
+                    ++cpuida;
+                }
+            } else {
+                cpumap[cpuida / 64] |= (1 << (cpuida % 64));
+            }
+        }
+    }
+    else {
+        memset(cpumap, -1, sizeof (uint64_t) * (physinfo.max_cpu_id + 1));
+    }
+
+    if (vcpuid != -1) {
+        if (libxl_set_vcpuaffinity(&ctx, domid, vcpuid,
+                                   cpumap, physinfo.max_cpu_id + 1) == -1) {
+            fprintf(stderr, "Could not set affinity for vcpu `%u'.\n", vcpuid);
+        }
+    }
+    else {
+        if (!(vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, &cpusize))) {
+            fprintf(stderr, "libxl_list_vcpu failed.\n");
+            goto vcpupin_out;
+        }
+        for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
+            if (libxl_set_vcpuaffinity(&ctx, domid, vcpuinfo->vcpuid,
+                                       cpumap, physinfo.max_cpu_id + 1) == -1) 
{
+                fprintf(stderr, "libxl_list_vcpu failed on vcpu `%u'.\n", 
vcpuinfo->vcpuid);
+            }
+        }
+    }
+  vcpupin_out1:
+    free(cpumap);
+  vcpupin_out:
+    ;
+}
+
+int main_vcpupin(int argc, char **argv)
+{
+    int opt;
+
+    if (argc != 5) {
+        help("vcpu-pin");
+        exit(0);
+    }
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("vcpu-pin");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    vcpupin(argv[2], argv[3] , argv[4]);
+    exit(0);
+}
+
+void vcpuset(char *d, char* nr_vcpus)
+{
+    char *endptr;
+    unsigned int max_vcpus;
+
+    max_vcpus = strtoul(nr_vcpus, &endptr, 10);
+    if (nr_vcpus == endptr) {
+        fprintf(stderr, "Error: Invalid argument.\n");
+        return;
+    }
+
+    find_domain(d);
+
+    if (libxl_set_vcpucount(&ctx, domid, max_vcpus) == ERROR_INVAL) {
+        fprintf(stderr, "Error: Cannot set vcpus greater than max vcpus on 
running domain or lesser than 1.\n");
+    }
+}
+
+int main_vcpuset(int argc, char **argv)
+{
+    int opt;
+
+    if (argc != 4) {
+        help("vcpu-set");
+        exit(0);
+    }
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+        help("vcpu-set");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    vcpuset(argv[2], argv[3]);
+    exit(0);
+}
+
+static void output_xeninfo(void)
+{
+    const libxl_version_info *info;
+    int sched_id;
+
+    if (!(info = libxl_get_version_info(&ctx))) {
+        fprintf(stderr, "libxl_get_version_info failed.\n");
+        return;
+    }
+
+    if ((sched_id = libxl_get_sched_id(&ctx)) < 0) {
+        fprintf(stderr, "get_sched_id sysctl failed.\n");
+        return;
+    }
+
+    printf("xen_major              : %d\n", info->xen_version_major);
+    printf("xen_minor              : %d\n", info->xen_version_minor);
+    printf("xen_extra              : %s\n", info->xen_version_extra);
+    printf("xen_caps               : %s\n", info->capabilities);
+    printf("xen_scheduler          : %s\n",
+        sched_id == XEN_SCHEDULER_SEDF ? "sedf" : "credit");
+    printf("xen_pagesize           : %lu\n", info->pagesize);
+    printf("platform_params        : virt_start=0x%lx\n", info->virt_start);
+    printf("xen_changeset          : %s\n", info->changeset);
+    printf("xen_commandline        : %s\n", info->commandline);
+    printf("cc_compiler            : %s\n", info->compiler);
+    printf("cc_compile_by          : %s\n", info->compile_by);
+    printf("cc_compile_domain      : %s\n", info->compile_domain);
+    printf("cc_compile_date        : %s\n", info->compile_date);
+
+    return;
+}
+
+static void output_nodeinfo(void)
+{
+    struct utsname utsbuf;
+
+    if (uname(&utsbuf) < 0)
+        return;
+
+    printf("host                   : %s\n", utsbuf.nodename);
+    printf("release                : %s\n", utsbuf.release);
+    printf("version                : %s\n", utsbuf.version);
+    printf("machine                : %s\n", utsbuf.machine);
+}
+
+static void output_physinfo(void)
+{
+    struct libxl_physinfo info;
+    const libxl_version_info *vinfo;
+    unsigned int i;
+
+    if (libxl_get_physinfo(&ctx, &info) != 0) {
+        fprintf(stderr, "libxl_physinfo failed.\n");
+        return;
+    }
+
+    printf("nr_cpus                : %d\n", info.nr_cpus);
+    printf("cores_per_socket       : %d\n", info.cores_per_socket);
+    printf("threads_per_core       : %d\n", info.threads_per_core);
+    printf("cpu_mhz                : %d\n", info.cpu_khz / 1000);
+    printf("hw_caps                : ");
+    for (i = 0; i < 8; i++)
+        printf("%08x%c", info.hw_cap[i], i < 7 ? ':' : '\n');
+    printf("virt_caps              :");
+    if (info.phys_cap & XEN_SYSCTL_PHYSCAP_hvm)
+        printf(" hvm");
+    if (info.phys_cap & XEN_SYSCTL_PHYSCAP_hvm_directio)
+        printf(" hvm_directio");
+    printf("\n");
+    vinfo = libxl_get_version_info(&ctx);
+    if (vinfo) {
+        i = (1 << 20) / vinfo->pagesize;
+        printf("total_memory           : %"PRIu64"\n", info.total_pages / i);
+        printf("free_memory            : %"PRIu64"\n", info.free_pages / i);
+    }
+
+    return;
+}
+
+static void info(void)
+{
+    output_nodeinfo();
+
+    output_physinfo();
+
+    output_xeninfo();
+
+    printf("xend_config_format     : 4\n");
+
+    return;
+}
+
+int main_info(int argc, char **argv)
+{
+    int opt;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("info");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    info();
+    exit(0);
+}
+
+static int sched_credit_domain_get(
+    int domid, struct libxl_sched_credit *scinfo)
+{
+    int rc;
+
+    rc = libxl_sched_credit_domain_get(&ctx, domid, scinfo);
+    if (rc)
+        fprintf(stderr, "libxl_sched_credit_domain_get failed.\n");
+
+    return rc;
+}
+
+static int sched_credit_domain_set(
+    int domid, struct libxl_sched_credit *scinfo)
+{
+    int rc;
+
+    rc = libxl_sched_credit_domain_set(&ctx, domid, scinfo);
+    if (rc)
+        fprintf(stderr, "libxl_sched_credit_domain_set failed.\n");
+
+    return rc;
+}
+
+static void sched_credit_domain_output(
+    int domid, struct libxl_sched_credit *scinfo)
+{
+    printf("%-33s %4d %6d %4d\n",
+        libxl_domid_to_name(&ctx, domid),
+        domid,
+        scinfo->weight,
+        scinfo->cap);
+}
+
+int main_sched_credit(int argc, char **argv)
+{
+    struct libxl_dominfo *info;
+    struct libxl_sched_credit scinfo;
+    int nb_domain, i;
+    char *dom = NULL;
+    int weight = 256, cap = 0, opt_w = 0, opt_c = 0;
+    int opt, rc;
+
+    while ((opt = getopt(argc, argv, "hd:w:c:")) != -1) {
+        switch (opt) {
+        case 'd':
+            dom = optarg;
+            break;
+        case 'w':
+            weight = strtol(optarg, NULL, 10);
+            opt_w = 1;
+            break;
+        case 'c':
+            cap = strtol(optarg, NULL, 10);
+            opt_c = 1;
+            break;
+        case 'h':
+            help("sched-credit");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    if (!dom && (opt_w || opt_c)) {
+        fprintf(stderr, "Must specify a domain.\n");
+        exit(1);
+    }
+
+    if (!dom) { /* list all domain's credit scheduler info */
+        info = libxl_list_domain(&ctx, &nb_domain);
+        if (!info) {
+            fprintf(stderr, "libxl_domain_infolist failed.\n");
+            exit(1);
+        }
+
+        printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
+        for (i = 0; i < nb_domain; i++) {
+            rc = sched_credit_domain_get(info[i].domid, &scinfo);
+            if (rc)
+                exit(-rc);
+            sched_credit_domain_output(info[i].domid, &scinfo);
+        }
+    } else {
+        find_domain(dom);
+
+        rc = sched_credit_domain_get(domid, &scinfo);
+        if (rc)
+            exit(-rc);
+
+        if (!opt_w && !opt_c) { /* output credit scheduler info */
+            printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
+            sched_credit_domain_output(domid, &scinfo);
+        } else { /* set credit scheduler paramaters */
+            if (opt_w)
+                scinfo.weight = weight;
+            if (opt_c)
+                scinfo.cap = cap;
+            rc = sched_credit_domain_set(domid, &scinfo);
+            if (rc)
+                exit(-rc);
+        }
+    }
+
+    exit(0);
+}
+
+int main_domid(int argc, char **argv)
+{
+    int opt;
+    char *domname = NULL;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("domid");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    domname = argv[optind];
+    if (!domname) {
+        fprintf(stderr, "Must specify a domain name.\n\n");
+        help("domid");
+        exit(1);
+    }
+
+    if (libxl_name_to_domid(&ctx, domname, &domid)) {
+        fprintf(stderr, "Can't get domid of domain name '%s', maybe this 
domain does not exist.\n", domname);
+        exit(1);
+    }
+
+    printf("%d\n", domid);
+
+    exit(0);
+}
+
+int main_domname(int argc, char **argv)
+{
+    int opt;
+    char *domname = NULL;
+    char *endptr = NULL;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("domname");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    if (!argv[optind]) {
+        fprintf(stderr, "Must specify a domain id.\n\n");
+        help("domname");
+        exit(1);
+    }
+    domid = strtol(argv[optind], &endptr, 10);
+    if (domid == 0 && !strcmp(endptr, argv[optind])) {
+        /*no digits at all*/
+        fprintf(stderr, "Invalid domain id.\n\n");
+        exit(1);
+    }
+
+    domname = libxl_domid_to_name(&ctx, domid);
+    if (!domname) {
+        fprintf(stderr, "Can't get domain name of domain id '%d', maybe this 
domain does not exist.\n", domid);
+        exit(1);
+    }
+
+    printf("%s\n", domname);
+
+    exit(0);
+}
+
+int main_rename(int argc, char **argv)
+{
+    int opt;
+    char *dom;
+    char *new_name;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("rename");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    dom = argv[optind++];
+    if (!dom || !argv[optind]) {
+        fprintf(stderr, "'xl rename' requires 2 arguments.\n\n");
+        help("rename");
+        exit(1);
+    }
+
+    find_domain(dom);
+    new_name = argv[optind];
+
+    if (libxl_domain_rename(&ctx, domid, common_domname, new_name, 0)) {
+        fprintf(stderr, "Can't rename domain '%s'.\n", dom);
+        exit(1);
+    }
+
+    exit(0);
+}
+
+int main_trigger(int argc, char **argv)
+{
+    int opt;
+    char *trigger_name = NULL;
+    char *endptr = NULL;
+    char *dom = NULL;
+    int vcpuid = 0;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("trigger");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    dom = argv[optind++];
+    if (!dom || !argv[optind]) {
+        fprintf(stderr, "'xl trigger' requires between 2 and 3 
arguments.\n\n");
+        help("trigger");
+        exit(1);
+    }
+
+    find_domain(dom);
+
+    trigger_name = argv[optind++];
+
+    if (argv[optind]) {
+        vcpuid = strtol(argv[optind], &endptr, 10);
+        if (vcpuid == 0 && !strcmp(endptr, argv[optind])) {
+            fprintf(stderr, "Invalid vcpuid, using default vcpuid=0.\n\n");
+        }
+    }
+
+    libxl_send_trigger(&ctx, domid, trigger_name, vcpuid);
+
+    exit(0);
+}
+
+
+int main_sysrq(int argc, char **argv)
+{
+    int opt;
+    char *sysrq = NULL;
+    char *dom = NULL;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("sysrq");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    dom = argv[optind++];
+    if (!dom || !argv[optind]) {
+        fprintf(stderr, "'xl sysrq' requires 2 arguments.\n\n");
+        help("sysrq");
+        exit(1);
+    }
+
+    find_domain(dom);
+
+    sysrq = argv[optind];
+
+    if (sysrq[1] != '\0') {
+        fprintf(stderr, "Invalid sysrq.\n\n");
+        help("sysrq");
+        exit(1);
+    }
+
+    libxl_send_sysrq(&ctx, domid, sysrq[0]);
+
+    exit(0);
+}
+
+int main_debug_keys(int argc, char **argv)
+{
+    int opt;
+    char *keys;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("debug-keys");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc) {
+        help("debug-keys");
+        exit(2);
+    }
+
+    keys = argv[optind];
+
+    if (libxl_send_debug_keys(&ctx, keys)) {
+        fprintf(stderr, "cannot send debug keys: %s\n", keys);
+        exit(1);
+    }
+
+    exit(0);
+}
+
+int main_dmesg(int argc, char **argv)
+{
+    unsigned int clear = 0;
+    struct libxl_xen_console_reader *cr;
+    char *line;
+    int opt, ret = 1;
+
+    while ((opt = getopt(argc, argv, "hc")) != -1) {
+        switch (opt) {
+        case 'c':
+            clear = 1;
+            break;
+        case 'h':
+            help("dmesg");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    cr = libxl_xen_console_read_start(&ctx, clear);
+    if (!cr)
+        goto finish;
+
+    while ((ret = libxl_xen_console_read_line(&ctx, cr, &line)) > 0)
+        printf("%s", line);
+
+finish:
+    libxl_xen_console_read_finish(&ctx, cr);
+    exit(ret);
+}
+
+int main_top(int argc, char **argv)
+{
+    int opt;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("top");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    exit(system("xentop"));
+}
+
+int main_networkattach(int argc, char **argv)
+{
+    int opt;
+    libxl_device_nic nic;
+    char *endptr, *tok;
+    int i;
+    unsigned int val;
+
+    if ((argc < 3) || (argc > 11)) {
+        help("network-attach");
+        exit(0);
+    }
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("network-attach");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    if (domain_qualifier_to_domid(argv[2], &domid, 0) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[2]);
+        exit(1);
+    }
+    init_nic_info(&nic, -1);
+    for (argv += 3, argc -= 3; argc > 0; ++argv, --argc) {
+        if (!strncmp("type=", *argv, 5)) {
+            if (!strncmp("vif", (*argv) + 5, 4)) {
+                nic.nictype = NICTYPE_VIF;
+            } else if (!strncmp("ioemu", (*argv) + 5, 5)) {
+                nic.nictype = NICTYPE_IOEMU;
+            } else {
+                fprintf(stderr, "Invalid parameter `type'.\n");
+                exit(1);
+            }
+        } else if (!strncmp("mac=", *argv, 4)) {
+            tok = strtok((*argv) + 4, ":");
+            for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
+                val = strtoul(tok, &endptr, 16);
+                if ((tok == endptr) || (val > 255)) {
+                    fprintf(stderr, "Invalid parameter `mac'.\n");
+                    exit(1);
+                }
+                nic.mac[i] = val;
+            }
+        } else if (!strncmp("bridge=", *argv, 7)) {
+            nic.bridge = (*argv) + 7;
+        } else if (!strncmp("ip=", *argv, 3)) {
+            if (!inet_aton((*argv) + 3, &(nic.ip))) {
+                fprintf(stderr, "Invalid parameter `ip'.\n");
+                exit(1);
+            }
+        } else if (!strncmp("script=", *argv, 6)) {
+            nic.script = (*argv) + 6;
+        } else if (!strncmp("backend=", *argv, 8)) {
+            val = strtoul((*argv) + 8, &endptr, 10);
+            if (((*argv) + 8) == endptr) {
+                fprintf(stderr, "Invalid parameter `backend'.\n");
+                exit(1);
+            }
+            nic.backend_domid = val;
+        } else if (!strncmp("vifname=", *argv, 8)) {
+            nic.ifname = (*argv) + 8;
+        } else if (!strncmp("model=", *argv, 6)) {
+            nic.model = (*argv) + 6;
+        } else if (!strncmp("rate=", *argv, 5)) {
+        } else if (!strncmp("accel=", *argv, 6)) {
+        } else {
+            fprintf(stderr, "unrecognized argument `%s'\n", *argv);
+            exit(1);
+        }
+    }
+    nic.domid = domid;
+    if (libxl_device_nic_add(&ctx, domid, &nic)) {
+        fprintf(stderr, "libxl_device_nic_add failed.\n");
+        exit(1);
+    }
+    exit(0);
+}
+
+int main_networklist(int argc, char **argv)
+{
+    int opt;
+    libxl_nicinfo *nics;
+    unsigned int nb;
+
+    if (argc < 3) {
+        help("network-list");
+        exit(1);
+    }
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+            case 'h':
+                help("network-list");
+                exit(0);
+            default:
+                fprintf(stderr, "option `%c' not supported.\n", opt);
+                break;
+        }
+    }
+
+    /*      Idx  BE   MAC   Hdl  Sta  evch txr/rxr  BE-path */
+    printf("%-3s %-2s %-17s %-6s %-5s %-6s %5s/%-5s %-30s\n",
+           "Idx", "BE", "Mac Addr.", "handle", "state", "evt-ch", "tx-", 
"rx-ring-ref", "BE-path");
+    for (argv += 2, argc -= 2; argc > 0; --argc, ++argv) {
+        if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
+            fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+            continue;
+        }
+        if (!(nics = libxl_list_nics(&ctx, domid, &nb))) {
+            continue;
+        }
+        for (; nb > 0; --nb, ++nics) {
+            /* Idx BE */
+            printf("%-3d %-2d ", nics->devid, nics->backend_id);
+            /* MAC */
+            printf("%02x:%02x:%02x:%02x:%02x:%02x ",
+                   nics->mac[0], nics->mac[1], nics->mac[2],
+                   nics->mac[3], nics->mac[4], nics->mac[5]);
+            /* Hdl  Sta  evch txr/rxr  BE-path */
+            printf("%6d %5d %6d %5d/%-11d %-30s\n",
+                   nics->devid, nics->state, nics->evtch,
+                   nics->rref_tx, nics->rref_rx, nics->backend);
+        }
+    }
+    exit(0);
+}
+
+int main_networkdetach(int argc, char **argv)
+{
+    int opt;
+    libxl_device_nic nic;
+
+    if (argc != 4) {
+        help("network-detach");
+        exit(0);
+    }
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("network-detach");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    if (domain_qualifier_to_domid(argv[2], &domid, 0) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[2]);
+        exit(1);
+    }
+
+    if (!strchr(argv[3], ':')) {
+        if (libxl_devid_to_device_nic(&ctx, domid, argv[3], &nic)) {
+            fprintf(stderr, "Unknown device %s.\n", argv[3]);
+            exit(1);
+        }
+    } else {
+        if (libxl_mac_to_device_nic(&ctx, domid, argv[3], &nic)) {
+            fprintf(stderr, "Unknown device %s.\n", argv[3]);
+            exit(1);
+        }
+    }
+    if (libxl_device_nic_del(&ctx, &nic, 1)) {
+        fprintf(stderr, "libxl_device_nic_del failed.\n");
+        exit(1);
+    }
+    exit(0);
+}
+
+int main_blockattach(int argc, char **argv)
+{
+    int opt;
+    char *tok;
+    uint32_t fe_domid, be_domid = 0;
+    libxl_device_disk disk = { 0 };
+
+    if ((argc < 5) || (argc > 7)) {
+        help("block-attach");
+        exit(0);
+    }
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("block-attach");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    tok = strtok(argv[3], ":");
+    if (!strcmp(tok, "phy")) {
+        disk.phystype = PHYSTYPE_PHY;
+    } else if (!strcmp(tok, "file")) {
+        disk.phystype = PHYSTYPE_FILE;
+    } else if (!strcmp(tok, "tap")) {
+        tok = strtok(NULL, ":");
+        if (!strcmp(tok, "aio")) {
+            disk.phystype = PHYSTYPE_AIO;
+        } else if (!strcmp(tok, "vhd")) {
+            disk.phystype = PHYSTYPE_VHD;
+        } else if (!strcmp(tok, "qcow")) {
+            disk.phystype = PHYSTYPE_QCOW;
+        } else if (!strcmp(tok, "qcow2")) {
+            disk.phystype = PHYSTYPE_QCOW2;
+        } else {
+            fprintf(stderr, "Error: `%s' is not a valid disk image.\n", tok);
+            exit(1);
+        }
+    } else {
+        fprintf(stderr, "Error: `%s' is not a valid block device.\n", tok);
+        exit(1);
+    }
+    disk.physpath = strtok(NULL, "\0");
+    if (!disk.physpath) {
+        fprintf(stderr, "Error: missing path to disk image.\n");
+        exit(1);
+    }
+    disk.virtpath = argv[4];
+    disk.unpluggable = 1;
+    disk.readwrite = ((argc <= 4) || (argv[5][0] == 'w'));
+
+    if (domain_qualifier_to_domid(argv[2], &fe_domid, 0) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[2]);
+        exit(1);
+    }
+    if (argc == 7) {
+        if (domain_qualifier_to_domid(argv[6], &be_domid, 0) < 0) {
+            fprintf(stderr, "%s is an invalid domain identifier\n", argv[6]);
+            exit(1);
+        }
+    }
+    disk.domid = fe_domid;
+    disk.backend_domid = be_domid;
+    if (libxl_device_disk_add(&ctx, fe_domid, &disk)) {
+        fprintf(stderr, "libxl_device_disk_add failed.\n");
+    }
+    exit(0);
+}
+
+int main_blocklist(int argc, char **argv)
+{
+    int opt;
+    int nb;
+    libxl_device_disk *disks;
+    libxl_diskinfo diskinfo;
+
+    if (argc < 3) {
+        help("block-list");
+        exit(0);
+    }
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("block-list");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    printf("%-5s %-3s %-6s %-5s %-6s %-8s %-30s\n",
+           "Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path");
+    for (argv += 2, argc -= 2; argc > 0; --argc, ++argv) {
+        if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
+            fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+            continue;
+        }
+        disks = libxl_device_disk_list(&ctx, domid, &nb);
+        if (!disks) {
+            continue;
+        }
+        for (; nb > 0; --nb, ++disks) {
+            if (!libxl_device_disk_getinfo(&ctx, domid, disks, &diskinfo)) {
+                /*      Vdev BE   hdl  st   evch rref BE-path*/
+                printf("%-5d %-3d %-6d %-5d %-6d %-8d %-30s\n",
+                       diskinfo.devid, diskinfo.backend_id, 
diskinfo.frontend_id,
+                       diskinfo.state, diskinfo.evtch, diskinfo.rref, 
diskinfo.backend);
+            }
+        }
+    }
+    exit(0);
+}
+
+int main_blockdetach(int argc, char **argv)
+{
+    int opt;
+    libxl_device_disk disk;
+
+    if (argc != 4) {
+        help("block-detach");
+        exit(0);
+    }
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("block-detach");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    if (domain_qualifier_to_domid(argv[2], &domid, 0) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[2]);
+        exit(1);
+    }
+    if (libxl_devid_to_device_disk(&ctx, domid, argv[3], &disk)) {
+        fprintf(stderr, "Error: Device %s not connected.\n", argv[3]);
+        exit(1);
+    }
+    if (libxl_device_disk_del(&ctx, &disk, 1)) {
+        fprintf(stderr, "libxl_device_del failed.\n");
+    }
+    exit(0);
+}
+
+static char *uptime_to_string(unsigned long time, int short_mode)
+{
+    int sec, min, hour, day;
+    char *time_string;
+    int ret;
+
+    day = (int)(time / 86400);
+    time -= (day * 86400);
+    hour = (int)(time / 3600);
+    time -= (hour * 3600);
+    min = (int)(time / 60);
+    time -= (min * 60);
+    sec = time;
+
+    if (short_mode)
+        if (day > 1)
+            ret = asprintf(&time_string, "%d days, %2d:%02d", day, hour, min);
+        else if (day == 1)
+            ret = asprintf(&time_string, "%d day, %2d:%02d", day, hour, min);
+        else
+            ret = asprintf(&time_string, "%2d:%02d", hour, min);
+    else
+        if (day > 1)
+            ret = asprintf(&time_string, "%d days, %2d:%02d:%02d", day, hour, 
min, sec);
+        else if (day == 1)
+            ret = asprintf(&time_string, "%d day, %2d:%02d:%02d", day, hour, 
min, sec);
+        else
+            ret = asprintf(&time_string, "%2d:%02d:%02d", hour, min, sec);
+
+    if (ret < 0)
+        return NULL;
+    return time_string;
+}
+
+static char *current_time_to_string(time_t now)
+{
+    char now_str[100];
+    struct tm *tmp;
+
+    tmp = localtime(&now);
+    if (tmp == NULL) {
+        fprintf(stderr, "Get localtime error");
+        exit(-1);
+    }
+    if (strftime(now_str, sizeof(now_str), "%H:%M:%S", tmp) == 0) {
+        fprintf(stderr, "strftime returned 0");
+        exit(-1);
+    }
+    return strdup(now_str);
+}
+
+static void print_dom0_uptime(int short_mode, time_t now)
+{
+    int fd;
+    char buf[512];
+    uint32_t uptime = 0;
+    char *uptime_str = NULL;
+    char *now_str = NULL;
+
+    fd = open("/proc/uptime", O_RDONLY);
+    if (fd == -1)
+        goto err;
+
+    if (read(fd, buf, sizeof(buf)) == -1) {
+        close(fd);
+        goto err;
+    }
+    close(fd);
+
+    strtok(buf, " ");
+    uptime = strtoul(buf, NULL, 10);
+
+    if (short_mode)
+    {
+        now_str = current_time_to_string(now);
+        uptime_str = uptime_to_string(uptime, 1);
+        printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
+               libxl_domid_to_name(&ctx, 0), 0);
+    }
+    else
+    {
+        uptime_str = uptime_to_string(uptime, 0);
+        printf("%-33s %4d %s\n", libxl_domid_to_name(&ctx, 0),
+               0, uptime_str);
+    }
+
+    if (now_str)
+        free(now_str);
+    if (uptime_str)
+        free(uptime_str);
+    return;
+err:
+    fprintf(stderr, "Can not get Dom0 uptime.\n");
+    exit(-1);
+}
+
+static void print_domU_uptime(uint32_t domuid, int short_mode, time_t now)
+{
+    uint32_t s_time = 0;
+    uint32_t uptime = 0;
+    char *uptime_str = NULL;
+    char *now_str = NULL;
+
+    s_time = libxl_vm_get_start_time(&ctx, domuid);
+    if (s_time == -1)
+        return;
+    uptime = now - s_time;
+    if (short_mode)
+    {
+        now_str = current_time_to_string(now);
+        uptime_str = uptime_to_string(uptime, 1);
+        printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
+               libxl_domid_to_name(&ctx, domuid), domuid);
+    }
+    else
+    {
+        uptime_str = uptime_to_string(uptime, 0);
+        printf("%-33s %4d %s\n", libxl_domid_to_name(&ctx, domuid),
+               domuid, uptime_str);
+    }
+
+    if (now_str)
+        free(now_str);
+    if (uptime_str)
+        free(uptime_str);
+    return;
+}
+
+static void print_uptime(int short_mode, uint32_t doms[], int nb_doms)
+{
+    struct libxl_vminfo *info;
+    time_t now;
+    int nb_vm, i;
+
+    now = time(NULL);
+
+    if (!short_mode)
+        printf("%-33s %4s %s\n", "Name", "ID", "Uptime");
+
+    if (nb_doms == 0) {
+        print_dom0_uptime(short_mode, now);
+        info = libxl_list_vm(&ctx, &nb_vm);
+        for (i = 0; i < nb_vm; i++)
+            print_domU_uptime(info[i].domid, short_mode, now);
+    } else {
+        for (i = 0; i < nb_doms; i++) {
+            if (doms[i] == 0)
+                print_dom0_uptime(short_mode, now);
+            else
+                print_domU_uptime(doms[i], short_mode, now);
+        }
+    }
+}
+
+int main_uptime(int argc, char **argv)
+{
+    char *dom = NULL;
+    int short_mode = 0;
+    uint32_t domains[100];
+    int nb_doms = 0;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "hs")) != -1) {
+        switch (opt) {
+        case 's':
+            short_mode = 1;
+            break;
+        case 'h':
+            help("uptime");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    for (;(dom = argv[optind]) != NULL; nb_doms++,optind++) {
+        find_domain(dom);
+        domains[nb_doms] = domid;
+    }
+
+    print_uptime(short_mode, domains, nb_doms);
+
+    exit(0);
+}
+
+int main_tmem_list(int argc, char **argv)
+{
+    char *dom = NULL;
+    char *buf = NULL;
+    int use_long = 0;
+    int all = 0;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "alh")) != -1) {
+        switch (opt) {
+        case 'l':
+            use_long = 1;
+            break;
+        case 'a':
+            all = 1;
+            break;
+        case 'h':
+            help("tmem-list");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-list");
+        exit(1);
+    }
+
+    if (all)
+        domid = -1;
+    else
+        find_domain(dom);
+
+    buf = libxl_tmem_list(&ctx, domid, use_long);
+    if (buf == NULL)
+        exit(-1);
+
+    printf("%s\n", buf);
+    free(buf);
+    exit(0);
+}
+
+int main_tmem_freeze(int argc, char **argv)
+{
+    char *dom = NULL;
+    int all = 0;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "ah")) != -1) {
+        switch (opt) {
+        case 'a':
+            all = 1;
+            break;
+        case 'h':
+            help("tmem-freeze");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-freeze");
+        exit(1);
+    }
+
+    if (all)
+        domid = -1;
+    else
+        find_domain(dom);
+
+    libxl_tmem_freeze(&ctx, domid);
+    exit(0);
+}
+
+int main_tmem_destroy(int argc, char **argv)
+{
+    char *dom = NULL;
+    int all = 0;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "ah")) != -1) {
+        switch (opt) {
+        case 'a':
+            all = 1;
+            break;
+        case 'h':
+            help("tmem-destroy");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-destroy");
+        exit(1);
+    }
+
+    if (all)
+        domid = -1;
+    else
+        find_domain(dom);
+
+    libxl_tmem_destroy(&ctx, domid);
+    exit(0);
+}
+
+int main_tmem_thaw(int argc, char **argv)
+{
+    char *dom = NULL;
+    int all = 0;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "ah")) != -1) {
+        switch (opt) {
+        case 'a':
+            all = 1;
+            break;
+        case 'h':
+            help("tmem-thaw");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-thaw");
+        exit(1);
+    }
+
+    if (all)
+        domid = -1;
+    else
+        find_domain(dom);
+
+    libxl_tmem_thaw(&ctx, domid);
+    exit(0);
+}
+
+int main_tmem_set(int argc, char **argv)
+{
+    char *dom = NULL;
+    uint32_t weight = 0, cap = 0, compress = 0;
+    int opt_w = 0, opt_c = 0, opt_p = 0;
+    int all = 0;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "aw:c:p:h")) != -1) {
+        switch (opt) {
+        case 'a':
+            all = 1;
+            break;
+        case 'w':
+            weight = strtol(optarg, NULL, 10);
+            opt_w = 1;
+            break;
+        case 'c':
+            cap = strtol(optarg, NULL, 10);
+            opt_c = 1;
+            break;
+        case 'p':
+            compress = strtol(optarg, NULL, 10);
+            opt_p = 1;
+            break;
+        case 'h':
+            help("tmem-set");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-set");
+        exit(1);
+    }
+
+    if (all)
+        domid = -1;
+    else
+        find_domain(dom);
+
+    if (!opt_w && !opt_c && !opt_p) {
+        fprintf(stderr, "No set value specified.\n\n");
+        help("tmem-set");
+        exit(1);
+    }
+
+    if (opt_w)
+        libxl_tmem_set(&ctx, domid, "weight", weight);
+    if (opt_c)
+        libxl_tmem_set(&ctx, domid, "cap", cap);
+    if (opt_p)
+        libxl_tmem_set(&ctx, domid, "compress", compress);
+
+    exit(0);
+}
+
+int main_tmem_shared_auth(int argc, char **argv)
+{
+    char *autharg = NULL;
+    char *endptr = NULL;
+    char *dom = NULL;
+    char *uuid = NULL;
+    int auth = -1;
+    int all = 0;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "au:A:h")) != -1) {
+        switch (opt) {
+        case 'a':
+            all = 1;
+            break;
+        case 'u':
+            uuid = optarg;
+            break;
+        case 'A':
+            autharg = optarg;
+            break;
+        case 'h':
+            help("tmem-shared-auth");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-shared-auth");
+        exit(1);
+    }
+
+    if (all)
+        domid = -1;
+    else
+        find_domain(dom);
+
+    if (uuid == NULL || autharg == NULL) {
+        fprintf(stderr, "No uuid or auth specified.\n\n");
+        help("tmem-shared-auth");
+        exit(1);
+    }
+
+    auth = strtol(autharg, &endptr, 10);
+    if (*endptr != '\0') {
+        fprintf(stderr, "Invalid auth, valid auth are <0|1>.\n\n");
+        exit(1);
+    }
+
+    libxl_tmem_shared_auth(&ctx, domid, uuid, auth);
+
+    exit(0);
+}
+
diff -r 1952867c5c92 -r b1321a50f626 tools/libxl/xl_cmdtable.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/xl_cmdtable.c Tue Jul 06 16:49:01 2010 +0100
@@ -0,0 +1,322 @@
+/*
+ * Author Yang Hongyang <yanghy@xxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <string.h>
+
+#include "xl.h"
+
+struct cmd_spec cmd_table[] = {
+    { "create",
+      &main_create,
+      "Create a domain from config file <filename>",
+      "<ConfigFile> [options] [vars]",
+      "-h                      Print this help.\n"
+      "-p                      Leave the domain paused after it is created.\n"
+      "-c                      Connect to the console after the domain is 
created.\n"
+      "-d                      Enable debug messages.\n"
+      "-f=FILE, --defconfig=FILE\n                     Use the given 
configuration file.\n"
+      "-q, --quiet             Quiet.\n"
+      "-n, --dryrun            Dry run - prints the resulting configuration.\n"
+      "-d                      Enable debug messages.\n"
+      "-e                      Do not wait in the background for the death of 
the domain."
+    },
+    { "list",
+      &main_list,
+      "List information about all/some domains",
+      "[options] [Domain]\n",
+      "-l, --long                              Output all VM details"
+      "-v, --verbose                   Prints out UUIDs",
+    },
+    { "destroy",
+      &main_destroy,
+      "Terminate a domain immediately",
+      "<Domain>",
+    },
+    { "shutdown",
+      &main_shutdown,
+      "Issue a shutdown signal to a domain",
+      "<Domain>",
+    },
+    { "reboot",
+      &main_reboot,
+      "Issue a reboot signal to a domain",
+      "<Domain>",
+    },
+    { "pci-attach",
+      &main_pciattach,
+      "Insert a new pass-through pci device",
+      "<Domain> <BDF> [Virtual Slot]",
+    },
+    { "pci-detach",
+      &main_pcidetach,
+      "Remove a domain's pass-through pci device",
+      "<Domain> <BDF>",
+    },
+    { "pci-list",
+      &main_pcilist,
+      "List pass-through pci devices for a domain",
+      "<Domain>",
+    },
+    { "pause",
+      &main_pause,
+      "Pause execution of a domain",
+      "<Domain>",
+    },
+    { "unpause",
+      &main_unpause,
+      "Unpause a paused domain",
+      "<Domain>",
+    },
+    { "console",
+      &main_console,
+      "Attach to domain's console",
+      "<Domain>",
+    },
+    { "save",
+      &main_save,
+      "Save a domain state to restore later",
+      "[options] <Domain> <CheckpointFile> [<ConfigFile>]",
+      "-h  Print this help.\n"
+      "-c  Leave domain running after creating the snapshot."
+    },
+    { "migrate",
+      &main_migrate,
+      "Save a domain state to restore later",
+      "[options] <Domain> <host>",
+      "-h              Print this help.\n"
+      "-C <config>     Send <config> instead of config file from creation.\n"
+      "-s <sshcommand> Use <sshcommand> instead of ssh.  String will be 
passed\n"
+      "                to sh. If empty, run <host> instead of ssh <host> xl\n"
+      "                migrate-receive [-d -e]\n"
+      "-e              Do not wait in the background (on <host>) for the 
death\n"
+      "                of the domain."
+    },
+    { "restore",
+      &main_restore,
+      "Restore a domain from a saved state",
+      "[options] [<ConfigFile>] <CheckpointFile>",
+      "-h  Print this help.\n"
+      "-p  Do not unpause domain after restoring it.\n"
+      "-e  Do not wait in the background for the death of the domain.\n"
+      "-d  Enable debug messages."
+    },
+    { "migrate-receive",
+      &main_migrate_receive,
+      "Restore a domain from a saved state",
+      "- for internal use only",
+    },
+    { "cd-insert",
+      &main_cd_insert,
+      "Insert a cdrom into a guest's cd drive",
+      "<Domain> <VirtualDevice> <type:path>",
+    },
+    { "cd-eject",
+      &main_cd_eject,
+      "Eject a cdrom from a guest's cd drive",
+      "<Domain> <VirtualDevice>",
+    },
+    { "mem-max",
+      &main_memmax,
+      "Set the maximum amount reservation for a domain",
+      "<Domain> <MemMB['b'[bytes]|'k'[KB]|'m'[MB]|'g'[GB]|'t'[TB]]>",
+    },
+    { "mem-set",
+      &main_memset,
+      "Set the current memory usage for a domain",
+      "<Domain> <MemMB['b'[bytes]|'k'[KB]|'m'[MB]|'g'[GB]|'t'[TB]]>",
+    },
+    { "button-press",
+      &main_button_press,
+      "Indicate an ACPI button press to the domain",
+      "<Domain> <Button>",
+      "<Button> may be 'power' or 'sleep'."
+    },
+    { "vcpu-list",
+      &main_vcpulist,
+      "List the VCPUs for all/some domains",
+      "[Domain, ...]",
+    },
+    { "vcpu-pin",
+      &main_vcpupin,
+      "Set which CPUs a VCPU can use",
+      "<Domain> <VCPU|all> <CPUs|all>",
+    },
+    { "vcpu-set",
+      &main_vcpuset,
+      "Set the number of active VCPUs allowed for the domain",
+      "<Domain> <vCPUs>",
+    },
+    { "list-vm",
+      &main_list_vm,
+      "List the VMs,without DOM0",
+      "",
+    },
+    { "info",
+      &main_info,
+      "Get information about Xen host",
+      "",
+    },
+    { "sched-credit",
+      &main_sched_credit,
+      "Get/set credit scheduler parameters",
+      "[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]",
+      "-d DOMAIN, --domain=DOMAIN     Domain to modify\n"
+      "-w WEIGHT, --weight=WEIGHT     Weight (int)\n"
+      "-c CAP, --cap=CAP              Cap (int)"
+    },
+    { "domid",
+      &main_domid,
+      "Convert a domain name to domain id",
+      "<DomainName>",
+    },
+    { "domname",
+      &main_domname,
+      "Convert a domain id to domain name",
+      "<DomainId>",
+    },
+    { "rename",
+      &main_rename,
+      "Rename a domain",
+      "<Domain> <NewDomainName>",
+    },
+    { "trigger",
+      &main_trigger,
+      "Send a trigger to a domain",
+      "<Domain> <nmi|reset|init|power|sleep> [<VCPU>]",
+    },
+    { "sysrq",
+      &main_sysrq,
+      "Send a sysrq to a domain",
+      "<Domain> <letter>",
+    },
+    { "debug-keys",
+      &main_debug_keys,
+      "Send debug keys to Xen",
+      "<Keys>",
+    },
+    { "dmesg",
+      &main_dmesg,
+      "Read and/or clear dmesg buffer",
+      "[-c]",
+      "  -c                        Clear dmesg buffer as well as printing it",
+    },
+    { "top",
+      &main_top,
+      "Monitor a host and the domains in real time",
+      "",
+    },
+    { "network-attach",
+      &main_networkattach,
+      "Create a new virtual network device",
+      "<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] "
+      "[ip=<ip>] [script=<script>] [backend=<BackDomain>] [vifname=<name>] "
+      "[rate=<rate>] [model=<model>][accel=<accel>]",
+    },
+    { "network-list",
+      &main_networklist,
+      "List virtual network interfaces for a domain",
+      "<Domain(s)>",
+    },
+    { "network-detach",
+      &main_networkdetach,
+      "Destroy a domain's virtual network device",
+      "<Domain> <DevId|mac>",
+    },
+    { "block-attach",
+      &main_blockattach,
+      "Create a new virtual block device",
+      "<Domain> <BackDev> <FrontDev> [<Mode>] [BackDomain]",
+    },
+    { "block-list",
+      &main_blocklist,
+      "List virtual block devices for a domain",
+      "<Domain(s)>",
+    },
+    { "block-detach",
+      &main_blockdetach,
+      "Destroy a domain's virtual block device",
+      "<Domain> <DevId>",
+    },
+    { "uptime",
+      &main_uptime,
+      "Print uptime for all/some domains",
+      "[-s] [Domain]",
+    },
+    { "tmem-list",
+      &main_tmem_list,
+      "List tmem pools",
+      "[-l] [<Domain>|-a]",
+      "  -l                             List tmem stats",
+    },
+    { "tmem-freeze",
+      &main_tmem_freeze,
+      "Freeze tmem pools",
+      "[<Domain>|-a]",
+      "  -a                             Freeze all tmem",
+    },
+    { "tmem-destroy",
+      &main_tmem_destroy,
+      "Destroy tmem pools",
+      "[<Domain>|-a]",
+      "  -a                             Destroy all tmem",
+    },
+    { "tmem-thaw",
+      &main_tmem_thaw,
+      "Thaw tmem pools",
+      "[<Domain>|-a]",
+      "  -a                             Thaw all tmem",
+    },
+    { "tmem-set",
+      &main_tmem_set,
+      "Change tmem settings",
+      "[<Domain>|-a] [-w[=WEIGHT]|-c[=CAP]|-p[=COMPRESS]]",
+      "  -a                             Operate on all tmem\n"
+      "  -w WEIGHT                      Weight (int)\n"
+      "  -c CAP                         Cap (int)\n"
+      "  -p COMPRESS                    Compress (int)",
+    },
+    { "tmem-shared-auth",
+      &main_tmem_shared_auth,
+      "De/authenticate shared tmem pool",
+      "[<Domain>|-a] [-u[=UUID] [-A[=AUTH]",
+      "  -a                             Authenticate for all tmem pools\n"
+      "  -u UUID                        Specify uuid\n"
+      "                                 
(abcdef01-2345-6789-1234-567890abcdef)\n"
+      "  -A AUTH                        0=auth,1=deauth",
+    },
+};
+
+int cmdtable_len = sizeof(cmd_table)/sizeof(struct cmd_spec);
+
+/* Look up a command in the table, allowing unambiguous truncation */
+struct cmd_spec *cmdtable_lookup(const char *s)
+{
+    struct cmd_spec *cmd = NULL;
+    size_t len;
+    int i, count = 0;
+
+    if (!s)
+        return NULL;
+    len = strlen(s);
+    for (i = 0; i < cmdtable_len; i++) {
+        if (!strncmp(s, cmd_table[i].cmd_name, len)) {
+            cmd = &cmd_table[i];
+            /* Take an exact match, even if it also prefixes another command */
+            if (len == strlen(cmd->cmd_name))
+                return cmd;
+            count++;
+        }
+    }
+    return (count == 1) ? cmd : NULL;
+}
diff -r 1952867c5c92 -r b1321a50f626 tools/xenstore/xs.c
--- a/tools/xenstore/xs.c       Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/xenstore/xs.c       Tue Jul 06 16:49:01 2010 +0100
@@ -236,10 +236,39 @@ struct xs_handle *xs_domain_open(void)
        return get_handle(xs_domain_dev());
 }
 
+static void close_free_msgs(struct xs_handle *h) {
+       struct xs_stored_msg *msg, *tmsg;
+
+       list_for_each_entry_safe(msg, tmsg, &h->reply_list, list) {
+               free(msg->body);
+               free(msg);
+       }
+
+       list_for_each_entry_safe(msg, tmsg, &h->watch_list, list) {
+               free(msg->body);
+               free(msg);
+       }
+}
+
+static void close_fds_free(struct xs_handle *h) {
+       if (h->watch_pipe[0] != -1) {
+               close(h->watch_pipe[0]);
+               close(h->watch_pipe[1]);
+       }
+
+       close(h->fd);
+
+       free(h);
+}
+
+void xs_daemon_destroy_postfork(struct xs_handle *h)
+{
+       close_free_msgs(h);
+       close_fds_free(h);
+}
+
 void xs_daemon_close(struct xs_handle *h)
 {
-       struct xs_stored_msg *msg, *tmsg;
-
 #ifdef USE_PTHREAD
        if (h->read_thr_exists) {
                pthread_cancel(h->read_thr);
@@ -251,28 +280,11 @@ void xs_daemon_close(struct xs_handle *h
        mutex_lock(&h->reply_mutex);
        mutex_lock(&h->watch_mutex);
 
-       list_for_each_entry_safe(msg, tmsg, &h->reply_list, list) {
-               free(msg->body);
-               free(msg);
-       }
-
-       list_for_each_entry_safe(msg, tmsg, &h->watch_list, list) {
-               free(msg->body);
-               free(msg);
-       }
+       close_free_msgs(h);
 
        mutex_unlock(&h->request_mutex);
        mutex_unlock(&h->reply_mutex);
        mutex_unlock(&h->watch_mutex);
-
-       if (h->watch_pipe[0] != -1) {
-               close(h->watch_pipe[0]);
-               close(h->watch_pipe[1]);
-       }
-
-       close(h->fd);
-
-       free(h);
 }
 
 static bool read_all(int fd, void *data, unsigned int len)
diff -r 1952867c5c92 -r b1321a50f626 tools/xenstore/xs.h
--- a/tools/xenstore/xs.h       Mon Jul 05 12:11:38 2010 +0100
+++ b/tools/xenstore/xs.h       Tue Jul 06 16:49:01 2010 +0100
@@ -47,6 +47,9 @@ struct xs_handle *xs_daemon_open_readonl
 
 /* Close the connection to the xs daemon. */
 void xs_daemon_close(struct xs_handle *);
+
+/* Throw away the connection to the xs daemon, for use after fork(). */
+void xs_daemon_destroy_postfork(struct xs_handle *);
 
 /* Get contents of a directory.
  * Returns a malloced array: call free() on it after use.

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-4.0-testing] libxl: Backported stuff from unstable, Xen patchbot-4.0-testing <=