diff options
Diffstat (limited to 'libdaemon/client/config-util.c')
-rw-r--r-- | libdaemon/client/config-util.c | 132 |
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); } |