pacemaker  2.1.9-49aab99839
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 <stdint.h> // UINT32_MAX
14 #include <inttypes.h> // PRIu32
15 #include <sys/types.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <glib.h>
19 #include <libxml/tree.h>
20 
21 #include <crm/crm.h>
22 #include <crm/common/xml.h>
24 #include "crmcommon_private.h"
25 
26 /*
27  * This file isolates handling of various kinds of name/value pairs:
28  *
29  * - pcmk_nvpair_t data type
30  * - XML attributes (<TAG ... NAME=VALUE ...>)
31  * - XML nvpair elements (<nvpair id=ID name=NAME value=VALUE>)
32  * - Meta-attributes (for resources and actions)
33  */
34 
35 // pcmk_nvpair_t handling
36 
48 static pcmk_nvpair_t *
49 pcmk__new_nvpair(const char *name, const char *value)
50 {
51  pcmk_nvpair_t *nvpair = NULL;
52 
54 
55  nvpair = pcmk__assert_alloc(1, sizeof(pcmk_nvpair_t));
56 
57  nvpair->name = pcmk__str_copy(name);
58  nvpair->value = pcmk__str_copy(value);
59  return nvpair;
60 }
61 
68 static void
69 pcmk__free_nvpair(gpointer data)
70 {
71  if (data) {
72  pcmk_nvpair_t *nvpair = data;
73 
74  free(nvpair->name);
75  free(nvpair->value);
76  free(nvpair);
77  }
78 }
79 
91 GSList *
92 pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
93 {
94  return g_slist_prepend(nvpairs, pcmk__new_nvpair(name, value));
95 }
96 
102 void
103 pcmk_free_nvpairs(GSList *nvpairs)
104 {
105  g_slist_free_full(nvpairs, pcmk__free_nvpair);
106 }
107 
117 static gint
118 pcmk__compare_nvpair(gconstpointer a, gconstpointer b)
119 {
120  int rc = 0;
121  const pcmk_nvpair_t *pair_a = a;
122  const pcmk_nvpair_t *pair_b = b;
123 
124  pcmk__assert((pair_a != NULL) && (pair_a->name != NULL)
125  && (pair_b != NULL) && (pair_b->name != NULL));
126 
127  rc = strcmp(pair_a->name, pair_b->name);
128  if (rc < 0) {
129  return -1;
130  } else if (rc > 0) {
131  return 1;
132  }
133  return 0;
134 }
135 
143 GSList *
144 pcmk_sort_nvpairs(GSList *list)
145 {
146  return g_slist_sort(list, pcmk__compare_nvpair);
147 }
148 
158 GSList *
159 pcmk_xml_attrs2nvpairs(const xmlNode *xml)
160 {
161  GSList *result = NULL;
162 
163  for (xmlAttrPtr iter = pcmk__xe_first_attr(xml); iter != NULL;
164  iter = iter->next) {
165 
167  (const char *) iter->name,
168  (const char *) pcmk__xml_attr_value(iter));
169  }
170  return result;
171 }
172 
183 static void
184 pcmk__nvpair_add_xml_attr(gpointer data, gpointer user_data)
185 {
186  pcmk_nvpair_t *pair = data;
187  xmlNode *parent = user_data;
188 
189  crm_xml_add(parent, pair->name, pair->value);
190 }
191 
198 void
199 pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
200 {
201  g_slist_foreach(list, pcmk__nvpair_add_xml_attr, xml);
202 }
203 
204 // convenience function for name=value strings
205 
218 int
219 pcmk__scan_nvpair(const char *input, char **name, char **value)
220 {
221 #ifdef HAVE_SSCANF_M
222  *name = NULL;
223  *value = NULL;
224  if (sscanf(input, "%m[^=]=%m[^\n]", name, value) <= 0) {
225  return -pcmk_err_bad_nvpair;
226  }
227 #else
228  char *sep = NULL;
229  *name = NULL;
230  *value = NULL;
231 
232  sep = strstr(optarg, "=");
233  if (sep == NULL) {
234  return -pcmk_err_bad_nvpair;
235  }
236 
237  *name = strndup(input, sep-input);
238 
239  if (*name == NULL) {
240  return -ENOMEM;
241  }
242 
243  /* If the last char in optarg is =, the user gave no
244  * value for the option. Leave it as NULL.
245  */
246  if (*(sep+1) != '\0') {
247  *value = strdup(sep+1);
248 
249  if (*value == NULL) {
250  return -ENOMEM;
251  }
252  }
253 #endif
254 
255  if (*name != NULL && *value != NULL) {
256  return 2;
257  } else if (*name != NULL || *value != NULL) {
258  return 1;
259  } else {
260  return -pcmk_err_bad_nvpair;
261  }
262 }
263 
281 char *
282 pcmk__format_nvpair(const char *name, const char *value, const char *units)
283 {
284  return crm_strdup_printf("%s=\"%s%s\"", name, value, units ? units : "");
285 }
286 
287 // XML attribute handling
288 
289 xmlAttr *
290 pcmk__xe_set_attr_force(xmlNode *node, const char *name, const char *value)
291 {
292  xmlAttr *attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
293 
294  /* If the attribute already exists, this does nothing. Attribute values
295  * don't get private data.
296  */
297  pcmk__xml_new_private_data((xmlNode *) attr);
298 
299  return attr;
300 }
301 
312 const char *
313 crm_xml_add(xmlNode *node, const char *name, const char *value)
314 {
315  bool dirty = FALSE;
316  xmlAttr *attr = NULL;
317 
318  CRM_CHECK(node != NULL, return NULL);
319  CRM_CHECK(name != NULL, return NULL);
320 
321  if (value == NULL) {
322  return NULL;
323  }
324 
325  if (pcmk__tracking_xml_changes(node, FALSE)) {
326  const char *old = crm_element_value(node, name);
327 
328  if (old == NULL || value == NULL || strcmp(old, value) != 0) {
329  dirty = TRUE;
330  }
331  }
332 
333  if (dirty && (pcmk__check_acl(node, name, pcmk__xf_acl_create) == FALSE)) {
334  crm_trace("Cannot add %s=%s to %s", name, value, node->name);
335  return NULL;
336  }
337 
338  attr = pcmk__xe_set_attr_force(node, name, value);
339  if (dirty) {
341  }
342 
343  CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
344  return (char *)attr->children->content;
345 }
346 
359 const char *
360 crm_xml_add_int(xmlNode *node, const char *name, int value)
361 {
362  char *number = pcmk__itoa(value);
363  const char *added = crm_xml_add(node, name, number);
364 
365  free(number);
366  return added;
367 }
368 
381 const char *
382 crm_xml_add_ms(xmlNode *node, const char *name, guint ms)
383 {
384  char *number = crm_strdup_printf("%u", ms);
385  const char *added = crm_xml_add(node, name, number);
386 
387  free(number);
388  return added;
389 }
390 
391 // Maximum size of null-terminated string representation of 64-bit integer
392 // -9223372036854775808
393 #define LLSTRSIZE 21
394 
409 const char *
410 crm_xml_add_ll(xmlNode *xml, const char *name, long long value)
411 {
412  char s[LLSTRSIZE] = { '\0', };
413 
414  if (snprintf(s, LLSTRSIZE, "%lld", (long long) value) == LLSTRSIZE) {
415  return NULL;
416  }
417  return crm_xml_add(xml, name, s);
418 }
419 
433 const char *
434 crm_xml_add_timeval(xmlNode *xml, const char *name_sec, const char *name_usec,
435  const struct timeval *value)
436 {
437  const char *added = NULL;
438 
439  if (xml && name_sec && value) {
440  added = crm_xml_add_ll(xml, name_sec, (long long) value->tv_sec);
441  if (added && name_usec) {
442  // Any error is ignored (we successfully added seconds)
443  crm_xml_add_ll(xml, name_usec, (long long) value->tv_usec);
444  }
445  }
446  return added;
447 }
448 
457 const char *
458 crm_element_value(const xmlNode *data, const char *name)
459 {
460  xmlAttr *attr = NULL;
461 
462  if (data == NULL) {
463  crm_err("Couldn't find %s in NULL", name ? name : "<null>");
464  CRM_LOG_ASSERT(data != NULL);
465  return NULL;
466 
467  } else if (name == NULL) {
468  crm_err("Couldn't find NULL in %s", data->name);
469  return NULL;
470  }
471 
472  /* The first argument to xmlHasProp() has always been const,
473  * but libxml2 <2.9.2 didn't declare that, so cast it
474  */
475  attr = xmlHasProp((xmlNode *) data, (pcmkXmlStr) name);
476  if (!attr || !attr->children) {
477  return NULL;
478  }
479  return (const char *) attr->children->content;
480 }
481 
493 int
494 crm_element_value_int(const xmlNode *data, const char *name, int *dest)
495 {
496  const char *value = NULL;
497 
498  CRM_CHECK(dest != NULL, return -1);
499  value = crm_element_value(data, name);
500  if (value) {
501  long long value_ll;
502  int rc = pcmk__scan_ll(value, &value_ll, 0LL);
503 
504  *dest = PCMK__PARSE_INT_DEFAULT;
505  if (rc != pcmk_rc_ok) {
506  crm_warn("Using default for %s "
507  "because '%s' is not a valid integer: %s",
508  name, value, pcmk_rc_str(rc));
509  } else if ((value_ll < INT_MIN) || (value_ll > INT_MAX)) {
510  crm_warn("Using default for %s because '%s' is out of range",
511  name, value);
512  } else {
513  *dest = (int) value_ll;
514  return 0;
515  }
516  }
517  return -1;
518 }
519 
534 int
535 pcmk__xe_get_flags(const xmlNode *xml, const char *name, uint32_t *dest,
536  uint32_t default_value)
537 {
538  const char *value = NULL;
539  long long value_ll = 0LL;
540  int rc = pcmk_rc_ok;
541 
542  if (dest != NULL) {
543  *dest = default_value;
544  }
545 
546  if (name == NULL) {
547  return EINVAL;
548  }
549  if (xml == NULL) {
550  return pcmk_rc_ok;
551  }
552  value = crm_element_value(xml, name);
553  if (value == NULL) {
554  return pcmk_rc_ok;
555  }
556 
557  rc = pcmk__scan_ll(value, &value_ll, default_value);
558  if ((value_ll < 0) || (value_ll > UINT32_MAX)) {
559  value_ll = default_value;
560  if (rc == pcmk_rc_ok) {
561  rc = pcmk_rc_bad_input;
562  }
563  }
564 
565  if (dest != NULL) {
566  *dest = (uint32_t) value_ll;
567  }
568  return rc;
569 }
570 
582 int
583 crm_element_value_ll(const xmlNode *data, const char *name, long long *dest)
584 {
585  const char *value = NULL;
586 
587  CRM_CHECK(dest != NULL, return -1);
588  value = crm_element_value(data, name);
589  if (value != NULL) {
590  int rc = pcmk__scan_ll(value, dest, PCMK__PARSE_INT_DEFAULT);
591 
592  if (rc == pcmk_rc_ok) {
593  return 0;
594  }
595  crm_warn("Using default for %s "
596  "because '%s' is not a valid integer: %s",
597  name, value, pcmk_rc_str(rc));
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  int rc = pcmk_rc_ok;
619 
620  CRM_CHECK(dest != NULL, return -1);
621  *dest = 0;
622  value = crm_element_value(data, name);
623  rc = pcmk__scan_ll(value, &value_ll, 0LL);
624  if (rc != pcmk_rc_ok) {
625  crm_warn("Using default for %s "
626  "because '%s' is not valid milliseconds: %s",
627  name, value, pcmk_rc_str(rc));
628  return -1;
629  }
630  if ((value_ll < 0) || (value_ll > G_MAXUINT)) {
631  crm_warn("Using default for %s because '%s' is out of range",
632  name, value);
633  return -1;
634  }
635  *dest = (guint) value_ll;
636  return pcmk_ok;
637 }
638 
650 int
651 crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
652 {
653  long long value_ll = 0;
654 
655  if (crm_element_value_ll(xml, name, &value_ll) < 0) {
656  return -1;
657  }
658 
659  /* Unfortunately, we can't do any bounds checking, since time_t has neither
660  * standardized bounds nor constants defined for them.
661  */
662  *dest = (time_t) value_ll;
663  return pcmk_ok;
664 }
665 
679 int
680 crm_element_value_timeval(const xmlNode *xml, const char *name_sec,
681  const char *name_usec, struct timeval *dest)
682 {
683  long long value_i = 0;
684 
685  CRM_CHECK(dest != NULL, return -EINVAL);
686  dest->tv_sec = 0;
687  dest->tv_usec = 0;
688 
689  if (xml == NULL) {
690  return pcmk_ok;
691  }
692 
693  /* Unfortunately, we can't do any bounds checking, since there are no
694  * constants provided for the bounds of time_t and suseconds_t, and
695  * calculating them isn't worth the effort. If there are XML values
696  * beyond the native sizes, there will probably be worse problems anyway.
697  */
698 
699  // Parse seconds
700  errno = 0;
701  if (crm_element_value_ll(xml, name_sec, &value_i) < 0) {
702  return -errno;
703  }
704  dest->tv_sec = (time_t) value_i;
705 
706  // Parse microseconds
707  if (crm_element_value_ll(xml, name_usec, &value_i) < 0) {
708  return -errno;
709  }
710  dest->tv_usec = (suseconds_t) value_i;
711 
712  return pcmk_ok;
713 }
714 
727 int
728 pcmk__xe_get_datetime(const xmlNode *xml, const char *attr, crm_time_t **t)
729 {
730  const char *value = NULL;
731 
732  if ((t == NULL) || (*t != NULL) || (xml == NULL) || (attr == NULL)) {
733  return EINVAL;
734  }
735 
736  value = crm_element_value(xml, attr);
737  if (value != NULL) {
738  *t = crm_time_new(value);
739  if (*t == NULL) {
740  return pcmk_rc_unpack_error;
741  }
742  }
743  return pcmk_rc_ok;
744 }
745 
757 char *
758 crm_element_value_copy(const xmlNode *data, const char *name)
759 {
761 }
762 
777 void
778 hash2smartfield(gpointer key, gpointer value, gpointer user_data)
779 {
780  /* @TODO Generate PCMK__XE_PARAM nodes for all keys that aren't valid XML
781  * attribute names (not just those that start with digits), or possibly for
782  * all keys to simplify parsing.
783  *
784  * Consider either deprecating as public API or exposing PCMK__XE_PARAM.
785  * PCMK__XE_PARAM is currently private because it doesn't appear in any
786  * output that Pacemaker generates.
787  */
788  const char *name = key;
789  const char *s_value = value;
790 
791  xmlNode *xml_node = user_data;
792 
793  if (isdigit(name[0])) {
794  xmlNode *tmp = pcmk__xe_create(xml_node, PCMK__XE_PARAM);
795 
797  crm_xml_add(tmp, PCMK_XA_VALUE, s_value);
798 
799  } else if (crm_element_value(xml_node, name) == NULL) {
800  crm_xml_add(xml_node, name, s_value);
801  crm_trace("dumped: %s=%s", name, s_value);
802 
803  } else {
804  crm_trace("duplicate: %s=%s", name, s_value);
805  }
806 }
807 
819 void
820 hash2field(gpointer key, gpointer value, gpointer user_data)
821 {
822  const char *name = key;
823  const char *s_value = value;
824 
825  xmlNode *xml_node = user_data;
826 
827  if (crm_element_value(xml_node, name) == NULL) {
828  crm_xml_add(xml_node, name, s_value);
829 
830  } else {
831  crm_trace("duplicate: %s=%s", name, s_value);
832  }
833 }
834 
847 void
848 hash2metafield(gpointer key, gpointer value, gpointer user_data)
849 {
850  char *crm_name = NULL;
851 
852  if (key == NULL || value == NULL) {
853  return;
854  }
855 
856  /* Filter out cluster-generated attributes that contain a '#' or ':'
857  * (like fail-count and last-failure).
858  */
859  for (crm_name = key; *crm_name; ++crm_name) {
860  if ((*crm_name == '#') || (*crm_name == ':')) {
861  return;
862  }
863  }
864 
865  crm_name = crm_meta_name(key);
866  hash2field(crm_name, value, user_data);
867  free(crm_name);
868 }
869 
870 // nvpair handling
871 
882 xmlNode *
883 crm_create_nvpair_xml(xmlNode *parent, const char *id, const char *name,
884  const char *value)
885 {
886  xmlNode *nvp;
887 
888  /* id can be NULL so we auto-generate one, and name can be NULL if this
889  * will be used to delete a name/value pair by ID, but both can't be NULL
890  */
891  CRM_CHECK(id || name, return NULL);
892 
894 
895  if (id) {
896  crm_xml_add(nvp, PCMK_XA_ID, id);
897  } else {
898  crm_xml_set_id(nvp, "%s-%s",
899  pcmk__s(pcmk__xe_id(parent), PCMK_XE_NVPAIR), name);
900  }
902  crm_xml_add(nvp, PCMK_XA_VALUE, value);
903  return nvp;
904 }
905 
917 void
918 hash2nvpair(gpointer key, gpointer value, gpointer user_data)
919 {
920  const char *name = key;
921  const char *s_value = value;
922  xmlNode *xml_node = user_data;
923 
924  crm_create_nvpair_xml(xml_node, name, name, s_value);
925  crm_trace("dumped: name=%s value=%s", name, s_value);
926 }
927 
942 GHashTable *
943 xml2list(const xmlNode *parent)
944 {
945  xmlNode *child = NULL;
946  xmlAttrPtr pIter = NULL;
947  xmlNode *nvpair_list = NULL;
948  GHashTable *nvpair_hash = pcmk__strkey_table(free, free);
949 
950  CRM_CHECK(parent != NULL, return nvpair_hash);
951 
952  nvpair_list = pcmk__xe_first_child(parent, PCMK__XE_ATTRIBUTES, NULL, NULL);
953  if (nvpair_list == NULL) {
954  crm_trace("No attributes in %s", parent->name);
955  crm_log_xml_trace(parent, "No attributes for resource op");
956  }
957 
958  crm_log_xml_trace(nvpair_list, "Unpacking");
959 
960  for (pIter = pcmk__xe_first_attr(nvpair_list); pIter != NULL;
961  pIter = pIter->next) {
962 
963  const char *p_name = (const char *)pIter->name;
964  const char *p_value = pcmk__xml_attr_value(pIter);
965 
966  crm_trace("Added %s=%s", p_name, p_value);
967 
968  pcmk__insert_dup(nvpair_hash, p_name, p_value);
969  }
970 
971  for (child = pcmk__xe_first_child(nvpair_list, PCMK__XE_PARAM, NULL, NULL);
972  child != NULL; child = pcmk__xe_next_same(child)) {
973 
974  const char *key = crm_element_value(child, PCMK_XA_NAME);
975  const char *value = crm_element_value(child, PCMK_XA_VALUE);
976 
977  crm_trace("Added %s=%s", key, value);
978  if (key != NULL && value != NULL) {
979  pcmk__insert_dup(nvpair_hash, key, value);
980  }
981  }
982 
983  return nvpair_hash;
984 }
985 
986 void
987 pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value)
988 {
989  crm_xml_add(node, name, pcmk__btoa(value));
990 }
991 
992 int
993 pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
994 {
995  const char *xml_value = NULL;
996  int ret, rc;
997 
998  if (node == NULL) {
999  return ENODATA;
1000  } else if (name == NULL || value == NULL) {
1001  return EINVAL;
1002  }
1003 
1004  xml_value = crm_element_value(node, name);
1005 
1006  if (xml_value == NULL) {
1007  return ENODATA;
1008  }
1009 
1010  rc = crm_str_to_boolean(xml_value, &ret);
1011  if (rc == 1) {
1012  *value = ret;
1013  return pcmk_rc_ok;
1014  } else {
1015  return pcmk_rc_bad_input;
1016  }
1017 }
1018 
1019 bool
1020 pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
1021 {
1022  bool value = false;
1023  int rc;
1024 
1025  rc = pcmk__xe_get_bool_attr(node, name, &value);
1026  return rc == pcmk_rc_ok && value == true;
1027 }
1028 
1029 // Meta-attribute handling
1030 
1042 char *
1043 crm_meta_name(const char *attr_name)
1044 {
1045  char *env_name = NULL;
1046 
1047  pcmk__assert(!pcmk__str_empty(attr_name));
1048 
1049  env_name = crm_strdup_printf(CRM_META "_%s", attr_name);
1050  for (char *c = env_name; *c != '\0'; ++c) {
1051  if (*c == '-') {
1052  *c = '_';
1053  }
1054  }
1055  return env_name;
1056 }
1057 
1070 const char *
1071 crm_meta_value(GHashTable *meta, const char *attr_name)
1072 {
1073  if ((meta != NULL) && (attr_name != NULL)) {
1074  char *key = crm_meta_name(attr_name);
1075  const char *value = g_hash_table_lookup(meta, key);
1076 
1077  free(key);
1078  return value;
1079  }
1080  return NULL;
1081 }
1082 
1083 // Deprecated functions kept only for backward API compatibility
1084 // LCOV_EXCL_START
1085 
1086 #include <crm/common/util_compat.h>
1087 
1088 int
1089 pcmk_scan_nvpair(const char *input, char **name, char **value)
1090 {
1091  return pcmk__scan_nvpair(input, name, value);
1092 }
1093 
1094 char *
1095 pcmk_format_nvpair(const char *name, const char *value,
1096  const char *units)
1097 {
1098  return pcmk__format_nvpair(name, value, units);
1099 }
1100 
1101 char *
1102 pcmk_format_named_time(const char *name, time_t epoch_time)
1103 {
1104  char *now_s = pcmk__epoch2str(&epoch_time, 0);
1105  char *result = crm_strdup_printf("%s=\"%s\"", name, pcmk__s(now_s, ""));
1106 
1107  free(now_s);
1108  return result;
1109 }
1110 
1111 const char *
1112 crm_xml_replace(xmlNode *node, const char *name, const char *value)
1113 {
1114  bool dirty = FALSE;
1115  xmlAttr *attr = NULL;
1116  const char *old_value = NULL;
1117 
1118  CRM_CHECK(node != NULL, return NULL);
1119  CRM_CHECK(name != NULL && name[0] != 0, return NULL);
1120 
1121  old_value = crm_element_value(node, name);
1122 
1123  /* Could be re-setting the same value */
1124  CRM_CHECK(old_value != value, return value);
1125 
1126  if (pcmk__check_acl(node, name, pcmk__xf_acl_write) == FALSE) {
1127  /* Create a fake object linked to doc->_private instead? */
1128  crm_trace("Cannot replace %s=%s to %s", name, value, node->name);
1129  return NULL;
1130 
1131  } else if (old_value && !value) {
1132  pcmk__xe_remove_attr(node, name);
1133  return NULL;
1134  }
1135 
1136  if (pcmk__tracking_xml_changes(node, FALSE)) {
1137  if (!old_value || !value || !strcmp(old_value, value)) {
1138  dirty = TRUE;
1139  }
1140  }
1141 
1142  attr = pcmk__xe_set_attr_force(node, name, value);
1143  if (dirty) {
1145  }
1146  CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
1147  return (char *) attr->children->content;
1148 }
1149 
1150 // LCOV_EXCL_STOP
1151 // 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:92
A dumping ground.
#define PCMK_XE_NVPAIR
Definition: xml_names.h:144
#define PCMK_XA_NAME
Definition: xml_names.h:330
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:583
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:282
G_GNUC_INTERNAL void pcmk__mark_xml_attr_dirty(xmlAttr *a)
Definition: xml_attr.c:75
char * crm_meta_name(const char *attr_name)
Get the environment variable equivalent of a meta-attribute name.
Definition: nvpair.c:1043
GHashTable * xml2list(const xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition: nvpair.c:943
int pcmk__xe_get_flags(const xmlNode *xml, const char *name, uint32_t *dest, uint32_t default_value)
Retrieve a flag group from an XML attribute value.
Definition: nvpair.c:535
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
GSList * pcmk_xml_attrs2nvpairs(const xmlNode *xml)
Create a list of name/value pairs from an XML node&#39;s attributes.
Definition: nvpair.c:159
#define PCMK__XE_ATTRIBUTES
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:228
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:503
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:883
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
Definition: nvpair.c:1020
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:680
int pcmk__xe_get_datetime(const xmlNode *xml, const char *attr, crm_time_t **t)
Definition: nvpair.c:728
#define PCMK__PARSE_INT_DEFAULT
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition: strings.c:96
#define crm_warn(fmt, args...)
Definition: logging.h:394
void hash2metafield(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry, as meta-attribute name.
Definition: nvpair.c:848
void pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
Add XML attributes based on a list of name/value pairs.
Definition: nvpair.c:199
void pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value)
Definition: nvpair.c:987
G_GNUC_INTERNAL void pcmk__xml_new_private_data(xmlNode *xml)
Definition: xml.c:326
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml.c:481
char * pcmk_format_nvpair(const char *name, const char *value, const char *units)
Definition: nvpair.c:1095
#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:820
void pcmk_free_nvpairs(GSList *nvpairs)
Free a list of name/value pairs.
Definition: nvpair.c:103
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:778
Wrappers for and extensions to libxml2.
void pcmk__xe_remove_attr(xmlNode *element, const char *name)
Definition: xml.c:702
char * pcmk_format_named_time(const char *name, time_t epoch_time)
Definition: nvpair.c:1102
#define LLSTRSIZE
Definition: nvpair.c:393
void hash2nvpair(gpointer key, gpointer value, gpointer user_data)
Add XML nvpair element based on hash table entry.
Definition: nvpair.c:918
#define PCMK_XA_ID
Definition: xml_names.h:301
#define PCMK_XA_VALUE
Definition: xml_names.h:442
int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
Definition: nvpair.c:993
#define pcmk__str_copy(str)
GSList * pcmk_sort_nvpairs(GSList *list)
Sort a list of name/value pairs.
Definition: nvpair.c:144
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:1071
#define pcmk__assert(expr)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:458
xmlAttr * pcmk__xe_set_attr_force(xmlNode *node, const char *name, const char *value)
Definition: nvpair.c:290
int crm_str_to_boolean(const char *s, int *ret)
Definition: strings.c:508
const char * crm_xml_replace(xmlNode *node, const char *name, const char *value)
Definition: nvpair.c:1112
#define ENODATA
Definition: portability.h:106
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:695
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
char * pcmk__epoch2str(const time_t *source, uint32_t flags)
Definition: iso8601.c:2147
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:360
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:651
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:313
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:410
#define pcmk_ok
Definition: results.h:65
#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:758
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:434
#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:382
G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
Definition: xml.c:67
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:494
const char * parent
Definition: cib.c:27
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
Definition: xml.c:770
#define pcmk__assert_alloc(nmemb, size)
Definition: internal.h:297
int pcmk_scan_nvpair(const char *input, char **name, char **value)
Definition: nvpair.c:1089
xmlNode * pcmk__xe_next_same(const xmlNode *node)
Definition: xml.c:2130
#define pcmk_err_bad_nvpair
Definition: results.h:94
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition: strings.c:713
int pcmk__scan_nvpair(const char *input, char **name, char **value)
Definition: nvpair.c:219