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-unstable] xenstore: Remove broken and unmaintained

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] xenstore: Remove broken and unmaintained test code.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 03 Jul 2007 13:35:44 -0700
Delivery-date: Tue, 03 Jul 2007 13:34:11 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
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/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/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 kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1183474319 -3600
# Node ID eb71f258e8551858ff11d2331f008539cf399a55
# Parent  0528bc25c4042188bf25f5f0c365f7849d63a684
xenstore: Remove broken and unmaintained test code.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 tools/xenstore/fake_libxc.c                     |  143 --
 tools/xenstore/speedtest.c                      |  130 -
 tools/xenstore/testsuite/01simple.test          |    4 
 tools/xenstore/testsuite/02directory.test       |   45 
 tools/xenstore/testsuite/03write.test           |   28 
 tools/xenstore/testsuite/04rm.test              |   20 
 tools/xenstore/testsuite/05filepermissions.test |   81 -
 tools/xenstore/testsuite/06dirpermissions.test  |  119 -
 tools/xenstore/testsuite/07watch.test           |  176 --
 tools/xenstore/testsuite/08transaction.slowtest |   43 
 tools/xenstore/testsuite/08transaction.test     |   92 -
 tools/xenstore/testsuite/09domain.test          |   19 
 tools/xenstore/testsuite/10domain-homedir.test  |   18 
 tools/xenstore/testsuite/11domain-watch.test    |   50 
 tools/xenstore/testsuite/12readonly.test        |   38 
 tools/xenstore/testsuite/13watch-ack.test       |   21 
 tools/xenstore/testsuite/14complexperms.test    |   68 -
 tools/xenstore/testsuite/test.sh                |   64 
 tools/xenstore/testsuite/vg-suppressions        |    9 
 tools/xenstore/xenstored_test.h                 |   37 
 tools/xenstore/xs_crashme.c                     |  393 -----
 tools/xenstore/xs_random.c                      | 1590 ------------------------
 tools/xenstore/xs_stress.c                      |  207 ---
 tools/xenstore/xs_test.c                        |  812 ------------
 tools/xenstore/Makefile                         |   94 -
 tools/xenstore/xenstored_core.c                 |  105 -
 tools/xenstore/xenstored_domain.c               |    4 
 tools/xenstore/xenstored_transaction.c          |    1 
 tools/xenstore/xenstored_watch.c                |   12 
 29 files changed, 5 insertions(+), 4418 deletions(-)

diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/Makefile
--- a/tools/xenstore/Makefile   Tue Jul 03 15:49:16 2007 +0100
+++ b/tools/xenstore/Makefile   Tue Jul 03 15:51:59 2007 +0100
@@ -11,15 +11,11 @@ BASECFLAGS += -Wp,-MD,.$(@F).d
 BASECFLAGS += -Wp,-MD,.$(@F).d
 PROG_DEP = .*.d
 BASECFLAGS+= $(PROFILE)
-#BASECFLAGS+= -I$(XEN_ROOT)/tools
 BASECFLAGS+= -I$(XEN_ROOT)/tools/libxc
 BASECFLAGS+= -I.
 
 CFLAGS  += $(BASECFLAGS)
 LDFLAGS += $(PROFILE) -L$(XEN_LIBXC)
-TESTDIR  = testsuite/tmp
-TESTFLAGS= -DTESTING
-TESTENV  = XENSTORED_ROOTDIR=$(TESTDIR) XENSTORED_RUNDIR=$(TESTDIR)
 
 CLIENTS := xenstore-exists xenstore-list xenstore-read xenstore-rm 
xenstore-chmod
 CLIENTS += xenstore-write
@@ -34,12 +30,6 @@ XENSTORED_OBJS += $(XENSTORED_OBJS_y)
 
 .PHONY: all
 all: libxenstore.so libxenstore.a xenstored $(CLIENTS) xs_tdb_dump 
xenstore-control xenstore-ls
-
-test_interleaved_transactions: test_interleaved_transactions.o
-       $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o 
$@
-
-.PHONY: testcode
-testcode: xs_test xenstored_test xs_random
 
 xenstored: $(XENSTORED_OBJS)
        $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl 
$(SOCKET_LIBS) -o $@
@@ -56,34 +46,8 @@ xenstore-ls: xsls.o libxenstore.so
 xenstore-ls: xsls.o libxenstore.so
        $(CC) $(CFLAGS) $(LDFLAGS) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore 
$(SOCKET_LIBS) -o $@
 
-xenstored_test: xenstored_core_test.o xenstored_watch_test.o 
xenstored_domain_test.o xenstored_transaction_test.o xs_lib.o talloc_test.o 
fake_libxc.o utils.o tdb.o
-       $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
-
 xs_tdb_dump: xs_tdb_dump.o utils.o tdb.o talloc.o
        $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
-
-xs_test xs_random xs_stress xs_crashme: LDFLAGS+=-lpthread
-xs_test: xs_test.o xs_lib.o utils.o
-xs_random: xs_random.o xs_test_lib.o xs_lib.o talloc.o utils.o
-xs_stress: xs_stress.o xs_test_lib.o xs_lib.o talloc.o utils.o
-xs_crashme: xs_crashme.o xs_lib.o talloc.o utils.o
-
-speedtest: speedtest.o xs.o xs_lib.o utils.o talloc.o
-
-.PHONY: check-speed
-check-speed: speedtest xenstored_test $(TESTDIR)
-       $(TESTENV) time ./speedtest 100
-
-xs_test.o xs_stress.o xenstored_core_test.o xenstored_watch_test.o 
xenstored_transaction_test.o xenstored_domain_test.o xs_random.o xs_test_lib.o 
talloc_test.o fake_libxc.o xs_crashme.o: CFLAGS=$(BASECFLAGS) $(TESTFLAGS)
-
-xenstored_%_test.o: xenstored_%.c
-       $(COMPILE.c) -o $@ $<
-
-xs_test_lib.o: xs.c
-       $(COMPILE.c) -o $@ $<
-
-talloc_test.o: talloc.c
-       $(COMPILE.c) -o $@ $<
 
 libxenstore.so: libxenstore.so.$(MAJOR)
        ln -sf $< $@
@@ -97,66 +61,12 @@ libxenstore.a: xs.o xs_lib.o
        $(AR) rcs libxenstore.a $^
 
 .PHONY: clean
-clean: testsuite-clean
+clean:
        rm -f *.a *.o *.opic *.so*
        rm -f xenstored xs_random xs_stress xs_crashme
-       rm -f xs_test xenstored_test xs_tdb_dump xenstore-control xenstore-ls
+       rm -f xs_tdb_dump xenstore-control xenstore-ls
        rm -f $(CLIENTS)
        $(RM) $(PROG_DEP)
