pacemaker 2.1.1-77db578727
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
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
47static pcmk_nvpair_t *
48pcmk__new_nvpair(const char *name, const char *value)
49{
50 pcmk_nvpair_t *nvpair = NULL;
51
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
68static void
69pcmk__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
91GSList *
92pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
93{
94 return g_slist_prepend(nvpairs, pcmk__new_nvpair(name, value));
95}
96
102void
103pcmk_free_nvpairs(GSList *nvpairs)
104{
105 g_slist_free_full(nvpairs, pcmk__free_nvpair);
106}
107
117static gint
118pcmk__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
146GSList *
147pcmk_sort_nvpairs(GSList *list)
148{
149 return g_slist_sort(list, pcmk__compare_nvpair);
150}
151
161GSList *
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
186static void
187pcmk__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
201void
202pcmk_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
221int
222pcmk__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
284char *
285pcmk__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
303char *
304pcmk__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
323const char *
324crm_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
380const char *
381crm_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
431const char *
432crm_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
453const char *
454crm_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
481const char *
482crm_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
505const char *
506crm_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
529const char *
530crm_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
565int
566crm_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)) {
578 } else {
579 *dest = (int) value_ll;
580 return 0;
581 }
582 }
583 return -1;
584}
585
597int
598crm_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
622int
623crm_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
650int
651crm_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
679int
680crm_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
726char *
727crm_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
751void
752hash2smartfield(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
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
785void
786hash2field(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
813void
814hash2metafield(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
848xmlNode *
849crm_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 }
872 return nvp;
873}
874
886void
887hash2nvpair(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
911GHashTable *
912xml2list(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
960
961int
962pcmk_scan_nvpair(const char *input, char **name, char **value)
963{
964 return pcmk__scan_nvpair(input, name, value);
965}
966
967char *
968pcmk_format_nvpair(const char *name, const char *value,
969 const char *units)
970{
971 return pcmk__format_nvpair(name, value, units);
972}
973
974char *
975pcmk_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
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition acl.c:599
char * crm_meta_name(const char *field)
Definition utils.c:511
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
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:52
G_GNUC_INTERNAL void pcmk__mark_xml_attr_dirty(xmlAttr *a)
Definition xml.c:174
@ xpf_acl_write
@ xpf_acl_create
const char * pcmk__epoch2str(time_t *when)
Definition iso8601.c:1715
#define CRM_LOG_ASSERT(expr)
Definition logging.h:202
#define CRM_CHECK(expr, failure_action)
Definition logging.h:218
#define crm_err(fmt, args...)
Definition logging.h:350
#define crm_log_xml_trace(xml, text)
Definition logging.h:364
#define crm_trace(fmt, args...)
Definition logging.h:356
#define ID(x)
Definition msg_xml.h:456
#define XML_NVPAIR_ATTR_VALUE
Definition msg_xml.h:378
#define XML_ATTR_ID
Definition msg_xml.h:129
#define XML_TAG_ATTRS
Definition msg_xml.h:205
#define XML_NVPAIR_ATTR_NAME
Definition msg_xml.h:377
#define XML_CIB_TAG_NVPAIR
Definition msg_xml.h:200
#define XML_TAG_PARAM
Definition msg_xml.h:210
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:482
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
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:530
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
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:968
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
GSList * pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
Prepend a name/value pair to a list.
Definition nvpair.c:92
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
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
GSList * pcmk_sort_nvpairs(GSList *list)
Sort a list of name/value pairs.
Definition nvpair.c:147
void hash2field(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry.
Definition nvpair.c:786
GHashTable * xml2list(xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition nvpair.c:912
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
GSList * pcmk_xml_attrs2nvpairs(xmlNode *xml)
Create a list of name/value pairs from an XML node's attributes.
Definition nvpair.c:162
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
int pcmk_scan_nvpair(const char *input, char **name, char **value)
Definition nvpair.c:962
int pcmk__scan_nvpair(const char *input, char **name, char **value)
Definition nvpair.c:222
char * pcmk__format_nvpair(const char *name, const char *value, const char *units)
Definition nvpair.c:285
void pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
Add XML attributes based on a list of name/value pairs.
Definition nvpair.c:202
void pcmk_free_nvpairs(GSList *nvpairs)
Free a list of name/value pairs.
Definition nvpair.c:103
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
void hash2smartfield(gpointer key, gpointer value, gpointer user_data)
Add hash table entry to XML as (possibly legacy) name/value.
Definition nvpair.c:752
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
char * pcmk__format_named_time(const char *name, time_t epoch_time)
Definition nvpair.c:304
char * pcmk_format_named_time(const char *name, time_t epoch_time)
Definition nvpair.c:975
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
#define LLSTRSIZE
Definition nvpair.c:465
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
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 * name
Definition pcmk_fence.c:31
int rc
Definition pcmk_fence.c:35
char * strndup(const char *str, size_t len)
#define CRM_ASSERT(expr)
Definition results.h:42
@ pcmk_rc_ok
Definition results.h:142
#define pcmk_err_bad_nvpair
Definition results.h:90
#define pcmk_ok
Definition results.h:67
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:610
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition strings.c:97
#define PCMK__PARSE_INT_DEFAULT
char * value
Definition nvpair.h:30
char * name
Definition nvpair.h:29
Deprecated Pacemaker utilities.
Wrappers for and extensions to libxml2.
xmlNode * find_xml_node(xmlNode *cib, const char *node_path, gboolean must_find)
Definition xml.c:446
const xmlChar * pcmkXmlStr
Definition xml.h:51
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:2036