pacemaker  2.1.8-3980678f03
Scalable High-Availability cluster resource manager
nvpair.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2024 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/common/xml.h>
22 #include "crmcommon_private.h"
23 
24 /*
25  * This file isolates handling of various kinds of name/value pairs:
26  *
27  * - pcmk_nvpair_t data type
28  * - XML attributes (<TAG ... NAME=VALUE ...>)
29  * - XML nvpair elements (<nvpair id=ID name=NAME value=VALUE>)
30  * - Meta-attributes (for resources and actions)
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 
52 
53  nvpair = pcmk__assert_alloc(1, sizeof(pcmk_nvpair_t));
54 
55  nvpair->name = pcmk__str_copy(name);
56  nvpair->value = pcmk__str_copy(value);
57  return nvpair;
58 }
59 
66 static void
67 pcmk__free_nvpair(gpointer data)
68 {
69  if (data) {
70  pcmk_nvpair_t *nvpair = data;
71 
72  free(nvpair->name);
73  free(nvpair->value);
74  free(nvpair);
75  }
76 }
77 
89 GSList *
90 pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
91 {
92  return g_slist_prepend(nvpairs, pcmk__new_nvpair(name, value));
93 }
94 
100 void
101 pcmk_free_nvpairs(GSList *nvpairs)
102 {
103  g_slist_free_full(nvpairs, pcmk__free_nvpair);
104 }
105 
115 static gint
116 pcmk__compare_nvpair(gconstpointer a, gconstpointer b)
117 {
118  int rc = 0;
119  const pcmk_nvpair_t *pair_a = a;
120  const pcmk_nvpair_t *pair_b = b;
121 
122  CRM_ASSERT(a != NULL);
123  CRM_ASSERT(pair_a->name != NULL);
124 
125  CRM_ASSERT(b != NULL);
126  CRM_ASSERT(pair_b->name != NULL);
127 
128  rc = strcmp(pair_a->name, pair_b->name);
129  if (rc < 0) {
130  return -1;
131  } else if (rc > 0) {
132  return 1;
133  }
134  return 0;
135 }
136 
144 GSList *
145 pcmk_sort_nvpairs(GSList *list)
146 {
147  return g_slist_sort(list, pcmk__compare_nvpair);
148 }
149 
159 GSList *
160 pcmk_xml_attrs2nvpairs(const xmlNode *xml)
161 {
162  GSList *result = NULL;
163 
164  for (xmlAttrPtr iter = pcmk__xe_first_attr(xml); iter != NULL;
165  iter = iter->next) {
166 
168  (const char *) iter->name,
169  (const char *) pcmk__xml_attr_value(iter));
170  }
171  return result;
172 }
173 
184 static void
185 pcmk__nvpair_add_xml_attr(gpointer data, gpointer user_data)
186 {
187  pcmk_nvpair_t *pair = data;
188  xmlNode *parent = user_data;
189 
190  crm_xml_add(parent, pair->name, pair->value);
191 }
192 
199 void
200 pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
201 {
202  g_slist_foreach(list, pcmk__nvpair_add_xml_attr, xml);
203 }
204 
205 // convenience function for name=value strings
206 
219 int
220 pcmk__scan_nvpair(const char *input, char **name, char **value)
221 {
222 #ifdef HAVE_SSCANF_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 
282 char *
283 pcmk__format_nvpair(const char *name, const char *value, const char *units)
284 {
285  return crm_strdup_printf("%s=\"%s%s\"", name, value, units ? units : "");
286 }
287 
288 // XML attribute handling
289 
300 const char *
301 crm_xml_add(xmlNode *node, const char *name, const char *value)
302 {
303  bool dirty = FALSE;
304  xmlAttr *attr = NULL;
305 
306  CRM_CHECK(node != NULL, return NULL);
307  CRM_CHECK(name != NULL, return NULL);
308 
309  if (value == NULL) {
310  return NULL;
311  }
312 
313  if (pcmk__tracking_xml_changes(node, FALSE)) {
314  const char *old = crm_element_value(node, name);
315 
316  if (old == NULL || value == NULL || strcmp(old, value) != 0) {
317  dirty = TRUE;
318  }
319  }
320 
321  if (dirty && (pcmk__check_acl(node, name, pcmk__xf_acl_create) == FALSE)) {
322  crm_trace("Cannot add %s=%s to %s", name, value, node->name);
323  return NULL;
324  }
325 
326  attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
327  if (dirty) {
329  }
330 
331  CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
332  return (char *)attr->children->content;
333 }
334 
347 const char *
348 crm_xml_add_int(xmlNode *node, const char *name, int value)
349 {
350  char *number = pcmk__itoa(value);
351  const char *added = crm_xml_add(node, name, number);
352 
353  free(number);
354  return added;
355 }
356 
369 const char *
370 crm_xml_add_ms(xmlNode *node, const char *name, guint ms)
371 {
372  char *number = crm_strdup_printf("%u", ms);
373  const char *added = crm_xml_add(node, name, number);
374 
375  free(number);
376  return added;
377 }
378 
379 // Maximum size of null-terminated string representation of 64-bit integer
380 // -9223372036854775808
381 #define LLSTRSIZE 21
382 
397 const char *
398 crm_xml_add_ll(xmlNode *xml, const char *name, long long value)
399 {
400  char s[LLSTRSIZE] = { '\0', };
401 
402  if (snprintf(s, LLSTRSIZE, "%lld", (long long) value) == LLSTRSIZE) {
403  return NULL;
404  }
405  return crm_xml_add(xml, name, s);
406 }
407 
421 const char *
422 crm_xml_add_timeval(xmlNode *xml, const char *name_sec, const char *name_usec,
423  const struct timeval *value)
424 {
425  const char *added = NULL;
426 
427  if (xml && name_sec && value) {
428  added = crm_xml_add_ll(xml, name_sec, (long long) value->tv_sec);
429  if (added && name_usec) {
430  // Any error is ignored (we successfully added seconds)
431  crm_xml_add_ll(xml, name_usec, (long long) value->tv_usec);
432  }
433  }
434  return added;
435 }
436 
445 const char *
446 crm_element_value(const xmlNode *data, const char *name)
447 {
448  xmlAttr *attr = NULL;
449 
450  if (data == NULL) {
451  crm_err("Couldn't find %s in NULL", name ? name : "<null>");
452  CRM_LOG_ASSERT(data != NULL);
453  return NULL;
454 
455  } else if (name == NULL) {
456  crm_err("Couldn't find NULL in %s", data->name);
457  return NULL;
458  }
459 
460  /* The first argument to xmlHasProp() has always been const,
461  * but libxml2 <2.9.2 didn't declare that, so cast it
462  */
463  attr = xmlHasProp((xmlNode *) data, (pcmkXmlStr) name);
464  if (!attr || !attr->children) {
465  return NULL;
466  }
467  return (const char *) attr->children->content;
468 }
469 
481 int
482 crm_element_value_int(const xmlNode *data, const char *name, int *dest)
483 {
484  const char *value = NULL;
485 
486  CRM_CHECK(dest != NULL, return -1);
487  value = crm_element_value(data, name);
488  if (value) {
489  long long value_ll;
490 
491  if ((pcmk__scan_ll(value, &value_ll, 0LL) != pcmk_rc_ok)
492  || (value_ll < INT_MIN) || (value_ll > INT_MAX)) {
493  *dest = PCMK__PARSE_INT_DEFAULT;
494  } else {
495  *dest = (int) value_ll;
496  return 0;
497  }
498  }
499  return -1;
500 }
501 
513 int
514 crm_element_value_ll(const xmlNode *data, const char *name, long long *dest)
515 {
516  const char *value = NULL;
517 
518  CRM_CHECK(dest != NULL, return -1);
519  value = crm_element_value(data, name);
520  if ((value != NULL)
521  && (pcmk__scan_ll(value, dest, PCMK__PARSE_INT_DEFAULT) == pcmk_rc_ok)) {
522  return 0;
523  }
524  return -1;
525 }
526 
538 int
539 crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
540 {
541  const char *value = NULL;
542  long long value_ll;
543 
544  CRM_CHECK(dest != NULL, return -1);
545  *dest = 0;
546  value = crm_element_value(data, name);
547  if ((pcmk__scan_ll(value, &value_ll, 0LL) != pcmk_rc_ok)
548  || (value_ll < 0) || (value_ll > G_MAXUINT)) {
549  return -1;
550  }
551  *dest = (guint) value_ll;
552  return pcmk_ok;
553 }
554 
566 int
567 crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
568 {
569  long long value_ll = 0;
570 
571  if (crm_element_value_ll(xml, name, &value_ll) < 0) {
572  return -1;
573  }
574 
575  /* Unfortunately, we can't do any bounds checking, since time_t has neither
576  * standardized bounds nor constants defined for them.
577  */
578  *dest = (time_t) value_ll;
579  return pcmk_ok;
580 }
581 
595 int
596 crm_element_value_timeval(const xmlNode *xml, const char *name_sec,
597  const char *name_usec, struct timeval *dest)
598 {
599  long long value_i = 0;
600 
601  CRM_CHECK(dest != NULL, return -EINVAL);
602  dest->tv_sec = 0;
603  dest->tv_usec = 0;
604 
605  if (xml == NULL) {
606  return pcmk_ok;
607  }
608 
609  /* Unfortunately, we can't do any bounds checking, since there are no
610  * constants provided for the bounds of time_t and suseconds_t, and
611  * calculating them isn't worth the effort. If there are XML values
612  * beyond the native sizes, there will probably be worse problems anyway.
613  */
614 
615  // Parse seconds
616  errno = 0;
617  if (crm_element_value_ll(xml, name_sec, &value_i) < 0) {
618  return -errno;
619  }
620  dest->tv_sec = (time_t) value_i;
621 
622  // Parse microseconds
623  if (crm_element_value_ll(xml, name_usec, &value_i) < 0) {
624  return -errno;
625  }
626  dest->tv_usec = (suseconds_t) value_i;
627 
628  return pcmk_ok;
629 }
630 
643 int
644 pcmk__xe_get_datetime(const xmlNode *xml, const char *attr, crm_time_t **t)
645 {
646  const char *value = NULL;
647 
648  if ((t == NULL) || (*t != NULL) || (xml == NULL) || (attr == NULL)) {
649  return EINVAL;
650  }
651 
652  value = crm_element_value(xml, attr);
653  if (value != NULL) {
654  *t = crm_time_new(value);
655  if (*t == NULL) {
656  return pcmk_rc_unpack_error;
657  }
658  }
659  return pcmk_rc_ok;
660 }
661 
673 char *
674 crm_element_value_copy(const xmlNode *data, const char *name)
675 {
677 }
678 
693 void
694 hash2smartfield(gpointer key, gpointer value, gpointer user_data)
695 {
696  /* @TODO Generate PCMK__XE_PARAM nodes for all keys that aren't valid XML
697  * attribute names (not just those that start with digits), or possibly for
698  * all keys to simplify parsing.
699  *
700  * Consider either deprecating as public API or exposing PCMK__XE_PARAM.
701  * PCMK__XE_PARAM is currently private because it doesn't appear in any
702  * output that Pacemaker generates.
703  */
704  const char *name = key;
705  const char *s_value = value;
706 
707  xmlNode *xml_node = user_data;
708 
709  if (isdigit(name[0])) {
710  xmlNode *tmp = pcmk__xe_create(xml_node, PCMK__XE_PARAM);
711 
713  crm_xml_add(tmp, PCMK_XA_VALUE, s_value);
714 
715  } else if (crm_element_value(xml_node, name) == NULL) {
716  crm_xml_add(xml_node, name, s_value);
717  crm_trace("dumped: %s=%s", name, s_value);
718 
719  } else {
720  crm_trace("duplicate: %s=%s", name, s_value);
721  }
722 }
723 
735 void
736 hash2field(gpointer key, gpointer value, gpointer user_data)
737 {
738  const char *name = key;
739  const char *s_value = value;
740 
741  xmlNode *xml_node = user_data;
742 
743  if (crm_element_value(xml_node, name) == NULL) {
744  crm_xml_add(xml_node, name, s_value);
745 
746  } else {
747  crm_trace("duplicate: %s=%s", name, s_value);
748  }
749 }
750 
763 void
764 hash2metafield(gpointer key, gpointer value, gpointer user_data)
765 {
766  char *crm_name = NULL;
767 
768  if (key == NULL || value == NULL) {
769  return;
770  }
771 
772  /* Filter out cluster-generated attributes that contain a '#' or ':'
773  * (like fail-count and last-failure).
774  */
775  for (crm_name = key; *crm_name; ++crm_name) {
776  if ((*crm_name == '#') || (*crm_name == ':')) {
777  return;
778  }
779  }
780 
781  crm_name = crm_meta_name(key);
782  hash2field(crm_name, value, user_data);
783  free(crm_name);
784 }
785 
786 // nvpair handling
787 
798 xmlNode *
799 crm_create_nvpair_xml(xmlNode *parent, const char *id, const char *name,
800  const char *value)
801 {
802  xmlNode *nvp;
803 
804  /* id can be NULL so we auto-generate one, and name can be NULL if this
805  * will be used to delete a name/value pair by ID, but both can't be NULL
806  */
807  CRM_CHECK(id || name, return NULL);
808 
810 
811  if (id) {
812  crm_xml_add(nvp, PCMK_XA_ID, id);
813  } else {
814  crm_xml_set_id(nvp, "%s-%s",
815  pcmk__s(pcmk__xe_id(parent), PCMK_XE_NVPAIR), name);
816  }
818  crm_xml_add(nvp, PCMK_XA_VALUE, value);
819  return nvp;
820 }
821 
833 void
834 hash2nvpair(gpointer key, gpointer value, gpointer user_data)
835 {
836  const char *name = key;
837  const char *s_value = value;
838  xmlNode *xml_node = user_data;
839 
840  crm_create_nvpair_xml(xml_node, name, name, s_value);
841  crm_trace("dumped: name=%s value=%s", name, s_value);
842 }
843 
858 GHashTable *
859 xml2list(const xmlNode *parent)
860 {
861  xmlNode *child = NULL;
862  xmlAttrPtr pIter = NULL;
863  xmlNode *nvpair_list = NULL;
864  GHashTable *nvpair_hash = pcmk__strkey_table(free, free);
865 
866  CRM_CHECK(parent != NULL, return nvpair_hash);
867 
868  nvpair_list = pcmk__xe_first_child(parent, PCMK__XE_ATTRIBUTES, NULL, NULL);
869  if (nvpair_list == NULL) {
870  crm_trace("No attributes in %s", parent->name);
871  crm_log_xml_trace(parent, "No attributes for resource op");
872  }
873 
874  crm_log_xml_trace(nvpair_list, "Unpacking");
875 
876  for (pIter = pcmk__xe_first_attr(nvpair_list); pIter != NULL;
877  pIter = pIter->next) {
878 
879  const char *p_name = (const char *)pIter->name;
880  const char *p_value = pcmk__xml_attr_value(pIter);
881 
882  crm_trace("Added %s=%s", p_name, p_value);
883 
884  pcmk__insert_dup(nvpair_hash, p_name, p_value);
885  }
886 
887  for (child = pcmk__xe_first_child(nvpair_list, PCMK__XE_PARAM, NULL, NULL);
888  child != NULL; child = pcmk__xe_next_same(child)) {
889 
890  const char *key = crm_element_value(child, PCMK_XA_NAME);
891  const char *value = crm_element_value(child, PCMK_XA_VALUE);
892 
893  crm_trace("Added %s=%s", key, value);
894  if (key != NULL && value != NULL) {
895  pcmk__insert_dup(nvpair_hash, key, value);
896  }
897  }
898 
899  return nvpair_hash;
900 }
901 
902 void
903 pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value)
904 {
905  crm_xml_add(node, name, pcmk__btoa(value));
906 }
907 
908 int
909 pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
910 {
911  const char *xml_value = NULL;
912  int ret, rc;
913 
914  if (node == NULL) {
915  return ENODATA;
916  } else if (name == NULL || value == NULL) {
917  return EINVAL;
918  }
919 
920  xml_value = crm_element_value(node, name);
921 
922  if (xml_value == NULL) {
923  return ENODATA;
924  }
925 
926  rc = crm_str_to_boolean(xml_value, &ret);
927  if (rc == 1) {
928  *value = ret;
929  return pcmk_rc_ok;
930  } else {
931  return pcmk_rc_bad_input;
932  }
933 }
934 
935 bool
936 pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
937 {
938  bool value = false;
939  int rc;
940 
941  rc = pcmk__xe_get_bool_attr(node, name, &value);
942  return rc == pcmk_rc_ok && value == true;
943 }
944 
945 // Meta-attribute handling
946 
958 char *
959 crm_meta_name(const char *attr_name)
960 {
961  char *env_name = NULL;
962 
963  CRM_ASSERT(!pcmk__str_empty(attr_name));
964 
965  env_name = crm_strdup_printf(CRM_META "_%s", attr_name);
966  for (char *c = env_name; *c != '\0'; ++c) {
967  if (*c == '-') {
968  *c = '_';
969  }
970  }
971  return env_name;
972 }
973 
986 const char *
987 crm_meta_value(GHashTable *meta, const char *attr_name)
988 {
989  if ((meta != NULL) && (attr_name != NULL)) {
990  char *key = crm_meta_name(attr_name);
991  const char *value = g_hash_table_lookup(meta, key);
992 
993  free(key);
994  return value;
995  }
996  return NULL;
997 }
998 
999 // Deprecated functions kept only for backward API compatibility
1000 // LCOV_EXCL_START
1001 
1002 #include <crm/common/util_compat.h>
1003 
1004 int
1005 pcmk_scan_nvpair(const char *input, char **name, char **value)
1006 {
1007  return pcmk__scan_nvpair(input, name, value);
1008 }
1009 
1010 char *
1011 pcmk_format_nvpair(const char *name, const char *value,
1012  const char *units)
1013 {
1014  return pcmk__format_nvpair(name, value, units);
1015 }
1016 
1017 char *
1018 pcmk_format_named_time(const char *name, time_t epoch_time)
1019 {
1020  char *now_s = pcmk__epoch2str(&epoch_time, 0);
1021  char *result = crm_strdup_printf("%s=\"%s\"", name, pcmk__s(now_s, ""));
1022 
1023  free(now_s);
1024  return result;
1025 }
1026 
1027 const char *
1028 crm_xml_replace(xmlNode *node, const char *name, const char *value)
1029 {
1030  bool dirty = FALSE;
1031  xmlAttr *attr = NULL;
1032  const char *old_value = NULL;
1033 
1034  CRM_CHECK(node != NULL, return NULL);
1035  CRM_CHECK(name != NULL && name[0] != 0, return NULL);
1036 
1037  old_value = crm_element_value(node, name);
1038 
1039  /* Could be re-setting the same value */
1040  CRM_CHECK(old_value != value, return value);
1041 
1042  if (pcmk__check_acl(node, name, pcmk__xf_acl_write) == FALSE) {
1043  /* Create a fake object linked to doc->_private instead? */
1044  crm_trace("Cannot replace %s=%s to %s", name, value, node->name);
1045  return NULL;
1046 
1047  } else if (old_value && !value) {
1048  pcmk__xe_remove_attr(node, name);
1049  return NULL;
1050  }
1051 
1052  if (pcmk__tracking_xml_changes(node, FALSE)) {
1053  if (!old_value || !value || !strcmp(old_value, value)) {
1054  dirty = TRUE;
1055  }
1056  }
1057 
1058  attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
1059  if (dirty) {
1061  }
1062  CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
1063  return (char *) attr->children->content;
1064 }
1065 
1066 // LCOV_EXCL_STOP
1067 // End deprecated API
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:245
GSList * pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
Prepend a name/value pair to a list.
Definition: nvpair.c:90
A dumping ground.
#define PCMK_XE_NVPAIR
Definition: xml_names.h:141
#define PCMK_XA_NAME
Definition: xml_names.h:325
char * name
Definition: nvpair.h:30
char data[0]
Definition: cpg.c:58
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:514
const char * name
Definition: cib.c:26
char * value
Definition: nvpair.h:31
struct crm_time_s crm_time_t
Definition: iso8601.h:32
char * pcmk__format_nvpair(const char *name, const char *value, const char *units)
Definition: nvpair.c:283
G_GNUC_INTERNAL void pcmk__mark_xml_attr_dirty(xmlAttr *a)
Definition: xml_attr.c:31
char * crm_meta_name(const char *attr_name)
Get the environment variable equivalent of a meta-attribute name.
Definition: nvpair.c:959
GHashTable * xml2list(const xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition: nvpair.c:859
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
Definition: nvpair.c:539
GSList * pcmk_xml_attrs2nvpairs(const xmlNode *xml)
Create a list of name/value pairs from an XML node&#39;s attributes.
Definition: nvpair.c:160
#define PCMK__XE_ATTRIBUTES
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:228
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:799
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
Definition: nvpair.c:936
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.
Definition: nvpair.c:596
int pcmk__xe_get_datetime(const xmlNode *xml, const char *attr, crm_time_t **t)
Definition: nvpair.c:644
#define PCMK__PARSE_INT_DEFAULT
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition: strings.c:97
void hash2metafield(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry, as meta-attribute name.
Definition: nvpair.c:764
void pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
Add XML attributes based on a list of name/value pairs.
Definition: nvpair.c:200
void pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value)
Definition: nvpair.c:903
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml.c:440
char * pcmk_format_nvpair(const char *name, const char *value, const char *units)
Definition: nvpair.c:1011
#define crm_trace(fmt, args...)
Definition: logging.h:404
void hash2field(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry.
Definition: nvpair.c:736
void pcmk_free_nvpairs(GSList *nvpairs)
Free a list of name/value pairs.
Definition: nvpair.c:101
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
void crm_xml_set_id(xmlNode *xml, const char *format,...) G_GNUC_PRINTF(2
void hash2smartfield(gpointer key, gpointer value, gpointer user_data)
Safely add hash table entry to XML as attribute or name-value pair.
Definition: nvpair.c:694
Wrappers for and extensions to libxml2.
void pcmk__xe_remove_attr(xmlNode *element, const char *name)
Definition: xml.c:652
char * pcmk_format_named_time(const char *name, time_t epoch_time)
Definition: nvpair.c:1018
#define LLSTRSIZE
Definition: nvpair.c:381
void hash2nvpair(gpointer key, gpointer value, gpointer user_data)
Add XML nvpair element based on hash table entry.
Definition: nvpair.c:834
#define PCMK_XA_ID
Definition: xml_names.h:296
#define PCMK_XA_VALUE
Definition: xml_names.h:437
int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
Definition: nvpair.c:909
#define pcmk__str_copy(str)
GSList * pcmk_sort_nvpairs(GSList *list)
Sort a list of name/value pairs.
Definition: nvpair.c:145
const xmlChar * pcmkXmlStr
Definition: xml.h:41
const char * crm_meta_value(GHashTable *meta, const char *attr_name)
Get the value of a meta-attribute.
Definition: nvpair.c:987
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:446
int crm_str_to_boolean(const char *s, int *ret)
Definition: strings.c:496
const char * crm_xml_replace(xmlNode *node, const char *name, const char *value)
Definition: nvpair.c:1028
#define ENODATA
Definition: portability.h:106
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:683
pcmk__action_result_t result
Definition: pcmk_fence.c:35
#define CRM_META
Definition: crm.h:81
#define crm_err(fmt, args...)
Definition: logging.h:391
#define CRM_ASSERT(expr)
Definition: results.h:42
char * pcmk__epoch2str(const time_t *source, uint32_t flags)
Definition: iso8601.c:2075
Deprecated Pacemaker utilities.
xmlNode * input
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:112
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:348
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition: acl.c:658
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:567
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:301
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.
Definition: nvpair.c:398
#define pcmk_ok
Definition: results.h:69
#define PCMK__XE_PARAM
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition: nvpair.c:674
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:422
#define crm_log_xml_trace(xml, text)
Definition: logging.h:412
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:370
G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
Definition: xml.c:60
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:482
const char * parent
Definition: cib.c:27
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
Definition: xml.c:720
#define pcmk__assert_alloc(nmemb, size)
Definition: internal.h:297
int pcmk_scan_nvpair(const char *input, char **name, char **value)
Definition: nvpair.c:1005
xmlNode * pcmk__xe_next_same(const xmlNode *node)
Definition: xml.c:2108
#define pcmk_err_bad_nvpair
Definition: results.h:98
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition: strings.c:701
int pcmk__scan_nvpair(const char *input, char **name, char **value)
Definition: nvpair.c:220