-
-.PHONY: print-dir
-print-dir:
-       @echo -n tools/xenstore: 
-
-.PHONY: print-end
-print-end:
-       @echo
-
-.PHONY: check
-check: print-dir testsuite-fast randomcheck-fast print-end
-
-.PHONY: fullcheck
-fullcheck: testsuite-run randomcheck stresstest
-
-$(TESTDIR):
-       mkdir $@
-
-.PHONY: testsuite-run
-testsuite-run: xenstored_test xs_test $(TESTDIR)
-       $(TESTENV) testsuite/test.sh && echo
-
-.PHONY: testsuite-fast
-testsuite-fast: xenstored_test xs_test $(TESTDIR)
-       @$(TESTENV) testsuite/test.sh --fast
-
-.PHONY: testsuite-clean
-testsuite-clean:
-       rm -rf $(TESTDIR)
-
-# Make this visible so they can see repeat tests without --fast if they
-# fail.
-RANDSEED=$(shell date +%s)
-.PHONY: randomcheck
-randomcheck: xs_random xenstored_test $(TESTDIR)
-       $(TESTENV) ./xs_random --simple --fast /tmp/xs_random 200000 
$(RANDSEED) && echo
-       $(TESTENV) ./xs_random --fast /tmp/xs_random 100000 $(RANDSEED) && echo
-#      $(TESTENV) ./xs_random --fail /tmp/xs_random 10000 $(RANDSEED)
-
-.PHONY: crashme
-crashme:  xs_crashme xenstored_test $(TESTDIR)
-       rm -rf $(TESTDIR)/store $(TESTDIR)/transactions /tmp/xs_crashme.vglog* 
/tmp/trace
-       export $(TESTENV); ./xs_crashme 5000 $(RANDSEED) 2>/dev/null
-       if [ -n "`cat /tmp/xs_crashme.vglog*`" ]; then echo Valgrind 
complained; cat /tmp/xs_crashme.vglog*; exit 1; fi
-       rm -rf $(TESTDIR)/store $(TESTDIR)/transactions /tmp/xs_crashme.vglog* 
/tmp/trace
-
-.PHONY: randomcheck-fast
-randomcheck-fast: xs_random xenstored_test $(TESTDIR)
-       @$(TESTENV) ./xs_random --fast /tmp/xs_random 2000 $(RANDSEED)
-
-.PHONY: stresstest
-stresstest: xs_stress xenstored_test $(TESTDIR)
-       rm -rf $(TESTDIR)/store $(TESTDIR)/transactions
-       export $(TESTENV); PID=`./xenstored_test --output-pid 
--trace-file=/tmp/trace`; ./xs_stress 5000; ret=$$?; kill $$PID; exit $$ret
 
 .PHONY: TAGS
 TAGS:
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/fake_libxc.c
--- a/tools/xenstore/fake_libxc.c       Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-/* 
-    Fake libxc which doesn't require hypervisor but talks to xs_test.
-    Copyright (C) 2005 Rusty Russell IBM Corporation
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    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 General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <assert.h>
-#include <signal.h>
-#include "utils.h"
-#include "xenstored_core.h"
-#include "xenstored_domain.h"
-#include "xenstored_test.h"
-#include <xenctrl.h>
-
-static int sigfd;
-static int xs_test_pid;
-static evtchn_port_t port;
-
-/* The event channel maps to a signal, shared page to an mmapped file. */
-void xc_evtchn_notify(int xce_handle, int local_port)
-{
-       assert(local_port == port);
-       if (kill(xs_test_pid, SIGUSR2) != 0)
-               barf_perror("fake event channel failed");
-}
-
-void *xc_map_foreign_range(int xc_handle, uint32_t dom __attribute__((unused)),
-                          int size, int prot,
-                          unsigned long mfn __attribute__((unused)))
-{
-       void *ret;
-
-       ret = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0);
-       if (ret == MAP_FAILED)
-               return NULL;
-
-       /* xs_test tells us pid and port by putting it in buffer, we reply. */
-       xs_test_pid = *(int *)(ret + 32);
-       port = *(int *)(ret + 36);
-       *(int *)(ret + 32) = getpid();
-       return ret;
-}
-
-int xc_interface_open(void)
-{
-       int fd;
-       char page[getpagesize()];
-
-       fd = open("/tmp/xcmap", O_RDWR|O_CREAT|O_TRUNC, 0600);
-       if (fd < 0)
-               return fd;
-
-       memset(page, 0, sizeof(page));
-       if (!xs_write_all(fd, page, sizeof(page)))
-               barf_perror("Failed to write /tmp/xcmap page");
-       
-       return fd;
-}
-
-int xc_interface_close(int xc_handle)
-{
-       close(xc_handle);
-       return 0;
-}
-
-int xc_domain_getinfo(int xc_handle __attribute__((unused)),
-                     uint32_t first_domid, unsigned int max_doms,
-                      xc_dominfo_t *info)
-{
-       assert(max_doms == 1);
-        info->domid = first_domid;
-
-        info->dying    = 0;
-        info->shutdown = 0;
-        info->paused   = 0;
-        info->blocked  = 0;
-        info->running  = 1;
-
-        info->shutdown_reason = 0;
-
-        if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) )
-        {
-            info->shutdown = 0;
-            info->crashed  = 1;
-        }
-
-       return 1;
-}
-
-static void send_to_fd(int signo __attribute__((unused)))
-{
-       int saved_errno = errno;
-       write(sigfd, &port, sizeof(port));
-       errno = saved_errno;
-}
-
-void fake_block_events(void)
-{
-       signal(SIGUSR2, SIG_IGN);
-}
-
-void fake_ack_event(void)
-{
-       signal(SIGUSR2, send_to_fd);
-}
-
-int xc_evtchn_open(void)
-{
-       int fds[2];
-
-       if (pipe(fds) != 0)
-               return -1;
-
-       if (signal(SIGUSR2, send_to_fd) == SIG_ERR) {
-               int saved_errno = errno;
-               close(fds[0]);
-               close(fds[1]);
-               errno = saved_errno;
-               return -1;
-       }
-       sigfd = fds[1];
-       return fds[0];
-}
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/speedtest.c
--- a/tools/xenstore/speedtest.c        Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/* 
-    Xen Store Daemon Speed test
-    Copyright (C) 2005 Rusty Russell IBM Corporation
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    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 General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include "utils.h"
-#include "xs.h"
-#include "list.h"
-#include "talloc.h"
-
-static void do_command(const char *cmd)
-{
-       int ret;
-
-       ret = system(cmd);
-       if (ret == -1 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
-               barf_perror("Failed '%s': %i", cmd, ret);
-}
-
-static int start_daemon(void)
-{
-       int fds[2], pid;
-
-       do_command(talloc_asprintf(NULL, "rm -rf testsuite/tmp/*"));
-
-       /* Start daemon. */
-       pipe(fds);
-       if ((pid = fork())) {
-               /* Child writes PID when its ready: we wait for that. */
-               char buffer[20];
-               close(fds[1]);
-               if (read(fds[0], buffer, sizeof(buffer)) < 0)
-                       barf("Failed to summon daemon");
-               close(fds[0]);
-       } else {
-               dup2(fds[1], STDOUT_FILENO);
-               close(fds[0]);
-#if 0
-               execlp("valgrind", "valgrind", "-q", 
"--suppressions=testsuite/vg-suppressions", "xenstored_test", "--output-pid",
-                      "--no-fork", "--trace-file=/tmp/trace", NULL);
-#else
-               execlp("./xenstored_test", "xenstored_test", "--output-pid", 
"--no-fork", NULL);
-//             execlp("strace", "strace", "-o", "/tmp/out", 
"./xenstored_test", "--output-pid", "--no-fork", NULL);
-#endif
-               exit(1);
-       }
-       return pid;
-}
-
-static void kill_daemon(int pid)
-{
-       int saved_errno = errno;
-       kill(pid, SIGTERM);
-       errno = saved_errno;
-}
-
-#define NUM_ENTRIES 50
-
-/* We create the given number of trees, each with NUM_ENTRIES, using
- * transactions. */
-int main(int argc, char *argv[])
-{
-       int i, j, pid, print;
-       struct xs_handle *h;
-
-       if (argc != 2)
-               barf("Usage: speedtest <numdomains>");
-
-       pid = start_daemon();
-       h = xs_daemon_open();
-       print = atoi(argv[1]) / 76;
-       if (!print)
-               print = 1;
-       for (i = 0; i < atoi(argv[1]); i ++) {
-               char name[64];
-
-               if (i % print == 0)
-                       write(1, ".", 1);
-               if (!xs_transaction_start(h)) {
-                       kill_daemon(pid);
-                       barf_perror("Starting transaction");
-               }
-               sprintf(name, "/%i", i);
-               if (!xs_mkdir(h, name)) {
-                       kill_daemon(pid);
-                       barf_perror("Making directory %s", name);
-               }
-
-               for (j = 0; j < NUM_ENTRIES; j++) {
-                       sprintf(name, "/%i/%i", i, j);
-                       if (!xs_write(h, name, name, strlen(name))) {
-                               kill_daemon(pid);
-                               barf_perror("Making directory %s", name);
-                       }
-               }
-               if (!xs_transaction_end(h, false)) {
-                       kill_daemon(pid);
-                       barf_perror("Ending transaction");
-               }
-       }
-       write(1, "\n", 1);
-
-       kill_daemon(pid);
-       wait(NULL);
-       return 0;
-}
-       
-       
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/testsuite/01simple.test
--- a/tools/xenstore/testsuite/01simple.test    Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-# Create an entry, read it.
-write /test contents
-expect contents
-read /test
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/testsuite/02directory.test
--- a/tools/xenstore/testsuite/02directory.test Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-# Root directory has only tool dir in it.
-expect tool
-dir /
-
-# Create a file.
-write /test contents
-
-# Directory shows it.
-expect test
-expect tool
-dir /
-
-# Make a new directory, check it's there
-mkdir /dir
-expect dir
-expect test
-expect tool
-dir /
-
-# Check it's empty.
-dir /dir
-
-# Create a file, check it exists.
-write /dir/test2 contents2
-expect test2
-dir /dir
-expect contents2
-read /dir/test2
-
-# Creating dir over the top should succeed.
-mkdir /dir
-mkdir /dir/test2
-
-# Mkdir implicitly creates directories.
-mkdir /dir/1/2/3/4
-expect test2
-expect 1
-dir /dir
-expect 2
-dir /dir/1
-expect 3
-dir /dir/1/2
-expect 4
-dir /dir/1/2/3
-dir /dir/1/2/3/4
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/testsuite/03write.test
--- a/tools/xenstore/testsuite/03write.test     Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-# Write succeeds
-write /test contents
-expect contents
-read /test
-
-# Overwrite succeeds.
-write /test contents2
-expect contents2
-read /test
-
-# Write should implicitly create directories
-write /dir/test contents
-expect test
-dir /dir
-expect contents
-read /dir/test
-write /dir/1/2/3/4 contents4
-expect test
-expect 1
-dir /dir
-expect 2
-dir /dir/1
-expect 3
-dir /dir/1/2
-expect 4
-dir /dir/1/2/3
-expect contents4
-read /dir/1/2/3/4
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/testsuite/04rm.test
--- a/tools/xenstore/testsuite/04rm.test        Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-# Remove non-existant is OK, as long as parent exists
-rm /test
-expect rm failed: No such file or directory
-rm /dir/test
-
-# Create file and remove it
-write /test contents
-rm /test
-expect tool
-dir /
-
-# Create directory and remove it.
-mkdir /dir
-rm /dir
-
-# Create directory, create file, remove all.
-mkdir /dir
-write /dir/test contents
-rm /dir
-
diff -r 0528bc25c404 -r eb71f258e855 
tools/xenstore/testsuite/05filepermissions.test
--- a/tools/xenstore/testsuite/05filepermissions.test   Tue Jul 03 15:49:16 
2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-# Fail to get perms on non-existent file.
-expect getperm failed: No such file or directory
-getperm /test
-expect getperm failed: No such file or directory
-getperm /dir/test
-
-# Create file: inherits from root (0 READ)
-write /test contents
-expect 0 READ
-getperm /test
-setid 1
-expect 0 READ
-getperm /test
-expect contents
-read /test
-expect write failed: Permission denied
-write /test contents
-
-# Take away read access to file.
-setid 0
-setperm /test 0 NONE
-setid 1
-expect getperm failed: Permission denied
-getperm /test
-expect read failed: Permission denied
-read /test
-expect write failed: Permission denied
-write /test contents
-
-# Grant everyone write access to file.
-setid 0
-setperm /test 0 WRITE
-setid 1
-expect getperm failed: Permission denied
-getperm /test
-expect read failed: Permission denied
-read /test
-write /test contents2
-setid 0
-expect contents2
-read /test
-
-# Grant everyone both read and write access.
-setperm /test 0 READ/WRITE
-setid 1
-expect 0 READ/WRITE
-getperm /test
-expect contents2
-read /test
-write /test contents3
-expect contents3
-read /test
-
-# Change so that user 1 owns it, noone else can do anything.
-setid 0
-setperm /test 1 NONE
-setid 1
-expect 1 NONE
-getperm /test
-expect contents3
-read /test
-write /test contents4
-
-# User 2 can do nothing.
-setid 2
-expect setperm failed: Permission denied
-setperm /test 2 NONE
-expect getperm failed: Permission denied
-getperm /test
-expect read failed: Permission denied
-read /test
-expect write failed: Permission denied
-write /test contents4
-
-# Tools can always access things.
-setid 0
-expect 1 NONE
-getperm /test
-expect contents4
-read /test
-write /test contents5
diff -r 0528bc25c404 -r eb71f258e855 
tools/xenstore/testsuite/06dirpermissions.test
--- a/tools/xenstore/testsuite/06dirpermissions.test    Tue Jul 03 15:49:16 
2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-# Root directory: owned by tool, everyone has read access.
-expect 0 READ
-getperm /
-
-# Create directory: inherits from root.
-mkdir /dir
-expect 0 READ
-getperm /dir
-setid 1
-expect 0 READ
-getperm /dir
-dir /dir
-expect write failed: Permission denied
-write /dir/test contents2
-
-# Remove everyone's read access to directoy.
-setid 0
-setperm /dir 0 NONE
-setid 1
-expect dir failed: Permission denied
-dir /dir
-expect read failed: Permission denied
-read /dir/test create contents2
-expect write failed: Permission denied
-write /dir/test contents2
-
-# Grant everyone write access to directory.
-setid 0
-setperm /dir 0 WRITE
-setid 1
-expect getperm failed: Permission denied
-getperm /dir
-expect dir failed: Permission denied
-dir /dir
-write /dir/test contents
-setid 0
-expect 1 WRITE
-getperm /dir/test
-setperm /dir/test 0 NONE
-expect contents
-read /dir/test
-
-# Grant everyone both read and write access.
-setperm /dir 0 READ/WRITE
-setid 1
-expect 0 READ/WRITE
-getperm /dir
-expect test
-dir /dir
-write /dir/test2 contents
-expect contents
-read /dir/test2
-setperm /dir/test2 1 NONE
-
-# Change so that user 1 owns it, noone else can do anything.
-setid 0
-setperm /dir 1 NONE
-expect 1 NONE
-getperm /dir
-expect test
-expect test2
-dir /dir
-write /dir/test3 contents
-
-# User 2 can do nothing.  Can't even tell if file exists.
-setid 2
-expect setperm failed: Permission denied
-setperm /dir 2 NONE
-expect getperm failed: Permission denied
-getperm /dir
-expect dir failed: Permission denied
-dir /dir
-expect read failed: Permission denied
-read /dir/test
-expect read failed: Permission denied
-read /dir/test2
-expect read failed: Permission denied
-read /dir/test3
-expect read failed: Permission denied
-read /dir/test4
-expect write failed: Permission denied
-write /dir/test contents
-expect write failed: Permission denied
-write /dir/test4 contents
-
-# Tools can always access things.
-setid 0
-expect 1 NONE
-getperm /dir
-expect test
-expect test2
-expect test3
-dir /dir
-write /dir/test4 contents
-
-# Inherited by child.
-mkdir /dir/subdir
-expect 1 NONE
-getperm /dir/subdir
-write /dir/subfile contents
-expect 1 NONE
-getperm /dir/subfile
-
-# But for domains, they own it.
-setperm /dir/subdir 2 READ/WRITE
-expect 2 READ/WRITE
-getperm /dir/subdir
-setid 3
-write /dir/subdir/subfile contents
-expect 3 READ/WRITE
-getperm /dir/subdir/subfile
-
-# Inheritence works through multiple directories, too.
-write /dir/subdir/1/2/3/4 contents
-expect 3 READ/WRITE
-getperm /dir/subdir/1/2/3/4
-mkdir /dir/subdir/a/b/c/d
-expect 3 READ/WRITE
-getperm /dir/subdir/a/b/c/d
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/testsuite/07watch.test
--- a/tools/xenstore/testsuite/07watch.test     Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-# Watch something, write to it, check watch has fired.
-write /test contents
-
-1 watch /test token
-2 write /test contents2
-expect 1:/test:token
-1 waitwatch
-1 close
-
-# Check that reads don't set it off.
-1 watch /test token
-expect 2:contents2
-2 read /test
-expect 1: waitwatch failed: Connection timed out
-1 waitwatch
-1 close
-
-# mkdir, setperm and rm should (also tests watching dirs)
-mkdir /dir
-1 watch /dir token
-2 mkdir /dir/newdir
-expect 1:/dir/newdir:token
-1 waitwatch
-2 setperm /dir/newdir 0 READ
-expect 1:/dir/newdir:token
-1 waitwatch
-2 rm /dir/newdir
-expect 1:/dir/newdir:token
-1 waitwatch
-1 close
-2 close
-
-# Changed in b594bb976a743d509f1ffabb5bc698874ab90d8f
-## We don't get a watch from our own commands.
-#watch /dir token
-#mkdir /dir/newdir
-#expect waitwatch failed: Connection timed out
-#waitwatch
-#close
-
-# ignore watches while doing commands, should work.
-watch /dir token
-1 write /dir/test contents
-expect contents
-read /dir/test
-expect /dir/test:token
-waitwatch
-close
-
-# watch priority test: all simultaneous
-1 watch /dir token1
-3 watch /dir token3
-2 watch /dir token2
-write /dir/test contents
-expect 3:/dir/test:token3
-3 waitwatch
-expect 2:/dir/test:token2
-2 waitwatch
-expect 1:/dir/test:token1
-1 waitwatch
-1 close
-2 close
-3 close
-
-# If one dies (without acking), the other should still get ack.
-1 watch /dir token1
-2 watch /dir token2
-write /dir/test contents
-expect 2:/dir/test:token2
-2 waitwatch
-2 close
-expect 1:/dir/test:token1
-1 waitwatch
-1 close
-
-# If one dies (without reading at all), the other should still get ack.
-1 watch /dir token1
-2 watch /dir token2
-write /dir/test contents
-2 close
-expect 1:/dir/test:token1
-1 waitwatch
-1 close
-2 close
-
-# unwatch
-1 watch /dir token1
-1 unwatch /dir token1
-1 watch /dir token2
-2 write /dir/test2 contents
-expect 1:/dir/test2:token2
-1 waitwatch
-1 unwatch /dir token2
-1 close
-2 close
-
-# unwatch while watch pending.  Other watcher still gets the event.
-1 watch /dir token1
-2 watch /dir token2
-write /dir/test contents
-2 unwatch /dir token2
-expect 1:/dir/test:token1
-1 waitwatch
-1 close
-2 close
-
-# unwatch while watch pending.  Should clear this so we get next event.
-1 watch /dir token1
-write /dir/test contents
-1 unwatch /dir token1
-1 watch /dir/test token2
-write /dir/test contents2
-expect 1:/dir/test:token2
-1 waitwatch
-
-# check we only get notified once.
-1 watch /test token
-2 write /test contents2
-expect 1:/test:token
-1 waitwatch
-expect 1: waitwatch failed: Connection timed out
-1 waitwatch
-1 close
-
-# watches are queued in order.
-1 watch / token
-2 write /test1 contents
-2 write /test2 contents
-2 write /test3 contents
-expect 1:/test1:token
-1 waitwatch
-expect 1:/test2:token
-1 waitwatch
-expect 1:/test3:token
-1 waitwatch
-1 close
-
-# Creation of subpaths should be covered correctly.
-1 watch / token
-2 write /test/subnode contents2
-2 write /test/subnode/subnode contents2
-expect 1:/test/subnode:token
-1 waitwatch
-expect 1:/test/subnode/subnode:token
-1 waitwatch
-expect 1: waitwatch failed: Connection timed out
-1 waitwatch
-1 close
-
-# Watch event must have happened before we registered interest.
-1 watch / token
-2 write /test/subnode contents2
-1 watchnoack / token2 0
-expect 1:/test/subnode:token
-1 waitwatch
-expect 1:/:token2
-1 waitwatch
-expect 1: waitwatch failed: Connection timed out
-1 waitwatch
-1 close
-
-# Rm fires notification on child.
-1 watch /test/subnode token
-2 rm /test
-expect 1:/test/subnode:token
-1 waitwatch
-
-# Watch should not double-send after we ack, even if we did something in 
between.
-1 watch /test2 token
-2 write /test2/foo contents2
-expect 1:/test2/foo:token
-1 waitwatch
-expect 1:contents2
-1 read /test2/foo
-expect 1: waitwatch failed: Connection timed out
-1 waitwatch
diff -r 0528bc25c404 -r eb71f258e855 
tools/xenstore/testsuite/08transaction.slowtest
--- a/tools/xenstore/testsuite/08transaction.slowtest   Tue Jul 03 15:49:16 
2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-# Test transaction clashes.
-
-mkdir /test
-write /test/entry1 contents
-
-# Start transaction, do read-only op, transaction succeeds
-1 start
-1 write /test/entry1 contents2
-expect contents
-read /test/entry1
-1 commit
-expect contents2
-read /test/entry1
-
-# Start transaction, abort other transaction, transaction succeeds.
-1 start
-1 write /test/entry1 contents3
-start
-write /test/entry1 contents
-abort
-1 commit
-expect contents3
-read /test/entry1
-
-# Start transaction, do write op, transaction fails
-1 start
-1 write /test/entry1 contents4
-write /test/entry1 contents
-expect 1: commit failed: Resource temporarily unavailable
-1 commit
-expect contents
-read /test/entry1
-
-# Start transaction, do other transaction, transaction fails
-1 start
-1 write /test/entry1 contents4
-start
-write /test/entry1 contents5
-commit
-expect 1: commit failed: Resource temporarily unavailable
-1 commit
-expect contents5
-read /test/entry1
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/testsuite/08transaction.test
--- a/tools/xenstore/testsuite/08transaction.test       Tue Jul 03 15:49:16 
2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-# Test transactions.
-
-mkdir /test
-
-# Simple transaction: create a file inside transaction.
-1 start
-1 write /test/entry1 contents
-2 dir /test
-expect 1:entry1
-1 dir /test
-1 commit
-expect 2:contents
-2 read /test/entry1
-
-rm /test/entry1
-
-# Create a file and abort transaction.
-1 start
-1 write /test/entry1 contents
-2 dir /test
-expect 1:entry1
-1 dir /test
-1 abort
-2 dir /test
-
-write /test/entry1 contents
-# Delete in transaction, commit
-1 start
-1 rm /test/entry1
-expect 2:entry1
-2 dir /test
-1 dir /test
-1 commit
-2 dir /test
-
-# Delete in transaction, abort.
-write /test/entry1 contents
-1 start
-1 rm /test/entry1
-expect 2:entry1
-2 dir /test
-1 dir /test
-1 abort
-expect 2:entry1
-2 dir /test
-
-# Events inside transactions don't trigger watches until (successful) commit.
-mkdir /test/dir
-1 watch /test token
-2 start
-2 mkdir /test/dir/sub
-expect 1: waitwatch failed: Connection timed out
-1 waitwatch
-2 close
-1 close
-
-1 watch /test token
-2 start
-2 mkdir /test/dir/sub
-2 abort
-expect 1: waitwatch failed: Connection timed out
-1 waitwatch
-1 close
-
-1 watch /test token
-2 start
-2 mkdir /test/dir/sub
-2 commit
-expect 1:/test/dir/sub:token
-1 waitwatch
-1 close
-
-# Rm inside transaction works like rm outside: children get notified.
-1 watch /test/dir/sub token
-2 start
-2 rm /test/dir
-2 commit
-expect 1:/test/dir/sub:token
-1 waitwatch
-1 close
-
-# Multiple events from single transaction don't trigger assert
-1 watch /test token
-2 start
-2 write /test/1 contents
-2 write /test/2 contents
-2 commit
-expect 1:/test/1:token
-1 waitwatch
-expect 1:/test/2:token
-1 waitwatch
-1 close
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/testsuite/09domain.test
--- a/tools/xenstore/testsuite/09domain.test    Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-# Test domain communication.
-
-# Create a domain, write an entry.
-expect handle is 1
-introduce 1 100 7 /my/home
-1 write /entry1 contents
-expect entry1
-expect tool
-dir /
-close
-
-# Release that domain.
-release 1
-close
-
-# Introduce and release by same connection.
-expect handle is 2
-introduce 1 100 7 /my/home
-release 1
diff -r 0528bc25c404 -r eb71f258e855 
tools/xenstore/testsuite/10domain-homedir.test
--- a/tools/xenstore/testsuite/10domain-homedir.test    Tue Jul 03 15:49:16 
2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-# Test domain "implicit" paths.
-
-# Create a domain, write an entry using implicit path, read using implicit
-mkdir /home
-expect handle is 1
-introduce 1 100 7 /home
-1 write entry1 contents
-expect contents
-read /home/entry1
-expect entry1
-dir /home
-
-# Place a watch using a relative path: expect relative answer.
-1 mkdir foo
-1 watch foo token
-write /home/foo/bar contents
-expect 1:foo/bar:token
-1 waitwatch
diff -r 0528bc25c404 -r eb71f258e855 
tools/xenstore/testsuite/11domain-watch.test
--- a/tools/xenstore/testsuite/11domain-watch.test      Tue Jul 03 15:49:16 
2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-# Test watching from a domain.
-
-# Watch something, write to it, check watch has fired.
-write /test contents
-mkdir /dir
-
-expect handle is 1
-introduce 1 100 7 /my/home
-1 watch /test token
-write /test contents2
-expect 1:/test:token
-1 waitwatch
-1 unwatch /test token
-release 1
-1 close
-
-# ignore watches while doing commands, should work.
-expect handle is 1
-introduce 1 100 7 /my/home
-1 watch /dir token
-write /dir/test contents
-1 write /dir/test2 contents2
-1 write /dir/test3 contents3
-1 write /dir/test4 contents4
-expect 1:/dir/test:token
-1 waitwatch
-release 1
-1 close
-
-# unwatch
-expect handle is 1
-introduce 1 100 7 /my/home
-1 watch /dir token1
-1 unwatch /dir token1
-1 watch /dir token2
-write /dir/test2 contents
-expect 1:/dir/test2:token2
-1 waitwatch
-1 unwatch /dir token2
-release 1
-1 close
-
-# unwatch while watch pending.
-expect handle is 1
-introduce 1 100 7 /my/home
-1 watch /dir token1
-write /dir/test2 contents
-1 unwatch /dir token1
-release 1
-1 close
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/testsuite/12readonly.test
--- a/tools/xenstore/testsuite/12readonly.test  Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-# Test that read only connection can't alter store.
-
-write /test contents
-
-readonly
-expect test
-expect tool
-dir /
-
-expect contents
-read /test
-expect 0 READ
-getperm /test
-watch /test token
-unwatch /test token 
-start
-commit
-start
-abort
-
-# These don't work
-expect write failed: Permission denied
-write /test2 contents
-expect write failed: Permission denied
-write /test contents
-expect setperm failed: Permission denied
-setperm /test 100 NONE
-expect setperm failed: Permission denied
-setperm /test 100 NONE
-expect introduce failed: Permission denied
-introduce 1 100 7 /home
-
-# Check that watches work like normal.
-watch / token
-1 readwrite
-1 write /test contents
-expect /test:token
-waitwatch
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/testsuite/13watch-ack.test
--- a/tools/xenstore/testsuite/13watch-ack.test Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# This demonstrates a bug where an xs_acknowledge_watch returns
-# EINVAL, because the daemon doesn't track what watch event it sent
-# and relies on it being the "first" watch which has an event.
-# Watches firing after the first event is sent out will change this.
-
-# Create three things to watch.
-mkdir /test
-mkdir /test/1
-mkdir /test/2
-mkdir /test/3
-
-# Watch all three, fire event on 2, read watch, fire event on 1 and 3, ack 2.
-1 watch /test/1 token1
-1 watch /test/2 token2
-1 watch /test/3 token3
-2 write /test/2 contents2
-expect 1:/test/2:token2
-1 waitwatch
-3 write /test/1 contents1
-4 write /test/3 contents3
-1 close
diff -r 0528bc25c404 -r eb71f258e855 
tools/xenstore/testsuite/14complexperms.test
--- a/tools/xenstore/testsuite/14complexperms.test      Tue Jul 03 15:49:16 
2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-# We should not be able to tell the difference between a node which
-# doesn't exist, and a node we don't have permission on, if we don't
-# have permission on it directory.
-
-mkdir /dir
-setperm /dir 0 NONE
-
-# First when it doesn't exist
-setid 1
-expect *Permission denied
-dir /dir/file
-expect *Permission denied
-read /dir/file 
-expect *Permission denied
-write /dir/file value 
-expect *Permission denied
-mkdir /dir/file 
-expect *Permission denied
-rm /dir/file 
-expect *Permission denied
-rm /dir 
-expect *Permission denied
-getperm /dir/file 
-expect *Permission denied
-setperm /dir/file 0 NONE 
-# We get no watch event when there's no permission.  It's a corner case.
-watchnoack /dir/file token 
-1 write /dir/file contents
-1 rm /dir/file
-expect waitwatch failed: Connection timed out
-waitwatch
-unwatch /dir/file token 
-expect *No such file or directory
-unwatch /dir/file token 
-expect *Permission denied
-introduce 2 100 7 /dir/file
-
-# Now it exists
-setid 0
-write /dir/file contents
-
-setid 1
-expect *Permission denied
-dir /dir/file
-expect *Permission denied
-read /dir/file 
-expect *Permission denied
-write /dir/file value 
-expect *Permission denied
-mkdir /dir/file 
-expect *Permission denied
-rm /dir/file 
-expect *Permission denied
-rm /dir 
-expect *Permission denied
-getperm /dir/file 
-expect *Permission denied
-setperm /dir/file 0 NONE 
-watchnoack /dir/file token 
-1 write /dir/file contents
-1 rm /dir/file
-expect waitwatch failed: Connection timed out
-waitwatch
-unwatch /dir/file token 
-expect *No such file or directory
-unwatch /dir/file token 
-expect *Permission denied
-introduce 2 100 7 /dir/file
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/testsuite/test.sh
--- a/tools/xenstore/testsuite/test.sh  Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-#! /bin/sh
-
-set -e
-set -m
-
-run_test()
-{
-    rm -rf $XENSTORED_ROOTDIR
-    mkdir $XENSTORED_ROOTDIR
-    if [ $VALGRIND -eq 1 ]; then
-       valgrind --suppressions=testsuite/vg-suppressions -q ./xenstored_test 
--output-pid --trace-file=testsuite/tmp/trace --no-fork > /tmp/pid 2> 
testsuite/tmp/xenstored_errors &
-       while [ ! -s /tmp/pid ]; do sleep 0; done
-       PID=`cat /tmp/pid`
-       rm /tmp/pid
-    else
-       # We don't get error messages from this, though. 
-       PID=`./xenstored_test --output-pid --trace-file=testsuite/tmp/trace`
-    fi
-    if ./xs_test $2 $1; then
-       if [ -s testsuite/tmp/xenstored_errors ]; then
-           kill $PID
-           echo Errors:
-           cat testsuite/tmp/xenstored_errors
-           return 1
-       fi
-       kill $PID
-       sleep 1
-       return 0
-    else
-       # In case daemon is wedged.
-       kill $PID
-       sleep 1
-       return 1
-    fi
-}
-
-if [ x$1 = x--fast ]; then
-    VALGRIND=0
-    SLOWTESTS=""
-    shift
-else
-    if type valgrind >/dev/null 2>&1; then
-       VALGRIND=1
-    else
-       echo "WARNING: valgrind not available" >&2
-       VALGRIND=0
-    fi
-    SLOWTESTS=testsuite/[0-9]*.slowtest
-fi
-
-MATCH=${1:-"*"}
-for f in testsuite/[0-9]*.test $SLOWTESTS; do
-    case `basename $f` in $MATCH) RUN=1;; esac
-    [ -n "$RUN" ] || continue
-
-    if run_test $f -x >/tmp/out; then
-       echo -n .
-    else
-       cat /tmp/out
-       # That will have filled the screen, repeat message.
-       echo Test $f failed
-       exit 1
-    fi
-done
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/testsuite/vg-suppressions
--- a/tools/xenstore/testsuite/vg-suppressions  Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-{
-   Glibc goes boom from _start (Debian glibc 2.3.5-3)
-   Memcheck:Cond
-   obj:/lib/ld-2.3.5.so
-   obj:/lib/ld-2.3.5.so
-   obj:/lib/ld-2.3.5.so
-   obj:/lib/ld-2.3.5.so
-   obj:/lib/ld-2.3.5.so
-}
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/xenstored_core.c
--- a/tools/xenstore/xenstored_core.c   Tue Jul 03 15:49:16 2007 +0100
+++ b/tools/xenstore/xenstored_core.c   Tue Jul 03 15:51:59 2007 +0100
@@ -39,7 +39,6 @@
 #include <assert.h>
 #include <setjmp.h>
 
