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