pacemaker 2.1.8-2.1.8
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
nvpair.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2024 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU Lesser General Public License
7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8 */
9
10#include <crm_internal.h>
11
12#include <stdio.h>
13#include <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/common/xml.h>
22#include "crmcommon_private.h"
23
24/*
25 * This file isolates handling of various kinds of name/value pairs:
26 *
27 * - pcmk_nvpair_t data type
28 * - XML attributes (<TAG ... NAME=VALUE ...>)
29 * - XML nvpair elements (<nvpair id=ID name=NAME value=VALUE>)
30 * - Meta-attributes (for resources and actions)
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 = pcmk__assert_alloc(1, sizeof(pcmk_nvpair_t));
54
55 nvpair->name = pcmk__str_copy(name);
56 nvpair->value = pcmk__str_copy(value);
57 return nvpair;
58}
59
66static void
67pcmk__free_nvpair(gpointer data)
68{
69 if (data) {
70 pcmk_nvpair_t *nvpair = data;
71
72 free(nvpair->name);
73 free(nvpair->value);
74 free(nvpair);
75 }
76}
77
89GSList *
90pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
91{
92 return g_slist_prepend(nvpairs, pcmk__new_nvpair(name, value));
93}
94
100void
101pcmk_free_nvpairs(GSList *nvpairs)
102{
103 g_slist_free_full(nvpairs, pcmk__free_nvpair);
104}
105
115static gint
116pcmk__compare_nvpair(gconstpointer a, gconstpointer b)
117{
118 int rc = 0;
119 const pcmk_nvpair_t *pair_a = a;
120 const pcmk_nvpair_t *pair_b = b;
121
122 CRM_ASSERT(a != NULL);
123 CRM_ASSERT(pair_a->name != NULL);
124
125 CRM_ASSERT(b != NULL);
126 CRM_ASSERT(pair_b->name != NULL);
127
128 rc = strcmp(pair_a->name, pair_b->name);
129 if (rc < 0) {
130 return -1;
131 } else if (rc > 0) {
132 return 1;
133 }
134 return 0;
135}
136
144GSList *
145pcmk_sort_nvpairs(GSList *list)
146{
147 return g_slist_sort(list, pcmk__compare_nvpair);
148}
149
159GSList *
160pcmk_xml_attrs2nvpairs(const xmlNode *xml)
161{
162 GSList *result = NULL;
163
164 for (xmlAttrPtr iter = pcmk__xe_first_attr(xml); iter != NULL;
165 iter = iter->next) {
166
168 (const char *) iter->name,
169 (const char *) pcmk__xml_attr_value(iter));
170 }
171 return result;
172}
173
184static void
185pcmk__nvpair_add_xml_attr(gpointer data, gpointer user_data)
186{
187 pcmk_nvpair_t *pair = data;
188 xmlNode *parent = user_data;
189
190 crm_xml_add(parent, pair->name, pair->value);
191}
192
199void
200pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
201{
202 g_slist_foreach(list, pcmk__nvpair_add_xml_attr, xml);
203}
204
205// convenience function for name=value strings
206
219int
220pcmk__scan_nvpair(const char *input, char **name, char **value)
221{
222#ifdef HAVE_SSCANF_M
223 *name = NULL;
224 *value = NULL;
225 if (sscanf(input, "%m[^=]=%m[^\n]", name, value) <= 0) {
226 return -pcmk_err_bad_nvpair;
227 }
228#else
229 char *sep = NULL;
230 *name = NULL;
231 *value = NULL;
232
233 sep = strstr(optarg, "=");
234 if (sep == NULL) {
235 return -pcmk_err_bad_nvpair;
236 }
237
238 *name = strndup(input, sep-input);
239
240 if (*name == NULL) {
241 return -ENOMEM;
242 }
243
244 /* If the last char in optarg is =, the user gave no
245 * value for the option. Leave it as NULL.
246 */
247 if (*(sep+1) != '\0') {
248 *value = strdup(sep+1);
249
250 if (*value == NULL) {
251 return -ENOMEM;
252 }
253 }
254#endif
255
256 if (*name != NULL && *value != NULL) {
257 return 2;
258 } else if (*name != NULL || *value != NULL) {
259 return 1;
260 } else {
261 return -pcmk_err_bad_nvpair;
262 }
263}
264
282char *
283pcmk__format_nvpair(const char *name, const char *value, const char *units)
284{
285 return crm_strdup_printf("%s=\"%s%s\"", name, value, units ? units : "");
286}
287
288// XML attribute handling
289
300const char *
301crm_xml_add(xmlNode *node, const char *name, const char *value)
302{
303 bool dirty = FALSE;
304 xmlAttr *attr = NULL;
305
306 CRM_CHECK(node != NULL, return NULL);
307 CRM_CHECK(name != NULL, return NULL);
308
309 if (value == NULL) {
310 return NULL;
311 }
312
313 if (pcmk__tracking_xml_changes(node, FALSE)) {
314 const char *old = crm_element_value(node, name);
315
316 if (old == NULL || value == NULL || strcmp(old, value) != 0) {
317 dirty = TRUE;
318 }
319 }
320
321 if (dirty && (pcmk__check_acl(node, name, pcmk__xf_acl_create) == FALSE)) {
322 crm_trace("Cannot add %s=%s to %s", name, value, node->name);
323 return NULL;
324 }
325
326 attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
327 if (dirty) {
329 }
330
331 CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
332 return (char *)attr->children->content;
333}
334
347const char *
348crm_xml_add_int(xmlNode *node, const char *name, int value)
349{
350 char *number = pcmk__itoa(value);
351 const char *added = crm_xml_add(node, name, number);
352
353 free(number);
354 return added;
355}
356
369const char *
370crm_xml_add_ms(xmlNode *node, const char *name, guint ms)
371{
372 char *number = crm_strdup_printf("%u", ms);
373 const char *added = crm_xml_add(node, name, number);
374
375 free(number);
376 return added;
377}
378
379// Maximum size of null-terminated string representation of 64-bit integer
380// -9223372036854775808
381#define LLSTRSIZE 21
382
397const char *
398crm_xml_add_ll(xmlNode *xml, const char *name, long long value)
399{
400 char s[LLSTRSIZE] = { '\0', };
401
402 if (snprintf(s, LLSTRSIZE, "%lld", (long long) value) == LLSTRSIZE) {
403 return NULL;
404 }
405 return crm_xml_add(xml, name, s);
406}
407
421const char *
422crm_xml_add_timeval(xmlNode *xml, const char *name_sec, const char *name_usec,
423 const struct timeval *value)
424{
425 const char *added = NULL;
426
427 if (xml && name_sec && value) {
428 added = crm_xml_add_ll(xml, name_sec, (long long) value->tv_sec);
429 if (added && name_usec) {
430 // Any error is ignored (we successfully added seconds)
431 crm_xml_add_ll(xml, name_usec, (long long) value->tv_usec);
432 }
433 }
434 return added;
435}
436
445const char *
446crm_element_value(const xmlNode *data, const char *name)
447{
448 xmlAttr *attr = NULL;
449
450 if (data == NULL) {
451 crm_err("Couldn't find %s in NULL", name ? name : "<null>");
452 CRM_LOG_ASSERT(data != NULL);
453 return NULL;
454
455 } else if (name == NULL) {
456 crm_err("Couldn't find NULL in %s", data->name);
457 return NULL;
458 }
459
460 /* The first argument to xmlHasProp() has always been const,
461 * but libxml2 <2.9.2 didn't declare that, so cast it
462 */
463 attr = xmlHasProp((xmlNode *) data, (pcmkXmlStr) name);
464 if (!attr || !attr->children) {
465 return NULL;
466 }
467 return (const char *) attr->children->content;
468}
469
481int
482crm_element_value_int(const xmlNode *data, const char *name, int *dest)
483{
484 const char *value = NULL;
485
486 CRM_CHECK(dest != NULL, return -1);
487 value = crm_element_value(data, name);
488 if (value) {
489 long long value_ll;
490
491 if ((pcmk__scan_ll(value, &value_ll, 0LL) != pcmk_rc_ok)
492 || (value_ll < INT_MIN) || (value_ll > INT_MAX)) {
494 } else {
495 *dest = (int) value_ll;
496 return 0;
497 }
498 }
499 return -1;
500}
501
513int
514crm_element_value_ll(const xmlNode *data, const char *name, long long *dest)
515{
516 const char *value = NULL;
517
518 CRM_CHECK(dest != NULL, return -1);
519 value = crm_element_value(data, name);
520 if ((value != NULL)
521 && (pcmk__scan_ll(value, dest, PCMK__PARSE_INT_DEFAULT) == pcmk_rc_ok)) {
522 return 0;
523 }
524 return -1;
525}
526
538int
539crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
540{
541 const char *value = NULL;
542 long long value_ll;
543
544 CRM_CHECK(dest != NULL, return -1);
545 *dest = 0;
546 value = crm_element_value(data, name);
547 if ((pcmk__scan_ll(value, &value_ll, 0LL) != pcmk_rc_ok)
548 || (value_ll < 0) || (value_ll > G_MAXUINT)) {
549 return -1;
550 }
551 *dest = (guint) value_ll;
552 return pcmk_ok;
553}
554
566int
567crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
568{
569 long long value_ll = 0;
570
571 if (crm_element_value_ll(xml, name, &value_ll) < 0) {
572 return -1;
573 }
574
575 /* Unfortunately, we can't do any bounds checking, since time_t has neither
576 * standardized bounds nor constants defined for them.
577 */
578 *dest = (time_t) value_ll;
579 return pcmk_ok;
580}
581
595int
596crm_element_value_timeval(const xmlNode *xml, const char *name_sec,
597 const char *name_usec, struct timeval *dest)
598{
599 long long value_i = 0;
600
601 CRM_CHECK(dest != NULL, return -EINVAL);
602 dest->tv_sec = 0;
603 dest->tv_usec = 0;
604
605 if (xml == NULL) {
606 return pcmk_ok;
607 }
608
609 /* Unfortunately, we can't do any bounds checking, since there are no
610 * constants provided for the bounds of time_t and suseconds_t, and
611 * calculating them isn't worth the effort. If there are XML values
612 * beyond the native sizes, there will probably be worse problems anyway.
613 */
614
615 // Parse seconds
616 errno = 0;
617 if (crm_element_value_ll(xml, name_sec, &value_i) < 0) {
618 return -errno;
619 }
620 dest->tv_sec = (time_t) value_i;
621
622 // Parse microseconds
623 if (crm_element_value_ll(xml, name_usec, &value_i) < 0) {
624 return -errno;
625 }
626 dest->tv_usec = (suseconds_t) value_i;
627
628 return pcmk_ok;
629}
630
643int
644pcmk__xe_get_datetime(const xmlNode *xml, const char *attr, crm_time_t **t)
645{
646 const char *value = NULL;
647
648 if ((t == NULL) || (*t != NULL) || (xml == NULL) || (attr == NULL)) {
649 return EINVAL;
650 }
651
652 value = crm_element_value(xml, attr);
653 if (value != NULL) {
654 *t = crm_time_new(value);
655 if (*t == NULL) {
657 }
658 }
659 return pcmk_rc_ok;
660}
661
673char *
674crm_element_value_copy(const xmlNode *data, const char *name)
675{
677}
678
693void
694hash2smartfield(gpointer key, gpointer value, gpointer user_data)
695{
696 /* @TODO Generate PCMK__XE_PARAM nodes for all keys that aren't valid XML
697 * attribute names (not just those that start with digits), or possibly for
698 * all keys to simplify parsing.
699 *
700 * Consider either deprecating as public API or exposing PCMK__XE_PARAM.
701 * PCMK__XE_PARAM is currently private because it doesn't appear in any
702 * output that Pacemaker generates.
703 */
704 const char *name = key;
705 const char *s_value = value;
706
707 xmlNode *xml_node = user_data;
708
709 if (isdigit(name[0])) {
710 xmlNode *tmp = pcmk__xe_create(xml_node, PCMK__XE_PARAM);
711
713 crm_xml_add(tmp, PCMK_XA_VALUE, s_value);
714
715 } else if (crm_element_value(xml_node, name) == NULL) {
716 crm_xml_add(xml_node, name, s_value);
717 crm_trace("dumped: %s=%s", name, s_value);
718
719 } else {
720 crm_trace("duplicate: %s=%s", name, s_value);
721 }
722}
723
735void
736hash2field(gpointer key, gpointer value, gpointer user_data)
737{
738 const char *name = key;
739 const char *s_value = value;
740
741 xmlNode *xml_node = user_data;
742
743 if (crm_element_value(xml_node, name) == NULL) {
744 crm_xml_add(xml_node, name, s_value);
745
746 } else {
747 crm_trace("duplicate: %s=%s", name, s_value);
748 }
749}
750
763void
764hash2metafield(gpointer key, gpointer value, gpointer user_data)
765{
766 char *crm_name = NULL;
767
768 if (key == NULL || value == NULL) {
769 return;
770 }
771
772 /* Filter out cluster-generated attributes that contain a '#' or ':'
773 * (like fail-count and last-failure).
774 */
775 for (crm_name = key; *crm_name; ++crm_name) {
776 if ((*crm_name == '#') || (*crm_name == ':')) {
777 return;
778 }
779 }
780
781 crm_name = crm_meta_name(key);
782 hash2field(crm_name, value, user_data);
783 free(crm_name);
784}
785
786// nvpair handling
787
798xmlNode *
799crm_create_nvpair_xml(xmlNode *parent, const char *id, const char *name,
800 const char *value)
801{
802 xmlNode *nvp;
803
804 /* id can be NULL so we auto-generate one, and name can be NULL if this
805 * will be used to delete a name/value pair by ID, but both can't be NULL
806 */
807 CRM_CHECK(id || name, return NULL);
808
810
811 if (id) {
812 crm_xml_add(nvp, PCMK_XA_ID, id);
813 } else {
814 crm_xml_set_id(nvp, "%s-%s",
815 pcmk__s(pcmk__xe_id(parent), PCMK_XE_NVPAIR), name);
816 }
818 crm_xml_add(nvp, PCMK_XA_VALUE, value);
819 return nvp;
820}
821
833void
834hash2nvpair(gpointer key, gpointer value, gpointer user_data)
835{
836 const char *name = key;
837 const char *s_value = value;
838 xmlNode *xml_node = user_data;
839
840 crm_create_nvpair_xml(xml_node, name, name, s_value);
841 crm_trace("dumped: name=%s value=%s", name, s_value);
842}
843
858GHashTable *
859xml2list(const xmlNode *parent)
860{
861 xmlNode *child = NULL;
862 xmlAttrPtr pIter = NULL;
863 xmlNode *nvpair_list = NULL;
864 GHashTable *nvpair_hash = pcmk__strkey_table(free, free);
865
866 CRM_CHECK(parent != NULL, return nvpair_hash);
867
868 nvpair_list = pcmk__xe_first_child(parent, PCMK__XE_ATTRIBUTES, NULL, NULL);
869 if (nvpair_list == NULL) {
870 crm_trace("No attributes in %s", parent->name);
871 crm_log_xml_trace(parent, "No attributes for resource op");
872 }
873
874 crm_log_xml_trace(nvpair_list, "Unpacking");
875
876 for (pIter = pcmk__xe_first_attr(nvpair_list); pIter != NULL;
877 pIter = pIter->next) {
878
879 const char *p_name = (const char *)pIter->name;
880 const char *p_value = pcmk__xml_attr_value(pIter);
881
882 crm_trace("Added %s=%s", p_name, p_value);
883
884 pcmk__insert_dup(nvpair_hash, p_name, p_value);
885 }
886
887 for (child = pcmk__xe_first_child(nvpair_list, PCMK__XE_PARAM, NULL, NULL);
888 child != NULL; child = pcmk__xe_next_same(child)) {
889
890 const char *key = crm_element_value(child, PCMK_XA_NAME);
891 const char *value = crm_element_value(child, PCMK_XA_VALUE);
892
893 crm_trace("Added %s=%s", key, value);
894 if (key != NULL && value != NULL) {
895 pcmk__insert_dup(nvpair_hash, key, value);
896 }
897 }
898
899 return nvpair_hash;
900}
901
902void
903pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value)
904{
905 crm_xml_add(node, name, pcmk__btoa(value));
906}
907
908int
909pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
910{
911 const char *xml_value = NULL;
912 int ret, rc;
913
914 if (node == NULL) {
915 return ENODATA;
916 } else if (name == NULL || value == NULL) {
917 return EINVAL;
918 }
919
920 xml_value = crm_element_value(node, name);
921
922 if (xml_value == NULL) {
923 return ENODATA;
924 }
925
926 rc = crm_str_to_boolean(xml_value, &ret);
927 if (rc == 1) {
928 *value = ret;
929 return pcmk_rc_ok;
930 } else {
931 return pcmk_rc_bad_input;
932 }
933}
934
935bool
936pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
937{
938 bool value = false;
939 int rc;
940
941 rc = pcmk__xe_get_bool_attr(node, name, &value);
942 return rc == pcmk_rc_ok && value == true;
943}
944
945// Meta-attribute handling
946
958char *
959crm_meta_name(const char *attr_name)
960{
961 char *env_name = NULL;
962
963 CRM_ASSERT(!pcmk__str_empty(attr_name));
964
965 env_name = crm_strdup_printf(CRM_META "_%s", attr_name);
966 for (char *c = env_name; *c != '\0'; ++c) {
967 if (*c == '-') {
968 *c = '_';
969 }
970 }
971 return env_name;
972}
973
986const char *
987crm_meta_value(GHashTable *meta, const char *attr_name)
988{
989 if ((meta != NULL) && (attr_name != NULL)) {
990 char *key = crm_meta_name(attr_name);
991 const char *value = g_hash_table_lookup(meta, key);
992
993 free(key);
994 return value;
995 }
996 return NULL;
997}
998
999// Deprecated functions kept only for backward API compatibility
1000// LCOV_EXCL_START
1001
1002#include <crm/common/util_compat.h>
1003
1004int
1005pcmk_scan_nvpair(const char *input, char **name, char **value)
1006{
1007 return pcmk__scan_nvpair(input, name, value);
1008}
1009
1010char *
1011pcmk_format_nvpair(const char *name, const char *value,
1012 const char *units)
1013{
1014 return pcmk__format_nvpair(name, value, units);
1015}
1016
1017char *
1018pcmk_format_named_time(const char *name, time_t epoch_time)
1019{
1020 char *now_s = pcmk__epoch2str(&epoch_time, 0);
1021 char *result = crm_strdup_printf("%s=\"%s\"", name, pcmk__s(now_s, ""));
1022
1023 free(now_s);
1024 return result;
1025}
1026
1027const char *
1028crm_xml_replace(xmlNode *node, const char *name, const char *value)
1029{
1030 bool dirty = FALSE;
1031 xmlAttr *attr = NULL;
1032 const char *old_value = NULL;
1033
1034 CRM_CHECK(node != NULL, return NULL);
1035 CRM_CHECK(name != NULL && name[0] != 0, return NULL);
1036
1037 old_value = crm_element_value(node, name);
1038
1039 /* Could be re-setting the same value */
1040 CRM_CHECK(old_value != value, return value);
1041
1042 if (pcmk__check_acl(node, name, pcmk__xf_acl_write) == FALSE) {
1043 /* Create a fake object linked to doc->_private instead? */
1044 crm_trace("Cannot replace %s=%s to %s", name, value, node->name);
1045 return NULL;
1046
1047 } else if (old_value && !value) {
1049 return NULL;
1050 }
1051
1052 if (pcmk__tracking_xml_changes(node, FALSE)) {
1053 if (!old_value || !value || !strcmp(old_value, value)) {
1054 dirty = TRUE;
1055 }
1056 }
1057
1058 attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
1059 if (dirty) {
1061 }
1062 CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
1063 return (char *) attr->children->content;
1064}
1065
1066// LCOV_EXCL_STOP
1067// End deprecated API
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition acl.c:658
const char * parent
Definition cib.c:27
const char * name
Definition cib.c:26
#define pcmk__assert_alloc(nmemb, size)
Definition internal.h:297
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
int crm_str_to_boolean(const char *s, int *ret)
Definition strings.c:496
Deprecated Pacemaker utilities.
char data[0]
Definition cpg.c:10
A dumping ground.
#define CRM_META
Definition crm.h:81
G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
Definition xml.c:60
G_GNUC_INTERNAL void pcmk__mark_xml_attr_dirty(xmlAttr *a)
Definition xml_attr.c:31
crm_time_t * crm_time_new(const char *string)
Definition iso8601.c:112
struct crm_time_s crm_time_t
Definition iso8601.h:32
char * pcmk__epoch2str(const time_t *source, uint32_t flags)
Definition iso8601.c:2075
#define CRM_LOG_ASSERT(expr)
Definition logging.h:228
#define CRM_CHECK(expr, failure_action)
Definition logging.h:245
#define crm_err(fmt, args...)
Definition logging.h:389
#define crm_log_xml_trace(xml, text)
Definition logging.h:410
#define crm_trace(fmt, args...)
Definition logging.h:402
xmlNode * input
int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value)
Definition nvpair.c:909
GHashTable * xml2list(const xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition nvpair.c:859
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:398
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:596
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:446
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:422
void hash2nvpair(gpointer key, gpointer value, gpointer user_data)
Add XML nvpair element based on hash table entry.
Definition nvpair.c:834
char * pcmk_format_nvpair(const char *name, const char *value, const char *units)
Definition nvpair.c:1011
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition nvpair.c:482
GSList * pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
Prepend a name/value pair to a list.
Definition nvpair.c:90
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:799
void hash2metafield(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry, as meta-attribute name.
Definition nvpair.c:764
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
Definition nvpair.c:936
GSList * pcmk_sort_nvpairs(GSList *list)
Sort a list of name/value pairs.
Definition nvpair.c:145
void hash2field(gpointer key, gpointer value, gpointer user_data)
Set XML attribute based on hash table entry.
Definition nvpair.c:736
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:348
const char * crm_xml_replace(xmlNode *node, const char *name, const char *value)
Definition nvpair.c:1028
int pcmk_scan_nvpair(const char *input, char **name, char **value)
Definition nvpair.c:1005
int pcmk__scan_nvpair(const char *input, char **name, char **value)
Definition nvpair.c:220
char * pcmk__format_nvpair(const char *name, const char *value, const char *units)
Definition nvpair.c:283
void pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
Add XML attributes based on a list of name/value pairs.
Definition nvpair.c:200
void pcmk_free_nvpairs(GSList *nvpairs)
Free a list of name/value pairs.
Definition nvpair.c:101
int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
Retrieve the millisecond value of an XML attribute.
Definition nvpair.c:539
int pcmk__xe_get_datetime(const xmlNode *xml, const char *attr, crm_time_t **t)
Definition nvpair.c:644
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition nvpair.c:674
void hash2smartfield(gpointer key, gpointer value, gpointer user_data)
Safely add hash table entry to XML as attribute or name-value pair.
Definition nvpair.c:694
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:514
char * crm_meta_name(const char *attr_name)
Get the environment variable equivalent of a meta-attribute name.
Definition nvpair.c:959
void pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value)
Definition nvpair.c:903
char * pcmk_format_named_time(const char *name, time_t epoch_time)
Definition nvpair.c:1018
GSList * pcmk_xml_attrs2nvpairs(const xmlNode *xml)
Create a list of name/value pairs from an XML node's attributes.
Definition nvpair.c:160
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:567
const char * crm_meta_value(GHashTable *meta, const char *attr_name)
Get the value of a meta-attribute.
Definition nvpair.c:987
#define LLSTRSIZE
Definition nvpair.c:381
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:301
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:370
pcmk__action_result_t result
Definition pcmk_fence.c:35
#define ENODATA
#define CRM_ASSERT(expr)
Definition results.h:42
@ pcmk_rc_ok
Definition results.h:162
@ pcmk_rc_unpack_error
Definition results.h:125
@ pcmk_rc_bad_input
Definition results.h:122
#define pcmk_err_bad_nvpair
Definition results.h:98
#define pcmk_ok
Definition results.h:69
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition strings.c:701
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:683
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition strings.c:97
#define pcmk__str_copy(str)
#define PCMK__PARSE_INT_DEFAULT
char * value
Definition nvpair.h:31
char * name
Definition nvpair.h:30
Wrappers for and extensions to libxml2.
const xmlChar * pcmkXmlStr
Definition xml.h:41
void crm_xml_set_id(xmlNode *xml, const char *format,...) G_GNUC_PRINTF(2
void pcmk__xe_remove_attr(xmlNode *element, const char *name)
Definition xml.c:652
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition xml.c:440
xmlNode * pcmk__xe_next_same(const xmlNode *node)
Definition xml.c:2108
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
Definition xml.c:720
@ pcmk__xf_acl_create
@ pcmk__xf_acl_write
#define PCMK_XA_ID
Definition xml_names.h:296
#define PCMK_XA_VALUE
Definition xml_names.h:437
#define PCMK_XE_NVPAIR
Definition xml_names.h:141
#define PCMK_XA_NAME
Definition xml_names.h:325
#define PCMK__XE_ATTRIBUTES
#define PCMK__XE_PARAM