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