1 /*
2 * libvirt-gconfig-helpers.c: libvirt configuration helpers
3 *
4 * Copyright (C) 2010, 2011 Red Hat, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 * Authors: Daniel P. Berrange <berrange@redhat.com>
21 * Christophe Fergeau <cfergeau@gmail.com>
22 */
23
24 #include <config.h>
25
26 #include <string.h>
27
28 #include <libxml/xmlerror.h>
29 #include <glib/gi18n-lib.h>
30
31 #include "libvirt-gconfig/libvirt-gconfig.h"
32 #include "libvirt-gconfig/libvirt-gconfig-helpers-private.h"
33
34 GQuark
gvir_config_object_error_quark(void)35 gvir_config_object_error_quark(void)
36 {
37 return g_quark_from_static_string("gvir-config-object");
38 }
39
gvir_config_error_new_literal(GQuark domain,gint code,const gchar * message)40 static GError *gvir_config_error_new_literal(GQuark domain,
41 gint code,
42 const gchar *message)
43 {
44 xmlErrorPtr xerr = xmlGetLastError();
45
46 if (!xerr)
47 return NULL;
48
49 if (message)
50 return g_error_new(domain,
51 code,
52 "%s: %s",
53 message,
54 xerr->message);
55 else
56 return g_error_new(domain,
57 code,
58 "%s",
59 xerr->message);
60 }
61
62
gvir_config_error_new(GQuark domain,gint code,const gchar * format,...)63 GError *gvir_config_error_new(GQuark domain,
64 gint code,
65 const gchar *format,
66 ...)
67 {
68 GError *err;
69 va_list args;
70 gchar *message;
71
72 va_start(args, format);
73 message = g_strdup_vprintf(format, args);
74 va_end(args);
75
76 err = gvir_config_error_new_literal(domain, code, message);
77
78 g_free(message);
79
80 return err;
81 }
82
83
gvir_config_set_error(GError ** err,GQuark domain,gint code,const gchar * format,...)84 void gvir_config_set_error(GError **err,
85 GQuark domain, gint code,
86 const gchar *format, ...)
87 {
88 va_list args;
89 gchar *message;
90
91 if (!err)
92 return;
93
94 va_start(args, format);
95 message = g_strdup_vprintf(format, args);
96 va_end(args);
97
98 *err = gvir_config_error_new_literal(domain, code, message);
99
100 g_free(message);
101 }
102
103
gvir_config_set_error_literal(GError ** err,GQuark domain,gint code,const gchar * message)104 void gvir_config_set_error_literal(GError **err,
105 GQuark domain, gint code,
106 const gchar *message)
107 {
108 if (!err)
109 return;
110
111 *err = gvir_config_error_new_literal(domain, code, message);
112 }
113
114
gvir_config_set_error_valist(GError ** err,GQuark domain,gint code,const gchar * format,va_list args)115 void gvir_config_set_error_valist(GError **err,
116 GQuark domain, gint code,
117 const gchar *format,
118 va_list args)
119 {
120 gchar *message;
121
122 if (!err)
123 return;
124
125 message = g_strdup_vprintf(format, args);
126
127 *err = gvir_config_error_new_literal(domain, code, message);
128
129 g_free(message);
130 }
131
132 xmlNodePtr
gvir_config_xml_parse(const char * xml,const char * root_node,GError ** err)133 gvir_config_xml_parse(const char *xml, const char *root_node, GError **err)
134 {
135 xmlDocPtr doc;
136
137 if (!xml) {
138 *err = g_error_new(GVIR_CONFIG_OBJECT_ERROR,
139 0,
140 "%s",
141 _("No XML document to parse"));
142 return NULL;
143 }
144
145 doc = xmlParseMemory(xml, strlen(xml));
146 if (!doc) {
147 gvir_config_set_error_literal(err, GVIR_CONFIG_OBJECT_ERROR,
148 0,
149 _("Unable to parse configuration"));
150 return NULL;
151 }
152 if ((!doc->children) ||
153 ((root_node != NULL) && g_strcmp0((char *)doc->children->name, root_node) != 0)) {
154 g_set_error(err,
155 GVIR_CONFIG_OBJECT_ERROR,
156 0,
157 _("XML data has no '%s' node"),
158 root_node);
159 xmlFreeDoc(doc);
160 return NULL;
161 }
162
163 return doc->children;
164 }
165
gvir_config_xml_foreach_child(xmlNodePtr node,GVirConfigXmlNodeIterator iter_func,gpointer opaque)166 void gvir_config_xml_foreach_child(xmlNodePtr node,
167 GVirConfigXmlNodeIterator iter_func,
168 gpointer opaque)
169 {
170 xmlNodePtr it;
171
172 g_return_if_fail(iter_func != NULL);
173
174 it = node->children;
175 while (it != NULL) {
176 gboolean cont;
177 xmlNodePtr next = it->next;
178
179 if (!xmlIsBlankNode(it)) {
180 cont = iter_func(it, opaque);
181 if (!cont)
182 break;
183 }
184
185 it = next;
186 }
187 }
188
189 /*
190 * gvir_config_xml_get_element is
191 *
192 * Copyright (C) 2006, 2007 OpenedHand Ltd.
193 *
194 * Author: Jorn Baayen <jorn@openedhand.com>
195 */
196 xmlNode *
gvir_config_xml_get_element(xmlNode * node,...)197 gvir_config_xml_get_element (xmlNode *node, ...)
198 {
199 va_list var_args;
200
201 va_start (var_args, node);
202
203 while (TRUE) {
204 const char *arg;
205
206 arg = va_arg (var_args, const char *);
207 if (!arg)
208 break;
209
210 for (node = node->children; node; node = node->next)
211 if (!g_strcmp0 (arg, (char *) node->name))
212 break;
213
214 if (!node)
215 break;
216 }
217
218 va_end (var_args);
219
220 return node;
221 }
222
223 G_GNUC_INTERNAL const char *
gvir_config_xml_get_child_element_content(xmlNode * node,const char * child_name)224 gvir_config_xml_get_child_element_content (xmlNode *node,
225 const char *child_name)
226 {
227 xmlNode *child_node;
228
229 child_node = gvir_config_xml_get_element(node, child_name, NULL);
230 if (!child_node || !(child_node->children))
231 return NULL;
232
233 return (const char *)child_node->children->content;
234 }
235
236 G_GNUC_INTERNAL const char *
gvir_config_xml_get_attribute_content(xmlNodePtr node,const char * attr_name)237 gvir_config_xml_get_attribute_content(xmlNodePtr node, const char *attr_name)
238 {
239 xmlAttr *attr;
240
241 for (attr = node->properties; attr; attr = attr->next)
242 if (g_strcmp0 (attr_name, (char *)attr->name) == 0)
243 return (const char *)attr->children->content;
244
245 return NULL;
246 }
247
gvir_config_genum_get_nick(GType enum_type,gint value)248 const char *gvir_config_genum_get_nick (GType enum_type, gint value)
249 {
250 GEnumClass *enum_class;
251 GEnumValue *enum_value;
252
253 g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), NULL);
254
255 enum_class = g_type_class_ref(enum_type);
256 enum_value = g_enum_get_value(enum_class, value);
257 g_type_class_unref(enum_class);
258
259 if (enum_value != NULL)
260 return enum_value->value_nick;
261
262 g_return_val_if_reached(NULL);
263 }
264
265 G_GNUC_INTERNAL int
gvir_config_genum_get_value(GType enum_type,const char * nick,gint default_value)266 gvir_config_genum_get_value (GType enum_type, const char *nick,
267 gint default_value)
268 {
269 GEnumClass *enum_class;
270 GEnumValue *enum_value;
271
272 g_return_val_if_fail(G_TYPE_IS_ENUM(enum_type), default_value);
273 g_return_val_if_fail(nick != NULL, default_value);
274
275 enum_class = g_type_class_ref(enum_type);
276 enum_value = g_enum_get_value_by_nick(enum_class, nick);
277 g_type_class_unref(enum_class);
278
279 if (enum_value != NULL)
280 return enum_value->value;
281
282 g_return_val_if_reached(default_value);
283 }
284
285 G_GNUC_INTERNAL char *
gvir_config_xml_node_to_string(xmlNodePtr node)286 gvir_config_xml_node_to_string(xmlNodePtr node)
287 {
288 xmlBufferPtr xmlbuf;
289 char *xml;
290
291 if (node == NULL)
292 return NULL;
293
294 xmlbuf = xmlBufferCreate();
295 if (xmlNodeDump(xmlbuf, node->doc, node, 0, 1) < 0)
296 xml = NULL;
297 else
298 xml = g_strndup((gchar *)xmlBufferContent(xmlbuf), xmlBufferLength(xmlbuf));
299
300 xmlBufferFree(xmlbuf);
301
302 return xml;
303 }
304