static void reset_notify_element(const struct dm_table *kw, struct dm_value_table *st, int index, uint32_t mask) { const struct dm_element *elem; if (!kw->table) return; elem = &kw->table[index]; switch(elem->type) { case T_TOKEN: if (DM_TABLE(st->values[index])) reset_notify_table(elem->u.t.table, DM_TABLE(st->values[index]), mask); break; case T_OBJECT: reset_notify_object(elem, DM_INSTANCE(st->values[index]), mask); break; default: break; } st->values[index].notify &= mask; DM_parity_update(st->values[index]); }
DM_RESULT set_notify_single_slot_element(const struct dm_element *elem, DM_VALUE *value, int slot, uint32_t ntfy) { uint32_t mask = ~(0x0003 << (slot * 2)); uint32_t notify; notify = (value->notify & mask) | ((ntfy & 0x0003) << (slot * 2)); if (slot == 0) { if (!notify_is_valid(elem, notify & 0x0003)) return DM_INVALID_VALUE; value->notify = notify; if (notify_default(elem) != (value->notify & 0x0003)) value->flags |= DV_NOTIFY; else value->flags &= ~DV_NOTIFY; } else value->notify = notify; DM_parity_update(*value); return DM_OK; }
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; }
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( ¬ify_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); } }