summaryrefslogtreecommitdiff
path: root/libdaemon/client/config-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdaemon/client/config-util.c')
-rw-r--r--libdaemon/client/config-util.c132
1 files changed, 107 insertions, 25 deletions
diff --git a/libdaemon/client/config-util.c b/libdaemon/client/config-util.c
index 1c83134..3f27f31 100644
--- a/libdaemon/client/config-util.c
+++ b/libdaemon/client/config-util.c
@@ -9,17 +9,16 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
+#include "tools/tool.h"
-#include "dm-logging.h"
-#include "config-util.h"
-#include "libdevmapper.h"
+#include "daemon-io.h"
+#include "device_mapper/misc/dm-logging.h"
+
+#include <math.h> /* fabs() */
+#include <float.h> /* DBL_EPSILON */
int buffer_append_vf(struct buffer *buf, va_list ap)
{
@@ -37,7 +36,12 @@ int buffer_append_vf(struct buffer *buf, va_list ap)
goto fail;
}
keylen = strchr(next, '=') - next;
- if (strstr(next, "%d") || strstr(next, "%" PRId64)) {
+ if (strstr(next, "%d")) {
+ /* Use of plain %d is prohibited, use FMTd64 */
+ log_error(INTERNAL_ERROR "Do not use %%d and use correct 64bit form");
+ goto fail;
+ }
+ if (strstr(next, FMTd64)) {
value = va_arg(ap, int64_t);
if (dm_asprintf(&append, "%.*s= %" PRId64 "\n", keylen, next, value) < 0)
goto fail;
@@ -57,12 +61,12 @@ int buffer_append_vf(struct buffer *buf, va_list ap)
!buffer_append(buf, append))
goto fail;
- dm_free(append);
+ free(append);
}
return 1;
fail:
- dm_free(append);
+ free(append);
return 0;
}
@@ -133,9 +137,9 @@ int set_flag(struct dm_config_tree *cft, struct dm_config_node *parent,
return 1;
}
-static void chain_node(struct dm_config_node *cn,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib)
+void chain_node(struct dm_config_node *cn,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib)
{
cn->parent = parent;
cn->sib = NULL;
@@ -155,6 +159,21 @@ static void chain_node(struct dm_config_node *cn,
}
+struct dm_config_tree *config_tree_from_string_without_dup_node_check(const char *config_settings)
+{
+ struct dm_config_tree *cft;
+
+ if (!(cft = dm_config_create()))
+ return_NULL;
+
+ if (!dm_config_parse_without_dup_node_check(cft, config_settings, config_settings + strlen(config_settings))) {
+ dm_config_destroy(cft);
+ return_NULL;
+ }
+
+ return cft;
+}
+
struct dm_config_node *make_config_node(struct dm_config_tree *cft,
const char *key,
struct dm_config_node *parent,
@@ -207,6 +226,10 @@ struct dm_config_node *make_int_node(struct dm_config_tree *cft,
return cn;
}
+/*
+ * FIXME: return 1 even if VA list is empty and return the
+ * dm_config_node* result as output parameter
+ */
struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
struct dm_config_node *parent,
struct dm_config_node *pre_sib,
@@ -215,7 +238,8 @@ struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
const char *next;
struct dm_config_node *first = NULL;
struct dm_config_node *cn;
- const char *fmt, *key;
+ const char *fmt;
+ char *key;
while ((next = va_arg(ap, char *))) {
cn = NULL;
@@ -223,14 +247,18 @@ struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
if (!fmt) {
log_error(INTERNAL_ERROR "Bad format string '%s'", fmt);
- return_NULL;
+ return NULL;
}
- fmt += 2;
- key = dm_pool_strdup(cft->mem, next);
- *strchr(key, '=') = 0;
+ if (!(key = dm_pool_strdup(cft->mem, next))) {
+ log_error("Failed to duplicate node key.");
+ return NULL;
+ }
+
+ key[fmt - next] = '\0';
+ fmt += 2;
- if (!strcmp(fmt, "%d") || !strcmp(fmt, "%" PRId64)) {
+ if (!strcmp(fmt, FMTd64)) {
int64_t value = va_arg(ap, int64_t);
if (!(cn = make_int_node(cft, key, value, parent, pre_sib)))
return 0;
@@ -247,7 +275,7 @@ struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
chain_node(cn, parent, pre_sib);
} else {
log_error(INTERNAL_ERROR "Bad format string '%s'", fmt);
- return_NULL;
+ return NULL;
}
if (!first)
first = cn;
@@ -273,6 +301,60 @@ struct dm_config_node *config_make_nodes(struct dm_config_tree *cft,
return res;
}
+/* Test if the doubles are close enough to be considered equal */
+static int _close_enough(double d1, double d2)
+{
+ return fabs(d1 - d2) < DBL_EPSILON;
+}
+
+int compare_value(struct dm_config_value *a, struct dm_config_value *b)
+{
+ int r = 0;
+
+ if (a->type > b->type)
+ return 1;
+ if (a->type < b->type)
+ return -1;
+
+ switch (a->type) {
+ case DM_CFG_STRING: r = strcmp(a->v.str, b->v.str); break;
+ case DM_CFG_FLOAT: r = _close_enough(a->v.f, b->v.f) ? 0 : (a->v.f > b->v.f) ? 1 : -1; break;
+ case DM_CFG_INT: r = (a->v.i == b->v.i) ? 0 : (a->v.i > b->v.i) ? 1 : -1; break;
+ case DM_CFG_EMPTY_ARRAY: return 0;
+ }
+
+ if (r == 0 && a->next && b->next)
+ r = compare_value(a->next, b->next);
+ return r;
+}
+
+int compare_config(struct dm_config_node *a, struct dm_config_node *b)
+{
+ int result = 0;
+ if (a->v && b->v)
+ result = compare_value(a->v, b->v);
+ if (a->v && !b->v)
+ result = 1;
+ if (!a->v && b->v)
+ result = -1;
+ if (a->child && b->child)
+ result = compare_config(a->child, b->child);
+
+ if (result) {
+ // DEBUGLOG("config inequality at %s / %s", a->key, b->key);
+ return result;
+ }
+
+ if (a->sib && b->sib)
+ result = compare_config(a->sib, b->sib);
+ if (a->sib && !b->sib)
+ result = 1;
+ if (!a->sib && b->sib)
+ result = -1;
+
+ return result;
+}
+
int buffer_realloc(struct buffer *buf, int needed)
{
char *new;
@@ -285,7 +367,7 @@ int buffer_realloc(struct buffer *buf, int needed)
if (new)
buf->mem = new;
else { /* utter failure */
- dm_free(buf->mem);
+ free(buf->mem);
buf->mem = 0;
buf->allocated = buf->used = 0;
return 0;
@@ -297,9 +379,9 @@ int buffer_append(struct buffer *buf, const char *string)
{
int len = strlen(string);
- if ((buf->allocated - buf->used <= len) &&
+ if ((!buf->mem || (buf->allocated - buf->used <= len)) &&
!buffer_realloc(buf, len + 1))
- return 0;
+ return 0;
strcpy(buf->mem + buf->used, string);
buf->used += len;
@@ -318,7 +400,7 @@ int buffer_line(const char *line, void *baton)
void buffer_destroy(struct buffer *buf)
{
- dm_free(buf->mem);
+ free(buf->mem);
buffer_init(buf);
}