pacemaker  2.0.3-4b1f869f0f
Scalable High-Availability cluster resource manager
nvpair.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2019 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This source code is licensed under the GNU Lesser General Public License
5  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
6  */
7 
8 #include <crm_internal.h>
9 
10 #include <stdio.h>
11 #include <sys/types.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <glib.h>
15 #include <libxml/tree.h>
16 
17 #include <crm/crm.h>
18 #include <crm/msg_xml.h>
19 #include <crm/common/xml.h>
21 #include "crmcommon_private.h"
22 
23 /*
24  * This file isolates handling of three types of name/value pairs:
25  *
26  * - pcmk_nvpair_t data type
27  * - XML attributes (<TAG ... NAME=VALUE ...>)
28  * - XML nvpair elements (<nvpair id=ID name=NAME value=VALUE>)
29  */
30 
31 // pcmk_nvpair_t handling
32 
44 static pcmk_nvpair_t *
45 pcmk__new_nvpair(const char *name, const char *value)
46 {
47  pcmk_nvpair_t *nvpair = NULL;
48 
49  CRM_ASSERT(name);
50 
51  nvpair = calloc(1, sizeof(pcmk_nvpair_t));
52  CRM_ASSERT(nvpair);
53 
54  nvpair->name = strdup(name);
55  nvpair->value = value? strdup(value) : NULL;
56  return nvpair;
57 }
58 
65 static void
66 pcmk__free_nvpair(gpointer data)
67 {
68  if (data) {
69  pcmk_nvpair_t *nvpair = data;
70 
71  free(nvpair->name);
72  free(nvpair->value);
73  free(nvpair);
74  }
75 }
76 
88 GSList *
89 pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
90 {
91  return g_slist_prepend(nvpairs, pcmk__new_nvpair(name, value));
92 }
93 
99 void
100 pcmk_free_nvpairs(GSList *nvpairs)
101 {
102  g_slist_free_full(nvpairs, pcmk__free_nvpair);
103 }
104 
114 static gint
115 pcmk__compare_nvpair(gconstpointer a, gconstpointer b)
116 {
117  int rc = 0;
118  const pcmk_nvpair_t *pair_a = a;
119  const pcmk_nvpair_t *pair_b = b;
120 
121  CRM_ASSERT(a != NULL);
122  CRM_ASSERT(pair_a->name != NULL);
123 
124  CRM_ASSERT(b != NULL);
125  CRM_ASSERT(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 *
160 {
161  GSList *result = NULL;
162 
163  for (xmlAttrPtr iter = pcmk__first_xml_attr(xml); iter != NULL;
164  iter = iter->next) {
165 
166  result = pcmk_prepend_nvpair(result,
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 
217 int
218 pcmk_scan_nvpair(const char *input, char **name, char **value)
219 {
220 #ifdef SSCANF_HAS_M
221  *name = NULL;
222  *value = NULL;
223  if (sscanf(input, "%m[^=]=%m[^\n]", name, value) <= 0) {
224  return -pcmk_err_bad_nvpair;
225  }
226 #else
227  char *sep = NULL;
228  *name = NULL;
229  *value = NULL;
230 
231  sep = strstr(optarg, "=");
232  if (sep == NULL) {
233  return -pcmk_err_bad_nvpair;
234  }
235 
236  *name = strndup(input, sep-input);
237 
238  if (*name == NULL) {
239  return -ENOMEM;
240  }
241 
242  /* If the last char in optarg is =, the user gave no
243  * value for the option. Leave it as NULL.
244  */
245  if (*(sep+1) != '\0') {
246  *value = strdup(sep+1);
247 
248  if (*value == NULL) {
249  return -ENOMEM;
250  }
251  }
252 #endif
253 
254  if (*name != NULL && *value != NULL) {
255  return 2;
256  } else if (*name != NULL || *value != NULL) {
257  return 1;
258  } else {
259  return -pcmk_err_bad_nvpair;
260  }
261 }
262 
278 char *
279 pcmk_format_nvpair(const char *name, const char *value, const char *units) {
280  return crm_strdup_printf("%s=\"%s%s\"", name, value, units ? units : "");
281 }
282 
294 char *
295 pcmk_format_named_time(const char *name, time_t epoch_time) {
296  const char *now_str = crm_now_string(&epoch_time);
297  return crm_strdup_printf("%s=\"%s\"", name, now_str ? now_str : "");
298 }
299 
300 // XML attribute handling
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 #if XML_PARANOIA_CHECKS
325  {
326  const char *old_value = NULL;
327 
328  old_value = crm_element_value(node, name);
329 
330  /* Could be re-setting the same value */
331  CRM_CHECK(old_value != value,
332  crm_err("Cannot reset %s with crm_xml_add(%s)", name, value);
333  return value);
334  }
335 #endif
336 
337  if (pcmk__tracking_xml_changes(node, FALSE)) {
338  const char *old = crm_element_value(node, name);
339 
340  if (old == NULL || value == NULL || strcmp(old, value) != 0) {
341  dirty = TRUE;
342  }
343  }
344 
345  if (dirty && (pcmk__check_acl(node, name, xpf_acl_create) == FALSE)) {
346  crm_trace("Cannot add %s=%s to %s", name, value, node->name);
347  return NULL;
348  }
349 
350  attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
351  if (dirty) {
353  }
354 
355  CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
356  return (char *)attr->children->content;
357 }
358 
369 const char *
370 crm_xml_replace(xmlNode *node, const char *name, const char *value)
371 {
372  bool dirty = FALSE;
373  xmlAttr *attr = NULL;
374  const char *old_value = NULL;
375 
376  CRM_CHECK(node != NULL, return NULL);
377  CRM_CHECK(name != NULL && name[0] != 0, return NULL);
378 
379  old_value = crm_element_value(node, name);
380 
381  /* Could be re-setting the same value */
382  CRM_CHECK(old_value != value, return value);
383 
384  if (pcmk__check_acl(node, name, xpf_acl_write) == FALSE) {
385  /* Create a fake object linked to doc->_private instead? */
386  crm_trace("Cannot replace %s=%s to %s", name, value, node->name);
387  return NULL;
388 
389  } else if (old_value && !value) {
390  xml_remove_prop(node, name);
391  return NULL;
392  }
393 
394  if (pcmk__tracking_xml_changes(node, FALSE)) {
395  if (!old_value || !value || !strcmp(old_value, value)) {
396  dirty = TRUE;
397  }
398  }
399 
400  attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
401  if (dirty) {
403  }
404  CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
405  return (char *) attr->children->content;
406 }
407 
420 const char *
421 crm_xml_add_int(xmlNode *node, const char *name, int value)
422 {
423  char *number = crm_itoa(value);
424  const char *added = crm_xml_add(node, name, number);
425 
426  free(number);
427  return added;
428 }
429 
442 const char *
443 crm_xml_add_ms(xmlNode *node, const char *name, guint ms)
444 {
445  char *number = crm_strdup_printf("%u", ms);
446  const char *added = crm_xml_add(node, name, number);
447 
448  free(number);
449  return added;
450 }
451 
452 // Maximum size of null-terminated string representation of 64-bit integer
453 // -9223372036854775808
454 #define LLSTRSIZE 21
455 
470 const char *
471 crm_xml_add_ll(xmlNode *xml, const char *name, long long value)
472 {
473  char s[LLSTRSIZE] = { '\0', };
474 
475  if (snprintf(s, LLSTRSIZE, "%lld", (long long) value) == LLSTRSIZE) {
476  return NULL;
477  }
478  return crm_xml_add(xml, name, s);
479 }
480 
494 const char *
495 crm_xml_add_timeval(xmlNode *xml, const char *name_sec, const char *name_usec,
496  const struct timeval *value)
497 {
498  const char *added = NULL;
499 
500  if (xml && name_sec && value) {
501  added = crm_xml_add_ll(xml, name_sec, (long long) value->tv_sec);
502  if (added && name_usec) {
503  // Any error is ignored (we successfully added seconds)
504  crm_xml_add_ll(xml, name_usec, (long long) value->tv_usec);
505  }
506  }
507  return added;
508 }
509 
518 const char *
519 crm_element_value(const xmlNode *data, const char *name)
520 {
521  xmlAttr *attr = NULL;
522 
523  if (data == NULL) {
524  crm_err("Couldn't find %s in NULL", name ? name : "<null>");
525  CRM_LOG_ASSERT(data != NULL);
526  return NULL;
527 
528  } else if (name == NULL) {
529  crm_err("Couldn't find NULL in %s", crm_element_name(data));
530  return NULL;
531  }
532 
533  /* The first argument to xmlHasProp() has always been const,
534  * but libxml2 <2.9.2 didn't declare that, so cast it
535  */
536  attr = xmlHasProp((xmlNode *) data, (pcmkXmlStr) name);
537  if (!attr || !attr->children) {
538  return NULL;
539  }
540  return (const char *) attr->children->content;
541 }
542 
554 int
555 crm_element_value_int(const xmlNode *data, const char *name, int *dest)
556 {
557  const char *value = NULL;
558 
559  CRM_CHECK(dest != NULL, return -1);
560  value = crm_element_value(data, name);
561  if (value) {
562  errno = 0;
563  *dest = crm_parse_int(value, NULL);
564  if (errno == 0) {
565  return 0;
566  }
567  }
568  return -1;
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) {
590  errno = 0;
591  *dest = crm_int_helper(value, NULL);
592  if (errno == 0) {
593  return 0;
594  }
595  }
596  return -1;
597 }
598 
610 int
611 crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
612 {
613  const char *value = NULL;
614 
615  CRM_CHECK(dest != NULL, return -1);
616  value = crm_element_value(data, name);
617  *dest = crm_parse_ms(value);
618  return errno? -1 : 0;
619 }
620 
632 int
633 crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
634 {
635  long long value_ll = 0;
636 
637  if (crm_element_value_ll(xml, name, &value_ll) < 0) {
638  return -1;
639  }
640 
641  /* Unfortunately, we can't do any bounds checking, since time_t has neither
642  * standardized bounds nor constants defined for them.
643  */
644  *dest = (time_t) value_ll;
645  return pcmk_ok;
646 }
647 
661 int
662 crm_element_value_timeval(const xmlNode *xml, const char *name_sec,
663  const char *name_usec, struct timeval *dest)
664 {
665  long long value_i = 0;
666 
667  CRM_CHECK(dest != NULL, return -EINVAL);
668  dest->tv_sec = 0;
669  dest->tv_usec = 0;
670 
671  if (xml == NULL) {
672  return pcmk_ok;
673  }
674 
675  /* Unfortunately, we can't do any bounds checking, since there are no
676  * constants provided for the bounds of time_t and suseconds_t, and
677  * calculating them isn't worth the effort. If there are XML values
678  * beyond the native sizes, there will probably be worse problems anyway.
679  */
680 
681  // Parse seconds
682  errno = 0;
683  if (crm_element_value_ll(xml, name_sec, &value_i) < 0) {
684  return -errno;
685  }
686  dest->tv_sec = (time_t) value_i;
687 
688  // Parse microseconds
689  if (crm_element_value_ll(xml, name_usec, &value_i) < 0) {
690  return -errno;
691  }
692  dest->tv_usec = (suseconds_t) value_i;
693 
694  return pcmk_ok;
695 }
696 
708 char *
709 crm_element_value_copy(const xmlNode *data, const char *name)
710 {
711  char *value_copy = NULL;
712  const char *value = crm_element_value(data, name);
713 
714  if (value != NULL) {
715  value_copy = strdup(value);
716  }
717  return value_copy;
718 }
719 
733 void
734 hash2smartfield(gpointer key, gpointer value, gpointer user_data)
735 {
736  const char *name = key;
737  const char *s_value = value;
738 
739  xmlNode *xml_node = user_data;
740 
741  if (isdigit(name[0])) {
742  xmlNode *tmp = create_xml_node(xml_node, XML_TAG_PARAM);
743 
744  crm_xml_add(tmp, XML_NVPAIR_ATTR_NAME, name);
745  crm_xml_add(tmp, XML_NVPAIR_ATTR_VALUE, s_value);
746 
747  } else if (crm_element_value(xml_node, name) == NULL) {
748  crm_xml_add(xml_node, name, s_value);
749  crm_trace("dumped: %s=%s", name, s_value);
750 
751  } else {
752  crm_trace("duplicate: %s=%s", name, s_value);
753  }
754 }
755 
767 void
768 hash2field(gpointer key, gpointer value, gpointer user_data)
769 {
770  const char *name = key;
771  const char *s_value = value;
772 
773  xmlNode *xml_node = user_data;
774 
775  if (crm_element_value(xml_node, name) == NULL) {
776  crm_xml_add(xml_node, name, s_value);
777 
778  } else {
779  crm_trace("duplicate: %s=%s", name, s_value);
780  }
781 }
782 
795 void
796 hash2metafield(gpointer key, gpointer value, gpointer user_data)
797 {
798  char *crm_name = NULL;
799 
800  if (key == NULL || value == NULL) {
801  return;
802  }
803 
804  /* Filter out cluster-generated attributes that contain a '#' or ':'
805  * (like fail-count and last-failure).
806  */
807  for (crm_name = key; *crm_name; ++crm_name) {
808  if ((*crm_name == '#') || (*crm_name == ':')) {
809  return;
810  }
811  }
812 
813  crm_name = crm_meta_name(key);
814  hash2field(crm_name, value, user_data);
815  free(crm_name);
816 }
817 
818 // nvpair handling
819 
830 xmlNode *
831 crm_create_nvpair_xml(xmlNode *parent, const char *id, const char *name,
832  const char *value)
833 {
834  xmlNode *nvp;
835 
836  /* id can be NULL so we auto-generate one, and name can be NULL if this
837  * will be used to delete a name/value pair by ID, but both can't be NULL
838  */
839  CRM_CHECK(id || name, return NULL);
840 
841  nvp = create_xml_node(parent, XML_CIB_TAG_NVPAIR);
842  CRM_CHECK(nvp, return NULL);
843 
844  if (id) {
845  crm_xml_add(nvp, XML_ATTR_ID, id);
846  } else {
847  const char *parent_id = ID(parent);
848 
849  crm_xml_set_id(nvp, "%s-%s",
850  (parent_id? parent_id : XML_CIB_TAG_NVPAIR), name);
851  }
852  crm_xml_add(nvp, XML_NVPAIR_ATTR_NAME, name);
853  crm_xml_add(nvp, XML_NVPAIR_ATTR_VALUE, value);
854  return nvp;
855 }
856 
868 void
869 hash2nvpair(gpointer key, gpointer value, gpointer user_data)
870 {
871  const char *name = key;
872  const char *s_value = value;
873  xmlNode *xml_node = user_data;
874 
875  crm_create_nvpair_xml(xml_node, name, name, s_value);
876  crm_trace("dumped: name=%s value=%s", name, s_value);
877 }
878 
893 GHashTable *
894 xml2list(xmlNode *parent)
895 {
896  xmlNode *child = NULL;
897  xmlAttrPtr pIter = NULL;
898  xmlNode *nvpair_list = NULL;
899  GHashTable *nvpair_hash = crm_str_table_new();
900 
901  CRM_CHECK(parent != NULL, return nvpair_hash);
902 
903  nvpair_list = find_xml_node(parent, XML_TAG_ATTRS, FALSE);
904  if (nvpair_list == NULL) {
905  crm_trace("No attributes in %s", crm_element_name(parent));
906  crm_log_xml_trace(parent, "No attributes for resource op");
907  }
908 
909  crm_log_xml_trace(nvpair_list, "Unpacking");
910 
911  for (pIter = pcmk__first_xml_attr(nvpair_list); pIter != NULL;
912  pIter = pIter->next) {
913 
914  const char *p_name = (const char *)pIter->name;
915  const char *p_value = pcmk__xml_attr_value(pIter);
916 
917  crm_trace("Added %s=%s", p_name, p_value);
918 
919  g_hash_table_insert(nvpair_hash, strdup(p_name), strdup(p_value));
920  }
921 
922  for (child = __xml_first_child(nvpair_list); child != NULL;
923  child = __xml_next(child)) {
924 
925  if (strcmp((const char *)child->name, XML_TAG_PARAM) == 0) {
926  const char *key = crm_element_value(child, XML_NVPAIR_ATTR_NAME);
927  const char *value = crm_element_value(child, XML_NVPAIR_ATTR_VALUE);
928 
929  crm_trace("Added %s=%s", key, value);
930  if (key != NULL && value != NULL) {
931  g_hash_table_insert(nvpair_hash, strdup(key), strdup(value));
932  }
933  }
934  }
935 
936  return nvpair_hash;
937 }
crm_element_value_ms
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
Definition: nvpair.c:611
msg_xml.h
xpf_acl_write
@ xpf_acl_write
Definition: crmcommon_private.h:31
data
char data[0]
Definition: internal.h:12
crm_element_value_epoch
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:633
create_xml_node
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:1970
crm_xml_add
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
crm_element_value_copy
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition: nvpair.c:709
crm_element_value_timeval
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:662
LLSTRSIZE
#define LLSTRSIZE
Definition: nvpair.c:454
CRM_CHECK
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:157
crm_parse_ms
guint crm_parse_ms(const char *text)
Definition: strings.c:147
crm_err
#define crm_err(fmt, args...)
Definition: logging.h:241
crm_trace
#define crm_trace(fmt, args...)
Definition: logging.h:247
XML_NVPAIR_ATTR_VALUE
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:340
pcmk_sort_nvpairs
GSList * pcmk_sort_nvpairs(GSList *list)
Sort a list of name/value pairs.
Definition: nvpair.c:144
pcmk_format_nvpair
char * pcmk_format_nvpair(const char *name, const char *value, const char *units)
Definition: nvpair.c:279
pcmk_scan_nvpair
int pcmk_scan_nvpair(const char *input, char **name, char **value)
Extract the name and value from an input string formatted as "name=value". If unable to extract them,...
Definition: nvpair.c:218
crm_xml_add_int
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:421
xml.h
Wrappers for and extensions to libxml2.
hash2field
void hash2field(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry.
Definition: nvpair.c:768
pcmk_free_nvpairs
void pcmk_free_nvpairs(GSList *nvpairs)
Free a list of name/value pairs.
Definition: nvpair.c:100
XML_ATTR_ID
#define XML_ATTR_ID
Definition: msg_xml.h:96
ID
#define ID(x)
Definition: msg_xml.h:415
hash2nvpair
void hash2nvpair(gpointer key, gpointer value, gpointer user_data)
Add XML nvpair element based on hash table entry.
Definition: nvpair.c:869
crm_xml_set_id
void crm_xml_set_id(xmlNode *xml, const char *format,...) __attribute__((__format__(__printf__
CRM_LOG_ASSERT
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:143
crm_strdup_printf
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
crmcommon_private.h
XML_TAG_ATTRS
#define XML_TAG_ATTRS
Definition: msg_xml.h:165
crm_xml_replace
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:370
pcmk__tracking_xml_changes
G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
Definition: xml.c:74
xml2list
GHashTable * xml2list(xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition: nvpair.c:894
crm_log_xml_trace
#define crm_log_xml_trace(xml, text)
Definition: logging.h:255
crm_now_string
const char * crm_now_string(time_t *when)
Definition: iso8601.c:1701
crm_xml_add_ll
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:471
crm_parse_int
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
Definition: strings.c:114
pcmk_format_named_time
char * pcmk_format_named_time(const char *name, time_t epoch_time)
Definition: nvpair.c:295
crm_xml_add_timeval
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:495
pcmkXmlStr
const typedef xmlChar * pcmkXmlStr
Definition: xml.h:51
xpf_acl_create
@ xpf_acl_create
Definition: crmcommon_private.h:34
pcmk_xml_attrs2nvpairs
GSList * pcmk_xml_attrs2nvpairs(xmlNode *xml)
Create a list of name/value pairs from an XML node's attributes.
Definition: nvpair.c:159
crm_xml_add_ms
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:443
crm_element_value_int
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:555
xml_remove_prop
void xml_remove_prop(xmlNode *obj, const char *name)
Definition: xml.c:3325
pcmk_prepend_nvpair
GSList * pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
Prepend a name/value pair to a list.
Definition: nvpair.c:89
hash2smartfield
void hash2smartfield(gpointer key, gpointer value, gpointer user_data)
Add hash table entry to XML as (possibly legacy) name/value.
Definition: nvpair.c:734
pcmk__mark_xml_attr_dirty
G_GNUC_INTERNAL void pcmk__mark_xml_attr_dirty(xmlAttr *a)
Definition: xml.c:193
pcmk_err_bad_nvpair
#define pcmk_err_bad_nvpair
Definition: results.h:80
crm_element_value_ll
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
CRM_ASSERT
#define CRM_ASSERT(expr)
Definition: results.h:42
find_xml_node
xmlNode * find_xml_node(xmlNode *cib, const char *node_path, gboolean must_find)
Definition: xml.c:1758
XML_TAG_PARAM
#define XML_TAG_PARAM
Definition: msg_xml.h:170
pcmk_nvpair_s
Definition: nvpair.h:28
XML_CIB_TAG_NVPAIR
#define XML_CIB_TAG_NVPAIR
Definition: msg_xml.h:160
crm_element_value
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:519
iso8601_internal.h
crm_create_nvpair_xml
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:831
pcmk__check_acl
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition: acl.c:635
strndup
char * strndup(const char *str, size_t len)
hash2metafield
void hash2metafield(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry, as meta-attribute name.
Definition: nvpair.c:796
crm_internal.h
pcmk_nvpairs2xml_attrs
void pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
Add XML attributes based on a list of name/value pairs.
Definition: nvpair.c:199
pcmk_nvpair_s::value
char * value
Definition: nvpair.h:30
crm.h
A dumping ground.
crm_meta_name
char * crm_meta_name(const char *field)
Definition: utils.c:739
XML_NVPAIR_ATTR_NAME
#define XML_NVPAIR_ATTR_NAME
Definition: msg_xml.h:339
pcmk_nvpair_s::name
char * name
Definition: nvpair.h:29
crm_int_helper
long long crm_int_helper(const char *text, char **end_text)
Definition: strings.c:34
pcmk_ok
#define pcmk_ok
Definition: results.h:57