-//#define DEBUG
 #include "utils.h"
 #include "list.h"
 #include "talloc.h"
@@ -53,7 +52,6 @@
 
 #include "hashtable.h"
 
-
 extern int xce_handle; /* in xenstored_domain.c */
 
 static bool verbose = false;
@@ -81,50 +79,6 @@ int quota_nb_watch_per_domain = 128;
 int quota_nb_watch_per_domain = 128;
 int quota_max_entry_size = 2048; /* 2K */
 int quota_max_transaction = 10;
-
-#ifdef TESTING
-static bool failtest = false;
-
-/* We override talloc's malloc. */
-void *test_malloc(size_t size)
-{
-       /* 1 in 20 means only about 50% of connections establish. */
-       if (failtest && (random() % 32) == 0)
-               return NULL;
-       return malloc(size);
-}
-
-static void stop_failtest(int signum __attribute__((unused)))
-{
-       failtest = false;
-}
-
-/* Need these before we #define away write_all/mkdir in testing.h */
-bool test_write_all(int fd, void *contents, unsigned int len);
-bool test_write_all(int fd, void *contents, unsigned int len)
-{
-       if (failtest && (random() % 8) == 0) {
-               if (len)
-                       len = random() % len;
-               write(fd, contents, len);
-               errno = ENOSPC;
-               return false;
-       }
-       return xs_write_all(fd, contents, len);
-}
-
-int test_mkdir(const char *dir, int perms);
-int test_mkdir(const char *dir, int perms)
-{
-       if (failtest && (random() % 8) == 0) {
-               errno = ENOSPC;
-               return -1;
-       }
-       return mkdir(dir, perms);
-}
-#endif /* TESTING */
-
-#include "xenstored_test.h"
 
 TDB_CONTEXT *tdb_context(struct connection *conn)
 {
@@ -1163,12 +1117,10 @@ static void do_debug(struct connection *
 {
        int num;
 
-#ifndef TESTING
        if (conn->id != 0) {
                send_error(conn, EACCES);
                return;
        }
-#endif
 
        num = xs_count_strings(in->buffer, in->used);
 
@@ -1179,18 +1131,10 @@ static void do_debug(struct connection *
                }
                xprintf("debug: %s", in->buffer + get_string(in, 0));
        }
+
        if (streq(in->buffer, "check"))
                check_store();
-#ifdef TESTING
-       /* For testing, we allow them to set id. */
-       if (streq(in->buffer, "setid")) {
-               conn->id = atoi(in->buffer + get_string(in, 0));
-       } else if (streq(in->buffer, "failtest")) {
-               if (get_string(in, 0) < in->used)
-                       srandom(atoi(in->buffer + get_string(in, 0)));
-               failtest = true;
-       }
-#endif /* TESTING */
+
        send_ack(conn, XS_DEBUG);
 }
 
@@ -1319,10 +1263,8 @@ static void handle_input(struct connecti
                        return;
 
                if (in->hdr.msg.len > PATH_MAX) {
-#ifndef TESTING
                        syslog(LOG_ERR, "Client tried to feed us %i",
                               in->hdr.msg.len);
-#endif
                        goto bad_client;
                }
 
@@ -1414,39 +1356,7 @@ static void accept_connection(int sock, 
                close(fd);
 }
 
-#ifdef TESTING
-/* Valgrind can check our writes better if we don't use mmap */
-#define TDB_FLAGS TDB_NOMMAP
-/* Useful for running under debugger. */
-void dump_connection(void)
-{
-       struct connection *i;
-
-       list_for_each_entry(i, &connections, list) {
-               printf("Connection %p:\n", i);
-               printf("    state = %s\n",
-                      list_empty(&i->out_list) ? "OK" : "BUSY");
-               if (i->id)
-                       printf("    id = %i\n", i->id);
-               if (!i->in->inhdr || i->in->used)
-                       printf("    got %i bytes of %s\n",
-                              i->in->used, i->in->inhdr ? "header" : "data");
-#if 0
-               if (i->out)
-                       printf("    sending message %s (%s) out\n",
-                              sockmsg_string(i->out->hdr.msg.type),
-                              i->out->buffer);
-               if (i->transaction)
-                       dump_transaction(i);
-               if (i->domain)
-                       dump_domain(i);
-#endif
-               dump_watches(i);
-       }
-}
-#else
 #define TDB_FLAGS 0
-#endif
 
 /* We create initial nodes manually. */
 static void manual_node(const char *name, const char *child)
@@ -1693,10 +1603,6 @@ static void corrupt(struct connection *c
        log("corruption detected by connection %i: err %s: %s",
            conn ? (int)conn->id : -1, strerror(saved_errno), str);
 
-#ifdef TESTING
-       /* Allow them to attach debugger. */
-       sleep(30);
-#endif
        check_store();
 }
 
@@ -1740,11 +1646,10 @@ static void daemonize(void)
        if (pid != 0)
                exit(0);
 
-#ifndef TESTING        /* Relative paths for socket names */
        /* Move off any mount points we might be in. */
        if (chdir("/") == -1)
                barf_perror("Failed to chdir");
-#endif
+
        /* Discard our parent's old-fashioned umask prejudices. */
        umask(0);
 }
@@ -1941,10 +1846,6 @@ int main(int argc, char *argv[])
 
        signal(SIGHUP, trigger_reopen_log);
 
-#ifdef TESTING
-       signal(SIGUSR1, stop_failtest);
-#endif
-
        if (xce_handle != -1)
                evtchn_fd = xc_evtchn_fd(xce_handle);
 
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/xenstored_domain.c
--- a/tools/xenstore/xenstored_domain.c Tue Jul 03 15:49:16 2007 +0100
+++ b/tools/xenstore/xenstored_domain.c Tue Jul 03 15:51:59 2007 +0100
@@ -23,14 +23,12 @@
 #include <stdlib.h>
 #include <stdarg.h>
 
-//#define DEBUG
 #include "utils.h"
 #include "talloc.h"
 #include "xenstored_core.h"
 #include "xenstored_domain.h"
 #include "xenstored_transaction.h"
 #include "xenstored_watch.h"
-#include "xenstored_test.h"
 
 #include <xenctrl.h>
 
@@ -217,10 +215,8 @@ void handle_event(void)
        if (port == virq_port)
                domain_cleanup();
 
-#ifndef TESTING
        if (xc_evtchn_unmask(xce_handle, port) == -1)
                barf_perror("Failed to write to event fd");
-#endif
 }
 
 bool domain_can_read(struct connection *conn)
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/xenstored_test.h
--- a/tools/xenstore/xenstored_test.h   Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/* 
-    Testing replcements for Xen Store Daemon.
-    Copyright (C) 2005 Rusty Russell IBM Corporation
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    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 General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-#ifndef _XENSTORED_TEST_H
-#define _XENSTORED_TEST_H
-
-#ifdef TESTING
-bool test_write_all(int fd, void *contents, unsigned int len);
-#define xs_write_all test_write_all
-
-int test_mkdir(const char *dir, int perms);
-#define mkdir test_mkdir
-
-int fake_open_eventchn(void);
-void fake_block_events(void);
-void fake_ack_event(void);
-
-#define ioctl(a,b,c) 0
-
-#endif
-
-#endif /* _XENSTORED_INTERNAL_H */
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/xenstored_transaction.c
--- a/tools/xenstore/xenstored_transaction.c    Tue Jul 03 15:49:16 2007 +0100
+++ b/tools/xenstore/xenstored_transaction.c    Tue Jul 03 15:51:59 2007 +0100
@@ -35,7 +35,6 @@
 #include "xenstored_domain.h"
 #include "xs_lib.h"
 #include "utils.h"
-#include "xenstored_test.h"
 
 struct changed_node
 {
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/xenstored_watch.c
--- a/tools/xenstore/xenstored_watch.c  Tue Jul 03 15:49:16 2007 +0100
+++ b/tools/xenstore/xenstored_watch.c  Tue Jul 03 15:51:59 2007 +0100
@@ -29,7 +29,6 @@
 #include "xenstored_watch.h"
 #include "xs_lib.h"
 #include "utils.h"
-#include "xenstored_test.h"
 #include "xenstored_domain.h"
 
 extern int quota_nb_watch_per_domain;
@@ -195,17 +194,6 @@ void conn_delete_all_watches(struct conn
                domain_watch_dec(conn);
        }
 }
