summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Rockai <prockai@redhat.com>2014-11-19 18:37:31 +0100
committerPetr Rockai <prockai@redhat.com>2014-11-20 16:51:06 +0100
commit274a7a68b80fdce9e9398ffbe45e788b13b04642 (patch)
tree2bb34a21c74178d65786967d5a573ab781862420
parent956c19284195f3200a1370166bd8847e5d159588 (diff)
downloadlvm2-274a7a68b80fdce9e9398ffbe45e788b13b04642.tar.gz
libdm-config: Implement dm_config_flatten.
-rw-r--r--libdm/libdevmapper.h5
-rw-r--r--libdm/libdm-config.c53
2 files changed, 58 insertions, 0 deletions
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index 6e237c011..3400c2825 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -1848,6 +1848,11 @@ struct dm_config_tree *dm_config_insert_cascaded_tree(struct dm_config_tree *fir
*/
struct dm_config_tree *dm_config_remove_cascaded_tree(struct dm_config_tree *cft);
+/*
+ * Create a new, uncascaded config tree equivalent to the input cascade.
+ */
+struct dm_config_tree *dm_config_flatten(struct dm_config_tree *cft);
+
void dm_config_destroy(struct dm_config_tree *cft);
/* Simple output line by line. */
diff --git a/libdm/libdm-config.c b/libdm/libdm-config.c
index c02638513..e6b2b90d1 100644
--- a/libdm/libdm-config.c
+++ b/libdm/libdm-config.c
@@ -1315,3 +1315,56 @@ struct dm_pool *dm_config_memory(struct dm_config_tree *cft)
{
return cft->mem;
}
+
+static int _override_path(const char *path, struct dm_config_node *node, void *baton)
+{
+ struct dm_config_tree *cft = baton;
+ struct dm_config_node dummy, *target;
+ dummy.child = cft->root;
+ if (!(target = _find_or_make_node(cft->mem, &dummy, path)))
+ return_0;
+ if (!(target->v = _clone_config_value(cft->mem, node->v)))
+ return_0;
+ cft->root = dummy.child;
+ return 1;
+}
+
+static int _enumerate(const char *path, struct dm_config_node *cn, int (*cb)(const char *, struct dm_config_node *, void *), void *baton)
+{
+ char *sub = NULL;
+
+ while (cn) {
+ if (dm_asprintf(&sub, "%s/%s", path, cn->key) < 0)
+ return_0;
+ if (cn->child) {
+ if (!_enumerate(sub, cn->child, cb, baton))
+ goto_bad;
+ } else
+ if (!cb(sub, cn, baton))
+ goto_bad;
+ dm_free(sub);
+ cn = cn->sib;
+ }
+ return 1;
+bad:
+ dm_free(sub);
+ return 0;
+}
+
+struct dm_config_tree *dm_config_flatten(struct dm_config_tree *cft)
+{
+ struct dm_config_tree *res = dm_config_create(), *done = NULL, *current = NULL;
+
+ if (!res)
+ return_NULL;
+
+ while (done != cft) {
+ current = cft;
+ while (current->cascade != done)
+ current = current->cascade;
+ _enumerate("", current->root, _override_path, res);
+ done = current;
+ }
+
+ return res;
+}