]>
Commit | Line | Data |
---|---|---|
094a2239 PD |
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 | } | |
82a29e30 PD |
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 | } |