mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Add support in libxenstore for using the xenbus_dev store connection.
Also add simple read/write/rm clients for command line access to the store (using the xenbus_dev store connection). Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
This commit is contained in:
1 parent
b8ea605500
commit
a916bf616c
7 files changed
+239
-6
No files matched your search
@@ -153,8 +153,12 @@
|
||||
^tools/xenstat/xentop/xentop$
|
||||
^tools/xenstore/testsuite/tmp/.*$
|
||||
^tools/xenstore/xen$
|
||||
^tools/xenstore/xenbus_dev.h$
|
||||
^tools/xenstore/xenstored$
|
||||
^tools/xenstore/xenstored_test$
|
||||
^tools/xenstore/xenstore-read$
|
||||
^tools/xenstore/xenstore-rm$
|
||||
^tools/xenstore/xenstore-write$
|
||||
^tools/xenstore/xs_dom0_test$
|
||||
^tools/xenstore/xs_random$
|
||||
^tools/xenstore/xs_stress$
|
||||
|
||||
+15
-2
@@ -24,16 +24,28 @@ TESTDIR = `pwd`/testsuite/tmp
|
||||
TESTFLAGS= -DTESTING
|
||||
TESTENV = XENSTORED_ROOTDIR=$(TESTDIR) XENSTORED_RUNDIR=$(TESTDIR)
|
||||
|
||||
all: xen xenstored libxenstore.so
|
||||
CLIENTS := xenstore-read xenstore-rm xenstore-write
|
||||
CLIENTS_OBJS := $(patsubst xenstore-%,xenstore_%.o,$(CLIENTS))
|
||||
|
||||
all: xen xenbus_dev.h libxenstore.so xenstored $(CLIENTS)
|
||||
|
||||
testcode: xen xs_test xenstored_test xs_random xs_dom0_test
|
||||
|
||||
xen:
|
||||
ln -sf $(XEN_ROOT)/xen/include/public $@
|
||||
|
||||
xenbus_dev.h:
|
||||
ln -sf $(XEN_ROOT)/linux-2.6-xen-sparse/include/asm-xen/linux-public/xenbus_dev.h $@
|
||||
|
||||
xenstored: xenstored_core.o xenstored_watch.o xenstored_domain.o xenstored_transaction.o xs_lib.o talloc.o utils.o
|
||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -o $@
|
||||
|
||||
$(CLIENTS): xenstore-%: xenstore_%.o
|
||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -L. -lxenstore -o $@
|
||||
|
||||
$(CLIENTS_OBJS): xenstore_%.o: xenstore_client.c
|
||||
$(COMPILE.c) -DCLIENT_$(*F) -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
|
||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
|
||||
|
||||
@@ -111,12 +123,13 @@ TAGS:
|
||||
tarball: clean
|
||||
cd .. && tar -c -j -v -h -f xenstore.tar.bz2 xenstore/
|
||||
|
||||
install: xenstored libxenstore.so
|
||||
install: libxenstore.so xenstored $(CLIENTS)
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/var/run/xenstored
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/var/lib/xenstored
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/usr/sbin
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/usr/include
|
||||
$(INSTALL_PROG) xenstored $(DESTDIR)/usr/sbin
|
||||
$(INSTALL_PROG) $(CLIENTS) $(DESTDIR)/usr/bin
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR)
|
||||
$(INSTALL_DATA) libxenstore.so $(DESTDIR)/usr/$(LIBDIR)
|
||||
$(INSTALL_DATA) xs.h $(DESTDIR)/usr/include
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file "COPYING" in the main directory of
|
||||
* this archive for more details.
|
||||
*
|
||||
* Copyright (C) 2005 by Christian Limpach
|
||||
*
|
||||
*/
|
||||
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xs.h>
|
||||
|
||||
static void
|
||||
usage(const char *progname)
|
||||
{
|
||||
#if defined(CLIENT_read)
|
||||
errx(1, "Usage: %s [-h] [-p] key [...]", progname);
|
||||
#elif defined(CLIENT_write)
|
||||
errx(1, "Usage: %s [-h] key value [...]", progname);
|
||||
#elif defined(CLIENT_rm)
|
||||
errx(1, "Usage: %s [-h] key [...]", progname);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct xs_handle *xsh;
|
||||
bool success;
|
||||
int ret = 0;
|
||||
#if defined(CLIENT_read)
|
||||
char *val;
|
||||
int prefix = 0;
|
||||
#endif
|
||||
|
||||
xsh = xs_domain_open();
|
||||
if (xsh == NULL)
|
||||
err(1, "xs_domain_open");
|
||||
|
||||
while (1) {
|
||||
int c, index = 0;
|
||||
static struct option long_options[] = {
|
||||
{"help", 0, 0, 'h'},
|
||||
#if defined(CLIENT_read)
|
||||
{"prefix", 0, 0, 'p'},
|
||||
#endif
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "h"
|
||||
#if defined(CLIENT_read)
|
||||
"p"
|
||||
#endif
|
||||
, long_options, &index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
/* NOTREACHED */
|
||||
#if defined(CLIENT_read)
|
||||
case 'p':
|
||||
prefix = 1;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (optind == argc) {
|
||||
usage(argv[0]);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#if defined(CLIENT_write)
|
||||
if ((argc - optind) % 1) {
|
||||
usage(argv[0]);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* XXX maybe find longest common prefix */
|
||||
success = xs_transaction_start(xsh, "/");
|
||||
if (!success)
|
||||
errx(1, "couldn't start transaction");
|
||||
|
||||
while (optind < argc) {
|
||||
#if defined(CLIENT_read)
|
||||
val = xs_read(xsh, argv[optind], NULL);
|
||||
if (val == NULL) {
|
||||
warnx("couldn't read path %s", argv[optind]);
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
if (prefix)
|
||||
printf("%s: ", argv[optind]);
|
||||
printf("%s\n", val);
|
||||
free(val);
|
||||
optind++;
|
||||
#elif defined(CLIENT_write)
|
||||
success = xs_write(xsh, argv[optind], argv[optind + 1],
|
||||
strlen(argv[optind + 1]), O_CREAT);
|
||||
if (!success) {
|
||||
warnx("could not write path %s", argv[optind]);
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
optind += 2;
|
||||
#elif defined(CLIENT_rm)
|
||||
success = xs_rm(xsh, argv[optind]);
|
||||
if (!success) {
|
||||
warnx("could not remove path %s", argv[optind]);
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
optind++;
|
||||
#endif
|
||||
}
|
||||
|
||||
out:
|
||||
success = xs_transaction_end(xsh, ret ? true : false);
|
||||
if (!success)
|
||||
errx(1, "couldn't end transaction");
|
||||
|
||||
return ret;
|
||||
}
|
||||
+82
-4
@@ -31,14 +31,17 @@
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "xs.h"
|
||||
#include "xenstored.h"
|
||||
#include "xs_lib.h"
|
||||
#include "utils.h"
|
||||
#include "xenbus_dev.h"
|
||||
|
||||
struct xs_handle
|
||||
{
|
||||
int fd;
|
||||
enum { SOCK, DEV } type;
|
||||
};
|
||||
|
||||
/* Get the socket from the store daemon handle.
|
||||
@@ -65,13 +68,35 @@ static struct xs_handle *get_socket(const char *connect_to)
|
||||
h = malloc(sizeof(*h));
|
||||
if (h) {
|
||||
h->fd = sock;
|
||||
h->type = SOCK;
|
||||
return h;
|
||||
}
|
||||
}
|
||||
|
||||
saved_errno = errno;
|
||||
close(sock);
|
||||
free(h);
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct xs_handle *get_dev(const char *connect_to)
|
||||
{
|
||||
int fd, saved_errno;
|
||||
struct xs_handle *h = NULL;
|
||||
|
||||
fd = open(connect_to, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
h = malloc(sizeof(*h));
|
||||
if (h) {
|
||||
h->fd = fd;
|
||||
h->type = DEV;
|
||||
return h;
|
||||
}
|
||||
|
||||
saved_errno = errno;
|
||||
close(fd);
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
}
|
||||
@@ -86,6 +111,11 @@ struct xs_handle *xs_daemon_open_readonly(void)
|
||||
return get_socket(xs_daemon_socket_ro());
|
||||
}
|
||||
|
||||
struct xs_handle *xs_domain_open(void)
|
||||
{
|
||||
return get_dev(xs_domain_dev());
|
||||
}
|
||||
|
||||
void xs_daemon_close(struct xs_handle *h)
|
||||
{
|
||||
if (h->fd >= 0)
|
||||
@@ -160,9 +190,9 @@ static void *read_reply(int fd, enum xsd_sockmsg_type *type, unsigned int *len)
|
||||
}
|
||||
|
||||
/* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
|
||||
static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
|
||||
const struct iovec *iovec, unsigned int num_vecs,
|
||||
unsigned int *len)
|
||||
static void *xs_talkv_sock(struct xs_handle *h, enum xsd_sockmsg_type type,
|
||||
const struct iovec *iovec, unsigned int num_vecs,
|
||||
unsigned int *len)
|
||||
{
|
||||
struct xsd_sockmsg msg;
|
||||
void *ret = NULL;
|
||||
@@ -223,6 +253,54 @@ close_fd:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
|
||||
static void *xs_talkv_dev(struct xs_handle *h, enum xsd_sockmsg_type type,
|
||||
const struct iovec *iovec, unsigned int num_vecs,
|
||||
unsigned int *len)
|
||||
{
|
||||
struct xenbus_dev_talkv dt;
|
||||
char *buf;
|
||||
int err, buflen = 1024;
|
||||
|
||||
again:
|
||||
buf = malloc(buflen);
|
||||
if (buf == NULL) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
dt.type = type;
|
||||
dt.iovec = (struct kvec *)iovec;
|
||||
dt.num_vecs = num_vecs;
|
||||
dt.buf = buf;
|
||||
dt.len = buflen;
|
||||
err = ioctl(h->fd, IOCTL_XENBUS_DEV_TALKV, &dt);
|
||||
if (err < 0) {
|
||||
free(buf);
|
||||
errno = err;
|
||||
return NULL;
|
||||
}
|
||||
if (err > buflen) {
|
||||
free(buf);
|
||||
buflen = err;
|
||||
goto again;
|
||||
}
|
||||
if (len)
|
||||
*len = err;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
|
||||
static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
|
||||
const struct iovec *iovec, unsigned int num_vecs,
|
||||
unsigned int *len)
|
||||
{
|
||||
if (h->type == SOCK)
|
||||
return xs_talkv_sock(h, type, iovec, num_vecs, len);
|
||||
if (h->type == DEV)
|
||||
return xs_talkv_dev(h, type, iovec, num_vecs, len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* free(), but don't change errno. */
|
||||
static void free_no_errno(void *p)
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@ struct xs_handle;
|
||||
* Returns a handle or NULL.
|
||||
*/
|
||||
struct xs_handle *xs_daemon_open(void);
|
||||
struct xs_handle *xs_domain_open(void);
|
||||
|
||||
/* Connect to the xs daemon (readonly for non-root clients).
|
||||
* Returns a handle or NULL.
|
||||
|
||||
@@ -66,6 +66,12 @@ const char *xs_daemon_transactions(void)
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *xs_domain_dev(void)
|
||||
{
|
||||
char *s = getenv("XENSTORED_DOMAIN_DEV");
|
||||
return (s ? s : "/proc/xen/xenbus");
|
||||
}
|
||||
|
||||
/* Simple routines for writing to sockets, etc. */
|
||||
bool xs_write_all(int fd, const void *data, unsigned int len)
|
||||
{
|
||||
|
||||
@@ -48,6 +48,7 @@ const char *xs_daemon_socket(void);
|
||||
const char *xs_daemon_socket_ro(void);
|
||||
const char *xs_daemon_store(void);
|
||||
const char *xs_daemon_transactions(void);
|
||||
const char *xs_domain_dev(void);
|
||||
|
||||
/* Simple write function: loops for you. */
|
||||
bool xs_write_all(int fd, const void *data, unsigned int len);
|
||||
|
||||