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
xs_strstate(enum xenbus_state state)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
xs_node_create(struct qemu_xs_handle * h,xs_transaction_t tid,const char * node,unsigned int owner,unsigned int domid,unsigned int perms,Error ** errp)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
xs_node_destroy(struct qemu_xs_handle * h,xs_transaction_t tid,const char * node,Error ** errp)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
xs_node_vprintf(struct qemu_xs_handle * h,xs_transaction_t tid,const char * node,const char * key,Error ** errp,const char * fmt,va_list ap)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
xs_node_printf(struct qemu_xs_handle * h,xs_transaction_t tid,const char * node,const char * key,Error ** errp,const char * fmt,...)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
xs_node_vscanf(struct qemu_xs_handle * h,xs_transaction_t tid,const char * node,const char * key,Error ** errp,const char * fmt,va_list ap)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
xs_node_scanf(struct qemu_xs_handle * h,xs_transaction_t tid,const char * node,const char * key,Error ** errp,const char * fmt,...)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
xs_node_read(struct qemu_xs_handle * h,xs_transaction_t tid,unsigned int * len,Error ** errp,const char * path_fmt,...)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
xs_node_watch(struct qemu_xs_handle * h,const char * node,const char * key,xs_watch_fn fn,void * opaque,Error ** errp)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
xs_node_unwatch(struct qemu_xs_handle * h,struct qemu_xs_watch * w)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