pacemaker  2.1.0-7c3f660
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-2021 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>
24 #include "crmcommon_private.h"
25 
26 /*
27  * This file isolates handling of three types 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  */
33 
34 // pcmk_nvpair_t handling
35 
47 static pcmk_nvpair_t *
48 pcmk__new_nvpair(const char *name, const char *value)
49 {
50  pcmk_nvpair_t *nvpair = NULL;
51 
52  CRM_ASSERT(name);
53 
54  nvpair = calloc(1, sizeof(pcmk_nvpair_t));
55  CRM_ASSERT(nvpair);
56 
57  nvpair->name = strdup(name);
58  nvpair->value = value? strdup(value) : NULL;
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  CRM_ASSERT(a != NULL);
125  CRM_ASSERT(pair_a->name != NULL);
126 
127  CRM_ASSERT(b != NULL);
128  CRM_ASSERT(pair_b->name != NULL);
129 
130  rc = strcmp(pair_a->name, pair_b->name);
131  if (rc < 0) {
132  return -1;
133  } else if (rc > 0) {
134  return 1;
135  }
136  return 0;
137 }
138 
146 GSList *
147 pcmk_sort_nvpairs(GSList *list)
148 {
149  return g_slist_sort(list, pcmk__compare_nvpair);
150 }
151 
161 GSList *
163 {
164  GSList *result = NULL;
165 
166  for (xmlAttrPtr iter = pcmk__xe_first_attr(xml); iter != NULL;
167  iter = iter->next) {
168 
169  result = pcmk_prepend_nvpair(result,
170  (const char *) iter->name,
171  (const char *) pcmk__xml_attr_value(iter));
172  }
173  return result;
174 }
175 
186 static void
187 pcmk__nvpair_add_xml_attr(gpointer data, gpointer user_data)
188 {
189  pcmk_nvpair_t *pair = data;
190  xmlNode *parent = user_data;
191 
192  crm_xml_add(parent, pair->name, pair->value);
193 }
194 
201 void
202 pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
203 {
204  g_slist_foreach(list, pcmk__nvpair_add_xml_attr, xml);
205 }
206 
207 // convenience function for name=value strings
208 
221 int
222 pcmk__scan_nvpair(const char *input, char **name, char **value)
223 {
224 #ifdef SSCANF_HAS_M
225  *name = NULL;
226  *value = NULL;
227  if (sscanf(input, "%m[^=]=%m[^\n]", name, value) <= 0) {
228  return -pcmk_err_bad_nvpair;
229  }
230 #else
231  char *sep = NULL;
232  *name = NULL;
233  *value = NULL;
234 
235  sep = strstr(optarg, "=");
236  if (sep == NULL) {
237  return -pcmk_err_bad_nvpair;
238  }
239 
240  *name = strndup(input, sep-input);
241 
242  if (*name == NULL) {
243  return -ENOMEM;
244  }
245 
246  /* If the last char in optarg is =, the user gave no
247  * value for the option. Leave it as NULL.
248  */
249  if (*(sep+1) != '\0') {
250  *value = strdup(sep+1);
251 
252  if (*value == NULL) {
253  return -ENOMEM;
254  }
255  }
256 #endif
257 
258  if (*name != NULL && *value != NULL) {
259  return 2;
260  } else if (*name != NULL || *value != NULL) {
261  return 1;
262  } else {
263  return -pcmk_err_bad_nvpair;
264  }
265 }
266 
284 char *
285 pcmk__format_nvpair(const char *name, const char *value, const char *units)
286 {
287  return crm_strdup_printf("%s=\"%s%s\"", name, value, units ? units : "");
288 }
289 
303 char *
304 pcmk__format_named_time(const char *name, time_t epoch_time)
305 {
306  const char *now_str = pcmk__epoch2str(&epoch_time);
307 
308  return crm_strdup_printf("%s=\"%s\"", name, now_str ? now_str : "");
309 }
310 
311 // XML attribute handling
312 
323 const char *
324 crm_xml_add(xmlNode *node, const char *name, const char *value)
325 {
326  bool dirty = FALSE;
327  xmlAttr *attr = NULL;
328 
329  CRM_CHECK(node != NULL, return NULL);
330  CRM_CHECK(name != NULL, return NULL);
331 
332  if (value == NULL) {
333  return NULL;
334  }
335 #if XML_PARANOIA_CHECKS
336  {
337  const char *old_value = NULL;
338 
339  old_value = crm_element_value(node, name);
340 
341  /* Could be re-setting the same value */
342  CRM_CHECK(old_value != value,
343  crm_err("Cannot reset %s with crm_xml_add(%s)", name, value);
344  return value);
345  }
346 #endif
347 
348  if (pcmk__tracking_xml_changes(node, FALSE)) {
349  const char *old = crm_element_value(node, name);
350 
351  if (old == NULL || value == NULL || strcmp(old, value) != 0) {
352  dirty = TRUE;
353  }
354  }
355 
356  if (dirty && (pcmk__check_acl(node, name, xpf_acl_create) == FALSE)) {
357  crm_trace("Cannot add %s=%s to %s", name, value, node->name);
358  return NULL;
359  }
360 
361  attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
362  if (dirty) {
364  }
365 
366  CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
367  return (char *)attr->children->content;
368 }
369 
380 const char *
381 crm_xml_replace(xmlNode *node, const char *name, const char *value)
382 {
383  bool dirty = FALSE;
384  xmlAttr *attr = NULL;
385  const char *old_value = NULL;
386 
387  CRM_CHECK(node != NULL, return NULL);
388  CRM_CHECK(name != NULL && name[0] != 0, return NULL);
389 
390  old_value = crm_element_value(node, name);
391 
392  /* Could be re-setting the same value */
393  CRM_CHECK(old_value != value, return value);
394 
395  if (pcmk__check_acl(node, name, xpf_acl_write) == FALSE) {
396  /* Create a fake object linked to doc->_private instead? */
397  crm_trace("Cannot replace %s=%s to %s", name, value, node->name);
398  return NULL;
399 
400  } else if (old_value && !value) {
401  xml_remove_prop(node, name);
402  return NULL;
403  }
404 
405  if (pcmk__tracking_xml_changes(node, FALSE)) {
406  if (!old_value || !value || !strcmp(old_value, value)) {
407  dirty = TRUE;
408  }
409  }
410 
411  attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
412  if (dirty) {
414  }
415  CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
416  return (char *) attr->children->content;
417 }
418 
431 const char *
432 crm_xml_add_int(xmlNode *node, const char *name, int value)
433 {
434  char *number = pcmk__itoa(value);
435  const char *added = crm_xml_add(node, name, number);
436 
437  free(number);
438  return added;
439 }
440 
453 const char *
454 crm_xml_add_ms(xmlNode *node, const char *name, guint ms)
455 {
456  char *number = crm_strdup_printf("%u", ms);
457  const char *added = crm_xml_add(node, name, number);
458 
459  free(number);
460  return added;
461 }
462 
463 // Maximum size of null-terminated string representation of 64-bit integer
464 // -9223372036854775808
465 #define LLSTRSIZE 21
466 
481 const char *
482 crm_xml_add_ll(xmlNode *xml, const char *name, long long value)
483 {
484  char s[LLSTRSIZE] = { '\0', };
485 
486  if (snprintf(s, LLSTRSIZE, "%lld", (long long) value) == LLSTRSIZE) {
487  return NULL;
488  }
489  return crm_xml_add(xml, name, s);
490 }
491 
505 const char *
506 crm_xml_add_timeval(xmlNode *xml, const char *name_sec, const char *name_usec,
507  const struct timeval *value)
508 {
509  const char *added = NULL;
510 
511  if (xml && name_sec && value) {
512  added = crm_xml_add_ll(xml, name_sec, (long long) value->tv_sec);
513  if (added && name_usec) {
514  // Any error is ignored (we successfully added seconds)
515  crm_xml_add_ll(xml, name_usec, (long long) value->tv_usec);
516  }
517  }
518  return added;
519 }
520 
529 const char *
530 crm_element_value(const xmlNode *data, const char *name)
531 {
532  xmlAttr *attr = NULL;
533 
534  if (data == NULL) {
535  crm_err("Couldn't find %s in NULL", name ? name : "<null>");
536  CRM_LOG_ASSERT(data != NULL);
537  return NULL;
538 
539  } else if (name == NULL) {
540  crm_err("Couldn't find NULL in %s", crm_element_name(data));
541  return NULL;
542  }
543 
544  /* The first argument to xmlHasProp() has always been const,
545  * but libxml2 <2.9.2 didn't declare that, so cast it
546  */
547  attr = xmlHasProp((xmlNode *) data, (pcmkXmlStr) name);
548  if (!attr || !attr->children) {
549  return NULL;
550  }
551  return (const char *) attr->children->content;
552 }
553 
565 int
566 crm_element_value_int(const xmlNode *data, const char *name, int *dest)
567 {
568  const char *value = NULL;
569 
570  CRM_CHECK(dest != NULL, return -1);
571  value = crm_element_value(data, name);
572  if (value) {
573  long long value_ll;
574 
575  if ((pcmk__scan_ll(value, &value_ll, 0LL) != pcmk_rc_ok)
576  || (value_ll < INT_MIN) || (value_ll > INT_MAX)) {
577  *dest = PCMK__PARSE_INT_DEFAULT;
578  } else {
579  *dest = (int) value_ll;
580  return 0;
581  }
582  }
583  return -1;
584 }
585 
597 int
598 crm_element_value_ll(const xmlNode *data, const char *name, long long *dest)
599 {
600  const char *value = NULL;
601 
602  CRM_CHECK(dest != NULL, return -1);
603  value = crm_element_value(data, name);
604  if ((value != NULL)
605  && (pcmk__scan_ll(value, dest, PCMK__PARSE_INT_DEFAULT) == pcmk_rc_ok)) {
606  return 0;
607  }
608  return -1;
609 }
610 
622 int
623 crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
624 {
625  const char *value = NULL;
626  long long value_ll;
627 
628  CRM_CHECK(dest != NULL, return -1);
629  *dest = 0;
630  value = crm_element_value(data, name);
631  if ((pcmk__scan_ll(value, &value_ll, 0LL) != pcmk_rc_ok)
632  || (value_ll < 0) || (value_ll > G_MAXUINT)) {
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 
726 char *
727 crm_element_value_copy(const xmlNode *data, const char *name)
728 {
729  char *value_copy = NULL;
730  const char *value = crm_element_value(data, name);
731 
732  if (value != NULL) {
733  value_copy = strdup(value);
734  }
735  return value_copy;
736 }
737 
751 void
752 hash2smartfield(gpointer key, gpointer value, gpointer user_data)
753 {
754  const char *name = key;
755  const char *s_value = value;
756 
757  xmlNode *xml_node = user_data;
758 
759  if (isdigit(name[0])) {
760  xmlNode *tmp = create_xml_node(xml_node, XML_TAG_PARAM);
761 
762  crm_xml_add(tmp, XML_NVPAIR_ATTR_NAME, name);
763  crm_xml_add(tmp, XML_NVPAIR_ATTR_VALUE, s_value);
764 
765  } else if (crm_element_value(xml_node, name) == NULL) {
766  crm_xml_add(xml_node, name, s_value);
767  crm_trace("dumped: %s=%s", name, s_value);
768 
769  } else {
770  crm_trace("duplicate: %s=%s", name, s_value);
771  }
772 }
773 
785 void
786 hash2field(gpointer key, gpointer value, gpointer user_data)
787 {
788  const char *name = key;
789  const char *s_value = value;
790 
791  xmlNode *xml_node = user_data;
792 
793  if (crm_element_value(xml_node, name) == NULL) {
794  crm_xml_add(xml_node, name, s_value);
795 
796  } else {
797  crm_trace("duplicate: %s=%s", name, s_value);
798  }
799 }
800 
813 void
814 hash2metafield(gpointer key, gpointer value, gpointer user_data)
815 {
816  char *crm_name = NULL;
817 
818  if (key == NULL || value == NULL) {
819  return;
820  }
821 
822  /* Filter out cluster-generated attributes that contain a '#' or ':'
823  * (like fail-count and last-failure).
824  */
825  for (crm_name = key; *crm_name; ++crm_name) {
826  if ((*crm_name == '#') || (*crm_name == ':')) {
827  return;
828  }
829  }
830 
831  crm_name = crm_meta_name(key);
832  hash2field(crm_name, value, user_data);
833  free(crm_name);
834 }
835 
836 // nvpair handling
837 
848 xmlNode *
849 crm_create_nvpair_xml(xmlNode *parent, const char *id, const char *name,
850  const char *value)
851 {
852  xmlNode *nvp;
853 
854  /* id can be NULL so we auto-generate one, and name can be NULL if this
855  * will be used to delete a name/value pair by ID, but both can't be NULL
856  */
857  CRM_CHECK(id || name, return NULL);
858 
859  nvp = create_xml_node(parent, XML_CIB_TAG_NVPAIR);
860  CRM_CHECK(nvp, return NULL);
861 
862  if (id) {
863  crm_xml_add(nvp, XML_ATTR_ID, id);
864  } else {
865  const char *parent_id = ID(parent);
866 
867  crm_xml_set_id(nvp, "%s-%s",
868  (parent_id? parent_id : XML_CIB_TAG_NVPAIR), name);
869  }
870  crm_xml_add(nvp, XML_NVPAIR_ATTR_NAME, name);
871  crm_xml_add(nvp, XML_NVPAIR_ATTR_VALUE, value);
872  return nvp;
873 }
874 
886 void
887 hash2nvpair(gpointer key, gpointer value, gpointer user_data)
888 {
889  const char *name = key;
890  const char *s_value = value;
891  xmlNode *xml_node = user_data;
892 
893  crm_create_nvpair_xml(xml_node, name, name, s_value);
894  crm_trace("dumped: name=%s value=%s", name, s_value);
895 }
896 
911 GHashTable *
912 xml2list(xmlNode *parent)
913 {
914  xmlNode *child = NULL;
915  xmlAttrPtr pIter = NULL;
916  xmlNode *nvpair_list = NULL;
917  GHashTable *nvpair_hash = pcmk__strkey_table(free, free);
918 
919  CRM_CHECK(parent != NULL, return nvpair_hash);
920 
921  nvpair_list = find_xml_node(parent, XML_TAG_ATTRS, FALSE);
922  if (nvpair_list == NULL) {
923  crm_trace("No attributes in %s", crm_element_name(parent));
924  crm_log_xml_trace(parent, "No attributes for resource op");
925  }
926 
927  crm_log_xml_trace(nvpair_list, "Unpacking");
928 
929  for (pIter = pcmk__xe_first_attr(nvpair_list); pIter != NULL;
930  pIter = pIter->next) {
931 
932  const char *p_name = (const char *)pIter->name;
933  const char *p_value = pcmk__xml_attr_value(pIter);
934 
935  crm_trace("Added %s=%s", p_name, p_value);
936 
937  g_hash_table_insert(nvpair_hash, strdup(p_name), strdup(p_value));
938  }
939 
940  for (child = pcmk__xml_first_child(nvpair_list); child != NULL;
941  child = pcmk__xml_next(child)) {
942 
943  if (strcmp((const char *)child->name, XML_TAG_PARAM) == 0) {
944  const char *key = crm_element_value(child, XML_NVPAIR_ATTR_NAME);
945  const char *value = crm_element_value(child, XML_NVPAIR_ATTR_VALUE);
946 
947  crm_trace("Added %s=%s", key, value);
948  if (key != NULL && value != NULL) {
949  g_hash_table_insert(nvpair_hash, strdup(key), strdup(value));
950  }
951  }
952  }
953 
954  return nvpair_hash;
955 }
956 
957 // Deprecated functions kept only for backward API compatibility
958 
959 #include <crm/common/util_compat.h>
960 
961 int
962 pcmk_scan_nvpair(const char *input, char **name, char **value)
963 {
964  return pcmk__scan_nvpair(input, name, value);
965 }
966 
967 char *
968 pcmk_format_nvpair(const char *name, const char *value,
969  const char *units)
970 {
971  return pcmk__format_nvpair(name, value, units);
972 }
973 
974 char *
975 pcmk_format_named_time(const char *name, time_t epoch_time)
976 {
977  return pcmk__format_named_time(name, epoch_time);
978 }
979 
980 // End deprecated API
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:218
xmlNode * find_xml_node(xmlNode *cib, const char *node_path, gboolean must_find)
Definition: xml.c:446
A dumping ground.
GSList * pcmk_sort_nvpairs(GSList *list)
Sort a list of name/value pairs.
Definition: nvpair.c:147
char * name
Definition: nvpair.h:29
char data[0]
Definition: cpg.c:55
void hash2field(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry.
Definition: nvpair.c:786
void pcmk_free_nvpairs(GSList *nvpairs)
Free a list of name/value pairs.
Definition: nvpair.c:103
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:454
char * value
Definition: nvpair.h:30
G_GNUC_INTERNAL void pcmk__mark_xml_attr_dirty(xmlAttr *a)
Definition: xml.c:174
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:432
#define XML_TAG_ATTRS
Definition: msg_xml.h:205
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:324
#define XML_NVPAIR_ATTR_NAME
Definition: msg_xml.h:377
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:202
GSList * pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
Prepend a name/value pair to a list.
Definition: nvpair.c:92
#define XML_CIB_TAG_NVPAIR
Definition: msg_xml.h:200
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:598
GSList * pcmk_xml_attrs2nvpairs(xmlNode *xml)
Create a list of name/value pairs from an XML node&#39;s attributes.
Definition: nvpair.c:162
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:566
char * pcmk__format_named_time(const char *name, time_t epoch_time)
Definition: nvpair.c:304
void hash2smartfield(gpointer key, gpointer value, gpointer user_data)
Add hash table entry to XML as (possibly legacy) name/value.
Definition: nvpair.c:752
char * strndup(const char *str, size_t len)
char * crm_meta_name(const char *field)
Definition: utils.c:511
void hash2nvpair(gpointer key, gpointer value, gpointer user_data)
Add XML nvpair element based on hash table entry.
Definition: nvpair.c:887
char * pcmk__format_nvpair(const char *name, const char *value, const char *units)
Definition: nvpair.c:285
#define PCMK__PARSE_INT_DEFAULT
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition: strings.c:97
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition: acl.c:599
int rc
Definition: pcmk_fence.c:35
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
Definition: nvpair.c:623
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition: nvpair.c:727
#define XML_ATTR_ID
Definition: msg_xml.h:129
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:530
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:680
char * pcmk_format_nvpair(const char *name, const char *value, const char *units)
Definition: nvpair.c:968
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:381
#define crm_trace(fmt, args...)
Definition: logging.h:356
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
int pcmk__scan_nvpair(const char *input, char **name, char **value)
Definition: nvpair.c:222
void crm_xml_set_id(xmlNode *xml, const char *format,...) G_GNUC_PRINTF(2
Wrappers for and extensions to libxml2.
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:696
#define LLSTRSIZE
Definition: nvpair.c:465
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
int pcmk_scan_nvpair(const char *input, char **name, char **value)
Definition: nvpair.c:962
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:506
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:482
const xmlChar * pcmkXmlStr
Definition: xml.h:51
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:610
#define crm_err(fmt, args...)
Definition: logging.h:350
#define CRM_ASSERT(expr)
Definition: results.h:42
void xml_remove_prop(xmlNode *obj, const char *name)
Definition: xml.c:2036
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:378
void hash2metafield(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry, as meta-attribute name.
Definition: nvpair.c:814
GHashTable * xml2list(xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition: nvpair.c:912
void pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
Add XML attributes based on a list of name/value pairs.
Definition: nvpair.c:202
#define pcmk_ok
Definition: results.h:67
#define crm_log_xml_trace(xml, text)
Definition: logging.h:364
G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
Definition: xml.c:52
char * pcmk_format_named_time(const char *name, time_t epoch_time)
Definition: nvpair.c:975
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:849
#define ID(x)
Definition: msg_xml.h:456
char * name
Definition: pcmk_fence.c:31
#define pcmk_err_bad_nvpair
Definition: results.h:90
#define XML_TAG_PARAM
Definition: msg_xml.h:210
Deprecated Pacemaker utilities.