From c981a16579bd4cf220cc6ef5f59c9062034ed569 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Thu, 21 Nov 2013 13:55:03 -0600 Subject: [PATCH] Function to prune all non-final nodes from a configuration node. --- src/conf.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++- src/conf.h | 2 +- 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/conf.c b/src/conf.c index 61fd294886..9f3deb4a5a 100644 --- a/src/conf.c +++ b/src/conf.c @@ -770,8 +770,41 @@ char *ConfLoadCompleteIncludePath(char *file) return path; } +/** + * \brief Prune a configuration node. + * + * Pruning a configuration is similar to freeing, but only fields that + * may be overridden are, leaving final type parameters. Additional + * the value of the provided node is also free'd, but the node itself + * is left. + * + * \param node The configuration node to prune. + */ +void +ConfNodePrune(ConfNode *node) +{ + ConfNode *item, *it; + + for (item = TAILQ_FIRST(&node->head); item != NULL; item = it) { + it = TAILQ_NEXT(item, next); + if (!item->final) { + ConfNodePrune(item); + if (TAILQ_EMPTY(&item->head)) { + TAILQ_REMOVE(&node->head, item, next); + if (item->name != NULL) + SCFree(item->name); + if (item->val != NULL) + SCFree(item->val); + SCFree(item); + } + } + } - + if (node->val != NULL) { + SCFree(node->val); + node->val = NULL; + } +} #ifdef UNITTESTS @@ -1283,6 +1316,54 @@ end: return ret; } +static int +ConfNodePruneTest(void) +{ + int ret = 0; + ConfNode *node; + + ConfCreateContextBackup(); + ConfInit(); + + /* Test that final nodes exist after a prune. */ + if (ConfSet("node.notfinal", "notfinal") != 1) + goto end; + if (ConfSetFinal("node.final", "final") != 1) + goto end; + if (ConfGetNode("node.notfinal") == NULL) + goto end; + if (ConfGetNode("node.final") == NULL) + goto end; + if ((node = ConfGetNode("node")) == NULL) + goto end; + ConfNodePrune(node); + if (ConfGetNode("node.notfinal") != NULL) + goto end; + if (ConfGetNode("node.final") == NULL) + goto end; + + /* Test that everything under a final node exists after a prune. */ + if (ConfSet("node.final.one", "one") != 1) + goto end; + if (ConfSet("node.final.two", "two") != 1) + goto end; + ConfNodePrune(node); + if (ConfNodeLookupChild(node, "final") == NULL) + goto end; + if (ConfGetNode("node.final.one") == NULL) + goto end; + if (ConfGetNode("node.final.two") == NULL) + goto end; + + ret = 1; + +end: + ConfDeInit(); + ConfRestoreContextBackup(); + + return ret; +} + void ConfRegisterTests(void) { @@ -1300,6 +1381,7 @@ ConfRegisterTests(void) UtRegisterTest("ConfGetChildValueIntWithDefaultTest", ConfGetChildValueIntWithDefaultTest, 1); UtRegisterTest("ConfGetChildValueBoolWithDefaultTest", ConfGetChildValueBoolWithDefaultTest, 1); UtRegisterTest("ConfGetNodeOrCreateTest", ConfGetNodeOrCreateTest, 1); + UtRegisterTest("ConfNodePruneTest", ConfNodePruneTest, 1); } #endif /* UNITTESTS */ diff --git a/src/conf.h b/src/conf.h index 86caeaa8f4..c819eb0493 100644 --- a/src/conf.h +++ b/src/conf.h @@ -77,7 +77,7 @@ void ConfRegisterTests(); int ConfNodeChildValueIsTrue(ConfNode *node, const char *key); int ConfValIsTrue(const char *val); int ConfValIsFalse(const char *val); - +void ConfNodePrune(ConfNode *node); ConfNode *ConfNodeLookupKeyValue(ConfNode *base, const char *key, const char *value); int ConfGetChildValue(ConfNode *base, char *name, char **vptr);