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