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/hw.h" 10 #include "hw/sysbus.h" 11 #include "hw/xen/xen.h" 12 #include "hw/xen/xen-bus.h" 13 #include "hw/xen/xen-bus-helper.h" 14 #include "qapi/error.h" 15 16 #include <glib/gprintf.h> 17 18 struct xs_state { 19 enum xenbus_state statenum; 20 const char *statestr; 21 }; 22 #define XS_STATE(state) { state, #state } 23 24 static struct xs_state xs_state[] = { 25 XS_STATE(XenbusStateUnknown), 26 XS_STATE(XenbusStateInitialising), 27 XS_STATE(XenbusStateInitWait), 28 XS_STATE(XenbusStateInitialised), 29 XS_STATE(XenbusStateConnected), 30 XS_STATE(XenbusStateClosing), 31 XS_STATE(XenbusStateClosed), 32 XS_STATE(XenbusStateReconfiguring), 33 XS_STATE(XenbusStateReconfigured), 34 }; 35 36 #undef XS_STATE 37 38 const char *xs_strstate(enum xenbus_state state) 39 { 40 unsigned int i; 41 42 for (i = 0; i < ARRAY_SIZE(xs_state); i++) { 43 if (xs_state[i].statenum == state) { 44 return xs_state[i].statestr; 45 } 46 } 47 48 return "INVALID"; 49 } 50 51 void xs_node_create(struct xs_handle *xsh, xs_transaction_t tid, 52 const char *node, struct xs_permissions perms[], 53 unsigned int nr_perms, Error **errp) 54 { 55 trace_xs_node_create(node); 56 57 if (!xs_write(xsh, tid, node, "", 0)) { 58 error_setg_errno(errp, errno, "failed to create node '%s'", node); 59 return; 60 } 61 62 if (!xs_set_permissions(xsh, tid, node, perms, nr_perms)) { 63 error_setg_errno(errp, errno, "failed to set node '%s' permissions", 64 node); 65 } 66 } 67 68 void xs_node_destroy(struct xs_handle *xsh, xs_transaction_t tid, 69 const char *node, Error **errp) 70 { 71 trace_xs_node_destroy(node); 72 73 if (!xs_rm(xsh, tid, node)) { 74 error_setg_errno(errp, errno, "failed to destroy node '%s'", node); 75 } 76 } 77 78 void xs_node_vprintf(struct xs_handle *xsh, xs_transaction_t tid, 79 const char *node, const char *key, Error **errp, 80 const char *fmt, va_list ap) 81 { 82 char *path, *value; 83 int len; 84 85 path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : 86 g_strdup(key); 87 len = g_vasprintf(&value, fmt, ap); 88 89 trace_xs_node_vprintf(path, value); 90 91 if (!xs_write(xsh, tid, path, value, len)) { 92 error_setg_errno(errp, errno, "failed to write '%s' to '%s'", 93 value, path); 94 } 95 96 g_free(value); 97 g_free(path); 98 } 99 100 void xs_node_printf(struct xs_handle *xsh, xs_transaction_t tid, 101 const char *node, const char *key, Error **errp, 102 const char *fmt, ...) 103 { 104 va_list ap; 105 106 va_start(ap, fmt); 107 xs_node_vprintf(xsh, tid, node, key, errp, fmt, ap); 108 va_end(ap); 109 } 110 111 int xs_node_vscanf(struct xs_handle *xsh, xs_transaction_t tid, 112 const char *node, const char *key, Error **errp, 113 const char *fmt, va_list ap) 114 { 115 char *path, *value; 116 int rc; 117 118 path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : 119 g_strdup(key); 120 value = xs_read(xsh, tid, path, NULL); 121 122 trace_xs_node_vscanf(path, value); 123 124 if (value) { 125 rc = vsscanf(value, fmt, ap); 126 } else { 127 error_setg_errno(errp, errno, "failed to read from '%s'", 128 path); 129 rc = EOF; 130 } 131 132 free(value); 133 g_free(path); 134 135 return rc; 136 } 137 138 int xs_node_scanf(struct xs_handle *xsh, xs_transaction_t tid, 139 const char *node, const char *key, Error **errp, 140 const char *fmt, ...) 141 { 142 va_list ap; 143 int rc; 144 145 va_start(ap, fmt); 146 rc = xs_node_vscanf(xsh, tid, node, key, errp, fmt, ap); 147 va_end(ap); 148 149 return rc; 150 } 151 152 void xs_node_watch(struct xs_handle *xsh, const char *node, const char *key, 153 char *token, Error **errp) 154 { 155 char *path; 156 157 path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : 158 g_strdup(key); 159 160 trace_xs_node_watch(path); 161 162 if (!xs_watch(xsh, path, token)) { 163 error_setg_errno(errp, errno, "failed to watch node '%s'", path); 164 } 165 166 g_free(path); 167 } 168 169 void xs_node_unwatch(struct xs_handle *xsh, const char *node, 170 const char *key, const char *token, Error **errp) 171 { 172 char *path; 173 174 path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : 175 g_strdup(key); 176 177 trace_xs_node_unwatch(path); 178 179 if (!xs_unwatch(xsh, path, token)) { 180 error_setg_errno(errp, errno, "failed to unwatch node '%s'", path); 181 } 182 183 g_free(path); 184 } 185