pacemaker 2.1.4-dc6eb4362e
Scalable High-Availability cluster resource manager
nvpair.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2022 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU Lesser General Public License
7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8 */
9
10#include <crm_internal.h>
11
12#include <stdio.h>
13#include <sys/types.h>
14#include <string.h>
15#include <ctype.h>
16#include <glib.h>
17#include <libxml/tree.h>
18
19#include <crm/crm.h>
20#include <crm/msg_xml.h>
21#include <crm/common/xml.h>
23#include "crmcommon_private.h"
24
25/*
26 * This file isolates handling of three types of name/value pairs:
27 *
28 * - pcmk_nvpair_t data type
29 * - XML attributes (<TAG ... NAME=VALUE ...>)
30 * - XML nvpair elements (<nvpair id=ID name=NAME value=VALUE>)
31 */
32
33// pcmk_nvpair_t handling
34
46static pcmk_nvpair_t *
47pcmk__new_nvpair(const char *name, const char *value)
48{
49 pcmk_nvpair_t *nvpair = NULL;
50
52
53 nvpair = calloc(1, sizeof(pcmk_nvpair_t));
54 CRM_ASSERT(nvpair);
55
56 pcmk__str_update(&nvpair->name, name);
57 pcmk__str_update(&nvpair->value, value);
58 return nvpair;
59}
60
67static void
68pcmk__free_nvpair(gpointer data)
69{
70 if (data) {
71 pcmk_nvpair_t *nvpair = data;
72
73 free(nvpair->name);
74 free(nvpair->value);
75 free(nvpair);
76 }
77}
78
90GSList *
91pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
92{
93 return g_slist_prepend(nvpairs, pcmk__new_nvpair(name, value));
94}
95
101void
102pcmk_free_nvpairs(GSList *nvpairs)
103{
104 g_slist_free_full(nvpairs, pcmk__free_nvpair);
105}
106
116static gint
117pcmk__compare_nvpair(gconstpointer a, gconstpointer b)
118{
119 int rc = 0;
120 const pcmk_nvpair_t *pair_a = a;
121 const pcmk_nvpair_t *pair_b = b;
122
123 CRM_ASSERT(a != NULL);
124 CRM_ASSERT(pair_a->name != NULL);
125
126 CRM_ASSERT(b != NULL);
127 CRM_ASSERT(pair_b->name != NULL);
128
129 rc = strcmp(pair_a->name, pair_b->name);
130 if (rc < 0) {
131 return -1;
132 } else if (rc > 0) {
133 return 1;
134 }
135 return 0;
136}
137
145GSList *
146pcmk_sort_nvpairs(GSList *list)
147{
148 return g_slist_sort(list, pcmk__compare_nvpair);
149}
150
160GSList *
162{
163 GSList *result = NULL;
164
165 for (xmlAttrPtr iter = pcmk__xe_first_attr(xml); iter != NULL;
166 iter = iter->next) {
167
169 (const char *) iter->name,
170 (const char *) pcmk__xml_attr_value(iter));
171 }
172 return result;
173}
174
185static void
186pcmk__nvpair_add_xml_attr(gpointer data, gpointer user_data)
187{
188 pcmk_nvpair_t *pair = data;
189 xmlNode *parent = user_data;
190
191 crm_xml_add(parent, pair->name, pair->value);
192}
193
200void
201pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
202{
203 g_slist_foreach(list, pcmk__nvpair_add_xml_attr, xml);
204}
205
206// convenience function for name=value strings
207
220int
221pcmk__scan_nvpair(const char *input, char **name, char **value)
222{
223#ifdef SSCANF_HAS_M
224 *name = NULL;
225 *value = NULL;
226 if (sscanf(input, "%m[^=]=%m[^\n]", name, value) <= 0) {
227 return -pcmk_err_bad_nvpair;
228 }
229#else
230 char *sep = NULL;
231 *name = NULL;
232 *value = NULL;
233
234 sep = strstr(optarg, "=");
235 if (sep == NULL) {
236 return -pcmk_err_bad_nvpair;
237 }
238
239 *name = strndup(input, sep-input);
240
241 if (*name == NULL) {
242 return -ENOMEM;
243 }
244
245 /* If the last char in optarg is =, the user gave no
246 * value for the option. Leave it as NULL.
247 */
248 if (*(sep+1) != '\0') {
249 *value = strdup(sep+1);
250
251 if (*value == NULL) {
252 return -ENOMEM;
253 }
254 }
255#endif
256
257 if (*name != NULL && *value != NULL) {
258 return 2;
259 } else if (*name != NULL || *value != NULL) {
260 return 1;
261 } else {
262 return -pcmk_err_bad_nvpair;
263 }
264}
265
283char *
284pcmk__format_nvpair(const char *name, const char *value, const char *units)
285{
286 return crm_strdup_printf("%s=\"%s%s\"", name, value, units ? units : "");
287}
288
302char *
303pcmk__format_named_time(const char *name, time_t epoch_time)
304{
305 const char *now_str = pcmk__epoch2str(&epoch_time);
306
307 return crm_strdup_printf("%s=\"%s\"", name, now_str ? now_str : "");
308}
309
310// XML attribute handling
311
322const char *
323crm_xml_add(xmlNode *node, const char *name, const char *value)
324{
325 bool dirty = FALSE;
326 xmlAttr *attr = NULL;
327
328 CRM_CHECK(node != NULL, return NULL);
329 CRM_CHECK(name != NULL, return NULL);
330
331 if (value == NULL) {
332 return NULL;
333 }
334#if XML_PARANOIA_CHECKS
335 {
336 const char *old_value = NULL;
337
338 old_value = crm_element_value(node, name);
339
340 /* Could be re-setting the same value */
341 CRM_CHECK(old_value != value,
342 crm_err("Cannot reset %s with crm_xml_add(%s)", name, value);
343 return value);
344 }
345#endif
346
347 if (pcmk__tracking_xml_changes(node, FALSE)) {
348 const char *old = crm_element_value(node, name);
349
350 if (old == NULL || value == NULL || strcmp(old, value) != 0) {
351 dirty = TRUE;
352 }
353 }
354
355 if (dirty && (pcmk__check_acl(node, name, pcmk__xf_acl_create) == FALSE)) {
356 crm_trace("Cannot add %s=%s to %s", name, value, node->name);
357 return NULL;
358 }
359
360 attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
361 if (dirty) {
363 }
364
365 CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
366 return (char *)attr->children->content;
367}
368
379const char *
380crm_xml_replace(xmlNode *node, const char *name, const char *value)
381{
382 bool dirty = FALSE;
383 xmlAttr *attr = NULL;
384 const char *old_value = NULL;
385
386 CRM_CHECK(node != NULL, return NULL);
387 CRM_CHECK(name != NULL && name[0] != 0, return NULL);
388
389 old_value = crm_element_value(node, name);
390
391 /* Could be re-setting the same value */
392 CRM_CHECK(old_value != value, return value);
393
394 if (pcmk__check_acl(node, name, pcmk__xf_acl_write) == FALSE) {
395 /* Create a fake object linked to doc->_private instead? */
396 crm_trace("Cannot replace %s=%s to %s", name, value, node->name);
397 return NULL;
398
399 } else if (old_value && !value) {
400 xml_remove_prop(node, name);
401 return NULL;
402 }
403
404 if (pcmk__tracking_xml_changes(node, FALSE)) {
405 if (!old_value || !value || !strcmp(old_value, value)) {
406 dirty = TRUE;
407 }
408 }
409
410 attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
411 if (dirty) {
413 }
414 CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
415 return (char *) attr->children->content;
416}
417
430const char *
431crm_xml_add_int(xmlNode *node, const char *name, int value)
432{
433 char *number = pcmk__itoa(value);
434 const char *added = crm_xml_add(node, name, number);
435
436 free(number);
437 return added;
438}
439
452const char *
453crm_xml_add_ms(xmlNode *node, const char *name, guint ms)
454{
455 char *number = crm_strdup_printf("%u", ms);
456 const char *added = crm_xml_add(node, name, number);
457
458 free(number);
459 return added;
460}
461
462// Maximum size of null-terminated string representation of 64-bit integer
463// -9223372036854775808
464#define LLSTRSIZE 21
465
480const char *
481crm_xml_add_ll(xmlNode *xml, const char *name, long long value)
482{
483 char s[LLSTRSIZE] = { '\0', };
484
485 if (snprintf(s, LLSTRSIZE, "%lld", (long long) value) == LLSTRSIZE) {
486 return NULL;
487 }
488 return crm_xml_add(xml, name, s);
489}
490
504const char *
505crm_xml_add_timeval(xmlNode *xml, const char *name_sec, const char *name_usec,
506 const struct timeval *value)
507{
508 const char *added = NULL;
509
510 if (xml && name_sec && value) {
511 added = crm_xml_add_ll(xml, name_sec, (long long) value->tv_sec);
512 if (added && name_usec) {
513 // Any error is ignored (we successfully added seconds)
514 crm_xml_add_ll(xml, name_usec, (long long) value->tv_usec);
515 }
516 }
517 return added;
518}
519
528const char *
529crm_element_value(const xmlNode *data, const char *name)
530{
531 xmlAttr *attr = NULL;
532
533 if (data == NULL) {
534 crm_err("Couldn't find %s in NULL", name ? name : "<null>");
535 CRM_LOG_ASSERT(data != NULL);
536 return NULL;
537
538 } else if (name == NULL) {
539 crm_err("Couldn't find NULL in %s", crm_element_name(data));
540 return NULL;
541 }
542
543 /* The first argument to xmlHasProp() has always been const,
544 * but libxml2 <2.9.2 didn't declare that, so cast it
545 */
546 attr = xmlHasProp((xmlNode *) data, (pcmkXmlStr) name);
547 if (!attr || !attr->children) {
548 return NULL;
549 }
550 return (const char *) attr->children->content;
551}
552
564int
565crm_element_value_int(const xmlNode *data, const char *name, int *dest)
566{
567 const char *value = NULL;
568
569 CRM_CHECK(dest != NULL, return -1);
570 value = crm_element_value(data, name);
571 if (value) {
572 long long value_ll;
573
574 if ((pcmk__scan_ll(value, &value_ll, 0LL) != pcmk_rc_ok)
575 || (value_ll < INT_MIN) || (value_ll > INT_MAX)) {
577 } else {
578 *dest = (int) value_ll;
579 return 0;
580 }
581 }
582 return -1;
583}
584
596int
597crm_element_value_ll(const xmlNode *data, const char *name, long long *dest)
598{
599 const char *value = NULL;
600
601 CRM_CHECK(dest != NULL, return -1);
602 value = crm_element_value(data, name);
603 if ((value != NULL)
604 && (pcmk__scan_ll(value, dest, PCMK__PARSE_INT_DEFAULT) == pcmk_rc_ok)) {
605 return 0;
606 }
607 return -1;
608}
609
621int
622crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
623{
624 const char *value = NULL;
625 long long value_ll;
626
627 CRM_CHECK(dest != NULL, return -1);
628 *dest = 0;
629 value = crm_element_value(data, name);
630 if ((pcmk__scan_ll(value, &value_ll, 0LL) != pcmk_rc_ok)
631 || (value_ll < 0) || (value_ll > G_MAXUINT)) {
632 return -1;
633 }
634 *dest = (guint) value_ll;
635 return pcmk_ok;
636}
637
649int
650crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
651{
652 long long value_ll = 0;
653
654 if (crm_element_value_ll(xml, name, &value_ll) < 0) {
655 return -1;
656 }
657
658 /* Unfortunately, we can't do any bounds checking, since time_t has neither
659 * standardized bounds nor constants defined for them.
660 */
661 *dest = (time_t) value_ll;
662 return pcmk_ok;
663}
664
678int
679crm_element_value_timeval(const xmlNode *xml, const char *name_sec,
680 const char *name_usec, struct timeval *dest)
681{
682 long long value_i = 0;
683
684 CRM_CHECK(dest != NULL, return -EINVAL);
685 dest->tv_sec = 0;
686 dest->tv_usec = 0;
687
688 if (xml == NULL) {
689 return pcmk_ok;
690 }
691
692 /* Unfortunately, we can't do any bounds checking, since there are no
693 * constants provided for the bounds of time_t and suseconds_t, and
694 * calculating them isn't worth the effort. If there are XML values
695 * beyond the native sizes, there will probably be worse problems anyway.
696 */
697
698 // Parse seconds
699 errno = 0;
700 if (crm_element_value_ll(xml, name_sec, &value_i) < 0) {
701 return -errno;
702 }
703 dest->tv_sec = (time_t) value_i;
704
705 // Parse microseconds
706 if (crm_element_value_ll(xml, name_usec, &value_i) < 0) {
707 return -errno;
708 }
709 dest->tv_usec = (suseconds_t) value_i;
710
711 return pcmk_ok;
712}
713
725char *
726crm_element_value_copy(const xmlNode *data, const char *name)
727{
728 char *value_copy = NULL;
729
731 return value_copy;
732}
733
747void
748hash2smartfield(gpointer key, gpointer value, gpointer user_data)
749{
750 const char *name = key;
751 const char *s_value = value;
752
753 xmlNode *xml_node = user_data;
754
755 if (isdigit(name[0])) {
756 xmlNode *tmp = create_xml_node(xml_node, XML_TAG_PARAM);
757
759 crm_xml_add(tmp, XML_NVPAIR_ATTR_VALUE, s_value);
760
761 } else if (crm_element_value(xml_node, name) == NULL) {
762 crm_xml_add(xml_node, name, s_value);
763 crm_trace("dumped: %s=%s", name, s_value);
764
765 } else {
766 crm_trace("duplicate: %s=%s", name, s_value);
767 }
768}
769
781void
782hash2field(gpointer key, gpointer value, gpointer user_data)
783{
784 const char *name = key;
785 const char *s_value = value;
786
787 xmlNode *xml_node = user_data;
788
789 if (crm_element_value(xml_node, name) == NULL) {
790 crm_xml_add(xml_node, name, s_value);
791
792 } else {
793 crm_trace("duplicate: %s=%s", name, s_value);
794 }
795}
796
809void
810hash2metafield(gpointer key, gpointer value, gpointer user_data)
811{
812 char *crm_name = NULL;
813
814 if (key == NULL || value == NULL) {
815 return;
816 }
817
818 /* Filter out cluster-generated attributes that contain a '#' or ':'
819 * (like fail-count and last-failure).
820 */
821 for (crm_name = key; *crm_name; ++crm_name) {
822 if ((*crm_name == '#') || (*crm_name == ':')) {
823 return;
824 }
825 }
826
827 crm_name = crm_meta_name(key);
828 hash2field(crm_name, value, user_data);
829 free(crm_name);
830}
831
832// nvpair handling
833
844xmlNode *
845crm_create_nvpair_xml(xmlNode *parent, const char *id, const char *name,
846 const char *value)
847{
848 xmlNode *nvp;
849
850 /* id can be NULL so we auto-generate one, and name can be NULL if this
851 * will be used to delete a name/value pair by ID, but both can't be NULL
852 */
853 CRM_CHECK(id || name, return NULL);
854
856 CRM_CHECK(nvp, return NULL);
857
858 if (id) {
859 crm_xml_add(nvp, XML_ATTR_ID, id);
860 } else {
861 const char *parent_id = ID(parent);
862
863 crm_xml_set_id(nvp, "%s-%s",
864 (parent_id? parent_id : XML_CIB_TAG_NVPAIR), name);
865 }
868 return nvp;
869}
870
882void
883hash2nvpair(gpointer key, gpointer value, gpointer user_data)
884{
885 const char *name = key;
886 const char *s_value = value;
887 xmlNode *xml_node = user_data;
888
889 crm_create_nvpair_xml(xml_node, name, name, s_value);
890 crm_trace("dumped: name=%s value=%s", name, s_value);
891}
892
907GHashTable *
909{
910 xmlNode *child = NULL;
911 xmlAttrPtr pIter = NULL;
912 xmlNode *nvpair_list = NULL;
913 GHashTable *nvpair_hash = pcmk__strkey_table(free, free);
914
915 CRM_CHECK(parent != NULL, return nvpair_hash);
916
917 nvpair_list = find_xml_node(parent, XML_TAG_ATTRS, FALSE);
918 if (nvpair_list == NULL) {
919 crm_trace("No attributes in %s", crm_element_name(parent));
920 crm_log_xml_trace(parent, "No attributes for resource op");
921 }
922
923 crm_log_xml_trace(nvpair_list, "Unpacking");
924
925 for (pIter = pcmk__xe_first_attr(nvpair_list); pIter != NULL;
926 pIter = pIter->next) {
927
928 const char *p_name = (const char *)pIter->name;
929 const char *p_value = pcmk__xml_attr_value(pIter);
930
931 crm_trace("Added %s=%s", p_name, p_value);
932
933 g_hash_table_insert(nvpair_hash, strdup(p_name), strdup(p_value));
934 }
935
936 for (child = pcmk__xml_first_child(nvpair_list); child != NULL;
937 child = pcmk__xml_next(child)) {
938
939 if (strcmp((const char *)child->name, XML_TAG_PARAM) == 0) {
940 const char *key = crm_element_value(child, XML_NVPAIR_ATTR_NAME);
941 const char *value = crm_element_value(child, XML_NVPAIR_ATTR_VALUE);
942
943 crm_trace("Added %s=%s", key, value);
944 if (key != NULL && value != NULL) {
945 g_hash_table_insert(nvpair_hash, strdup(key), strdup(value));
946 }
947 }
948 }
949
950 return nvpair_hash;
951}
952
953void
954pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value)
955{
957}
958
959int
960pcmk__xe_get_bool_attr(xmlNodePtr node, const char *name, bool *value) {
961 const char *xml_value = NULL;
962 int ret, rc;
963
964 if (node == NULL) {
965 return ENODATA;
966 } else if (name == NULL || value == NULL) {
967 return EINVAL;
968 }
969
970 xml_value = crm_element_value(node, name);
971
972 if (xml_value == NULL) {
973 return ENODATA;
974 }
975
976 rc = crm_str_to_boolean(xml_value, &ret);
977 if (rc == 1) {
978 *value = ret;
979 return pcmk_rc_ok;
980 } else {
982 }
983}
984
985bool
986pcmk__xe_attr_is_true(xmlNodePtr node, const char *name)
987{
988 bool value = false;
989 int rc;
990
991 rc = pcmk__xe_get_bool_attr(node, name, &value);
992 return rc == pcmk_rc_ok && value == true;
993}
994
995// Deprecated functions kept only for backward API compatibility
996// LCOV_EXCL_START
997
999
1000int
1001pcmk_scan_nvpair(const char *input, char **name, char **value)
1002{
1003 return pcmk__scan_nvpair(input, name, value);
1004}
1005
1006char *
1007pcmk_format_nvpair(const char *name, const char *value,
1008 const char *units)
1009{
1010 return pcmk__format_nvpair(name, value, units);
1011}
1012
1013char *
1014pcmk_format_named_time(const char *name, time_t epoch_time)
1015{
1016 return pcmk__format_named_time(name, epoch_time);
1017}
1018
1019// LCOV_EXCL_STOP
1020// End deprecated API
const char * parent
Definition: cib.c:25
const char * name
Definition: cib.c:24
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition: acl.c:611
char * crm_meta_name(const char *field)
Definition: utils.c:439
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
int crm_str_to_boolean(const char *s, int *ret)
Definition: strings.c:427
Deprecated Pacemaker utilities.
char data[0]
Definition: cpg.c:10
A dumping ground.
G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
Definition: xml.c:51
G_GNUC_INTERNAL void pcmk__mark_xml_attr_dirty(xmlAttr *a)
Definition: xml.c:173
const char * pcmk__epoch2str(time_t *when)
Definition: iso8601.c:1715
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:210
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:226
#define crm_err(fmt, args...)
Definition: logging.h:358
#define crm_log_xml_trace(xml, text)
Definition: logging.h:372
#define crm_trace(fmt, args...)
Definition: logging.h:364
#define ID(x)
Definition: msg_xml.h:460
#define XML_BOOLEAN_TRUE
Definition: msg_xml.h:146
#define XML_NVPAIR_ATTR_VALUE
Definition: msg_xml.h:384
#define XML_ATTR_ID
Definition: msg_xml.h:135
#define XML_TAG_ATTRS
Definition: msg_xml.h:211
#define XML_BOOLEAN_FALSE
Definition: msg_xml.h:147
#define XML_NVPAIR_ATTR_NAME
Definition: msg_xml.h:383
#define XML_CIB_TAG_NVPAIR
Definition: msg_xml.h:206
#define XML_TAG_PARAM
Definition: msg_xml.h:216
xmlNode * input
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:481
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:679
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:529
int pcmk__xe_get_bool_attr(xmlNodePtr node, const char *name, bool *value)
Definition: nvpair.c:960
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:505
void hash2nvpair(gpointer key, gpointer value, gpointer user_data)
Add XML nvpair element based on hash table entry.
Definition: nvpair.c:883
char * pcmk_format_nvpair(const char *name, const char *value, const char *units)
Definition: nvpair.c:1007
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:565
GSList * pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
Prepend a name/value pair to a list.
Definition: nvpair.c:91
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:845
bool pcmk__xe_attr_is_true(xmlNodePtr node, const char *name)
Definition: nvpair.c:986
void hash2metafield(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry, as meta-attribute name.
Definition: nvpair.c:810
GSList * pcmk_sort_nvpairs(GSList *list)
Sort a list of name/value pairs.
Definition: nvpair.c:146
void hash2field(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry.
Definition: nvpair.c:782
GHashTable * xml2list(xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition: nvpair.c:908
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:431
GSList * pcmk_xml_attrs2nvpairs(xmlNode *xml)
Create a list of name/value pairs from an XML node's attributes.
Definition: nvpair.c:161
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:380
int pcmk_scan_nvpair(const char *input, char **name, char **value)
Definition: nvpair.c:1001
int pcmk__scan_nvpair(const char *input, char **name, char **value)
Definition: nvpair.c:221
char * pcmk__format_nvpair(const char *name, const char *value, const char *units)
Definition: nvpair.c:284
void pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
Add XML attributes based on a list of name/value pairs.
Definition: nvpair.c:201
void pcmk_free_nvpairs(GSList *nvpairs)
Free a list of name/value pairs.
Definition: nvpair.c:102
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
Definition: nvpair.c:622
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition: nvpair.c:726
void hash2smartfield(gpointer key, gpointer value, gpointer user_data)
Add hash table entry to XML as (possibly legacy) name/value.
Definition: nvpair.c:748
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:597
char * pcmk__format_named_time(const char *name, time_t epoch_time)
Definition: nvpair.c:303
void pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value)
Definition: nvpair.c:954
char * pcmk_format_named_time(const char *name, time_t epoch_time)
Definition: nvpair.c:1014
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:650
#define LLSTRSIZE
Definition: nvpair.c:464
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:323
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:453
pcmk__action_result_t result
Definition: pcmk_fence.c:34
#define ENODATA
Definition: portability.h:145
char * strndup(const char *str, size_t len)
#define CRM_ASSERT(expr)
Definition: results.h:42
@ pcmk_rc_ok
Definition: results.h:146
@ pcmk_rc_unknown_format
Definition: results.h:140
#define pcmk_err_bad_nvpair
Definition: results.h:91
#define pcmk_ok
Definition: results.h:68
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:611
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition: strings.c:97
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1188
#define PCMK__PARSE_INT_DEFAULT
char * value
Definition: nvpair.h:31
char * name
Definition: nvpair.h:30
Wrappers for and extensions to libxml2.
xmlNode * find_xml_node(xmlNode *cib, const char *node_path, gboolean must_find)
Definition: xml.c:445
const xmlChar * pcmkXmlStr
Definition: xml.h:52
void crm_xml_set_id(xmlNode *xml, const char *format,...) G_GNUC_PRINTF(2
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:696
void xml_remove_prop(xmlNode *obj, const char *name)
Definition: xml.c:2037
@ pcmk__xf_acl_create
Definition: xml_internal.h:332
@ pcmk__xf_acl_write
Definition: xml_internal.h:329