1 /*
2 * Copyright 2004-2023 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/common/results.h"
11 #include <crm_internal.h>
12
13 #ifndef _GNU_SOURCE
14 # define _GNU_SOURCE
15 #endif
16
17 #include <regex.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <ctype.h>
22 #include <float.h> // DBL_MIN
23 #include <limits.h>
24 #include <bzlib.h>
25 #include <sys/types.h>
26
27 /*!
28 * \internal
29 * \brief Scan a long long integer from a string
30 *
31 * \param[in] text String to scan
32 * \param[out] result If not NULL, where to store scanned value
33 * \param[in] default_value Value to use if text is NULL or invalid
34 * \param[out] end_text If not NULL, where to store pointer to first
35 * non-integer character
36 *
37 * \return Standard Pacemaker return code (\c pcmk_rc_ok on success,
38 * \c EINVAL on failed string conversion due to invalid input,
39 * or \c EOVERFLOW on arithmetic overflow)
40 * \note Sets \c errno on error
41 */
42 static int
43 scan_ll(const char *text, long long *result, long long default_value,
44 char **end_text)
45 {
46 long long local_result = default_value;
47 char *local_end_text = NULL;
48 int rc = pcmk_rc_ok;
49
50 errno = 0;
51 if (text != NULL) {
52 local_result = strtoll(text, &local_end_text, 10);
53 if (errno == ERANGE) {
54 rc = EOVERFLOW;
55 crm_warn("Integer parsed from '%s' was clipped to %lld",
56 text, local_result);
57
58 } else if (errno != 0) {
59 rc = errno;
60 local_result = default_value;
61 crm_warn("Could not parse integer from '%s' (using %lld instead): "
62 "%s", text, default_value, pcmk_rc_str(rc));
63
64 } else if (local_end_text == text) {
65 rc = EINVAL;
66 local_result = default_value;
67 crm_warn("Could not parse integer from '%s' (using %lld instead): "
68 "No digits found", text, default_value);
69 }
70
71 if ((end_text == NULL) && !pcmk__str_empty(local_end_text)) {
72 crm_warn("Characters left over after parsing '%s': '%s'",
73 text, local_end_text);
74 }
75 errno = rc;
76 }
77 if (end_text != NULL) {
78 *end_text = local_end_text;
79 }
80 if (result != NULL) {
81 *result = local_result;
82 }
83 return rc;
84 }
85
86 /*!
87 * \internal
88 * \brief Scan a long long integer value from a string
89 *
90 * \param[in] text The string to scan (may be NULL)
91 * \param[out] result Where to store result (or NULL to ignore)
92 * \param[in] default_value Value to use if text is NULL or invalid
93 *
94 * \return Standard Pacemaker return code
95 */
96 int
97 pcmk__scan_ll(const char *text, long long *result, long long default_value)
98 {
99 long long local_result = default_value;
100 int rc = pcmk_rc_ok;
101
102 if (text != NULL) {
103 rc = scan_ll(text, &local_result, default_value, NULL);
104 if (rc != pcmk_rc_ok) {
105 local_result = default_value;
106 }
107 }
108 if (result != NULL) {
109 *result = local_result;
110 }
111 return rc;
112 }
113
114 /*!
115 * \internal
116 * \brief Scan an integer value from a string, constrained to a minimum
117 *
118 * \param[in] text The string to scan (may be NULL)
119 * \param[out] result Where to store result (or NULL to ignore)
120 * \param[in] minimum Value to use as default and minimum
121 *
122 * \return Standard Pacemaker return code
123 * \note If the value is larger than the maximum integer, EOVERFLOW will be
124 * returned and \p result will be set to the maximum integer.
125 */
126 int
127 pcmk__scan_min_int(const char *text, int *result, int minimum)
128 {
129 int rc;
130 long long result_ll;
131
132 rc = pcmk__scan_ll(text, &result_ll, (long long) minimum);
133
134 if (result_ll < (long long) minimum) {
135 crm_warn("Clipped '%s' to minimum acceptable value %d", text, minimum);
136 result_ll = (long long) minimum;
137
138 } else if (result_ll > INT_MAX) {
139 crm_warn("Clipped '%s' to maximum integer %d", text, INT_MAX);
140 result_ll = (long long) INT_MAX;
141 rc = EOVERFLOW;
142 }
143
144 if (result != NULL) {
145 *result = (int) result_ll;
146 }
147 return rc;
148 }
149
150 /*!
151 * \internal
152 * \brief Scan a TCP port number from a string
153 *
154 * \param[in] text The string to scan
155 * \param[out] port Where to store result (or NULL to ignore)
156 *
157 * \return Standard Pacemaker return code
158 * \note \p port will be -1 if \p text is NULL or invalid
159 */
160 int
161 pcmk__scan_port(const char *text, int *port)
162 {
163 long long port_ll;
164 int rc = pcmk__scan_ll(text, &port_ll, -1LL);
165
166 if ((text != NULL) && (rc == pcmk_rc_ok) // wasn't default or invalid
167 && ((port_ll < 0LL) || (port_ll > 65535LL))) {
168 crm_warn("Ignoring port specification '%s' "
169 "not in valid range (0-65535)", text);
170 rc = (port_ll < 0LL)? pcmk_rc_before_range : pcmk_rc_after_range;
171 port_ll = -1LL;
172 }
173 if (port != NULL) {
174 *port = (int) port_ll;
175 }
176 return rc;
177 }
178
179 /*!
180 * \internal
181 * \brief Scan a double-precision floating-point value from a string
182 *
183 * \param[in] text The string to parse
184 * \param[out] result Parsed value on success, or
185 * \c PCMK__PARSE_DBL_DEFAULT on error
186 * \param[in] default_text Default string to parse if \p text is
187 * \c NULL
188 * \param[out] end_text If not \c NULL, where to store a pointer
189 * to the position immediately after the
190 * value
191 *
192 * \return Standard Pacemaker return code (\c pcmk_rc_ok on success,
193 * \c EINVAL on failed string conversion due to invalid input,
194 * \c EOVERFLOW on arithmetic overflow, \c pcmk_rc_underflow
195 * on arithmetic underflow, or \c errno from \c strtod() on
196 * other parse errors)
197 */
198 int
199 pcmk__scan_double(const char *text, double *result, const char *default_text,
200 char **end_text)
201 {
202 int rc = pcmk_rc_ok;
203 char *local_end_text = NULL;
204
205 CRM_ASSERT(result != NULL);
206 *result = PCMK__PARSE_DBL_DEFAULT;
207
208 text = (text != NULL) ? text : default_text;
209
210 if (text == NULL) {
211 rc = EINVAL;
212 crm_debug("No text and no default conversion value supplied");
213
214 } else {
215 errno = 0;
216 *result = strtod(text, &local_end_text);
217
218 if (errno == ERANGE) {
219 /*
220 * Overflow: strtod() returns +/- HUGE_VAL and sets errno to
221 * ERANGE
222 *
223 * Underflow: strtod() returns "a value whose magnitude is
224 * no greater than the smallest normalized
225 * positive" double. Whether ERANGE is set is
226 * implementation-defined.
227 */
228 const char *over_under;
229
230 if (QB_ABS(*result) > DBL_MIN) {
231 rc = EOVERFLOW;
232 over_under = "over";
233 } else {
234 rc = pcmk_rc_underflow;
235 over_under = "under";
236 }
237
238 crm_debug("Floating-point value parsed from '%s' would %sflow "
239 "(using %g instead)", text, over_under, *result);
240
241 } else if (errno != 0) {
242 rc = errno;
243 // strtod() set *result = 0 on parse failure
244 *result = PCMK__PARSE_DBL_DEFAULT;
245
246 crm_debug("Could not parse floating-point value from '%s' (using "
247 "%.1f instead): %s", text, PCMK__PARSE_DBL_DEFAULT,
248 pcmk_rc_str(rc));
249
250 } else if (local_end_text == text) {
251 // errno == 0, but nothing was parsed
252 rc = EINVAL;
253 *result = PCMK__PARSE_DBL_DEFAULT;
254
255 crm_debug("Could not parse floating-point value from '%s' (using "
256 "%.1f instead): No digits found", text,
257 PCMK__PARSE_DBL_DEFAULT);
258
259 } else if (QB_ABS(*result) <= DBL_MIN) {
260 /*
261 * errno == 0 and text was parsed, but value might have
262 * underflowed.
263 *
264 * ERANGE might not be set for underflow. Check magnitude
265 * of *result, but also make sure the input number is not
266 * actually zero (0 <= DBL_MIN is not underflow).
267 *
268 * This check must come last. A parse failure in strtod()
269 * also sets *result == 0, so a parse failure would match
270 * this test condition prematurely.
271 */
272 for (const char *p = text; p != local_end_text; p++) {
273 if (strchr("0.eE", *p) == NULL) {
274 rc = pcmk_rc_underflow;
275 crm_debug("Floating-point value parsed from '%s' would "
276 "underflow (using %g instead)", text, *result);
277 break;
278 }
279 }
280
281 } else {
282 crm_trace("Floating-point value parsed successfully from "
283 "'%s': %g", text, *result);
284 }
285
286 if ((end_text == NULL) && !pcmk__str_empty(local_end_text)) {
287 crm_debug("Characters left over after parsing '%s': '%s'",
288 text, local_end_text);
289 }
290 }
291
292 if (end_text != NULL) {
293 *end_text = local_end_text;
294 }
295
296 return rc;
297 }
298
299 /*!
300 * \internal
301 * \brief Parse a guint from a string stored in a hash table
302 *
303 * \param[in] table Hash table to search
304 * \param[in] key Hash table key to use to retrieve string
305 * \param[in] default_val What to use if key has no entry in table
306 * \param[out] result If not NULL, where to store parsed integer
307 *
308 * \return Standard Pacemaker return code
309 */
310 int
311 pcmk__guint_from_hash(GHashTable *table, const char *key, guint default_val,
312 guint *result)
313 {
314 const char *value;
315 long long value_ll;
316 int rc = pcmk_rc_ok;
317
318 CRM_CHECK((table != NULL) && (key != NULL), return EINVAL);
319
320 if (result != NULL) {
321 *result = default_val;
322 }
323
324 value = g_hash_table_lookup(table, key);
325 if (value == NULL) {
326 return pcmk_rc_ok;
327 }
328
329 rc = pcmk__scan_ll(value, &value_ll, 0LL);
330 if (rc != pcmk_rc_ok) {
331 return rc;
332 }
333
334 if ((value_ll < 0) || (value_ll > G_MAXUINT)) {
335 crm_warn("Could not parse non-negative integer from %s", value);
336 return ERANGE;
337 }
338
339 if (result != NULL) {
340 *result = (guint) value_ll;
341 }
342 return pcmk_rc_ok;
343 }
344
345 #ifndef NUMCHARS
346 # define NUMCHARS "0123456789."
347 #endif
348
349 #ifndef WHITESPACE
350 # define WHITESPACE " \t\n\r\f"
351 #endif
352
353 /*!
354 * \brief Parse a time+units string and return milliseconds equivalent
355 *
356 * \param[in] input String with a number and optional unit (optionally
357 * with whitespace before and/or after the number). If
358 * missing, the unit defaults to seconds.
359 *
360 * \return Milliseconds corresponding to string expression, or
361 * PCMK__PARSE_INT_DEFAULT on error
362 */
363 long long
364 crm_get_msec(const char *input)
365 {
366 const char *num_start = NULL;
367 const char *units;
368 long long multiplier = 1000;
369 long long divisor = 1;
370 long long msec = PCMK__PARSE_INT_DEFAULT;
371 size_t num_len = 0;
372 char *end_text = NULL;
373
374 if (input == NULL) {
375 return PCMK__PARSE_INT_DEFAULT;
376 }
377
378 num_start = input + strspn(input, WHITESPACE);
379 num_len = strspn(num_start, NUMCHARS);
380 if (num_len < 1) {
381 return PCMK__PARSE_INT_DEFAULT;
382 }
383 units = num_start + num_len;
384 units += strspn(units, WHITESPACE);
385
386 if (!strncasecmp(units, "ms", 2) || !strncasecmp(units, "msec", 4)) {
387 multiplier = 1;
388 divisor = 1;
389 } else if (!strncasecmp(units, "us", 2) || !strncasecmp(units, "usec", 4)) {
390 multiplier = 1;
391 divisor = 1000;
392 } else if (!strncasecmp(units, "s", 1) || !strncasecmp(units, "sec", 3)) {
393 multiplier = 1000;
394 divisor = 1;
395 } else if (!strncasecmp(units, "m", 1) || !strncasecmp(units, "min", 3)) {
396 multiplier = 60 * 1000;
397 divisor = 1;
398 } else if (!strncasecmp(units, "h", 1) || !strncasecmp(units, "hr", 2)) {
399 multiplier = 60 * 60 * 1000;
400 divisor = 1;
401 } else if ((*units != '\0') && (*units != '\n') && (*units != '\r')) {
402 return PCMK__PARSE_INT_DEFAULT;
403 }
404
405 scan_ll(num_start, &msec, PCMK__PARSE_INT_DEFAULT, &end_text);
406 if (msec > (LLONG_MAX / multiplier)) {
407 // Arithmetics overflow while multiplier/divisor mutually exclusive
408 return LLONG_MAX;
409 }
410 msec *= multiplier;
411 msec /= divisor;
412 return msec;
413 }
414
415 gboolean
416 crm_is_true(const char *s)
417 {
418 gboolean ret = FALSE;
419
420 return (crm_str_to_boolean(s, &ret) < 0)? FALSE : ret;
421 }
422
423 int
424 crm_str_to_boolean(const char *s, int *ret)
425 {
426 if (s == NULL) {
427 return -1;
428
429 } else if (strcasecmp(s, "true") == 0
430 || strcasecmp(s, "on") == 0
431 || strcasecmp(s, "yes") == 0 || strcasecmp(s, "y") == 0 || strcasecmp(s, "1") == 0) {
432 *ret = TRUE;
433 return 1;
434
435 } else if (strcasecmp(s, "false") == 0
436 || strcasecmp(s, "off") == 0
437 || strcasecmp(s, "no") == 0 || strcasecmp(s, "n") == 0 || strcasecmp(s, "0") == 0) {
438 *ret = FALSE;
439 return 1;
440 }
441 return -1;
442 }
443
444 /*!
445 * \internal
446 * \brief Replace any trailing newlines in a string with \0's
447 *
448 * \param[in,out] str String to trim
449 *
450 * \return \p str
451 */
452 char *
453 pcmk__trim(char *str)
454 {
455 int len;
456
457 if (str == NULL) {
458 return str;
459 }
460
461 for (len = strlen(str) - 1; len >= 0 && str[len] == '\n'; len--) {
462 str[len] = '\0';
463 }
464
465 return str;
466 }
467
468 /*!
469 * \brief Check whether a string starts with a certain sequence
470 *
471 * \param[in] str String to check
472 * \param[in] prefix Sequence to match against beginning of \p str
473 *
474 * \return \c true if \p str begins with match, \c false otherwise
475 * \note This is equivalent to !strncmp(s, prefix, strlen(prefix))
476 * but is likely less efficient when prefix is a string literal
477 * if the compiler optimizes away the strlen() at compile time,
478 * and more efficient otherwise.
479 */
480 bool
481 pcmk__starts_with(const char *str, const char *prefix)
482 {
483 const char *s = str;
484 const char *p = prefix;
485
486 if (!s || !p) {
487 return false;
488 }
489 while (*s && *p) {
490 if (*s++ != *p++) {
491 return false;
492 }
493 }
494 return (*p == 0);
495 }
496
497 static inline bool
498 ends_with(const char *s, const char *match, bool as_extension)
499 {
500 if (pcmk__str_empty(match)) {
501 return true;
502 } else if (s == NULL) {
503 return false;
504 } else {
505 size_t slen, mlen;
506
507 /* Besides as_extension, we could also check
508 !strchr(&match[1], match[0]) but that would be inefficient.
509 */
510 if (as_extension) {
511 s = strrchr(s, match[0]);
512 return (s == NULL)? false : !strcmp(s, match);
513 }
514
515 mlen = strlen(match);
516 slen = strlen(s);
517 return ((slen >= mlen) && !strcmp(s + slen - mlen, match));
518 }
519 }
520
521 /*!
522 * \internal
523 * \brief Check whether a string ends with a certain sequence
524 *
525 * \param[in] s String to check
526 * \param[in] match Sequence to match against end of \p s
527 *
528 * \return \c true if \p s ends case-sensitively with match, \c false otherwise
529 * \note pcmk__ends_with_ext() can be used if the first character of match
530 * does not recur in match.
531 */
532 bool
533 pcmk__ends_with(const char *s, const char *match)
534 {
535 return ends_with(s, match, false);
536 }
537
538 /*!
539 * \internal
540 * \brief Check whether a string ends with a certain "extension"
541 *
542 * \param[in] s String to check
543 * \param[in] match Extension to match against end of \p s, that is,
544 * its first character must not occur anywhere
545 * in the rest of that very sequence (example: file
546 * extension where the last dot is its delimiter,
547 * e.g., ".html"); incorrect results may be
548 * returned otherwise.
549 *
550 * \return \c true if \p s ends (verbatim, i.e., case sensitively)
551 * with "extension" designated as \p match (including empty
552 * string), \c false otherwise
553 *
554 * \note Main incentive to prefer this function over \c pcmk__ends_with()
555 * where possible is the efficiency (at the cost of added
556 * restriction on \p match as stated; the complexity class
557 * remains the same, though: BigO(M+N) vs. BigO(M+2N)).
558 */
559 bool
560 pcmk__ends_with_ext(const char *s, const char *match)
561 {
562 return ends_with(s, match, true);
563 }
564
565 /*!
566 * \internal
567 * \brief Create a hash of a string suitable for use with GHashTable
568 *
569 * \param[in] v String to hash
570 *
571 * \return A hash of \p v compatible with g_str_hash() before glib 2.28
572 * \note glib changed their hash implementation:
573 *
574 * https://gitlab.gnome.org/GNOME/glib/commit/354d655ba8a54b754cb5a3efb42767327775696c
575 *
576 * Note that the new g_str_hash is presumably a *better* hash (it's actually
577 * a correct implementation of DJB's hash), but we need to preserve existing
578 * behaviour, because the hash key ultimately determines the "sort" order
579 * when iterating through GHashTables, which affects allocation of scores to
580 * clone instances when iterating through rsc->allowed_nodes. It (somehow)
581 * also appears to have some minor impact on the ordering of a few
582 * pseudo_event IDs in the transition graph.
583 */
584 static guint
585 pcmk__str_hash(gconstpointer v)
586 {
587 const signed char *p;
588 guint32 h = 0;
589
590 for (p = v; *p != '\0'; p++)
591 h = (h << 5) - h + *p;
592
593 return h;
594 }
595
596 /*!
597 * \internal
598 * \brief Create a hash table with case-sensitive strings as keys
599 *
600 * \param[in] key_destroy_func Function to free a key
601 * \param[in] value_destroy_func Function to free a value
602 *
603 * \return Newly allocated hash table
604 * \note It is the caller's responsibility to free the result, using
605 * g_hash_table_destroy().
606 */
607 GHashTable *
608 pcmk__strkey_table(GDestroyNotify key_destroy_func,
609 GDestroyNotify value_destroy_func)
610 {
611 return g_hash_table_new_full(pcmk__str_hash, g_str_equal,
612 key_destroy_func, value_destroy_func);
613 }
614
615 /* used with hash tables where case does not matter */
616 static gboolean
617 pcmk__strcase_equal(gconstpointer a, gconstpointer b)
618 {
619 return pcmk__str_eq((const char *)a, (const char *)b, pcmk__str_casei);
620 }
621
622 static guint
623 pcmk__strcase_hash(gconstpointer v)
624 {
625 const signed char *p;
626 guint32 h = 0;
627
628 for (p = v; *p != '\0'; p++)
629 h = (h << 5) - h + g_ascii_tolower(*p);
630
631 return h;
632 }
633
634 /*!
635 * \internal
636 * \brief Create a hash table with case-insensitive strings as keys
637 *
638 * \param[in] key_destroy_func Function to free a key
639 * \param[in] value_destroy_func Function to free a value
640 *
641 * \return Newly allocated hash table
642 * \note It is the caller's responsibility to free the result, using
643 * g_hash_table_destroy().
644 */
645 GHashTable *
646 pcmk__strikey_table(GDestroyNotify key_destroy_func,
647 GDestroyNotify value_destroy_func)
648 {
649 return g_hash_table_new_full(pcmk__strcase_hash, pcmk__strcase_equal,
650 key_destroy_func, value_destroy_func);
651 }
652
653 static void
654 copy_str_table_entry(gpointer key, gpointer value, gpointer user_data)
655 {
656 if (key && value && user_data) {
657 g_hash_table_insert((GHashTable*)user_data, strdup(key), strdup(value));
658 }
659 }
660
661 /*!
662 * \internal
663 * \brief Copy a hash table that uses dynamically allocated strings
664 *
665 * \param[in,out] old_table Hash table to duplicate
666 *
667 * \return New hash table with copies of everything in \p old_table
668 * \note This assumes the hash table uses dynamically allocated strings -- that
669 * is, both the key and value free functions are free().
670 */
671 GHashTable *
672 pcmk__str_table_dup(GHashTable *old_table)
673 {
674 GHashTable *new_table = NULL;
675
676 if (old_table) {
677 new_table = pcmk__strkey_table(free, free);
678 g_hash_table_foreach(old_table, copy_str_table_entry, new_table);
679 }
680 return new_table;
681 }
682
683 /*!
684 * \internal
685 * \brief Add a word to a string list of words
686 *
687 * \param[in,out] list Pointer to current string list (may not be \p NULL)
688 * \param[in] init_size \p list will be initialized to at least this size,
689 * if it needs initialization (if 0, use GLib's default
690 * initial string size)
691 * \param[in] word String to add to \p list (\p list will be
692 * unchanged if this is \p NULL or the empty string)
693 * \param[in] separator String to separate words in \p list
694 * (a space will be used if this is NULL)
695 *
696 * \note \p word may contain \p separator, though that would be a bad idea if
697 * the string needs to be parsed later.
698 */
699 void
700 pcmk__add_separated_word(GString **list, size_t init_size, const char *word,
701 const char *separator)
702 {
703 CRM_ASSERT(list != NULL);
704
705 if (pcmk__str_empty(word)) {
706 return;
707 }
708
709 if (*list == NULL) {
710 if (init_size > 0) {
711 *list = g_string_sized_new(init_size);
712 } else {
713 *list = g_string_new(NULL);
714 }
715 }
716
717 if ((*list)->len == 0) {
718 // Don't add a separator before the first word in the list
719 separator = "";
720
721 } else if (separator == NULL) {
722 // Default to space-separated
723 separator = " ";
724 }
725
726 g_string_append(*list, separator);
727 g_string_append(*list, word);
728 }
729
730 /*!
731 * \internal
732 * \brief Compress data
733 *
734 * \param[in] data Data to compress
735 * \param[in] length Number of characters of data to compress
736 * \param[in] max Maximum size of compressed data (or 0 to estimate)
737 * \param[out] result Where to store newly allocated compressed result
738 * \param[out] result_len Where to store actual compressed length of result
739 *
740 * \return Standard Pacemaker return code
741 */
742 int
743 pcmk__compress(const char *data, unsigned int length, unsigned int max,
744 char **result, unsigned int *result_len)
745 {
746 int rc;
747 char *compressed = NULL;
748 char *uncompressed = strdup(data);
749 #ifdef CLOCK_MONOTONIC
750 struct timespec after_t;
751 struct timespec before_t;
752 #endif
753
754 if (max == 0) {
755 max = (length * 1.01) + 601; // Size guaranteed to hold result
756 }
757
758 #ifdef CLOCK_MONOTONIC
759 clock_gettime(CLOCK_MONOTONIC, &before_t);
760 #endif
761
762 compressed = calloc((size_t) max, sizeof(char));
763 CRM_ASSERT(compressed);
764
765 *result_len = max;
766 rc = BZ2_bzBuffToBuffCompress(compressed, result_len, uncompressed, length,
767 CRM_BZ2_BLOCKS, 0, CRM_BZ2_WORK);
768 rc = pcmk__bzlib2rc(rc);
769
770 free(uncompressed);
771
772 if (rc != pcmk_rc_ok) {
773 crm_err("Compression of %d bytes failed: %s " CRM_XS " rc=%d",
774 length, pcmk_rc_str(rc), rc);
775 free(compressed);
776 return rc;
777 }
778
779 #ifdef CLOCK_MONOTONIC
780 clock_gettime(CLOCK_MONOTONIC, &after_t);
781
782 crm_trace("Compressed %d bytes into %d (ratio %d:1) in %.0fms",
783 length, *result_len, length / (*result_len),
784 (after_t.tv_sec - before_t.tv_sec) * 1000 +
785 (after_t.tv_nsec - before_t.tv_nsec) / 1e6);
786 #else
787 crm_trace("Compressed %d bytes into %d (ratio %d:1)",
788 length, *result_len, length / (*result_len));
789 #endif
790
791 *result = compressed;
792 return pcmk_rc_ok;
793 }
794
795 char *
796 crm_strdup_printf(char const *format, ...)
797 {
798 va_list ap;
799 int len = 0;
800 char *string = NULL;
801
802 va_start(ap, format);
803 len = vasprintf (&string, format, ap);
804 CRM_ASSERT(len > 0);
805 va_end(ap);
806 return string;
807 }
808
809 int
810 pcmk__parse_ll_range(const char *srcstring, long long *start, long long *end)
811 {
812 char *remainder = NULL;
813 int rc = pcmk_rc_ok;
814
815 CRM_ASSERT(start != NULL && end != NULL);
816
817 *start = PCMK__PARSE_INT_DEFAULT;
818 *end = PCMK__PARSE_INT_DEFAULT;
819
820 crm_trace("Attempting to decode: [%s]", srcstring);
821 if (pcmk__str_eq(srcstring, "", pcmk__str_null_matches)) {
822 return ENODATA;
823 } else if (pcmk__str_eq(srcstring, "-", pcmk__str_none)) {
824 return pcmk_rc_bad_input;
825 }
826
827 /* String starts with a dash, so this is either a range with
828 * no beginning or garbage.
829 * */
830 if (*srcstring == '-') {
831 int rc = scan_ll(srcstring+1, end, PCMK__PARSE_INT_DEFAULT, &remainder);
832
833 if (rc != pcmk_rc_ok || *remainder != '\0') {
834 return pcmk_rc_bad_input;
835 } else {
836 return pcmk_rc_ok;
837 }
838 }
839
840 rc = scan_ll(srcstring, start, PCMK__PARSE_INT_DEFAULT, &remainder);
841 if (rc != pcmk_rc_ok) {
842 return rc;
843 }
844
845 if (*remainder && *remainder == '-') {
846 if (*(remainder+1)) {
847 char *more_remainder = NULL;
848 int rc = scan_ll(remainder+1, end, PCMK__PARSE_INT_DEFAULT,
849 &more_remainder);
850
851 if (rc != pcmk_rc_ok) {
852 return rc;
853 } else if (*more_remainder != '\0') {
854 return pcmk_rc_bad_input;
855 }
856 }
857 } else if (*remainder && *remainder != '-') {
858 *start = PCMK__PARSE_INT_DEFAULT;
859 return pcmk_rc_bad_input;
860 } else {
861 /* The input string contained only one number. Set start and end
862 * to the same value and return pcmk_rc_ok. This gives the caller
863 * a way to tell this condition apart from a range with no end.
864 */
865 *end = *start;
866 }
867
868 return pcmk_rc_ok;
869 }
870
871 /*!
872 * \internal
873 * \brief Find a string in a list of strings
874 *
875 * \note This function takes the same flags and has the same behavior as
876 * pcmk__str_eq().
877 *
878 * \note No matter what input string or flags are provided, an empty
879 * list will always return FALSE.
880 *
881 * \param[in] s String to search for
882 * \param[in] lst List to search
883 * \param[in] flags A bitfield of pcmk__str_flags to modify operation
884 *
885 * \return \c TRUE if \p s is in \p lst, or \c FALSE otherwise
886 */
887 gboolean
888 pcmk__str_in_list(const gchar *s, const GList *lst, uint32_t flags)
889 {
890 for (const GList *ele = lst; ele != NULL; ele = ele->next) {
891 if (pcmk__str_eq(s, ele->data, flags)) {
892 return TRUE;
893 }
894 }
895
896 return FALSE;
897 }
898
899 static bool
900 str_any_of(const char *s, va_list args, uint32_t flags)
901 {
902 if (s == NULL) {
903 return pcmk_is_set(flags, pcmk__str_null_matches);
904 }
905
906 while (1) {
907 const char *ele = va_arg(args, const char *);
908
909 if (ele == NULL) {
910 break;
911 } else if (pcmk__str_eq(s, ele, flags)) {
912 return true;
913 }
914 }
915
916 return false;
917 }
918
919 /*!
920 * \internal
921 * \brief Is a string a member of a list of strings?
922 *
923 * \param[in] s String to search for in \p ...
924 * \param[in] ... Strings to compare \p s against. The final string
925 * must be NULL.
926 *
927 * \note The comparison is done case-insensitively. The function name is
928 * meant to be reminiscent of strcasecmp.
929 *
930 * \return \c true if \p s is in \p ..., or \c false otherwise
931 */
932 bool
933 pcmk__strcase_any_of(const char *s, ...)
934 {
935 va_list ap;
936 bool rc;
937
938 va_start(ap, s);
939 rc = str_any_of(s, ap, pcmk__str_casei);
940 va_end(ap);
941 return rc;
942 }
943
944 /*!
945 * \internal
946 * \brief Is a string a member of a list of strings?
947 *
948 * \param[in] s String to search for in \p ...
949 * \param[in] ... Strings to compare \p s against. The final string
950 * must be NULL.
951 *
952 * \note The comparison is done taking case into account.
953 *
954 * \return \c true if \p s is in \p ..., or \c false otherwise
955 */
956 bool
957 pcmk__str_any_of(const char *s, ...)
958 {
959 va_list ap;
960 bool rc;
961
962 va_start(ap, s);
963 rc = str_any_of(s, ap, pcmk__str_none);
964 va_end(ap);
965 return rc;
966 }
967
968 /*!
969 * \internal
970 * \brief Check whether a character is in any of a list of strings
971 *
972 * \param[in] ch Character (ASCII) to search for
973 * \param[in] ... Strings to search. Final argument must be
974 * \c NULL.
975 *
976 * \return \c true if any of \p ... contain \p ch, \c false otherwise
977 * \note \p ... must contain at least one argument (\c NULL).
978 */
979 bool
980 pcmk__char_in_any_str(int ch, ...)
981 {
982 bool rc = false;
983 va_list ap;
984
985 /*
986 * Passing a char to va_start() can generate compiler warnings,
987 * so ch is declared as an int.
988 */
989 va_start(ap, ch);
990
991 while (1) {
992 const char *ele = va_arg(ap, const char *);
993
994 if (ele == NULL) {
995 break;
996 } else if (strchr(ele, ch) != NULL) {
997 rc = true;
998 break;
999 }
1000 }
1001
1002 va_end(ap);
1003 return rc;
1004 }
1005
1006 /*!
1007 * \internal
1008 * \brief Sort strings, with numeric portions sorted numerically
1009 *
1010 * Sort two strings case-insensitively like strcasecmp(), but with any numeric
1011 * portions of the string sorted numerically. This is particularly useful for
1012 * node names (for example, "node10" will sort higher than "node9" but lower
1013 * than "remotenode9").
1014 *
1015 * \param[in] s1 First string to compare (must not be NULL)
1016 * \param[in] s2 Second string to compare (must not be NULL)
1017 *
1018 * \retval -1 \p s1 comes before \p s2
1019 * \retval 0 \p s1 and \p s2 are equal
1020 * \retval 1 \p s1 comes after \p s2
1021 */
1022 int
1023 pcmk__numeric_strcasecmp(const char *s1, const char *s2)
1024 {
1025 CRM_ASSERT((s1 != NULL) && (s2 != NULL));
1026
1027 while (*s1 && *s2) {
1028 if (isdigit(*s1) && isdigit(*s2)) {
1029 // If node names contain a number, sort numerically
1030
1031 char *end1 = NULL;
1032 char *end2 = NULL;
1033 long num1 = strtol(s1, &end1, 10);
1034 long num2 = strtol(s2, &end2, 10);
1035
1036 // allow ordering e.g. 007 > 7
1037 size_t len1 = end1 - s1;
1038 size_t len2 = end2 - s2;
1039
1040 if (num1 < num2) {
1041 return -1;
1042 } else if (num1 > num2) {
1043 return 1;
1044 } else if (len1 < len2) {
1045 return -1;
1046 } else if (len1 > len2) {
1047 return 1;
1048 }
1049 s1 = end1;
1050 s2 = end2;
1051 } else {
1052 // Compare non-digits case-insensitively
1053 int lower1 = tolower(*s1);
1054 int lower2 = tolower(*s2);
1055
1056 if (lower1 < lower2) {
1057 return -1;
1058 } else if (lower1 > lower2) {
1059 return 1;
1060 }
1061 ++s1;
1062 ++s2;
1063 }
1064 }
1065 if (!*s1 && *s2) {
1066 return -1;
1067 } else if (*s1 && !*s2) {
1068 return 1;
1069 }
1070 return 0;
1071 }
1072
1073 /*!
1074 * \internal
1075 * \brief Sort strings.
1076 *
1077 * This is your one-stop function for string comparison. By default, this
1078 * function works like \p g_strcmp0. That is, like \p strcmp but a \p NULL
1079 * string sorts before a non-<tt>NULL</tt> string.
1080 *
1081 * The \p pcmk__str_none flag produces the default behavior. Behavior can be
1082 * changed with various flags:
1083 *
1084 * - \p pcmk__str_regex - The second string is a regular expression that the
1085 * first string will be matched against.
1086 * - \p pcmk__str_casei - By default, comparisons are done taking case into
1087 * account. This flag makes comparisons case-
1088 * insensitive. This can be combined with
1089 * \p pcmk__str_regex.
1090 * - \p pcmk__str_null_matches - If one string is \p NULL and the other is not,
1091 * still return \p 0.
1092 * - \p pcmk__str_star_matches - If one string is \p "*" and the other is not,
1093 * still return \p 0.
1094 *
1095 * \param[in] s1 First string to compare
1096 * \param[in] s2 Second string to compare, or a regular expression to
1097 * match if \p pcmk__str_regex is set
1098 * \param[in] flags A bitfield of \p pcmk__str_flags to modify operation
1099 *
1100 * \retval negative \p s1 is \p NULL or comes before \p s2
1101 * \retval 0 \p s1 and \p s2 are equal, or \p s1 is found in \p s2 if
1102 * \c pcmk__str_regex is set
1103 * \retval positive \p s2 is \p NULL or \p s1 comes after \p s2, or \p s2
1104 * is an invalid regular expression, or \p s1 was not found
1105 * in \p s2 if \p pcmk__str_regex is set.
1106 */
1107 int
1108 pcmk__strcmp(const char *s1, const char *s2, uint32_t flags)
1109 {
1110 /* If this flag is set, the second string is a regex. */
1111 if (pcmk_is_set(flags, pcmk__str_regex)) {
1112 regex_t r_patt;
1113 int reg_flags = REG_EXTENDED | REG_NOSUB;
1114 int regcomp_rc = 0;
1115 int rc = 0;
1116
1117 if (s1 == NULL || s2 == NULL) {
1118 return 1;
1119 }
1120
1121 if (pcmk_is_set(flags, pcmk__str_casei)) {
1122 reg_flags |= REG_ICASE;
1123 }
1124 regcomp_rc = regcomp(&r_patt, s2, reg_flags);
1125 if (regcomp_rc != 0) {
1126 rc = 1;
1127 crm_err("Bad regex '%s' for update: %s", s2, strerror(regcomp_rc));
1128 } else {
1129 rc = regexec(&r_patt, s1, 0, NULL, 0);
1130 regfree(&r_patt);
1131 if (rc != 0) {
1132 rc = 1;
1133 }
1134 }
1135 return rc;
1136 }
1137
1138 /* If the strings are the same pointer, return 0 immediately. */
1139 if (s1 == s2) {
1140 return 0;
1141 }
1142
1143 /* If this flag is set, return 0 if either (or both) of the input strings
1144 * are NULL. If neither one is NULL, we need to continue and compare
1145 * them normally.
1146 */
1147 if (pcmk_is_set(flags, pcmk__str_null_matches)) {
1148 if (s1 == NULL || s2 == NULL) {
1149 return 0;
1150 }
1151 }
1152
1153 /* Handle the cases where one is NULL and the str_null_matches flag is not set.
1154 * A NULL string always sorts to the beginning.
1155 */
1156 if (s1 == NULL) {
1157 return -1;
1158 } else if (s2 == NULL) {
1159 return 1;
1160 }
1161
1162 /* If this flag is set, return 0 if either (or both) of the input strings
1163 * are "*". If neither one is, we need to continue and compare them
1164 * normally.
1165 */
1166 if (pcmk_is_set(flags, pcmk__str_star_matches)) {
1167 if (strcmp(s1, "*") == 0 || strcmp(s2, "*") == 0) {
1168 return 0;
1169 }
1170 }
1171
1172 if (pcmk_is_set(flags, pcmk__str_casei)) {
1173 return strcasecmp(s1, s2);
1174 } else {
1175 return strcmp(s1, s2);
1176 }
1177 }
1178
1179 /*!
1180 * \internal
1181 * \brief Update a dynamically allocated string with a new value
1182 *
1183 * Given a dynamically allocated string and a new value for it, if the string
1184 * is different from the new value, free the string and replace it with either a
1185 * newly allocated duplicate of the value or NULL as appropriate.
1186 *
1187 * \param[in,out] str Pointer to dynamically allocated string
1188 * \param[in] value New value to duplicate (or NULL)
1189 *
1190 * \note The caller remains responsibile for freeing \p *str.
1191 */
1192 void
1193 pcmk__str_update(char **str, const char *value)
1194 {
1195 if ((str != NULL) && !pcmk__str_eq(*str, value, pcmk__str_none)) {
1196 free(*str);
1197 if (value == NULL) {
1198 *str = NULL;
1199 } else {
1200 *str = strdup(value);
1201 CRM_ASSERT(*str != NULL);
1202 }
1203 }
1204 }
1205
1206 /*!
1207 * \internal
1208 * \brief Append a list of strings to a destination \p GString
1209 *
1210 * \param[in,out] buffer Where to append the strings (must not be \p NULL)
1211 * \param[in] ... A <tt>NULL</tt>-terminated list of strings
1212 *
1213 * \note This tends to be more efficient than a single call to
1214 * \p g_string_append_printf().
1215 */
1216 void
1217 pcmk__g_strcat(GString *buffer, ...)
1218 {
1219 va_list ap;
1220
1221 CRM_ASSERT(buffer != NULL);
1222 va_start(ap, buffer);
1223
1224 while (true) {
1225 const char *ele = va_arg(ap, const char *);
1226
1227 if (ele == NULL) {
1228 break;
1229 }
1230 g_string_append(buffer, ele);
1231 }
1232 va_end(ap);
1233 }
1234
1235 // Deprecated functions kept only for backward API compatibility
1236 // LCOV_EXCL_START
1237
1238 #include <crm/common/util_compat.h>
1239
1240 gboolean
1241 safe_str_neq(const char *a, const char *b)
1242 {
1243 if (a == b) {
1244 return FALSE;
1245
1246 } else if (a == NULL || b == NULL) {
1247 return TRUE;
1248
1249 } else if (strcasecmp(a, b) == 0) {
1250 return FALSE;
1251 }
1252 return TRUE;
1253 }
1254
1255 gboolean
1256 crm_str_eq(const char *a, const char *b, gboolean use_case)
1257 {
1258 if (use_case) {
1259 return g_strcmp0(a, b) == 0;
1260
1261 /* TODO - Figure out which calls, if any, really need to be case independent */
1262 } else if (a == b) {
1263 return TRUE;
1264
1265 } else if (a == NULL || b == NULL) {
1266 /* shouldn't be comparing NULLs */
1267 return FALSE;
1268
1269 } else if (strcasecmp(a, b) == 0) {
1270 return TRUE;
1271 }
1272 return FALSE;
1273 }
1274
1275 char *
1276 crm_itoa_stack(int an_int, char *buffer, size_t len)
1277 {
1278 if (buffer != NULL) {
1279 snprintf(buffer, len, "%d", an_int);
1280 }
1281 return buffer;
1282 }
1283
1284 guint
1285 g_str_hash_traditional(gconstpointer v)
1286 {
1287 return pcmk__str_hash(v);
1288 }
1289
1290 gboolean
1291 crm_strcase_equal(gconstpointer a, gconstpointer b)
1292 {
1293 return pcmk__strcase_equal(a, b);
1294 }
1295
1296 guint
1297 crm_strcase_hash(gconstpointer v)
1298 {
1299 return pcmk__strcase_hash(v);
1300 }
1301
1302 GHashTable *
1303 crm_str_table_dup(GHashTable *old_table)
1304 {
1305 return pcmk__str_table_dup(old_table);
1306 }
1307
1308 long long
1309 crm_parse_ll(const char *text, const char *default_text)
1310 {
1311 long long result;
1312
1313 if (text == NULL) {
1314 text = default_text;
1315 if (text == NULL) {
1316 crm_err("No default conversion value supplied");
1317 errno = EINVAL;
1318 return PCMK__PARSE_INT_DEFAULT;
1319 }
1320 }
1321 scan_ll(text, &result, PCMK__PARSE_INT_DEFAULT, NULL);
1322 return result;
1323 }
1324
1325 int
1326 crm_parse_int(const char *text, const char *default_text)
1327 {
1328 long long result = crm_parse_ll(text, default_text);
1329
1330 if (result < INT_MIN) {
1331 // If errno is ERANGE, crm_parse_ll() has already logged a message
1332 if (errno != ERANGE) {
1333 crm_err("Conversion of %s was clipped: %lld", text, result);
1334 errno = ERANGE;
1335 }
1336 return INT_MIN;
1337
1338 } else if (result > INT_MAX) {
1339 // If errno is ERANGE, crm_parse_ll() has already logged a message
1340 if (errno != ERANGE) {
1341 crm_err("Conversion of %s was clipped: %lld", text, result);
1342 errno = ERANGE;
1343 }
1344 return INT_MAX;
1345 }
1346
1347 return (int) result;
1348 }
1349
1350 char *
1351 crm_strip_trailing_newline(char *str)
1352 {
1353 return pcmk__trim(str);
1354 }
1355
1356 int
1357 pcmk_numeric_strcasecmp(const char *s1, const char *s2)
1358 {
1359 return pcmk__numeric_strcasecmp(s1, s2);
1360 }
1361
1362 // LCOV_EXCL_STOP
1363 // End deprecated API
1364