17 #include <sys/types.h> 19 #include <libxml/tree.h> 20 #include <libxml/valid.h> 43 const char *attr_n,
const char *attr_v)
45 xmlNode *child = NULL;
46 const char *parent_name =
"<null>";
48 CRM_CHECK((attr_v == NULL) || (attr_n != NULL),
return NULL);
52 while ((child != NULL) && (child->type != XML_ELEMENT_NODE)) {
56 parent_name = (
const char *)
parent->name;
60 const char *value = NULL;
62 if ((node_name != NULL) && !pcmk__xe_is(child, node_name)) {
73 if ((attr_v == NULL) && (value != NULL)) {
77 if ((attr_v != NULL) && (pcmk__str_eq(value, attr_v,
pcmk__str_none))) {
83 if (node_name == NULL) {
87 crm_trace(
"XML child node <%s %s=%s> not found in %s",
88 node_name, attr_n, attr_v, parent_name);
90 crm_trace(
"XML child node <%s> not found in %s",
91 node_name, parent_name);
108 for (xmlNode *next = (xml == NULL)? NULL : xml->next;
109 next != NULL; next = next->next) {
110 if ((next->type == XML_ELEMENT_NODE)
111 && ((element_name == NULL) || pcmk__xe_is(next, element_name))) {
135 const char *value = NULL;
176 const char *old_value = NULL;
188 if (old_value != NULL) {
189 const char *n =
name;
190 const char *v = value;
193 for (; (*n == *v) && (*n !=
'\0'); n++, v++);
198 && ((*v ==
'+') || (*v ==
'='))) {
205 if (old_value != value) {
209 crm_trace(
"Using 0 before incrementing %s because '%s' " 210 "is not a score",
name, old_value);
221 crm_trace(
"Not incrementing %s because '%s' does not have " 222 "a valid increment",
name, value);
232 if (old_value != value) {
256 for (xmlAttr *attr = pcmk__xe_first_attr(src); attr != NULL;
259 const char *
name = (
const char *) attr->name;
260 const char *value = pcmk__xml_attr_value(attr);
291 compare_xml_attr(gconstpointer a, gconstpointer b)
293 const xmlAttr *attr_a = a;
294 const xmlAttr *attr_b = b;
314 GSList *attr_list = NULL;
316 for (xmlAttr *iter = pcmk__xe_first_attr(xml); iter != NULL;
318 attr_list = g_slist_prepend(attr_list, iter);
320 attr_list = g_slist_sort(attr_list, compare_xml_attr);
322 for (GSList *iter = attr_list; iter != NULL; iter = iter->next) {
323 xmlNode *attr = iter->data;
326 xmlAddChild(xml, attr);
328 g_slist_free(attr_list);
363 const char *
name = user_data;
380 bool (*match)(xmlAttrPtr,
void *),
383 xmlAttrPtr next = NULL;
385 for (xmlAttrPtr a = pcmk__xe_first_attr(element); a != NULL; a = next) {
387 if ((match == NULL) || match(a, user_data)) {
409 xmlNode *node = NULL;
419 xmlDocSetRootElement(doc, node);
446 const char *content = NULL;
454 || (node->children->type == XML_TEXT_NODE),
457 if (strchr(format,
'%') == NULL) {
464 va_start(ap, format);
468 content = va_arg(ap,
const char *);
477 xmlNodeSetContent(node, (
pcmkXmlStr) content);
506 va_start(ap, format);
529 const char *
result = NULL;
532 pcmk__s(now_s,
"Could not determine current time"));
573 const char *update_name = NULL;
574 const char *update_id_attr = NULL;
575 const char *update_id_val = NULL;
576 char *trace_s = NULL;
583 if (update->type == XML_COMMENT_NODE) {
588 update_name = (
const char *) update->name;
590 CRM_CHECK(update_name != NULL,
goto done);
593 update_id_val = pcmk__xe_id(update);
594 if (update_id_val != NULL) {
599 if (update_id_val != NULL) {
606 if (update_id_attr != NULL) {
608 update_name, update_id_attr,
626 crm_trace(
"Added %s", pcmk__s(trace_s, update_name));
630 crm_trace(
"Found node %s to update", pcmk__s(trace_s, update_name));
637 for (xmlNode *child = pcmk__xml_first_child(update); child != NULL;
638 child = pcmk__xml_next(child)) {
640 crm_trace(
"Updating child of %s", pcmk__s(trace_s, update_name));
644 crm_trace(
"Finished with %s", pcmk__s(trace_s, update_name));
669 delete_xe_if_matching(xmlNode *xml,
void *user_data)
671 xmlNode *search = user_data;
673 if (!pcmk__xe_is(search, (
const char *) xml->name)) {
678 for (
const xmlAttr *attr = pcmk__xe_first_attr(search); attr != NULL;
681 const char *search_val = pcmk__xml_attr_value(attr);
720 CRM_CHECK((xml != NULL) && (search != NULL),
return EINVAL);
747 replace_node(xmlNode *old, xmlNode *
new)
751 old = xmlReplaceNode(old,
new);
785 replace_xe_if_matching(xmlNode *xml,
void *user_data)
787 xmlNode *replace = user_data;
788 const char *xml_id = NULL;
789 const char *replace_id = NULL;
791 xml_id = pcmk__xe_id(xml);
792 replace_id = pcmk__xe_id(replace);
794 if (!pcmk__xe_is(replace, (
const char *) xml->name)) {
799 if ((replace_id != NULL)
808 replace_node(xml, replace);
840 CRM_CHECK((xml != NULL) && (replace != NULL),
return EINVAL);
883 update_xe_if_matching(xmlNode *xml,
void *user_data)
885 struct update_data *
data = user_data;
886 xmlNode *update =
data->update;
888 if (!pcmk__xe_is(update, (
const char *) xml->name)) {
893 if (!pcmk__str_eq(pcmk__xe_id(xml), pcmk__xe_id(update),
pcmk__str_none)) {
900 update_xe(NULL, xml, update,
data->flags);
935 struct update_data
data = {
940 CRM_CHECK((xml != NULL) && (update != NULL),
return EINVAL);
955 const char *
name, *value;
957 name = va_arg(pairs,
const char *);
962 value = va_arg(pairs,
const char *);
973 va_start(pairs, node);
980 int (*handler)(xmlNode *xml,
void *userdata),
983 xmlNode *children = (xml? xml->children : NULL);
987 for (xmlNode *node = children; node != NULL; node = node->next) {
988 if ((node->type == XML_ELEMENT_NODE)
989 && ((child_element_name == NULL)
990 || pcmk__xe_is(node, child_element_name))) {
991 int rc = handler(node, userdata);
1019 xmlAttr *attr = NULL;
1024 if (value == NULL) {
1031 if (old == NULL || value == NULL || strcmp(old, value) != 0) {
1037 crm_trace(
"Cannot add %s=%s to %s",
name, value, node->name);
1052 CRM_CHECK(attr && attr->children && attr->children->content,
return NULL);
1053 return (
char *)attr->children->content;
1072 char *number = pcmk__itoa(value);
1103 #define LLSTRSIZE 21 1145 const struct timeval *value)
1147 const char *added = NULL;
1149 if (xml && name_sec && value) {
1150 added =
crm_xml_add_ll(xml, name_sec, (
long long) value->tv_sec);
1151 if (added && name_usec) {
1170 xmlAttr *attr = NULL;
1177 }
else if (
name == NULL) {
1183 if (!attr || !attr->children) {
1186 return (
const char *) attr->children->content;
1203 const char *value = NULL;
1214 "because '%s' is not a valid integer: %s",
1216 }
else if ((value_ll < INT_MIN) || (value_ll > INT_MAX)) {
1217 crm_warn(
"Using default for %s because '%s' is out of range",
1220 *dest = (int) value_ll;
1244 uint32_t default_value)
1246 const char *value = NULL;
1247 long long value_ll = 0LL;
1251 *dest = default_value;
1261 if (value == NULL) {
1266 if ((value_ll < 0) || (value_ll > UINT32_MAX)) {
1267 value_ll = default_value;
1274 *dest = (uint32_t) value_ll;
1293 const char *value = NULL;
1297 if (value != NULL) {
1304 "because '%s' is not a valid integer: %s",
1324 const char *value = NULL;
1334 "because '%s' is not valid milliseconds: %s",
1338 if ((value_ll < 0) || (value_ll > G_MAXUINT)) {
1339 crm_warn(
"Using default for %s because '%s' is out of range",
1343 *dest = (guint) value_ll;
1361 long long value_ll = 0;
1370 *dest = (time_t) value_ll;
1389 const char *name_usec,
struct timeval *dest)
1391 long long value_i = 0;
1393 CRM_CHECK(dest != NULL,
return -EINVAL);
1412 dest->tv_sec = (time_t) value_i;
1418 dest->tv_usec = (suseconds_t) value_i;
1438 const char *value = NULL;
1440 if ((t == NULL) || (*t != NULL) || (xml == NULL) || (attr == NULL)) {
1445 if (value != NULL) {
1503 const char *xml_value = NULL;
1508 }
else if (
name == NULL || value == NULL) {
1514 if (xml_value == NULL) {
1570 va_start(ap, format);
1571 len = vasprintf(&
id, format, ap);
1583 xmlNode *child = NULL;
1584 GSList *nvpairs = NULL;
int crm_element_value_ll(const xmlNode *data, const char *name, long long *dest)
Retrieve the long long integer value of an XML attribute.
int pcmk__xe_delete_match(xmlNode *xml, xmlNode *search)
Deprecated Pacemaker XML element API.
#define CRM_CHECK(expr, failure_action)
xmlNode * pcmk__xe_resolve_idref(xmlNode *xml, xmlNode *search)
void pcmk__xe_set_props(xmlNodePtr node,...)
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
void pcmk__xe_remove_attr(xmlNode *element, const char *name)
G_GNUC_INTERNAL bool pcmk__xml_reset_node_flags(xmlNode *xml, void *user_data)
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
#define pcmk__if_tracing(if_action, else_action)
void pcmk_free_nvpairs(GSList *nvpairs)
Free a list of name/value pairs.
void pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value)
int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
struct crm_time_s crm_time_t
int pcmk__xe_get_datetime(const xmlNode *xml, const char *attr, crm_time_t **t)
void pcmk__xe_set_propv(xmlNodePtr node, va_list pairs)
G_GNUC_INTERNAL void pcmk__mark_xml_attr_dirty(xmlAttr *a)
GSList * pcmk_xml_attrs2nvpairs(const xmlNode *xml)
void pcmk__xe_set_id(xmlNode *node, const char *format,...)
int pcmk__xe_copy_attrs(xmlNode *target, const xmlNode *src, uint32_t flags)
xmlNode * sorted_xml(xmlNode *input, xmlNode *parent, gboolean recursive)
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
int pcmk__xe_get_score(const xmlNode *xml, const char *name, int *score, int default_score)
const char * crm_xml_add_timeval(xmlNode *xml, const char *name_sec, const char *name_usec, const struct timeval *value)
Create XML attributes for seconds and microseconds.
#define PCMK_XA_CIB_LAST_WRITTEN
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
#define CRM_LOG_ASSERT(expr)
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
void pcmk__xe_sort_attrs(xmlNode *xml)
Deprecated Pacemaker name-value pair API.
void pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
Deprecated Pacemaker XML API.
void pcmk__xe_set_content(xmlNode *node, const char *format,...)
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
G_GNUC_INTERNAL xmlDoc * pcmk__xml_new_doc(void)
bool xml_tracking_changes(xmlNode *xml)
void pcmk__xml_free(xmlNode *xml)
const char * pcmk__xe_add_last_written(xmlNode *xe)
#define PCMK__PARSE_INT_DEFAULT
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
#define crm_warn(fmt, args...)
G_GNUC_INTERNAL void pcmk__xc_update(xmlNode *parent, xmlNode *target, xmlNode *update)
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
void pcmk__xe_remove_matching_attrs(xmlNode *element, bool(*match)(xmlAttrPtr, void *), void *user_data)
void crm_xml_sanitize_id(char *id)
G_GNUC_INTERNAL void pcmk__xml_new_private_data(xmlNode *xml)
G_GNUC_INTERNAL void pcmk__xml_free_node(xmlNode *xml)
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
#define crm_trace(fmt, args...)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Wrappers for and extensions to libxml2.
int pcmk__xe_set_score(xmlNode *target, const char *name, const char *value)
xmlNode * pcmk__xe_next(const xmlNode *xml, const char *element_name)
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
int pcmk__add_scores(int score1, int score2)
#define pcmk__str_copy(str)
GSList * pcmk_sort_nvpairs(GSList *list)
Function and executable result codes.
int pcmk__xe_replace_match(xmlNode *xml, xmlNode *replace)
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
const xmlChar * pcmkXmlStr
Functionality for manipulating name/value pairs.
#define pcmk__assert(expr)
const char * crm_xml_add_ll(xmlNode *xml, const char *name, long long value)
Create an XML attribute with specified name and long long int value.
bool pcmk__xe_remove_attr_cb(xmlNode *xml, void *user_data)
pcmk__action_result_t result
#define crm_err(fmt, args...)
int pcmk__xe_update_match(xmlNode *xml, xmlNode *update, uint32_t flags)
char * pcmk__epoch2str(const time_t *source, uint32_t flags)
crm_time_t * crm_time_new(const char *string)
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
void pcmk__apply_acl(xmlNode *xml)
#define pcmk__mem_assert(ptr)
int pcmk__strcmp(const char *s1, const char *s2, uint32_t flags)
int pcmk_parse_score(const char *score_s, int *score, int default_score)
Parse an integer score from a string.
void crm_xml_set_id(xmlNode *xml, const char *format,...)
bool pcmk__xml_tree_foreach(xmlNode *xml, bool(*fn)(xmlNode *, void *), void *user_data)
int crm_element_value_timeval(const xmlNode *xml, const char *name_sec, const char *name_usec, struct timeval *dest)
Retrieve the value of XML second/microsecond attributes as time.
const char * crm_xml_add_ms(xmlNode *node, const char *name, guint ms)
Create an XML attribute with specified name and unsigned value.
int crm_str_to_boolean(const char *s, int *ret)
#define crm_log_xml_trace(xml, text)
void pcmk__xml_sanitize_id(char *id)
G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
int pcmk__xe_get_flags(const xmlNode *xml, const char *name, uint32_t *dest, uint32_t default_value)
int pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name, int(*handler)(xmlNode *xml, void *userdata), void *userdata)
int crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
Retrieve the seconds-since-epoch value of an XML attribute.
void xml_calculate_changes(xmlNode *old_xml, xmlNode *new_xml)
G_GNUC_INTERNAL int pcmk__xa_remove(xmlAttr *attr, bool force)
Don't overwrite existing values.
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1