pacemaker  2.0.4-2deceaa
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
nvpair.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2020 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
12 #include <stdio.h>
13 #include <sys/types.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <glib.h>
17 #include <libxml/tree.h>
18 
19 #include <crm/crm.h>
20 #include <crm/msg_xml.h>
21 #include <crm/common/xml.h>
23 #include "crmcommon_private.h"
24 
25 /*
26  * This file isolates handling of three types of name/value pairs:
27  *
28  * - pcmk_nvpair_t data type
29  * - XML attributes (<TAG ... NAME=VALUE ...>)
30  * - XML nvpair elements (<nvpair id=ID name=NAME value=VALUE>)
31  */
32 
33 // pcmk_nvpair_t handling
34 
46 static pcmk_nvpair_t *
47 pcmk__new_nvpair(const char *name, const char *value)
48 {
49  pcmk_nvpair_t *nvpair = NULL;
50 
51  CRM_ASSERT(name);
52 
53  nvpair = calloc(1, sizeof(pcmk_nvpair_t));
54  CRM_ASSERT(nvpair);
55 
56  nvpair->name = strdup(name);
57  nvpair->value = value? strdup(value) : NULL;
58  return nvpair;
59 }
60 
67 static void
68 pcmk__free_nvpair(gpointer data)
69 {
70  if (data) {
71  pcmk_nvpair_t *nvpair = data;
72 
73  free(nvpair->name);
74  free(nvpair->value);
75  free(nvpair);
76  }
77 }
78 
90 GSList *
91 pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
92 {
93  return g_slist_prepend(nvpairs, pcmk__new_nvpair(name, value));
94 }
95 
101 void
102 pcmk_free_nvpairs(GSList *nvpairs)
103 {
104  g_slist_free_full(nvpairs, pcmk__free_nvpair);
105 }
106 
116 static gint
117 pcmk__compare_nvpair(gconstpointer a, gconstpointer b)
118 {
119  int rc = 0;
120  const pcmk_nvpair_t *pair_a = a;
121  const pcmk_nvpair_t *pair_b = b;
122 
123  CRM_ASSERT(a != NULL);
124  CRM_ASSERT(pair_a->name != NULL);
125 
126  CRM_ASSERT(b != NULL);
127  CRM_ASSERT(pair_b->name != NULL);
128 
129  rc = strcmp(pair_a->name, pair_b->name);
130  if (rc < 0) {
131  return -1;
132  } else if (rc > 0) {
133  return 1;
134  }
135  return 0;
136 }
137 
145 GSList *
146 pcmk_sort_nvpairs(GSList *list)
147 {
148  return g_slist_sort(list, pcmk__compare_nvpair);
149 }
150 
160 GSList *
162 {
163  GSList *result = NULL;
164 
165  for (xmlAttrPtr iter = pcmk__first_xml_attr(xml); iter != NULL;
166  iter = iter->next) {
167 
168  result = pcmk_prepend_nvpair(result,
169  (const char *) iter->name,
170  (const char *) pcmk__xml_attr_value(iter));
171  }
172  return result;
173 }
174 
185 static void
186 pcmk__nvpair_add_xml_attr(gpointer data, gpointer user_data)
187 {
188  pcmk_nvpair_t *pair = data;
189  xmlNode *parent = user_data;
190 
191  crm_xml_add(parent, pair->name, pair->value);
192 }
193 
200 void
201 pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
202 {
203  g_slist_foreach(list, pcmk__nvpair_add_xml_attr, xml);
204 }
205 
206 // convenience function for name=value strings
207 
219 int
220 pcmk_scan_nvpair(const char *input, char **name, char **value)
221 {
222 #ifdef SSCANF_HAS_M
223  *name = NULL;
224  *value = NULL;
225  if (sscanf(input, "%m[^=]=%m[^\n]", name, value) <= 0) {
226  return -pcmk_err_bad_nvpair;
227  }
228 #else
229  char *sep = NULL;
230  *name = NULL;
231  *value = NULL;
232 
233  sep = strstr(optarg, "=");
234  if (sep == NULL) {
235  return -pcmk_err_bad_nvpair;
236  }
237 
238  *name = strndup(input, sep-input);
239 
240  if (*name == NULL) {
241  return -ENOMEM;
242  }
243 
244  /* If the last char in optarg is =, the user gave no
245  * value for the option. Leave it as NULL.
246  */
247  if (*(sep+1) != '\0') {
248  *value = strdup(sep+1);
249 
250  if (*value == NULL) {
251  return -ENOMEM;
252  }
253  }
254 #endif
255 
256  if (*name != NULL && *value != NULL) {
257  return 2;
258  } else if (*name != NULL || *value != NULL) {
259  return 1;
260  } else {
261  return -pcmk_err_bad_nvpair;
262  }
263 }
264 
280 char *
281 pcmk_format_nvpair(const char *name, const char *value, const char *units) {
282  return crm_strdup_printf("%s=\"%s%s\"", name, value, units ? units : "");
283 }
284 
296 char *
297 pcmk_format_named_time(const char *name, time_t epoch_time) {
298  const char *now_str = pcmk__epoch2str(&epoch_time);
299 
300  return crm_strdup_printf("%s=\"%s\"", name, now_str ? now_str : "");
301 }
302 
303 // XML attribute handling
304 
315 const char *
316 crm_xml_add(xmlNode *node, const char *name, const char *value)
317 {
318  bool dirty = FALSE;
319  xmlAttr *attr = NULL;
320 
321  CRM_CHECK(node != NULL, return NULL);
322  CRM_CHECK(name != NULL, return NULL);
323 
324  if (value == NULL) {
325  return NULL;
326  }
327 #if XML_PARANOIA_CHECKS
328  {
329  const char *old_value = NULL;
330 
331  old_value = crm_element_value(node, name);
332 
333  /* Could be re-setting the same value */
334  CRM_CHECK(old_value != value,
335  crm_err("Cannot reset %s with crm_xml_add(%s)", name, value);
336  return value);
337  }
338 #endif
339 
340  if (pcmk__tracking_xml_changes(node, FALSE)) {
341  const char *old = crm_element_value(node, name);
342 
343  if (old == NULL || value == NULL || strcmp(old, value) != 0) {
344  dirty = TRUE;
345  }
346  }
347 
348  if (dirty && (pcmk__check_acl(node, name, xpf_acl_create) == FALSE)) {
349  crm_trace("Cannot add %s=%s to %s", name, value, node->name);
350  return NULL;
351  }
352 
353  attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
354  if (dirty) {
356  }
357 
358  CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
359  return (char *)attr->children->content;
360 }
361 
372 const char *
373 crm_xml_replace(xmlNode *node, const char *name, const char *value)
374 {
375  bool dirty = FALSE;
376  xmlAttr *attr = NULL;
377  const char *old_value = NULL;
378 
379  CRM_CHECK(node != NULL, return NULL);
380  CRM_CHECK(name != NULL && name[0] != 0, return NULL);
381 
382  old_value = crm_element_value(node, name);
383 
384  /* Could be re-setting the same value */
385  CRM_CHECK(old_value != value, return value);
386 
387  if (pcmk__check_acl(node, name, xpf_acl_write) == FALSE) {
388  /* Create a fake object linked to doc->_private instead? */
389  crm_trace("Cannot replace %s=%s to %s", name, value, node->name);
390  return NULL;
391 
392  } else if (old_value && !value) {
393  xml_remove_prop(node, name);
394  return NULL;
395  }
396 
397  if (pcmk__tracking_xml_changes(node, FALSE)) {
398  if (!old_value || !value || !strcmp(old_value, value)) {
399  dirty = TRUE;
400  }
401  }
402 
403  attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
404  if (dirty) {
406  }
407  CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
408  return (char *) attr->children->content;
409 }
410 
423 const char *
424 crm_xml_add_int(xmlNode *node, const char *name, int value)
425 {
426  char *number = crm_itoa(value);
427  const char *added = crm_xml_add(node, name, number);
428 
429  free(number);
430  return added;
431 }
432 
445 const char *
446 crm_xml_add_ms(xmlNode *node, const char *name, guint ms)
447 {
448  char *number = crm_strdup_printf("%u", ms);
449  const char *added = crm_xml_add(node, name, number);
450 
451  free(number);
452  return added;
453 }
454 
455 // Maximum size of null-terminated string representation of 64-bit integer
456 // -9223372036854775808
457 #define LLSTRSIZE 21
458 
473 const char *
474 crm_xml_add_ll(xmlNode *xml, const char *name, long long value)
475 {
476  char s[LLSTRSIZE] = { '\0', };
477 
478  if (snprintf(s, LLSTRSIZE, "%lld", (long long) value) == LLSTRSIZE) {
479  return NULL;
480  }
481  return crm_xml_add(xml, name, s);
482 }
483 
497 const char *
498 crm_xml_add_timeval(xmlNode *xml, const char *name_sec, const char *name_usec,
499  const struct timeval *value)
500 {
501  const char *added = NULL;
502 
503  if (xml && name_sec && value) {
504  added = crm_xml_add_ll(xml, name_sec, (long long) value->tv_sec);
505  if (added && name_usec) {
506  // Any error is ignored (we successfully added seconds)
507  crm_xml_add_ll(xml, name_usec, (long long) value->tv_usec);
508  }
509  }
510  return added;
511 }
512 
521 const char *
522 crm_element_value(const xmlNode *data, const char *name)
523 {
524  xmlAttr *attr = NULL;
525 
526  if (data == NULL) {
527  crm_err("Couldn't find %s in NULL", name ? name : "<null>");
528  CRM_LOG_ASSERT(data != NULL);
529  return NULL;
530 
531  } else if (name == NULL) {
532  crm_err("Couldn't find NULL in %s", crm_element_name(data));
533  return NULL;
534  }
535 
536  /* The first argument to xmlHasProp() has always been const,
537  * but libxml2 <2.9.2 didn't declare that, so cast it
538  */
539  attr = xmlHasProp((xmlNode *) data, (pcmkXmlStr) name);
540  if (!attr || !attr->children) {
541  return NULL;
542  }
543  return (const char *) attr->children->content;
544 }
545 
557 int
558 crm_element_value_int(const xmlNode *data, const char *name, int *dest)
559 {
560  const char *value = NULL;
561 
562  CRM_CHECK(dest != NULL, return -1);
563  value = crm_element_value(data, name);
564  if (value) {
565  errno = 0;
566  *dest = crm_parse_int(value, NULL);
567  if (errno == 0) {
568  return 0;
569  }
570  }
571  return -1;
572 }
573 
585 int
586 crm_element_value_ll(const xmlNode *data, const char *name, long long *dest)
587 {
588  const char *value = NULL;
589 
590  CRM_CHECK(dest != NULL, return -1);
591  value = crm_element_value(data, name);
592  if (value) {
593  errno = 0;
594  *dest = crm_parse_ll(value, NULL);
595  if (errno == 0) {
596  return 0;
597  }
598  }
599  return -1;
600 }
601 
613 int
614 crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
615 {
616  const char *value = NULL;
617  long long value_ll;
618 
619  CRM_CHECK(dest != NULL, return -1);
620  *dest = 0;
621 
622  value = crm_element_value(data, name);
623  if (value == NULL) {
624  return pcmk_ok;
625  }
626 
627  errno = 0;
628  value_ll = crm_parse_ll(value, NULL);
629  if ((errno != 0) || (value_ll < 0) || (value_ll > G_MAXUINT)) {
630  return -1;
631  }
632 
633  *dest = (guint) value_ll;
634  return pcmk_ok;
635 }
636 
648 int
649 crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
650 {
651  long long value_ll = 0;
652 
653  if (crm_element_value_ll(xml, name, &value_ll) < 0) {
654  return -1;
655  }
656 
657  /* Unfortunately, we can't do any bounds checking, since time_t has neither
658  * standardized bounds nor constants defined for them.
659  */
660  *dest = (time_t) value_ll;
661  return pcmk_ok;
662 }
663 
677 int
678 crm_element_value_timeval(const xmlNode *xml, const char *name_sec,
679  const char *name_usec, struct timeval *dest)
680 {
681  long long value_i = 0;
682 
683  CRM_CHECK(dest != NULL, return -EINVAL);
684  dest->tv_sec = 0;
685  dest->tv_usec = 0;
686 
687  if (xml == NULL) {
688  return pcmk_ok;
689  }
690 
691  /* Unfortunately, we can't do any bounds checking, since there are no
692  * constants provided for the bounds of time_t and suseconds_t, and
693  * calculating them isn't worth the effort. If there are XML values
694  * beyond the native sizes, there will probably be worse problems anyway.
695  */
696 
697  // Parse seconds
698  errno = 0;
699  if (crm_element_value_ll(xml, name_sec, &value_i) < 0) {
700  return -errno;
701  }
702  dest->tv_sec = (time_t) value_i;
703 
704  // Parse microseconds
705  if (crm_element_value_ll(xml, name_usec, &value_i) < 0) {
706  return -errno;
707  }
708  dest->tv_usec = (suseconds_t) value_i;
709 
710  return pcmk_ok;
711 }
712 
724 char *
725 crm_element_value_copy(const xmlNode *data, const char *name)
726 {
727  char *value_copy = NULL;
728  const char *value = crm_element_value(data, name);
729 
730  if (value != NULL) {
731  value_copy = strdup(value);
732  }
733  return value_copy;
734 }
735 
749 void
750 hash2smartfield(gpointer key, gpointer value, gpointer user_data)
751 {
752  const char *name = key;
753  const char *s_value = value;
754 
755  xmlNode *xml_node = user_data;
756 
757  if (isdigit(name[0])) {
758  xmlNode *tmp = create_xml_node(xml_node, XML_TAG_PARAM);
759 
760  crm_xml_add(tmp, XML_NVPAIR_ATTR_NAME, name);
761  crm_xml_add(tmp, XML_NVPAIR_ATTR_VALUE, s_value);
762 
763  } else if (crm_element_value(xml_node, name) == NULL) {
764  crm_xml_add(xml_node, name, s_value);
765  crm_trace("dumped: %s=%s", name, s_value);
766 
767  } else {
768  crm_trace("duplicate: %s=%s", name, s_value);
769  }
770 }
771 
783 void
784 hash2field(gpointer key, gpointer value, gpointer user_data)
785 {
786  const char *name = key;
787  const char *s_value = value;
788 
789  xmlNode *xml_node = user_data;
790 
791  if (crm_element_value(xml_node, name) == NULL) {
792  crm_xml_add(xml_node, name, s_value);
793 
794  } else {
795  crm_trace("duplicate: %s=%s", name, s_value);
796  }
797 }
798 
811 void
812 hash2metafield(gpointer key, gpointer value, gpointer user_data)
813 {
814  char *crm_name = NULL;
815 
816  if (key == NULL || value == NULL) {
817  return;
818  }
819 
820  /* Filter out cluster-generated attributes that contain a '#' or ':'
821  * (like fail-count and last-failure).
822  */
823  for (crm_name = key; *crm_name; ++crm_name) {
824  if ((*crm_name == '#') || (*crm_name == ':')) {
825  return;
826  }
827  }
828 
829  crm_name = crm_meta_name(key);
830  hash2field(crm_name, value, user_data);
831  free(crm_name);
832 }
833 
834 // nvpair handling
835 
846 xmlNode *
847 crm_create_nvpair_xml(xmlNode *parent, const char *id, const char *name,
848  const char *value)
849 {
850  xmlNode *nvp;
851 
852  /* id can be NULL so we auto-generate one, and name can be NULL if this
853  * will be used to delete a name/value pair by ID, but both can't be NULL
854  */
855  CRM_CHECK(id || name, return NULL);
856 
857  nvp = create_xml_node(parent, XML_CIB_TAG_NVPAIR);
858  CRM_CHECK(nvp, return NULL);
859 
860  if (id) {
861  crm_xml_add(nvp, XML_ATTR_ID, id);
862  } else {
863  const char *parent_id = ID(parent);
864 
865  crm_xml_set_id(nvp, "%s-%s",
866  (parent_id? parent_id : XML_CIB_TAG_NVPAIR), name);
867  }
868  crm_xml_add(nvp, XML_NVPAIR_ATTR_NAME, name);
869  crm_xml_add(nvp, XML_NVPAIR_ATTR_VALUE, value);
870  return nvp;
871 }
872 
884 void
885 hash2nvpair(gpointer key, gpointer value, gpointer user_data)
886 {
887  const char *name = key;
888  const char *s_value = value;
889  xmlNode *xml_node = user_data;
890 
891  crm_create_nvpair_xml(xml_node, name, name, s_value);
892  crm_trace("dumped: name=%s value=%s", name, s_value);
893 }
894 
909 GHashTable *
910 xml2list(xmlNode *parent)
911 {
912  xmlNode *child = NULL;
913  xmlAttrPtr pIter = NULL;
914  xmlNode *nvpair_list = NULL;
915  GHashTable *nvpair_hash = crm_str_table_new();
916 
917  CRM_CHECK(parent != NULL, return nvpair_hash);
918 
919  nvpair_list = find_xml_node(parent, XML_TAG_ATTRS, FALSE);
920  if (nvpair_list == NULL) {
921  crm_trace("No attributes in %s", crm_element_name(parent));
922  crm_log_xml_trace(parent, "No attributes for resource op");
923  }
924 
925  crm_log_xml_trace(nvpair_list, "Unpacking");
926 
927  for (pIter = pcmk__first_xml_attr(nvpair_list); pIter != NULL;
928  pIter = pIter->next) {
929 
930  const char *p_name = (const char *)pIter->name;
931  const char *p_value = pcmk__xml_attr_value(pIter);
932 
933  crm_trace("Added %s=%s", p_name, p_value);
934 
935  g_hash_table_insert(nvpair_hash, strdup(p_name), strdup(p_value));
936  }
937 
938  for (child = __xml_first_child(nvpair_list); child != NULL;
939  child = __xml_next(child)) {
940 
941  if (strcmp((const char *)child->name, XML_TAG_PARAM) == 0) {
942  const char *key = crm_element_value(child, XML_NVPAIR_ATTR_NAME);
943  const char *value = crm_element_value(child, XML_NVPAIR_ATTR_VALUE);
944 
945  crm_trace("Added %s=%s", key, value);
946  if (key != NULL && value != NULL) {
947  g_hash_table_insert(nvpair_hash, strdup(key), strdup(value));
948  }
949  }
950  }
951 
952  return nvpair_hash;
953 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:233
xmlNode * find_xml_node(xmlNode *cib, const char *node_path, gboolean must_find)
Definition: xml.c:1764
A dumping ground.
GSList * pcmk_sort_nvpairs(GSList *list)
Sort a list of name/value pairs.
Definition: nvpair.c:146
char * name
Definition: nvpair.h:29
void hash2field(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry.
Definition: nvpair.c:784
void pcmk_free_nvpairs(GSList *nvpairs)
Free a list of name/value pairs.
Definition: nvpair.c:102
const char * crm_xml_add_ms(xmlNode *node, const char *name, guint ms)
Create an XML attribute with specified name and unsigned value.
Definition: nvpair.c:446
char * value
Definition: nvpair.h:30
G_GNUC_INTERNAL void pcmk__mark_xml_attr_dirty(xmlAttr *a)
Definition: xml.c:193
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition: nvpair.c:424
#define XML_TAG_ATTRS
Definition: msg_xml.h:165
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:316
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
Definition: strings.c:126
#define XML_NVPAIR_ATTR_NAME
Definition: msg_xml.h:339
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:219
GSList * pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
Prepend a name/value pair to a list.
Definition: nvpair.c:91
int pcmk_scan_nvpair(const char *input, char **name, char **value)
Extract the name and value from an input string formatted as &quot;name=value&quot;. If unable to extract them...
Definition: nvpair.c:220
#define XML_CIB_TAG_NVPAIR
Definition: msg_xml.h:160
char * pcmk_format_nvpair(const char *name, const char *value, const char *units)
Definition: nvpair.c:281
int crm_element_value_ll(const xmlNode *data, const char *name, long long *dest)
Retrieve the long long integer value of an XML attribute.
Definition: nvpair.c:586
GSList * pcmk_xml_attrs2nvpairs(xmlNode *xml)
Create a list of name/value pairs from an XML node&#39;s attributes.
Definition: nvpair.c:161
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:558
void hash2smartfield(gpointer key, gpointer value, gpointer user_data)
Add hash table entry to XML as (possibly legacy) name/value.
Definition: nvpair.c:750
char * strndup(const char *str, size_t len)
char * crm_meta_name(const char *field)
Definition: utils.c:454
void hash2nvpair(gpointer key, gpointer value, gpointer user_data)
Add XML nvpair element based on hash table entry.
Definition: nvpair.c:885
char * pcmk_format_named_time(const char *name, time_t epoch_time)
Definition: nvpair.c:297
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition: acl.c:635
int rc
Definition: pcmk_fence.c:34
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
Definition: nvpair.c:614
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition: nvpair.c:725
#define XML_ATTR_ID
Definition: msg_xml.h:96
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:522
int crm_element_value_timeval(const xmlNode *data, const char *name_sec, const char *name_usec, struct timeval *dest)
Retrieve the value of XML second/microsecond attributes as time.
Definition: nvpair.c:678
const char * crm_xml_replace(xmlNode *node, const char *name, const char *value)
Replace an XML attribute with specified name and (possibly NULL) value.
Definition: nvpair.c:373
#define crm_trace(fmt, args...)
Definition: logging.h:369
Wrappers for and extensions to libxml2.
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:1976
#define LLSTRSIZE
Definition: nvpair.c:457
int crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
Retrieve the seconds-since-epoch value of an XML attribute.
Definition: nvpair.c:649
const char * pcmk__epoch2str(time_t *when)
Definition: iso8601.c:1715
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.
Definition: nvpair.c:498
const char * crm_xml_add_ll(xmlNode *node, const char *name, long long value)
Create an XML attribute with specified name and long long int value.
Definition: nvpair.c:474
const xmlChar * pcmkXmlStr
Definition: xml.h:51
long long crm_parse_ll(const char *text, const char *default_text)
Parse a long long integer value from a string.
Definition: strings.c:100
#define crm_err(fmt, args...)
Definition: logging.h:363
#define CRM_ASSERT(expr)
Definition: results.h:42
void crm_xml_set_id(xmlNode *xml, const char *format,...) __attribute__((__format__(__printf__
void xml_remove_prop(xmlNode *obj, const char *name)
Definition: xml.c:3340
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:340
void hash2metafield(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry, as meta-attribute name.
Definition: nvpair.c:812
char data[0]
Definition: internal.h:90
GHashTable * xml2list(xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition: nvpair.c:910
void pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
Add XML attributes based on a list of name/value pairs.
Definition: nvpair.c:201
#define pcmk_ok
Definition: results.h:67
#define crm_log_xml_trace(xml, text)
Definition: logging.h:377
G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
Definition: xml.c:74
xmlNode * crm_create_nvpair_xml(xmlNode *parent, const char *id, const char *name, const char *value)
Create an XML name/value pair.
Definition: nvpair.c:847
#define ID(x)
Definition: msg_xml.h:418
char * name
Definition: pcmk_fence.c:30
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
#define pcmk_err_bad_nvpair
Definition: results.h:90
#define XML_TAG_PARAM
Definition: msg_xml.h:170