1    	/*
2    	 * Copyright 2004-2026 the Pacemaker project contributors
3    	 *
4    	 * The version control history for this file may have further details.
5    	 *
6    	 * This source code is licensed under the GNU Lesser General Public License
7    	 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8    	 */
9    	
10   	#include <crm_internal.h>
11   	
12   	#include <bzlib.h>
13   	#include <errno.h>
14   	#include <netdb.h>
15   	#include <stdlib.h>
16   	#include <string.h>
17   	#include <sys/types.h>
18   	#include <sys/wait.h>
19   	#include <qb/qbdefs.h>
20   	
21   	#include <crm/common/mainloop.h>
22   	#include <crm/common/xml.h>
23   	
24   	G_DEFINE_QUARK(pcmk-rc-error-quark, pcmk__rc_error)
25   	G_DEFINE_QUARK(pcmk-exitc-error-quark, pcmk__exitc_error)
26   	
27   	// General (all result code types)
28   	
29   	/*!
30   	 * \brief Get the name and description of a given result code
31   	 *
32   	 * A result code can be interpreted as a member of any one of several families.
33   	 *
34   	 * \param[in]  code  The result code to look up
35   	 * \param[in]  type  How \p code should be interpreted
36   	 * \param[out] name  Where to store the result code's name
37   	 * \param[out] desc  Where to store the result code's description
38   	 *
39   	 * \return Standard Pacemaker return code
40   	 */
41   	int
42   	pcmk_result_get_strings(int code, enum pcmk_result_type type, const char **name,
43   	                        const char **desc)
44   	{
45   	    const char *code_name = NULL;
46   	    const char *code_desc = NULL;
47   	
48   	    switch (type) {
49   	        case pcmk_result_legacy:
50   	            code_name = pcmk_errorname(code);
51   	            code_desc = pcmk_strerror(code);
52   	            break;
53   	        case pcmk_result_rc:
54   	            code_name = pcmk_rc_name(code);
55   	            code_desc = pcmk_rc_str(code);
56   	            break;
57   	        case pcmk_result_exitcode:
58   	            code_name = crm_exit_name(code);
59   	            code_desc = crm_exit_str((crm_exit_t) code);
60   	            break;
61   	        default:
62   	            return pcmk_rc_undetermined;
63   	    }
64   	
65   	    if (name != NULL) {
66   	        *name = code_name;
67   	    }
68   	    
69   	    if (desc != NULL) {
70   	        *desc = code_desc;
71   	    }
72   	    return pcmk_rc_ok;
73   	}
74   	
75   	/*!
76   	 * \internal
77   	 * \brief Get the lower and upper bounds of a result code family
78   	 *
79   	 * \param[in]   type    Type of result code
80   	 * \param[out]  lower   Where to store the lower bound
81   	 * \param[out]  upper   Where to store the upper bound
82   	 *
83   	 * \return Standard Pacemaker return code
84   	 *
85   	 * \note There is no true upper bound on standard Pacemaker return codes or
86   	 *       legacy return codes. All system \p errno values are valid members of
87   	 *       these result code families, and there is no global upper limit nor a
88   	 *       constant by which to refer to the highest \p errno value on a given
89   	 *       system.
90   	 */
91   	int
92   	pcmk__result_bounds(enum pcmk_result_type type, int *lower, int *upper)
93   	{
94   	    pcmk__assert((lower != NULL) && (upper != NULL));
95   	
96   	    switch (type) {
97   	        case pcmk_result_legacy:
98   	            *lower = pcmk_ok;
99   	            *upper = 256;   // should be enough for almost any system error code
100  	            break;
101  	        case pcmk_result_rc:
102  	            *lower = pcmk_rc_error - pcmk__n_rc + 1;
103  	            *upper = 256;
104  	            break;
105  	        case pcmk_result_exitcode:
106  	            *lower = CRM_EX_OK;
107  	            *upper = CRM_EX_MAX;
108  	            break;
109  	        default:
110  	            *lower = 0;
111  	            *upper = -1;
112  	            return pcmk_rc_undetermined;
113  	    }
114  	    return pcmk_rc_ok;
115  	}
116  	
117  	/*!
118  	 * \internal
119  	 * \brief Log a failed assertion
120  	 *
121  	 * \param[in] file              File making the assertion
122  	 * \param[in] function          Function making the assertion
123  	 * \param[in] line              Line of file making the assertion
124  	 * \param[in] assert_condition  String representation of assertion
125  	 */
126  	static void
127  	log_assertion_as(const char *file, const char *function, int line,
128  	                 const char *assert_condition)
129  	{
130  	    if (!pcmk__is_daemon) {
131  	        crm_enable_stderr(TRUE); // Make sure command-line user sees message
132  	    }
133  	    pcmk__err("%s: Triggered fatal assertion at %s:%d : %s", function, file,
134  	              line, assert_condition);
135  	}
136  	
137  	/* coverity[+kill] */
138  	/*!
139  	 * \internal
140  	 * \brief Log a failed assertion and abort
141  	 *
142  	 * \param[in] file              File making the assertion
143  	 * \param[in] function          Function making the assertion
144  	 * \param[in] line              Line of file making the assertion
145  	 * \param[in] assert_condition  String representation of assertion
146  	 *
147  	 * \note This does not return
148  	 */
149  	_Noreturn void
150  	pcmk__abort_as(const char *file, const char *function, int line,
151  	               const char *assert_condition)
152  	{
153  	    log_assertion_as(file, function, line, assert_condition);
154  	    abort();
155  	}
156  	
157  	/* coverity[+kill] */
158  	/*!
159  	 * \internal
160  	 * \brief Handle a failed assertion
161  	 *
162  	 * When called by a daemon, fork a child that aborts (to dump core), otherwise
163  	 * abort the current process.
164  	 *
165  	 * \param[in] file              File making the assertion
166  	 * \param[in] function          Function making the assertion
167  	 * \param[in] line              Line of file making the assertion
168  	 * \param[in] assert_condition  String representation of assertion
169  	 */
170  	static void
171  	fail_assert_as(const char *file, const char *function, int line,
172  	               const char *assert_condition)
173  	{
174  	    int status = 0;
175  	    pid_t pid = 0;
176  	
177  	    if (!pcmk__is_daemon) {
178  	        pcmk__abort_as(file, function, line, assert_condition); // No return
179  	    }
180  	
181  	    pid = fork();
182  	    switch (pid) {
183  	        case -1: // Fork failed
184  	            pcmk__warn("%s: Cannot dump core for non-fatal assertion at %s:%d "
185  	                       ": %s", function, file, line, assert_condition);
186  	            break;
187  	
188  	        case 0: // Child process: just abort to dump core
189  	            abort();
190  	            break;
191  	
192  	        default: // Parent process: wait for child
193  	            pcmk__err("%s: Forked child [%d] to record non-fatal assertion at "
194  	                      "%s:%d : %s",
195  	                      function, pid, file, line, assert_condition);
196  	            crm_write_blackbox(SIGTRAP, NULL);
197  	            do {
198  	                if (waitpid(pid, &status, 0) == pid) {
199  	                    return; // Child finished dumping core
200  	                }
201  	            } while (errno == EINTR);
202  	            if (errno == ECHILD) {
203  	                // crm_mon ignores SIGCHLD
204  	                pcmk__trace("Cannot wait on forked child [%lld] (SIGCHLD is "
205  	                            "probably ignored)",
206  	                            (long long) pid);
207  	            } else {
208  	                pcmk__err("Cannot wait on forked child [%lld]: %s",
209  	                          (long long) pid, pcmk_rc_str(errno));
210  	            }
211  	            break;
212  	    }
213  	}
214  	
215  	/* coverity[+kill] */
216  	void
217  	crm_abort(const char *file, const char *function, int line,
218  	          const char *assert_condition, gboolean do_core, gboolean do_fork)
219  	{
220  	    if (!do_fork) {
221  	        pcmk__abort_as(file, function, line, assert_condition); // No return
222  	    } else if (do_core) {
223  	        fail_assert_as(file, function, line, assert_condition);
224  	    } else {
225  	        log_assertion_as(file, function, line, assert_condition);
226  	    }
227  	}
228  	
229  	// @COMPAT Legacy function return codes
230  	
231  	//! \deprecated Use standard return codes and pcmk_rc_name() instead
232  	const char *
233  	pcmk_errorname(int rc)
234  	{
235  	    rc = abs(rc);
236  	    switch (rc) {
237  	        case pcmk_err_generic: return "pcmk_err_generic";
238  	        case pcmk_err_no_quorum: return "pcmk_err_no_quorum";
239  	        case pcmk_err_schema_validation: return "pcmk_err_schema_validation";
240  	        case pcmk_err_transform_failed: return "pcmk_err_transform_failed";
241  	        case pcmk_err_old_data: return "pcmk_err_old_data";
242  	        case pcmk_err_diff_failed: return "pcmk_err_diff_failed";
243  	        case pcmk_err_diff_resync: return "pcmk_err_diff_resync";
244  	        case pcmk_err_cib_modified: return "pcmk_err_cib_modified";
245  	        case pcmk_err_cib_backup: return "pcmk_err_cib_backup";
246  	        case pcmk_err_cib_save: return "pcmk_err_cib_save";
247  	        case pcmk_err_cib_corrupt: return "pcmk_err_cib_corrupt";
248  	        case pcmk_err_multiple: return "pcmk_err_multiple";
249  	        case pcmk_err_node_unknown: return "pcmk_err_node_unknown";
250  	        case pcmk_err_already: return "pcmk_err_already";
251  	        case pcmk_err_bad_nvpair: return "pcmk_err_bad_nvpair";
252  	        case pcmk_err_unknown_format: return "pcmk_err_unknown_format";
253  	        default: return pcmk_rc_name(rc); // system errno
254  	    }
255  	}
256  	
257  	//! \deprecated Use standard return codes and pcmk_rc_str() instead
258  	const char *
259  	pcmk_strerror(int rc)
260  	{
261  	    return pcmk_rc_str(pcmk_legacy2rc(rc));
262  	}
263  	
264  	// Standard Pacemaker API return codes
265  	
266  	/* This array is used only for nonzero values of pcmk_rc_e. Its values must be
267  	 * kept in the exact reverse order of the enum value numbering (i.e. add new
268  	 * values to the end of the array).
269  	 */
270  	static const struct pcmk__rc_info {
271  	    const char *name;
272  	    const char *desc;
273  	    int legacy_rc;
274  	} pcmk__rcs[] = {
275  	    { "pcmk_rc_error",
276  	      "Error",
277  	      -pcmk_err_generic,
278  	    },
279  	    { "pcmk_rc_unknown_format",
280  	      "Unknown output format",
281  	      -pcmk_err_unknown_format,
282  	    },
283  	    { "pcmk_rc_bad_nvpair",
284  	      "Bad name/value pair given",
285  	      -pcmk_err_bad_nvpair,
286  	    },
287  	    { "pcmk_rc_already",
288  	      "Already in requested state",
289  	      -pcmk_err_already,
290  	    },
291  	    { "pcmk_rc_node_unknown",
292  	      "Node not found",
293  	      -pcmk_err_node_unknown,
294  	    },
295  	    { "pcmk_rc_multiple",
296  	      "Resource active on multiple nodes",
297  	      -pcmk_err_multiple,
298  	    },
299  	    { "pcmk_rc_cib_corrupt",
300  	      "Could not parse on-disk configuration",
301  	      -pcmk_err_cib_corrupt,
302  	    },
303  	    { "pcmk_rc_cib_save",
304  	      "Could not save new configuration to disk",
305  	      -pcmk_err_cib_save,
306  	    },
307  	    { "pcmk_rc_cib_backup",
308  	      "Could not archive previous configuration",
309  	      -pcmk_err_cib_backup,
310  	    },
311  	    { "pcmk_rc_cib_modified",
312  	      "On-disk configuration was manually modified",
313  	      -pcmk_err_cib_modified,
314  	    },
315  	    { "pcmk_rc_diff_resync",
316  	      "Application of update diff failed, requesting full refresh",
317  	      -pcmk_err_diff_resync,
318  	    },
319  	    { "pcmk_rc_diff_failed",
320  	      "Application of update diff failed",
321  	      -pcmk_err_diff_failed,
322  	    },
323  	    { "pcmk_rc_old_data",
324  	      "Update was older than existing configuration",
325  	      -pcmk_err_old_data,
326  	    },
327  	    { "pcmk_rc_transform_failed",
328  	      "Schema transform failed",
329  	      -pcmk_err_transform_failed,
330  	    },
331  	    { "pcmk_rc_schema_unchanged",
332  	      "Schema is already the latest available",
333  	      -pcmk_err_schema_unchanged,
334  	    },
335  	    { "pcmk_rc_schema_validation",
336  	      "Update does not conform to the configured schema",
337  	      -pcmk_err_schema_validation,
338  	    },
339  	    { "pcmk_rc_no_quorum",
340  	      "Operation requires quorum",
341  	      -pcmk_err_no_quorum,
342  	    },
343  	    { "pcmk_rc_ipc_unauthorized",
344  	      "IPC server is blocked by unauthorized process",
345  	      -pcmk_err_generic,
346  	    },
347  	    { "pcmk_rc_ipc_unresponsive",
348  	      "IPC server is unresponsive",
349  	      -pcmk_err_generic,
350  	    },
351  	    { "pcmk_rc_ipc_pid_only",
352  	      "IPC server process is active but not accepting connections",
353  	      -pcmk_err_generic,
354  	    },
355  	    { "pcmk_rc_op_unsatisfied",
356  	      "Not applicable under current conditions",
357  	      -pcmk_err_generic,
358  	    },
359  	    { "pcmk_rc_undetermined",
360  	      "Result undetermined",
361  	      -pcmk_err_generic,
362  	    },
363  	    { "pcmk_rc_before_range",
364  	      "Result occurs before given range",
365  	      -pcmk_err_generic,
366  	    },
367  	    { "pcmk_rc_within_range",
368  	      "Result occurs within given range",
369  	      -pcmk_err_generic,
370  	    },
371  	    { "pcmk_rc_after_range",
372  	      "Result occurs after given range",
373  	      -pcmk_err_generic,
374  	    },
375  	    { "pcmk_rc_no_output",
376  	      "Output message produced no output",
377  	      -pcmk_err_generic,
378  	    },
379  	    { "pcmk_rc_no_input",
380  	      "Input file not available",
381  	      -pcmk_err_generic,
382  	    },
383  	    { "pcmk_rc_underflow",
384  	      "Value too small to be stored in data type",
385  	      -pcmk_err_generic,
386  	    },
387  	    { "pcmk_rc_dot_error",
388  	      "Error writing dot(1) file",
389  	      -pcmk_err_generic,
390  	    },
391  	    { "pcmk_rc_graph_error",
392  	      "Error writing graph file",
393  	      -pcmk_err_generic,
394  	    },
395  	    { "pcmk_rc_invalid_transition",
396  	      "Cluster simulation produced invalid transition",
397  	      -pcmk_err_generic,
398  	    },
399  	    { "pcmk_rc_unpack_error",
400  	      "Unable to parse CIB XML",
401  	      -pcmk_err_generic,
402  	    },
403  	    { "pcmk_rc_duplicate_id",
404  	      "Two or more XML elements have the same ID",
405  	      -pcmk_err_generic,
406  	    },
407  	    { "pcmk_rc_disabled",
408  	      "Disabled",
409  	      -pcmk_err_generic,
410  	    },
411  	    { "pcmk_rc_bad_input",
412  	      "Bad input value provided",
413  	      -pcmk_err_generic,
414  	    },
415  	    { "pcmk_rc_bad_xml_patch",
416  	      "Bad XML patch format",
417  	      -pcmk_err_generic,
418  	    },
419  	    { "pcmk_rc_no_transaction",
420  	      "No active transaction found",
421  	      -pcmk_err_generic,
422  	    },
423  	    { "pcmk_rc_ns_resolution",
424  	      "Nameserver resolution error",
425  	      -pcmk_err_generic,
426  	    },
427  	    { "pcmk_rc_compression",
428  	      "Compression/decompression error",
429  	      -pcmk_err_generic,
430  	    },
431  	    { "pcmk_rc_no_dc",
432  	      "DC is not yet elected",
433  	      -pcmk_err_generic,
434  	    },
435  	    { "pcmk_rc_ipc_more",
436  	      "More IPC message fragments to send",
437  	      -pcmk_err_generic,
438  	    },
439  	    { "pcmk_rc_cs_internal",
440  	      "Internal corosync error",
441  	      -pcmk_err_generic,
442  	    },
443  	    { "pcmk_rc_digest_mismatch",
444  	      "Digest does not match expected value",
445  	      -pcmk_err_generic,
446  	    },
447  	};
448  	
449  	/*!
450  	 * \internal
451  	 * \brief The number of <tt>enum pcmk_rc_e</tt> values, excluding \c pcmk_rc_ok
452  	 *
453  	 * This constant stores the number of negative standard Pacemaker return codes.
454  	 * These represent Pacemaker-custom error codes. The count does not include
455  	 * positive system error numbers, nor does it include \c pcmk_rc_ok (success).
456  	 */
457  	const size_t pcmk__n_rc = PCMK__NELEM(pcmk__rcs);
458  	
459  	/*!
460  	 * \brief Get a return code constant name as a string
461  	 *
462  	 * \param[in] rc  Integer return code to convert
463  	 *
464  	 * \return String of constant name corresponding to rc
465  	 */
466  	const char *
467  	pcmk_rc_name(int rc)
468  	{
469  	    if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < pcmk__n_rc)) {
470  	        return pcmk__rcs[pcmk_rc_error - rc].name;
471  	    }
472  	    switch (rc) {
473  	        case pcmk_rc_ok:        return "pcmk_rc_ok";
474  	        case E2BIG:             return "E2BIG";
475  	        case EACCES:            return "EACCES";
476  	        case EADDRINUSE:        return "EADDRINUSE";
477  	        case EADDRNOTAVAIL:     return "EADDRNOTAVAIL";
478  	        case EAFNOSUPPORT:      return "EAFNOSUPPORT";
479  	        case EAGAIN:            return "EAGAIN";
480  	        case EALREADY:          return "EALREADY";
481  	        case EBADF:             return "EBADF";
482  	        case EBADMSG:           return "EBADMSG";
483  	        case EBUSY:             return "EBUSY";
484  	        case ECANCELED:         return "ECANCELED";
485  	        case ECHILD:            return "ECHILD";
486  	        case ECOMM:             return "ECOMM";
487  	        case ECONNABORTED:      return "ECONNABORTED";
488  	        case ECONNREFUSED:      return "ECONNREFUSED";
489  	        case ECONNRESET:        return "ECONNRESET";
490  	        /* case EDEADLK:        return "EDEADLK"; */
491  	        case EDESTADDRREQ:      return "EDESTADDRREQ";
492  	        case EDOM:              return "EDOM";
493  	        case EDQUOT:            return "EDQUOT";
494  	        case EEXIST:            return "EEXIST";
495  	        case EFAULT:            return "EFAULT";
496  	        case EFBIG:             return "EFBIG";
497  	        case EHOSTDOWN:         return "EHOSTDOWN";
498  	        case EHOSTUNREACH:      return "EHOSTUNREACH";
499  	        case EIDRM:             return "EIDRM";
500  	        case EILSEQ:            return "EILSEQ";
501  	        case EINPROGRESS:       return "EINPROGRESS";
502  	        case EINTR:             return "EINTR";
503  	        case EINVAL:            return "EINVAL";
504  	        case EIO:               return "EIO";
505  	        case EISCONN:           return "EISCONN";
506  	        case EISDIR:            return "EISDIR";
507  	        case ELIBACC:           return "ELIBACC";
508  	        case ELOOP:             return "ELOOP";
509  	        case EMFILE:            return "EMFILE";
510  	        case EMLINK:            return "EMLINK";
511  	        case EMSGSIZE:          return "EMSGSIZE";
512  	#ifdef EMULTIHOP // Not available on OpenBSD
513  	        case EMULTIHOP:         return "EMULTIHOP";
514  	#endif
515  	        case ENAMETOOLONG:      return "ENAMETOOLONG";
516  	        case ENETDOWN:          return "ENETDOWN";
517  	        case ENETRESET:         return "ENETRESET";
518  	        case ENETUNREACH:       return "ENETUNREACH";
519  	        case ENFILE:            return "ENFILE";
520  	        case ENOBUFS:           return "ENOBUFS";
521  	        case ENODATA:           return "ENODATA";
522  	        case ENODEV:            return "ENODEV";
523  	        case ENOENT:            return "ENOENT";
524  	        case ENOEXEC:           return "ENOEXEC";
525  	        case ENOKEY:            return "ENOKEY";
526  	        case ENOLCK:            return "ENOLCK";
527  	#ifdef ENOLINK // Not available on OpenBSD
528  	        case ENOLINK:           return "ENOLINK";
529  	#endif
530  	        case ENOMEM:            return "ENOMEM";
531  	        case ENOMSG:            return "ENOMSG";
532  	        case ENOPROTOOPT:       return "ENOPROTOOPT";
533  	        case ENOSPC:            return "ENOSPC";
534  	#ifdef ENOSR
535  	        case ENOSR:             return "ENOSR";
536  	#endif
537  	#ifdef ENOSTR
538  	        case ENOSTR:            return "ENOSTR";
539  	#endif
540  	        case ENOSYS:            return "ENOSYS";
541  	        case ENOTBLK:           return "ENOTBLK";
542  	        case ENOTCONN:          return "ENOTCONN";
543  	        case ENOTDIR:           return "ENOTDIR";
544  	        case ENOTEMPTY:         return "ENOTEMPTY";
545  	        case ENOTSOCK:          return "ENOTSOCK";
546  	#if ENOTSUP != EOPNOTSUPP
547  	        case ENOTSUP:           return "ENOTSUP";
548  	#endif
549  	        case ENOTTY:            return "ENOTTY";
550  	        case ENOTUNIQ:          return "ENOTUNIQ";
551  	        case ENXIO:             return "ENXIO";
552  	        case EOPNOTSUPP:        return "EOPNOTSUPP";
553  	        case EOVERFLOW:         return "EOVERFLOW";
554  	        case EPERM:             return "EPERM";
555  	        case EPFNOSUPPORT:      return "EPFNOSUPPORT";
556  	        case EPIPE:             return "EPIPE";
557  	        case EPROTO:            return "EPROTO";
558  	        case EPROTONOSUPPORT:   return "EPROTONOSUPPORT";
559  	        case EPROTOTYPE:        return "EPROTOTYPE";
560  	        case ERANGE:            return "ERANGE";
561  	        case EREMOTE:           return "EREMOTE";
562  	        case EREMOTEIO:         return "EREMOTEIO";
563  	        case EROFS:             return "EROFS";
564  	        case ESHUTDOWN:         return "ESHUTDOWN";
565  	        case ESPIPE:            return "ESPIPE";
566  	        case ESOCKTNOSUPPORT:   return "ESOCKTNOSUPPORT";
567  	        case ESRCH:             return "ESRCH";
568  	        case ESTALE:            return "ESTALE";
569  	        case ETIME:             return "ETIME";
570  	        case ETIMEDOUT:         return "ETIMEDOUT";
571  	        case ETXTBSY:           return "ETXTBSY";
572  	#ifdef EUNATCH
573  	        case EUNATCH:           return "EUNATCH";
574  	#endif
575  	        case EUSERS:            return "EUSERS";
576  	        /* case EWOULDBLOCK:    return "EWOULDBLOCK"; */
577  	        case EXDEV:             return "EXDEV";
578  	
579  	#ifdef EBADE // Not available on OS X
580  	        case EBADE:             return "EBADE";
581  	        case EBADFD:            return "EBADFD";
582  	        case EBADSLT:           return "EBADSLT";
583  	        case EDEADLOCK:         return "EDEADLOCK";
584  	        case EBADR:             return "EBADR";
585  	        case EBADRQC:           return "EBADRQC";
586  	        case ECHRNG:            return "ECHRNG";
587  	#ifdef EISNAM // Not available on OS X, Illumos, Solaris
588  	        case EISNAM:            return "EISNAM";
589  	        case EKEYEXPIRED:       return "EKEYEXPIRED";
590  	        case EKEYREVOKED:       return "EKEYREVOKED";
591  	#endif
592  	        case EKEYREJECTED:      return "EKEYREJECTED";
593  	        case EL2HLT:            return "EL2HLT";
594  	        case EL2NSYNC:          return "EL2NSYNC";
595  	        case EL3HLT:            return "EL3HLT";
596  	        case EL3RST:            return "EL3RST";
597  	        case ELIBBAD:           return "ELIBBAD";
598  	        case ELIBMAX:           return "ELIBMAX";
599  	        case ELIBSCN:           return "ELIBSCN";
600  	        case ELIBEXEC:          return "ELIBEXEC";
601  	#ifdef ENOMEDIUM // Not available on OS X, Illumos, Solaris
602  	        case ENOMEDIUM:         return "ENOMEDIUM";
603  	        case EMEDIUMTYPE:       return "EMEDIUMTYPE";
604  	#endif
605  	        case ENONET:            return "ENONET";
606  	        case ENOPKG:            return "ENOPKG";
607  	        case EREMCHG:           return "EREMCHG";
608  	        case ERESTART:          return "ERESTART";
609  	        case ESTRPIPE:          return "ESTRPIPE";
610  	#ifdef EUCLEAN // Not available on OS X, Illumos, Solaris
611  	        case EUCLEAN:           return "EUCLEAN";
612  	#endif
613  	        case EXFULL:            return "EXFULL";
614  	#endif // EBADE
615  	        default:                return "Unknown";
616  	    }
617  	}
618  	
619  	/*!
620  	 * \brief Get a user-friendly description of a return code
621  	 *
622  	 * \param[in] rc  Integer return code to convert
623  	 *
624  	 * \return String description of rc
625  	 */
626  	const char *
627  	pcmk_rc_str(int rc)
628  	{
629  	    if (rc == pcmk_rc_ok) {
630  	        return "OK";
631  	    }
632  	    if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < pcmk__n_rc)) {
633  	        return pcmk__rcs[pcmk_rc_error - rc].desc;
634  	    }
635  	    if (rc < 0) {
636  	        return "Error";
637  	    }
638  	
639  	    // Handle values that could be defined by system or by portability.h
640  	    switch (rc) {
641  	#ifdef PCMK__ENOTUNIQ
642  	        case ENOTUNIQ:      return "Name not unique on network";
643  	#endif
644  	#ifdef PCMK__ECOMM
645  	        case ECOMM:         return "Communication error on send";
646  	#endif
647  	#ifdef PCMK__ELIBACC
648  	        case ELIBACC:       return "Can not access a needed shared library";
649  	#endif
650  	#ifdef PCMK__EREMOTEIO
651  	        case EREMOTEIO:     return "Remote I/O error";
652  	#endif
653  	#ifdef PCMK__ENOKEY
654  	        case ENOKEY:        return "Required key not available";
655  	#endif
656  	#ifdef PCMK__ENODATA
657  	        case ENODATA:       return "No data available";
658  	#endif
659  	#ifdef PCMK__ETIME
660  	        case ETIME:         return "Timer expired";
661  	#endif
662  	#ifdef PCMK__EKEYREJECTED
663  	        case EKEYREJECTED:  return "Key was rejected by service";
664  	#endif
665  	        default:            return strerror(rc);
666  	    }
667  	}
668  	
669  	// This returns negative values for errors
670  	//! \deprecated Use standard return codes instead
671  	int
672  	pcmk_rc2legacy(int rc)
673  	{
674  	    if (rc >= 0) {
675  	        return -rc; // OK or system errno
676  	    }
677  	    if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < pcmk__n_rc)) {
678  	        return pcmk__rcs[pcmk_rc_error - rc].legacy_rc;
679  	    }
680  	    return -pcmk_err_generic;
681  	}
682  	
683  	//! \deprecated Use standard return codes instead
684  	int
685  	pcmk_legacy2rc(int legacy_rc)
686  	{
687  	    legacy_rc = abs(legacy_rc);
688  	    switch (legacy_rc) {
689  	        case pcmk_err_no_quorum:            return pcmk_rc_no_quorum;
690  	        case pcmk_err_schema_validation:    return pcmk_rc_schema_validation;
691  	        case pcmk_err_schema_unchanged:     return pcmk_rc_schema_unchanged;
692  	        case pcmk_err_transform_failed:     return pcmk_rc_transform_failed;
693  	        case pcmk_err_old_data:             return pcmk_rc_old_data;
694  	        case pcmk_err_diff_failed:          return pcmk_rc_diff_failed;
695  	        case pcmk_err_diff_resync:          return pcmk_rc_diff_resync;
696  	        case pcmk_err_cib_modified:         return pcmk_rc_cib_modified;
697  	        case pcmk_err_cib_backup:           return pcmk_rc_cib_backup;
698  	        case pcmk_err_cib_save:             return pcmk_rc_cib_save;
699  	        case pcmk_err_cib_corrupt:          return pcmk_rc_cib_corrupt;
700  	        case pcmk_err_multiple:             return pcmk_rc_multiple;
701  	        case pcmk_err_node_unknown:         return pcmk_rc_node_unknown;
702  	        case pcmk_err_already:              return pcmk_rc_already;
703  	        case pcmk_err_bad_nvpair:           return pcmk_rc_bad_nvpair;
704  	        case pcmk_err_unknown_format:       return pcmk_rc_unknown_format;
705  	        case pcmk_err_generic:              return pcmk_rc_error;
706  	        case pcmk_ok:                       return pcmk_rc_ok;
707  	        default:                            return legacy_rc; // system errno
708  	    }
709  	}
710  	
711  	// Exit status codes
712  	
713  	const char *
714  	crm_exit_name(crm_exit_t exit_code)
715  	{
716  	    switch (exit_code) {
717  	        case CRM_EX_OK: return "CRM_EX_OK";
718  	        case CRM_EX_ERROR: return "CRM_EX_ERROR";
719  	        case CRM_EX_INVALID_PARAM: return "CRM_EX_INVALID_PARAM";
720  	        case CRM_EX_UNIMPLEMENT_FEATURE: return "CRM_EX_UNIMPLEMENT_FEATURE";
721  	        case CRM_EX_INSUFFICIENT_PRIV: return "CRM_EX_INSUFFICIENT_PRIV";
722  	        case CRM_EX_NOT_INSTALLED: return "CRM_EX_NOT_INSTALLED";
723  	        case CRM_EX_NOT_CONFIGURED: return "CRM_EX_NOT_CONFIGURED";
724  	        case CRM_EX_NOT_RUNNING: return "CRM_EX_NOT_RUNNING";
725  	        case CRM_EX_PROMOTED: return "CRM_EX_PROMOTED";
726  	        case CRM_EX_FAILED_PROMOTED: return "CRM_EX_FAILED_PROMOTED";
727  	        case CRM_EX_USAGE: return "CRM_EX_USAGE";
728  	        case CRM_EX_DATAERR: return "CRM_EX_DATAERR";
729  	        case CRM_EX_NOINPUT: return "CRM_EX_NOINPUT";
730  	        case CRM_EX_NOUSER: return "CRM_EX_NOUSER";
731  	        case CRM_EX_NOHOST: return "CRM_EX_NOHOST";
732  	        case CRM_EX_UNAVAILABLE: return "CRM_EX_UNAVAILABLE";
733  	        case CRM_EX_SOFTWARE: return "CRM_EX_SOFTWARE";
734  	        case CRM_EX_OSERR: return "CRM_EX_OSERR";
735  	        case CRM_EX_OSFILE: return "CRM_EX_OSFILE";
736  	        case CRM_EX_CANTCREAT: return "CRM_EX_CANTCREAT";
737  	        case CRM_EX_IOERR: return "CRM_EX_IOERR";
738  	        case CRM_EX_TEMPFAIL: return "CRM_EX_TEMPFAIL";
739  	        case CRM_EX_PROTOCOL: return "CRM_EX_PROTOCOL";
740  	        case CRM_EX_NOPERM: return "CRM_EX_NOPERM";
741  	        case CRM_EX_CONFIG: return "CRM_EX_CONFIG";
742  	        case CRM_EX_FATAL: return "CRM_EX_FATAL";
743  	        case CRM_EX_PANIC: return "CRM_EX_PANIC";
744  	        case CRM_EX_DISCONNECT: return "CRM_EX_DISCONNECT";
745  	        case CRM_EX_DIGEST: return "CRM_EX_DIGEST";
746  	        case CRM_EX_NOSUCH: return "CRM_EX_NOSUCH";
747  	        case CRM_EX_QUORUM: return "CRM_EX_QUORUM";
748  	        case CRM_EX_UNSAFE: return "CRM_EX_UNSAFE";
749  	        case CRM_EX_EXISTS: return "CRM_EX_EXISTS";
750  	        case CRM_EX_MULTIPLE: return "CRM_EX_MULTIPLE";
751  	        case CRM_EX_EXPIRED: return "CRM_EX_EXPIRED";
752  	        case CRM_EX_NOT_YET_IN_EFFECT: return "CRM_EX_NOT_YET_IN_EFFECT";
753  	        case CRM_EX_INDETERMINATE: return "CRM_EX_INDETERMINATE";
754  	        case CRM_EX_UNSATISFIED: return "CRM_EX_UNSATISFIED";
755  	        case CRM_EX_NO_DC: return "CRM_EX_NO_DC";
756  	        case CRM_EX_OLD: return "CRM_EX_OLD";
757  	        case CRM_EX_TIMEOUT: return "CRM_EX_TIMEOUT";
758  	        case CRM_EX_DEGRADED: return "CRM_EX_DEGRADED";
759  	        case CRM_EX_DEGRADED_PROMOTED: return "CRM_EX_DEGRADED_PROMOTED";
760  	        case CRM_EX_NONE: return "CRM_EX_NONE";
761  	        case CRM_EX_MAX: return "CRM_EX_UNKNOWN";
762  	    }
763  	    return "CRM_EX_UNKNOWN";
764  	}
765  	
766  	const char *
767  	crm_exit_str(crm_exit_t exit_code)
768  	{
769  	    switch (exit_code) {
770  	        case CRM_EX_OK: return "OK";
771  	        case CRM_EX_ERROR: return "Error occurred";
772  	        case CRM_EX_INVALID_PARAM: return "Invalid parameter";
773  	        case CRM_EX_UNIMPLEMENT_FEATURE: return "Unimplemented";
774  	        case CRM_EX_INSUFFICIENT_PRIV: return "Insufficient privileges";
775  	        case CRM_EX_NOT_INSTALLED: return "Not installed";
776  	        case CRM_EX_NOT_CONFIGURED: return "Not configured";
777  	        case CRM_EX_NOT_RUNNING: return "Not running";
778  	        case CRM_EX_PROMOTED: return "Promoted";
779  	        case CRM_EX_FAILED_PROMOTED: return "Failed in promoted role";
780  	        case CRM_EX_USAGE: return "Incorrect usage";
781  	        case CRM_EX_DATAERR: return "Invalid data given";
782  	        case CRM_EX_NOINPUT: return "Input file not available";
783  	        case CRM_EX_NOUSER: return "User does not exist";
784  	        case CRM_EX_NOHOST: return "Host does not exist";
785  	        case CRM_EX_UNAVAILABLE: return "Necessary service unavailable";
786  	        case CRM_EX_SOFTWARE: return "Internal software bug";
787  	        case CRM_EX_OSERR: return "Operating system error occurred";
788  	        case CRM_EX_OSFILE: return "System file not available";
789  	        case CRM_EX_CANTCREAT: return "Cannot create output file";
790  	        case CRM_EX_IOERR: return "I/O error occurred";
791  	        case CRM_EX_TEMPFAIL: return "Temporary failure, try again";
792  	        case CRM_EX_PROTOCOL: return "Protocol violated";
793  	        case CRM_EX_NOPERM: return "Insufficient privileges";
794  	        case CRM_EX_CONFIG: return "Invalid configuration";
795  	        case CRM_EX_FATAL: return "Fatal error occurred, will not respawn";
796  	        case CRM_EX_PANIC: return "System panic required";
797  	        case CRM_EX_DISCONNECT: return "Not connected";
798  	        case CRM_EX_DIGEST: return "Digest mismatch";
799  	        case CRM_EX_NOSUCH: return "No such object";
800  	        case CRM_EX_QUORUM: return "Quorum required";
801  	        case CRM_EX_UNSAFE: return "Operation not safe";
802  	        case CRM_EX_EXISTS: return "Requested item already exists";
803  	        case CRM_EX_MULTIPLE: return "Multiple items match request";
804  	        case CRM_EX_EXPIRED: return "Requested item has expired";
805  	        case CRM_EX_NOT_YET_IN_EFFECT: return "Requested item is not yet in effect";
806  	        case CRM_EX_INDETERMINATE: return "Could not determine status";
807  	        case CRM_EX_UNSATISFIED: return "Not applicable under current conditions";
808  	        case CRM_EX_NO_DC: return "DC is not yet elected";
809  	        case CRM_EX_OLD: return "Update was older than existing configuration";
810  	        case CRM_EX_TIMEOUT: return "Timeout occurred";
811  	        case CRM_EX_DEGRADED: return "Service is active but might fail soon";
812  	        case CRM_EX_DEGRADED_PROMOTED: return "Service is promoted but might fail soon";
813  	        case CRM_EX_NONE: return "No exit status available";
814  	        case CRM_EX_MAX: return "Error occurred";
815  	    }
816  	    if ((exit_code > 128) && (exit_code < CRM_EX_MAX)) {
817  	        return "Interrupted by signal";
818  	    }
819  	    return "Unknown exit status";
820  	}
821  	
822  	/*!
823  	 * \brief Map a function return code to the most similar exit code
824  	 *
825  	 * \param[in] rc  Function return code
826  	 *
827  	 * \return Most similar exit code
828  	 */
829  	crm_exit_t
830  	pcmk_rc2exitc(int rc)
831  	{
832  	    switch (rc) {
833  	        case pcmk_rc_ok:
834  	        case pcmk_rc_no_output: // quiet mode, or nothing to output
835  	            return CRM_EX_OK;
836  	
837  	        case pcmk_rc_no_quorum:
838  	            return CRM_EX_QUORUM;
839  	
840  	        case pcmk_rc_old_data:
841  	            return CRM_EX_OLD;
842  	
843  	        case pcmk_rc_cib_corrupt:
844  	        case pcmk_rc_schema_validation:
845  	        case pcmk_rc_transform_failed:
846  	        case pcmk_rc_unpack_error:
847  	            return CRM_EX_CONFIG;
848  	
849  	        case pcmk_rc_bad_nvpair:
850  	            return CRM_EX_INVALID_PARAM;
851  	
852  	        case EACCES:
853  	            return CRM_EX_INSUFFICIENT_PRIV;
854  	
855  	        case EBADF:
856  	        case EINVAL:
857  	        case EFAULT:
858  	        case ENOSYS:
859  	        case EOVERFLOW:
860  	        case pcmk_rc_underflow:
861  	        case pcmk_rc_compression:
862  	        case pcmk_rc_cs_internal:
863  	            return CRM_EX_SOFTWARE;
864  	
865  	        case EBADMSG:
866  	        case EMSGSIZE:
867  	        case ENOMSG:
868  	        case ENOPROTOOPT:
869  	        case EPROTO:
870  	        case EPROTONOSUPPORT:
871  	        case EPROTOTYPE:
872  	            return CRM_EX_PROTOCOL;
873  	
874  	        case ECOMM:
875  	        case ENOMEM:
876  	            return CRM_EX_OSERR;
877  	
878  	        case ECONNABORTED:
879  	        case ECONNREFUSED:
880  	        case ECONNRESET:
881  	        case ENOTCONN:
882  	            return CRM_EX_DISCONNECT;
883  	
884  	        case EEXIST:
885  	        case pcmk_rc_already:
886  	            return CRM_EX_EXISTS;
887  	
888  	        case EIO:
889  	        case pcmk_rc_dot_error:
890  	        case pcmk_rc_graph_error:
891  	            return CRM_EX_IOERR;
892  	
893  	        case ENOTSUP:
894  	#if EOPNOTSUPP != ENOTSUP
895  	        case EOPNOTSUPP:
896  	#endif
897  	            return CRM_EX_UNIMPLEMENT_FEATURE;
898  	
899  	        case ENOTUNIQ:
900  	        case pcmk_rc_multiple:
901  	            return CRM_EX_MULTIPLE;
902  	
903  	        case ENODEV:
904  	        case ENOENT:
905  	        case ENXIO:
906  	        case pcmk_rc_no_transaction:
907  	        case pcmk_rc_unknown_format:
908  	            return CRM_EX_NOSUCH;
909  	
910  	        case pcmk_rc_node_unknown:
911  	        case pcmk_rc_ns_resolution:
912  	            return CRM_EX_NOHOST;
913  	
914  	        case ETIME:
915  	        case ETIMEDOUT:
916  	            return CRM_EX_TIMEOUT;
917  	
918  	        case EAGAIN:
919  	        case EBUSY:
920  	            return CRM_EX_UNSATISFIED;
921  	
922  	        case pcmk_rc_before_range:
923  	            return CRM_EX_NOT_YET_IN_EFFECT;
924  	
925  	        case pcmk_rc_after_range:
926  	            return CRM_EX_EXPIRED;
927  	
928  	        case pcmk_rc_undetermined:
929  	            return CRM_EX_INDETERMINATE;
930  	
931  	        case pcmk_rc_op_unsatisfied:
932  	            return CRM_EX_UNSATISFIED;
933  	
934  	        case pcmk_rc_within_range:
935  	            return CRM_EX_OK;
936  	
937  	        case pcmk_rc_no_input:
938  	            return CRM_EX_NOINPUT;
939  	
940  	        case pcmk_rc_duplicate_id:
941  	            return CRM_EX_MULTIPLE;
942  	
943  	        case pcmk_rc_bad_input:
944  	        case pcmk_rc_bad_xml_patch:
945  	            return CRM_EX_DATAERR;
946  	
947  	        case pcmk_rc_no_dc:
948  	            return CRM_EX_NO_DC;
949  	
950  	        case pcmk_rc_digest_mismatch:
951  	            return CRM_EX_DIGEST;
952  	
953  	        default:
954  	            return CRM_EX_ERROR;
955  	    }
956  	}
957  	
958  	/*!
959  	 * \brief Map a function return code to the most similar OCF exit code
960  	 *
961  	 * \param[in] rc  Function return code
962  	 *
963  	 * \return Most similar OCF exit code
964  	 */
965  	enum ocf_exitcode
966  	pcmk_rc2ocf(int rc)
967  	{
968  	    switch (rc) {
969  	        case pcmk_rc_ok:
970  	            return PCMK_OCF_OK;
971  	
972  	        case pcmk_rc_bad_nvpair:
973  	            return PCMK_OCF_INVALID_PARAM;
974  	
975  	        case EACCES:
976  	            return PCMK_OCF_INSUFFICIENT_PRIV;
977  	
978  	        case ENOTSUP:
979  	#if EOPNOTSUPP != ENOTSUP
980  	        case EOPNOTSUPP:
981  	#endif
982  	            return PCMK_OCF_UNIMPLEMENT_FEATURE;
983  	
984  	        default:
985  	            return PCMK_OCF_UNKNOWN_ERROR;
986  	    }
987  	}
988  	
989  	
990  	// Other functions
991  	
992  	/*!
993  	 * \brief Map a getaddrinfo() return code to the most similar Pacemaker
994  	 *        return code
995  	 *
996  	 * \param[in] gai  getaddrinfo() return code
997  	 *
998  	 * \return Most similar Pacemaker return code
999  	 */
1000 	int
1001 	pcmk__gaierror2rc(int gai)
1002 	{
1003 	    switch (gai) {
1004 	        case 0:
1005 	            return pcmk_rc_ok;
1006 	
1007 	        case EAI_AGAIN:
1008 	            return EAGAIN;
1009 	
1010 	        case EAI_BADFLAGS:
1011 	        case EAI_SERVICE:
1012 	            return EINVAL;
1013 	
1014 	        case EAI_FAMILY:
1015 	            return EAFNOSUPPORT;
1016 	
1017 	        case EAI_MEMORY:
1018 	            return ENOMEM;
1019 	
1020 	        case EAI_NONAME:
1021 	            return pcmk_rc_node_unknown;
1022 	
1023 	        case EAI_SOCKTYPE:
1024 	            return ESOCKTNOSUPPORT;
1025 	
1026 	        case EAI_SYSTEM:
1027 	            return errno;
1028 	
1029 	        default:
1030 	            return pcmk_rc_ns_resolution;
1031 	    }
1032 	}
1033 	
1034 	/*!
1035 	 * \brief Map a bz2 return code to the most similar Pacemaker return code
1036 	 *
1037 	 * \param[in] bz2  bz2 return code
1038 	 *
1039 	 * \return Most similar Pacemaker return code
1040 	 */
1041 	int
1042 	pcmk__bzlib2rc(int bz2)
1043 	{
1044 	    switch (bz2) {
1045 	        case BZ_OK:
1046 	        case BZ_RUN_OK:
1047 	        case BZ_FLUSH_OK:
1048 	        case BZ_FINISH_OK:
1049 	        case BZ_STREAM_END:
1050 	            return pcmk_rc_ok;
1051 	
1052 	        case BZ_MEM_ERROR:
1053 	            return ENOMEM;
1054 	
1055 	        case BZ_DATA_ERROR:
1056 	        case BZ_DATA_ERROR_MAGIC:
1057 	        case BZ_UNEXPECTED_EOF:
1058 	            return pcmk_rc_bad_input;
1059 	
1060 	        case BZ_IO_ERROR:
1061 	            return EIO;
1062 	
1063 	        case BZ_OUTBUFF_FULL:
1064 	            return EFBIG;
1065 	
1066 	        default:
1067 	            return pcmk_rc_compression;
1068 	    }
1069 	}
1070 	
1071 	/*!
1072 	 * \internal
1073 	 * \brief Map a corosync return code to the most similar Pacemaker return code
1074 	 *
1075 	 * \param[in] cs  corosync return code
1076 	 *
1077 	 * \return Most similar Pacemaker return code
1078 	 */
1079 	int
1080 	pcmk__corosync2rc(int cs)
1081 	{
1082 	#if SUPPORT_COROSYNC
1083 	    switch (cs) {
1084 	        case CS_OK:
1085 	            return pcmk_rc_ok;
1086 	
1087 	        /* These are all-purpose internal error occurred codes. */
1088 	        case CS_ERR_LIBRARY:
1089 	        case CS_ERR_FAILED_OPERATION:
1090 	            return pcmk_rc_cs_internal;
1091 	
1092 	        /* None of these are returned by corosync >= 2.0.0 so it's not worth
1093 	         * defining standard Pacemaker return codes to match.
1094 	         */
1095 	        case CS_ERR_VERSION:
1096 	        case CS_ERR_BAD_FLAGS:
1097 	            return pcmk_rc_error;
1098 	
1099 	        /* This is only returned by corosync when qb_trie_create fails, which
1100 	         * only happens when malloc fails, therefore...
1101 	         */
1102 	        case CS_ERR_INIT:
1103 	        case CS_ERR_NO_MEMORY:
1104 	            return ENOMEM;
1105 	
1106 	        case CS_ERR_TIMEOUT:
1107 	            return ETIMEDOUT;
1108 	
1109 	        case CS_ERR_TRY_AGAIN:
1110 	            return EAGAIN;
1111 	
1112 	        case CS_ERR_INVALID_PARAM:
1113 	            return EINVAL;
1114 	
1115 	        case CS_ERR_BAD_HANDLE:
1116 	            return EBADF;
1117 	
1118 	        case CS_ERR_BUSY:
1119 	            return EBUSY;
1120 	
1121 	        case CS_ERR_ACCESS:
1122 	            return EACCES;
1123 	
1124 	        case CS_ERR_NOT_EXIST:
1125 	        case CS_ERR_NAME_NOT_FOUND:
1126 	            return ENOENT;
1127 	
1128 	        case CS_ERR_NAME_TOO_LONG:
1129 	            return ENAMETOOLONG;
1130 	
1131 	        case CS_ERR_EXIST:
1132 	            return EEXIST;
1133 	
1134 	        case CS_ERR_NO_SPACE:
1135 	            return ENOSPC;
1136 	
1137 	        case CS_ERR_INTERRUPT:
1138 	            return EINTR;
1139 	
1140 	        case CS_ERR_NO_RESOURCES:
1141 	            return EMFILE;
1142 	
1143 	        case CS_ERR_NOT_SUPPORTED:
1144 	            return ENOTSUP;
1145 	
1146 	        case CS_ERR_BAD_OPERATION:
1147 	            return EOPNOTSUPP;
1148 	
1149 	        case CS_ERR_MESSAGE_ERROR:
1150 	            return EBADMSG;
1151 	
1152 	        /* These are still handled by corosync, but I can't find any evidence
1153 	         * that they are returned anywhere.  At one point, certain libqb error
1154 	         * codes were converted into these errors but I don't see that happening
1155 	         * anymore.  Thus, just turn them into the default as well.
1156 	         */
1157 	        case CS_ERR_QUEUE_FULL:
1158 	        case CS_ERR_QUEUE_NOT_AVAILABLE:
1159 	            return pcmk_rc_error;
1160 	
1161 	        case CS_ERR_TOO_BIG:
1162 	            return EFBIG;
1163 	
1164 	        case CS_ERR_NO_SECTIONS:
1165 	            return ENODATA;
1166 	    }
1167 	#endif
1168 	
1169 	    return pcmk_rc_error;
1170 	}
1171 	
1172 	crm_exit_t
1173 	crm_exit(crm_exit_t exit_status)
1174 	{
1175 	    /* A compiler could theoretically use any type for crm_exit_t, but an int
1176 	     * should always hold it, so cast to int to keep static analysis happy.
1177 	     */
1178 	    if ((((int) exit_status) < 0) || (((int) exit_status) > CRM_EX_MAX)) {
1179 	        exit_status = CRM_EX_ERROR;
1180 	    }
1181 	
1182 	    pcmk__info("Exiting %s " QB_XS " with status %d (%s: %s)",
1183 	               pcmk__s(crm_system_name, "process"), exit_status,
1184 	               crm_exit_name(exit_status), crm_exit_str(exit_status));
1185 	    pcmk_common_cleanup();
1186 	    exit(exit_status);
1187 	}
1188 	
1189 	/*
1190 	 * External action results
1191 	 */
1192 	
1193 	/*!
1194 	 * \internal
1195 	 * \brief Set the result of an action
1196 	 *
1197 	 * \param[out] result        Where to set action result
1198 	 * \param[in]  exit_status   OCF exit status to set
1199 	 * \param[in]  exec_status   Execution status to set
1200 	 * \param[in]  exit_reason   Human-friendly description of event to set
1201 	 */
1202 	void
1203 	pcmk__set_result(pcmk__action_result_t *result, int exit_status,
1204 	                 enum pcmk_exec_status exec_status, const char *exit_reason)
1205 	{
1206 	    if (result == NULL) {
1207 	        return;
1208 	    }
1209 	
1210 	    result->exit_status = exit_status;
1211 	    result->execution_status = exec_status;
1212 	
1213 	    if (!pcmk__str_eq(result->exit_reason, exit_reason, pcmk__str_none)) {
1214 	        free(result->exit_reason);
1215 	        result->exit_reason = (exit_reason == NULL)? NULL : strdup(exit_reason);
1216 	    }
1217 	}
1218 	
1219 	
1220 	/*!
1221 	 * \internal
1222 	 * \brief Set the result of an action, with a formatted exit reason
1223 	 *
1224 	 * \param[out] result        Where to set action result
1225 	 * \param[in]  exit_status   OCF exit status to set
1226 	 * \param[in]  exec_status   Execution status to set
1227 	 * \param[in]  format        printf-style format for a human-friendly
1228 	 *                           description of reason for result
1229 	 * \param[in]  ...           arguments for \p format
1230 	 */
1231 	G_GNUC_PRINTF(4, 5)
1232 	void
1233 	pcmk__format_result(pcmk__action_result_t *result, int exit_status,
1234 	                    enum pcmk_exec_status exec_status,
1235 	                    const char *format, ...)
1236 	{
1237 	    va_list ap;
1238 	    int len = 0;
1239 	    char *reason = NULL;
1240 	
1241 	    if (result == NULL) {
1242 	        return;
1243 	    }
1244 	
1245 	    result->exit_status = exit_status;
1246 	    result->execution_status = exec_status;
1247 	
1248 	    if (format != NULL) {
1249 	        va_start(ap, format);
1250 	        len = vasprintf(&reason, format, ap);
1251 	        pcmk__assert(len > 0);
1252 	        va_end(ap);
1253 	    }
1254 	    free(result->exit_reason);
1255 	    result->exit_reason = reason;
1256 	}
1257 	
1258 	/*!
1259 	 * \internal
1260 	 * \brief Set the output of an action
1261 	 *
1262 	 * \param[out] result         Action result to set output for
1263 	 * \param[in]  out            Action output to set (must be dynamically
1264 	 *                            allocated)
1265 	 * \param[in]  err            Action error output to set (must be dynamically
1266 	 *                            allocated)
1267 	 *
1268 	 * \note \p result will take ownership of \p out and \p err, so the caller
1269 	 *       should not free them.
1270 	 */
1271 	void
(3) Event deallocator: Deallocator for "struct [unnamed type of 'pcmk__action_result_t']".
Also see events: [allocation][allocation]
1272 	pcmk__set_result_output(pcmk__action_result_t *result, char *out, char *err)
1273 	{
1274 	    if (result == NULL) {
1275 	        return;
1276 	    }
1277 	
1278 	    free(result->action_stdout);
1279 	    result->action_stdout = out;
1280 	
1281 	    free(result->action_stderr);
1282 	    result->action_stderr = err;
1283 	}
1284 	
1285 	/*!
1286 	 * \internal
1287 	 * \brief Clear a result's exit reason, output, and error output
1288 	 *
1289 	 * \param[in,out] result  Result to reset
1290 	 */
1291 	void
1292 	pcmk__reset_result(pcmk__action_result_t *result)
1293 	{
1294 	    if (result == NULL) {
1295 	        return;
1296 	    }
1297 	
1298 	    g_clear_pointer(&result->exit_reason, free);
1299 	    g_clear_pointer(&result->action_stdout, free);
1300 	    g_clear_pointer(&result->action_stderr, free);
1301 	}
1302 	
1303 	/*!
1304 	 * \internal
1305 	 * \brief Copy the result of an action
1306 	 *
1307 	 * \param[in]  src  Result to copy
1308 	 * \param[out] dst  Where to copy \p src to
1309 	 */
1310 	void
1311 	pcmk__copy_result(const pcmk__action_result_t *src, pcmk__action_result_t *dst)
1312 	{
1313 	    CRM_CHECK((src != NULL) && (dst != NULL), return);
1314 	    dst->exit_status = src->exit_status;
1315 	    dst->execution_status = src->execution_status;
CID (unavailable; MK=28a11575bd3785f23d7d31446f16f1e4) (#1 of 1): Resource not released (INCOMPLETE_DEALLOCATOR):
(1) Event allocation: Memory is allocated. [details]
(2) Event allocation: The field "dst->exit_reason" is allocated, but not released in the identified deallocator.
Also see events: [deallocator]
1316 	    dst->exit_reason = pcmk__str_copy(src->exit_reason);
1317 	    dst->action_stdout = pcmk__str_copy(src->action_stdout);
1318 	    dst->action_stderr = pcmk__str_copy(src->action_stderr);
1319 	}
1320