xref: /qemu/hw/xen/xen-bus-helper.c (revision f07a5674cf97b8473e5d06d7b1df9b51e97d553f)
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