1 /* 2 * Copyright (c) 2018 Citrix Systems Inc. 3 * 4 * This work is licensed under the terms of the GNU GPL, version 2 or later. 5 * See the COPYING file in the top-level directory. 6 */ 7 8 #include "qemu/osdep.h" 9 #include "hw/xen/xen.h" 10 #include "hw/xen/xen-bus.h" 11 #include "hw/xen/xen-bus-helper.h" 12 #include "qapi/error.h" 13 #include "trace.h" 14 15 #include <glib/gprintf.h> 16 17 struct xs_state { 18 enum xenbus_state statenum; 19 const char *statestr; 20 }; 21 #define XS_STATE(state) { state, #state } 22 23 static struct xs_state xs_state[] = { 24 XS_STATE(XenbusStateUnknown), 25 XS_STATE(XenbusStateInitialising), 26 XS_STATE(XenbusStateInitWait), 27 XS_STATE(XenbusStateInitialised), 28 XS_STATE(XenbusStateConnected), 29 XS_STATE(XenbusStateClosing), 30 XS_STATE(XenbusStateClosed), 31 XS_STATE(XenbusStateReconfiguring), 32 XS_STATE(XenbusStateReconfigured), 33 }; 34 35 #undef XS_STATE 36 37 const char *xs_strstate(enum xenbus_state state) 38 { 39 unsigned int i; 40 41 for (i = 0; i < ARRAY_SIZE(xs_state); i++) { 42 if (xs_state[i].statenum == state) { 43 return xs_state[i].statestr; 44 } 45 } 46 47 return "INVALID"; 48 } 49 50 void xs_node_create(struct qemu_xs_handle *h, xs_transaction_t tid, 51 const char *node, unsigned int owner, unsigned int domid, 52 unsigned int perms, Error **errp) 53 { 54 trace_xs_node_create(node); 55 56 if (!qemu_xen_xs_create(h, tid, owner, domid, perms, node)) { 57 error_setg_errno(errp, errno, "failed to create node '%s'", node); 58 } 59 } 60 61 void xs_node_destroy(struct qemu_xs_handle *h, xs_transaction_t tid, 62 const char *node, Error **errp) 63 { 64 trace_xs_node_destroy(node); 65 66 if (!qemu_xen_xs_destroy(h, tid, node)) { 67 error_setg_errno(errp, errno, "failed to destroy node '%s'", node); 68 } 69 } 70 71 void xs_node_vprintf(struct qemu_xs_handle *h, xs_transaction_t tid, 72 const char *node, const char *key, Error **errp, 73 const char *fmt, va_list ap) 74 { 75 char *path, *value; 76 int len; 77 78 path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : 79 g_strdup(key); 80 len = g_vasprintf(&value, fmt, ap); 81 82 trace_xs_node_vprintf(path, value); 83 84 if (!qemu_xen_xs_write(h, tid, path, value, len)) { 85 error_setg_errno(errp, errno, "failed to write '%s' to '%s'", 86 value, path); 87 } 88 89 g_free(value); 90 g_free(path); 91 } 92 93 void xs_node_printf(struct qemu_xs_handle *h, xs_transaction_t tid, 94 const char *node, const char *key, Error **errp, 95 const char *fmt, ...) 96 { 97 va_list ap; 98 99 va_start(ap, fmt); 100 xs_node_vprintf(h, tid, node, key, errp, fmt, ap); 101 va_end(ap); 102 } 103 104 int xs_node_vscanf(struct qemu_xs_handle *h, xs_transaction_t tid, 105 const char *node, const char *key, Error **errp, 106 const char *fmt, va_list ap) 107 { 108 char *value; 109 int rc; 110 111 if (node && strlen(node) != 0) { 112 value = xs_node_read(h, tid, NULL, errp, "%s/%s", node, key); 113 } else { 114 value = xs_node_read(h, tid, NULL, errp, "%s", key); 115 } 116 117 if (value) { 118 rc = vsscanf(value, fmt, ap); 119 } else { 120 rc = EOF; 121 } 122 123 free(value); 124 125 return rc; 126 } 127 128 int xs_node_scanf(struct qemu_xs_handle *h, xs_transaction_t tid, 129 const char *node, const char *key, Error **errp, 130 const char *fmt, ...) 131 { 132 va_list ap; 133 int rc; 134 135 va_start(ap, fmt); 136 rc = xs_node_vscanf(h, tid, node, key, errp, fmt, ap); 137 va_end(ap); 138 139 return rc; 140 } 141 142 char *xs_node_read(struct qemu_xs_handle *h, xs_transaction_t tid, 143 unsigned int *len, Error **errp, 144 const char *path_fmt, ...) 145 { 146 char *path, *value; 147 va_list ap; 148 149 va_start(ap, path_fmt); 150 path = g_strdup_vprintf(path_fmt, ap); 151 va_end(ap); 152 153 value = qemu_xen_xs_read(h, tid, path, len); 154 trace_xs_node_read(path, value); 155 if (!value) { 156 error_setg_errno(errp, errno, "failed to read from '%s'", path); 157 } 158 159 g_free(path); 160 161 return value; 162 } 163 164 struct qemu_xs_watch *xs_node_watch(struct qemu_xs_handle *h, const char *node, 165 const char *key, xs_watch_fn fn, 166 void *opaque, Error **errp) 167 { 168 char *path; 169 struct qemu_xs_watch *w; 170 171 path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : 172 g_strdup(key); 173 174 trace_xs_node_watch(path); 175 176 w = qemu_xen_xs_watch(h, path, fn, opaque); 177 if (!w) { 178 error_setg_errno(errp, errno, "failed to watch node '%s'", path); 179 } 180 181 g_free(path); 182 183 return w; 184 } 185 186 void xs_node_unwatch(struct qemu_xs_handle *h, struct qemu_xs_watch *w) 187 { 188 qemu_xen_xs_unwatch(h, w); 189 } 190