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/sysbus.h" 10 #include "hw/xen/xen.h" 11 #include "hw/xen/xen-bus.h" 12 #include "hw/xen/xen-bus-helper.h" 13 #include "qapi/error.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 xs_handle *xsh, xs_transaction_t tid, 51 const char *node, struct xs_permissions perms[], 52 unsigned int nr_perms, Error **errp) 53 { 54 trace_xs_node_create(node); 55 56 if (!xs_write(xsh, tid, node, "", 0)) { 57 error_setg_errno(errp, errno, "failed to create node '%s'", node); 58 return; 59 } 60 61 if (!xs_set_permissions(xsh, tid, node, perms, nr_perms)) { 62 error_setg_errno(errp, errno, "failed to set node '%s' permissions", 63 node); 64 } 65 } 66 67 void xs_node_destroy(struct xs_handle *xsh, xs_transaction_t tid, 68 const char *node, Error **errp) 69 { 70 trace_xs_node_destroy(node); 71 72 if (!xs_rm(xsh, tid, node)) { 73 error_setg_errno(errp, errno, "failed to destroy node '%s'", node); 74 } 75 } 76 77 void xs_node_vprintf(struct xs_handle *xsh, xs_transaction_t tid, 78 const char *node, const char *key, Error **errp, 79 const char *fmt, va_list ap) 80 { 81 char *path, *value; 82 int len; 83 84 path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : 85 g_strdup(key); 86 len = g_vasprintf(&value, fmt, ap); 87 88 trace_xs_node_vprintf(path, value); 89 90 if (!xs_write(xsh, tid, path, value, len)) { 91 error_setg_errno(errp, errno, "failed to write '%s' to '%s'", 92 value, path); 93 } 94 95 g_free(value); 96 g_free(path); 97 } 98 99 void xs_node_printf(struct xs_handle *xsh, xs_transaction_t tid, 100 const char *node, const char *key, Error **errp, 101 const char *fmt, ...) 102 { 103 va_list ap; 104 105 va_start(ap, fmt); 106 xs_node_vprintf(xsh, tid, node, key, errp, fmt, ap); 107 va_end(ap); 108 } 109 110 int xs_node_vscanf(struct xs_handle *xsh, xs_transaction_t tid, 111 const char *node, const char *key, Error **errp, 112 const char *fmt, va_list ap) 113 { 114 char *path, *value; 115 int rc; 116 117 path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : 118 g_strdup(key); 119 value = xs_read(xsh, tid, path, NULL); 120 121 trace_xs_node_vscanf(path, value); 122 123 if (value) { 124 rc = vsscanf(value, fmt, ap); 125 } else { 126 error_setg_errno(errp, errno, "failed to read from '%s'", 127 path); 128 rc = EOF; 129 } 130 131 free(value); 132 g_free(path); 133 134 return rc; 135 } 136 137 int xs_node_scanf(struct xs_handle *xsh, xs_transaction_t tid, 138 const char *node, const char *key, Error **errp, 139 const char *fmt, ...) 140 { 141 va_list ap; 142 int rc; 143 144 va_start(ap, fmt); 145 rc = xs_node_vscanf(xsh, tid, node, key, errp, fmt, ap); 146 va_end(ap); 147 148 return rc; 149 } 150 151 void xs_node_watch(struct xs_handle *xsh, const char *node, const char *key, 152 char *token, Error **errp) 153 { 154 char *path; 155 156 path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : 157 g_strdup(key); 158 159 trace_xs_node_watch(path); 160 161 if (!xs_watch(xsh, path, token)) { 162 error_setg_errno(errp, errno, "failed to watch node '%s'", path); 163 } 164 165 g_free(path); 166 } 167 168 void xs_node_unwatch(struct xs_handle *xsh, const char *node, 169 const char *key, const char *token, Error **errp) 170 { 171 char *path; 172 173 path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : 174 g_strdup(key); 175 176 trace_xs_node_unwatch(path); 177 178 if (!xs_unwatch(xsh, path, token)) { 179 error_setg_errno(errp, errno, "failed to unwatch node '%s'", path); 180 } 181 182 g_free(path); 183 } 184