Esempio n. 1
0
DM_RESULT
dm_string2value(const struct dm_element *elem, const char *str, uint8_t set_update, DM_VALUE *value)
{
	uint8_t		updated = 0;
	DM_RESULT	res = DM_OK;

	if (!elem || !str || !value)
		return DM_VALUE_NOT_FOUND;

	switch (elem->type) {
		case T_STR:
			updated = DM_STRING(*value) ? strcmp(DM_STRING(*value), str) != 0 : 1;

			res = dm_set_string_value(value, str);

			break;

		case T_BINARY:
			/* FIXME: this is not entirely correct */
			res = dm_set_binary_data(value, strlen(str), (const uint8_t *)str);
			break;

		case T_BASE64: {
			unsigned int len;
			binary_t *n;

			/* this is going to waste some bytes.... */
			len = ((strlen(str) + 4) * 3) / 4;

			n = malloc(sizeof(binary_t) + len);
			if (!n)
				return DM_OOM;

			debug(": base64 string: %zd, buffer: %d", strlen(str), len);
			n->len = dm_from64((const unsigned char *)str, n->data);
			debug(": base64 result: %d", n->len);
			updated = dm_binarycmp(DM_BINARY(*value), n) != 0;
			res = dm_set_binary_value(value, n);
			free(n);

			break;
		}

		case T_SELECTOR: {
			dm_selector sb;

			if (*str) {
				if (!dm_name2sel(str, &sb)) {
					res = DM_INVALID_VALUE;
					break;
				}
			} else
				memset(&sb, 0, sizeof(dm_selector));

			updated = DM_SELECTOR(*value) ?
					dm_selcmp(*DM_SELECTOR(*value), sb, DM_SELECTOR_LEN) != 0 : 1;

			res = dm_set_selector_value(value, sb);

			break;
		}
		case T_BOOL:
			if (!strcasecmp("true", str)) {
				updated = DM_BOOL(*value) != 1;
				set_DM_BOOL(*value, 1);
			} else if (!strcasecmp("false", str)) {
				updated = DM_BOOL(*value);
				set_DM_BOOL(*value, 0);
			} else
				res = DM_INVALID_VALUE;

			break;

		case T_ENUM: {
			int i;

			if ((i = dm_enum2int(&elem->u.e, str)) == -1)
				res = DM_INVALID_VALUE;
			else {
				updated = DM_ENUM(*value) != i;
				set_DM_ENUM(*value, i);
			}

			break;
		}
		case T_INT: {
			int32_t		i;
			char		*endl;

			i = strtol(str, &endl, 10);
			if (*endl)
				res = DM_INVALID_VALUE;
			else {
				updated = DM_INT(*value) != i;
				set_DM_INT(*value, i);
			}

			break;
		}
		case T_UINT: {
			uint32_t	i;
			char		*endl;

			i = strtoul(str, &endl, 10);
			if (*endl)
				res = DM_INVALID_VALUE;
			else {
				updated = DM_UINT(*value) != i;
				set_DM_UINT(*value, i);
			}

			break;
		}
		case T_INT64: {
			int64_t		i;
			char		*endl;

			i = strtoll(str, &endl, 10);
			if (*endl)
				res = DM_INVALID_VALUE;
			else {
				updated = DM_INT64(*value) != i;
				set_DM_INT64(*value, i);
			}

			break;
		}
		case T_UINT64: {
			uint64_t	i;
			char		*endl;

			i = strtoull(str, &endl, 10);
			if (*endl)
				res = DM_INVALID_VALUE;
			else {
				updated = DM_UINT64(*value) != i;
				set_DM_UINT64(*value, i);
			}

			break;
		}
		case T_IPADDR4: {
			struct in_addr addr;

			if (!inet_pton(AF_INET, str, &addr))
				res = DM_INVALID_VALUE;
			else {
				updated = memcmp(DM_IP4_REF(*value), &addr, sizeof(struct in_addr));
				set_DM_IP4(*value, addr);
			}

			break;
		}
		case T_IPADDR6: {
			struct in6_addr addr;

			if (!inet_pton(AF_INET6, str, &addr))
				res = DM_INVALID_VALUE;
			else {
				updated = memcmp(DM_IP6_REF(*value), &addr, sizeof(struct in6_addr));
				set_DM_IP6(*value, addr);
			}

			break;
		}
		case T_DATE: {
			time_t	val;
			char	*endl;

			val = (time_t)strtoul(str, &endl, 10);
			if (*endl)
				res = DM_INVALID_TYPE;
			else {
				updated = DM_TIME(*value) != val;
				set_DM_TIME(*value, val);
			}

			break;
		}
		case T_TICKS: {
			ticks_t	val;
			char	*endl;

			if (str2ticks(str, &val) < 0) {
				val = (ticks_t)strtoul(str, &endl, 10);
				if (*endl) {
					res = DM_INVALID_TYPE;
					break;
				}
			}

			updated = DM_TICKS(*value) != val;
			set_DM_TICKS(*value, val);
			break;
		}
		default:	/* unsupported type including T_COUNTER */
			res = DM_INVALID_TYPE;
	}

	if (res == DM_OK && set_update && updated)
		value->flags |= DV_UPDATED;

	DM_parity_update(*value);
	return res;
}
Esempio n. 2
0
static void XMLCALL
startElement(void *userData, const char *name, const char **atts)
{
	const struct dm_element *kw = NULL;
	DM_VALUE *val = NULL;

	struct XMLstate **state = userData;

	const char *base = (*state)->base;
	int valid = ((*state)->flags & XML_VALID) == XML_VALID;
	int is_root = ((*state)->flags & XML_ROOT) == XML_ROOT;
	const struct dm_element *element = (*state)->element;
	DM_VALUE *value = (*state)->value;

	int xid = 0;
	int ntfy = 0;
	dm_id id;

	for (int i = 0; atts[i]; i += 2) {
		if (strcasecmp("instance", atts[i]) == 0) {
			xml_debug("%s: instance: %s\n", name, atts[i + 1]);
			xid = atoi(atts[i + 1]);
			break;
		}
		else if (strcasecmp("notify", atts[i]) == 0) {
			xml_debug("%s: notify: %s\n", name, atts[i + 1]);
			ntfy = dm_enum2int( &notify_attr, atts[i + 1]);
		}
		else if (strcasecmp("encoding", atts[i]) == 0) {
			xml_debug("%s: encoding: %s\n", name, atts[i + 1]);
			if (strcasecmp(atts[i+1], "escaped") == 0)
				(*state)->flags |= XML_ESCAPED;
		}
		else if (strcasecmp("version", atts[i]) == 0) {
			xml_debug("%s: config version: %s\n", name, atts[i + 1]);
			dm_set_cfg_version(atoi(atts[i + 1]));
		}
	}

	(*state)++;

	if (is_root) {
		if (flags & DS_VERSIONCHECK &&
		    dm_get_cfg_version() != CFG_VERSION) {
			(*state)->flags |= XML_UPGRADE;

			lua_pushinteger(lua_environment, CFG_VERSION);
			lua_pushinteger(lua_environment, dm_get_cfg_version());
			if (fp_Lua_function("fncPreVersionCheck", 2))
				debug("(): Error during Lua function execution");
		}
	} else {
		memset(*state, 0, sizeof(struct XMLstate));

		if (xid != 0)
			asprintf(&(*state)->base, "%s.%s.%d", base, name, xid);
		else
			asprintf(&(*state)->base, "%s.%s", base, name);

		if (valid) {
			const struct dm_table *table = element->u.t.table;

			id = dm_get_element_id_by_name(name, strlen(name), table);
			if (id != DM_ERR) {
				kw = &(table->table[id - 1]);
				val = dm_get_value_ref_by_id(DM_TABLE(*value), id);
				(*state)->flags |= XML_VALID;
			} else {
				printf("Element '%s' not found in table '%s'\n", name, element->key);
				valid = 0;
			}
		}

		if (!valid || !((*state)->flags & XML_VALID)) {
			debug("enter invalid: %s\n", (*state)->base);
			return;
		}

		xml_debug("enter: %s = %p, (%p, %p)\n", name, *state, kw, val);

		(*state)->element = kw;
		if (kw->type == T_OBJECT) {
			struct dm_instance *inst = DM_INSTANCE(*val);
			struct dm_instance_node *node = NULL;

			/** FIXME: this should be easier */
			if (xid > 0)
				node = dm_get_instance_node_by_id(inst, xid);
			if (!node) {
				dm_selector basesel;

				dm_selcpy(basesel, DM_TABLE(*value)->id);
				dm_selcat(basesel, id);

				node = dm_add_instance(kw, inst, basesel, xid);
				dm_assert(node);

				if (flags & DS_USERCONFIG) {
					val->flags |= DV_UPDATED;
					DM_parity_update(*val);
					node->table.flags |= DV_UPDATED;
					DM_parity_update(node->table);
				}
			}

			val = &node->table;

			(*state)->inst = inst;
			(*state)->node = node;

		} else if (kw->type == T_TOKEN) {
			if (DM_TABLE(*val) == NULL) {
				set_DM_TABLE(*val, dm_alloc_table(kw->u.t.table, DM_TABLE(*value)->id, id));

				if (flags & DS_USERCONFIG)
					val->flags |= DV_UPDATED;
				xml_debug("adding table for token \"%s\" with %d elements: %p\n", name,
					  kw->u.t.table->size, DM_TABLE(*val));
				DM_parity_update(*val);
			}
		}
		(*state)->value = val;
		if (ntfy >= 0)
			set_notify_single_slot_element(kw, (*state)->value, 0, ntfy);
	}
}