By changing gvir_config_xml_foreach_child to make it robust against
current node deletion in the "foreach" callback, we can use
gvir_config_object_foreach_child to implement
gvir_config_object_delete_child
---
libvirt-gconfig/libvirt-gconfig-helpers.c | 5 +++-
libvirt-gconfig/libvirt-gconfig-object.c | 32 ++++++++++++++++++----------
2 files changed, 24 insertions(+), 13 deletions(-)
diff --git a/libvirt-gconfig/libvirt-gconfig-helpers.c
b/libvirt-gconfig/libvirt-gconfig-helpers.c
index cc2e5cc..c406a49 100644
--- a/libvirt-gconfig/libvirt-gconfig-helpers.c
+++ b/libvirt-gconfig/libvirt-gconfig-helpers.c
@@ -169,14 +169,17 @@ void gvir_config_xml_foreach_child(xmlNodePtr node,
g_return_if_fail(iter_func != NULL);
- for (it = node->children; it != NULL; it = it->next) {
+ it = node->children;
+ while (it != NULL) {
gboolean cont;
+ xmlNodePtr next = it->next;
if (xmlIsBlankNode(it))
continue;
cont = iter_func(it, opaque);
if (!cont)
break;
+ it = next;
}
}
diff --git a/libvirt-gconfig/libvirt-gconfig-object.c
b/libvirt-gconfig/libvirt-gconfig-object.c
index 5645490..7fb8b69 100644
--- a/libvirt-gconfig/libvirt-gconfig-object.c
+++ b/libvirt-gconfig/libvirt-gconfig-object.c
@@ -465,27 +465,35 @@ gvir_config_object_replace_child_with_attribute(GVirConfigObject
*object,
g_object_unref(G_OBJECT(child));
}
+static gboolean maybe_unlink_node(xmlNodePtr node, const char *name)
+{
+ if (g_strcmp0((char *)node->name, name) == 0) {
+ xmlUnlinkNode(node);
+ xmlFreeNode(node);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean remove_oneshot(xmlNodePtr node, gpointer opaque)
+{
+ return !maybe_unlink_node(node, opaque);
+}
+
G_GNUC_INTERNAL void
gvir_config_object_delete_child(GVirConfigObject *object,
const char *child_name)
{
- xmlNodePtr parent_node;
- xmlNodePtr old_node;
-
g_return_if_fail(GVIR_CONFIG_IS_OBJECT(object));
g_return_if_fail(child_name != NULL);
- parent_node = gvir_config_object_get_xml_node(GVIR_CONFIG_OBJECT(object));
- g_return_if_fail(parent_node != NULL);
+ gvir_config_object_foreach_child(object, NULL, remove_oneshot,
+ (gpointer)child_name);
+}
- if (!(old_node = gvir_config_xml_get_element(parent_node, child_name, NULL)))
- return;
- /* FIXME: should we make sure there are no multiple occurrences
- * of this node?
- */
- xmlUnlinkNode(old_node);
- xmlFreeNode(old_node);
}
--
1.7.7.5