This source file includes following definitions.
- pcmk__new_nvpair
- pcmk__free_nvpair
- pcmk_prepend_nvpair
- pcmk_free_nvpairs
- pcmk__scan_nvpair
- pcmk__format_nvpair
- hash2smartfield
- hash2field
- hash2metafield
- crm_create_nvpair_xml
- xml2list
- crm_meta_name
- crm_meta_value
- pcmk__cmp_nvpair_blocks
- pcmk__compare_nvpair
- pcmk_sort_nvpairs
- pcmk_xml_attrs2nvpairs
- pcmk__nvpair_add_xml_attr
- pcmk_nvpairs2xml_attrs
- hash2nvpair
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdio.h>
13 #include <stdint.h>
14 #include <inttypes.h>
15 #include <sys/types.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <glib.h>
19 #include <libxml/tree.h>
20
21 #include <crm/crm.h>
22 #include <crm/common/xml.h>
23 #include <crm/common/xml_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
48 static pcmk_nvpair_t *
49 pcmk__new_nvpair(const char *name, const char *value)
50 {
51 pcmk_nvpair_t *nvpair = NULL;
52
53 pcmk__assert(name);
54
55 nvpair = pcmk__assert_alloc(1, sizeof(pcmk_nvpair_t));
56
57 nvpair->name = pcmk__str_copy(name);
58 nvpair->value = pcmk__str_copy(value);
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
118
119
120
121
122
123 int
124 pcmk__scan_nvpair(const char *input, char **name, char **value)
125 {
126 #ifdef HAVE_SSCANF_M
127 *name = NULL;
128 *value = NULL;
129 if (sscanf(input, "%m[^=]=%m[^\n]", name, value) <= 0) {
130 return -pcmk_err_bad_nvpair;
131 }
132 #else
133 char *sep = NULL;
134 *name = NULL;
135 *value = NULL;
136
137 sep = strstr(optarg, "=");
138 if (sep == NULL) {
139 return -pcmk_err_bad_nvpair;
140 }
141
142 *name = strndup(input, sep-input);
143
144 if (*name == NULL) {
145 return -ENOMEM;
146 }
147
148
149
150
151 if (*(sep+1) != '\0') {
152 *value = strdup(sep+1);
153
154 if (*value == NULL) {
155 return -ENOMEM;
156 }
157 }
158 #endif
159
160 if (*name != NULL && *value != NULL) {
161 return 2;
162 } else if (*name != NULL || *value != NULL) {
163 return 1;
164 } else {
165 return -pcmk_err_bad_nvpair;
166 }
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186 char *
187 pcmk__format_nvpair(const char *name, const char *value, const char *units)
188 {
189 return crm_strdup_printf("%s=\"%s%s\"", name, value, units ? units : "");
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206 void
207 hash2smartfield(gpointer key, gpointer value, gpointer user_data)
208 {
209
210
211
212
213
214
215
216
217 const char *name = key;
218 const char *s_value = value;
219
220 xmlNode *xml_node = user_data;
221
222 if (isdigit(name[0])) {
223 xmlNode *tmp = pcmk__xe_create(xml_node, PCMK__XE_PARAM);
224
225 crm_xml_add(tmp, PCMK_XA_NAME, name);
226 crm_xml_add(tmp, PCMK_XA_VALUE, s_value);
227
228 } else if (crm_element_value(xml_node, name) == NULL) {
229 crm_xml_add(xml_node, name, s_value);
230 crm_trace("dumped: %s=%s", name, s_value);
231
232 } else {
233 crm_trace("duplicate: %s=%s", name, s_value);
234 }
235 }
236
237
238
239
240
241
242
243
244
245
246
247
248 void
249 hash2field(gpointer key, gpointer value, gpointer user_data)
250 {
251 const char *name = key;
252 const char *s_value = value;
253
254 xmlNode *xml_node = user_data;
255
256 if (crm_element_value(xml_node, name) == NULL) {
257 crm_xml_add(xml_node, name, s_value);
258
259 } else {
260 crm_trace("duplicate: %s=%s", name, s_value);
261 }
262 }
263
264
265
266
267
268
269
270
271
272
273
274
275
276 void
277 hash2metafield(gpointer key, gpointer value, gpointer user_data)
278 {
279 char *crm_name = NULL;
280
281 if (key == NULL || value == NULL) {
282 return;
283 }
284
285
286
287
288 for (crm_name = key; *crm_name; ++crm_name) {
289 if ((*crm_name == '#') || (*crm_name == ':')) {
290 return;
291 }
292 }
293
294 crm_name = crm_meta_name(key);
295 hash2field(crm_name, value, user_data);
296 free(crm_name);
297 }
298
299
300
301
302
303
304
305
306
307
308
309
310
311 xmlNode *
312 crm_create_nvpair_xml(xmlNode *parent, const char *id, const char *name,
313 const char *value)
314 {
315 xmlNode *nvp;
316
317
318
319
320 CRM_CHECK(id || name, return NULL);
321
322 nvp = pcmk__xe_create(parent, PCMK_XE_NVPAIR);
323
324 if (id) {
325 crm_xml_add(nvp, PCMK_XA_ID, id);
326 } else {
327 pcmk__xe_set_id(nvp, "%s-%s",
328 pcmk__s(pcmk__xe_id(parent), PCMK_XE_NVPAIR), name);
329 }
330 crm_xml_add(nvp, PCMK_XA_NAME, name);
331 crm_xml_add(nvp, PCMK_XA_VALUE, value);
332 return nvp;
333 }
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349 GHashTable *
350 xml2list(const xmlNode *parent)
351 {
352 xmlNode *child = NULL;
353 xmlAttrPtr pIter = NULL;
354 xmlNode *nvpair_list = NULL;
355 GHashTable *nvpair_hash = pcmk__strkey_table(free, free);
356
357 CRM_CHECK(parent != NULL, return nvpair_hash);
358
359 nvpair_list = pcmk__xe_first_child(parent, PCMK__XE_ATTRIBUTES, NULL, NULL);
360 if (nvpair_list == NULL) {
361 crm_trace("No attributes in %s", parent->name);
362 crm_log_xml_trace(parent, "No attributes for resource op");
363 }
364
365 crm_log_xml_trace(nvpair_list, "Unpacking");
366
367 for (pIter = pcmk__xe_first_attr(nvpair_list); pIter != NULL;
368 pIter = pIter->next) {
369
370 const char *p_name = (const char *)pIter->name;
371 const char *p_value = pcmk__xml_attr_value(pIter);
372
373 crm_trace("Added %s=%s", p_name, p_value);
374
375 pcmk__insert_dup(nvpair_hash, p_name, p_value);
376 }
377
378 for (child = pcmk__xe_first_child(nvpair_list, PCMK__XE_PARAM, NULL, NULL);
379 child != NULL; child = pcmk__xe_next(child, PCMK__XE_PARAM)) {
380
381 const char *key = crm_element_value(child, PCMK_XA_NAME);
382 const char *value = crm_element_value(child, PCMK_XA_VALUE);
383
384 crm_trace("Added %s=%s", key, value);
385 if (key != NULL && value != NULL) {
386 pcmk__insert_dup(nvpair_hash, key, value);
387 }
388 }
389
390 return nvpair_hash;
391 }
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406 char *
407 crm_meta_name(const char *attr_name)
408 {
409 char *env_name = NULL;
410
411 pcmk__assert(!pcmk__str_empty(attr_name));
412
413 env_name = crm_strdup_printf(CRM_META "_%s", attr_name);
414 for (char *c = env_name; *c != '\0'; ++c) {
415 if (*c == '-') {
416 *c = '_';
417 }
418 }
419 return env_name;
420 }
421
422
423
424
425
426
427
428
429
430
431
432
433
434 const char *
435 crm_meta_value(GHashTable *meta, const char *attr_name)
436 {
437 if ((meta != NULL) && (attr_name != NULL)) {
438 char *key = crm_meta_name(attr_name);
439 const char *value = g_hash_table_lookup(meta, key);
440
441 free(key);
442 return value;
443 }
444 return NULL;
445 }
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463 gint
464 pcmk__cmp_nvpair_blocks(gconstpointer a, gconstpointer b, gpointer user_data)
465 {
466 const xmlNode *pair_a = a;
467 const xmlNode *pair_b = b;
468 const pcmk__nvpair_unpack_t *unpack_data = user_data;
469
470 int score_a = 0;
471 int score_b = 0;
472 int rc = pcmk_rc_ok;
473
474
475
476
477
478
479 const gint a_is_higher = ((unpack_data != NULL)
480 && unpack_data->overwrite)? 1 : -1;
481 const gint b_is_higher = -a_is_higher;
482
483
484
485
486 if (a == NULL) {
487 return (b == NULL)? 0 : b_is_higher;
488
489 } else if (b == NULL) {
490 return a_is_higher;
491 }
492
493
494
495
496
497
498 if ((unpack_data != NULL) && (unpack_data->first_id != NULL)) {
499 if (pcmk__str_eq(pcmk__xe_id(pair_a), unpack_data->first_id,
500 pcmk__str_none)) {
501 return a_is_higher;
502
503 } else if (pcmk__str_eq(pcmk__xe_id(pair_b), unpack_data->first_id,
504 pcmk__str_none)) {
505 return b_is_higher;
506 }
507 }
508
509
510
511 rc = pcmk__xe_get_score(pair_a, PCMK_XA_SCORE, &score_a, 0);
512 if (rc != pcmk_rc_ok) {
513 pcmk__config_warn("Using 0 as %s score because '%s' "
514 "is not a valid score: %s",
515 pcmk__xe_id(pair_a),
516 crm_element_value(pair_a, PCMK_XA_SCORE),
517 pcmk_rc_str(rc));
518 }
519
520 rc = pcmk__xe_get_score(pair_b, PCMK_XA_SCORE, &score_b, 0);
521 if (rc != pcmk_rc_ok) {
522 pcmk__config_warn("Using 0 as %s score because '%s' "
523 "is not a valid score: %s",
524 pcmk__xe_id(pair_b),
525 crm_element_value(pair_b, PCMK_XA_SCORE),
526 pcmk_rc_str(rc));
527 }
528
529 if (score_a < score_b) {
530 return b_is_higher;
531
532 } else if (score_a > score_b) {
533 return a_is_higher;
534 }
535 return 0;
536 }
537
538
539
540
541 #include <crm/common/nvpair_compat.h>
542
543 static gint
544 pcmk__compare_nvpair(gconstpointer a, gconstpointer b)
545 {
546 int rc = 0;
547 const pcmk_nvpair_t *pair_a = a;
548 const pcmk_nvpair_t *pair_b = b;
549
550 pcmk__assert((pair_a != NULL) && (pair_a->name != NULL)
551 && (pair_b != NULL) && (pair_b->name != NULL));
552
553 rc = strcmp(pair_a->name, pair_b->name);
554 if (rc < 0) {
555 return -1;
556 } else if (rc > 0) {
557 return 1;
558 }
559 return 0;
560 }
561
562 GSList *
563 pcmk_sort_nvpairs(GSList *list)
564 {
565 return g_slist_sort(list, pcmk__compare_nvpair);
566 }
567
568 GSList *
569 pcmk_xml_attrs2nvpairs(const xmlNode *xml)
570 {
571 GSList *result = NULL;
572
573 for (xmlAttrPtr iter = pcmk__xe_first_attr(xml); iter != NULL;
574 iter = iter->next) {
575
576 result = pcmk_prepend_nvpair(result,
577 (const char *) iter->name,
578 (const char *) pcmk__xml_attr_value(iter));
579 }
580 return result;
581 }
582
583 static void
584 pcmk__nvpair_add_xml_attr(gpointer data, gpointer user_data)
585 {
586 pcmk_nvpair_t *pair = data;
587 xmlNode *parent = user_data;
588
589 crm_xml_add(parent, pair->name, pair->value);
590 }
591
592 void
593 pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
594 {
595 g_slist_foreach(list, pcmk__nvpair_add_xml_attr, xml);
596 }
597
598 void
599 hash2nvpair(gpointer key, gpointer value, gpointer user_data)
600 {
601 const char *name = key;
602 const char *s_value = value;
603 xmlNode *xml_node = user_data;
604
605 crm_create_nvpair_xml(xml_node, name, name, s_value);
606 crm_trace("dumped: name=%s value=%s", name, s_value);
607 }
608
609
610