-
-#ifdef TESTING
-void dump_watches(struct connection *conn)
-{
-       struct watch *watch;
-
-       list_for_each_entry(watch, &conn->watches, list)
-               printf("    watch on %s token %s\n",
-                      watch->node, watch->token);
-}
-#endif
 
 /*
  * Local variables:
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/xs_crashme.c
--- a/tools/xenstore/xs_crashme.c       Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,393 +0,0 @@
-/* Code which randomly corrupts bits going to the daemon.
-    Copyright (C) 2005 Rusty Russell IBM Corporation
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    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 General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-#include <stdbool.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <stdarg.h>
-#include <string.h>
-#include <sys/time.h>
-#include "xs.h"
-#include "talloc.h"
-#include <errno.h>
-
-#define XSTEST
-#define RAND_FREQ 128          /* One char in 32 is corrupted. */
-
-/* jhash.h: Jenkins hash support.
- *
- * Copyright (C) 1996 Bob Jenkins (bob_jenkins@xxxxxxxxxxxxxxxx)
- *
- * http://burtleburtle.net/bob/hash/
- *
- * These are the credits from Bob's sources:
- *
- * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
- * hash(), hash2(), hash3, and mix() are externally useful functions.
- * Routines to test the hash are included if SELF_TEST is defined.
- * You can use this free for any purpose.  It has no warranty.
- *
- * Copyright (C) 2003 David S. Miller (davem@xxxxxxxxxx)
- *
- * I've modified Bob's hash to be useful in the Linux kernel, and
- * any bugs present are surely my fault.  -DaveM
- */
-
-/* NOTE: Arguments are modified. */
-#define __jhash_mix(a, b, c) \
-{ \
-  a -= b; a -= c; a ^= (c>>13); \
-  b -= c; b -= a; b ^= (a<<8); \
-  c -= a; c -= b; c ^= (b>>13); \
-  a -= b; a -= c; a ^= (c>>12);  \
-  b -= c; b -= a; b ^= (a<<16); \
-  c -= a; c -= b; c ^= (b>>5); \
-  a -= b; a -= c; a ^= (c>>3);  \
-  b -= c; b -= a; b ^= (a<<10); \
-  c -= a; c -= b; c ^= (b>>15); \
-}
-
-/* The golden ration: an arbitrary value */
-#define JHASH_GOLDEN_RATIO     0x9e3779b9
-
-/* The most generic version, hashes an arbitrary sequence
- * of bytes.  No alignment or length assumptions are made about
- * the input key.
- */
-static inline uint32_t jhash(const void *key, uint32_t length, uint32_t 
initval)
-{
-       uint32_t a, b, c, len;
-       const uint8_t *k = key;
-
-       len = length;
-       a = b = JHASH_GOLDEN_RATIO;
-       c = initval;
-
-       while (len >= 12) {
-               a += (k[0] +((uint32_t)k[1]<<8) +((uint32_t)k[2]<<16) 
+((uint32_t)k[3]<<24));
-               b += (k[4] +((uint32_t)k[5]<<8) +((uint32_t)k[6]<<16) 
+((uint32_t)k[7]<<24));
-               c += (k[8] +((uint32_t)k[9]<<8) 
+((uint32_t)k[10]<<16)+((uint32_t)k[11]<<24));
-
-               __jhash_mix(a,b,c);
-
-               k += 12;
-               len -= 12;
-       }
-
-       c += length;
-       switch (len) {
-       case 11: c += ((uint32_t)k[10]<<24);
-       case 10: c += ((uint32_t)k[9]<<16);
-       case 9 : c += ((uint32_t)k[8]<<8);
-       case 8 : b += ((uint32_t)k[7]<<24);
-       case 7 : b += ((uint32_t)k[6]<<16);
-       case 6 : b += ((uint32_t)k[5]<<8);
-       case 5 : b += k[4];
-       case 4 : a += ((uint32_t)k[3]<<24);
-       case 3 : a += ((uint32_t)k[2]<<16);
-       case 2 : a += ((uint32_t)k[1]<<8);
-       case 1 : a += k[0];
-       };
-
-       __jhash_mix(a,b,c);
-
-       return c;
-}
-
-/* A special optimized version that handles 1 or more of uint32_ts.
- * The length parameter here is the number of uint32_ts in the key.
- */
-static inline uint32_t jhash2(uint32_t *k, uint32_t length, uint32_t initval)
-{
-       uint32_t a, b, c, len;
-
-       a = b = JHASH_GOLDEN_RATIO;
-       c = initval;
-       len = length;
-
-       while (len >= 3) {
-               a += k[0];
-               b += k[1];
-               c += k[2];
-               __jhash_mix(a, b, c);
-               k += 3; len -= 3;
-       }
-
-       c += length * 4;
-
-       switch (len) {
-       case 2 : b += k[1];
-       case 1 : a += k[0];
-       };
-
-       __jhash_mix(a,b,c);
-
-       return c;
-}
-
-
-/* A special ultra-optimized versions that knows they are hashing exactly
- * 3, 2 or 1 word(s).
- *
- * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
- *       done at the end is not done here.
- */
-static inline uint32_t jhash_3words(uint32_t a, uint32_t b, uint32_t c, 
uint32_t initval)
-{
-       a += JHASH_GOLDEN_RATIO;
-       b += JHASH_GOLDEN_RATIO;
-       c += initval;
-
-       __jhash_mix(a, b, c);
-
-       return c;
-}
-
-static inline uint32_t jhash_2words(uint32_t a, uint32_t b, uint32_t initval)
-{
-       return jhash_3words(a, b, 0, initval);
-}
-
-static inline uint32_t jhash_1word(uint32_t a, uint32_t initval)
-{
-       return jhash_3words(a, 0, 0, initval);
-}
-
-static unsigned int get_randomness(int *state)
-{
-       return jhash_1word((*state)++, *state * 1103515243);
-}
-
-static int state;
-
-/* Lengthening headers is pointless: other end will just wait for more
- * data and timeout.  We merely shorten the length. */
-static void corrupt_header(char *output, const struct xsd_sockmsg *msg,
-                          unsigned int *next_bit)
-{
-       struct xsd_sockmsg newmsg = *msg;
-
-       while (*next_bit < sizeof(*msg)) {
-               if (newmsg.len)
-                       newmsg.len = get_randomness(&state) % newmsg.len;
-               *next_bit += get_randomness(&state) % RAND_FREQ;
-       }
-       memcpy(output, &newmsg, sizeof(newmsg));
-}
-
-#define read_all_choice read_all
-static bool write_all_choice(int fd, const void *data, unsigned int len)
-{
-       char corrupt_data[len];
-       bool ret;
-       static unsigned int next_bit;
-
-       if (len == sizeof(struct xsd_sockmsg)
-           && ((unsigned long)data % __alignof__(struct xsd_sockmsg)) == 0)
-               corrupt_header(corrupt_data, data, &next_bit);
-       else {
-               memcpy(corrupt_data, data, len);
-               while (next_bit < len * CHAR_BIT) {
-                       corrupt_data[next_bit/CHAR_BIT]
-                               ^= (1 << (next_bit%CHAR_BIT));
-                       next_bit += get_randomness(&state) % RAND_FREQ;
-               }
-       }
-
-       ret = xs_write_all(fd, corrupt_data, len);
-       next_bit -= len * CHAR_BIT;
-       return ret;
-}
-
-#include "xs.c"
-
-static char *random_path(void)
-{
-       unsigned int i;
-       char *ret = NULL;
-
-       if (get_randomness(&state) % 20 == 0)
-               return talloc_strdup(NULL, "/");
-
-       for (i = 0; i < 1 || (get_randomness(&state) % 2); i++) {
-               ret = talloc_asprintf_append(ret, "/%i", 
-                                            get_randomness(&state) % 15);
-       }
-       return ret;
-}
-
-/* Do the next operation, return the results. */
-static void do_next_op(struct xs_handle *h, bool verbose)
-{
-       char *name;
-       unsigned int num;
-
-       if (verbose)
-               printf("State %i: ", state);
-
-       name = random_path();
-       switch (get_randomness(&state) % 9) {
-       case 0:
-               if (verbose)
-                       printf("DIR %s\n", name);
-               free(xs_directory(h, name, &num));
-               break;
-       case 1:
-               if (verbose)
-                       printf("READ %s\n", name);
-               free(xs_read(h, name, &num));
-               break;
-       case 2: {
-               char *contents = talloc_asprintf(NULL, "%i",
-                                                get_randomness(&state));
-               unsigned int len = get_randomness(&state)%(strlen(contents)+1);
-               if (verbose)
-                       printf("WRITE %s %.*s\n", name, len, contents);
-               xs_write(h, name, contents, len);
-               break;
-       }
-       case 3:
-               if (verbose)
-                       printf("MKDIR %s\n", name);
-               xs_mkdir(h, name);
-               break;
-       case 4:
-               if (verbose)
-                       printf("RM %s\n", name);
-               xs_rm(h, name);
-               break;
-       case 5:
-               if (verbose)
-                       printf("GETPERMS %s\n", name);
-               free(xs_get_permissions(h, name, &num));
-               break;
-       case 6: {
-               unsigned int i, num = get_randomness(&state)%8;
-               struct xs_permissions perms[num];
-
-               if (verbose)
-                       printf("SETPERMS %s: ", name);
-               for (i = 0; i < num; i++) {
-                       perms[i].id = get_randomness(&state)%8;
-                       perms[i].perms = get_randomness(&state)%4;
-                       if (verbose)
-                               printf("%i%c ", perms[i].id,
-                                      perms[i].perms == XS_PERM_WRITE ? 'W'
-                                      : perms[i].perms == XS_PERM_READ ? 'R'
-                                      : perms[i].perms == 
-                                      (XS_PERM_READ|XS_PERM_WRITE) ? 'B'
-                                      : 'N');
-               }
-               if (verbose)
-                       printf("\n");
-               xs_set_permissions(h, name, perms, num);
-               break;
-       }
-       case 7: {
-               if (verbose)
-                       printf("START %s\n", name);
-               xs_transaction_start(h);
-               break;
-       }
-       case 8: {
-               bool abort = (get_randomness(&state) % 2);
-
-               if (verbose)
-                       printf("STOP %s\n", abort ? "ABORT" : "COMMIT");
-               xs_transaction_end(h, abort);
-               break;
-       }
-       default:
-               barf("Impossible randomness");
-       }
-}
-
-static struct xs_handle *h;
-static void alarmed(int sig __attribute__((unused)))
-{
-       /* We force close on timeout. */
-       close(h->fd);
-}
-
-static int start_daemon(void)
-{
-       int fds[2];
-       int daemon_pid;
-
-       /* Start daemon. */
-       pipe(fds);
-       if ((daemon_pid = fork())) {
-               /* Child writes PID when its ready: we wait for that. */
-               char buffer[20];
-               close(fds[1]);
-               if (read(fds[0], buffer, sizeof(buffer)) < 0)
-                       barf("Failed to summon daemon");
-               close(fds[0]);
-               return daemon_pid;
-       } else {
-               dup2(fds[1], STDOUT_FILENO);
-               close(fds[0]);
-#if 1
-               execlp("valgrind", "valgrind", 
"--log-file=/tmp/xs_crashme.vglog", "-q", "./xenstored_test", "--output-pid",
-                      "--no-fork", "--trace-file=/tmp/trace", NULL);
-#else
-               execlp("./xenstored_test", "xenstored_test", "--output-pid",
-                      "--no-fork", NULL);
-#endif
-               exit(1);
-       }
-}
-
-
-int main(int argc, char **argv)
-{
-       unsigned int i;
-       int pid;
-
-       if (argc != 3 && argc != 4)
-               barf("Usage: xs_crashme <iterations> <seed> [pid]");
-
-       if (argc == 3)
-               pid = start_daemon();
-       else
-               pid = atoi(argv[3]);
-
-       state = atoi(argv[2]);
-       h = xs_daemon_open();
-       if (!h)
-               barf_perror("Opening connection to daemon");
-       signal(SIGALRM, alarmed);
-       for (i = 0; i < (unsigned)atoi(argv[1]); i++) {
-               alarm(1);
-               do_next_op(h, false);
-               if (i % (atoi(argv[1]) / 72 ?: 1) == 0) {
-                       printf(".");
-                       fflush(stdout);
-               }
-               if (kill(pid, 0) != 0)
-                       barf_perror("Pinging daemon on iteration %i", i);
-               if (h->fd < 0) {
-                       xs_daemon_close(h);
-                       h = xs_daemon_open();
-                       if (!h)
-                               barf_perror("Connecting on iteration %i", i);
-               }
-       }
-       kill(pid, SIGTERM);
-       return 0;
-}
-
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/xs_random.c
--- a/tools/xenstore/xs_random.c        Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,1590 +0,0 @@
-/* Random tests.
-
-   We check that the results from a real filesystem are the same.
-*/
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <dirent.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include "xs.h"
-#include "talloc.h"
-#include "utils.h"
-
-struct ops
-{
-       char *name;
-
-       char **(*dir)(void *h, const char *path, unsigned int *num);
-
-       void *(*read)(void *h, const char *path, unsigned int *len);
-
-       bool (*write)(void *h, const char *path, const void *data,
-                     unsigned int len);
-
-       bool (*mkdir)(void *h, const char *path);
-
-       bool (*rm)(void *h, const char *path);
-
-       struct xs_permissions *(*get_perms)(void *h,
-                                           const char *path,
-                                           unsigned int *num);
-
-       bool (*set_perms)(void *h,
-                         const char *path,
-                         struct xs_permissions *perms,
-                         unsigned int num);
-
-       bool (*transaction_start)(void *h);
-       bool (*transaction_end)(void *h, bool abort);
-
-       /* Create and destroy a new handle. */
-       void *(*handle)(const char *path);
-       void (*close)(void *);
-};
-
-struct file_ops_info
-{
-       const char *base;
-       char *transact_base;
-};
-
-static void convert_to_dir(const char *dirname)
-{
-       char *tmpname = talloc_asprintf(dirname, "%s.tmp", dirname);
-       if (rename(dirname, tmpname) != 0)
-               barf_perror("Failed to rename %s to %s", dirname, tmpname);
-       if (mkdir(dirname, 0700) != 0) 
-               barf_perror("Failed to mkdir %s", dirname);
-       if (rename(tmpname,talloc_asprintf(dirname, "%s/.DATA", dirname)) != 0)
-               barf_perror("Failed to rename into %s", dirname);
-       /* If perms exists, move it in. */
-       rename(talloc_asprintf(dirname, "%s.perms", dirname),
-              talloc_asprintf(dirname, "%s/.perms", dirname));
-}
-
-/* Files can be used as dirs, too.  Convert them when they are. */
-static void maybe_convert_to_directory(const char *filename)
-{
-       struct stat st;
-       char *dirname = talloc_asprintf(
-               filename, "%.*s",
-               (int)(strrchr(filename, '/') - filename), filename);
-       if (lstat(dirname, &st) == 0 && S_ISREG(st.st_mode))
-               convert_to_dir(dirname);
-}
-
-static char *get_name(struct file_ops_info *info, const char *path)
-{
-       if (info->transact_base)
-               return talloc_asprintf(path, "%s%s", info->transact_base,
-                                      path);
-       return talloc_asprintf(path, "%s%s", info->base, path);
-}
-
-static char *path_to_name(struct file_ops_info *info, const char *path)
-{
-       char *filename = get_name(info, path);
-       maybe_convert_to_directory(filename);
-       return filename;
-}
-
-static char **file_directory(struct file_ops_info *info,
-                            const char *path, unsigned int *num)
-{
-       char **ret;
-       DIR *dir;
-       struct dirent *dirent;
-       char *p, *dirname = path_to_name(info, path);
-       unsigned int i, len = 0;
-       struct stat st;
-
-       /* If it exists, but isn't a directory, we convert it. */
-       if (lstat(dirname, &st) == 0 && !S_ISDIR(st.st_mode))
-               convert_to_dir(dirname);
-
-       *num = 0;
-       dir = opendir(dirname);
-       if (!dir)
-               return NULL;;
-
-       /* Once to count them. */
-       while ((dirent = readdir(dir)) != NULL) {
-               if (strchr(dirent->d_name, '.'))
-                       continue;
-               len += strlen(dirent->d_name) + 1;
-               (*num)++;
-       }
-       rewinddir(dir);
-
-       /* Now allocate and fill in. */
-       ret = malloc(sizeof(char *) * *num + len);
-       p = (char *)&ret[*num];
-       i = 0;
-       while ((dirent = readdir(dir)) != NULL) {
-               if (strchr(dirent->d_name, '.'))
-                       continue;
-               ret[i] = p;
-               strcpy(p, dirent->d_name);
-               p += strlen(p) + 1;
-               i++;
-       }
-       closedir(dir);
-
-       return ret;
-}
-
-static char *filename_to_data(const char *filename)
-{
-       struct stat st;
-
-       if (lstat(filename, &st) == 0 && S_ISDIR(st.st_mode))
-               return talloc_asprintf(filename, "%s/.DATA", filename);
-       return (char *)filename;
-}
-
-static void *file_read(struct file_ops_info *info,
-                      const char *path, unsigned int *len)
-{
-       void *ret;
-       char *filename = filename_to_data(path_to_name(info, path));
-       unsigned long size;
-
-       ret = grab_file(filename, &size);
-       /* Directory exists, .DATA doesn't. */
-       if (!ret && errno == ENOENT && strends(filename, ".DATA")) {
-               ret = strdup("");
-               size = 0;
-       }
-       *len = size;
-       return ret;
-}
-
-static struct xs_permissions *file_get_perms(struct file_ops_info *info,
-                                            const char *path,
-                                            unsigned int *num)
-{
-       void *perms;
-       struct xs_permissions *ret;
-       char *filename = path_to_name(info, path);
-       char *permfile;
-       unsigned long size;
-       struct stat st;
-
-       if (lstat(filename, &st) != 0)
-               return NULL;
-
-       if (S_ISDIR(st.st_mode)) 
-               permfile = talloc_asprintf(path, "%s/.perms", filename);
-       else
-               permfile = talloc_asprintf(path, "%s.perms", filename);
-
-       perms = grab_file(permfile, &size);
-       if (!perms)
-               barf("Grabbing permissions for %s", permfile);
-       *num = xs_count_strings(perms, size);
-
-       ret = new_array(struct xs_permissions, *num);
-       if (!xs_strings_to_perms(ret, *num, perms))
-               barf("Reading permissions from %s", permfile);
-       release_file(perms, size);
-       return ret;
-}
-
-static void do_command(const char *cmd)
-{
-       int ret;
-
-       ret = system(cmd);
-       if (ret == -1 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
-               barf_perror("Failed '%s': %i", cmd, ret);
-}
-
-static void init_perms(const char *filename)
-{
-       struct stat st;
-       char *permfile, *command;
-
-       if (lstat(filename, &st) != 0)
-               barf_perror("Failed to stat %s", filename);
-
-       if (S_ISDIR(st.st_mode)) 
-               permfile = talloc_asprintf(filename, "%s/.perms", filename);
-       else
-               permfile = talloc_asprintf(filename, "%s.perms", filename);
-
-       /* Leave permfile if it already exists. */
-       if (lstat(permfile, &st) == 0)
-               return;
-
-       /* Copy permissions from parent */
-       command = talloc_asprintf(filename, "cp %.*s/.perms %s",
-                                 (int)(strrchr(filename, '/') - filename),
-                                 filename, permfile);
-       do_command(command);
-}      
-
-static bool file_set_perms(struct file_ops_info *info,
-                          const char *path,
-                          struct xs_permissions *perms,
-                          unsigned int num)
-{
-       unsigned int i;
-       char *filename = path_to_name(info, path);
-       char *permfile;
-       int fd;
-       struct stat st;
-
-       if (num < 1) {
-               errno = EINVAL;
-               return false;
-       }
-
-       /* Check non-perm file exists/ */
-       if (lstat(filename, &st) != 0)
-               return false;
-
-       if (S_ISDIR(st.st_mode)) 
-               permfile = talloc_asprintf(path, "%s/.perms", filename);
-       else
-               permfile = talloc_asprintf(path, "%s.perms", filename);
-
-       fd = open(permfile, O_WRONLY|O_CREAT|O_TRUNC, 0600);
-       if (fd < 0)
-               return false;
-
-       for (i = 0; i < num; i++) {
-               char buffer[100];
-
-               if (!xs_perm_to_string(&perms[i], buffer)) {
-                       int saved_errno = errno;
-                       close(fd);
-                       errno = saved_errno;
-                       return false;
-               }
-               if (write(fd, buffer, strlen(buffer) + 1)
-                   != (int)strlen(buffer) + 1)
-                       barf_perror("Failed to write perm");
-       }
-       close(fd);
-       return true;
-}
-
-static char *parent_filename(const char *name)
-{
-       char *slash = strrchr(name + 1, '/');
-       if (!slash)
-               return talloc_strdup(name, "/");
-       return talloc_asprintf(name, "%.*s", (int)(slash-name), name);
-}
-
-static void make_dirs(const char *filename)
-{
-       struct stat st;
-
-       if (lstat(filename, &st) == 0 && S_ISREG(st.st_mode))
-               convert_to_dir(filename);
-
-       if (mkdir(filename, 0700) == 0) {
-               init_perms(filename);
-               return;
-       }
-       if (errno == EEXIST)
-               return;
-
-       make_dirs(parent_filename(filename));
-       if (mkdir(filename, 0700) != 0)
-               barf_perror("Failed to mkdir %s", filename);
-       init_perms(filename);
-}
-
-static bool file_write(struct file_ops_info *info,
-                      const char *path, const void *data,
-                      unsigned int len)
-{
-       char *filename = filename_to_data(path_to_name(info, path));
-       int fd;
-
-       make_dirs(parent_filename(filename));
-       fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0600);
-       if (fd < 0)
-               return false;
-
-       if (write(fd, data, len) != (int)len)
-               barf_perror("Bad write to %s", filename);
-
-       init_perms(filename);
-       close(fd);
-       return true;
-}
-
-static bool file_mkdir(struct file_ops_info *info, const char *path)
-{
-       char *dirname = path_to_name(info, path);
-
-       make_dirs(parent_filename(dirname));
-       if (mkdir(dirname, 0700) != 0)
-               return (errno == EEXIST);
-
-       init_perms(dirname);
-       return true;
-}
-
-static bool file_rm(struct file_ops_info *info, const char *path)
-{
-       char *filename = path_to_name(info, path);
-       struct stat st;
-
-       if (lstat(filename, &st) != 0) {
-               if (lstat(parent_filename(filename), &st) != 0)
-                       return false;
-               return true;
-       }
-
-       if (streq(path, "/")) {
-               errno = EINVAL;
-               return false;
-       }
-
-       do_command(talloc_asprintf(path, "rm -f %s.perms; rm -r %s", 
-                                  filename, filename));
-       return true;
-}
-
-static bool file_transaction_start(struct file_ops_info *info)
-{
-       char *cmd;
-
-       if (info->transact_base) {
-               errno = EBUSY;
-               return false;
-       }
-
-       info->transact_base = talloc_asprintf(NULL, "%s.transact", info->base);
-       cmd = talloc_asprintf(NULL, "cp -r %s %s",
-                             info->base, info->transact_base);
-       do_command(cmd);
-       talloc_free(cmd);
-       return true;
-}
-
-static bool file_transaction_end(struct file_ops_info *info, bool abort)
-{
-       char *old, *cmd;
-
-       if (!info->transact_base) {
-               errno = ENOENT;
-               return false;
-       }
-
-       if (abort) {
-               cmd = talloc_asprintf(NULL, "rm -rf %s", info->transact_base);
-               do_command(cmd);
-               goto success;
-       }
-
-       old = talloc_asprintf(NULL, "rm -rf %s", info->base);
-       do_command(old);
-       talloc_free(old);
-
-       cmd = talloc_asprintf(NULL, "mv %s %s",
-                             info->transact_base, info->base);
-       do_command(cmd);
-
-success:
-       talloc_free(cmd);
-       talloc_free(info->transact_base);
-       info->transact_base = NULL;
-       return true;
-}
-
-static struct file_ops_info *file_handle(const char *dir)
-{
-       struct file_ops_info *info = talloc(NULL, struct file_ops_info);
-
-       info->base = dir;
-       info->transact_base = NULL;
-       return info;
-}
-
-static void file_close(struct file_ops_info *handle)
-{
-       talloc_free(handle);
-}
-
-static struct xs_handle *xs_handle(const char *dir __attribute__((unused)))
-{
-       struct xs_handle *h;
-
-       h = xs_daemon_open();
-       if (!h)
-               barf_perror("Connecting to xs daemon");
-       return h;
-}
-
-static void xs_close(struct xs_handle *handle)
-{
-       xs_daemon_close(handle);
-}
-
-struct ops file_ops = {
-       .name = "FILE",
-       .dir = (void *)file_directory,
-       .read = (void *)file_read,
-       .write = (void *)file_write,
-       .mkdir = (void *)file_mkdir,
-       .rm = (void *)file_rm,
-       .get_perms = (void *)file_get_perms,
-       .set_perms = (void *)file_set_perms,
-       .transaction_start = (void *)file_transaction_start,
-       .transaction_end = (void *)file_transaction_end,
-       .handle = (void *)file_handle,
-       .close = (void *)file_close,
-};
-
-struct ops xs_ops = {
-       .name = "XS",
-       .dir = (void *)xs_directory,
-       .read = (void *)xs_read,
-       .write = (void *)xs_write,
-       .mkdir = (void *)xs_mkdir,
-       .rm = (void *)xs_rm,
-       .get_perms = (void *)xs_get_permissions,
-       .set_perms = (void *)xs_set_permissions,
-       .transaction_start = (void *)xs_transaction_start,
-       .transaction_end = (void *)xs_transaction_end,
-       .handle = (void *)xs_handle,
-       .close = (void *)xs_close,
-};
-
-static int strptrcmp(const void *a, const void *b)
-{
-       return strcmp(*(char **)a, *(char **)b);
-}
-
-static void sort_dir(char **dir, unsigned int num)
-{
-       qsort(dir, num, sizeof(char *), strptrcmp);
-}
-
-static char *dump_dir(struct ops *ops,
-                     void *h,
-                     const char *node,
-                     char **dir,
-                     unsigned int numdirs,
-                     unsigned int depth)
-{
-       char *ret = talloc_strdup(node, "");
-       unsigned int i;
-       char spacing[depth+1];
-
-       memset(spacing, ' ', depth);
-       spacing[depth] = '\0';
-
-       sort_dir(dir, numdirs);
-
-       for (i = 0; i < numdirs; i++) {
-               struct xs_permissions *perms;
-               unsigned int j, numperms;
-               unsigned int len;
-               char *contents;
-               unsigned int subnum;
-               char **subdirs;
-               char *subret;
-               char *subnode = talloc_asprintf(node, "%s/%s", node, dir[i]);
-
-               perms = ops->get_perms(h, subnode, &numperms);
-               if (!perms)
-                       return NULL;
-               ret = talloc_asprintf_append(ret, "%s%s: ", spacing, dir[i]);
-               for (j = 0; j < numperms; j++) {
-                       char buffer[100];
-                       if (!xs_perm_to_string(&perms[j], buffer))
-                               barf("perm to string");
-                       ret = talloc_asprintf_append(ret, "%s ", buffer);
-               }
-               free(perms);
-               ret = talloc_asprintf_append(ret, "\n");
-
-               /* Even directories can have contents. */
-               contents = ops->read(h, subnode, &len);
-               if (!contents) {
-                       if (errno != EISDIR)
-                               return NULL;
-               } else {
-                       ret = talloc_asprintf_append(ret, " %s(%.*s)\n",
-                                                    spacing, len, contents);
-                       free(contents);
-               }                       
-
-               /* Every node is a directory. */
-               subdirs = ops->dir(h, subnode, &subnum);
-               if (!subdirs)
-                       return NULL;
-               subret = dump_dir(ops, h, subnode, subdirs, subnum, depth+1);
-               if (!subret)
-                       return NULL;
-               ret = talloc_asprintf_append(ret, "%s", subret);
-               free(subdirs);
-       }
-       return ret;
-}
-
-static char *dump(struct ops *ops, void *h)
-{
-       char **subdirs;
-       unsigned int subnum;
-       char *ret = NULL, *root = talloc_strdup(NULL, "/");
-
-       subdirs = ops->dir(h, root, &subnum);
-       if (subdirs) {
-               ret = dump_dir(ops, h, talloc_strdup(root, ""), subdirs,
-                              subnum, 0);
-               free(subdirs);
-               if (ret)
-                       talloc_steal(NULL, ret);
-       }
-       talloc_free(root);
-       return ret;
-}
-
-/* jhash.h: Jenkins hash support.
- *
- * Copyright (C) 1996 Bob Jenkins (bob_jenkins@xxxxxxxxxxxxxxxx)
- *
- * http://burtleburtle.net/bob/hash/
- *
- * These are the credits from Bob's sources:
- *
- * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
- * hash(), hash2(), hash3, and mix() are externally useful functions.
- * Routines to test the hash are included if SELF_TEST is defined.
- * You can use this free for any purpose.  It has no warranty.
- *
- * Copyright (C) 2003 David S. Miller (davem@xxxxxxxxxx)
- *
- * I've modified Bob's hash to be useful in the Linux kernel, and
- * any bugs present are surely my fault.  -DaveM
- */
-
-/* NOTE: Arguments are modified. */
-#define __jhash_mix(a, b, c) \
-{ \
-  a -= b; a -= c; a ^= (c>>13); \
-  b -= c; b -= a; b ^= (a<<8); \
-  c -= a; c -= b; c ^= (b>>13); \
-  a -= b; a -= c; a ^= (c>>12);  \
-  b -= c; b -= a; b ^= (a<<16); \
-  c -= a; c -= b; c ^= (b>>5); \
-  a -= b; a -= c; a ^= (c>>3);  \
-  b -= c; b -= a; b ^= (a<<10); \
-  c -= a; c -= b; c ^= (b>>15); \
-}
-
-/* The golden ration: an arbitrary value */
-#define JHASH_GOLDEN_RATIO     0x9e3779b9
-
-/* The most generic version, hashes an arbitrary sequence
- * of bytes.  No alignment or length assumptions are made about
- * the input key.
- */
-static inline uint32_t jhash(const void *key, uint32_t length, uint32_t 
initval)
-{
-       uint32_t a, b, c, len;
-       const uint8_t *k = key;
-
-       len = length;
-       a = b = JHASH_GOLDEN_RATIO;
-       c = initval;
-
-       while (len >= 12) {
-               a += (k[0] +((uint32_t)k[1]<<8) +((uint32_t)k[2]<<16) 
+((uint32_t)k[3]<<24));
-               b += (k[4] +((uint32_t)k[5]<<8) +((uint32_t)k[6]<<16) 
+((uint32_t)k[7]<<24));
-               c += (k[8] +((uint32_t)k[9]<<8) 
+((uint32_t)k[10]<<16)+((uint32_t)k[11]<<24));
-
-               __jhash_mix(a,b,c);
-
-               k += 12;
-               len -= 12;
-       }
-
-       c += length;
-       switch (len) {
-       case 11: c += ((uint32_t)k[10]<<24);
-       case 10: c += ((uint32_t)k[9]<<16);
-       case 9 : c += ((uint32_t)k[8]<<8);
-       case 8 : b += ((uint32_t)k[7]<<24);
-       case 7 : b += ((uint32_t)k[6]<<16);
-       case 6 : b += ((uint32_t)k[5]<<8);
-       case 5 : b += k[4];
-       case 4 : a += ((uint32_t)k[3]<<24);
-       case 3 : a += ((uint32_t)k[2]<<16);
-       case 2 : a += ((uint32_t)k[1]<<8);
-       case 1 : a += k[0];
-       };
-
-       __jhash_mix(a,b,c);
-
-       return c;
-}
-
-/* A special optimized version that handles 1 or more of uint32_ts.
- * The length parameter here is the number of uint32_ts in the key.
- */
-static inline uint32_t jhash2(uint32_t *k, uint32_t length, uint32_t initval)
-{
-       uint32_t a, b, c, len;
-
-       a = b = JHASH_GOLDEN_RATIO;
-       c = initval;
-       len = length;
-
-       while (len >= 3) {
-               a += k[0];
-               b += k[1];
-               c += k[2];
-               __jhash_mix(a, b, c);
-               k += 3; len -= 3;
-       }
-
-       c += length * 4;
-
-       switch (len) {
-       case 2 : b += k[1];
-       case 1 : a += k[0];
-       };
-
-       __jhash_mix(a,b,c);
-
-       return c;
-}
-
-
-/* A special ultra-optimized versions that knows they are hashing exactly
- * 3, 2 or 1 word(s).
- *
- * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
- *       done at the end is not done here.
- */
-static inline uint32_t jhash_3words(uint32_t a, uint32_t b, uint32_t c, 
uint32_t initval)
-{
-       a += JHASH_GOLDEN_RATIO;
-       b += JHASH_GOLDEN_RATIO;
-       c += initval;
-
-       __jhash_mix(a, b, c);
-
-       return c;
-}
-
-static inline uint32_t jhash_2words(uint32_t a, uint32_t b, uint32_t initval)
-{
-       return jhash_3words(a, b, 0, initval);
-}
-
-static inline uint32_t jhash_1word(uint32_t a, uint32_t initval)
-{
-       return jhash_3words(a, 0, 0, initval);
-}
-
-static unsigned int get_randomness(int *state)
-{
-       return jhash_1word((*state)++, *state * 1103515243);
-}
-
-static char *random_path(int *state)
-{
-       unsigned int i;
-       char *ret = NULL;
-
-       if (get_randomness(state) % 20 == 0)
-               return talloc_strdup(NULL, "/");
-
-       for (i = 0; i < 1 || (get_randomness(state) % 2); i++) {
-               ret = talloc_asprintf_append(ret, "/%i", 
-                                            get_randomness(state) % 15);
-       }
-       return ret;
-}
-
-static char *bool_to_errstring(bool result)
-{
-       if (result)
-               return talloc_strdup(NULL, "OK");
-
-       /* Real daemon can never return this. */
-       if (errno == ENOTDIR)
-               errno = ENOENT;
-       return talloc_asprintf(NULL, "FAILED:%s", strerror(errno));
-}
-
-static char *linearize_dir(char **dir, unsigned int *num)
-{
-       char *result = NULL;
-       unsigned int i;
-
-       if (!dir)
-               return bool_to_errstring(false);
-
-       if (!*num) {
-               free(dir);
-               return talloc_strdup(NULL, "");
-       }
-
-       sort_dir(dir, *num);
-       for (i = 0; i < *num; i++)
-               result = talloc_asprintf_append(result, "%s\n", dir[i]);
-       free(dir);
-       return result;
-}
-
-static char *linearize_read(char *read, unsigned int *size)
-{
-       char *ret;
-
-       if (!read)
-               return bool_to_errstring(false);
-
-       ret = talloc_asprintf(NULL, "%i:%.*s", *size, *size, read);
-       free(read);
-       return ret;
-}
-
-static char *linearize_perms(struct xs_permissions *perms, unsigned int *size)
-{
-       char *ret = NULL;
-       unsigned int i;
-
-       if (!perms)
-               return bool_to_errstring(false);
-
-       for (i = 0; i < *size; i++)
-               ret = talloc_asprintf_append(ret, "(%u %u)",
-                                            perms[i].id, perms[i].perms);
-
-       free(perms);
-       return ret;
-}
-
-/* Do the next operation, return the results. */
-static char *do_next_op(struct ops *ops, void *h, int state, bool verbose)
-{
-       char *name;
-       unsigned int num;
-       char *ret;
-
-       if (verbose)
-               printf("State %i: ", state);
-
-       name = random_path(&state);
-       switch (get_randomness(&state) % 9) {
-       case 0:
-               if (verbose)
-                       printf("DIR %s\n", name);
-               ret = linearize_dir(ops->dir(h, name, &num), &num);
-               break;
-       case 1:
-               if (verbose)
-                       printf("READ %s\n", name);
-               ret = linearize_read(ops->read(h, name, &num), &num);
-               break;
-       case 2: {
-               char *contents = talloc_asprintf(NULL, "%i",
-                                                get_randomness(&state));
-               unsigned int len = get_randomness(&state)%(strlen(contents)+1);
-               if (verbose)
-                       printf("WRITE %s %.*s\n", name, len, contents);
-               ret = bool_to_errstring(ops->write(h, name, contents, len));
-               talloc_steal(ret, contents);
-               break;
-       }
-       case 3:
-               if (verbose)
-                       printf("MKDIR %s\n", name);
-               ret = bool_to_errstring(ops->mkdir(h, name));
-               break;
-       case 4:
-               if (verbose)
-                       printf("RM %s\n", name);
-               ret = bool_to_errstring(ops->rm(h, name));
-               break;
-       case 5:
-               if (verbose)
-                       printf("GETPERMS %s\n", name);
-               ret = linearize_perms(ops->get_perms(h, name, &num),
-                                     &num);
-               break;
-       case 6: {
-               unsigned int i, num = get_randomness(&state)%8;
-               struct xs_permissions perms[num];
-
-               if (verbose)
-                       printf("SETPERMS %s: ", name);
-               for (i = 0; i < num; i++) {
-                       perms[i].id = get_randomness(&state)%8;
-                       perms[i].perms = get_randomness(&state)%4;
-                       if (verbose)
-                               printf("%i%c ", perms[i].id,
-                                      perms[i].perms == XS_PERM_WRITE ? 'W'
-                                      : perms[i].perms == XS_PERM_READ ? 'R'
-                                      : perms[i].perms == 
-                                      (XS_PERM_READ|XS_PERM_WRITE) ? 'B'
-                                      : 'N');
-               }
-               if (verbose)
-                       printf("\n");
-               ret = bool_to_errstring(ops->set_perms(h, name, perms,
-                                                      num));
-               break;
-       }
-       case 7: {
-               if (verbose)
-                       printf("START %s\n", name);
-               ret = bool_to_errstring(ops->transaction_start(h));
-               if (streq(ret, "OK")) {
-                       talloc_free(ret);
-                       ret = talloc_asprintf(NULL, "OK:START-TRANSACT");
-               }
-
-               break;
-       }
-       case 8: {
-               bool abort = (get_randomness(&state) % 2);
-
-               if (verbose)
-                       printf("STOP %s\n", abort ? "ABORT" : "COMMIT");
-               ret = bool_to_errstring(ops->transaction_end(h, abort));
-               if (streq(ret, "OK")) {
-                       talloc_free(ret);
-                       ret = talloc_strdup(NULL, "OK:STOP-TRANSACT");
-               }
-               break;
-       }
-       default:
-               barf("Impossible randomness");
-       }
-
-       talloc_steal(ret, name);
-       return ret;
-}
-
-static int daemon_pid;
-
-static void cleanup_xs_ops(void)
-{
-       char *cmd;
-
-       if (daemon_pid) {
-               kill(daemon_pid, SIGTERM);
-               waitpid(daemon_pid, NULL, 0);
-               daemon_pid = 0;
-       }
-       
-       cmd = talloc_asprintf(NULL, "rm -rf testsuite/tmp/*");
-       do_command(cmd);
-       talloc_free(cmd);
-}
-
-static void cleanup_file_ops(const char *dir)
-{
-       char *cmd;
-
-       cmd = talloc_asprintf(NULL, "rm -rf %s %s.transact", dir, dir);
-       do_command(cmd);
-       talloc_free(cmd);
-}
-
-static void cleanup(const char *dir)
-{
-       cleanup_xs_ops();
-       cleanup_file_ops(dir);
-}
-
-static void setup_file_ops(const char *dir)
-{
-       struct xs_permissions perm = { .id = 0, .perms = XS_PERM_READ };
-       struct file_ops_info *h = file_handle(dir);
-       if (mkdir(dir, 0700) != 0)
-               barf_perror("Creating directory %s", dir);
-       if (mkdir(talloc_asprintf(h, "%s/tool", dir), 0700) != 0)
-               barf_perror("Creating directory %s/tool", dir);
-       if (!file_set_perms(h, talloc_strdup(h, "/"), &perm, 1))
-               barf_perror("Setting root perms in %s", dir);
-       if (!file_set_perms(h, talloc_strdup(h, "/tool"), &perm, 1))
-               barf_perror("Setting root perms in %s/tool", dir);
-       file_close(h);
-}
-
-static void setup_xs_ops(void)
-{
-       int fds[2];
-
-       /* Start daemon. */
-       pipe(fds);
-       if ((daemon_pid = fork())) {
-               /* Child writes PID when its ready: we wait for that. */
-               char buffer[20];
-               close(fds[1]);
-               if (read(fds[0], buffer, sizeof(buffer)) < 0)
-                       barf("Failed to summon daemon");
-               close(fds[0]);
-       } else {
-               dup2(fds[1], STDOUT_FILENO);
-               close(fds[0]);
-#if 1
-               execlp("valgrind", "valgrind", "-q", 
"--suppressions=testsuite/vg-suppressions", "xenstored_test", "--output-pid",
-                      "--no-fork", NULL);
-#else
-               execlp("./xenstored_test", "xenstored_test", "--output-pid",
-                      "--no-fork", NULL);
-#endif
-               exit(1);
-       }
-}
-
-static void setup(const char *dir)
-{
-       setup_file_ops(dir);
-       setup_xs_ops();
-};
-
-struct simple_data
-{
-       unsigned int seed;
-       bool print_progress;
-       bool fast;
-       struct ops *ops;
-       const char *dir;
-};
-
-/* Just a random test.  Don't care about results, just that it doesn't
- * go boom. */
-static unsigned int try_simple(const bool *trymap,
-                              unsigned int number,
-                              bool verbose,
-                              void *_data)
-{
-       unsigned int i, print;
-       void *h;
-       char *snapshot = NULL;
-       struct simple_data *data = _data;
-
-       if (data->ops == &xs_ops) {
-               cleanup_xs_ops();
-               setup_xs_ops();
-       } else {
-               cleanup_file_ops(data->dir);
-               setup_file_ops(data->dir);
-       }
-       h = data->ops->handle(data->dir);
-
-       print = number / 76;
-       if (!print)
-               print = 1;
-
-       for (i = 0; i < number; i++) {
-               char *ret;
-
-               if (data->print_progress) {
-                       if (i % print == 0) {
-                               printf(".");
-                               fflush(stdout);
-                       }
-               }
-
-               if (trymap && !trymap[i])
-                       continue;
-
-               ret = do_next_op(data->ops, h, i + data->seed, verbose);
-               if (verbose)
-                       printf("-> %.*s\n",
-                              (int)(strchr(ret, '\n') - ret), ret);
-               if (streq(ret, "FAILED:Bad file descriptor"))
-                       goto out;
-               if (kill(daemon_pid, 0) != 0)
-                       goto out;
-
-               if (!data->fast) {
-                       if (streq(ret, "OK:START-TRANSACT")) {
-                               void *pre = data->ops->handle(data->dir);
-
-                               snapshot = dump(data->ops, pre);
-                               if (!snapshot)
-                                       goto out;
-                               data->ops->close(pre);
-                       } else if (streq(ret, "OK:STOP-TRANSACT")) {
-                               talloc_free(snapshot);
-                               snapshot = NULL;
-                       }
-               }
-
-               talloc_free(ret);
-
-               if (snapshot) {
-                       void *pre = data->ops->handle(data->dir);
-                       char *contents;
-
-                       contents = dump(data->ops, pre);
-                       if (!contents)
-                               goto out;
-
-                       if (!streq(contents, snapshot))
-                               goto out;
-
-                       talloc_free(contents);
-                       data->ops->close(pre);
-               }
-       }
-out:
-       data->ops->close(h);    
-       return i;
-}
-
-/* Binary elimination: try eliminating all of them, then reduce. */
-static void reduce(bool *map,
-                  unsigned int number,
-                  unsigned int try_start, unsigned int try_num,
-                  unsigned int (*try)(const bool *map,
-                                      unsigned int number,
-                                      bool verbose,
-                                      void *),
-                  void *data)
-{
-       bool newmap[number];
-
-       if (try_num == 0)
-               return;
-
-       /* Try skipping everything between start and end.  */
-       memcpy(newmap, map, sizeof(newmap));
-       memset(newmap + try_start, 0, try_num * sizeof(bool));
-
-       /* We want the *same* failure: must fail at "number-1". */
-       if (try(newmap, number, false, data) == number - 1) {
-               memset(map + try_start, 0, try_num * sizeof(bool));
-               return;
-       }
-
-       if (try_num == 1)
-               return;
-
-       /* Try each half... */
-       reduce(map, number, try_start, try_num/2, try, data);
-       reduce(map, number, try_start + try_num/2, try_num - try_num/2,
-              try, data);
-}
-
-static void reduce_problem(unsigned int failed,
-                          unsigned int (*try)(const bool *map,
-                                              unsigned int number,
-                                              bool verbose,
-                                              void *data),
-                          void *data)
-{
-       bool map[failed];
-
-       memset(map, 1, sizeof(map));
-       reduce(map, failed, 0, failed-1, try, data);
-
-       printf("Cut down:\n");
-       if (try(map, failed, true, data) != failed - 1) {
-               printf("Except, that didn't actually fail.  Bugger!");
-               exit(2);
-       }
-       exit(1);
-}
-
-/* Just a random test.  Don't care about results, just that it doesn't
- * go boom. */
-static void simple_test(const char *dir,
-                       unsigned int iters, unsigned int seed,
-                       bool fast, bool verbose)
-{
-       struct simple_data data;
-       unsigned int try;
-
-       data.seed = seed;
-       data.print_progress = !verbose;
-       data.fast = fast;
-       data.ops = &xs_ops;
-       data.dir = dir;
-
-       try = try_simple(NULL, iters, verbose, &data);
-       if (try == iters) {
-               cleanup_xs_ops();
-               exit(0);
-       }
-       printf("Failed on iteration %u of seed %u\n", try + 1, seed);
-       data.print_progress = false;
-       reduce_problem(try + 1, try_simple, &data);
-}
-
-static bool ops_equal(struct ops *a, void *ah,
-                     struct ops *b, void *bh,
-                     const char *node,
-                     struct ops **fail)
-{
-       char **dira = NULL, **dirb = NULL;
-       char *dataa = NULL, *datab = NULL;
-       unsigned int i, numa, numb, lena, lenb;
-       struct xs_permissions *permsa = NULL, *permsb = NULL;
-       unsigned int numpermsa, numpermsb;
-       char *nodename;
-       bool ret = false;
-
-       /* Ignore tool/ dir. */
-       if (streq(node, "/tool"))
-               return true;
-
-       /* FILE backend expects talloc'ed pointer. */
-       nodename = talloc_strdup(NULL, node);
-       permsa = a->get_perms(ah, nodename, &numpermsa);
-       if (!permsa) {
-               *fail = a;
-               goto out;
-       }
-       permsb = b->get_perms(bh, nodename, &numpermsb);
-       if (!permsb) {
-               *fail = b;
-               goto out;
-       }
-       if (numpermsa != numpermsb)
-               goto out;
-       for (i = 0; i < numpermsa; i++) {
-               if (permsa[i].perms != permsb[i].perms)
-                       goto out;
-               if (permsa[i].id != permsb[i].id)
-                       goto out;
-       }
-
-       /* Non-pure-directory nodes contain data. */
-       dataa = a->read(ah, nodename, &lena);
-       if (!dataa && errno != EISDIR) {
-               *fail = a;
-               goto out;
-       }
-       datab = b->read(bh, nodename, &lenb);
-       if (!datab && errno != EISDIR) {
-               *fail = b;
-               goto out;
-       }
-
-       if (dataa) {
-               if (!datab)
-                       goto out;
-               if (lena != lenb)
-                       goto out;
-
-               if (memcmp(dataa, datab, lena) != 0)
-                       goto out;
-       } else
-               if (datab)
-                       goto out;
-
-       /* Everything is a directory. */
-       dira = a->dir(ah, nodename, &numa);
-       if (!dira) {
-               *fail = a;
-               goto out;
-       }
-       dirb = b->dir(bh, nodename, &numb);
-       if (!dirb) {
-               *fail = b;
-               goto out;
-       }
-       if (numa != numb)
-               goto out;
-       sort_dir(dira, numa);
-       sort_dir(dirb, numb);
-       for (i = 0; i < numa; i++) {
-               char subnode[strlen(node) + 1 + strlen(dira[i]) + 1];
-
-               if (!streq(dira[i], dirb[i]))
-                       goto out;
-
-               strcpy(subnode, node);
-               if (!streq(node, "/"))
-                       strcat(subnode, "/");
-               strcat(subnode, dira[i]);
-               if (!ops_equal(a, ah, b, bh, subnode, fail))
-                       goto out;
-       }
-
-       ret = true;
-out:
-       free(permsa);
-       free(permsb);
-       free(dataa);
-       free(datab);
-       free(dira);
-       free(dirb);
-       talloc_free(nodename);
-       return ret;
-}
-
-struct diff_data
-{
-       unsigned int seed;
-       bool print_progress;
-       bool fast;
-       const char *dir;
-};
-
-/* Differential: try both file and xs backend, watch for differences. */
-static unsigned int try_diff(const bool *trymap,
-                            unsigned int number,
-                            bool verbose,
-                            void *_data)
-{
-       void *fileh, *xsh;
-       bool transact = false;
-       struct ops *fail;
-       struct diff_data *data = _data;
-       unsigned int i, print;
-
-       cleanup(data->dir);
-       setup(data->dir);
-
-       fileh = file_handle(data->dir);
-       xsh = xs_handle(data->dir);
-
-       print = number / 76;
-       if (!print)
-               print = 1;
-
-       for (i = 0; i < number; i++) {
-               char *file, *xs;
-
-               if (data->print_progress) {
-                       if (i % print == 0) {
-                               printf(".");
-                               fflush(stdout);
-                       }
-               }
-               if (trymap && !trymap[i])
-                       continue;
-
-               if (verbose)
-                       printf("FILE: ");
-
-               file = do_next_op(&file_ops, fileh, i+data->seed, verbose);
-               if (verbose)
-                       printf("-> %.*s\n",
-                              (int)(strchr(file, '/') - file), file);
-               
-               if (verbose)
-                       printf("XS: ");
-               xs = do_next_op(&xs_ops, xsh, i+data->seed, verbose);
-               if (verbose)
-                       printf("-> %.*s\n", (int)(strchr(xs, '/') - xs), xs);
-
-               if (!streq(file, xs))
-                       goto out;
-
-               if (strstarts(file, "OK:START-TRANSACT:"))
-                       transact = true;
-               else if (streq(file, "OK:STOP-TRANSACT"))
-                       transact = false;
-
-               talloc_free(file);
-               talloc_free(xs);
-
-               if (data->fast)
-                       continue;
-
-               fail = NULL;
-               if (!ops_equal(&xs_ops, xsh, &file_ops, fileh, "/", &fail)) {
-                       if (fail)
-                               barf("%s failed during test\n", fail->name);
-                       if (verbose)
-                               printf("Trees differ:\nXS:%s\nFILE%s\n",
-                                      dump(&xs_ops, xsh),
-                                      dump(&file_ops, fileh));
-                       goto out;
-               }
-
-               if (transact) {
-                       void *fileh_pre = file_handle(data->dir);
-                       void *xsh_pre = xs_handle(data->dir);
-
-                       fail = NULL;
-                       if (!ops_equal(&xs_ops, xsh_pre, &file_ops, fileh_pre,
-                                      "/", &fail)) {
-                               if (fail)
-                                       barf("%s failed during transact\n",
-                                            fail->name);
-
-                               xs_daemon_close(xsh_pre);
-                               talloc_free(fileh_pre);
-                               goto out;
-                       }
-                       xs_daemon_close(xsh_pre);
-                       talloc_free(fileh_pre);
-               }
-       }
-
-       fail = NULL;
-       if (data->fast)
-               if (!ops_equal(&xs_ops, xsh, &file_ops, fileh, "/", &fail))
-                       barf("Final result not the same: try without --fast");
-out:
-       file_ops.close(fileh);  
-       xs_ops.close(xsh);      
-       return i;
-}
-
-/* Differential random test: compare results against file backend. */
-static void diff_test(const char *dir,
-                     unsigned int iters, unsigned int seed, bool fast, 
-                     bool verbose)
-{
-       struct diff_data data;
-       unsigned int try;
-
-       data.seed = seed;
-       data.print_progress = !verbose;
-       data.fast = fast;
-       data.dir = dir;
-
-       try = try_diff(NULL, iters, verbose, &data);
-       if (try == iters) {
-               cleanup_xs_ops();
-               exit(0);
-       }
-       printf("Failed on iteration %u of seed %u\n", try + 1, seed);
-       data.print_progress = false;
-       reduce_problem(try + 1, try_diff, &data);
-}
-
-struct fail_data
-{
-       unsigned int seed;
-       bool print_progress;
-       const char *dir;
-};
-
-/* Try xs with inserted failures: every op should either succeed or fail. */
-static unsigned int try_fail(const bool *trymap,
-                             unsigned int number,
-                             bool verbose,
-                             void *_data)
-{
-       unsigned int i, print, tried = 0, aborted = 0;
-       struct fail_data *data = _data;
-       struct xs_handle *tmpxsh;
-       struct file_ops_info *tmpfileh;
-       void *fileh, *xsh;
-       struct ops *fail;
-       char seed[20];
-
-       /* Make sure failures off to shut down. */
-       if (daemon_pid)
-               kill(daemon_pid, SIGUSR1);
-       cleanup(data->dir);
-       setup(data->dir);
-
-       fileh = file_handle(data->dir);
-       xsh = xs_handle(data->dir);
-
-       print = number / 76;
-       if (!print)
-               print = 1;
-
-       for (i = 0; i < number; i++) {
-               unsigned int limit, failed;
-               char *ret;
-
-               /* A few times we fail due to other end OOM. */
-               limit = 0;
-               while (!xsh) {
-                       xsh = xs_handle(data->dir);
-                       if (!xsh && errno == ECONNREFUSED) {
-                               if (verbose)
-                                       printf("Daemon refused connection\n");
-                               goto out;
-                       }
-                       if (!xsh && limit++ == 5) {
-                               printf("Daemon failed conn 5 times\n");
-                               goto out;
-                       }
-               }
-
-               if (data->print_progress) {
-                       if (i % print == 0) {
-                               printf(".");
-                               fflush(stdout);
-                       }
-               }
-               if (trymap && !trymap[i])
-                       continue;
-
-               /* Turn on failure. */
-               sprintf(seed, "%i", data->seed + i);
-               free(xs_debug_command(xsh, "failtest",seed,strlen(seed)+1));
-
-               if (verbose)
-                       printf("(%i) seed %s ", i, seed);
-               ret = do_next_op(&xs_ops, xsh, i + data->seed, verbose);
-               if (streq(ret, "FAILED:Connection reset by peer")
-                   || streq(ret, "FAILED:Bad file descriptor")
-                   || streq(ret, "FAILED:Broken pipe")) {
-                       xs_close(xsh);
-                       xsh = NULL;
-                       failed = 2;
-               } else if (strstarts(ret, "OK"))
-                       failed = 0;
-               else
-                       failed = 1;
-
-               tried++;
-               if (xsh)
-                       aborted++;
-
-               if (verbose)
-                       printf("-> %.*s\n",
-                              (int)(strchr(ret, '\n') - ret), ret);
-
-               talloc_free(ret);
-
-               /* Turn off failures using signal. */
-               if (kill(daemon_pid, SIGUSR1) != 0) {
-                       if (verbose)
-                               printf("Failed to signal daemon\n");
-                       goto out;
-               }
-
-               if (failed == 0) {
-                       /* Succeeded?  Do same thing to file backend
-                        * to compare */
-               try_applying:
-                       ret = do_next_op(&file_ops, fileh, i + data->seed,
-                                        false);
-                       if (!strstarts(ret, "OK")) {
-                               if (!verbose)
-                                       printf("File op failed on %i\n",
-                                              i + data->seed);
-                               talloc_free(ret);
-                               goto out;
-                       }
-                       talloc_free(ret);
-               }
-
-               tmpxsh = xs_handle(data->dir);
-               if (!tmpxsh) {
-                       if (verbose)
-                               printf("Failed to open signalled daemon");
-                       goto out;
-               }
-               tmpfileh = file_handle(data->dir);
-
-               fail = NULL;
-               if (!ops_equal(&xs_ops, tmpxsh, &file_ops, tmpfileh, "/",
-                              &fail)) {
-                       if (fail) {
-                               if (verbose)
-                                       printf("%s failed\n", fail->name);
-                               goto out;
-                       }
-                       /* Maybe op succeeded: try comparing after local op? */
-                       if (failed == 2) {
-                               failed = 0;
-                               if (verbose)
-                                       printf("(Looks like it succeeded)\n");
-                               xs_close(tmpxsh);
-                               file_close(tmpfileh);
-                               goto try_applying;
-                       }
-                       if (verbose)
-                               printf("Trees differ:\nXS:%s\nFILE:%s\n",
-                                      dump(&xs_ops, tmpxsh),
-                                      dump(&file_ops, tmpfileh));
-                       xs_close(tmpxsh);
-                       file_close(tmpfileh);
-                       goto out;
-               }
-
-               /* If we lost the xs handle, that ended the transaction */
-               if (!xsh)
-                       file_transaction_end(fileh, true);
-
-               xs_close(tmpxsh);
-               file_close(tmpfileh);
-       }
-out:
-       if (xsh)
-               xs_close(xsh);
-       return i;
-}
-
-static void fail_test(const char *dir,
-                     unsigned int iters, unsigned int seed,
-                     bool fast __attribute__((unused)), bool verbose)
-{
-       struct fail_data data;
-       unsigned int try;
-
-       data.seed = seed;
-       data.print_progress = !verbose;
-       data.dir = dir;
-
-       try = try_fail(NULL, iters, verbose, &data);
-       if (try == iters) {
-               cleanup_xs_ops();
-               exit(0);
-       }
-       printf("Failed on iteration %u of seed %u\n", try + 1, seed);
-       fflush(stdout);
-       data.print_progress = false;
-       reduce_problem(try + 1, try_fail, &data);
-}
-
-int main(int argc, char *argv[])
-{
-       bool verbose = false;
-       bool simple = false;
-       bool fast = false;
-       bool fail = false;
-
-       if (argv[1] && streq(argv[1], "--fail")) {
-               fail = true;
-               argv++;
-               argc--;
-       }
-
-       if (argv[1] && streq(argv[1], "--simple")) {
-               simple = true;
-               argv++;
-               argc--;
-       }
-
-       if (argv[1] && streq(argv[1], "--fast")) {
-               fast = true;
-               argv++;
-               argc--;
-       }
-
-       if (argv[1] && streq(argv[1], "--verbose")) {
-               verbose = true;
-               argv++;
-               argc--;
-       }
-
-       if (argc != 4)
-               barf("Usage: xs_random [--fail|--simple] [--fast] [--verbose] 
<directory> <iterations> <seed>");
-
-       talloc_enable_null_tracking();
-
-       if (fail)
-               fail_test(argv[1], atoi(argv[2]), atoi(argv[3]), fast, verbose);
-       else if (simple)
-               simple_test(argv[1], atoi(argv[2]), atoi(argv[3]), fast, 
verbose);
-       else
-               diff_test(argv[1],  atoi(argv[2]), atoi(argv[3]), fast, 
verbose);
-       exit(2);
-}
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/xs_stress.c
--- a/tools/xenstore/xs_stress.c        Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +0,0 @@
-/* Stress test for Xen Store: multiple people hammering transactions */
-#include "xs.h"
-#include "utils.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-#define NUM_HANDLES 2
-#define DIR_FANOUT 3
-#define DIR_DEPTH 3
-
-/* How often to print progress */
-static int print;
-
-/* Layout looks like /<num>/<num>/count. */
-static void work(unsigned int cycles, unsigned int childnum)
-{
-       unsigned int i;
-       struct xs_handle *handles[NUM_HANDLES];
-       char id;
-
-       if (childnum < 10)
-               id = '0' + childnum;
-       else
-               id = 'A' + childnum - 10;
-
-       for (i = 0; i < NUM_HANDLES; i++) {
-               handles[i] = xs_daemon_open();
-               if (!handles[i])
-                       barf_perror("Opening handle %i", i);
-       }
-
-       srandom(childnum);
-       for (i = 0; i < cycles; i++) {
-               unsigned int j, len;
-               char file[100] = "";
-               char *contents, tmp[100];
-               struct xs_handle *h = handles[random() % NUM_HANDLES];
-
-               for (j = 0; j < DIR_DEPTH; j++)
-                       sprintf(file + strlen(file), "/%li",
-                               random()%DIR_FANOUT);
-
-               if (!xs_transaction_start(h))
-                       barf_perror("%i: starting transaction %i",
-                                   childnum, i);
-
-               sprintf(file + strlen(file), "/count");
-               contents = xs_read(h, file, &len);
-               if (!contents)
-                       barf_perror("%i: can't read %s iter %i",
-                                   childnum, file, i);
-               sprintf(tmp, "%i", atoi(contents) + 1);
-               if (!xs_write(h, file, tmp, strlen(tmp)+1))
-                       barf_perror("%i: can't write %s iter %i",
-                                   childnum, file, i);
-
-               /* Abandon 1 in 10 */
-               if (random() % 10 == 0) {
-                       if (!xs_transaction_end(h, true))
-                               barf_perror("%i: can't abort transact",
-                                           childnum);
-                       i--;
-               } else {
-                       if (!xs_transaction_end(h, false)) {
-                               if (errno == EAGAIN) {
-                                       write(STDOUT_FILENO, "!", 1);
-                                       i--;
-                               } else
-                                       barf_perror("%i: can't commit trans",
-                                                   childnum);
-                       } else {
-                               /* Offset when we print . so kids don't all
-                                * print at once. */
-                               if ((i + print/(childnum+1)) % print == 0)
-                                       write(STDOUT_FILENO, &id, 1);
-                       }
-               }
-       }
-}
-
-static void create_dirs(struct xs_handle *h, const char *base, int togo)
-{
-       unsigned int i;
-       char filename[100];
-
-       if (togo == 0) {
-               sprintf(filename, "%s/count", base);
-               if (!xs_write(h, filename, "0", 1))
-                       barf_perror("Writing to %s", filename);
-               return;
-       }
-
-       for (i = 0; i < DIR_FANOUT; i++) {
-               sprintf(filename, "%s/%i", base, i);
-               if (!xs_mkdir(h, filename))
-                       barf_perror("xs_mkdir %s", filename);
-               create_dirs(h, filename, togo-1);
-       }
-}
-
-static unsigned int add_count(struct xs_handle *h, const char *base, int togo)
-{
-       unsigned int i, count;
-       char filename[100];
-
-       if (togo == 0) {
-               char *answer;
-               unsigned int len;
-
-               sprintf(filename, "%s/count", base);
-               answer = xs_read(h, filename, &len);
-               if (!answer)
-                       barf_perror("Reading %s", filename);
-               count = atoi(answer);
-               free(answer);
-               return count;
-       }
-
-       count = 0;
-       for (i = 0; i < DIR_FANOUT; i++) {
-               sprintf(filename, "%s/%i", base, i);
-               count += add_count(h, filename, togo-1);
-       }
-       return count;
-}
-
-static void setup(void)
-{
-       struct xs_handle *h;
-
-       /* Do setup. */
-       h = xs_daemon_open();
-       if (!h)
-               barf_perror("Contacting daemon");
-       create_dirs(h, "", DIR_DEPTH);
-       xs_daemon_close(h);
-}
-
-static unsigned int tally_counts(void)
-{
-       struct xs_handle *h;
-       unsigned int ret;
-       
-       h = xs_daemon_open();
-       if (!h)
-               barf_perror("Contacting daemon");
-
-       ret = add_count(h, "", DIR_DEPTH);
-       xs_daemon_close(h);
-       return ret;
-}      
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       bool failed = false;
-       int kids[10];
-
-       if (argc != 2)
-               barf("Usage: xs_stress <iterations>");
-
-       printf("Setting up directories...\n");
-       setup();
-
-       print = atoi(argv[1]) / 76;
-       if (!print)
-               print = 1;
-
-       printf("Running %i children...\n", ARRAY_SIZE(kids));
-       for (i = 0; i < ARRAY_SIZE(kids); i++) {
-               kids[i] = fork();
-               if (kids[i] == -1)
-                       barf_perror("fork");
-               if (kids[i] == 0) {
-                       work(atoi(argv[1]) / ARRAY_SIZE(kids), i);
-                       exit(0);
-               }
-       }
-
-       for (i = 0; i < ARRAY_SIZE(kids); i++) {
-               int status;
-               if (waitpid(kids[i], &status, 0) == -1)
-                       barf_perror("waitpid");
-               if (!WIFEXITED(status))
-                       barf("Kid %i died via signal %i\n",
-                            i, WTERMSIG(status));
-               if (WEXITSTATUS(status) != 0) {
-                       printf("Child %i exited %i\n", i, WEXITSTATUS(status));
-                       failed = true;
-               }
-       }
-       if (failed)
-               exit(1);
-
-       printf("\nCounting results...\n");
-       i = tally_counts();
-       if (i != (unsigned)atoi(argv[1]))
-               barf("Total counts %i not %s", i, argv[1]);
-       printf("Success!\n");
-       exit(0);
-}
diff -r 0528bc25c404 -r eb71f258e855 tools/xenstore/xs_test.c
--- a/tools/xenstore/xs_test.c  Tue Jul 03 15:49:16 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,812 +0,0 @@
-/* 
-    Xen Store Daemon Test tool
-    Copyright (C) 2005 Rusty Russell IBM Corporation
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    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 General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <fnmatch.h>
-#include <stdarg.h>
-#include <string.h>
-#include <getopt.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include "utils.h"
-#include "xs_lib.h"
-#include "xs.h"
-#include "list.h"
-
-#define XSTEST
-
-static struct xs_handle *handles[10] = { NULL };
-static xs_transaction_t txh[10] = { XBT_NULL };
-
-static unsigned int timeout_ms = 500;
-static bool timeout_suppressed = true;
-static bool readonly = false;
-static bool print_input = false;
-static unsigned int linenum = 0;
-
-static int daemon_pid;
-static struct xenstore_domain_interface *interface;
-
-/* FIXME: Mark connection as broken (close it?) when this happens. */
-static bool check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
-{
-       return ((prod - cons) <= XENSTORE_RING_SIZE);
-}
-
-static void *get_output_chunk(XENSTORE_RING_IDX cons,
-                             XENSTORE_RING_IDX prod,
-                             char *buf, uint32_t *len)
-{
-       *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
-       if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
-               *len = XENSTORE_RING_SIZE - (prod - cons);
-       return buf + MASK_XENSTORE_IDX(prod);
-}
-
-static const void *get_input_chunk(XENSTORE_RING_IDX cons,
-                                  XENSTORE_RING_IDX prod,
-                                  const char *buf, uint32_t *len)
-{
-       *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
-       if ((prod - cons) < *len)
-               *len = prod - cons;
-       return buf + MASK_XENSTORE_IDX(cons);
-}
-
-/* FIXME: We spin, and we're sloppy. */
-static bool read_all_shmem(int fd __attribute__((unused)),
-                          void *data, unsigned int len)
-{
-       unsigned int avail;
-       struct xenstore_domain_interface *intf = interface;
-       XENSTORE_RING_IDX cons, prod;
-       const void *src;
-
-       while (len) {
-               cons = intf->rsp_cons;
-               prod = intf->rsp_prod;
-               if (!check_indexes(cons, prod))
-                       barf("Corrupt buffer");
-
-               src = get_input_chunk(cons, prod, intf->rsp, &avail);
-               if (avail > len)
-                       avail = len;
-               memcpy(data, src, avail);
-               data += avail;
-               len -= avail;
-               intf->rsp_cons += avail;
-       }
-
-       /* Tell other end we read something. */
-       kill(daemon_pid, SIGUSR2);
-
-       return true;
-}
-
-static bool write_all_shmem(int fd __attribute__((unused)),
-                           const void *data, unsigned int len)
-{
-       uint32_t avail;
-       struct xenstore_domain_interface *intf = interface;
-       XENSTORE_RING_IDX cons, prod;
-       void *dst;
-
-       while (len) {
-               cons = intf->req_cons;
-               prod = intf->req_prod;
-               if (!check_indexes(cons, prod))
-                       barf("Corrupt buffer");
-
-               dst = get_output_chunk(cons, prod, intf->req, &avail);
-               if (avail > len)
-                       avail = len;
-               memcpy(dst, data, avail);
-               data += avail;
-               len -= avail;
-               intf->req_prod += avail;
-       }
-
-       /* Tell other end we wrote something. */
-       kill(daemon_pid, SIGUSR2);
-
-       return true;
-}
-
-static bool read_all(int fd, void *data, unsigned int len);
-static bool read_all_choice(int fd, void *data, unsigned int len)
-{
-       if (fd == -2)
-               return read_all_shmem(fd, data, len);
-       return read_all(fd, data, len);
-}
-
-static bool write_all_choice(int fd, const void *data, unsigned int len)
-{
-       if (fd == -2)
-               return write_all_shmem(fd, data, len);
-       return xs_write_all(fd, data, len);
-}
-
-/* We want access to internal functions. */
-#include "xs.c"
-
-static void __attribute__((noreturn)) usage(void)
-{
-       barf("Usage:\n"
-            "       xs_test [--readonly] [--no-timeout] [-x]\n"
-            "Reads commands from stdin, one per line:"
-            "  dir <path>\n"
-            "  read <path>\n"
-            "  write <path> <value>...\n"
-            "  setid <id>\n"
-            "  mkdir <path>\n"
-            "  rm <path>\n"
-            "  getperm <path>\n"
-            "  setperm <path> <id> <flags> ...\n"
-            "  watch <path> <token>\n"
-            "  watchnoack <path> <token>\n"
-            "  waitwatch\n"
-            "  unwatch <path> <token>\n"
-            "  close\n"
-            "  start <node>\n"
-            "  abort\n"
-            "  introduce <domid> <mfn> <eventchn> <path>\n"
-            "  commit\n"
-            "  sleep <milliseconds>\n"
-            "  expect <pattern>\n"
-            "  notimeout\n"
-            "  readonly\n"
-            "  readwrite\n"
-            "  dump\n");
-}
-
-static int argpos(const char *line, unsigned int num)
-{
-       unsigned int i, len = 0, off = 0;
-
-       for (i = 0; i <= num; i++) {
-               off += len;
-               off += strspn(line + off, " \t\n");
-               len = strcspn(line + off, " \t\n");
-               if (!len)
-                       return off;
-       }
-       return off;
-}
-
-static char *arg(const char *line, unsigned int num)
-{
-       static char *args[10];
-       unsigned int off, len;
-
-       off = argpos(line, num);
-       len = strcspn(line + off, " \t\n");
-
-       if (!len)
-               barf("Can't get arg %u", num);
-
-       free(args[num]);
-       args[num] = malloc(len + 1);
-       memcpy(args[num], line+off, len);
-       args[num][len] = '\0';
-       return args[num];
-}
-
-struct expect
-{
-       struct list_head list;
-       char *pattern;
-};
-static LIST_HEAD(expects);
-
-static char *command;
-
-/* Trim leading and trailing whitespace */
-static void trim(char *str)
-{
-       while (isspace(str[0]))
-               memmove(str, str+1, strlen(str));
-
-       while (strlen(str) && isspace(str[strlen(str)-1]))
-               str[strlen(str)-1] = '\0';
-}
-
-static void output(const char *fmt, ...)
-{
-       char *str;
-       struct expect *i;
-       va_list arglist;
-
-       va_start(arglist, fmt);
-       vasprintf(&str, fmt, arglist);
-       va_end(arglist);
-
-       printf("%s", str);
-       fflush(stdout);
-       trim(str);
-       list_for_each_entry(i, &expects, list) {
-               if (fnmatch(i->pattern, str, 0) == 0) {
-                       list_del(&i->list);
-                       free(i);
-                       return;
-               }
-       }
-       barf("Unexpected output %s\n", str);
-}
-
-static void failed(int handle)
-{
-       if (handle)
-               output("%i: %s failed: %s\n",
-                      handle, command, strerror(errno));
-       else
-               output("%s failed: %s\n", command, strerror(errno));
-}
-
-static void expect(const char *line)
-{
-       struct expect *e = malloc(sizeof(*e));
-
-       e->pattern = strdup(line + argpos(line, 1));
-       trim(e->pattern);
-       list_add(&e->list, &expects);
-}
-
-static void do_dir(unsigned int handle, char *path)
-{
-       char **entries;
-       unsigned int i, num;
-
-       entries = xs_directory(handles[handle], txh[handle], path, &num);
-       if (!entries) {
-               failed(handle);
-               return;
-       }
-
-       for (i = 0; i < num; i++)
-               if (handle)
-                       output("%i:%s\n", handle, entries[i]);
-               else
-                       output("%s\n", entries[i]);
-       free(entries);
-}
-
-static void do_read(unsigned int handle, char *path)
-{
-       char *value;
-       unsigned int len;
-
-       value = xs_read(handles[handle], txh[handle], path, &len);
-       if (!value) {
-               failed(handle);
-               return;
-       }
-
-       /* It's supposed to nul terminate for us. */
-       assert(value[len] == '\0');
-       if (handle)
-               output("%i:%.*s\n", handle, len, value);
-       else
-               output("%.*s\n", len, value);
-}
-
-static void do_write(unsigned int handle, char *path, char *data)
-{
-       if (!xs_write(handles[handle], txh[handle], path, data, strlen(data)))
-               failed(handle);
-}
-
-static void do_setid(unsigned int handle, char *id)
-{
-       if (!xs_bool(xs_debug_command(handles[handle], "setid", id,
-                                     strlen(id)+1)))
-               failed(handle);
-}
-
-static void do_mkdir(unsigned int handle, char *path)
-{
-       if (!xs_mkdir(handles[handle], txh[handle], path))
-               failed(handle);
-}
-
-static void do_rm(unsigned int handle, char *path)
-{
-       if (!xs_rm(handles[handle], txh[handle], path))
-               failed(handle);
-}
-
-static void do_getperm(unsigned int handle, char *path)
-{
-       unsigned int i, num;
-       struct xs_permissions *perms;
-
-       perms = xs_get_permissions(handles[handle], txh[handle], path, &num);
-       if (!perms) {
-               failed(handle);
-               return;
-       }
-
-       for (i = 0; i < num; i++) {
-               char *permstring;
-
-               switch (perms[i].perms) {
-               case XS_PERM_NONE:
-                       permstring = "NONE";
-                       break;
-               case XS_PERM_WRITE:
-                       permstring = "WRITE";
-                       break;
-               case XS_PERM_READ:
-                       permstring = "READ";
-                       break;
-               case XS_PERM_READ|XS_PERM_WRITE:
-                       permstring = "READ/WRITE";
-                       break;
-               default:
-                       barf("bad perm value %i", perms[i].perms);
-               }
-
-               if (handle)
-                       output("%i:%i %s\n", handle, perms[i].id, permstring);
-               else
-                       output("%i %s\n", perms[i].id, permstring);
-       }
-       free(perms);
-}
-
-static void do_setperm(unsigned int handle, char *path, char *line)
-{
-       unsigned int i;
-       struct xs_permissions perms[100];
-
-       strtok(line, " \t\n");
-       strtok(NULL, " \t\n");
-       for (i = 0; ; i++) {
-               char *arg = strtok(NULL, " \t\n");
-               if (!arg)
-                       break;
-               perms[i].id = atoi(arg);
-               arg = strtok(NULL, " \t\n");
-               if (!arg)
-                       break;
-               if (streq(arg, "WRITE"))
-                       perms[i].perms = XS_PERM_WRITE;
-               else if (streq(arg, "READ"))
-                       perms[i].perms = XS_PERM_READ;
-               else if (streq(arg, "READ/WRITE"))
-                       perms[i].perms = XS_PERM_READ|XS_PERM_WRITE;
-               else if (streq(arg, "NONE"))
-                       perms[i].perms = XS_PERM_NONE;
-               else
-                       barf("bad flags %s\n", arg);
-       }
-
-       if (!xs_set_permissions(handles[handle], txh[handle], path, perms, i))
-               failed(handle);
-}
-
-static void do_watch(unsigned int handle, const char *node, const char *token,
-                    bool swallow_event)
-{
-       if (!xs_watch(handles[handle], node, token))
-               failed(handle);
-
-       /* Convenient for testing... */
-       if (swallow_event) {
-               unsigned int num;
-               char **vec = xs_read_watch(handles[handle], &num);
-               if (!vec ||
-                   !streq(vec[XS_WATCH_PATH], node) ||
-                   !streq(vec[XS_WATCH_TOKEN], token))
-                       failed(handle);
-       }
-}
-
-static void set_timeout(void)
-{
-       struct itimerval timeout;
-
-       timeout.it_value.tv_sec = timeout_ms / 1000;
-       timeout.it_value.tv_usec = (timeout_ms * 1000) % 1000000;
-       timeout.it_interval.tv_sec = timeout.it_interval.tv_usec = 0;
-       setitimer(ITIMER_REAL, &timeout, NULL);
-}
-
-static void disarm_timeout(void)
-{
-       struct itimerval timeout;
-
-       timeout.it_value.tv_sec = 0;
-       timeout.it_value.tv_usec = 0;
-       setitimer(ITIMER_REAL, &timeout, NULL);
-}
-
-static void do_waitwatch(unsigned int handle)
-{
-       char **vec;
-       struct timeval tv = {.tv_sec = timeout_ms/1000,
-                            .tv_usec = (timeout_ms*1000)%1000000 };
-       fd_set set;
-       unsigned int num;
-
-       if (xs_fileno(handles[handle]) != -2) {
-               /* Manually select here so we can time out gracefully. */
-               FD_ZERO(&set);
-               FD_SET(xs_fileno(handles[handle]), &set);
-               disarm_timeout();
-               if (select(xs_fileno(handles[handle])+1, &set,
-                          NULL, NULL, &tv) == 0) {
-                       errno = ETIMEDOUT;
-                       failed(handle);
-                       return;
-               }
-               set_timeout();
-       }
-
-       vec = xs_read_watch(handles[handle], &num);
-       if (!vec) {
-               failed(handle);
-               return;
-       }
-
-       if (handle)
-               output("%i:%s:%s\n", handle,
-                      vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN]);
-       else
-               output("%s:%s\n", vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN]);
-       free(vec);
-}
-
-static void do_unwatch(unsigned int handle, const char *node, const char 
*token)
-{
-       if (!xs_unwatch(handles[handle], node, token))
-               failed(handle);
-}
-
-static void do_start(unsigned int handle)
-{
-       txh[handle] = xs_transaction_start(handles[handle]);
-       if (txh[handle] == XBT_NULL)
-               failed(handle);
-}
-
-static void do_end(unsigned int handle, bool abort)
-{
-       if (!xs_transaction_end(handles[handle], txh[handle], abort))
-               failed(handle);
-       txh[handle] = XBT_NULL;
-}
-
-static void do_introduce(unsigned int handle,
-                        const char *domid,
-                        const char *mfn,
-                        const char *eventchn,
-                        const char *path)
-{
-       unsigned int i;
-       int fd;
-
-       /* This mechanism is v. slow w. valgrind running. */
-       timeout_ms = 5000;
-
-       /* We poll, so ignore signal */
-       signal(SIGUSR2, SIG_IGN);
-       for (i = 0; i < ARRAY_SIZE(handles); i++)
-               if (!handles[i])
-                       break;
-
-       fd = open("/tmp/xcmap", O_RDWR);
-       /* Set shared comms page. */
-       interface = mmap(NULL, getpagesize(), PROT_WRITE|PROT_READ,
-                        MAP_SHARED,fd,0);
-       if (interface == MAP_FAILED)
-               barf_perror("Failed to map /tmp/xcmap page");
-       close(fd);
-
-       /* Tell them the event channel and our PID. */
-       *(int *)((void *)interface + 32) = getpid();
-       *(uint16_t *)((void *)interface + 36) = atoi(eventchn);
-
-       if (!xs_introduce_domain(handles[handle], atoi(domid),
-                                atol(mfn), atoi(eventchn))) {
-               failed(handle);
-               munmap(interface, getpagesize());
-               return;
-       }
-       output("handle is %i\n", i);
-
-       /* Create new handle. */
-       handles[i] = new(struct xs_handle);
-       handles[i]->fd = -2;
-
-       /* Read in daemon pid. */
-       daemon_pid = *(int *)((void *)interface + 32);
-}
-
-static void do_release(unsigned int handle, const char *domid)
-{
-       if (!xs_release_domain(handles[handle], atoi(domid)))
-               failed(handle);
-}
-
-static int strptrcmp(const void *a, const void *b)
-{
-       return strcmp(*(char **)a, *(char **)b);
-}
-
-static void sort_dir(char **dir, unsigned int num)
-{
-       qsort(dir, num, sizeof(char *), strptrcmp);
-}
-
-static void dump_dir(unsigned int handle,
-                    const char *node,
-                    char **dir,
-                    unsigned int numdirs,
-                    unsigned int depth)
-{
-       unsigned int i;
-       char spacing[depth+1];
-
-       memset(spacing, ' ', depth);
-       spacing[depth] = '\0';
-
-       sort_dir(dir, numdirs);
-
-       for (i = 0; i < numdirs; i++) {
-               struct xs_permissions *perms;
-               unsigned int j, numperms;
-               unsigned int len;
-               char *contents;
-               unsigned int subnum;
-               char **subdirs;
-               char subnode[strlen(node) + 1 + strlen(dir[i]) + 1];
-
-               sprintf(subnode, "%s/%s", node, dir[i]);
-
-               perms = xs_get_permissions(handles[handle], txh[handle],
-                                          subnode,&numperms);
-               if (!perms) {
-                       failed(handle);
-                       return;
-               }
-
-               output("%s%s: ", spacing, dir[i]);
-               for (j = 0; j < numperms; j++) {
-                       char buffer[100];
-                       if (!xs_perm_to_string(&perms[j], buffer))
-                               barf("perm to string");
-                       output("%s ", buffer);
-               }
-               free(perms);
-               output("\n");
-
-               /* Even directories can have contents. */
-               contents = xs_read(handles[handle], txh[handle], 
-                                  subnode, &len);
-               if (!contents) {
-                       if (errno != EISDIR)
-                               failed(handle);
-               } else {
-                       output(" %s(%.*s)\n", spacing, len, contents);
-                       free(contents);
-               }                       
-
-               /* Every node is a directory. */
-               subdirs = xs_directory(handles[handle], txh[handle], 
-                                      subnode, &subnum);
-               if (!subdirs) {
-                       failed(handle);
-                       return;
-               }
-               dump_dir(handle, subnode, subdirs, subnum, depth+1);
-               free(subdirs);
-       }
-}
-
-static void dump(int handle)
-{
-       char **subdirs;
-       unsigned int subnum;
-
-       subdirs = xs_directory(handles[handle], txh[handle], "/", &subnum);
-       if (!subdirs) {
-               failed(handle);
-               return;
-       }
-
-       dump_dir(handle, "", subdirs, subnum, 0);
-       free(subdirs);
-}
-
-static int handle;
-
-static void alarmed(int sig __attribute__((unused)))
-{
-       if (handle) {
-               char handlename[10];
-               sprintf(handlename, "%u:", handle);
-               write(STDOUT_FILENO, handlename, strlen(handlename));
-       }
-       write(STDOUT_FILENO, command, strlen(command));
-       write(STDOUT_FILENO, " timeout\n", strlen(" timeout\n"));
-       exit(1);
-}
-
-static void do_command(unsigned int default_handle, char *line)
-{
-       char *endp;
-
-       if (print_input)
-               printf("%i> %s", ++linenum, line);
-
-       if (strspn(line, " \n") == strlen(line))
-               return;
-       if (strstarts(line, "#"))
-               return;
-
-       handle = strtoul(line, &endp, 10);
-       if (endp != line)
-               memmove(line, endp+1, strlen(endp));
-       else
-               handle = default_handle;
-
-       command = arg(line, 0);
-       if (!handles[handle]) {
-               if (readonly)
-                       handles[handle] = xs_daemon_open_readonly();
-               else
-                       handles[handle] = xs_daemon_open();
-               if (!handles[handle])
-                       barf_perror("Opening connection to daemon");
-       }
-
-       if (!timeout_suppressed)
-               set_timeout();
-       timeout_suppressed = false;
-
-       if (streq(command, "dir"))
-               do_dir(handle, arg(line, 1));
-       else if (streq(command, "read"))
-               do_read(handle, arg(line, 1));
-       else if (streq(command, "write"))
-               do_write(handle, arg(line, 1), arg(line, 2));
-       else if (streq(command, "setid"))
-               do_setid(handle, arg(line, 1));
-       else if (streq(command, "mkdir"))
-               do_mkdir(handle, arg(line, 1));
-       else if (streq(command, "rm"))
-               do_rm(handle, arg(line, 1));
-       else if (streq(command, "getperm"))
-               do_getperm(handle, arg(line, 1));
-       else if (streq(command, "setperm"))
-               do_setperm(handle, arg(line, 1), line);
-       else if (streq(command, "watch"))
-               do_watch(handle, arg(line, 1), arg(line, 2), true);
-       else if (streq(command, "watchnoack"))
-               do_watch(handle, arg(line, 1), arg(line, 2), false);
-       else if (streq(command, "waitwatch"))
-               do_waitwatch(handle);
-       else if (streq(command, "unwatch"))
-               do_unwatch(handle, arg(line, 1), arg(line, 2));
-       else if (streq(command, "close")) {
-               xs_daemon_close(handles[handle]);
-               handles[handle] = NULL;
-               txh[handle] = XBT_NULL;
-       } else if (streq(command, "start"))
-               do_start(handle);
-       else if (streq(command, "commit"))
-               do_end(handle, false);
-       else if (streq(command, "abort"))
-               do_end(handle, true);
-       else if (streq(command, "introduce"))
-               do_introduce(handle, arg(line, 1), arg(line, 2),
-                            arg(line, 3), arg(line, 4));
-       else if (streq(command, "release"))
-               do_release(handle, arg(line, 1));
-       else if (streq(command, "dump"))
-               dump(handle);
-       else if (streq(command, "sleep")) {
-               disarm_timeout();
-               usleep(atoi(arg(line, 1)) * 1000);
-       } else if (streq(command, "expect"))
-               expect(line);
-       else if (streq(command, "notimeout"))
-               timeout_suppressed = true;
-       else if (streq(command, "readonly")) {
-               readonly = true;
-               xs_daemon_close(handles[handle]);
-               handles[handle] = NULL;
-       } else if (streq(command, "readwrite")) {
-               readonly = false;
-               xs_daemon_close(handles[handle]);
-               handles[handle] = NULL;
-       } else
-               barf("Unknown command %s", command);
-       fflush(stdout);
-       disarm_timeout();
-
-       /* Check expectations. */
-       if (!streq(command, "expect")) {
-               struct expect *i = list_top(&expects, struct expect, list);
-
-               if (i)
-                       barf("Expected '%s', didn't happen\n", i->pattern);
-       }
-}
-
-static struct option options[] = { { "readonly", 0, NULL, 'r' },
-                                  { "no-timeout", 0, NULL, 't' },
-                                  { NULL, 0, NULL, 0 } };
-
-int main(int argc, char *argv[])
-{
-       int opt;
-       char line[1024];
-
-       while ((opt = getopt_long(argc, argv, "xrt", options, NULL)) != -1) {
-               switch (opt) {
-               case 'r':
-                       readonly = true;
-                       break;
-               case 't':
-                       timeout_ms = 0;
-                       break;
-               case 'x':
-                       print_input = true;
-                       break;
-               }
-       }
-
-       if (optind + 1 == argc) {
-               int fd = open(argv[optind], O_RDONLY);
-               if (!fd)
-                       barf_perror("Opening %s", argv[optind]);
-               dup2(fd, STDIN_FILENO);
-       } else if (optind != argc)
-               usage();
-       
-
-       signal(SIGALRM, alarmed);
-       while (fgets(line, sizeof(line), stdin))
-               do_command(0, line);
-
-       return 0;
-}
-
-/*
- * Local variables:
- *  c-file-style: "linux"
- *  indent-tabs-mode: t
- *  c-indent-level: 8
- *  c-basic-offset: 8
- *  tab-width: 8
- * End:
- */

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] xenstore: Remove broken and unmaintained test code., Xen patchbot-unstable <=