/* * Copyright (c) 2018 Citrix Systems Inc. * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. */ #include "qemu/osdep.h" #include "hw/sysbus.h" #include "hw/xen/xen.h" #include "hw/xen/xen-bus.h" #include "hw/xen/xen-bus-helper.h" #include "qapi/error.h" #include struct xs_state { enum xenbus_state statenum; const char *statestr; }; #define XS_STATE(state) { state, #state } static struct xs_state xs_state[] = { XS_STATE(XenbusStateUnknown), XS_STATE(XenbusStateInitialising), XS_STATE(XenbusStateInitWait), XS_STATE(XenbusStateInitialised), XS_STATE(XenbusStateConnected), XS_STATE(XenbusStateClosing), XS_STATE(XenbusStateClosed), XS_STATE(XenbusStateReconfiguring), XS_STATE(XenbusStateReconfigured), }; #undef XS_STATE const char *xs_strstate(enum xenbus_state state) { unsigned int i; for (i = 0; i < ARRAY_SIZE(xs_state); i++) { if (xs_state[i].statenum == state) { return xs_state[i].statestr; } } return "INVALID"; } void xs_node_create(struct xs_handle *xsh, xs_transaction_t tid, const char *node, struct xs_permissions perms[], unsigned int nr_perms, Error **errp) { trace_xs_node_create(node); if (!xs_write(xsh, tid, node, "", 0)) { error_setg_errno(errp, errno, "failed to create node '%s'", node); return; } if (!xs_set_permissions(xsh, tid, node, perms, nr_perms)) { error_setg_errno(errp, errno, "failed to set node '%s' permissions", node); } } void xs_node_destroy(struct xs_handle *xsh, xs_transaction_t tid, const char *node, Error **errp) { trace_xs_node_destroy(node); if (!xs_rm(xsh, tid, node)) { error_setg_errno(errp, errno, "failed to destroy node '%s'", node); } } void xs_node_vprintf(struct xs_handle *xsh, xs_transaction_t tid, const char *node, const char *key, Error **errp, const char *fmt, va_list ap) { char *path, *value; int len; path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : g_strdup(key); len = g_vasprintf(&value, fmt, ap); trace_xs_node_vprintf(path, value); if (!xs_write(xsh, tid, path, value, len)) { error_setg_errno(errp, errno, "failed to write '%s' to '%s'", value, path); } g_free(value); g_free(path); } void xs_node_printf(struct xs_handle *xsh, xs_transaction_t tid, const char *node, const char *key, Error **errp, const char *fmt, ...) { va_list ap; va_start(ap, fmt); xs_node_vprintf(xsh, tid, node, key, errp, fmt, ap); va_end(ap); } int xs_node_vscanf(struct xs_handle *xsh, xs_transaction_t tid, const char *node, const char *key, Error **errp, const char *fmt, va_list ap) { char *path, *value; int rc; path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : g_strdup(key); value = xs_read(xsh, tid, path, NULL); trace_xs_node_vscanf(path, value); if (value) { rc = vsscanf(value, fmt, ap); } else { error_setg_errno(errp, errno, "failed to read from '%s'", path); rc = EOF; } free(value); g_free(path); return rc; } int xs_node_scanf(struct xs_handle *xsh, xs_transaction_t tid, const char *node, const char *key, Error **errp, const char *fmt, ...) { va_list ap; int rc; va_start(ap, fmt); rc = xs_node_vscanf(xsh, tid, node, key, errp, fmt, ap); va_end(ap); return rc; } void xs_node_watch(struct xs_handle *xsh, const char *node, const char *key, char *token, Error **errp) { char *path; path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : g_strdup(key); trace_xs_node_watch(path); if (!xs_watch(xsh, path, token)) { error_setg_errno(errp, errno, "failed to watch node '%s'", path); } g_free(path); } void xs_node_unwatch(struct xs_handle *xsh, const char *node, const char *key, const char *token, Error **errp) { char *path; path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : g_strdup(key); trace_xs_node_unwatch(path); if (!xs_unwatch(xsh, path, token)) { error_setg_errno(errp, errno, "failed to unwatch node '%s'", path); } g_free(path); }