direct-io.hg

changeset 15462:eb71f258e855

xenstore: Remove broken and unmaintained test code.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Tue Jul 03 15:51:59 2007 +0100 (2007-07-03)
parents 0528bc25c404
children 56da8753ba8d
files tools/xenstore/Makefile tools/xenstore/fake_libxc.c tools/xenstore/speedtest.c tools/xenstore/testsuite/01simple.test tools/xenstore/testsuite/02directory.test tools/xenstore/testsuite/03write.test tools/xenstore/testsuite/04rm.test tools/xenstore/testsuite/05filepermissions.test tools/xenstore/testsuite/06dirpermissions.test tools/xenstore/testsuite/07watch.test tools/xenstore/testsuite/08transaction.slowtest tools/xenstore/testsuite/08transaction.test tools/xenstore/testsuite/09domain.test tools/xenstore/testsuite/10domain-homedir.test tools/xenstore/testsuite/11domain-watch.test tools/xenstore/testsuite/12readonly.test tools/xenstore/testsuite/13watch-ack.test tools/xenstore/testsuite/14complexperms.test tools/xenstore/testsuite/test.sh tools/xenstore/testsuite/vg-suppressions tools/xenstore/xenstored_core.c tools/xenstore/xenstored_domain.c tools/xenstore/xenstored_test.h tools/xenstore/xenstored_transaction.c tools/xenstore/xenstored_watch.c tools/xenstore/xs_crashme.c tools/xenstore/xs_random.c tools/xenstore/xs_stress.c tools/xenstore/xs_test.c
line diff
     1.1 --- a/tools/xenstore/Makefile	Tue Jul 03 15:49:16 2007 +0100
     1.2 +++ b/tools/xenstore/Makefile	Tue Jul 03 15:51:59 2007 +0100
     1.3 @@ -11,15 +11,11 @@ BASECFLAGS=-Werror
     1.4  BASECFLAGS += -Wp,-MD,.$(@F).d
     1.5  PROG_DEP = .*.d
     1.6  BASECFLAGS+= $(PROFILE)
     1.7 -#BASECFLAGS+= -I$(XEN_ROOT)/tools
     1.8  BASECFLAGS+= -I$(XEN_ROOT)/tools/libxc
     1.9  BASECFLAGS+= -I.
    1.10  
    1.11  CFLAGS  += $(BASECFLAGS)
    1.12  LDFLAGS += $(PROFILE) -L$(XEN_LIBXC)
    1.13 -TESTDIR  = testsuite/tmp
    1.14 -TESTFLAGS= -DTESTING
    1.15 -TESTENV  = XENSTORED_ROOTDIR=$(TESTDIR) XENSTORED_RUNDIR=$(TESTDIR)
    1.16  
    1.17  CLIENTS := xenstore-exists xenstore-list xenstore-read xenstore-rm xenstore-chmod
    1.18  CLIENTS += xenstore-write
    1.19 @@ -35,12 +31,6 @@ XENSTORED_OBJS += $(XENSTORED_OBJS_y)
    1.20  .PHONY: all
    1.21  all: libxenstore.so libxenstore.a xenstored $(CLIENTS) xs_tdb_dump xenstore-control xenstore-ls
    1.22  
    1.23 -test_interleaved_transactions: test_interleaved_transactions.o
    1.24 -	$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
    1.25 -
    1.26 -.PHONY: testcode
    1.27 -testcode: xs_test xenstored_test xs_random
    1.28 -
    1.29  xenstored: $(XENSTORED_OBJS)
    1.30  	$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl $(SOCKET_LIBS) -o $@
    1.31  
    1.32 @@ -56,35 +46,9 @@ xenstore-control: xenstore_control.o lib
    1.33  xenstore-ls: xsls.o libxenstore.so
    1.34  	$(CC) $(CFLAGS) $(LDFLAGS) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore $(SOCKET_LIBS) -o $@
    1.35  
    1.36 -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
    1.37 -	$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
    1.38 -
    1.39  xs_tdb_dump: xs_tdb_dump.o utils.o tdb.o talloc.o
    1.40  	$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
    1.41  
    1.42 -xs_test xs_random xs_stress xs_crashme: LDFLAGS+=-lpthread
    1.43 -xs_test: xs_test.o xs_lib.o utils.o
    1.44 -xs_random: xs_random.o xs_test_lib.o xs_lib.o talloc.o utils.o
    1.45 -xs_stress: xs_stress.o xs_test_lib.o xs_lib.o talloc.o utils.o
    1.46 -xs_crashme: xs_crashme.o xs_lib.o talloc.o utils.o
    1.47 -
    1.48 -speedtest: speedtest.o xs.o xs_lib.o utils.o talloc.o
    1.49 -
    1.50 -.PHONY: check-speed
    1.51 -check-speed: speedtest xenstored_test $(TESTDIR)
    1.52 -	$(TESTENV) time ./speedtest 100
    1.53 -
    1.54 -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)
    1.55 -
    1.56 -xenstored_%_test.o: xenstored_%.c
    1.57 -	$(COMPILE.c) -o $@ $<
    1.58 -
    1.59 -xs_test_lib.o: xs.c
    1.60 -	$(COMPILE.c) -o $@ $<
    1.61 -
    1.62 -talloc_test.o: talloc.c
    1.63 -	$(COMPILE.c) -o $@ $<
    1.64 -
    1.65  libxenstore.so: libxenstore.so.$(MAJOR)
    1.66  	ln -sf $< $@
    1.67  libxenstore.so.$(MAJOR): libxenstore.so.$(MAJOR).$(MINOR)
    1.68 @@ -97,67 +61,13 @@ libxenstore.a: xs.o xs_lib.o
    1.69  	$(AR) rcs libxenstore.a $^
    1.70  
    1.71  .PHONY: clean
    1.72 -clean: testsuite-clean
    1.73 +clean:
    1.74  	rm -f *.a *.o *.opic *.so*
    1.75  	rm -f xenstored xs_random xs_stress xs_crashme
    1.76 -	rm -f xs_test xenstored_test xs_tdb_dump xenstore-control xenstore-ls
    1.77 +	rm -f xs_tdb_dump xenstore-control xenstore-ls
    1.78  	rm -f $(CLIENTS)
    1.79  	$(RM) $(PROG_DEP)
    1.80  
    1.81 -.PHONY: print-dir
    1.82 -print-dir:
    1.83 -	@echo -n tools/xenstore: 
    1.84 -
    1.85 -.PHONY: print-end
    1.86 -print-end:
    1.87 -	@echo
    1.88 -
    1.89 -.PHONY: check
    1.90 -check: print-dir testsuite-fast randomcheck-fast print-end
    1.91 -
    1.92 -.PHONY: fullcheck
    1.93 -fullcheck: testsuite-run randomcheck stresstest
    1.94 -
    1.95 -$(TESTDIR):
    1.96 -	mkdir $@
    1.97 -
    1.98 -.PHONY: testsuite-run
    1.99 -testsuite-run: xenstored_test xs_test $(TESTDIR)
   1.100 -	$(TESTENV) testsuite/test.sh && echo
   1.101 -
   1.102 -.PHONY: testsuite-fast
   1.103 -testsuite-fast: xenstored_test xs_test $(TESTDIR)
   1.104 -	@$(TESTENV) testsuite/test.sh --fast
   1.105 -
   1.106 -.PHONY: testsuite-clean
   1.107 -testsuite-clean:
   1.108 -	rm -rf $(TESTDIR)
   1.109 -
   1.110 -# Make this visible so they can see repeat tests without --fast if they
   1.111 -# fail.
   1.112 -RANDSEED=$(shell date +%s)
   1.113 -.PHONY: randomcheck
   1.114 -randomcheck: xs_random xenstored_test $(TESTDIR)
   1.115 -	$(TESTENV) ./xs_random --simple --fast /tmp/xs_random 200000 $(RANDSEED) && echo
   1.116 -	$(TESTENV) ./xs_random --fast /tmp/xs_random 100000 $(RANDSEED) && echo
   1.117 -#	$(TESTENV) ./xs_random --fail /tmp/xs_random 10000 $(RANDSEED)
   1.118 -
   1.119 -.PHONY: crashme
   1.120 -crashme:  xs_crashme xenstored_test $(TESTDIR)
   1.121 -	rm -rf $(TESTDIR)/store $(TESTDIR)/transactions /tmp/xs_crashme.vglog* /tmp/trace
   1.122 -	export $(TESTENV); ./xs_crashme 5000 $(RANDSEED) 2>/dev/null
   1.123 -	if [ -n "`cat /tmp/xs_crashme.vglog*`" ]; then echo Valgrind complained; cat /tmp/xs_crashme.vglog*; exit 1; fi
   1.124 -	rm -rf $(TESTDIR)/store $(TESTDIR)/transactions /tmp/xs_crashme.vglog* /tmp/trace
   1.125 -
   1.126 -.PHONY: randomcheck-fast
   1.127 -randomcheck-fast: xs_random xenstored_test $(TESTDIR)
   1.128 -	@$(TESTENV) ./xs_random --fast /tmp/xs_random 2000 $(RANDSEED)
   1.129 -
   1.130 -.PHONY: stresstest
   1.131 -stresstest: xs_stress xenstored_test $(TESTDIR)
   1.132 -	rm -rf $(TESTDIR)/store $(TESTDIR)/transactions
   1.133 -	export $(TESTENV); PID=`./xenstored_test --output-pid --trace-file=/tmp/trace`; ./xs_stress 5000; ret=$$?; kill $$PID; exit $$ret
   1.134 -
   1.135  .PHONY: TAGS
   1.136  TAGS:
   1.137  	etags `find . -name '*.[ch]'`
     2.1 --- a/tools/xenstore/fake_libxc.c	Tue Jul 03 15:49:16 2007 +0100
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,143 +0,0 @@
     2.4 -/* 
     2.5 -    Fake libxc which doesn't require hypervisor but talks to xs_test.
     2.6 -    Copyright (C) 2005 Rusty Russell IBM Corporation
     2.7 -
     2.8 -    This program is free software; you can redistribute it and/or modify
     2.9 -    it under the terms of the GNU General Public License as published by
    2.10 -    the Free Software Foundation; either version 2 of the License, or
    2.11 -    (at your option) any later version.
    2.12 -
    2.13 -    This program is distributed in the hope that it will be useful,
    2.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.16 -    GNU General Public License for more details.
    2.17 -
    2.18 -    You should have received a copy of the GNU General Public License
    2.19 -    along with this program; if not, write to the Free Software
    2.20 -    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2.21 -*/
    2.22 -
    2.23 -#include <stdio.h>
    2.24 -#include <stdlib.h>
    2.25 -#include <sys/types.h>
    2.26 -#include <sys/stat.h>
    2.27 -#include <fcntl.h>
    2.28 -#include <sys/mman.h>
    2.29 -#include <unistd.h>
    2.30 -#include <assert.h>
    2.31 -#include <signal.h>
    2.32 -#include "utils.h"
    2.33 -#include "xenstored_core.h"
    2.34 -#include "xenstored_domain.h"
    2.35 -#include "xenstored_test.h"
    2.36 -#include <xenctrl.h>
    2.37 -
    2.38 -static int sigfd;
    2.39 -static int xs_test_pid;
    2.40 -static evtchn_port_t port;
    2.41 -
    2.42 -/* The event channel maps to a signal, shared page to an mmapped file. */
    2.43 -void xc_evtchn_notify(int xce_handle, int local_port)
    2.44 -{
    2.45 -	assert(local_port == port);
    2.46 -	if (kill(xs_test_pid, SIGUSR2) != 0)
    2.47 -		barf_perror("fake event channel failed");
    2.48 -}
    2.49 -
    2.50 -void *xc_map_foreign_range(int xc_handle, uint32_t dom __attribute__((unused)),
    2.51 -			   int size, int prot,
    2.52 -			   unsigned long mfn __attribute__((unused)))
    2.53 -{
    2.54 -	void *ret;
    2.55 -
    2.56 -	ret = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0);
    2.57 -	if (ret == MAP_FAILED)
    2.58 -		return NULL;
    2.59 -
    2.60 -	/* xs_test tells us pid and port by putting it in buffer, we reply. */
    2.61 -	xs_test_pid = *(int *)(ret + 32);
    2.62 -	port = *(int *)(ret + 36);
    2.63 -	*(int *)(ret + 32) = getpid();
    2.64 -	return ret;
    2.65 -}
    2.66 -
    2.67 -int xc_interface_open(void)
    2.68 -{
    2.69 -	int fd;
    2.70 -	char page[getpagesize()];
    2.71 -
    2.72 -	fd = open("/tmp/xcmap", O_RDWR|O_CREAT|O_TRUNC, 0600);
    2.73 -	if (fd < 0)
    2.74 -		return fd;
    2.75 -
    2.76 -	memset(page, 0, sizeof(page));
    2.77 -	if (!xs_write_all(fd, page, sizeof(page)))
    2.78 -		barf_perror("Failed to write /tmp/xcmap page");
    2.79 -	
    2.80 -	return fd;
    2.81 -}
    2.82 -
    2.83 -int xc_interface_close(int xc_handle)
    2.84 -{
    2.85 -	close(xc_handle);
    2.86 -	return 0;
    2.87 -}
    2.88 -
    2.89 -int xc_domain_getinfo(int xc_handle __attribute__((unused)),
    2.90 -		      uint32_t first_domid, unsigned int max_doms,
    2.91 -                      xc_dominfo_t *info)
    2.92 -{
    2.93 -	assert(max_doms == 1);
    2.94 -        info->domid = first_domid;
    2.95 -
    2.96 -        info->dying    = 0;
    2.97 -        info->shutdown = 0;
    2.98 -        info->paused   = 0;
    2.99 -        info->blocked  = 0;
   2.100 -        info->running  = 1;
   2.101 -
   2.102 -        info->shutdown_reason = 0;
   2.103 -
   2.104 -        if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) )
   2.105 -        {
   2.106 -            info->shutdown = 0;
   2.107 -            info->crashed  = 1;
   2.108 -        }
   2.109 -
   2.110 -	return 1;
   2.111 -}
   2.112 -
   2.113 -static void send_to_fd(int signo __attribute__((unused)))
   2.114 -{
   2.115 -	int saved_errno = errno;
   2.116 -	write(sigfd, &port, sizeof(port));
   2.117 -	errno = saved_errno;
   2.118 -}
   2.119 -
   2.120 -void fake_block_events(void)
   2.121 -{
   2.122 -	signal(SIGUSR2, SIG_IGN);
   2.123 -}
   2.124 -
   2.125 -void fake_ack_event(void)
   2.126 -{
   2.127 -	signal(SIGUSR2, send_to_fd);
   2.128 -}
   2.129 -
   2.130 -int xc_evtchn_open(void)
   2.131 -{
   2.132 -	int fds[2];
   2.133 -
   2.134 -	if (pipe(fds) != 0)
   2.135 -		return -1;
   2.136 -
   2.137 -	if (signal(SIGUSR2, send_to_fd) == SIG_ERR) {
   2.138 -		int saved_errno = errno;
   2.139 -		close(fds[0]);
   2.140 -		close(fds[1]);
   2.141 -		errno = saved_errno;
   2.142 -		return -1;
   2.143 -	}
   2.144 -	sigfd = fds[1];
   2.145 -	return fds[0];
   2.146 -}
     3.1 --- a/tools/xenstore/speedtest.c	Tue Jul 03 15:49:16 2007 +0100
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,130 +0,0 @@
     3.4 -/* 
     3.5 -    Xen Store Daemon Speed test
     3.6 -    Copyright (C) 2005 Rusty Russell IBM Corporation
     3.7 -
     3.8 -    This program is free software; you can redistribute it and/or modify
     3.9 -    it under the terms of the GNU General Public License as published by
    3.10 -    the Free Software Foundation; either version 2 of the License, or
    3.11 -    (at your option) any later version.
    3.12 -
    3.13 -    This program is distributed in the hope that it will be useful,
    3.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.16 -    GNU General Public License for more details.
    3.17 -
    3.18 -    You should have received a copy of the GNU General Public License
    3.19 -    along with this program; if not, write to the Free Software
    3.20 -    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    3.21 -*/
    3.22 -
    3.23 -#include <stdlib.h>
    3.24 -#include <sys/types.h>
    3.25 -#include <sys/wait.h>
    3.26 -#include <stdio.h>
    3.27 -#include <stdarg.h>
    3.28 -#include <unistd.h>
    3.29 -#include <fcntl.h>
    3.30 -#include <errno.h>
    3.31 -#include "utils.h"
    3.32 -#include "xs.h"
    3.33 -#include "list.h"
    3.34 -#include "talloc.h"
    3.35 -
    3.36 -static void do_command(const char *cmd)
    3.37 -{
    3.38 -	int ret;
    3.39 -
    3.40 -	ret = system(cmd);
    3.41 -	if (ret == -1 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
    3.42 -		barf_perror("Failed '%s': %i", cmd, ret);
    3.43 -}
    3.44 -
    3.45 -static int start_daemon(void)
    3.46 -{
    3.47 -	int fds[2], pid;
    3.48 -
    3.49 -	do_command(talloc_asprintf(NULL, "rm -rf testsuite/tmp/*"));
    3.50 -
    3.51 -	/* Start daemon. */
    3.52 -	pipe(fds);
    3.53 -	if ((pid = fork())) {
    3.54 -		/* Child writes PID when its ready: we wait for that. */
    3.55 -		char buffer[20];
    3.56 -		close(fds[1]);
    3.57 -		if (read(fds[0], buffer, sizeof(buffer)) < 0)
    3.58 -			barf("Failed to summon daemon");
    3.59 -		close(fds[0]);
    3.60 -	} else {
    3.61 -		dup2(fds[1], STDOUT_FILENO);
    3.62 -		close(fds[0]);
    3.63 -#if 0
    3.64 -		execlp("valgrind", "valgrind", "-q", "--suppressions=testsuite/vg-suppressions", "xenstored_test", "--output-pid",
    3.65 -		       "--no-fork", "--trace-file=/tmp/trace", NULL);
    3.66 -#else
    3.67 -		execlp("./xenstored_test", "xenstored_test", "--output-pid", "--no-fork", NULL);
    3.68 -//		execlp("strace", "strace", "-o", "/tmp/out", "./xenstored_test", "--output-pid", "--no-fork", NULL);
    3.69 -#endif
    3.70 -		exit(1);
    3.71 -	}
    3.72 -	return pid;
    3.73 -}
    3.74 -
    3.75 -static void kill_daemon(int pid)
    3.76 -{
    3.77 -	int saved_errno = errno;
    3.78 -	kill(pid, SIGTERM);
    3.79 -	errno = saved_errno;
    3.80 -}
    3.81 -
    3.82 -#define NUM_ENTRIES 50
    3.83 -
    3.84 -/* We create the given number of trees, each with NUM_ENTRIES, using
    3.85 - * transactions. */
    3.86 -int main(int argc, char *argv[])
    3.87 -{
    3.88 -	int i, j, pid, print;
    3.89 -	struct xs_handle *h;
    3.90 -
    3.91 -	if (argc != 2)
    3.92 -		barf("Usage: speedtest <numdomains>");
    3.93 -
    3.94 -	pid = start_daemon();
    3.95 -	h = xs_daemon_open();
    3.96 -	print = atoi(argv[1]) / 76;
    3.97 -	if (!print)
    3.98 -		print = 1;
    3.99 -	for (i = 0; i < atoi(argv[1]); i ++) {
   3.100 -		char name[64];
   3.101 -
   3.102 -		if (i % print == 0)
   3.103 -			write(1, ".", 1);
   3.104 -		if (!xs_transaction_start(h)) {
   3.105 -			kill_daemon(pid);
   3.106 -			barf_perror("Starting transaction");
   3.107 -		}
   3.108 -		sprintf(name, "/%i", i);
   3.109 -		if (!xs_mkdir(h, name)) {
   3.110 -			kill_daemon(pid);
   3.111 -			barf_perror("Making directory %s", name);
   3.112 -		}
   3.113 -
   3.114 -		for (j = 0; j < NUM_ENTRIES; j++) {
   3.115 -			sprintf(name, "/%i/%i", i, j);
   3.116 -			if (!xs_write(h, name, name, strlen(name))) {
   3.117 -				kill_daemon(pid);
   3.118 -				barf_perror("Making directory %s", name);
   3.119 -			}
   3.120 -		}
   3.121 -		if (!xs_transaction_end(h, false)) {
   3.122 -			kill_daemon(pid);
   3.123 -			barf_perror("Ending transaction");
   3.124 -		}
   3.125 -	}
   3.126 -	write(1, "\n", 1);
   3.127 -
   3.128 -	kill_daemon(pid);
   3.129 -	wait(NULL);
   3.130 -	return 0;
   3.131 -}
   3.132 -	
   3.133 -	
     4.1 --- a/tools/xenstore/testsuite/01simple.test	Tue Jul 03 15:49:16 2007 +0100
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,4 +0,0 @@
     4.4 -# Create an entry, read it.
     4.5 -write /test contents
     4.6 -expect contents
     4.7 -read /test
     5.1 --- a/tools/xenstore/testsuite/02directory.test	Tue Jul 03 15:49:16 2007 +0100
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,45 +0,0 @@
     5.4 -# Root directory has only tool dir in it.
     5.5 -expect tool
     5.6 -dir /
     5.7 -
     5.8 -# Create a file.
     5.9 -write /test contents
    5.10 -
    5.11 -# Directory shows it.
    5.12 -expect test
    5.13 -expect tool
    5.14 -dir /
    5.15 -
    5.16 -# Make a new directory, check it's there
    5.17 -mkdir /dir
    5.18 -expect dir
    5.19 -expect test
    5.20 -expect tool
    5.21 -dir /
    5.22 -
    5.23 -# Check it's empty.
    5.24 -dir /dir
    5.25 -
    5.26 -# Create a file, check it exists.
    5.27 -write /dir/test2 contents2
    5.28 -expect test2
    5.29 -dir /dir
    5.30 -expect contents2
    5.31 -read /dir/test2
    5.32 -
    5.33 -# Creating dir over the top should succeed.
    5.34 -mkdir /dir
    5.35 -mkdir /dir/test2
    5.36 -
    5.37 -# Mkdir implicitly creates directories.
    5.38 -mkdir /dir/1/2/3/4
    5.39 -expect test2
    5.40 -expect 1
    5.41 -dir /dir
    5.42 -expect 2
    5.43 -dir /dir/1
    5.44 -expect 3
    5.45 -dir /dir/1/2
    5.46 -expect 4
    5.47 -dir /dir/1/2/3
    5.48 -dir /dir/1/2/3/4
     6.1 --- a/tools/xenstore/testsuite/03write.test	Tue Jul 03 15:49:16 2007 +0100
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,28 +0,0 @@
     6.4 -# Write succeeds
     6.5 -write /test contents
     6.6 -expect contents
     6.7 -read /test
     6.8 -
     6.9 -# Overwrite succeeds.
    6.10 -write /test contents2
    6.11 -expect contents2
    6.12 -read /test
    6.13 -
    6.14 -# Write should implicitly create directories
    6.15 -write /dir/test contents
    6.16 -expect test
    6.17 -dir /dir
    6.18 -expect contents
    6.19 -read /dir/test
    6.20 -write /dir/1/2/3/4 contents4
    6.21 -expect test
    6.22 -expect 1
    6.23 -dir /dir
    6.24 -expect 2
    6.25 -dir /dir/1
    6.26 -expect 3
    6.27 -dir /dir/1/2
    6.28 -expect 4
    6.29 -dir /dir/1/2/3
    6.30 -expect contents4
    6.31 -read /dir/1/2/3/4
     7.1 --- a/tools/xenstore/testsuite/04rm.test	Tue Jul 03 15:49:16 2007 +0100
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,20 +0,0 @@
     7.4 -# Remove non-existant is OK, as long as parent exists
     7.5 -rm /test
     7.6 -expect rm failed: No such file or directory
     7.7 -rm /dir/test
     7.8 -
     7.9 -# Create file and remove it
    7.10 -write /test contents
    7.11 -rm /test
    7.12 -expect tool
    7.13 -dir /
    7.14 -
    7.15 -# Create directory and remove it.
    7.16 -mkdir /dir
    7.17 -rm /dir
    7.18 -
    7.19 -# Create directory, create file, remove all.
    7.20 -mkdir /dir
    7.21 -write /dir/test contents
    7.22 -rm /dir
    7.23 -
     8.1 --- a/tools/xenstore/testsuite/05filepermissions.test	Tue Jul 03 15:49:16 2007 +0100
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,81 +0,0 @@
     8.4 -# Fail to get perms on non-existent file.
     8.5 -expect getperm failed: No such file or directory
     8.6 -getperm /test
     8.7 -expect getperm failed: No such file or directory
     8.8 -getperm /dir/test
     8.9 -
    8.10 -# Create file: inherits from root (0 READ)
    8.11 -write /test contents
    8.12 -expect 0 READ
    8.13 -getperm /test
    8.14 -setid 1
    8.15 -expect 0 READ
    8.16 -getperm /test
    8.17 -expect contents
    8.18 -read /test
    8.19 -expect write failed: Permission denied
    8.20 -write /test contents
    8.21 -
    8.22 -# Take away read access to file.
    8.23 -setid 0
    8.24 -setperm /test 0 NONE
    8.25 -setid 1
    8.26 -expect getperm failed: Permission denied
    8.27 -getperm /test
    8.28 -expect read failed: Permission denied
    8.29 -read /test
    8.30 -expect write failed: Permission denied
    8.31 -write /test contents
    8.32 -
    8.33 -# Grant everyone write access to file.
    8.34 -setid 0
    8.35 -setperm /test 0 WRITE
    8.36 -setid 1
    8.37 -expect getperm failed: Permission denied
    8.38 -getperm /test
    8.39 -expect read failed: Permission denied
    8.40 -read /test
    8.41 -write /test contents2
    8.42 -setid 0
    8.43 -expect contents2
    8.44 -read /test
    8.45 -
    8.46 -# Grant everyone both read and write access.
    8.47 -setperm /test 0 READ/WRITE
    8.48 -setid 1
    8.49 -expect 0 READ/WRITE
    8.50 -getperm /test
    8.51 -expect contents2
    8.52 -read /test
    8.53 -write /test contents3
    8.54 -expect contents3
    8.55 -read /test
    8.56 -
    8.57 -# Change so that user 1 owns it, noone else can do anything.
    8.58 -setid 0
    8.59 -setperm /test 1 NONE
    8.60 -setid 1
    8.61 -expect 1 NONE
    8.62 -getperm /test
    8.63 -expect contents3
    8.64 -read /test
    8.65 -write /test contents4
    8.66 -
    8.67 -# User 2 can do nothing.
    8.68 -setid 2
    8.69 -expect setperm failed: Permission denied
    8.70 -setperm /test 2 NONE
    8.71 -expect getperm failed: Permission denied
    8.72 -getperm /test
    8.73 -expect read failed: Permission denied
    8.74 -read /test
    8.75 -expect write failed: Permission denied
    8.76 -write /test contents4
    8.77 -
    8.78 -# Tools can always access things.
    8.79 -setid 0
    8.80 -expect 1 NONE
    8.81 -getperm /test
    8.82 -expect contents4
    8.83 -read /test
    8.84 -write /test contents5
     9.1 --- a/tools/xenstore/testsuite/06dirpermissions.test	Tue Jul 03 15:49:16 2007 +0100
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,119 +0,0 @@
     9.4 -# Root directory: owned by tool, everyone has read access.
     9.5 -expect 0 READ
     9.6 -getperm /
     9.7 -
     9.8 -# Create directory: inherits from root.
     9.9 -mkdir /dir
    9.10 -expect 0 READ
    9.11 -getperm /dir
    9.12 -setid 1
    9.13 -expect 0 READ
    9.14 -getperm /dir
    9.15 -dir /dir
    9.16 -expect write failed: Permission denied
    9.17 -write /dir/test contents2
    9.18 -
    9.19 -# Remove everyone's read access to directoy.
    9.20 -setid 0
    9.21 -setperm /dir 0 NONE
    9.22 -setid 1
    9.23 -expect dir failed: Permission denied
    9.24 -dir /dir
    9.25 -expect read failed: Permission denied
    9.26 -read /dir/test create contents2
    9.27 -expect write failed: Permission denied
    9.28 -write /dir/test contents2
    9.29 -
    9.30 -# Grant everyone write access to directory.
    9.31 -setid 0
    9.32 -setperm /dir 0 WRITE
    9.33 -setid 1
    9.34 -expect getperm failed: Permission denied
    9.35 -getperm /dir
    9.36 -expect dir failed: Permission denied
    9.37 -dir /dir
    9.38 -write /dir/test contents
    9.39 -setid 0
    9.40 -expect 1 WRITE
    9.41 -getperm /dir/test
    9.42 -setperm /dir/test 0 NONE
    9.43 -expect contents
    9.44 -read /dir/test
    9.45 -
    9.46 -# Grant everyone both read and write access.
    9.47 -setperm /dir 0 READ/WRITE
    9.48 -setid 1
    9.49 -expect 0 READ/WRITE
    9.50 -getperm /dir
    9.51 -expect test
    9.52 -dir /dir
    9.53 -write /dir/test2 contents
    9.54 -expect contents
    9.55 -read /dir/test2
    9.56 -setperm /dir/test2 1 NONE
    9.57 -
    9.58 -# Change so that user 1 owns it, noone else can do anything.
    9.59 -setid 0
    9.60 -setperm /dir 1 NONE
    9.61 -expect 1 NONE
    9.62 -getperm /dir
    9.63 -expect test
    9.64 -expect test2
    9.65 -dir /dir
    9.66 -write /dir/test3 contents
    9.67 -
    9.68 -# User 2 can do nothing.  Can't even tell if file exists.
    9.69 -setid 2
    9.70 -expect setperm failed: Permission denied
    9.71 -setperm /dir 2 NONE
    9.72 -expect getperm failed: Permission denied
    9.73 -getperm /dir
    9.74 -expect dir failed: Permission denied
    9.75 -dir /dir
    9.76 -expect read failed: Permission denied
    9.77 -read /dir/test
    9.78 -expect read failed: Permission denied
    9.79 -read /dir/test2
    9.80 -expect read failed: Permission denied
    9.81 -read /dir/test3
    9.82 -expect read failed: Permission denied
    9.83 -read /dir/test4
    9.84 -expect write failed: Permission denied
    9.85 -write /dir/test contents
    9.86 -expect write failed: Permission denied
    9.87 -write /dir/test4 contents
    9.88 -
    9.89 -# Tools can always access things.
    9.90 -setid 0
    9.91 -expect 1 NONE
    9.92 -getperm /dir
    9.93 -expect test
    9.94 -expect test2
    9.95 -expect test3
    9.96 -dir /dir
    9.97 -write /dir/test4 contents
    9.98 -
    9.99 -# Inherited by child.
   9.100 -mkdir /dir/subdir
   9.101 -expect 1 NONE
   9.102 -getperm /dir/subdir
   9.103 -write /dir/subfile contents
   9.104 -expect 1 NONE
   9.105 -getperm /dir/subfile
   9.106 -
   9.107 -# But for domains, they own it.
   9.108 -setperm /dir/subdir 2 READ/WRITE
   9.109 -expect 2 READ/WRITE
   9.110 -getperm /dir/subdir
   9.111 -setid 3
   9.112 -write /dir/subdir/subfile contents
   9.113 -expect 3 READ/WRITE
   9.114 -getperm /dir/subdir/subfile
   9.115 -
   9.116 -# Inheritence works through multiple directories, too.
   9.117 -write /dir/subdir/1/2/3/4 contents
   9.118 -expect 3 READ/WRITE
   9.119 -getperm /dir/subdir/1/2/3/4
   9.120 -mkdir /dir/subdir/a/b/c/d
   9.121 -expect 3 READ/WRITE
   9.122 -getperm /dir/subdir/a/b/c/d
    10.1 --- a/tools/xenstore/testsuite/07watch.test	Tue Jul 03 15:49:16 2007 +0100
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,176 +0,0 @@
    10.4 -# Watch something, write to it, check watch has fired.
    10.5 -write /test contents
    10.6 -
    10.7 -1 watch /test token
    10.8 -2 write /test contents2
    10.9 -expect 1:/test:token
   10.10 -1 waitwatch
   10.11 -1 close
   10.12 -
   10.13 -# Check that reads don't set it off.
   10.14 -1 watch /test token
   10.15 -expect 2:contents2
   10.16 -2 read /test
   10.17 -expect 1: waitwatch failed: Connection timed out
   10.18 -1 waitwatch
   10.19 -1 close
   10.20 -
   10.21 -# mkdir, setperm and rm should (also tests watching dirs)
   10.22 -mkdir /dir
   10.23 -1 watch /dir token
   10.24 -2 mkdir /dir/newdir
   10.25 -expect 1:/dir/newdir:token
   10.26 -1 waitwatch
   10.27 -2 setperm /dir/newdir 0 READ
   10.28 -expect 1:/dir/newdir:token
   10.29 -1 waitwatch
   10.30 -2 rm /dir/newdir
   10.31 -expect 1:/dir/newdir:token
   10.32 -1 waitwatch
   10.33 -1 close
   10.34 -2 close
   10.35 -
   10.36 -# Changed in b594bb976a743d509f1ffabb5bc698874ab90d8f
   10.37 -## We don't get a watch from our own commands.
   10.38 -#watch /dir token
   10.39 -#mkdir /dir/newdir
   10.40 -#expect waitwatch failed: Connection timed out
   10.41 -#waitwatch
   10.42 -#close
   10.43 -
   10.44 -# ignore watches while doing commands, should work.
   10.45 -watch /dir token
   10.46 -1 write /dir/test contents
   10.47 -expect contents
   10.48 -read /dir/test
   10.49 -expect /dir/test:token
   10.50 -waitwatch
   10.51 -close
   10.52 -
   10.53 -# watch priority test: all simultaneous
   10.54 -1 watch /dir token1
   10.55 -3 watch /dir token3
   10.56 -2 watch /dir token2
   10.57 -write /dir/test contents
   10.58 -expect 3:/dir/test:token3
   10.59 -3 waitwatch
   10.60 -expect 2:/dir/test:token2
   10.61 -2 waitwatch
   10.62 -expect 1:/dir/test:token1
   10.63 -1 waitwatch
   10.64 -1 close
   10.65 -2 close
   10.66 -3 close
   10.67 -
   10.68 -# If one dies (without acking), the other should still get ack.
   10.69 -1 watch /dir token1
   10.70 -2 watch /dir token2
   10.71 -write /dir/test contents
   10.72 -expect 2:/dir/test:token2
   10.73 -2 waitwatch
   10.74 -2 close
   10.75 -expect 1:/dir/test:token1
   10.76 -1 waitwatch
   10.77 -1 close
   10.78 -
   10.79 -# If one dies (without reading at all), the other should still get ack.
   10.80 -1 watch /dir token1
   10.81 -2 watch /dir token2
   10.82 -write /dir/test contents
   10.83 -2 close
   10.84 -expect 1:/dir/test:token1
   10.85 -1 waitwatch
   10.86 -1 close
   10.87 -2 close
   10.88 -
   10.89 -# unwatch
   10.90 -1 watch /dir token1
   10.91 -1 unwatch /dir token1
   10.92 -1 watch /dir token2
   10.93 -2 write /dir/test2 contents
   10.94 -expect 1:/dir/test2:token2
   10.95 -1 waitwatch
   10.96 -1 unwatch /dir token2
   10.97 -1 close
   10.98 -2 close
   10.99 -
  10.100 -# unwatch while watch pending.  Other watcher still gets the event.
  10.101 -1 watch /dir token1
  10.102 -2 watch /dir token2
  10.103 -write /dir/test contents
  10.104 -2 unwatch /dir token2
  10.105 -expect 1:/dir/test:token1
  10.106 -1 waitwatch
  10.107 -1 close
  10.108 -2 close
  10.109 -
  10.110 -# unwatch while watch pending.  Should clear this so we get next event.
  10.111 -1 watch /dir token1
  10.112 -write /dir/test contents
  10.113 -1 unwatch /dir token1
  10.114 -1 watch /dir/test token2
  10.115 -write /dir/test contents2
  10.116 -expect 1:/dir/test:token2
  10.117 -1 waitwatch
  10.118 -
  10.119 -# check we only get notified once.
  10.120 -1 watch /test token
  10.121 -2 write /test contents2
  10.122 -expect 1:/test:token
  10.123 -1 waitwatch
  10.124 -expect 1: waitwatch failed: Connection timed out
  10.125 -1 waitwatch
  10.126 -1 close
  10.127 -
  10.128 -# watches are queued in order.
  10.129 -1 watch / token
  10.130 -2 write /test1 contents
  10.131 -2 write /test2 contents
  10.132 -2 write /test3 contents
  10.133 -expect 1:/test1:token
  10.134 -1 waitwatch
  10.135 -expect 1:/test2:token
  10.136 -1 waitwatch
  10.137 -expect 1:/test3:token
  10.138 -1 waitwatch
  10.139 -1 close
  10.140 -
  10.141 -# Creation of subpaths should be covered correctly.
  10.142 -1 watch / token
  10.143 -2 write /test/subnode contents2
  10.144 -2 write /test/subnode/subnode contents2
  10.145 -expect 1:/test/subnode:token
  10.146 -1 waitwatch
  10.147 -expect 1:/test/subnode/subnode:token
  10.148 -1 waitwatch
  10.149 -expect 1: waitwatch failed: Connection timed out
  10.150 -1 waitwatch
  10.151 -1 close
  10.152 -
  10.153 -# Watch event must have happened before we registered interest.
  10.154 -1 watch / token
  10.155 -2 write /test/subnode contents2
  10.156 -1 watchnoack / token2 0
  10.157 -expect 1:/test/subnode:token
  10.158 -1 waitwatch
  10.159 -expect 1:/:token2
  10.160 -1 waitwatch
  10.161 -expect 1: waitwatch failed: Connection timed out
  10.162 -1 waitwatch
  10.163 -1 close
  10.164 -
  10.165 -# Rm fires notification on child.
  10.166 -1 watch /test/subnode token
  10.167 -2 rm /test
  10.168 -expect 1:/test/subnode:token
  10.169 -1 waitwatch
  10.170 -
  10.171 -# Watch should not double-send after we ack, even if we did something in between.
  10.172 -1 watch /test2 token
  10.173 -2 write /test2/foo contents2
  10.174 -expect 1:/test2/foo:token
  10.175 -1 waitwatch
  10.176 -expect 1:contents2
  10.177 -1 read /test2/foo
  10.178 -expect 1: waitwatch failed: Connection timed out
  10.179 -1 waitwatch
    11.1 --- a/tools/xenstore/testsuite/08transaction.slowtest	Tue Jul 03 15:49:16 2007 +0100
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,43 +0,0 @@
    11.4 -# Test transaction clashes.
    11.5 -
    11.6 -mkdir /test
    11.7 -write /test/entry1 contents
    11.8 -
    11.9 -# Start transaction, do read-only op, transaction succeeds
   11.10 -1 start
   11.11 -1 write /test/entry1 contents2
   11.12 -expect contents
   11.13 -read /test/entry1
   11.14 -1 commit
   11.15 -expect contents2
   11.16 -read /test/entry1
   11.17 -
   11.18 -# Start transaction, abort other transaction, transaction succeeds.
   11.19 -1 start
   11.20 -1 write /test/entry1 contents3
   11.21 -start
   11.22 -write /test/entry1 contents
   11.23 -abort
   11.24 -1 commit
   11.25 -expect contents3
   11.26 -read /test/entry1
   11.27 -
   11.28 -# Start transaction, do write op, transaction fails
   11.29 -1 start
   11.30 -1 write /test/entry1 contents4
   11.31 -write /test/entry1 contents
   11.32 -expect 1: commit failed: Resource temporarily unavailable
   11.33 -1 commit
   11.34 -expect contents
   11.35 -read /test/entry1
   11.36 -
   11.37 -# Start transaction, do other transaction, transaction fails
   11.38 -1 start
   11.39 -1 write /test/entry1 contents4
   11.40 -start
   11.41 -write /test/entry1 contents5
   11.42 -commit
   11.43 -expect 1: commit failed: Resource temporarily unavailable
   11.44 -1 commit
   11.45 -expect contents5
   11.46 -read /test/entry1
    12.1 --- a/tools/xenstore/testsuite/08transaction.test	Tue Jul 03 15:49:16 2007 +0100
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,92 +0,0 @@
    12.4 -# Test transactions.
    12.5 -
    12.6 -mkdir /test
    12.7 -
    12.8 -# Simple transaction: create a file inside transaction.
    12.9 -1 start
   12.10 -1 write /test/entry1 contents
   12.11 -2 dir /test
   12.12 -expect 1:entry1
   12.13 -1 dir /test
   12.14 -1 commit
   12.15 -expect 2:contents
   12.16 -2 read /test/entry1
   12.17 -
   12.18 -rm /test/entry1
   12.19 -
   12.20 -# Create a file and abort transaction.
   12.21 -1 start
   12.22 -1 write /test/entry1 contents
   12.23 -2 dir /test
   12.24 -expect 1:entry1
   12.25 -1 dir /test
   12.26 -1 abort
   12.27 -2 dir /test
   12.28 -
   12.29 -write /test/entry1 contents
   12.30 -# Delete in transaction, commit
   12.31 -1 start
   12.32 -1 rm /test/entry1
   12.33 -expect 2:entry1
   12.34 -2 dir /test
   12.35 -1 dir /test
   12.36 -1 commit
   12.37 -2 dir /test
   12.38 -
   12.39 -# Delete in transaction, abort.
   12.40 -write /test/entry1 contents
   12.41 -1 start
   12.42 -1 rm /test/entry1
   12.43 -expect 2:entry1
   12.44 -2 dir /test
   12.45 -1 dir /test
   12.46 -1 abort
   12.47 -expect 2:entry1
   12.48 -2 dir /test
   12.49 -
   12.50 -# Events inside transactions don't trigger watches until (successful) commit.
   12.51 -mkdir /test/dir
   12.52 -1 watch /test token
   12.53 -2 start
   12.54 -2 mkdir /test/dir/sub
   12.55 -expect 1: waitwatch failed: Connection timed out
   12.56 -1 waitwatch
   12.57 -2 close
   12.58 -1 close
   12.59 -
   12.60 -1 watch /test token
   12.61 -2 start
   12.62 -2 mkdir /test/dir/sub
   12.63 -2 abort
   12.64 -expect 1: waitwatch failed: Connection timed out
   12.65 -1 waitwatch
   12.66 -1 close
   12.67 -
   12.68 -1 watch /test token
   12.69 -2 start
   12.70 -2 mkdir /test/dir/sub
   12.71 -2 commit
   12.72 -expect 1:/test/dir/sub:token
   12.73 -1 waitwatch
   12.74 -1 close
   12.75 -
   12.76 -# Rm inside transaction works like rm outside: children get notified.
   12.77 -1 watch /test/dir/sub token
   12.78 -2 start
   12.79 -2 rm /test/dir
   12.80 -2 commit
   12.81 -expect 1:/test/dir/sub:token
   12.82 -1 waitwatch
   12.83 -1 close
   12.84 -
   12.85 -# Multiple events from single transaction don't trigger assert
   12.86 -1 watch /test token
   12.87 -2 start
   12.88 -2 write /test/1 contents
   12.89 -2 write /test/2 contents
   12.90 -2 commit
   12.91 -expect 1:/test/1:token
   12.92 -1 waitwatch
   12.93 -expect 1:/test/2:token
   12.94 -1 waitwatch
   12.95 -1 close
    13.1 --- a/tools/xenstore/testsuite/09domain.test	Tue Jul 03 15:49:16 2007 +0100
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,19 +0,0 @@
    13.4 -# Test domain communication.
    13.5 -
    13.6 -# Create a domain, write an entry.
    13.7 -expect handle is 1
    13.8 -introduce 1 100 7 /my/home
    13.9 -1 write /entry1 contents
   13.10 -expect entry1
   13.11 -expect tool
   13.12 -dir /
   13.13 -close
   13.14 -
   13.15 -# Release that domain.
   13.16 -release 1
   13.17 -close
   13.18 -
   13.19 -# Introduce and release by same connection.
   13.20 -expect handle is 2
   13.21 -introduce 1 100 7 /my/home
   13.22 -release 1
    14.1 --- a/tools/xenstore/testsuite/10domain-homedir.test	Tue Jul 03 15:49:16 2007 +0100
    14.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3 @@ -1,18 +0,0 @@
    14.4 -# Test domain "implicit" paths.
    14.5 -
    14.6 -# Create a domain, write an entry using implicit path, read using implicit
    14.7 -mkdir /home
    14.8 -expect handle is 1
    14.9 -introduce 1 100 7 /home
   14.10 -1 write entry1 contents
   14.11 -expect contents
   14.12 -read /home/entry1
   14.13 -expect entry1
   14.14 -dir /home
   14.15 -
   14.16 -# Place a watch using a relative path: expect relative answer.
   14.17 -1 mkdir foo
   14.18 -1 watch foo token
   14.19 -write /home/foo/bar contents
   14.20 -expect 1:foo/bar:token
   14.21 -1 waitwatch
    15.1 --- a/tools/xenstore/testsuite/11domain-watch.test	Tue Jul 03 15:49:16 2007 +0100
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,50 +0,0 @@
    15.4 -# Test watching from a domain.
    15.5 -
    15.6 -# Watch something, write to it, check watch has fired.
    15.7 -write /test contents
    15.8 -mkdir /dir
    15.9 -
   15.10 -expect handle is 1
   15.11 -introduce 1 100 7 /my/home
   15.12 -1 watch /test token
   15.13 -write /test contents2
   15.14 -expect 1:/test:token
   15.15 -1 waitwatch
   15.16 -1 unwatch /test token
   15.17 -release 1
   15.18 -1 close
   15.19 -
   15.20 -# ignore watches while doing commands, should work.
   15.21 -expect handle is 1
   15.22 -introduce 1 100 7 /my/home
   15.23 -1 watch /dir token
   15.24 -write /dir/test contents
   15.25 -1 write /dir/test2 contents2
   15.26 -1 write /dir/test3 contents3
   15.27 -1 write /dir/test4 contents4
   15.28 -expect 1:/dir/test:token
   15.29 -1 waitwatch
   15.30 -release 1
   15.31 -1 close
   15.32 -
   15.33 -# unwatch
   15.34 -expect handle is 1
   15.35 -introduce 1 100 7 /my/home
   15.36 -1 watch /dir token1
   15.37 -1 unwatch /dir token1
   15.38 -1 watch /dir token2
   15.39 -write /dir/test2 contents
   15.40 -expect 1:/dir/test2:token2
   15.41 -1 waitwatch
   15.42 -1 unwatch /dir token2
   15.43 -release 1
   15.44 -1 close
   15.45 -
   15.46 -# unwatch while watch pending.
   15.47 -expect handle is 1
   15.48 -introduce 1 100 7 /my/home
   15.49 -1 watch /dir token1
   15.50 -write /dir/test2 contents
   15.51 -1 unwatch /dir token1
   15.52 -release 1
   15.53 -1 close
    16.1 --- a/tools/xenstore/testsuite/12readonly.test	Tue Jul 03 15:49:16 2007 +0100
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,38 +0,0 @@
    16.4 -# Test that read only connection can't alter store.
    16.5 -
    16.6 -write /test contents
    16.7 -
    16.8 -readonly
    16.9 -expect test
   16.10 -expect tool
   16.11 -dir /
   16.12 -
   16.13 -expect contents
   16.14 -read /test
   16.15 -expect 0 READ
   16.16 -getperm /test
   16.17 -watch /test token
   16.18 -unwatch /test token 
   16.19 -start
   16.20 -commit
   16.21 -start
   16.22 -abort
   16.23 -
   16.24 -# These don't work
   16.25 -expect write failed: Permission denied
   16.26 -write /test2 contents
   16.27 -expect write failed: Permission denied
   16.28 -write /test contents
   16.29 -expect setperm failed: Permission denied
   16.30 -setperm /test 100 NONE
   16.31 -expect setperm failed: Permission denied
   16.32 -setperm /test 100 NONE
   16.33 -expect introduce failed: Permission denied
   16.34 -introduce 1 100 7 /home
   16.35 -
   16.36 -# Check that watches work like normal.
   16.37 -watch / token
   16.38 -1 readwrite
   16.39 -1 write /test contents
   16.40 -expect /test:token
   16.41 -waitwatch
    17.1 --- a/tools/xenstore/testsuite/13watch-ack.test	Tue Jul 03 15:49:16 2007 +0100
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,21 +0,0 @@
    17.4 -# This demonstrates a bug where an xs_acknowledge_watch returns
    17.5 -# EINVAL, because the daemon doesn't track what watch event it sent
    17.6 -# and relies on it being the "first" watch which has an event.
    17.7 -# Watches firing after the first event is sent out will change this.
    17.8 -
    17.9 -# Create three things to watch.
   17.10 -mkdir /test
   17.11 -mkdir /test/1
   17.12 -mkdir /test/2
   17.13 -mkdir /test/3
   17.14 -
   17.15 -# Watch all three, fire event on 2, read watch, fire event on 1 and 3, ack 2.
   17.16 -1 watch /test/1 token1
   17.17 -1 watch /test/2 token2
   17.18 -1 watch /test/3 token3
   17.19 -2 write /test/2 contents2
   17.20 -expect 1:/test/2:token2
   17.21 -1 waitwatch
   17.22 -3 write /test/1 contents1
   17.23 -4 write /test/3 contents3
   17.24 -1 close
    18.1 --- a/tools/xenstore/testsuite/14complexperms.test	Tue Jul 03 15:49:16 2007 +0100
    18.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3 @@ -1,68 +0,0 @@
    18.4 -# We should not be able to tell the difference between a node which
    18.5 -# doesn't exist, and a node we don't have permission on, if we don't
    18.6 -# have permission on it directory.
    18.7 -
    18.8 -mkdir /dir
    18.9 -setperm /dir 0 NONE
   18.10 -
   18.11 -# First when it doesn't exist
   18.12 -setid 1
   18.13 -expect *Permission denied
   18.14 -dir /dir/file
   18.15 -expect *Permission denied
   18.16 -read /dir/file 
   18.17 -expect *Permission denied
   18.18 -write /dir/file value 
   18.19 -expect *Permission denied
   18.20 -mkdir /dir/file 
   18.21 -expect *Permission denied
   18.22 -rm /dir/file 
   18.23 -expect *Permission denied
   18.24 -rm /dir 
   18.25 -expect *Permission denied
   18.26 -getperm /dir/file 
   18.27 -expect *Permission denied
   18.28 -setperm /dir/file 0 NONE 
   18.29 -# We get no watch event when there's no permission.  It's a corner case.
   18.30 -watchnoack /dir/file token 
   18.31 -1 write /dir/file contents
   18.32 -1 rm /dir/file
   18.33 -expect waitwatch failed: Connection timed out
   18.34 -waitwatch
   18.35 -unwatch /dir/file token 
   18.36 -expect *No such file or directory
   18.37 -unwatch /dir/file token 
   18.38 -expect *Permission denied
   18.39 -introduce 2 100 7 /dir/file
   18.40 -
   18.41 -# Now it exists
   18.42 -setid 0
   18.43 -write /dir/file contents
   18.44 -
   18.45 -setid 1
   18.46 -expect *Permission denied
   18.47 -dir /dir/file
   18.48 -expect *Permission denied
   18.49 -read /dir/file 
   18.50 -expect *Permission denied
   18.51 -write /dir/file value 
   18.52 -expect *Permission denied
   18.53 -mkdir /dir/file 
   18.54 -expect *Permission denied
   18.55 -rm /dir/file 
   18.56 -expect *Permission denied
   18.57 -rm /dir 
   18.58 -expect *Permission denied
   18.59 -getperm /dir/file 
   18.60 -expect *Permission denied
   18.61 -setperm /dir/file 0 NONE 
   18.62 -watchnoack /dir/file token 
   18.63 -1 write /dir/file contents
   18.64 -1 rm /dir/file
   18.65 -expect waitwatch failed: Connection timed out
   18.66 -waitwatch
   18.67 -unwatch /dir/file token 
   18.68 -expect *No such file or directory
   18.69 -unwatch /dir/file token 
   18.70 -expect *Permission denied
   18.71 -introduce 2 100 7 /dir/file
    19.1 --- a/tools/xenstore/testsuite/test.sh	Tue Jul 03 15:49:16 2007 +0100
    19.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3 @@ -1,64 +0,0 @@
    19.4 -#! /bin/sh
    19.5 -
    19.6 -set -e
    19.7 -set -m
    19.8 -
    19.9 -run_test()
   19.10 -{
   19.11 -    rm -rf $XENSTORED_ROOTDIR
   19.12 -    mkdir $XENSTORED_ROOTDIR
   19.13 -    if [ $VALGRIND -eq 1 ]; then
   19.14 -	valgrind --suppressions=testsuite/vg-suppressions -q ./xenstored_test --output-pid --trace-file=testsuite/tmp/trace --no-fork > /tmp/pid 2> testsuite/tmp/xenstored_errors &
   19.15 -	while [ ! -s /tmp/pid ]; do sleep 0; done
   19.16 -	PID=`cat /tmp/pid`
   19.17 -	rm /tmp/pid
   19.18 -    else
   19.19 -	# We don't get error messages from this, though. 
   19.20 -	PID=`./xenstored_test --output-pid --trace-file=testsuite/tmp/trace`
   19.21 -    fi
   19.22 -    if ./xs_test $2 $1; then
   19.23 -	if [ -s testsuite/tmp/xenstored_errors ]; then
   19.24 -	    kill $PID
   19.25 -	    echo Errors:
   19.26 -	    cat testsuite/tmp/xenstored_errors
   19.27 -	    return 1
   19.28 -	fi
   19.29 -	kill $PID
   19.30 -	sleep 1
   19.31 -	return 0
   19.32 -    else
   19.33 -	# In case daemon is wedged.
   19.34 -	kill $PID
   19.35 -	sleep 1
   19.36 -	return 1
   19.37 -    fi
   19.38 -}
   19.39 -
   19.40 -if [ x$1 = x--fast ]; then
   19.41 -    VALGRIND=0
   19.42 -    SLOWTESTS=""
   19.43 -    shift
   19.44 -else
   19.45 -    if type valgrind >/dev/null 2>&1; then
   19.46 -	VALGRIND=1
   19.47 -    else
   19.48 -	echo "WARNING: valgrind not available" >&2
   19.49 -	VALGRIND=0
   19.50 -    fi
   19.51 -    SLOWTESTS=testsuite/[0-9]*.slowtest
   19.52 -fi
   19.53 -
   19.54 -MATCH=${1:-"*"}
   19.55 -for f in testsuite/[0-9]*.test $SLOWTESTS; do
   19.56 -    case `basename $f` in $MATCH) RUN=1;; esac
   19.57 -    [ -n "$RUN" ] || continue
   19.58 -
   19.59 -    if run_test $f -x >/tmp/out; then
   19.60 -	echo -n .
   19.61 -    else
   19.62 -	cat /tmp/out
   19.63 -	# That will have filled the screen, repeat message.
   19.64 -	echo Test $f failed
   19.65 -	exit 1
   19.66 -    fi
   19.67 -done
    20.1 --- a/tools/xenstore/testsuite/vg-suppressions	Tue Jul 03 15:49:16 2007 +0100
    20.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.3 @@ -1,9 +0,0 @@
    20.4 -{
    20.5 -   Glibc goes boom from _start (Debian glibc 2.3.5-3)
    20.6 -   Memcheck:Cond
    20.7 -   obj:/lib/ld-2.3.5.so
    20.8 -   obj:/lib/ld-2.3.5.so
    20.9 -   obj:/lib/ld-2.3.5.so
   20.10 -   obj:/lib/ld-2.3.5.so
   20.11 -   obj:/lib/ld-2.3.5.so
   20.12 -}
    21.1 --- a/tools/xenstore/xenstored_core.c	Tue Jul 03 15:49:16 2007 +0100
    21.2 +++ b/tools/xenstore/xenstored_core.c	Tue Jul 03 15:51:59 2007 +0100
    21.3 @@ -39,7 +39,6 @@
    21.4  #include <assert.h>
    21.5  #include <setjmp.h>
    21.6  
    21.7 -//#define DEBUG
    21.8  #include "utils.h"
    21.9  #include "list.h"
   21.10  #include "talloc.h"
   21.11 @@ -53,7 +52,6 @@
   21.12  
   21.13  #include "hashtable.h"
   21.14  
   21.15 -
   21.16  extern int xce_handle; /* in xenstored_domain.c */
   21.17  
   21.18  static bool verbose = false;
   21.19 @@ -82,50 +80,6 @@ int quota_nb_watch_per_domain = 128;
   21.20  int quota_max_entry_size = 2048; /* 2K */
   21.21  int quota_max_transaction = 10;
   21.22  
   21.23 -#ifdef TESTING
   21.24 -static bool failtest = false;
   21.25 -
   21.26 -/* We override talloc's malloc. */
   21.27 -void *test_malloc(size_t size)
   21.28 -{
   21.29 -	/* 1 in 20 means only about 50% of connections establish. */
   21.30 -	if (failtest && (random() % 32) == 0)
   21.31 -		return NULL;
   21.32 -	return malloc(size);
   21.33 -}
   21.34 -
   21.35 -static void stop_failtest(int signum __attribute__((unused)))
   21.36 -{
   21.37 -	failtest = false;
   21.38 -}
   21.39 -
   21.40 -/* Need these before we #define away write_all/mkdir in testing.h */
   21.41 -bool test_write_all(int fd, void *contents, unsigned int len);
   21.42 -bool test_write_all(int fd, void *contents, unsigned int len)
   21.43 -{
   21.44 -	if (failtest && (random() % 8) == 0) {
   21.45 -		if (len)
   21.46 -			len = random() % len;
   21.47 -		write(fd, contents, len);
   21.48 -		errno = ENOSPC;
   21.49 -		return false;
   21.50 -	}
   21.51 -	return xs_write_all(fd, contents, len);
   21.52 -}
   21.53 -
   21.54 -int test_mkdir(const char *dir, int perms);
   21.55 -int test_mkdir(const char *dir, int perms)
   21.56 -{
   21.57 -	if (failtest && (random() % 8) == 0) {
   21.58 -		errno = ENOSPC;
   21.59 -		return -1;
   21.60 -	}
   21.61 -	return mkdir(dir, perms);
   21.62 -}
   21.63 -#endif /* TESTING */
   21.64 -
   21.65 -#include "xenstored_test.h"
   21.66 -
   21.67  TDB_CONTEXT *tdb_context(struct connection *conn)
   21.68  {
   21.69  	/* conn = NULL used in manual_node at setup. */
   21.70 @@ -1163,12 +1117,10 @@ static void do_debug(struct connection *
   21.71  {
   21.72  	int num;
   21.73  
   21.74 -#ifndef TESTING
   21.75  	if (conn->id != 0) {
   21.76  		send_error(conn, EACCES);
   21.77  		return;
   21.78  	}
   21.79 -#endif
   21.80  
   21.81  	num = xs_count_strings(in->buffer, in->used);
   21.82  
   21.83 @@ -1179,18 +1131,10 @@ static void do_debug(struct connection *
   21.84  		}
   21.85  		xprintf("debug: %s", in->buffer + get_string(in, 0));
   21.86  	}
   21.87 +
   21.88  	if (streq(in->buffer, "check"))
   21.89  		check_store();
   21.90 -#ifdef TESTING
   21.91 -	/* For testing, we allow them to set id. */
   21.92 -	if (streq(in->buffer, "setid")) {
   21.93 -		conn->id = atoi(in->buffer + get_string(in, 0));
   21.94 -	} else if (streq(in->buffer, "failtest")) {
   21.95 -		if (get_string(in, 0) < in->used)
   21.96 -			srandom(atoi(in->buffer + get_string(in, 0)));
   21.97 -		failtest = true;
   21.98 -	}
   21.99 -#endif /* TESTING */
  21.100 +
  21.101  	send_ack(conn, XS_DEBUG);
  21.102  }
  21.103  
  21.104 @@ -1319,10 +1263,8 @@ static void handle_input(struct connecti
  21.105  			return;
  21.106  
  21.107  		if (in->hdr.msg.len > PATH_MAX) {
  21.108 -#ifndef TESTING
  21.109  			syslog(LOG_ERR, "Client tried to feed us %i",
  21.110  			       in->hdr.msg.len);
  21.111 -#endif
  21.112  			goto bad_client;
  21.113  		}
  21.114  
  21.115 @@ -1414,39 +1356,7 @@ static void accept_connection(int sock, 
  21.116  		close(fd);
  21.117  }
  21.118  
  21.119 -#ifdef TESTING
  21.120 -/* Valgrind can check our writes better if we don't use mmap */
  21.121 -#define TDB_FLAGS TDB_NOMMAP
  21.122 -/* Useful for running under debugger. */
  21.123 -void dump_connection(void)
  21.124 -{
  21.125 -	struct connection *i;
  21.126 -
  21.127 -	list_for_each_entry(i, &connections, list) {
  21.128 -		printf("Connection %p:\n", i);
  21.129 -		printf("    state = %s\n",
  21.130 -		       list_empty(&i->out_list) ? "OK" : "BUSY");
  21.131 -		if (i->id)
  21.132 -			printf("    id = %i\n", i->id);
  21.133 -		if (!i->in->inhdr || i->in->used)
  21.134 -			printf("    got %i bytes of %s\n",
  21.135 -			       i->in->used, i->in->inhdr ? "header" : "data");
  21.136 -#if 0
  21.137 -		if (i->out)
  21.138 -			printf("    sending message %s (%s) out\n",
  21.139 -			       sockmsg_string(i->out->hdr.msg.type),
  21.140 -			       i->out->buffer);
  21.141 -		if (i->transaction)
  21.142 -			dump_transaction(i);
  21.143 -		if (i->domain)
  21.144 -			dump_domain(i);
  21.145 -#endif
  21.146 -		dump_watches(i);
  21.147 -	}
  21.148 -}
  21.149 -#else
  21.150  #define TDB_FLAGS 0
  21.151 -#endif
  21.152  
  21.153  /* We create initial nodes manually. */
  21.154  static void manual_node(const char *name, const char *child)
  21.155 @@ -1693,10 +1603,6 @@ static void corrupt(struct connection *c
  21.156  	log("corruption detected by connection %i: err %s: %s",
  21.157  	    conn ? (int)conn->id : -1, strerror(saved_errno), str);
  21.158  
  21.159 -#ifdef TESTING
  21.160 -	/* Allow them to attach debugger. */
  21.161 -	sleep(30);
  21.162 -#endif
  21.163  	check_store();
  21.164  }
  21.165  
  21.166 @@ -1740,11 +1646,10 @@ static void daemonize(void)
  21.167  	if (pid != 0)
  21.168  		exit(0);
  21.169  
  21.170 -#ifndef TESTING	/* Relative paths for socket names */
  21.171  	/* Move off any mount points we might be in. */
  21.172  	if (chdir("/") == -1)
  21.173  		barf_perror("Failed to chdir");
  21.174 -#endif
  21.175 +
  21.176  	/* Discard our parent's old-fashioned umask prejudices. */
  21.177  	umask(0);
  21.178  }
  21.179 @@ -1941,10 +1846,6 @@ int main(int argc, char *argv[])
  21.180  
  21.181  	signal(SIGHUP, trigger_reopen_log);
  21.182  
  21.183 -#ifdef TESTING
  21.184 -	signal(SIGUSR1, stop_failtest);
  21.185 -#endif
  21.186 -
  21.187  	if (xce_handle != -1)
  21.188  		evtchn_fd = xc_evtchn_fd(xce_handle);
  21.189  
    22.1 --- a/tools/xenstore/xenstored_domain.c	Tue Jul 03 15:49:16 2007 +0100
    22.2 +++ b/tools/xenstore/xenstored_domain.c	Tue Jul 03 15:51:59 2007 +0100
    22.3 @@ -23,14 +23,12 @@
    22.4  #include <stdlib.h>
    22.5  #include <stdarg.h>
    22.6  
    22.7 -//#define DEBUG
    22.8  #include "utils.h"
    22.9  #include "talloc.h"
   22.10  #include "xenstored_core.h"
   22.11  #include "xenstored_domain.h"
   22.12  #include "xenstored_transaction.h"
   22.13  #include "xenstored_watch.h"
   22.14 -#include "xenstored_test.h"
   22.15  
   22.16  #include <xenctrl.h>
   22.17  
   22.18 @@ -217,10 +215,8 @@ void handle_event(void)
   22.19  	if (port == virq_port)
   22.20  		domain_cleanup();
   22.21  
   22.22 -#ifndef TESTING
   22.23  	if (xc_evtchn_unmask(xce_handle, port) == -1)
   22.24  		barf_perror("Failed to write to event fd");
   22.25 -#endif
   22.26  }
   22.27  
   22.28  bool domain_can_read(struct connection *conn)
    23.1 --- a/tools/xenstore/xenstored_test.h	Tue Jul 03 15:49:16 2007 +0100
    23.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.3 @@ -1,37 +0,0 @@
    23.4 -/* 
    23.5 -    Testing replcements for Xen Store Daemon.
    23.6 -    Copyright (C) 2005 Rusty Russell IBM Corporation
    23.7 -
    23.8 -    This program is free software; you can redistribute it and/or modify
    23.9 -    it under the terms of the GNU General Public License as published by
   23.10 -    the Free Software Foundation; either version 2 of the License, or
   23.11 -    (at your option) any later version.
   23.12 -
   23.13 -    This program is distributed in the hope that it will be useful,
   23.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   23.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   23.16 -    GNU General Public License for more details.
   23.17 -
   23.18 -    You should have received a copy of the GNU General Public License
   23.19 -    along with this program; if not, write to the Free Software
   23.20 -    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   23.21 -*/
   23.22 -#ifndef _XENSTORED_TEST_H
   23.23 -#define _XENSTORED_TEST_H
   23.24 -
   23.25 -#ifdef TESTING
   23.26 -bool test_write_all(int fd, void *contents, unsigned int len);
   23.27 -#define xs_write_all test_write_all
   23.28 -
   23.29 -int test_mkdir(const char *dir, int perms);
   23.30 -#define mkdir test_mkdir
   23.31 -
   23.32 -int fake_open_eventchn(void);
   23.33 -void fake_block_events(void);
   23.34 -void fake_ack_event(void);
   23.35 -
   23.36 -#define ioctl(a,b,c) 0
   23.37 -
   23.38 -#endif
   23.39 -
   23.40 -#endif /* _XENSTORED_INTERNAL_H */
    24.1 --- a/tools/xenstore/xenstored_transaction.c	Tue Jul 03 15:49:16 2007 +0100
    24.2 +++ b/tools/xenstore/xenstored_transaction.c	Tue Jul 03 15:51:59 2007 +0100
    24.3 @@ -35,7 +35,6 @@
    24.4  #include "xenstored_domain.h"
    24.5  #include "xs_lib.h"
    24.6  #include "utils.h"
    24.7 -#include "xenstored_test.h"
    24.8  
    24.9  struct changed_node
   24.10  {
    25.1 --- a/tools/xenstore/xenstored_watch.c	Tue Jul 03 15:49:16 2007 +0100
    25.2 +++ b/tools/xenstore/xenstored_watch.c	Tue Jul 03 15:51:59 2007 +0100
    25.3 @@ -29,7 +29,6 @@
    25.4  #include "xenstored_watch.h"
    25.5  #include "xs_lib.h"
    25.6  #include "utils.h"
    25.7 -#include "xenstored_test.h"
    25.8  #include "xenstored_domain.h"
    25.9  
   25.10  extern int quota_nb_watch_per_domain;
   25.11 @@ -196,17 +195,6 @@ void conn_delete_all_watches(struct conn
   25.12  	}
   25.13  }
   25.14  
   25.15 -#ifdef TESTING
   25.16 -void dump_watches(struct connection *conn)
   25.17 -{
   25.18 -	struct watch *watch;
   25.19 -
   25.20 -	list_for_each_entry(watch, &conn->watches, list)
   25.21 -		printf("    watch on %s token %s\n",
   25.22 -		       watch->node, watch->token);
   25.23 -}
   25.24 -#endif
   25.25 -
   25.26  /*
   25.27   * Local variables:
   25.28   *  c-file-style: "linux"
    26.1 --- a/tools/xenstore/xs_crashme.c	Tue Jul 03 15:49:16 2007 +0100
    26.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.3 @@ -1,393 +0,0 @@
    26.4 -/* Code which randomly corrupts bits going to the daemon.
    26.5 -    Copyright (C) 2005 Rusty Russell IBM Corporation
    26.6 -
    26.7 -    This program is free software; you can redistribute it and/or modify
    26.8 -    it under the terms of the GNU General Public License as published by
    26.9 -    the Free Software Foundation; either version 2 of the License, or
   26.10 -    (at your option) any later version.
   26.11 -
   26.12 -    This program is distributed in the hope that it will be useful,
   26.13 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   26.14 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   26.15 -    GNU General Public License for more details.
   26.16 -
   26.17 -    You should have received a copy of the GNU General Public License
   26.18 -    along with this program; if not, write to the Free Software
   26.19 -    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   26.20 -*/
   26.21 -#include <stdbool.h>
   26.22 -#include <stdio.h>
   26.23 -#include <sys/types.h>
   26.24 -#include <stdarg.h>
   26.25 -#include <string.h>
   26.26 -#include <sys/time.h>
   26.27 -#include "xs.h"
   26.28 -#include "talloc.h"
   26.29 -#include <errno.h>
   26.30 -
   26.31 -#define XSTEST
   26.32 -#define RAND_FREQ 128 		/* One char in 32 is corrupted. */
   26.33 -
   26.34 -/* jhash.h: Jenkins hash support.
   26.35 - *
   26.36 - * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
   26.37 - *
   26.38 - * http://burtleburtle.net/bob/hash/
   26.39 - *
   26.40 - * These are the credits from Bob's sources:
   26.41 - *
   26.42 - * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
   26.43 - * hash(), hash2(), hash3, and mix() are externally useful functions.
   26.44 - * Routines to test the hash are included if SELF_TEST is defined.
   26.45 - * You can use this free for any purpose.  It has no warranty.
   26.46 - *
   26.47 - * Copyright (C) 2003 David S. Miller (davem@redhat.com)
   26.48 - *
   26.49 - * I've modified Bob's hash to be useful in the Linux kernel, and
   26.50 - * any bugs present are surely my fault.  -DaveM
   26.51 - */
   26.52 -
   26.53 -/* NOTE: Arguments are modified. */
   26.54 -#define __jhash_mix(a, b, c) \
   26.55 -{ \
   26.56 -  a -= b; a -= c; a ^= (c>>13); \
   26.57 -  b -= c; b -= a; b ^= (a<<8); \
   26.58 -  c -= a; c -= b; c ^= (b>>13); \
   26.59 -  a -= b; a -= c; a ^= (c>>12);  \
   26.60 -  b -= c; b -= a; b ^= (a<<16); \
   26.61 -  c -= a; c -= b; c ^= (b>>5); \
   26.62 -  a -= b; a -= c; a ^= (c>>3);  \
   26.63 -  b -= c; b -= a; b ^= (a<<10); \
   26.64 -  c -= a; c -= b; c ^= (b>>15); \
   26.65 -}
   26.66 -
   26.67 -/* The golden ration: an arbitrary value */
   26.68 -#define JHASH_GOLDEN_RATIO	0x9e3779b9
   26.69 -
   26.70 -/* The most generic version, hashes an arbitrary sequence
   26.71 - * of bytes.  No alignment or length assumptions are made about
   26.72 - * the input key.
   26.73 - */
   26.74 -static inline uint32_t jhash(const void *key, uint32_t length, uint32_t initval)
   26.75 -{
   26.76 -	uint32_t a, b, c, len;
   26.77 -	const uint8_t *k = key;
   26.78 -
   26.79 -	len = length;
   26.80 -	a = b = JHASH_GOLDEN_RATIO;
   26.81 -	c = initval;
   26.82 -
   26.83 -	while (len >= 12) {
   26.84 -		a += (k[0] +((uint32_t)k[1]<<8) +((uint32_t)k[2]<<16) +((uint32_t)k[3]<<24));
   26.85 -		b += (k[4] +((uint32_t)k[5]<<8) +((uint32_t)k[6]<<16) +((uint32_t)k[7]<<24));
   26.86 -		c += (k[8] +((uint32_t)k[9]<<8) +((uint32_t)k[10]<<16)+((uint32_t)k[11]<<24));
   26.87 -
   26.88 -		__jhash_mix(a,b,c);
   26.89 -
   26.90 -		k += 12;
   26.91 -		len -= 12;
   26.92 -	}
   26.93 -
   26.94 -	c += length;
   26.95 -	switch (len) {
   26.96 -	case 11: c += ((uint32_t)k[10]<<24);
   26.97 -	case 10: c += ((uint32_t)k[9]<<16);
   26.98 -	case 9 : c += ((uint32_t)k[8]<<8);
   26.99 -	case 8 : b += ((uint32_t)k[7]<<24);
  26.100 -	case 7 : b += ((uint32_t)k[6]<<16);
  26.101 -	case 6 : b += ((uint32_t)k[5]<<8);
  26.102 -	case 5 : b += k[4];
  26.103 -	case 4 : a += ((uint32_t)k[3]<<24);
  26.104 -	case 3 : a += ((uint32_t)k[2]<<16);
  26.105 -	case 2 : a += ((uint32_t)k[1]<<8);
  26.106 -	case 1 : a += k[0];
  26.107 -	};
  26.108 -
  26.109 -	__jhash_mix(a,b,c);
  26.110 -
  26.111 -	return c;
  26.112 -}
  26.113 -
  26.114 -/* A special optimized version that handles 1 or more of uint32_ts.
  26.115 - * The length parameter here is the number of uint32_ts in the key.
  26.116 - */
  26.117 -static inline uint32_t jhash2(uint32_t *k, uint32_t length, uint32_t initval)
  26.118 -{
  26.119 -	uint32_t a, b, c, len;
  26.120 -
  26.121 -	a = b = JHASH_GOLDEN_RATIO;
  26.122 -	c = initval;
  26.123 -	len = length;
  26.124 -
  26.125 -	while (len >= 3) {
  26.126 -		a += k[0];
  26.127 -		b += k[1];
  26.128 -		c += k[2];
  26.129 -		__jhash_mix(a, b, c);
  26.130 -		k += 3; len -= 3;
  26.131 -	}
  26.132 -
  26.133 -	c += length * 4;
  26.134 -
  26.135 -	switch (len) {
  26.136 -	case 2 : b += k[1];
  26.137 -	case 1 : a += k[0];
  26.138 -	};
  26.139 -
  26.140 -	__jhash_mix(a,b,c);
  26.141 -
  26.142 -	return c;
  26.143 -}
  26.144 -
  26.145 -
  26.146 -/* A special ultra-optimized versions that knows they are hashing exactly
  26.147 - * 3, 2 or 1 word(s).
  26.148 - *
  26.149 - * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
  26.150 - *       done at the end is not done here.
  26.151 - */
  26.152 -static inline uint32_t jhash_3words(uint32_t a, uint32_t b, uint32_t c, uint32_t initval)
  26.153 -{
  26.154 -	a += JHASH_GOLDEN_RATIO;
  26.155 -	b += JHASH_GOLDEN_RATIO;
  26.156 -	c += initval;
  26.157 -
  26.158 -	__jhash_mix(a, b, c);
  26.159 -
  26.160 -	return c;
  26.161 -}
  26.162 -
  26.163 -static inline uint32_t jhash_2words(uint32_t a, uint32_t b, uint32_t initval)
  26.164 -{
  26.165 -	return jhash_3words(a, b, 0, initval);
  26.166 -}
  26.167 -
  26.168 -static inline uint32_t jhash_1word(uint32_t a, uint32_t initval)
  26.169 -{
  26.170 -	return jhash_3words(a, 0, 0, initval);
  26.171 -}
  26.172 -
  26.173 -static unsigned int get_randomness(int *state)
  26.174 -{
  26.175 -	return jhash_1word((*state)++, *state * 1103515243);
  26.176 -}
  26.177 -
  26.178 -static int state;
  26.179 -
  26.180 -/* Lengthening headers is pointless: other end will just wait for more
  26.181 - * data and timeout.  We merely shorten the length. */
  26.182 -static void corrupt_header(char *output, const struct xsd_sockmsg *msg,
  26.183 -			   unsigned int *next_bit)
  26.184 -{
  26.185 -	struct xsd_sockmsg newmsg = *msg;
  26.186 -
  26.187 -	while (*next_bit < sizeof(*msg)) {
  26.188 -		if (newmsg.len)
  26.189 -			newmsg.len = get_randomness(&state) % newmsg.len;
  26.190 -		*next_bit += get_randomness(&state) % RAND_FREQ;
  26.191 -	}
  26.192 -	memcpy(output, &newmsg, sizeof(newmsg));
  26.193 -}
  26.194 -
  26.195 -#define read_all_choice read_all
  26.196 -static bool write_all_choice(int fd, const void *data, unsigned int len)
  26.197 -{
  26.198 -	char corrupt_data[len];
  26.199 -	bool ret;
  26.200 -	static unsigned int next_bit;
  26.201 -
  26.202 -	if (len == sizeof(struct xsd_sockmsg)
  26.203 -	    && ((unsigned long)data % __alignof__(struct xsd_sockmsg)) == 0)
  26.204 -		corrupt_header(corrupt_data, data, &next_bit);
  26.205 -	else {
  26.206 -		memcpy(corrupt_data, data, len);
  26.207 -		while (next_bit < len * CHAR_BIT) {
  26.208 -			corrupt_data[next_bit/CHAR_BIT]
  26.209 -				^= (1 << (next_bit%CHAR_BIT));
  26.210 -			next_bit += get_randomness(&state) % RAND_FREQ;
  26.211 -		}
  26.212 -	}
  26.213 -
  26.214 -	ret = xs_write_all(fd, corrupt_data, len);
  26.215 -	next_bit -= len * CHAR_BIT;
  26.216 -	return ret;
  26.217 -}
  26.218 -
  26.219 -#include "xs.c"
  26.220 -
  26.221 -static char *random_path(void)
  26.222 -{
  26.223 -	unsigned int i;
  26.224 -	char *ret = NULL;
  26.225 -
  26.226 -	if (get_randomness(&state) % 20 == 0)
  26.227 -		return talloc_strdup(NULL, "/");
  26.228 -
  26.229 -	for (i = 0; i < 1 || (get_randomness(&state) % 2); i++) {
  26.230 -		ret = talloc_asprintf_append(ret, "/%i", 
  26.231 -					     get_randomness(&state) % 15);
  26.232 -	}
  26.233 -	return ret;
  26.234 -}
  26.235 -
  26.236 -/* Do the next operation, return the results. */
  26.237 -static void do_next_op(struct xs_handle *h, bool verbose)
  26.238 -{
  26.239 -	char *name;
  26.240 -	unsigned int num;
  26.241 -
  26.242 -	if (verbose)
  26.243 -		printf("State %i: ", state);
  26.244 -
  26.245 -	name = random_path();
  26.246 -	switch (get_randomness(&state) % 9) {
  26.247 -	case 0:
  26.248 -		if (verbose)
  26.249 -			printf("DIR %s\n", name);
  26.250 -		free(xs_directory(h, name, &num));
  26.251 -		break;
  26.252 -	case 1:
  26.253 -		if (verbose)
  26.254 -			printf("READ %s\n", name);
  26.255 -		free(xs_read(h, name, &num));
  26.256 -		break;
  26.257 -	case 2: {
  26.258 -		char *contents = talloc_asprintf(NULL, "%i",
  26.259 -						 get_randomness(&state));
  26.260 -		unsigned int len = get_randomness(&state)%(strlen(contents)+1);
  26.261 -		if (verbose)
  26.262 -			printf("WRITE %s %.*s\n", name, len, contents);
  26.263 -		xs_write(h, name, contents, len);
  26.264 -		break;
  26.265 -	}
  26.266 -	case 3:
  26.267 -		if (verbose)
  26.268 -			printf("MKDIR %s\n", name);
  26.269 -		xs_mkdir(h, name);
  26.270 -		break;
  26.271 -	case 4:
  26.272 -		if (verbose)
  26.273 -			printf("RM %s\n", name);
  26.274 -		xs_rm(h, name);
  26.275 -		break;
  26.276 -	case 5:
  26.277 -		if (verbose)
  26.278 -			printf("GETPERMS %s\n", name);
  26.279 -		free(xs_get_permissions(h, name, &num));
  26.280 -		break;
  26.281 -	case 6: {
  26.282 -		unsigned int i, num = get_randomness(&state)%8;
  26.283 -		struct xs_permissions perms[num];
  26.284 -
  26.285 -		if (verbose)
  26.286 -			printf("SETPERMS %s: ", name);
  26.287 -		for (i = 0; i < num; i++) {
  26.288 -			perms[i].id = get_randomness(&state)%8;
  26.289 -			perms[i].perms = get_randomness(&state)%4;
  26.290 -			if (verbose)
  26.291 -				printf("%i%c ", perms[i].id,
  26.292 -				       perms[i].perms == XS_PERM_WRITE ? 'W'
  26.293 -				       : perms[i].perms == XS_PERM_READ ? 'R'
  26.294 -				       : perms[i].perms == 
  26.295 -				       (XS_PERM_READ|XS_PERM_WRITE) ? 'B'
  26.296 -				       : 'N');
  26.297 -		}
  26.298 -		if (verbose)
  26.299 -			printf("\n");
  26.300 -		xs_set_permissions(h, name, perms, num);
  26.301 -		break;
  26.302 -	}
  26.303 -	case 7: {
  26.304 -		if (verbose)
  26.305 -			printf("START %s\n", name);
  26.306 -		xs_transaction_start(h);
  26.307 -		break;
  26.308 -	}
  26.309 -	case 8: {
  26.310 -		bool abort = (get_randomness(&state) % 2);
  26.311 -
  26.312 -		if (verbose)
  26.313 -			printf("STOP %s\n", abort ? "ABORT" : "COMMIT");
  26.314 -		xs_transaction_end(h, abort);
  26.315 -		break;
  26.316 -	}
  26.317 -	default:
  26.318 -		barf("Impossible randomness");
  26.319 -	}
  26.320 -}
  26.321 -
  26.322 -static struct xs_handle *h;
  26.323 -static void alarmed(int sig __attribute__((unused)))
  26.324 -{
  26.325 -	/* We force close on timeout. */
  26.326 -	close(h->fd);
  26.327 -}
  26.328 -
  26.329 -static int start_daemon(void)
  26.330 -{
  26.331 -	int fds[2];
  26.332 -	int daemon_pid;
  26.333 -
  26.334 -	/* Start daemon. */
  26.335 -	pipe(fds);
  26.336 -	if ((daemon_pid = fork())) {
  26.337 -		/* Child writes PID when its ready: we wait for that. */
  26.338 -		char buffer[20];
  26.339 -		close(fds[1]);
  26.340 -		if (read(fds[0], buffer, sizeof(buffer)) < 0)
  26.341 -			barf("Failed to summon daemon");
  26.342 -		close(fds[0]);
  26.343 -		return daemon_pid;
  26.344 -	} else {
  26.345 -		dup2(fds[1], STDOUT_FILENO);
  26.346 -		close(fds[0]);
  26.347 -#if 1
  26.348 -		execlp("valgrind", "valgrind", "--log-file=/tmp/xs_crashme.vglog", "-q", "./xenstored_test", "--output-pid",
  26.349 -		       "--no-fork", "--trace-file=/tmp/trace", NULL);
  26.350 -#else
  26.351 -		execlp("./xenstored_test", "xenstored_test", "--output-pid",
  26.352 -		       "--no-fork", NULL);
  26.353 -#endif
  26.354 -		exit(1);
  26.355 -	}
  26.356 -}
  26.357 -
  26.358 -
  26.359 -int main(int argc, char **argv)
  26.360 -{
  26.361 -	unsigned int i;
  26.362 -	int pid;
  26.363 -
  26.364 -	if (argc != 3 && argc != 4)
  26.365 -		barf("Usage: xs_crashme <iterations> <seed> [pid]");
  26.366 -
  26.367 -	if (argc == 3)
  26.368 -		pid = start_daemon();
  26.369 -	else
  26.370 -		pid = atoi(argv[3]);
  26.371 -
  26.372 -	state = atoi(argv[2]);
  26.373 -	h = xs_daemon_open();
  26.374 -	if (!h)
  26.375 -		barf_perror("Opening connection to daemon");
  26.376 -	signal(SIGALRM, alarmed);
  26.377 -	for (i = 0; i < (unsigned)atoi(argv[1]); i++) {
  26.378 -		alarm(1);
  26.379 -		do_next_op(h, false);
  26.380 -		if (i % (atoi(argv[1]) / 72 ?: 1) == 0) {
  26.381 -			printf(".");
  26.382 -			fflush(stdout);
  26.383 -		}
  26.384 -		if (kill(pid, 0) != 0)
  26.385 -			barf_perror("Pinging daemon on iteration %i", i);
  26.386 -		if (h->fd < 0) {
  26.387 -			xs_daemon_close(h);
  26.388 -			h = xs_daemon_open();
  26.389 -			if (!h)
  26.390 -				barf_perror("Connecting on iteration %i", i);
  26.391 -		}
  26.392 -	}
  26.393 -	kill(pid, SIGTERM);
  26.394 -	return 0;
  26.395 -}
  26.396 -
    27.1 --- a/tools/xenstore/xs_random.c	Tue Jul 03 15:49:16 2007 +0100
    27.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.3 @@ -1,1590 +0,0 @@
    27.4 -/* Random tests.
    27.5 -
    27.6 -   We check that the results from a real filesystem are the same.
    27.7 -*/
    27.8 -#include <sys/types.h>
    27.9 -#include <stdio.h>
   27.10 -#include <stdarg.h>
   27.11 -#include <stdlib.h>
   27.12 -#include <dirent.h>
   27.13 -#include <errno.h>
   27.14 -#include <sys/stat.h>
   27.15 -#include <unistd.h>
   27.16 -#include <fcntl.h>
   27.17 -#include <signal.h>
   27.18 -#include <sys/wait.h>
   27.19 -#include "xs.h"
   27.20 -#include "talloc.h"
   27.21 -#include "utils.h"
   27.22 -
   27.23 -struct ops
   27.24 -{
   27.25 -	char *name;
   27.26 -
   27.27 -	char **(*dir)(void *h, const char *path, unsigned int *num);
   27.28 -
   27.29 -	void *(*read)(void *h, const char *path, unsigned int *len);
   27.30 -
   27.31 -	bool (*write)(void *h, const char *path, const void *data,
   27.32 -		      unsigned int len);
   27.33 -
   27.34 -	bool (*mkdir)(void *h, const char *path);
   27.35 -
   27.36 -	bool (*rm)(void *h, const char *path);
   27.37 -
   27.38 -	struct xs_permissions *(*get_perms)(void *h,
   27.39 -					    const char *path,
   27.40 -					    unsigned int *num);
   27.41 -
   27.42 -	bool (*set_perms)(void *h,
   27.43 -			  const char *path,
   27.44 -			  struct xs_permissions *perms,
   27.45 -			  unsigned int num);
   27.46 -
   27.47 -	bool (*transaction_start)(void *h);
   27.48 -	bool (*transaction_end)(void *h, bool abort);
   27.49 -
   27.50 -	/* Create and destroy a new handle. */
   27.51 -	void *(*handle)(const char *path);
   27.52 -	void (*close)(void *);
   27.53 -};
   27.54 -
   27.55 -struct file_ops_info
   27.56 -{
   27.57 -	const char *base;
   27.58 -	char *transact_base;
   27.59 -};
   27.60 -
   27.61 -static void convert_to_dir(const char *dirname)
   27.62 -{
   27.63 -	char *tmpname = talloc_asprintf(dirname, "%s.tmp", dirname);
   27.64 -	if (rename(dirname, tmpname) != 0)
   27.65 -		barf_perror("Failed to rename %s to %s", dirname, tmpname);
   27.66 -	if (mkdir(dirname, 0700) != 0) 
   27.67 -		barf_perror("Failed to mkdir %s", dirname);
   27.68 -	if (rename(tmpname,talloc_asprintf(dirname, "%s/.DATA", dirname)) != 0)
   27.69 -		barf_perror("Failed to rename into %s", dirname);
   27.70 -	/* If perms exists, move it in. */
   27.71 -	rename(talloc_asprintf(dirname, "%s.perms", dirname),
   27.72 -	       talloc_asprintf(dirname, "%s/.perms", dirname));
   27.73 -}
   27.74 -
   27.75 -/* Files can be used as dirs, too.  Convert them when they are. */
   27.76 -static void maybe_convert_to_directory(const char *filename)
   27.77 -{
   27.78 -	struct stat st;
   27.79 -	char *dirname = talloc_asprintf(
   27.80 -		filename, "%.*s",
   27.81 -		(int)(strrchr(filename, '/') - filename), filename);
   27.82 -	if (lstat(dirname, &st) == 0 && S_ISREG(st.st_mode))
   27.83 -		convert_to_dir(dirname);
   27.84 -}
   27.85 -
   27.86 -static char *get_name(struct file_ops_info *info, const char *path)
   27.87 -{
   27.88 -	if (info->transact_base)
   27.89 -		return talloc_asprintf(path, "%s%s", info->transact_base,
   27.90 -				       path);
   27.91 -	return talloc_asprintf(path, "%s%s", info->base, path);
   27.92 -}
   27.93 -
   27.94 -static char *path_to_name(struct file_ops_info *info, const char *path)
   27.95 -{
   27.96 -	char *filename = get_name(info, path);
   27.97 -	maybe_convert_to_directory(filename);
   27.98 -	return filename;
   27.99 -}
  27.100 -
  27.101 -static char **file_directory(struct file_ops_info *info,
  27.102 -			     const char *path, unsigned int *num)
  27.103 -{
  27.104 -	char **ret;
  27.105 -	DIR *dir;
  27.106 -	struct dirent *dirent;
  27.107 -	char *p, *dirname = path_to_name(info, path);
  27.108 -	unsigned int i, len = 0;
  27.109 -	struct stat st;
  27.110 -
  27.111 -	/* If it exists, but isn't a directory, we convert it. */
  27.112 -	if (lstat(dirname, &st) == 0 && !S_ISDIR(st.st_mode))
  27.113 -		convert_to_dir(dirname);
  27.114 -
  27.115 -	*num = 0;
  27.116 -	dir = opendir(dirname);
  27.117 -	if (!dir)
  27.118 -		return NULL;;
  27.119 -
  27.120 -	/* Once to count them. */
  27.121 -	while ((dirent = readdir(dir)) != NULL) {
  27.122 -		if (strchr(dirent->d_name, '.'))
  27.123 -			continue;
  27.124 -		len += strlen(dirent->d_name) + 1;
  27.125 -		(*num)++;
  27.126 -	}
  27.127 -	rewinddir(dir);
  27.128 -
  27.129 -	/* Now allocate and fill in. */
  27.130 -	ret = malloc(sizeof(char *) * *num + len);
  27.131 -	p = (char *)&ret[*num];
  27.132 -	i = 0;
  27.133 -	while ((dirent = readdir(dir)) != NULL) {
  27.134 -		if (strchr(dirent->d_name, '.'))
  27.135 -			continue;
  27.136 -		ret[i] = p;
  27.137 -		strcpy(p, dirent->d_name);
  27.138 -		p += strlen(p) + 1;
  27.139 -		i++;
  27.140 -	}
  27.141 -	closedir(dir);
  27.142 -
  27.143 -	return ret;
  27.144 -}
  27.145 -
  27.146 -static char *filename_to_data(const char *filename)
  27.147 -{
  27.148 -	struct stat st;
  27.149 -
  27.150 -	if (lstat(filename, &st) == 0 && S_ISDIR(st.st_mode))
  27.151 -		return talloc_asprintf(filename, "%s/.DATA", filename);
  27.152 -	return (char *)filename;
  27.153 -}
  27.154 -
  27.155 -static void *file_read(struct file_ops_info *info,
  27.156 -		       const char *path, unsigned int *len)
  27.157 -{
  27.158 -	void *ret;
  27.159 -	char *filename = filename_to_data(path_to_name(info, path));
  27.160 -	unsigned long size;
  27.161 -
  27.162 -	ret = grab_file(filename, &size);
  27.163 -	/* Directory exists, .DATA doesn't. */
  27.164 -	if (!ret && errno == ENOENT && strends(filename, ".DATA")) {
  27.165 -		ret = strdup("");
  27.166 -		size = 0;
  27.167 -	}
  27.168 -	*len = size;
  27.169 -	return ret;
  27.170 -}
  27.171 -
  27.172 -static struct xs_permissions *file_get_perms(struct file_ops_info *info,
  27.173 -					     const char *path,
  27.174 -					     unsigned int *num)
  27.175 -{
  27.176 -	void *perms;
  27.177 -	struct xs_permissions *ret;
  27.178 -	char *filename = path_to_name(info, path);
  27.179 -	char *permfile;
  27.180 -	unsigned long size;
  27.181 -	struct stat st;
  27.182 -
  27.183 -	if (lstat(filename, &st) != 0)
  27.184 -		return NULL;
  27.185 -
  27.186 -	if (S_ISDIR(st.st_mode)) 
  27.187 -		permfile = talloc_asprintf(path, "%s/.perms", filename);
  27.188 -	else
  27.189 -		permfile = talloc_asprintf(path, "%s.perms", filename);
  27.190 -
  27.191 -	perms = grab_file(permfile, &size);
  27.192 -	if (!perms)
  27.193 -		barf("Grabbing permissions for %s", permfile);
  27.194 -	*num = xs_count_strings(perms, size);
  27.195 -
  27.196 -	ret = new_array(struct xs_permissions, *num);
  27.197 -	if (!xs_strings_to_perms(ret, *num, perms))
  27.198 -		barf("Reading permissions from %s", permfile);
  27.199 -	release_file(perms, size);
  27.200 -	return ret;
  27.201 -}
  27.202 -
  27.203 -static void do_command(const char *cmd)
  27.204 -{
  27.205 -	int ret;
  27.206 -
  27.207 -	ret = system(cmd);
  27.208 -	if (ret == -1 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
  27.209 -		barf_perror("Failed '%s': %i", cmd, ret);
  27.210 -}
  27.211 -
  27.212 -static void init_perms(const char *filename)
  27.213 -{
  27.214 -	struct stat st;
  27.215 -	char *permfile, *command;
  27.216 -
  27.217 -	if (lstat(filename, &st) != 0)
  27.218 -		barf_perror("Failed to stat %s", filename);
  27.219 -
  27.220 -	if (S_ISDIR(st.st_mode)) 
  27.221 -		permfile = talloc_asprintf(filename, "%s/.perms", filename);
  27.222 -	else
  27.223 -		permfile = talloc_asprintf(filename, "%s.perms", filename);
  27.224 -
  27.225 -	/* Leave permfile if it already exists. */
  27.226 -	if (lstat(permfile, &st) == 0)
  27.227 -		return;
  27.228 -
  27.229 -	/* Copy permissions from parent */
  27.230 -	command = talloc_asprintf(filename, "cp %.*s/.perms %s",
  27.231 -				  (int)(strrchr(filename, '/') - filename),
  27.232 -				  filename, permfile);
  27.233 -	do_command(command);
  27.234 -}	
  27.235 -
  27.236 -static bool file_set_perms(struct file_ops_info *info,
  27.237 -			   const char *path,
  27.238 -			   struct xs_permissions *perms,
  27.239 -			   unsigned int num)
  27.240 -{
  27.241 -	unsigned int i;
  27.242 -	char *filename = path_to_name(info, path);
  27.243 -	char *permfile;
  27.244 -	int fd;
  27.245 -	struct stat st;
  27.246 -
  27.247 -	if (num < 1) {
  27.248 -		errno = EINVAL;
  27.249 -		return false;
  27.250 -	}
  27.251 -
  27.252 -	/* Check non-perm file exists/ */
  27.253 -	if (lstat(filename, &st) != 0)
  27.254 -		return false;
  27.255 -
  27.256 -	if (S_ISDIR(st.st_mode)) 
  27.257 -		permfile = talloc_asprintf(path, "%s/.perms", filename);
  27.258 -	else
  27.259 -		permfile = talloc_asprintf(path, "%s.perms", filename);
  27.260 -
  27.261 -	fd = open(permfile, O_WRONLY|O_CREAT|O_TRUNC, 0600);
  27.262 -	if (fd < 0)
  27.263 -		return false;
  27.264 -
  27.265 -	for (i = 0; i < num; i++) {
  27.266 -		char buffer[100];
  27.267 -
  27.268 -		if (!xs_perm_to_string(&perms[i], buffer)) {
  27.269 -			int saved_errno = errno;
  27.270 -			close(fd);
  27.271 -			errno = saved_errno;
  27.272 -			return false;
  27.273 -		}
  27.274 -		if (write(fd, buffer, strlen(buffer) + 1)
  27.275 -		    != (int)strlen(buffer) + 1)
  27.276 -			barf_perror("Failed to write perm");
  27.277 -	}
  27.278 -	close(fd);
  27.279 -	return true;
  27.280 -}
  27.281 -
  27.282 -static char *parent_filename(const char *name)
  27.283 -{
  27.284 -	char *slash = strrchr(name + 1, '/');
  27.285 -	if (!slash)
  27.286 -		return talloc_strdup(name, "/");
  27.287 -	return talloc_asprintf(name, "%.*s", (int)(slash-name), name);
  27.288 -}
  27.289 -
  27.290 -static void make_dirs(const char *filename)
  27.291 -{
  27.292 -	struct stat st;
  27.293 -
  27.294 -	if (lstat(filename, &st) == 0 && S_ISREG(st.st_mode))
  27.295 -		convert_to_dir(filename);
  27.296 -
  27.297 -	if (mkdir(filename, 0700) == 0) {
  27.298 -		init_perms(filename);
  27.299 -		return;
  27.300 -	}
  27.301 -	if (errno == EEXIST)
  27.302 -		return;
  27.303 -
  27.304 -	make_dirs(parent_filename(filename));
  27.305 -	if (mkdir(filename, 0700) != 0)
  27.306 -		barf_perror("Failed to mkdir %s", filename);
  27.307 -	init_perms(filename);
  27.308 -}
  27.309 -
  27.310 -static bool file_write(struct file_ops_info *info,
  27.311 -		       const char *path, const void *data,
  27.312 -		       unsigned int len)
  27.313 -{
  27.314 -	char *filename = filename_to_data(path_to_name(info, path));
  27.315 -	int fd;
  27.316 -
  27.317 -	make_dirs(parent_filename(filename));
  27.318 -	fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0600);
  27.319 -	if (fd < 0)
  27.320 -		return false;
  27.321 -
  27.322 -	if (write(fd, data, len) != (int)len)
  27.323 -		barf_perror("Bad write to %s", filename);
  27.324 -
  27.325 -	init_perms(filename);
  27.326 -	close(fd);
  27.327 -	return true;
  27.328 -}
  27.329 -
  27.330 -static bool file_mkdir(struct file_ops_info *info, const char *path)
  27.331 -{
  27.332 -	char *dirname = path_to_name(info, path);
  27.333 -
  27.334 -	make_dirs(parent_filename(dirname));
  27.335 -	if (mkdir(dirname, 0700) != 0)
  27.336 -		return (errno == EEXIST);
  27.337 -
  27.338 -	init_perms(dirname);
  27.339 -	return true;
  27.340 -}
  27.341 -
  27.342 -static bool file_rm(struct file_ops_info *info, const char *path)
  27.343 -{
  27.344 -	char *filename = path_to_name(info, path);
  27.345 -	struct stat st;
  27.346 -
  27.347 -	if (lstat(filename, &st) != 0) {
  27.348 -		if (lstat(parent_filename(filename), &st) != 0)
  27.349 -			return false;
  27.350 -		return true;
  27.351 -	}
  27.352 -
  27.353 -	if (streq(path, "/")) {
  27.354 -		errno = EINVAL;
  27.355 -		return false;
  27.356 -	}
  27.357 -
  27.358 -	do_command(talloc_asprintf(path, "rm -f %s.perms; rm -r %s", 
  27.359 -				   filename, filename));
  27.360 -	return true;
  27.361 -}
  27.362 -
  27.363 -static bool file_transaction_start(struct file_ops_info *info)
  27.364 -{
  27.365 -	char *cmd;
  27.366 -
  27.367 -	if (info->transact_base) {
  27.368 -		errno = EBUSY;
  27.369 -		return false;
  27.370 -	}
  27.371 -
  27.372 -	info->transact_base = talloc_asprintf(NULL, "%s.transact", info->base);
  27.373 -	cmd = talloc_asprintf(NULL, "cp -r %s %s",
  27.374 -			      info->base, info->transact_base);
  27.375 -	do_command(cmd);
  27.376 -	talloc_free(cmd);
  27.377 -	return true;
  27.378 -}
  27.379 -
  27.380 -static bool file_transaction_end(struct file_ops_info *info, bool abort)
  27.381 -{
  27.382 -	char *old, *cmd;
  27.383 -
  27.384 -	if (!info->transact_base) {
  27.385 -		errno = ENOENT;
  27.386 -		return false;
  27.387 -	}
  27.388 -
  27.389 -	if (abort) {
  27.390 -		cmd = talloc_asprintf(NULL, "rm -rf %s", info->transact_base);
  27.391 -		do_command(cmd);
  27.392 -		goto success;
  27.393 -	}
  27.394 -
  27.395 -	old = talloc_asprintf(NULL, "rm -rf %s", info->base);
  27.396 -	do_command(old);
  27.397 -	talloc_free(old);
  27.398 -
  27.399 -	cmd = talloc_asprintf(NULL, "mv %s %s",
  27.400 -			      info->transact_base, info->base);
  27.401 -	do_command(cmd);
  27.402 -
  27.403 -success:
  27.404 -	talloc_free(cmd);
  27.405 -	talloc_free(info->transact_base);
  27.406 -	info->transact_base = NULL;
  27.407 -	return true;
  27.408 -}
  27.409 -
  27.410 -static struct file_ops_info *file_handle(const char *dir)
  27.411 -{
  27.412 -	struct file_ops_info *info = talloc(NULL, struct file_ops_info);
  27.413 -
  27.414 -	info->base = dir;
  27.415 -	info->transact_base = NULL;
  27.416 -	return info;
  27.417 -}
  27.418 -
  27.419 -static void file_close(struct file_ops_info *handle)
  27.420 -{
  27.421 -	talloc_free(handle);
  27.422 -}
  27.423 -
  27.424 -static struct xs_handle *xs_handle(const char *dir __attribute__((unused)))
  27.425 -{
  27.426 -	struct xs_handle *h;
  27.427 -
  27.428 -	h = xs_daemon_open();
  27.429 -	if (!h)
  27.430 -		barf_perror("Connecting to xs daemon");
  27.431 -	return h;
  27.432 -}
  27.433 -
  27.434 -static void xs_close(struct xs_handle *handle)
  27.435 -{
  27.436 -	xs_daemon_close(handle);
  27.437 -}
  27.438 -
  27.439 -struct ops file_ops = {
  27.440 -	.name = "FILE",
  27.441 -	.dir = (void *)file_directory,
  27.442 -	.read = (void *)file_read,
  27.443 -	.write = (void *)file_write,
  27.444 -	.mkdir = (void *)file_mkdir,
  27.445 -	.rm = (void *)file_rm,
  27.446 -	.get_perms = (void *)file_get_perms,
  27.447 -	.set_perms = (void *)file_set_perms,
  27.448 -	.transaction_start = (void *)file_transaction_start,
  27.449 -	.transaction_end = (void *)file_transaction_end,
  27.450 -	.handle = (void *)file_handle,
  27.451 -	.close = (void *)file_close,
  27.452 -};
  27.453 -
  27.454 -struct ops xs_ops = {
  27.455 -	.name = "XS",
  27.456 -	.dir = (void *)xs_directory,
  27.457 -	.read = (void *)xs_read,
  27.458 -	.write = (void *)xs_write,
  27.459 -	.mkdir = (void *)xs_mkdir,
  27.460 -	.rm = (void *)xs_rm,
  27.461 -	.get_perms = (void *)xs_get_permissions,
  27.462 -	.set_perms = (void *)xs_set_permissions,
  27.463 -	.transaction_start = (void *)xs_transaction_start,
  27.464 -	.transaction_end = (void *)xs_transaction_end,
  27.465 -	.handle = (void *)xs_handle,
  27.466 -	.close = (void *)xs_close,
  27.467 -};
  27.468 -
  27.469 -static int strptrcmp(const void *a, const void *b)
  27.470 -{
  27.471 -	return strcmp(*(char **)a, *(char **)b);
  27.472 -}
  27.473 -
  27.474 -static void sort_dir(char **dir, unsigned int num)
  27.475 -{
  27.476 -	qsort(dir, num, sizeof(char *), strptrcmp);
  27.477 -}
  27.478 -
  27.479 -static char *dump_dir(struct ops *ops,
  27.480 -		      void *h,
  27.481 -		      const char *node,
  27.482 -		      char **dir,
  27.483 -		      unsigned int numdirs,
  27.484 -		      unsigned int depth)
  27.485 -{
  27.486 -	char *ret = talloc_strdup(node, "");
  27.487 -	unsigned int i;
  27.488 -	char spacing[depth+1];
  27.489 -
  27.490 -	memset(spacing, ' ', depth);
  27.491 -	spacing[depth] = '\0';
  27.492 -
  27.493 -	sort_dir(dir, numdirs);
  27.494 -
  27.495 -	for (i = 0; i < numdirs; i++) {
  27.496 -		struct xs_permissions *perms;
  27.497 -		unsigned int j, numperms;
  27.498 -		unsigned int len;
  27.499 -		char *contents;
  27.500 -		unsigned int subnum;
  27.501 -		char **subdirs;
  27.502 -		char *subret;
  27.503 -		char *subnode = talloc_asprintf(node, "%s/%s", node, dir[i]);
  27.504 -
  27.505 -		perms = ops->get_perms(h, subnode, &numperms);
  27.506 -		if (!perms)
  27.507 -			return NULL;
  27.508 -		ret = talloc_asprintf_append(ret, "%s%s: ", spacing, dir[i]);
  27.509 -		for (j = 0; j < numperms; j++) {
  27.510 -			char buffer[100];
  27.511 -			if (!xs_perm_to_string(&perms[j], buffer))
  27.512 -				barf("perm to string");
  27.513 -			ret = talloc_asprintf_append(ret, "%s ", buffer);
  27.514 -		}
  27.515 -		free(perms);
  27.516 -		ret = talloc_asprintf_append(ret, "\n");
  27.517 -
  27.518 -		/* Even directories can have contents. */
  27.519 -		contents = ops->read(h, subnode, &len);
  27.520 -		if (!contents) {
  27.521 -			if (errno != EISDIR)
  27.522 -				return NULL;
  27.523 -		} else {
  27.524 -			ret = talloc_asprintf_append(ret, " %s(%.*s)\n",
  27.525 -						     spacing, len, contents);
  27.526 -			free(contents);
  27.527 -		}			
  27.528 -
  27.529 -		/* Every node is a directory. */
  27.530 -		subdirs = ops->dir(h, subnode, &subnum);
  27.531 -		if (!subdirs)
  27.532 -			return NULL;
  27.533 -		subret = dump_dir(ops, h, subnode, subdirs, subnum, depth+1);
  27.534 -		if (!subret)
  27.535 -			return NULL;
  27.536 -		ret = talloc_asprintf_append(ret, "%s", subret);
  27.537 -		free(subdirs);
  27.538 -	}
  27.539 -	return ret;
  27.540 -}
  27.541 -
  27.542 -static char *dump(struct ops *ops, void *h)
  27.543 -{
  27.544 -	char **subdirs;
  27.545 -	unsigned int subnum;
  27.546 -	char *ret = NULL, *root = talloc_strdup(NULL, "/");
  27.547 -
  27.548 -	subdirs = ops->dir(h, root, &subnum);
  27.549 -	if (subdirs) {
  27.550 -		ret = dump_dir(ops, h, talloc_strdup(root, ""), subdirs,
  27.551 -			       subnum, 0);
  27.552 -		free(subdirs);
  27.553 -		if (ret)
  27.554 -			talloc_steal(NULL, ret);
  27.555 -	}
  27.556 -	talloc_free(root);
  27.557 -	return ret;
  27.558 -}
  27.559 -
  27.560 -/* jhash.h: Jenkins hash support.
  27.561 - *
  27.562 - * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
  27.563 - *
  27.564 - * http://burtleburtle.net/bob/hash/
  27.565 - *
  27.566 - * These are the credits from Bob's sources:
  27.567 - *
  27.568 - * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
  27.569 - * hash(), hash2(), hash3, and mix() are externally useful functions.
  27.570 - * Routines to test the hash are included if SELF_TEST is defined.
  27.571 - * You can use this free for any purpose.  It has no warranty.
  27.572 - *
  27.573 - * Copyright (C) 2003 David S. Miller (davem@redhat.com)
  27.574 - *
  27.575 - * I've modified Bob's hash to be useful in the Linux kernel, and
  27.576 - * any bugs present are surely my fault.  -DaveM
  27.577 - */
  27.578 -
  27.579 -/* NOTE: Arguments are modified. */
  27.580 -#define __jhash_mix(a, b, c) \
  27.581 -{ \
  27.582 -  a -= b; a -= c; a ^= (c>>13); \
  27.583 -  b -= c; b -= a; b ^= (a<<8); \
  27.584 -  c -= a; c -= b; c ^= (b>>13); \
  27.585 -  a -= b; a -= c; a ^= (c>>12);  \
  27.586 -  b -= c; b -= a; b ^= (a<<16); \
  27.587 -  c -= a; c -= b; c ^= (b>>5); \
  27.588 -  a -= b; a -= c; a ^= (c>>3);  \
  27.589 -  b -= c; b -= a; b ^= (a<<10); \
  27.590 -  c -= a; c -= b; c ^= (b>>15); \
  27.591 -}
  27.592 -
  27.593 -/* The golden ration: an arbitrary value */
  27.594 -#define JHASH_GOLDEN_RATIO	0x9e3779b9
  27.595 -
  27.596 -/* The most generic version, hashes an arbitrary sequence
  27.597 - * of bytes.  No alignment or length assumptions are made about
  27.598 - * the input key.
  27.599 - */
  27.600 -static inline uint32_t jhash(const void *key, uint32_t length, uint32_t initval)
  27.601 -{
  27.602 -	uint32_t a, b, c, len;
  27.603 -	const uint8_t *k = key;
  27.604 -
  27.605 -	len = length;
  27.606 -	a = b = JHASH_GOLDEN_RATIO;
  27.607 -	c = initval;
  27.608 -
  27.609 -	while (len >= 12) {
  27.610 -		a += (k[0] +((uint32_t)k[1]<<8) +((uint32_t)k[2]<<16) +((uint32_t)k[3]<<24));
  27.611 -		b += (k[4] +((uint32_t)k[5]<<8) +((uint32_t)k[6]<<16) +((uint32_t)k[7]<<24));
  27.612 -		c += (k[8] +((uint32_t)k[9]<<8) +((uint32_t)k[10]<<16)+((uint32_t)k[11]<<24));
  27.613 -
  27.614 -		__jhash_mix(a,b,c);
  27.615 -
  27.616 -		k += 12;
  27.617 -		len -= 12;
  27.618 -	}
  27.619 -
  27.620 -	c += length;
  27.621 -	switch (len) {
  27.622 -	case 11: c += ((uint32_t)k[10]<<24);
  27.623 -	case 10: c += ((uint32_t)k[9]<<16);
  27.624 -	case 9 : c += ((uint32_t)k[8]<<8);
  27.625 -	case 8 : b += ((uint32_t)k[7]<<24);
  27.626 -	case 7 : b += ((uint32_t)k[6]<<16);
  27.627 -	case 6 : b += ((uint32_t)k[5]<<8);
  27.628 -	case 5 : b += k[4];
  27.629 -	case 4 : a += ((uint32_t)k[3]<<24);
  27.630 -	case 3 : a += ((uint32_t)k[2]<<16);
  27.631 -	case 2 : a += ((uint32_t)k[1]<<8);
  27.632 -	case 1 : a += k[0];
  27.633 -	};
  27.634 -
  27.635 -	__jhash_mix(a,b,c);
  27.636 -
  27.637 -	return c;
  27.638 -}
  27.639 -
  27.640 -/* A special optimized version that handles 1 or more of uint32_ts.
  27.641 - * The length parameter here is the number of uint32_ts in the key.
  27.642 - */
  27.643 -static inline uint32_t jhash2(uint32_t *k, uint32_t length, uint32_t initval)
  27.644 -{
  27.645 -	uint32_t a, b, c, len;
  27.646 -
  27.647 -	a = b = JHASH_GOLDEN_RATIO;
  27.648 -	c = initval;
  27.649 -	len = length;
  27.650 -
  27.651 -	while (len >= 3) {
  27.652 -		a += k[0];
  27.653 -		b += k[1];
  27.654 -		c += k[2];
  27.655 -		__jhash_mix(a, b, c);
  27.656 -		k += 3; len -= 3;
  27.657 -	}
  27.658 -
  27.659 -	c += length * 4;
  27.660 -
  27.661 -	switch (len) {
  27.662 -	case 2 : b += k[1];
  27.663 -	case 1 : a += k[0];
  27.664 -	};
  27.665 -
  27.666 -	__jhash_mix(a,b,c);
  27.667 -
  27.668 -	return c;
  27.669 -}
  27.670 -
  27.671 -
  27.672 -/* A special ultra-optimized versions that knows they are hashing exactly
  27.673 - * 3, 2 or 1 word(s).
  27.674 - *
  27.675 - * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
  27.676 - *       done at the end is not done here.
  27.677 - */
  27.678 -static inline uint32_t jhash_3words(uint32_t a, uint32_t b, uint32_t c, uint32_t initval)
  27.679 -{
  27.680 -	a += JHASH_GOLDEN_RATIO;
  27.681 -	b += JHASH_GOLDEN_RATIO;
  27.682 -	c += initval;
  27.683 -
  27.684 -	__jhash_mix(a, b, c);
  27.685 -
  27.686 -	return c;
  27.687 -}
  27.688 -
  27.689 -static inline uint32_t jhash_2words(uint32_t a, uint32_t b, uint32_t initval)
  27.690 -{
  27.691 -	return jhash_3words(a, b, 0, initval);
  27.692 -}
  27.693 -
  27.694 -static inline uint32_t jhash_1word(uint32_t a, uint32_t initval)
  27.695 -{
  27.696 -	return jhash_3words(a, 0, 0, initval);
  27.697 -}
  27.698 -
  27.699 -static unsigned int get_randomness(int *state)
  27.700 -{
  27.701 -	return jhash_1word((*state)++, *state * 1103515243);
  27.702 -}
  27.703 -
  27.704 -static char *random_path(int *state)
  27.705 -{
  27.706 -	unsigned int i;
  27.707 -	char *ret = NULL;
  27.708 -
  27.709 -	if (get_randomness(state) % 20 == 0)
  27.710 -		return talloc_strdup(NULL, "/");
  27.711 -
  27.712 -	for (i = 0; i < 1 || (get_randomness(state) % 2); i++) {
  27.713 -		ret = talloc_asprintf_append(ret, "/%i", 
  27.714 -					     get_randomness(state) % 15);
  27.715 -	}
  27.716 -	return ret;
  27.717 -}
  27.718 -
  27.719 -static char *bool_to_errstring(bool result)
  27.720 -{
  27.721 -	if (result)
  27.722 -		return talloc_strdup(NULL, "OK");
  27.723 -
  27.724 -	/* Real daemon can never return this. */
  27.725 -	if (errno == ENOTDIR)
  27.726 -		errno = ENOENT;
  27.727 -	return talloc_asprintf(NULL, "FAILED:%s", strerror(errno));
  27.728 -}
  27.729 -
  27.730 -static char *linearize_dir(char **dir, unsigned int *num)
  27.731 -{
  27.732 -	char *result = NULL;
  27.733 -	unsigned int i;
  27.734 -
  27.735 -	if (!dir)
  27.736 -		return bool_to_errstring(false);
  27.737 -
  27.738 -	if (!*num) {
  27.739 -		free(dir);
  27.740 -		return talloc_strdup(NULL, "");
  27.741 -	}
  27.742 -
  27.743 -	sort_dir(dir, *num);
  27.744 -	for (i = 0; i < *num; i++)
  27.745 -		result = talloc_asprintf_append(result, "%s\n", dir[i]);
  27.746 -	free(dir);
  27.747 -	return result;
  27.748 -}
  27.749 -
  27.750 -static char *linearize_read(char *read, unsigned int *size)
  27.751 -{
  27.752 -	char *ret;
  27.753 -
  27.754 -	if (!read)
  27.755 -		return bool_to_errstring(false);
  27.756 -
  27.757 -	ret = talloc_asprintf(NULL, "%i:%.*s", *size, *size, read);
  27.758 -	free(read);
  27.759 -	return ret;
  27.760 -}
  27.761 -
  27.762 -static char *linearize_perms(struct xs_permissions *perms, unsigned int *size)
  27.763 -{
  27.764 -	char *ret = NULL;
  27.765 -	unsigned int i;
  27.766 -
  27.767 -	if (!perms)
  27.768 -		return bool_to_errstring(false);
  27.769 -
  27.770 -	for (i = 0; i < *size; i++)
  27.771 -		ret = talloc_asprintf_append(ret, "(%u %u)",
  27.772 -					     perms[i].id, perms[i].perms);
  27.773 -
  27.774 -	free(perms);
  27.775 -	return ret;
  27.776 -}
  27.777 -
  27.778 -/* Do the next operation, return the results. */
  27.779 -static char *do_next_op(struct ops *ops, void *h, int state, bool verbose)
  27.780 -{
  27.781 -	char *name;
  27.782 -	unsigned int num;
  27.783 -	char *ret;
  27.784 -
  27.785 -	if (verbose)
  27.786 -		printf("State %i: ", state);
  27.787 -
  27.788 -	name = random_path(&state);
  27.789 -	switch (get_randomness(&state) % 9) {
  27.790 -	case 0:
  27.791 -		if (verbose)
  27.792 -			printf("DIR %s\n", name);
  27.793 -		ret = linearize_dir(ops->dir(h, name, &num), &num);
  27.794 -		break;
  27.795 -	case 1:
  27.796 -		if (verbose)
  27.797 -			printf("READ %s\n", name);
  27.798 -		ret = linearize_read(ops->read(h, name, &num), &num);
  27.799 -		break;
  27.800 -	case 2: {
  27.801 -		char *contents = talloc_asprintf(NULL, "%i",
  27.802 -						 get_randomness(&state));
  27.803 -		unsigned int len = get_randomness(&state)%(strlen(contents)+1);
  27.804 -		if (verbose)
  27.805 -			printf("WRITE %s %.*s\n", name, len, contents);
  27.806 -		ret = bool_to_errstring(ops->write(h, name, contents, len));
  27.807 -		talloc_steal(ret, contents);
  27.808 -		break;
  27.809 -	}
  27.810 -	case 3:
  27.811 -		if (verbose)
  27.812 -			printf("MKDIR %s\n", name);
  27.813 -		ret = bool_to_errstring(ops->mkdir(h, name));
  27.814 -		break;
  27.815 -	case 4:
  27.816 -		if (verbose)
  27.817 -			printf("RM %s\n", name);
  27.818 -		ret = bool_to_errstring(ops->rm(h, name));
  27.819 -		break;
  27.820 -	case 5:
  27.821 -		if (verbose)
  27.822 -			printf("GETPERMS %s\n", name);
  27.823 -		ret = linearize_perms(ops->get_perms(h, name, &num),
  27.824 -				      &num);
  27.825 -		break;
  27.826 -	case 6: {
  27.827 -		unsigned int i, num = get_randomness(&state)%8;
  27.828 -		struct xs_permissions perms[num];
  27.829 -
  27.830 -		if (verbose)
  27.831 -			printf("SETPERMS %s: ", name);
  27.832 -		for (i = 0; i < num; i++) {
  27.833 -			perms[i].id = get_randomness(&state)%8;
  27.834 -			perms[i].perms = get_randomness(&state)%4;
  27.835 -			if (verbose)
  27.836 -				printf("%i%c ", perms[i].id,
  27.837 -				       perms[i].perms == XS_PERM_WRITE ? 'W'
  27.838 -				       : perms[i].perms == XS_PERM_READ ? 'R'
  27.839 -				       : perms[i].perms == 
  27.840 -				       (XS_PERM_READ|XS_PERM_WRITE) ? 'B'
  27.841 -				       : 'N');
  27.842 -		}
  27.843 -		if (verbose)
  27.844 -			printf("\n");
  27.845 -		ret = bool_to_errstring(ops->set_perms(h, name, perms,
  27.846 -						       num));
  27.847 -		break;
  27.848 -	}
  27.849 -	case 7: {
  27.850 -		if (verbose)
  27.851 -			printf("START %s\n", name);
  27.852 -		ret = bool_to_errstring(ops->transaction_start(h));
  27.853 -		if (streq(ret, "OK")) {
  27.854 -			talloc_free(ret);
  27.855 -			ret = talloc_asprintf(NULL, "OK:START-TRANSACT");
  27.856 -		}
  27.857 -
  27.858 -		break;
  27.859 -	}
  27.860 -	case 8: {
  27.861 -		bool abort = (get_randomness(&state) % 2);
  27.862 -
  27.863 -		if (verbose)
  27.864 -			printf("STOP %s\n", abort ? "ABORT" : "COMMIT");
  27.865 -		ret = bool_to_errstring(ops->transaction_end(h, abort));
  27.866 -		if (streq(ret, "OK")) {
  27.867 -			talloc_free(ret);
  27.868 -			ret = talloc_strdup(NULL, "OK:STOP-TRANSACT");
  27.869 -		}
  27.870 -		break;
  27.871 -	}
  27.872 -	default:
  27.873 -		barf("Impossible randomness");
  27.874 -	}
  27.875 -
  27.876 -	talloc_steal(ret, name);
  27.877 -	return ret;
  27.878 -}
  27.879 -
  27.880 -static int daemon_pid;
  27.881 -
  27.882 -static void cleanup_xs_ops(void)
  27.883 -{
  27.884 -	char *cmd;
  27.885 -
  27.886 -	if (daemon_pid) {
  27.887 -		kill(daemon_pid, SIGTERM);
  27.888 -		waitpid(daemon_pid, NULL, 0);
  27.889 -		daemon_pid = 0;
  27.890 -	}
  27.891 -	
  27.892 -	cmd = talloc_asprintf(NULL, "rm -rf testsuite/tmp/*");
  27.893 -	do_command(cmd);
  27.894 -	talloc_free(cmd);
  27.895 -}
  27.896 -
  27.897 -static void cleanup_file_ops(const char *dir)
  27.898 -{
  27.899 -	char *cmd;
  27.900 -
  27.901 -	cmd = talloc_asprintf(NULL, "rm -rf %s %s.transact", dir, dir);
  27.902 -	do_command(cmd);
  27.903 -	talloc_free(cmd);
  27.904 -}
  27.905 -
  27.906 -static void cleanup(const char *dir)
  27.907 -{
  27.908 -	cleanup_xs_ops();
  27.909 -	cleanup_file_ops(dir);
  27.910 -}
  27.911 -
  27.912 -static void setup_file_ops(const char *dir)
  27.913 -{
  27.914 -	struct xs_permissions perm = { .id = 0, .perms = XS_PERM_READ };
  27.915 -	struct file_ops_info *h = file_handle(dir);
  27.916 -	if (mkdir(dir, 0700) != 0)
  27.917 -		barf_perror("Creating directory %s", dir);
  27.918 -	if (mkdir(talloc_asprintf(h, "%s/tool", dir), 0700) != 0)
  27.919 -		barf_perror("Creating directory %s/tool", dir);
  27.920 -	if (!file_set_perms(h, talloc_strdup(h, "/"), &perm, 1))
  27.921 -		barf_perror("Setting root perms in %s", dir);
  27.922 -	if (!file_set_perms(h, talloc_strdup(h, "/tool"), &perm, 1))
  27.923 -		barf_perror("Setting root perms in %s/tool", dir);
  27.924 -	file_close(h);
  27.925 -}
  27.926 -
  27.927 -static void setup_xs_ops(void)
  27.928 -{
  27.929 -	int fds[2];
  27.930 -
  27.931 -	/* Start daemon. */
  27.932 -	pipe(fds);
  27.933 -	if ((daemon_pid = fork())) {
  27.934 -		/* Child writes PID when its ready: we wait for that. */
  27.935 -		char buffer[20];
  27.936 -		close(fds[1]);
  27.937 -		if (read(fds[0], buffer, sizeof(buffer)) < 0)
  27.938 -			barf("Failed to summon daemon");
  27.939 -		close(fds[0]);
  27.940 -	} else {
  27.941 -		dup2(fds[1], STDOUT_FILENO);
  27.942 -		close(fds[0]);
  27.943 -#if 1
  27.944 -		execlp("valgrind", "valgrind", "-q", "--suppressions=testsuite/vg-suppressions", "xenstored_test", "--output-pid",
  27.945 -		       "--no-fork", NULL);
  27.946 -#else
  27.947 -		execlp("./xenstored_test", "xenstored_test", "--output-pid",
  27.948 -		       "--no-fork", NULL);
  27.949 -#endif
  27.950 -		exit(1);
  27.951 -	}
  27.952 -}
  27.953 -
  27.954 -static void setup(const char *dir)
  27.955 -{
  27.956 -	setup_file_ops(dir);
  27.957 -	setup_xs_ops();
  27.958 -};
  27.959 -
  27.960 -struct simple_data
  27.961 -{
  27.962 -	unsigned int seed;
  27.963 -	bool print_progress;
  27.964 -	bool fast;
  27.965 -	struct ops *ops;
  27.966 -	const char *dir;
  27.967 -};
  27.968 -
  27.969 -/* Just a random test.  Don't care about results, just that it doesn't
  27.970 - * go boom. */
  27.971 -static unsigned int try_simple(const bool *trymap,
  27.972 -			       unsigned int number,
  27.973 -			       bool verbose,
  27.974 -			       void *_data)
  27.975 -{
  27.976 -	unsigned int i, print;
  27.977 -	void *h;
  27.978 -	char *snapshot = NULL;
  27.979 -	struct simple_data *data = _data;
  27.980 -
  27.981 -	if (data->ops == &xs_ops) {
  27.982 -		cleanup_xs_ops();
  27.983 -		setup_xs_ops();
  27.984 -	} else {
  27.985 -		cleanup_file_ops(data->dir);
  27.986 -		setup_file_ops(data->dir);
  27.987 -	}
  27.988 -	h = data->ops->handle(data->dir);
  27.989 -
  27.990 -	print = number / 76;
  27.991 -	if (!print)
  27.992 -		print = 1;
  27.993 -
  27.994 -	for (i = 0; i < number; i++) {
  27.995 -		char *ret;
  27.996 -
  27.997 -		if (data->print_progress) {
  27.998 -			if (i % print == 0) {
  27.999 -				printf(".");
 27.1000 -				fflush(stdout);
 27.1001 -			}
 27.1002 -		}
 27.1003 -
 27.1004 -		if (trymap && !trymap[i])
 27.1005 -			continue;
 27.1006 -
 27.1007 -		ret = do_next_op(data->ops, h, i + data->seed, verbose);
 27.1008 -		if (verbose)
 27.1009 -			printf("-> %.*s\n",
 27.1010 -			       (int)(strchr(ret, '\n') - ret), ret);
 27.1011 -		if (streq(ret, "FAILED:Bad file descriptor"))
 27.1012 -			goto out;
 27.1013 -		if (kill(daemon_pid, 0) != 0)
 27.1014 -			goto out;
 27.1015 -
 27.1016 -		if (!data->fast) {
 27.1017 -			if (streq(ret, "OK:START-TRANSACT")) {
 27.1018 -				void *pre = data->ops->handle(data->dir);
 27.1019 -
 27.1020 -				snapshot = dump(data->ops, pre);
 27.1021 -				if (!snapshot)
 27.1022 -					goto out;
 27.1023 -				data->ops->close(pre);
 27.1024 -			} else if (streq(ret, "OK:STOP-TRANSACT")) {
 27.1025 -				talloc_free(snapshot);
 27.1026 -				snapshot = NULL;
 27.1027 -			}
 27.1028 -		}
 27.1029 -
 27.1030 -		talloc_free(ret);
 27.1031 -
 27.1032 -		if (snapshot) {
 27.1033 -			void *pre = data->ops->handle(data->dir);
 27.1034 -			char *contents;
 27.1035 -
 27.1036 -			contents = dump(data->ops, pre);
 27.1037 -			if (!contents)
 27.1038 -				goto out;
 27.1039 -
 27.1040 -			if (!streq(contents, snapshot))
 27.1041 -				goto out;
 27.1042 -
 27.1043 -			talloc_free(contents);
 27.1044 -			data->ops->close(pre);
 27.1045 -		}
 27.1046 -	}
 27.1047 -out:
 27.1048 -	data->ops->close(h);	
 27.1049 -	return i;
 27.1050 -}
 27.1051 -
 27.1052 -/* Binary elimination: try eliminating all of them, then reduce. */
 27.1053 -static void reduce(bool *map,
 27.1054 -		   unsigned int number,
 27.1055 -		   unsigned int try_start, unsigned int try_num,
 27.1056 -		   unsigned int (*try)(const bool *map,
 27.1057 -				       unsigned int number,
 27.1058 -				       bool verbose,
 27.1059 -				       void *),
 27.1060 -		   void *data)
 27.1061 -{
 27.1062 -	bool newmap[number];
 27.1063 -
 27.1064 -	if (try_num == 0)
 27.1065 -		return;
 27.1066 -
 27.1067 -	/* Try skipping everything between start and end.  */
 27.1068 -	memcpy(newmap, map, sizeof(newmap));
 27.1069 -	memset(newmap + try_start, 0, try_num * sizeof(bool));
 27.1070 -
 27.1071 -	/* We want the *same* failure: must fail at "number-1". */
 27.1072 -	if (try(newmap, number, false, data) == number - 1) {
 27.1073 -		memset(map + try_start, 0, try_num * sizeof(bool));
 27.1074 -		return;
 27.1075 -	}
 27.1076 -
 27.1077 -	if (try_num == 1)
 27.1078 -		return;
 27.1079 -
 27.1080 -	/* Try each half... */
 27.1081 -	reduce(map, number, try_start, try_num/2, try, data);
 27.1082 -	reduce(map, number, try_start + try_num/2, try_num - try_num/2,
 27.1083 -	       try, data);
 27.1084 -}
 27.1085 -
 27.1086 -static void reduce_problem(unsigned int failed,
 27.1087 -			   unsigned int (*try)(const bool *map,
 27.1088 -					       unsigned int number,
 27.1089 -					       bool verbose,
 27.1090 -					       void *data),
 27.1091 -			   void *data)
 27.1092 -{
 27.1093 -	bool map[failed];
 27.1094 -
 27.1095 -	memset(map, 1, sizeof(map));
 27.1096 -	reduce(map, failed, 0, failed-1, try, data);
 27.1097 -
 27.1098 -	printf("Cut down:\n");
 27.1099 -	if (try(map, failed, true, data) != failed - 1) {
 27.1100 -		printf("Except, that didn't actually fail.  Bugger!");
 27.1101 -		exit(2);
 27.1102 -	}
 27.1103 -	exit(1);
 27.1104 -}
 27.1105 -
 27.1106 -/* Just a random test.  Don't care about results, just that it doesn't
 27.1107 - * go boom. */
 27.1108 -static void simple_test(const char *dir,
 27.1109 -			unsigned int iters, unsigned int seed,
 27.1110 -			bool fast, bool verbose)
 27.1111 -{
 27.1112 -	struct simple_data data;
 27.1113 -	unsigned int try;
 27.1114 -
 27.1115 -	data.seed = seed;
 27.1116 -	data.print_progress = !verbose;
 27.1117 -	data.fast = fast;
 27.1118 -	data.ops = &xs_ops;
 27.1119 -	data.dir = dir;
 27.1120 -
 27.1121 -	try = try_simple(NULL, iters, verbose, &data);
 27.1122 -	if (try == iters) {
 27.1123 -		cleanup_xs_ops();
 27.1124 -		exit(0);
 27.1125 -	}
 27.1126 -	printf("Failed on iteration %u of seed %u\n", try + 1, seed);
 27.1127 -	data.print_progress = false;
 27.1128 -	reduce_problem(try + 1, try_simple, &data);
 27.1129 -}
 27.1130 -
 27.1131 -static bool ops_equal(struct ops *a, void *ah,
 27.1132 -		      struct ops *b, void *bh,
 27.1133 -		      const char *node,
 27.1134 -		      struct ops **fail)
 27.1135 -{
 27.1136 -	char **dira = NULL, **dirb = NULL;
 27.1137 -	char *dataa = NULL, *datab = NULL;
 27.1138 -	unsigned int i, numa, numb, lena, lenb;
 27.1139 -	struct xs_permissions *permsa = NULL, *permsb = NULL;
 27.1140 -	unsigned int numpermsa, numpermsb;
 27.1141 -	char *nodename;
 27.1142 -	bool ret = false;
 27.1143 -
 27.1144 -	/* Ignore tool/ dir. */
 27.1145 -	if (streq(node, "/tool"))
 27.1146 -		return true;
 27.1147 -
 27.1148 -	/* FILE backend expects talloc'ed pointer. */
 27.1149 -	nodename = talloc_strdup(NULL, node);
 27.1150 -	permsa = a->get_perms(ah, nodename, &numpermsa);
 27.1151 -	if (!permsa) {
 27.1152 -		*fail = a;
 27.1153 -		goto out;
 27.1154 -	}
 27.1155 -	permsb = b->get_perms(bh, nodename, &numpermsb);
 27.1156 -	if (!permsb) {
 27.1157 -		*fail = b;
 27.1158 -		goto out;
 27.1159 -	}
 27.1160 -	if (numpermsa != numpermsb)
 27.1161 -		goto out;
 27.1162 -	for (i = 0; i < numpermsa; i++) {
 27.1163 -		if (permsa[i].perms != permsb[i].perms)
 27.1164 -			goto out;
 27.1165 -		if (permsa[i].id != permsb[i].id)
 27.1166 -			goto out;
 27.1167 -	}
 27.1168 -
 27.1169 -	/* Non-pure-directory nodes contain data. */
 27.1170 -	dataa = a->read(ah, nodename, &lena);
 27.1171 -	if (!dataa && errno != EISDIR) {
 27.1172 -		*fail = a;
 27.1173 -		goto out;
 27.1174 -	}
 27.1175 -	datab = b->read(bh, nodename, &lenb);
 27.1176 -	if (!datab && errno != EISDIR) {
 27.1177 -		*fail = b;
 27.1178 -		goto out;
 27.1179 -	}
 27.1180 -
 27.1181 -	if (dataa) {
 27.1182 -		if (!datab)
 27.1183 -			goto out;
 27.1184 -		if (lena != lenb)
 27.1185 -			goto out;
 27.1186 -
 27.1187 -		if (memcmp(dataa, datab, lena) != 0)
 27.1188 -			goto out;
 27.1189 -	} else
 27.1190 -		if (datab)
 27.1191 -			goto out;
 27.1192 -
 27.1193 -	/* Everything is a directory. */
 27.1194 -	dira = a->dir(ah, nodename, &numa);
 27.1195 -	if (!dira) {
 27.1196 -		*fail = a;
 27.1197 -		goto out;
 27.1198 -	}
 27.1199 -	dirb = b->dir(bh, nodename, &numb);
 27.1200 -	if (!dirb) {
 27.1201 -		*fail = b;
 27.1202 -		goto out;
 27.1203 -	}
 27.1204 -	if (numa != numb)
 27.1205 -		goto out;
 27.1206 -	sort_dir(dira, numa);
 27.1207 -	sort_dir(dirb, numb);
 27.1208 -	for (i = 0; i < numa; i++) {
 27.1209 -		char subnode[strlen(node) + 1 + strlen(dira[i]) + 1];
 27.1210 -
 27.1211 -		if (!streq(dira[i], dirb[i]))
 27.1212 -			goto out;
 27.1213 -
 27.1214 -		strcpy(subnode, node);
 27.1215 -		if (!streq(node, "/"))
 27.1216 -			strcat(subnode, "/");
 27.1217 -		strcat(subnode, dira[i]);
 27.1218 -		if (!ops_equal(a, ah, b, bh, subnode, fail))
 27.1219 -			goto out;
 27.1220 -	}
 27.1221 -
 27.1222 -	ret = true;
 27.1223 -out:
 27.1224 -	free(permsa);
 27.1225 -	free(permsb);
 27.1226 -	free(dataa);
 27.1227 -	free(datab);
 27.1228 -	free(dira);
 27.1229 -	free(dirb);
 27.1230 -	talloc_free(nodename);
 27.1231 -	return ret;
 27.1232 -}
 27.1233 -
 27.1234 -struct diff_data
 27.1235 -{
 27.1236 -	unsigned int seed;
 27.1237 -	bool print_progress;
 27.1238 -	bool fast;
 27.1239 -	const char *dir;
 27.1240 -};
 27.1241 -
 27.1242 -/* Differential: try both file and xs backend, watch for differences. */
 27.1243 -static unsigned int try_diff(const bool *trymap,
 27.1244 -			     unsigned int number,
 27.1245 -			     bool verbose,
 27.1246 -			     void *_data)
 27.1247 -{
 27.1248 -	void *fileh, *xsh;
 27.1249 -	bool transact = false;
 27.1250 -	struct ops *fail;
 27.1251 -	struct diff_data *data = _data;
 27.1252 -	unsigned int i, print;
 27.1253 -
 27.1254 -	cleanup(data->dir);
 27.1255 -	setup(data->dir);
 27.1256 -
 27.1257 -	fileh = file_handle(data->dir);
 27.1258 -	xsh = xs_handle(data->dir);
 27.1259 -
 27.1260 -	print = number / 76;
 27.1261 -	if (!print)
 27.1262 -		print = 1;
 27.1263 -
 27.1264 -	for (i = 0; i < number; i++) {
 27.1265 -		char *file, *xs;
 27.1266 -
 27.1267 -		if (data->print_progress) {
 27.1268 -			if (i % print == 0) {
 27.1269 -				printf(".");
 27.1270 -				fflush(stdout);
 27.1271 -			}
 27.1272 -		}
 27.1273 -		if (trymap && !trymap[i])
 27.1274 -			continue;
 27.1275 -
 27.1276 -		if (verbose)
 27.1277 -			printf("FILE: ");
 27.1278 -
 27.1279 -		file = do_next_op(&file_ops, fileh, i+data->seed, verbose);
 27.1280 -		if (verbose)
 27.1281 -			printf("-> %.*s\n",
 27.1282 -			       (int)(strchr(file, '/') - file), file);
 27.1283 -		
 27.1284 -		if (verbose)
 27.1285 -			printf("XS: ");
 27.1286 -		xs = do_next_op(&xs_ops, xsh, i+data->seed, verbose);
 27.1287 -		if (verbose)
 27.1288 -			printf("-> %.*s\n", (int)(strchr(xs, '/') - xs), xs);
 27.1289 -
 27.1290 -		if (!streq(file, xs))
 27.1291 -			goto out;
 27.1292 -
 27.1293 -		if (strstarts(file, "OK:START-TRANSACT:"))
 27.1294 -			transact = true;
 27.1295 -		else if (streq(file, "OK:STOP-TRANSACT"))
 27.1296 -			transact = false;
 27.1297 -
 27.1298 -		talloc_free(file);
 27.1299 -		talloc_free(xs);
 27.1300 -
 27.1301 -		if (data->fast)
 27.1302 -			continue;
 27.1303 -
 27.1304 -		fail = NULL;
 27.1305 -		if (!ops_equal(&xs_ops, xsh, &file_ops, fileh, "/", &fail)) {
 27.1306 -			if (fail)
 27.1307 -				barf("%s failed during test\n", fail->name);
 27.1308 -			if (verbose)
 27.1309 -				printf("Trees differ:\nXS:%s\nFILE%s\n",
 27.1310 -				       dump(&xs_ops, xsh),
 27.1311 -				       dump(&file_ops, fileh));
 27.1312 -			goto out;
 27.1313 -		}
 27.1314 -
 27.1315 -		if (transact) {
 27.1316 -			void *fileh_pre = file_handle(data->dir);
 27.1317 -			void *xsh_pre = xs_handle(data->dir);
 27.1318 -
 27.1319 -			fail = NULL;
 27.1320 -			if (!ops_equal(&xs_ops, xsh_pre, &file_ops, fileh_pre,
 27.1321 -				       "/", &fail)) {
 27.1322 -				if (fail)
 27.1323 -					barf("%s failed during transact\n",
 27.1324 -					     fail->name);
 27.1325 -
 27.1326 -				xs_daemon_close(xsh_pre);
 27.1327 -				talloc_free(fileh_pre);
 27.1328 -				goto out;
 27.1329 -			}
 27.1330 -			xs_daemon_close(xsh_pre);
 27.1331 -			talloc_free(fileh_pre);
 27.1332 -		}
 27.1333 -	}
 27.1334 -
 27.1335 -	fail = NULL;
 27.1336 -	if (data->fast)
 27.1337 -		if (!ops_equal(&xs_ops, xsh, &file_ops, fileh, "/", &fail))
 27.1338 -			barf("Final result not the same: try without --fast");
 27.1339 -out:
 27.1340 -	file_ops.close(fileh);	
 27.1341 -	xs_ops.close(xsh);	
 27.1342 -	return i;
 27.1343 -}
 27.1344 -
 27.1345 -/* Differential random test: compare results against file backend. */
 27.1346 -static void diff_test(const char *dir,
 27.1347 -		      unsigned int iters, unsigned int seed, bool fast, 
 27.1348 -		      bool verbose)
 27.1349 -{
 27.1350 -	struct diff_data data;
 27.1351 -	unsigned int try;
 27.1352 -
 27.1353 -	data.seed = seed;
 27.1354 -	data.print_progress = !verbose;
 27.1355 -	data.fast = fast;
 27.1356 -	data.dir = dir;
 27.1357 -
 27.1358 -	try = try_diff(NULL, iters, verbose, &data);
 27.1359 -	if (try == iters) {
 27.1360 -		cleanup_xs_ops();
 27.1361 -		exit(0);
 27.1362 -	}
 27.1363 -	printf("Failed on iteration %u of seed %u\n", try + 1, seed);
 27.1364 -	data.print_progress = false;
 27.1365 -	reduce_problem(try + 1, try_diff, &data);
 27.1366 -}
 27.1367 -
 27.1368 -struct fail_data
 27.1369 -{
 27.1370 -	unsigned int seed;
 27.1371 -	bool print_progress;
 27.1372 -	const char *dir;
 27.1373 -};
 27.1374 -
 27.1375 -/* Try xs with inserted failures: every op should either succeed or fail. */
 27.1376 -static unsigned int try_fail(const bool *trymap,
 27.1377 -			      unsigned int number,
 27.1378 -			      bool verbose,
 27.1379 -			      void *_data)
 27.1380 -{
 27.1381 -	unsigned int i, print, tried = 0, aborted = 0;
 27.1382 -	struct fail_data *data = _data;
 27.1383 -	struct xs_handle *tmpxsh;
 27.1384 -	struct file_ops_info *tmpfileh;
 27.1385 -	void *fileh, *xsh;
 27.1386 -	struct ops *fail;
 27.1387 -	char seed[20];
 27.1388 -
 27.1389 -	/* Make sure failures off to shut down. */
 27.1390 -	if (daemon_pid)
 27.1391 -		kill(daemon_pid, SIGUSR1);
 27.1392 -	cleanup(data->dir);
 27.1393 -	setup(data->dir);
 27.1394 -
 27.1395 -	fileh = file_handle(data->dir);
 27.1396 -	xsh = xs_handle(data->dir);
 27.1397 -
 27.1398 -	print = number / 76;
 27.1399 -	if (!print)
 27.1400 -		print = 1;
 27.1401 -
 27.1402 -	for (i = 0; i < number; i++) {
 27.1403 -		unsigned int limit, failed;
 27.1404 -		char *ret;
 27.1405 -
 27.1406 -		/* A few times we fail due to other end OOM. */
 27.1407 -		limit = 0;
 27.1408 -		while (!xsh) {
 27.1409 -			xsh = xs_handle(data->dir);
 27.1410 -			if (!xsh && errno == ECONNREFUSED) {
 27.1411 -				if (verbose)
 27.1412 -					printf("Daemon refused connection\n");
 27.1413 -				goto out;
 27.1414 -			}
 27.1415 -			if (!xsh && limit++ == 5) {
 27.1416 -				printf("Daemon failed conn 5 times\n");
 27.1417 -				goto out;
 27.1418 -			}
 27.1419 -		}
 27.1420 -
 27.1421 -		if (data->print_progress) {
 27.1422 -			if (i % print == 0) {
 27.1423 -				printf(".");
 27.1424 -				fflush(stdout);
 27.1425 -			}
 27.1426 -		}
 27.1427 -		if (trymap && !trymap[i])
 27.1428 -			continue;
 27.1429 -
 27.1430 -		/* Turn on failure. */
 27.1431 -		sprintf(seed, "%i", data->seed + i);
 27.1432 -		free(xs_debug_command(xsh, "failtest",seed,strlen(seed)+1));
 27.1433 -
 27.1434 -		if (verbose)
 27.1435 -			printf("(%i) seed %s ", i, seed);
 27.1436 -		ret = do_next_op(&xs_ops, xsh, i + data->seed, verbose);
 27.1437 -		if (streq(ret, "FAILED:Connection reset by peer")
 27.1438 -		    || streq(ret, "FAILED:Bad file descriptor")
 27.1439 -		    || streq(ret, "FAILED:Broken pipe")) {
 27.1440 -			xs_close(xsh);
 27.1441 -			xsh = NULL;
 27.1442 -			failed = 2;
 27.1443 -		} else if (strstarts(ret, "OK"))
 27.1444 -			failed = 0;
 27.1445 -		else
 27.1446 -			failed = 1;
 27.1447 -
 27.1448 -		tried++;
 27.1449 -		if (xsh)
 27.1450 -			aborted++;
 27.1451 -
 27.1452 -		if (verbose)
 27.1453 -			printf("-> %.*s\n",
 27.1454 -			       (int)(strchr(ret, '\n') - ret), ret);
 27.1455 -
 27.1456 -		talloc_free(ret);
 27.1457 -
 27.1458 -		/* Turn off failures using signal. */
 27.1459 -		if (kill(daemon_pid, SIGUSR1) != 0) {
 27.1460 -			if (verbose)
 27.1461 -				printf("Failed to signal daemon\n");
 27.1462 -			goto out;
 27.1463 -		}
 27.1464 -
 27.1465 -		if (failed == 0) {
 27.1466 -			/* Succeeded?  Do same thing to file backend
 27.1467 -			 * to compare */
 27.1468 -		try_applying:
 27.1469 -			ret = do_next_op(&file_ops, fileh, i + data->seed,
 27.1470 -					 false);
 27.1471 -			if (!strstarts(ret, "OK")) {
 27.1472 -				if (!verbose)
 27.1473 -					printf("File op failed on %i\n",
 27.1474 -					       i + data->seed);
 27.1475 -				talloc_free(ret);
 27.1476 -				goto out;
 27.1477 -			}
 27.1478 -			talloc_free(ret);
 27.1479 -		}
 27.1480 -
 27.1481 -		tmpxsh = xs_handle(data->dir);
 27.1482 -		if (!tmpxsh) {
 27.1483 -			if (verbose)
 27.1484 -				printf("Failed to open signalled daemon");
 27.1485 -			goto out;
 27.1486 -		}
 27.1487 -		tmpfileh = file_handle(data->dir);
 27.1488 -
 27.1489 -		fail = NULL;
 27.1490 -		if (!ops_equal(&xs_ops, tmpxsh, &file_ops, tmpfileh, "/",
 27.1491 -			       &fail)) {
 27.1492 -			if (fail) {
 27.1493 -				if (verbose)
 27.1494 -					printf("%s failed\n", fail->name);
 27.1495 -				goto out;
 27.1496 -			}
 27.1497 -			/* Maybe op succeeded: try comparing after local op? */
 27.1498 -			if (failed == 2) {
 27.1499 -				failed = 0;
 27.1500 -				if (verbose)
 27.1501 -					printf("(Looks like it succeeded)\n");
 27.1502 -				xs_close(tmpxsh);
 27.1503 -				file_close(tmpfileh);
 27.1504 -				goto try_applying;
 27.1505 -			}
 27.1506 -			if (verbose)
 27.1507 -				printf("Trees differ:\nXS:%s\nFILE:%s\n",
 27.1508 -				       dump(&xs_ops, tmpxsh),
 27.1509 -				       dump(&file_ops, tmpfileh));
 27.1510 -			xs_close(tmpxsh);
 27.1511 -			file_close(tmpfileh);
 27.1512 -			goto out;
 27.1513 -		}
 27.1514 -
 27.1515 -		/* If we lost the xs handle, that ended the transaction */
 27.1516 -		if (!xsh)
 27.1517 -			file_transaction_end(fileh, true);
 27.1518 -
 27.1519 -		xs_close(tmpxsh);
 27.1520 -		file_close(tmpfileh);
 27.1521 -	}
 27.1522 -out:
 27.1523 -	if (xsh)
 27.1524 -		xs_close(xsh);
 27.1525 -	return i;
 27.1526 -}
 27.1527 -
 27.1528 -static void fail_test(const char *dir,
 27.1529 -		      unsigned int iters, unsigned int seed,
 27.1530 -		      bool fast __attribute__((unused)), bool verbose)
 27.1531 -{
 27.1532 -	struct fail_data data;
 27.1533 -	unsigned int try;
 27.1534 -
 27.1535 -	data.seed = seed;
 27.1536 -	data.print_progress = !verbose;
 27.1537 -	data.dir = dir;
 27.1538 -
 27.1539 -	try = try_fail(NULL, iters, verbose, &data);
 27.1540 -	if (try == iters) {
 27.1541 -		cleanup_xs_ops();
 27.1542 -		exit(0);
 27.1543 -	}
 27.1544 -	printf("Failed on iteration %u of seed %u\n", try + 1, seed);
 27.1545 -	fflush(stdout);
 27.1546 -	data.print_progress = false;
 27.1547 -	reduce_problem(try + 1, try_fail, &data);
 27.1548 -}
 27.1549 -
 27.1550 -int main(int argc, char *argv[])
 27.1551 -{
 27.1552 -	bool verbose = false;
 27.1553 -	bool simple = false;
 27.1554 -	bool fast = false;
 27.1555 -	bool fail = false;
 27.1556 -
 27.1557 -	if (argv[1] && streq(argv[1], "--fail")) {
 27.1558 -		fail = true;
 27.1559 -		argv++;
 27.1560 -		argc--;
 27.1561 -	}
 27.1562 -
 27.1563 -	if (argv[1] && streq(argv[1], "--simple")) {
 27.1564 -		simple = true;
 27.1565 -		argv++;
 27.1566 -		argc--;
 27.1567 -	}
 27.1568 -
 27.1569 -	if (argv[1] && streq(argv[1], "--fast")) {
 27.1570 -		fast = true;
 27.1571 -		argv++;
 27.1572 -		argc--;
 27.1573 -	}
 27.1574 -
 27.1575 -	if (argv[1] && streq(argv[1], "--verbose")) {
 27.1576 -		verbose = true;
 27.1577 -		argv++;
 27.1578 -		argc--;
 27.1579 -	}
 27.1580 -
 27.1581 -	if (argc != 4)
 27.1582 -		barf("Usage: xs_random [--fail|--simple] [--fast] [--verbose] <directory> <iterations> <seed>");
 27.1583 -
 27.1584 -	talloc_enable_null_tracking();
 27.1585 -
 27.1586 -	if (fail)
 27.1587 -		fail_test(argv[1], atoi(argv[2]), atoi(argv[3]), fast, verbose);
 27.1588 -	else if (simple)
 27.1589 -		simple_test(argv[1], atoi(argv[2]), atoi(argv[3]), fast, verbose);
 27.1590 -	else
 27.1591 -		diff_test(argv[1],  atoi(argv[2]), atoi(argv[3]), fast, verbose);
 27.1592 -	exit(2);
 27.1593 -}
    28.1 --- a/tools/xenstore/xs_stress.c	Tue Jul 03 15:49:16 2007 +0100
    28.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.3 @@ -1,207 +0,0 @@
    28.4 -/* Stress test for Xen Store: multiple people hammering transactions */
    28.5 -#include "xs.h"
    28.6 -#include "utils.h"
    28.7 -#include <stdlib.h>
    28.8 -#include <stdio.h>
    28.9 -#include <sys/types.h>
   28.10 -#include <sys/wait.h>
   28.11 -#include <sys/stat.h>
   28.12 -#include <fcntl.h>
   28.13 -#include <unistd.h>
   28.14 -#include <errno.h>
   28.15 -
   28.16 -#define NUM_HANDLES 2
   28.17 -#define DIR_FANOUT 3
   28.18 -#define DIR_DEPTH 3
   28.19 -
   28.20 -/* How often to print progress */
   28.21 -static int print;
   28.22 -
   28.23 -/* Layout looks like /<num>/<num>/count. */
   28.24 -static void work(unsigned int cycles, unsigned int childnum)
   28.25 -{
   28.26 -	unsigned int i;
   28.27 -	struct xs_handle *handles[NUM_HANDLES];
   28.28 -	char id;
   28.29 -
   28.30 -	if (childnum < 10)
   28.31 -		id = '0' + childnum;
   28.32 -	else
   28.33 -		id = 'A' + childnum - 10;
   28.34 -
   28.35 -	for (i = 0; i < NUM_HANDLES; i++) {
   28.36 -		handles[i] = xs_daemon_open();
   28.37 -		if (!handles[i])
   28.38 -			barf_perror("Opening handle %i", i);
   28.39 -	}
   28.40 -
   28.41 -	srandom(childnum);
   28.42 -	for (i = 0; i < cycles; i++) {
   28.43 -		unsigned int j, len;
   28.44 -		char file[100] = "";
   28.45 -		char *contents, tmp[100];
   28.46 -		struct xs_handle *h = handles[random() % NUM_HANDLES];
   28.47 -
   28.48 -		for (j = 0; j < DIR_DEPTH; j++)
   28.49 -			sprintf(file + strlen(file), "/%li",
   28.50 -				random()%DIR_FANOUT);
   28.51 -
   28.52 -		if (!xs_transaction_start(h))
   28.53 -			barf_perror("%i: starting transaction %i",
   28.54 -				    childnum, i);
   28.55 -
   28.56 -		sprintf(file + strlen(file), "/count");
   28.57 -		contents = xs_read(h, file, &len);
   28.58 -		if (!contents)
   28.59 -			barf_perror("%i: can't read %s iter %i",
   28.60 -				    childnum, file, i);
   28.61 -		sprintf(tmp, "%i", atoi(contents) + 1);
   28.62 -		if (!xs_write(h, file, tmp, strlen(tmp)+1))
   28.63 -			barf_perror("%i: can't write %s iter %i",
   28.64 -				    childnum, file, i);
   28.65 -
   28.66 -		/* Abandon 1 in 10 */
   28.67 -		if (random() % 10 == 0) {
   28.68 -			if (!xs_transaction_end(h, true))
   28.69 -				barf_perror("%i: can't abort transact",
   28.70 -					    childnum);
   28.71 -			i--;
   28.72 -		} else {
   28.73 -			if (!xs_transaction_end(h, false)) {
   28.74 -				if (errno == EAGAIN) {
   28.75 -					write(STDOUT_FILENO, "!", 1);
   28.76 -					i--;
   28.77 -				} else
   28.78 -					barf_perror("%i: can't commit trans",
   28.79 -						    childnum);
   28.80 -			} else {
   28.81 -				/* Offset when we print . so kids don't all
   28.82 -				 * print at once. */
   28.83 -				if ((i + print/(childnum+1)) % print == 0)
   28.84 -					write(STDOUT_FILENO, &id, 1);
   28.85 -			}
   28.86 -		}
   28.87 -	}
   28.88 -}
   28.89 -
   28.90 -static void create_dirs(struct xs_handle *h, const char *base, int togo)
   28.91 -{
   28.92 -	unsigned int i;
   28.93 -	char filename[100];
   28.94 -
   28.95 -	if (togo == 0) {
   28.96 -		sprintf(filename, "%s/count", base);
   28.97 -		if (!xs_write(h, filename, "0", 1))
   28.98 -			barf_perror("Writing to %s", filename);
   28.99 -		return;
  28.100 -	}
  28.101 -
  28.102 -	for (i = 0; i < DIR_FANOUT; i++) {
  28.103 -		sprintf(filename, "%s/%i", base, i);
  28.104 -		if (!xs_mkdir(h, filename))
  28.105 -			barf_perror("xs_mkdir %s", filename);
  28.106 -		create_dirs(h, filename, togo-1);
  28.107 -	}
  28.108 -}
  28.109 -
  28.110 -static unsigned int add_count(struct xs_handle *h, const char *base, int togo)
  28.111 -{
  28.112 -	unsigned int i, count;
  28.113 -	char filename[100];
  28.114 -
  28.115 -	if (togo == 0) {
  28.116 -		char *answer;
  28.117 -		unsigned int len;
  28.118 -
  28.119 -		sprintf(filename, "%s/count", base);
  28.120 -		answer = xs_read(h, filename, &len);
  28.121 -		if (!answer)
  28.122 -			barf_perror("Reading %s", filename);
  28.123 -		count = atoi(answer);
  28.124 -		free(answer);
  28.125 -		return count;
  28.126 -	}
  28.127 -
  28.128 -	count = 0;
  28.129 -	for (i = 0; i < DIR_FANOUT; i++) {
  28.130 -		sprintf(filename, "%s/%i", base, i);
  28.131 -		count += add_count(h, filename, togo-1);
  28.132 -	}
  28.133 -	return count;
  28.134 -}
  28.135 -
  28.136 -static void setup(void)
  28.137 -{
  28.138 -	struct xs_handle *h;
  28.139 -
  28.140 -	/* Do setup. */
  28.141 -	h = xs_daemon_open();
  28.142 -	if (!h)
  28.143 -		barf_perror("Contacting daemon");
  28.144 -	create_dirs(h, "", DIR_DEPTH);
  28.145 -	xs_daemon_close(h);
  28.146 -}
  28.147 -
  28.148 -static unsigned int tally_counts(void)
  28.149 -{
  28.150 -	struct xs_handle *h;
  28.151 -	unsigned int ret;
  28.152 -	
  28.153 -	h = xs_daemon_open();
  28.154 -	if (!h)
  28.155 -		barf_perror("Contacting daemon");
  28.156 -
  28.157 -	ret = add_count(h, "", DIR_DEPTH);
  28.158 -	xs_daemon_close(h);
  28.159 -	return ret;
  28.160 -}	
  28.161 -
  28.162 -int main(int argc, char *argv[])
  28.163 -{
  28.164 -	unsigned int i;
  28.165 -	bool failed = false;
  28.166 -	int kids[10];
  28.167 -
  28.168 -	if (argc != 2)
  28.169 -		barf("Usage: xs_stress <iterations>");
  28.170 -
  28.171 -	printf("Setting up directories...\n");
  28.172 -	setup();
  28.173 -
  28.174 -	print = atoi(argv[1]) / 76;
  28.175 -	if (!print)
  28.176 -		print = 1;
  28.177 -
  28.178 -	printf("Running %i children...\n", ARRAY_SIZE(kids));
  28.179 -	for (i = 0; i < ARRAY_SIZE(kids); i++) {
  28.180 -		kids[i] = fork();
  28.181 -		if (kids[i] == -1)
  28.182 -			barf_perror("fork");
  28.183 -		if (kids[i] == 0) {
  28.184 -			work(atoi(argv[1]) / ARRAY_SIZE(kids), i);
  28.185 -			exit(0);
  28.186 -		}
  28.187 -	}
  28.188 -
  28.189 -	for (i = 0; i < ARRAY_SIZE(kids); i++) {
  28.190 -		int status;
  28.191 -		if (waitpid(kids[i], &status, 0) == -1)
  28.192 -			barf_perror("waitpid");
  28.193 -		if (!WIFEXITED(status))
  28.194 -			barf("Kid %i died via signal %i\n",
  28.195 -			     i, WTERMSIG(status));
  28.196 -		if (WEXITSTATUS(status) != 0) {
  28.197 -			printf("Child %i exited %i\n", i, WEXITSTATUS(status));
  28.198 -			failed = true;
  28.199 -		}
  28.200 -	}
  28.201 -	if (failed)
  28.202 -		exit(1);
  28.203 -
  28.204 -	printf("\nCounting results...\n");
  28.205 -	i = tally_counts();
  28.206 -	if (i != (unsigned)atoi(argv[1]))
  28.207 -		barf("Total counts %i not %s", i, argv[1]);
  28.208 -	printf("Success!\n");
  28.209 -	exit(0);
  28.210 -}
    29.1 --- a/tools/xenstore/xs_test.c	Tue Jul 03 15:49:16 2007 +0100
    29.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.3 @@ -1,812 +0,0 @@
    29.4 -/* 
    29.5 -    Xen Store Daemon Test tool
    29.6 -    Copyright (C) 2005 Rusty Russell IBM Corporation
    29.7 -
    29.8 -    This program is free software; you can redistribute it and/or modify
    29.9 -    it under the terms of the GNU General Public License as published by
   29.10 -    the Free Software Foundation; either version 2 of the License, or
   29.11 -    (at your option) any later version.
   29.12 -
   29.13 -    This program is distributed in the hope that it will be useful,
   29.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   29.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   29.16 -    GNU General Public License for more details.
   29.17 -
   29.18 -    You should have received a copy of the GNU General Public License
   29.19 -    along with this program; if not, write to the Free Software
   29.20 -    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   29.21 -*/
   29.22 -
   29.23 -#define _GNU_SOURCE
   29.24 -#include <stdio.h>
   29.25 -#include <stdlib.h>
   29.26 -#include <sys/types.h>
   29.27 -#include <sys/wait.h>
   29.28 -#include <sys/stat.h>
   29.29 -#include <fcntl.h>
   29.30 -#include <signal.h>
   29.31 -#include <stdint.h>
   29.32 -#include <stdbool.h>
   29.33 -#include <stdlib.h>
   29.34 -#include <sys/mman.h>
   29.35 -#include <fnmatch.h>
   29.36 -#include <stdarg.h>
   29.37 -#include <string.h>
   29.38 -#include <getopt.h>
   29.39 -#include <ctype.h>
   29.40 -#include <sys/time.h>
   29.41 -#include "utils.h"
   29.42 -#include "xs_lib.h"
   29.43 -#include "xs.h"
   29.44 -#include "list.h"
   29.45 -
   29.46 -#define XSTEST
   29.47 -
   29.48 -static struct xs_handle *handles[10] = { NULL };
   29.49 -static xs_transaction_t txh[10] = { XBT_NULL };
   29.50 -
   29.51 -static unsigned int timeout_ms = 500;
   29.52 -static bool timeout_suppressed = true;
   29.53 -static bool readonly = false;
   29.54 -static bool print_input = false;
   29.55 -static unsigned int linenum = 0;
   29.56 -
   29.57 -static int daemon_pid;
   29.58 -static struct xenstore_domain_interface *interface;
   29.59 -
   29.60 -/* FIXME: Mark connection as broken (close it?) when this happens. */
   29.61 -static bool check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
   29.62 -{
   29.63 -	return ((prod - cons) <= XENSTORE_RING_SIZE);
   29.64 -}
   29.65 -
   29.66 -static void *get_output_chunk(XENSTORE_RING_IDX cons,
   29.67 -			      XENSTORE_RING_IDX prod,
   29.68 -			      char *buf, uint32_t *len)
   29.69 -{
   29.70 -	*len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
   29.71 -	if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
   29.72 -		*len = XENSTORE_RING_SIZE - (prod - cons);
   29.73 -	return buf + MASK_XENSTORE_IDX(prod);
   29.74 -}
   29.75 -
   29.76 -static const void *get_input_chunk(XENSTORE_RING_IDX cons,
   29.77 -				   XENSTORE_RING_IDX prod,
   29.78 -				   const char *buf, uint32_t *len)
   29.79 -{
   29.80 -	*len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
   29.81 -	if ((prod - cons) < *len)
   29.82 -		*len = prod - cons;
   29.83 -	return buf + MASK_XENSTORE_IDX(cons);
   29.84 -}
   29.85 -
   29.86 -/* FIXME: We spin, and we're sloppy. */
   29.87 -static bool read_all_shmem(int fd __attribute__((unused)),
   29.88 -			   void *data, unsigned int len)
   29.89 -{
   29.90 -	unsigned int avail;
   29.91 -	struct xenstore_domain_interface *intf = interface;
   29.92 -	XENSTORE_RING_IDX cons, prod;
   29.93 -	const void *src;
   29.94 -
   29.95 -	while (len) {
   29.96 -		cons = intf->rsp_cons;
   29.97 -		prod = intf->rsp_prod;
   29.98 -		if (!check_indexes(cons, prod))
   29.99 -			barf("Corrupt buffer");
  29.100 -
  29.101 -		src = get_input_chunk(cons, prod, intf->rsp, &avail);
  29.102 -		if (avail > len)
  29.103 -			avail = len;
  29.104 -		memcpy(data, src, avail);
  29.105 -		data += avail;
  29.106 -		len -= avail;
  29.107 -		intf->rsp_cons += avail;
  29.108 -	}
  29.109 -
  29.110 -	/* Tell other end we read something. */
  29.111 -	kill(daemon_pid, SIGUSR2);
  29.112 -
  29.113 -	return true;
  29.114 -}
  29.115 -
  29.116 -static bool write_all_shmem(int fd __attribute__((unused)),
  29.117 -			    const void *data, unsigned int len)
  29.118 -{
  29.119 -	uint32_t avail;
  29.120 -	struct xenstore_domain_interface *intf = interface;
  29.121 -	XENSTORE_RING_IDX cons, prod;
  29.122 -	void *dst;
  29.123 -
  29.124 -	while (len) {
  29.125 -		cons = intf->req_cons;
  29.126 -		prod = intf->req_prod;
  29.127 -		if (!check_indexes(cons, prod))
  29.128 -			barf("Corrupt buffer");
  29.129 -
  29.130 -		dst = get_output_chunk(cons, prod, intf->req, &avail);
  29.131 -		if (avail > len)
  29.132 -			avail = len;
  29.133 -		memcpy(dst, data, avail);
  29.134 -		data += avail;
  29.135 -		len -= avail;
  29.136 -		intf->req_prod += avail;
  29.137 -	}
  29.138 -
  29.139 -	/* Tell other end we wrote something. */
  29.140 -	kill(daemon_pid, SIGUSR2);
  29.141 -
  29.142 -	return true;
  29.143 -}
  29.144 -
  29.145 -static bool read_all(int fd, void *data, unsigned int len);
  29.146 -static bool read_all_choice(int fd, void *data, unsigned int len)
  29.147 -{
  29.148 -	if (fd == -2)
  29.149 -		return read_all_shmem(fd, data, len);
  29.150 -	return read_all(fd, data, len);
  29.151 -}
  29.152 -
  29.153 -static bool write_all_choice(int fd, const void *data, unsigned int len)
  29.154 -{
  29.155 -	if (fd == -2)
  29.156 -		return write_all_shmem(fd, data, len);
  29.157 -	return xs_write_all(fd, data, len);
  29.158 -}
  29.159 -
  29.160 -/* We want access to internal functions. */
  29.161 -#include "xs.c"
  29.162 -
  29.163 -static void __attribute__((noreturn)) usage(void)
  29.164 -{
  29.165 -	barf("Usage:\n"
  29.166 -	     "       xs_test [--readonly] [--no-timeout] [-x]\n"
  29.167 -	     "Reads commands from stdin, one per line:"
  29.168 -	     "  dir <path>\n"
  29.169 -	     "  read <path>\n"
  29.170 -	     "  write <path> <value>...\n"
  29.171 -	     "  setid <id>\n"
  29.172 -	     "  mkdir <path>\n"
  29.173 -	     "  rm <path>\n"
  29.174 -	     "  getperm <path>\n"
  29.175 -	     "  setperm <path> <id> <flags> ...\n"
  29.176 -	     "  watch <path> <token>\n"
  29.177 -	     "  watchnoack <path> <token>\n"
  29.178 -	     "  waitwatch\n"
  29.179 -	     "  unwatch <path> <token>\n"
  29.180 -	     "  close\n"
  29.181 -	     "  start <node>\n"
  29.182 -	     "  abort\n"
  29.183 -	     "  introduce <domid> <mfn> <eventchn> <path>\n"
  29.184 -	     "  commit\n"
  29.185 -	     "  sleep <milliseconds>\n"
  29.186 -	     "  expect <pattern>\n"
  29.187 -	     "  notimeout\n"
  29.188 -	     "  readonly\n"
  29.189 -	     "  readwrite\n"
  29.190 -	     "  dump\n");
  29.191 -}
  29.192 -
  29.193 -static int argpos(const char *line, unsigned int num)
  29.194 -{
  29.195 -	unsigned int i, len = 0, off = 0;
  29.196 -
  29.197 -	for (i = 0; i <= num; i++) {
  29.198 -		off += len;
  29.199 -		off += strspn(line + off, " \t\n");
  29.200 -		len = strcspn(line + off, " \t\n");
  29.201 -		if (!len)
  29.202 -			return off;
  29.203 -	}
  29.204 -	return off;
  29.205 -}
  29.206 -
  29.207 -static char *arg(const char *line, unsigned int num)
  29.208 -{
  29.209 -	static char *args[10];
  29.210 -	unsigned int off, len;
  29.211 -
  29.212 -	off = argpos(line, num);
  29.213 -	len = strcspn(line + off, " \t\n");
  29.214 -
  29.215 -	if (!len)
  29.216 -		barf("Can't get arg %u", num);
  29.217 -
  29.218 -	free(args[num]);
  29.219 -	args[num] = malloc(len + 1);
  29.220 -	memcpy(args[num], line+off, len);
  29.221 -	args[num][len] = '\0';
  29.222 -	return args[num];
  29.223 -}
  29.224 -
  29.225 -struct expect
  29.226 -{
  29.227 -	struct list_head list;
  29.228 -	char *pattern;
  29.229 -};
  29.230 -static LIST_HEAD(expects);
  29.231 -
  29.232 -static char *command;
  29.233 -
  29.234 -/* Trim leading and trailing whitespace */
  29.235 -static void trim(char *str)
  29.236 -{
  29.237 -	while (isspace(str[0]))
  29.238 -		memmove(str, str+1, strlen(str));
  29.239 -
  29.240 -	while (strlen(str) && isspace(str[strlen(str)-1]))
  29.241 -		str[strlen(str)-1] = '\0';
  29.242 -}
  29.243 -
  29.244 -static void output(const char *fmt, ...)
  29.245 -{
  29.246 -	char *str;
  29.247 -	struct expect *i;
  29.248 -	va_list arglist;
  29.249 -
  29.250 -	va_start(arglist, fmt);
  29.251 -	vasprintf(&str, fmt, arglist);
  29.252 -	va_end(arglist);
  29.253 -
  29.254 -	printf("%s", str);
  29.255 -	fflush(stdout);
  29.256 -	trim(str);
  29.257 -	list_for_each_entry(i, &expects, list) {
  29.258 -		if (fnmatch(i->pattern, str, 0) == 0) {
  29.259 -			list_del(&i->list);
  29.260 -			free(i);
  29.261 -			return;
  29.262 -		}
  29.263 -	}
  29.264 -	barf("Unexpected output %s\n", str);
  29.265 -}
  29.266 -
  29.267 -static void failed(int handle)
  29.268 -{
  29.269 -	if (handle)
  29.270 -		output("%i: %s failed: %s\n",
  29.271 -		       handle, command, strerror(errno));
  29.272 -	else
  29.273 -		output("%s failed: %s\n", command, strerror(errno));
  29.274 -}
  29.275 -
  29.276 -static void expect(const char *line)
  29.277 -{
  29.278 -	struct expect *e = malloc(sizeof(*e));
  29.279 -
  29.280 -	e->pattern = strdup(line + argpos(line, 1));
  29.281 -	trim(e->pattern);
  29.282 -	list_add(&e->list, &expects);
  29.283 -}
  29.284 -
  29.285 -static void do_dir(unsigned int handle, char *path)
  29.286 -{
  29.287 -	char **entries;
  29.288 -	unsigned int i, num;
  29.289 -
  29.290 -	entries = xs_directory(handles[handle], txh[handle], path, &num);
  29.291 -	if (!entries) {
  29.292 -		failed(handle);
  29.293 -		return;
  29.294 -	}
  29.295 -
  29.296 -	for (i = 0; i < num; i++)
  29.297 -		if (handle)
  29.298 -			output("%i:%s\n", handle, entries[i]);
  29.299 -		else
  29.300 -			output("%s\n", entries[i]);
  29.301 -	free(entries);
  29.302 -}
  29.303 -
  29.304 -static void do_read(unsigned int handle, char *path)
  29.305 -{
  29.306 -	char *value;
  29.307 -	unsigned int len;
  29.308 -
  29.309 -	value = xs_read(handles[handle], txh[handle], path, &len);
  29.310 -	if (!value) {
  29.311 -		failed(handle);
  29.312 -		return;
  29.313 -	}
  29.314 -
  29.315 -	/* It's supposed to nul terminate for us. */
  29.316 -	assert(value[len] == '\0');
  29.317 -	if (handle)
  29.318 -		output("%i:%.*s\n", handle, len, value);
  29.319 -	else
  29.320 -		output("%.*s\n", len, value);
  29.321 -}
  29.322 -
  29.323 -static void do_write(unsigned int handle, char *path, char *data)
  29.324 -{
  29.325 -	if (!xs_write(handles[handle], txh[handle], path, data, strlen(data)))
  29.326 -		failed(handle);
  29.327 -}
  29.328 -
  29.329 -static void do_setid(unsigned int handle, char *id)
  29.330 -{
  29.331 -	if (!xs_bool(xs_debug_command(handles[handle], "setid", id,
  29.332 -				      strlen(id)+1)))
  29.333 -		failed(handle);
  29.334 -}
  29.335 -
  29.336 -static void do_mkdir(unsigned int handle, char *path)
  29.337 -{
  29.338 -	if (!xs_mkdir(handles[handle], txh[handle], path))
  29.339 -		failed(handle);
  29.340 -}
  29.341 -
  29.342 -static void do_rm(unsigned int handle, char *path)
  29.343 -{
  29.344 -	if (!xs_rm(handles[handle], txh[handle], path))
  29.345 -		failed(handle);
  29.346 -}
  29.347 -
  29.348 -static void do_getperm(unsigned int handle, char *path)
  29.349 -{
  29.350 -	unsigned int i, num;
  29.351 -	struct xs_permissions *perms;
  29.352 -
  29.353 -	perms = xs_get_permissions(handles[handle], txh[handle], path, &num);
  29.354 -	if (!perms) {
  29.355 -		failed(handle);
  29.356 -		return;
  29.357 -	}
  29.358 -
  29.359 -	for (i = 0; i < num; i++) {
  29.360 -		char *permstring;
  29.361 -
  29.362 -		switch (perms[i].perms) {
  29.363 -		case XS_PERM_NONE:
  29.364 -			permstring = "NONE";
  29.365 -			break;
  29.366 -		case XS_PERM_WRITE:
  29.367 -			permstring = "WRITE";
  29.368 -			break;
  29.369 -		case XS_PERM_READ:
  29.370 -			permstring = "READ";
  29.371 -			break;
  29.372 -		case XS_PERM_READ|XS_PERM_WRITE:
  29.373 -			permstring = "READ/WRITE";
  29.374 -			break;
  29.375 -		default:
  29.376 -			barf("bad perm value %i", perms[i].perms);
  29.377 -		}
  29.378 -
  29.379 -		if (handle)
  29.380 -			output("%i:%i %s\n", handle, perms[i].id, permstring);
  29.381 -		else
  29.382 -			output("%i %s\n", perms[i].id, permstring);
  29.383 -	}
  29.384 -	free(perms);
  29.385 -}
  29.386 -
  29.387 -static void do_setperm(unsigned int handle, char *path, char *line)
  29.388 -{
  29.389 -	unsigned int i;
  29.390 -	struct xs_permissions perms[100];
  29.391 -
  29.392 -	strtok(line, " \t\n");
  29.393 -	strtok(NULL, " \t\n");
  29.394 -	for (i = 0; ; i++) {
  29.395 -		char *arg = strtok(NULL, " \t\n");
  29.396 -		if (!arg)
  29.397 -			break;
  29.398 -		perms[i].id = atoi(arg);
  29.399 -		arg = strtok(NULL, " \t\n");
  29.400 -		if (!arg)
  29.401 -			break;
  29.402 -		if (streq(arg, "WRITE"))
  29.403 -			perms[i].perms = XS_PERM_WRITE;
  29.404 -		else if (streq(arg, "READ"))
  29.405 -			perms[i].perms = XS_PERM_READ;
  29.406 -		else if (streq(arg, "READ/WRITE"))
  29.407 -			perms[i].perms = XS_PERM_READ|XS_PERM_WRITE;
  29.408 -		else if (streq(arg, "NONE"))
  29.409 -			perms[i].perms = XS_PERM_NONE;
  29.410 -		else
  29.411 -			barf("bad flags %s\n", arg);
  29.412 -	}
  29.413 -
  29.414 -	if (!xs_set_permissions(handles[handle], txh[handle], path, perms, i))
  29.415 -		failed(handle);
  29.416 -}
  29.417 -
  29.418 -static void do_watch(unsigned int handle, const char *node, const char *token,
  29.419 -		     bool swallow_event)
  29.420 -{
  29.421 -	if (!xs_watch(handles[handle], node, token))
  29.422 -		failed(handle);
  29.423 -
  29.424 -	/* Convenient for testing... */
  29.425 -	if (swallow_event) {
  29.426 -		unsigned int num;
  29.427 -		char **vec = xs_read_watch(handles[handle], &num);
  29.428 -		if (!vec ||
  29.429 -		    !streq(vec[XS_WATCH_PATH], node) ||
  29.430 -		    !streq(vec[XS_WATCH_TOKEN], token))
  29.431 -			failed(handle);
  29.432 -	}
  29.433 -}
  29.434 -
  29.435 -static void set_timeout(void)
  29.436 -{
  29.437 -	struct itimerval timeout;
  29.438 -
  29.439 -	timeout.it_value.tv_sec = timeout_ms / 1000;
  29.440 -	timeout.it_value.tv_usec = (timeout_ms * 1000) % 1000000;
  29.441 -	timeout.it_interval.tv_sec = timeout.it_interval.tv_usec = 0;
  29.442 -	setitimer(ITIMER_REAL, &timeout, NULL);
  29.443 -}
  29.444 -
  29.445 -static void disarm_timeout(void)
  29.446 -{
  29.447 -	struct itimerval timeout;
  29.448 -
  29.449 -	timeout.it_value.tv_sec = 0;
  29.450 -	timeout.it_value.tv_usec = 0;
  29.451 -	setitimer(ITIMER_REAL, &timeout, NULL);
  29.452 -}
  29.453 -
  29.454 -static void do_waitwatch(unsigned int handle)
  29.455 -{
  29.456 -	char **vec;
  29.457 -	struct timeval tv = {.tv_sec = timeout_ms/1000,
  29.458 -			     .tv_usec = (timeout_ms*1000)%1000000 };
  29.459 -	fd_set set;
  29.460 -	unsigned int num;
  29.461 -
  29.462 -	if (xs_fileno(handles[handle]) != -2) {
  29.463 -		/* Manually select here so we can time out gracefully. */
  29.464 -		FD_ZERO(&set);
  29.465 -		FD_SET(xs_fileno(handles[handle]), &set);
  29.466 -		disarm_timeout();
  29.467 -		if (select(xs_fileno(handles[handle])+1, &set,
  29.468 -			   NULL, NULL, &tv) == 0) {
  29.469 -			errno = ETIMEDOUT;
  29.470 -			failed(handle);
  29.471 -			return;
  29.472 -		}
  29.473 -		set_timeout();
  29.474 -	}
  29.475 -
  29.476 -	vec = xs_read_watch(handles[handle], &num);
  29.477 -	if (!vec) {
  29.478 -		failed(handle);
  29.479 -		return;
  29.480 -	}
  29.481 -
  29.482 -	if (handle)
  29.483 -		output("%i:%s:%s\n", handle,
  29.484 -		       vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN]);
  29.485 -	else
  29.486 -		output("%s:%s\n", vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN]);
  29.487 -	free(vec);
  29.488 -}
  29.489 -
  29.490 -static void do_unwatch(unsigned int handle, const char *node, const char *token)
  29.491 -{
  29.492 -	if (!xs_unwatch(handles[handle], node, token))
  29.493 -		failed(handle);
  29.494 -}
  29.495 -
  29.496 -static void do_start(unsigned int handle)
  29.497 -{
  29.498 -	txh[handle] = xs_transaction_start(handles[handle]);
  29.499 -	if (txh[handle] == XBT_NULL)
  29.500 -		failed(handle);
  29.501 -}
  29.502 -
  29.503 -static void do_end(unsigned int handle, bool abort)
  29.504 -{
  29.505 -	if (!xs_transaction_end(handles[handle], txh[handle], abort))
  29.506 -		failed(handle);
  29.507 -	txh[handle] = XBT_NULL;
  29.508 -}
  29.509 -
  29.510 -static void do_introduce(unsigned int handle,
  29.511 -			 const char *domid,
  29.512 -			 const char *mfn,
  29.513 -			 const char *eventchn,
  29.514 -			 const char *path)
  29.515 -{
  29.516 -	unsigned int i;
  29.517 -	int fd;
  29.518 -
  29.519 -	/* This mechanism is v. slow w. valgrind running. */
  29.520 -	timeout_ms = 5000;
  29.521 -
  29.522 -	/* We poll, so ignore signal */
  29.523 -	signal(SIGUSR2, SIG_IGN);
  29.524 -	for (i = 0; i < ARRAY_SIZE(handles); i++)
  29.525 -		if (!handles[i])
  29.526 -			break;
  29.527 -
  29.528 -	fd = open("/tmp/xcmap", O_RDWR);
  29.529 -	/* Set shared comms page. */
  29.530 -	interface = mmap(NULL, getpagesize(), PROT_WRITE|PROT_READ,
  29.531 -			 MAP_SHARED,fd,0);
  29.532 -	if (interface == MAP_FAILED)
  29.533 -		barf_perror("Failed to map /tmp/xcmap page");
  29.534 -	close(fd);
  29.535 -
  29.536 -	/* Tell them the event channel and our PID. */
  29.537 -	*(int *)((void *)interface + 32) = getpid();
  29.538 -	*(uint16_t *)((void *)interface + 36) = atoi(eventchn);
  29.539 -
  29.540 -	if (!xs_introduce_domain(handles[handle], atoi(domid),
  29.541 -				 atol(mfn), atoi(eventchn))) {
  29.542 -		failed(handle);
  29.543 -		munmap(interface, getpagesize());
  29.544 -		return;
  29.545 -	}
  29.546 -	output("handle is %i\n", i);
  29.547 -
  29.548 -	/* Create new handle. */
  29.549 -	handles[i] = new(struct xs_handle);
  29.550 -	handles[i]->fd = -2;
  29.551 -
  29.552 -	/* Read in daemon pid. */
  29.553 -	daemon_pid = *(int *)((void *)interface + 32);
  29.554 -}
  29.555 -
  29.556 -static void do_release(unsigned int handle, const char *domid)
  29.557 -{
  29.558 -	if (!xs_release_domain(handles[handle], atoi(domid)))
  29.559 -		failed(handle);
  29.560 -}
  29.561 -
  29.562 -static int strptrcmp(const void *a, const void *b)
  29.563 -{
  29.564 -	return strcmp(*(char **)a, *(char **)b);
  29.565 -}
  29.566 -
  29.567 -static void sort_dir(char **dir, unsigned int num)
  29.568 -{
  29.569 -	qsort(dir, num, sizeof(char *), strptrcmp);
  29.570 -}
  29.571 -
  29.572 -static void dump_dir(unsigned int handle,
  29.573 -		     const char *node,
  29.574 -		     char **dir,
  29.575 -		     unsigned int numdirs,
  29.576 -		     unsigned int depth)
  29.577 -{
  29.578 -	unsigned int i;
  29.579 -	char spacing[depth+1];
  29.580 -
  29.581 -	memset(spacing, ' ', depth);
  29.582 -	spacing[depth] = '\0';
  29.583 -
  29.584 -	sort_dir(dir, numdirs);
  29.585 -
  29.586 -	for (i = 0; i < numdirs; i++) {
  29.587 -		struct xs_permissions *perms;
  29.588 -		unsigned int j, numperms;
  29.589 -		unsigned int len;
  29.590 -		char *contents;
  29.591 -		unsigned int subnum;
  29.592 -		char **subdirs;
  29.593 -		char subnode[strlen(node) + 1 + strlen(dir[i]) + 1];
  29.594 -
  29.595 -		sprintf(subnode, "%s/%s", node, dir[i]);
  29.596 -
  29.597 -		perms = xs_get_permissions(handles[handle], txh[handle],
  29.598 -					   subnode,&numperms);
  29.599 -		if (!perms) {
  29.600 -			failed(handle);
  29.601 -			return;
  29.602 -		}
  29.603 -
  29.604 -		output("%s%s: ", spacing, dir[i]);
  29.605 -		for (j = 0; j < numperms; j++) {
  29.606 -			char buffer[100];
  29.607 -			if (!xs_perm_to_string(&perms[j], buffer))
  29.608 -				barf("perm to string");
  29.609 -			output("%s ", buffer);
  29.610 -		}
  29.611 -		free(perms);
  29.612 -		output("\n");
  29.613 -
  29.614 -		/* Even directories can have contents. */
  29.615 -		contents = xs_read(handles[handle], txh[handle], 
  29.616 -				   subnode, &len);
  29.617 -		if (!contents) {
  29.618 -			if (errno != EISDIR)
  29.619 -				failed(handle);
  29.620 -		} else {
  29.621 -			output(" %s(%.*s)\n", spacing, len, contents);
  29.622 -			free(contents);
  29.623 -		}			
  29.624 -
  29.625 -		/* Every node is a directory. */
  29.626 -		subdirs = xs_directory(handles[handle], txh[handle], 
  29.627 -				       subnode, &subnum);
  29.628 -		if (!subdirs) {
  29.629 -			failed(handle);
  29.630 -			return;
  29.631 -		}
  29.632 -		dump_dir(handle, subnode, subdirs, subnum, depth+1);
  29.633 -		free(subdirs);
  29.634 -	}
  29.635 -}
  29.636 -
  29.637 -static void dump(int handle)
  29.638 -{
  29.639 -	char **subdirs;
  29.640 -	unsigned int subnum;
  29.641 -
  29.642 -	subdirs = xs_directory(handles[handle], txh[handle], "/", &subnum);
  29.643 -	if (!subdirs) {
  29.644 -		failed(handle);
  29.645 -		return;
  29.646 -	}
  29.647 -
  29.648 -	dump_dir(handle, "", subdirs, subnum, 0);
  29.649 -	free(subdirs);
  29.650 -}
  29.651 -
  29.652 -static int handle;
  29.653 -
  29.654 -static void alarmed(int sig __attribute__((unused)))
  29.655 -{
  29.656 -	if (handle) {
  29.657 -		char handlename[10];
  29.658 -		sprintf(handlename, "%u:", handle);
  29.659 -		write(STDOUT_FILENO, handlename, strlen(handlename));
  29.660 -	}
  29.661 -	write(STDOUT_FILENO, command, strlen(command));
  29.662 -	write(STDOUT_FILENO, " timeout\n", strlen(" timeout\n"));
  29.663 -	exit(1);
  29.664 -}
  29.665 -
  29.666 -static void do_command(unsigned int default_handle, char *line)
  29.667 -{
  29.668 -	char *endp;
  29.669 -
  29.670 -	if (print_input)
  29.671 -		printf("%i> %s", ++linenum, line);
  29.672 -
  29.673 -	if (strspn(line, " \n") == strlen(line))
  29.674 -		return;
  29.675 -	if (strstarts(line, "#"))
  29.676 -		return;
  29.677 -
  29.678 -	handle = strtoul(line, &endp, 10);
  29.679 -	if (endp != line)
  29.680 -		memmove(line, endp+1, strlen(endp));
  29.681 -	else
  29.682 -		handle = default_handle;
  29.683 -
  29.684 -	command = arg(line, 0);
  29.685 -	if (!handles[handle]) {
  29.686 -		if (readonly)
  29.687 -			handles[handle] = xs_daemon_open_readonly();
  29.688 -		else
  29.689 -			handles[handle] = xs_daemon_open();
  29.690 -		if (!handles[handle])
  29.691 -			barf_perror("Opening connection to daemon");
  29.692 -	}
  29.693 -
  29.694 -	if (!timeout_suppressed)
  29.695 -		set_timeout();
  29.696 -	timeout_suppressed = false;
  29.697 -
  29.698 -	if (streq(command, "dir"))
  29.699 -		do_dir(handle, arg(line, 1));
  29.700 -	else if (streq(command, "read"))
  29.701 -		do_read(handle, arg(line, 1));
  29.702 -	else if (streq(command, "write"))
  29.703 -		do_write(handle, arg(line, 1), arg(line, 2));
  29.704 -	else if (streq(command, "setid"))
  29.705 -		do_setid(handle, arg(line, 1));
  29.706 -	else if (streq(command, "mkdir"))
  29.707 -		do_mkdir(handle, arg(line, 1));
  29.708 -	else if (streq(command, "rm"))
  29.709 -		do_rm(handle, arg(line, 1));
  29.710 -	else if (streq(command, "getperm"))
  29.711 -		do_getperm(handle, arg(line, 1));
  29.712 -	else if (streq(command, "setperm"))
  29.713 -		do_setperm(handle, arg(line, 1), line);
  29.714 -	else if (streq(command, "watch"))
  29.715 -		do_watch(handle, arg(line, 1), arg(line, 2), true);
  29.716 -	else if (streq(command, "watchnoack"))
  29.717 -		do_watch(handle, arg(line, 1), arg(line, 2), false);
  29.718 -	else if (streq(command, "waitwatch"))
  29.719 -		do_waitwatch(handle);
  29.720 -	else if (streq(command, "unwatch"))
  29.721 -		do_unwatch(handle, arg(line, 1), arg(line, 2));
  29.722 -	else if (streq(command, "close")) {
  29.723 -		xs_daemon_close(handles[handle]);
  29.724 -		handles[handle] = NULL;
  29.725 -		txh[handle] = XBT_NULL;
  29.726 -	} else if (streq(command, "start"))
  29.727 -		do_start(handle);
  29.728 -	else if (streq(command, "commit"))
  29.729 -		do_end(handle, false);
  29.730 -	else if (streq(command, "abort"))
  29.731 -		do_end(handle, true);
  29.732 -	else if (streq(command, "introduce"))
  29.733 -		do_introduce(handle, arg(line, 1), arg(line, 2),
  29.734 -			     arg(line, 3), arg(line, 4));
  29.735 -	else if (streq(command, "release"))
  29.736 -		do_release(handle, arg(line, 1));
  29.737 -	else if (streq(command, "dump"))
  29.738 -		dump(handle);
  29.739 -	else if (streq(command, "sleep")) {
  29.740 -		disarm_timeout();
  29.741 -		usleep(atoi(arg(line, 1)) * 1000);
  29.742 -	} else if (streq(command, "expect"))
  29.743 -		expect(line);
  29.744 -	else if (streq(command, "notimeout"))
  29.745 -		timeout_suppressed = true;
  29.746 -	else if (streq(command, "readonly")) {
  29.747 -		readonly = true;
  29.748 -		xs_daemon_close(handles[handle]);
  29.749 -		handles[handle] = NULL;
  29.750 -	} else if (streq(command, "readwrite")) {
  29.751 -		readonly = false;
  29.752 -		xs_daemon_close(handles[handle]);
  29.753 -		handles[handle] = NULL;
  29.754 -	} else
  29.755 -		barf("Unknown command %s", command);
  29.756 -	fflush(stdout);
  29.757 -	disarm_timeout();
  29.758 -
  29.759 -	/* Check expectations. */
  29.760 -	if (!streq(command, "expect")) {
  29.761 -		struct expect *i = list_top(&expects, struct expect, list);
  29.762 -
  29.763 -		if (i)
  29.764 -			barf("Expected '%s', didn't happen\n", i->pattern);
  29.765 -	}
  29.766 -}
  29.767 -
  29.768 -static struct option options[] = { { "readonly", 0, NULL, 'r' },
  29.769 -				   { "no-timeout", 0, NULL, 't' },
  29.770 -				   { NULL, 0, NULL, 0 } };
  29.771 -
  29.772 -int main(int argc, char *argv[])
  29.773 -{
  29.774 -	int opt;
  29.775 -	char line[1024];
  29.776 -
  29.777 -	while ((opt = getopt_long(argc, argv, "xrt", options, NULL)) != -1) {
  29.778 -		switch (opt) {
  29.779 -		case 'r':
  29.780 -			readonly = true;
  29.781 -			break;
  29.782 -		case 't':
  29.783 -			timeout_ms = 0;
  29.784 -			break;
  29.785 -		case 'x':
  29.786 -			print_input = true;
  29.787 -			break;
  29.788 -		}
  29.789 -	}
  29.790 -
  29.791 -	if (optind + 1 == argc) {
  29.792 -		int fd = open(argv[optind], O_RDONLY);
  29.793 -		if (!fd)
  29.794 -			barf_perror("Opening %s", argv[optind]);
  29.795 -		dup2(fd, STDIN_FILENO);
  29.796 -	} else if (optind != argc)
  29.797 -		usage();
  29.798 -	
  29.799 -
  29.800 -	signal(SIGALRM, alarmed);
  29.801 -	while (fgets(line, sizeof(line), stdin))
  29.802 -		do_command(0, line);
  29.803 -
  29.804 -	return 0;
  29.805 -}
  29.806 -
  29.807 -/*
  29.808 - * Local variables:
  29.809 - *  c-file-style: "linux"
  29.810 - *  indent-tabs-mode: t
  29.811 - *  c-indent-level: 8
  29.812 - *  c-basic-offset: 8
  29.813 - *  tab-width: 8
  29.814 - * End:
  29.815 - */