This source file includes following definitions.
- pcmk__new_nvpair
- pcmk__free_nvpair
- pcmk_prepend_nvpair
- pcmk_free_nvpairs
- pcmk__compare_nvpair
- pcmk_sort_nvpairs
- pcmk_xml_attrs2nvpairs
- pcmk__nvpair_add_xml_attr
- pcmk_nvpairs2xml_attrs
- pcmk_scan_nvpair
- pcmk_format_nvpair
- pcmk_format_named_time
- crm_xml_add
- crm_xml_replace
- crm_xml_add_int
- crm_xml_add_ms
- crm_xml_add_ll
- crm_xml_add_timeval
- crm_element_value
- crm_element_value_int
- crm_element_value_ll
- crm_element_value_ms
- crm_element_value_epoch
- crm_element_value_timeval
- crm_element_value_copy
- hash2smartfield
- hash2field
- hash2metafield
- crm_create_nvpair_xml
- hash2nvpair
- xml2list
1
2
3
4
5
6
7
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>
22 #include <crm/common/xml_internal.h>
23 #include <crm/common/iso8601_internal.h>
24 #include "crmcommon_private.h"
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 static pcmk_nvpair_t *
48 pcmk__new_nvpair(const char *name, const char *value)
49 {
50 pcmk_nvpair_t *nvpair = NULL;
51
52 CRM_ASSERT(name);
53
54 nvpair = calloc(1, sizeof(pcmk_nvpair_t));
55 CRM_ASSERT(nvpair);
56
57 nvpair->name = strdup(name);
58 nvpair->value = value? strdup(value) : NULL;
59 return nvpair;
60 }
61
62
63
64
65
66
67
68 static void
69 pcmk__free_nvpair(gpointer data)
70 {
71 if (data) {
72 pcmk_nvpair_t *nvpair = data;
73
74 free(nvpair->name);
75 free(nvpair->value);
76 free(nvpair);
77 }
78 }
79
80
81
82
83
84
85
86
87
88
89
90
91 GSList *
92 pcmk_prepend_nvpair(GSList *nvpairs, const char *name, const char *value)
93 {
94 return g_slist_prepend(nvpairs, pcmk__new_nvpair(name, value));
95 }
96
97
98
99
100
101
102 void
103 pcmk_free_nvpairs(GSList *nvpairs)
104 {
105 g_slist_free_full(nvpairs, pcmk__free_nvpair);
106 }
107
108
109
110
111
112
113
114
115
116
117 static gint
118 pcmk__compare_nvpair(gconstpointer a, gconstpointer b)
119 {
120 int rc = 0;
121 const pcmk_nvpair_t *pair_a = a;
122 const pcmk_nvpair_t *pair_b = b;
123
124 CRM_ASSERT(a != NULL);
125 CRM_ASSERT(pair_a->name != NULL);
126
127 CRM_ASSERT(b != NULL);
128 CRM_ASSERT(pair_b->name != NULL);
129
130 rc = strcmp(pair_a->name, pair_b->name);
131 if (rc < 0) {
132 return -1;
133 } else if (rc > 0) {
134 return 1;
135 }
136 return 0;
137 }
138
139
140
141
142
143
144
145
146 GSList *
147 pcmk_sort_nvpairs(GSList *list)
148 {
149 return g_slist_sort(list, pcmk__compare_nvpair);
150 }
151
152
153
154
155
156
157
158
159
160
161 GSList *
162 pcmk_xml_attrs2nvpairs(xmlNode *xml)
163 {
164 GSList *result = NULL;
165
166 for (xmlAttrPtr iter = pcmk__first_xml_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
176
177
178
179
180
181
182
183
184
185
186 static void
187 pcmk__nvpair_add_xml_attr(gpointer data, gpointer user_data)
188 {
189 pcmk_nvpair_t *pair = data;
190 xmlNode *parent = user_data;
191
192 crm_xml_add(parent, pair->name, pair->value);
193 }
194
195
196
197
198
199
200
201 void
202 pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
203 {
204 g_slist_foreach(list, pcmk__nvpair_add_xml_attr, xml);
205 }
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220 int
221 pcmk_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
246
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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281 char *
282 pcmk_format_nvpair(const char *name, const char *value, const char *units) {
283 return crm_strdup_printf("%s=\"%s%s\"", name, value, units ? units : "");
284 }
285
286
287
288
289
290
291
292
293
294
295
296
297 char *
298 pcmk_format_named_time(const char *name, time_t epoch_time) {
299 const char *now_str = pcmk__epoch2str(&epoch_time);
300
301 return crm_strdup_printf("%s=\"%s\"", name, now_str ? now_str : "");
302 }
303
304
305
306
307
308
309
310
311
312
313
314
315
316 const char *
317 crm_xml_add(xmlNode *node, const char *name, const char *value)
318 {
319 bool dirty = FALSE;
320 xmlAttr *attr = NULL;
321
322 CRM_CHECK(node != NULL, return NULL);
323 CRM_CHECK(name != NULL, return NULL);
324
325 if (value == NULL) {
326 return NULL;
327 }
328 #if XML_PARANOIA_CHECKS
329 {
330 const char *old_value = NULL;
331
332 old_value = crm_element_value(node, name);
333
334
335 CRM_CHECK(old_value != value,
336 crm_err("Cannot reset %s with crm_xml_add(%s)", name, value);
337 return value);
338 }
339 #endif
340
341 if (pcmk__tracking_xml_changes(node, FALSE)) {
342 const char *old = crm_element_value(node, name);
343
344 if (old == NULL || value == NULL || strcmp(old, value) != 0) {
345 dirty = TRUE;
346 }
347 }
348
349 if (dirty && (pcmk__check_acl(node, name, xpf_acl_create) == FALSE)) {
350 crm_trace("Cannot add %s=%s to %s", name, value, node->name);
351 return NULL;
352 }
353
354 attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
355 if (dirty) {
356 pcmk__mark_xml_attr_dirty(attr);
357 }
358
359 CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
360 return (char *)attr->children->content;
361 }
362
363
364
365
366
367
368
369
370
371
372
373 const char *
374 crm_xml_replace(xmlNode *node, const char *name, const char *value)
375 {
376 bool dirty = FALSE;
377 xmlAttr *attr = NULL;
378 const char *old_value = NULL;
379
380 CRM_CHECK(node != NULL, return NULL);
381 CRM_CHECK(name != NULL && name[0] != 0, return NULL);
382
383 old_value = crm_element_value(node, name);
384
385
386 CRM_CHECK(old_value != value, return value);
387
388 if (pcmk__check_acl(node, name, xpf_acl_write) == FALSE) {
389
390 crm_trace("Cannot replace %s=%s to %s", name, value, node->name);
391 return NULL;
392
393 } else if (old_value && !value) {
394 xml_remove_prop(node, name);
395 return NULL;
396 }
397
398 if (pcmk__tracking_xml_changes(node, FALSE)) {
399 if (!old_value || !value || !strcmp(old_value, value)) {
400 dirty = TRUE;
401 }
402 }
403
404 attr = xmlSetProp(node, (pcmkXmlStr) name, (pcmkXmlStr) value);
405 if (dirty) {
406 pcmk__mark_xml_attr_dirty(attr);
407 }
408 CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
409 return (char *) attr->children->content;
410 }
411
412
413
414
415
416
417
418
419
420
421
422
423
424 const char *
425 crm_xml_add_int(xmlNode *node, const char *name, int value)
426 {
427 char *number = crm_itoa(value);
428 const char *added = crm_xml_add(node, name, number);
429
430 free(number);
431 return added;
432 }
433
434
435
436
437
438
439
440
441
442
443
444
445
446 const char *
447 crm_xml_add_ms(xmlNode *node, const char *name, guint ms)
448 {
449 char *number = crm_strdup_printf("%u", ms);
450 const char *added = crm_xml_add(node, name, number);
451
452 free(number);
453 return added;
454 }
455
456
457
458 #define LLSTRSIZE 21
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474 const char *
475 crm_xml_add_ll(xmlNode *xml, const char *name, long long value)
476 {
477 char s[LLSTRSIZE] = { '\0', };
478
479 if (snprintf(s, LLSTRSIZE, "%lld", (long long) value) == LLSTRSIZE) {
480 return NULL;
481 }
482 return crm_xml_add(xml, name, s);
483 }
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498 const char *
499 crm_xml_add_timeval(xmlNode *xml, const char *name_sec, const char *name_usec,
500 const struct timeval *value)
501 {
502 const char *added = NULL;
503
504 if (xml && name_sec && value) {
505 added = crm_xml_add_ll(xml, name_sec, (long long) value->tv_sec);
506 if (added && name_usec) {
507
508 crm_xml_add_ll(xml, name_usec, (long long) value->tv_usec);
509 }
510 }
511 return added;
512 }
513
514
515
516
517
518
519
520
521
522 const char *
523 crm_element_value(const xmlNode *data, const char *name)
524 {
525 xmlAttr *attr = NULL;
526
527 if (data == NULL) {
528 crm_err("Couldn't find %s in NULL", name ? name : "<null>");
529 CRM_LOG_ASSERT(data != NULL);
530 return NULL;
531
532 } else if (name == NULL) {
533 crm_err("Couldn't find NULL in %s", crm_element_name(data));
534 return NULL;
535 }
536
537
538
539
540 attr = xmlHasProp((xmlNode *) data, (pcmkXmlStr) name);
541 if (!attr || !attr->children) {
542 return NULL;
543 }
544 return (const char *) attr->children->content;
545 }
546
547
548
549
550
551
552
553
554
555
556
557
558 int
559 crm_element_value_int(const xmlNode *data, const char *name, int *dest)
560 {
561 const char *value = NULL;
562
563 CRM_CHECK(dest != NULL, return -1);
564 value = crm_element_value(data, name);
565 if (value) {
566 errno = 0;
567 *dest = crm_parse_int(value, NULL);
568 if (errno == 0) {
569 return 0;
570 }
571 }
572 return -1;
573 }
574
575
576
577
578
579
580
581
582
583
584
585
586 int
587 crm_element_value_ll(const xmlNode *data, const char *name, long long *dest)
588 {
589 const char *value = NULL;
590
591 CRM_CHECK(dest != NULL, return -1);
592 value = crm_element_value(data, name);
593 if (value) {
594 errno = 0;
595 *dest = crm_parse_ll(value, NULL);
596 if (errno == 0) {
597 return 0;
598 }
599 }
600 return -1;
601 }
602
603
604
605
606
607
608
609
610
611
612
613
614 int
615 crm_element_value_ms(const xmlNode *data, const char *name, guint *dest)
616 {
617 const char *value = NULL;
618 long long value_ll;
619
620 CRM_CHECK(dest != NULL, return -1);
621 *dest = 0;
622
623 value = crm_element_value(data, name);
624 if (value == NULL) {
625 return pcmk_ok;
626 }
627
628 errno = 0;
629 value_ll = crm_parse_ll(value, NULL);
630 if ((errno != 0) || (value_ll < 0) || (value_ll > G_MAXUINT)) {
631 return -1;
632 }
633
634 *dest = (guint) value_ll;
635 return pcmk_ok;
636 }
637
638
639
640
641
642
643
644
645
646
647
648
649 int
650 crm_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
659
660
661 *dest = (time_t) value_ll;
662 return pcmk_ok;
663 }
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678 int
679 crm_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
693
694
695
696
697
698
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
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
714
715
716
717
718
719
720
721
722
723
724
725 char *
726 crm_element_value_copy(const xmlNode *data, const char *name)
727 {
728 char *value_copy = NULL;
729 const char *value = crm_element_value(data, name);
730
731 if (value != NULL) {
732 value_copy = strdup(value);
733 }
734 return value_copy;
735 }
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750 void
751 hash2smartfield(gpointer key, gpointer value, gpointer user_data)
752 {
753 const char *name = key;
754 const char *s_value = value;
755
756 xmlNode *xml_node = user_data;
757
758 if (isdigit(name[0])) {
759 xmlNode *tmp = create_xml_node(xml_node, XML_TAG_PARAM);
760
761 crm_xml_add(tmp, XML_NVPAIR_ATTR_NAME, name);
762 crm_xml_add(tmp, XML_NVPAIR_ATTR_VALUE, s_value);
763
764 } else if (crm_element_value(xml_node, name) == NULL) {
765 crm_xml_add(xml_node, name, s_value);
766 crm_trace("dumped: %s=%s", name, s_value);
767
768 } else {
769 crm_trace("duplicate: %s=%s", name, s_value);
770 }
771 }
772
773
774
775
776
777
778
779
780
781
782
783
784 void
785 hash2field(gpointer key, gpointer value, gpointer user_data)
786 {
787 const char *name = key;
788 const char *s_value = value;
789
790 xmlNode *xml_node = user_data;
791
792 if (crm_element_value(xml_node, name) == NULL) {
793 crm_xml_add(xml_node, name, s_value);
794
795 } else {
796 crm_trace("duplicate: %s=%s", name, s_value);
797 }
798 }
799
800
801
802
803
804
805
806
807
808
809
810
811
812 void
813 hash2metafield(gpointer key, gpointer value, gpointer user_data)
814 {
815 char *crm_name = NULL;
816
817 if (key == NULL || value == NULL) {
818 return;
819 }
820
821
822
823
824 for (crm_name = key; *crm_name; ++crm_name) {
825 if ((*crm_name == '#') || (*crm_name == ':')) {
826 return;
827 }
828 }
829
830 crm_name = crm_meta_name(key);
831 hash2field(crm_name, value, user_data);
832 free(crm_name);
833 }
834
835
836
837
838
839
840
841
842
843
844
845
846
847 xmlNode *
848 crm_create_nvpair_xml(xmlNode *parent, const char *id, const char *name,
849 const char *value)
850 {
851 xmlNode *nvp;
852
853
854
855
856 CRM_CHECK(id || name, return NULL);
857
858 nvp = create_xml_node(parent, XML_CIB_TAG_NVPAIR);
859 CRM_CHECK(nvp, return NULL);
860
861 if (id) {
862 crm_xml_add(nvp, XML_ATTR_ID, id);
863 } else {
864 const char *parent_id = ID(parent);
865
866 crm_xml_set_id(nvp, "%s-%s",
867 (parent_id? parent_id : XML_CIB_TAG_NVPAIR), name);
868 }
869 crm_xml_add(nvp, XML_NVPAIR_ATTR_NAME, name);
870 crm_xml_add(nvp, XML_NVPAIR_ATTR_VALUE, value);
871 return nvp;
872 }
873
874
875
876
877
878
879
880
881
882
883
884
885 void
886 hash2nvpair(gpointer key, gpointer value, gpointer user_data)
887 {
888 const char *name = key;
889 const char *s_value = value;
890 xmlNode *xml_node = user_data;
891
892 crm_create_nvpair_xml(xml_node, name, name, s_value);
893 crm_trace("dumped: name=%s value=%s", name, s_value);
894 }
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910 GHashTable *
911 xml2list(xmlNode *parent)
912 {
913 xmlNode *child = NULL;
914 xmlAttrPtr pIter = NULL;
915 xmlNode *nvpair_list = NULL;
916 GHashTable *nvpair_hash = crm_str_table_new();
917
918 CRM_CHECK(parent != NULL, return nvpair_hash);
919
920 nvpair_list = find_xml_node(parent, XML_TAG_ATTRS, FALSE);
921 if (nvpair_list == NULL) {
922 crm_trace("No attributes in %s", crm_element_name(parent));
923 crm_log_xml_trace(parent, "No attributes for resource op");
924 }
925
926 crm_log_xml_trace(nvpair_list, "Unpacking");
927
928 for (pIter = pcmk__first_xml_attr(nvpair_list); pIter != NULL;
929 pIter = pIter->next) {
930
931 const char *p_name = (const char *)pIter->name;
932 const char *p_value = pcmk__xml_attr_value(pIter);
933
934 crm_trace("Added %s=%s", p_name, p_value);
935
936 g_hash_table_insert(nvpair_hash, strdup(p_name), strdup(p_value));
937 }
938
939 for (child = pcmk__xml_first_child(nvpair_list); child != NULL;
940 child = pcmk__xml_next(child)) {
941
942 if (strcmp((const char *)child->name, XML_TAG_PARAM) == 0) {
943 const char *key = crm_element_value(child, XML_NVPAIR_ATTR_NAME);
944 const char *value = crm_element_value(child, XML_NVPAIR_ATTR_VALUE);
945
946 crm_trace("Added %s=%s", key, value);
947 if (key != NULL && value != NULL) {
948 g_hash_table_insert(nvpair_hash, strdup(key), strdup(value));
949 }
950 }
951 }
952
953 return nvpair_hash;
954 }