root/lib/common/results.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. G_DEFINE_QUARK
  2. pcmk__result_bounds
  3. log_assertion_as
  4. pcmk__abort_as
  5. fail_assert_as
  6. crm_abort
  7. pcmk_errorname
  8. pcmk_strerror
  9. pcmk_rc_name
  10. pcmk_rc_str
  11. pcmk_rc2legacy
  12. pcmk_legacy2rc
  13. crm_exit_name
  14. crm_exit_str
  15. pcmk_rc2exitc
  16. pcmk_rc2ocf
  17. pcmk__gaierror2rc
  18. pcmk__bzlib2rc
  19. crm_exit
  20. pcmk__set_result
  21. G_GNUC_PRINTF
  22. pcmk__set_result_output
  23. pcmk__reset_result
  24. pcmk__copy_result

   1 /*
   2  * Copyright 2004-2025 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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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     crm_err("%s: Triggered fatal assertion at %s:%d : %s",
 134             function, file, 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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             crm_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             crm_err("%s: Forked child [%d] to record non-fatal assertion at "
 194                     "%s:%d : %s", function, pid, file, line, assert_condition);
 195             crm_write_blackbox(SIGTRAP, NULL);
 196             do {
 197                 if (waitpid(pid, &status, 0) == pid) {
 198                     return; // Child finished dumping core
 199                 }
 200             } while (errno == EINTR);
 201             if (errno == ECHILD) {
 202                 // crm_mon ignores SIGCHLD
 203                 crm_trace("Cannot wait on forked child [%d] "
 204                           "(SIGCHLD is probably ignored)", pid);
 205             } else {
 206                 crm_err("Cannot wait on forked child [%d]: %s",
 207                         pid, pcmk_rc_str(errno));
 208             }
 209             break;
 210     }
 211 }
 212 
 213 /* coverity[+kill] */
 214 void
 215 crm_abort(const char *file, const char *function, int line,
     /* [previous][next][first][last][top][bottom][index][help] */
 216           const char *assert_condition, gboolean do_core, gboolean do_fork)
 217 {
 218     if (!do_fork) {
 219         pcmk__abort_as(file, function, line, assert_condition); // No return
 220     } else if (do_core) {
 221         fail_assert_as(file, function, line, assert_condition);
 222     } else {
 223         log_assertion_as(file, function, line, assert_condition);
 224     }
 225 }
 226 
 227 // @COMPAT Legacy function return codes
 228 
 229 //! \deprecated Use standard return codes and pcmk_rc_name() instead
 230 const char *
 231 pcmk_errorname(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 232 {
 233     rc = abs(rc);
 234     switch (rc) {
 235         case pcmk_err_generic: return "pcmk_err_generic";
 236         case pcmk_err_no_quorum: return "pcmk_err_no_quorum";
 237         case pcmk_err_schema_validation: return "pcmk_err_schema_validation";
 238         case pcmk_err_transform_failed: return "pcmk_err_transform_failed";
 239         case pcmk_err_old_data: return "pcmk_err_old_data";
 240         case pcmk_err_diff_failed: return "pcmk_err_diff_failed";
 241         case pcmk_err_diff_resync: return "pcmk_err_diff_resync";
 242         case pcmk_err_cib_modified: return "pcmk_err_cib_modified";
 243         case pcmk_err_cib_backup: return "pcmk_err_cib_backup";
 244         case pcmk_err_cib_save: return "pcmk_err_cib_save";
 245         case pcmk_err_cib_corrupt: return "pcmk_err_cib_corrupt";
 246         case pcmk_err_multiple: return "pcmk_err_multiple";
 247         case pcmk_err_node_unknown: return "pcmk_err_node_unknown";
 248         case pcmk_err_already: return "pcmk_err_already";
 249         case pcmk_err_bad_nvpair: return "pcmk_err_bad_nvpair";
 250         case pcmk_err_unknown_format: return "pcmk_err_unknown_format";
 251         default: return pcmk_rc_name(rc); // system errno
 252     }
 253 }
 254 
 255 //! \deprecated Use standard return codes and pcmk_rc_str() instead
 256 const char *
 257 pcmk_strerror(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 258 {
 259     return pcmk_rc_str(pcmk_legacy2rc(rc));
 260 }
 261 
 262 // Standard Pacemaker API return codes
 263 
 264 /* This array is used only for nonzero values of pcmk_rc_e. Its values must be
 265  * kept in the exact reverse order of the enum value numbering (i.e. add new
 266  * values to the end of the array).
 267  */
 268 static const struct pcmk__rc_info {
 269     const char *name;
 270     const char *desc;
 271     int legacy_rc;
 272 } pcmk__rcs[] = {
 273     { "pcmk_rc_error",
 274       "Error",
 275       -pcmk_err_generic,
 276     },
 277     { "pcmk_rc_unknown_format",
 278       "Unknown output format",
 279       -pcmk_err_unknown_format,
 280     },
 281     { "pcmk_rc_bad_nvpair",
 282       "Bad name/value pair given",
 283       -pcmk_err_bad_nvpair,
 284     },
 285     { "pcmk_rc_already",
 286       "Already in requested state",
 287       -pcmk_err_already,
 288     },
 289     { "pcmk_rc_node_unknown",
 290       "Node not found",
 291       -pcmk_err_node_unknown,
 292     },
 293     { "pcmk_rc_multiple",
 294       "Resource active on multiple nodes",
 295       -pcmk_err_multiple,
 296     },
 297     { "pcmk_rc_cib_corrupt",
 298       "Could not parse on-disk configuration",
 299       -pcmk_err_cib_corrupt,
 300     },
 301     { "pcmk_rc_cib_save",
 302       "Could not save new configuration to disk",
 303       -pcmk_err_cib_save,
 304     },
 305     { "pcmk_rc_cib_backup",
 306       "Could not archive previous configuration",
 307       -pcmk_err_cib_backup,
 308     },
 309     { "pcmk_rc_cib_modified",
 310       "On-disk configuration was manually modified",
 311       -pcmk_err_cib_modified,
 312     },
 313     { "pcmk_rc_diff_resync",
 314       "Application of update diff failed, requesting full refresh",
 315       -pcmk_err_diff_resync,
 316     },
 317     { "pcmk_rc_diff_failed",
 318       "Application of update diff failed",
 319       -pcmk_err_diff_failed,
 320     },
 321     { "pcmk_rc_old_data",
 322       "Update was older than existing configuration",
 323       -pcmk_err_old_data,
 324     },
 325     { "pcmk_rc_transform_failed",
 326       "Schema transform failed",
 327       -pcmk_err_transform_failed,
 328     },
 329     { "pcmk_rc_schema_unchanged",
 330       "Schema is already the latest available",
 331       -pcmk_err_schema_unchanged,
 332     },
 333     { "pcmk_rc_schema_validation",
 334       "Update does not conform to the configured schema",
 335       -pcmk_err_schema_validation,
 336     },
 337     { "pcmk_rc_no_quorum",
 338       "Operation requires quorum",
 339       -pcmk_err_no_quorum,
 340     },
 341     { "pcmk_rc_ipc_unauthorized",
 342       "IPC server is blocked by unauthorized process",
 343       -pcmk_err_generic,
 344     },
 345     { "pcmk_rc_ipc_unresponsive",
 346       "IPC server is unresponsive",
 347       -pcmk_err_generic,
 348     },
 349     { "pcmk_rc_ipc_pid_only",
 350       "IPC server process is active but not accepting connections",
 351       -pcmk_err_generic,
 352     },
 353     { "pcmk_rc_op_unsatisfied",
 354       "Not applicable under current conditions",
 355       -pcmk_err_generic,
 356     },
 357     { "pcmk_rc_undetermined",
 358       "Result undetermined",
 359       -pcmk_err_generic,
 360     },
 361     { "pcmk_rc_before_range",
 362       "Result occurs before given range",
 363       -pcmk_err_generic,
 364     },
 365     { "pcmk_rc_within_range",
 366       "Result occurs within given range",
 367       -pcmk_err_generic,
 368     },
 369     { "pcmk_rc_after_range",
 370       "Result occurs after given range",
 371       -pcmk_err_generic,
 372     },
 373     { "pcmk_rc_no_output",
 374       "Output message produced no output",
 375       -pcmk_err_generic,
 376     },
 377     { "pcmk_rc_no_input",
 378       "Input file not available",
 379       -pcmk_err_generic,
 380     },
 381     { "pcmk_rc_underflow",
 382       "Value too small to be stored in data type",
 383       -pcmk_err_generic,
 384     },
 385     { "pcmk_rc_dot_error",
 386       "Error writing dot(1) file",
 387       -pcmk_err_generic,
 388     },
 389     { "pcmk_rc_graph_error",
 390       "Error writing graph file",
 391       -pcmk_err_generic,
 392     },
 393     { "pcmk_rc_invalid_transition",
 394       "Cluster simulation produced invalid transition",
 395       -pcmk_err_generic,
 396     },
 397     { "pcmk_rc_unpack_error",
 398       "Unable to parse CIB XML",
 399       -pcmk_err_generic,
 400     },
 401     { "pcmk_rc_duplicate_id",
 402       "Two or more XML elements have the same ID",
 403       -pcmk_err_generic,
 404     },
 405     { "pcmk_rc_disabled",
 406       "Disabled",
 407       -pcmk_err_generic,
 408     },
 409     { "pcmk_rc_bad_input",
 410       "Bad input value provided",
 411       -pcmk_err_generic,
 412     },
 413     { "pcmk_rc_bad_xml_patch",
 414       "Bad XML patch format",
 415       -pcmk_err_generic,
 416     },
 417     { "pcmk_rc_no_transaction",
 418       "No active transaction found",
 419       -pcmk_err_generic,
 420     },
 421     { "pcmk_rc_ns_resolution",
 422       "Nameserver resolution error",
 423       -pcmk_err_generic,
 424     },
 425     { "pcmk_rc_compression",
 426       "Compression/decompression error",
 427       -pcmk_err_generic,
 428     },
 429     { "pcmk_rc_no_dc",
 430       "DC is not yet elected",
 431       -pcmk_err_generic,
 432     },
 433     { "pcmk_rc_ipc_more",
 434       "More IPC message fragments to send",
 435       -pcmk_err_generic,
 436     },
 437 };
 438 
 439 /*!
 440  * \internal
 441  * \brief The number of <tt>enum pcmk_rc_e</tt> values, excluding \c pcmk_rc_ok
 442  *
 443  * This constant stores the number of negative standard Pacemaker return codes.
 444  * These represent Pacemaker-custom error codes. The count does not include
 445  * positive system error numbers, nor does it include \c pcmk_rc_ok (success).
 446  */
 447 const size_t pcmk__n_rc = PCMK__NELEM(pcmk__rcs);
 448 
 449 /*!
 450  * \brief Get a return code constant name as a string
 451  *
 452  * \param[in] rc  Integer return code to convert
 453  *
 454  * \return String of constant name corresponding to rc
 455  */
 456 const char *
 457 pcmk_rc_name(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 458 {
 459     if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < pcmk__n_rc)) {
 460         return pcmk__rcs[pcmk_rc_error - rc].name;
 461     }
 462     switch (rc) {
 463         case pcmk_rc_ok:        return "pcmk_rc_ok";
 464         case E2BIG:             return "E2BIG";
 465         case EACCES:            return "EACCES";
 466         case EADDRINUSE:        return "EADDRINUSE";
 467         case EADDRNOTAVAIL:     return "EADDRNOTAVAIL";
 468         case EAFNOSUPPORT:      return "EAFNOSUPPORT";
 469         case EAGAIN:            return "EAGAIN";
 470         case EALREADY:          return "EALREADY";
 471         case EBADF:             return "EBADF";
 472         case EBADMSG:           return "EBADMSG";
 473         case EBUSY:             return "EBUSY";
 474         case ECANCELED:         return "ECANCELED";
 475         case ECHILD:            return "ECHILD";
 476         case ECOMM:             return "ECOMM";
 477         case ECONNABORTED:      return "ECONNABORTED";
 478         case ECONNREFUSED:      return "ECONNREFUSED";
 479         case ECONNRESET:        return "ECONNRESET";
 480         /* case EDEADLK:        return "EDEADLK"; */
 481         case EDESTADDRREQ:      return "EDESTADDRREQ";
 482         case EDOM:              return "EDOM";
 483         case EDQUOT:            return "EDQUOT";
 484         case EEXIST:            return "EEXIST";
 485         case EFAULT:            return "EFAULT";
 486         case EFBIG:             return "EFBIG";
 487         case EHOSTDOWN:         return "EHOSTDOWN";
 488         case EHOSTUNREACH:      return "EHOSTUNREACH";
 489         case EIDRM:             return "EIDRM";
 490         case EILSEQ:            return "EILSEQ";
 491         case EINPROGRESS:       return "EINPROGRESS";
 492         case EINTR:             return "EINTR";
 493         case EINVAL:            return "EINVAL";
 494         case EIO:               return "EIO";
 495         case EISCONN:           return "EISCONN";
 496         case EISDIR:            return "EISDIR";
 497         case ELIBACC:           return "ELIBACC";
 498         case ELOOP:             return "ELOOP";
 499         case EMFILE:            return "EMFILE";
 500         case EMLINK:            return "EMLINK";
 501         case EMSGSIZE:          return "EMSGSIZE";
 502 #ifdef EMULTIHOP // Not available on OpenBSD
 503         case EMULTIHOP:         return "EMULTIHOP";
 504 #endif
 505         case ENAMETOOLONG:      return "ENAMETOOLONG";
 506         case ENETDOWN:          return "ENETDOWN";
 507         case ENETRESET:         return "ENETRESET";
 508         case ENETUNREACH:       return "ENETUNREACH";
 509         case ENFILE:            return "ENFILE";
 510         case ENOBUFS:           return "ENOBUFS";
 511         case ENODATA:           return "ENODATA";
 512         case ENODEV:            return "ENODEV";
 513         case ENOENT:            return "ENOENT";
 514         case ENOEXEC:           return "ENOEXEC";
 515         case ENOKEY:            return "ENOKEY";
 516         case ENOLCK:            return "ENOLCK";
 517 #ifdef ENOLINK // Not available on OpenBSD
 518         case ENOLINK:           return "ENOLINK";
 519 #endif
 520         case ENOMEM:            return "ENOMEM";
 521         case ENOMSG:            return "ENOMSG";
 522         case ENOPROTOOPT:       return "ENOPROTOOPT";
 523         case ENOSPC:            return "ENOSPC";
 524 #ifdef ENOSR
 525         case ENOSR:             return "ENOSR";
 526 #endif
 527 #ifdef ENOSTR
 528         case ENOSTR:            return "ENOSTR";
 529 #endif
 530         case ENOSYS:            return "ENOSYS";
 531         case ENOTBLK:           return "ENOTBLK";
 532         case ENOTCONN:          return "ENOTCONN";
 533         case ENOTDIR:           return "ENOTDIR";
 534         case ENOTEMPTY:         return "ENOTEMPTY";
 535         case ENOTSOCK:          return "ENOTSOCK";
 536 #if ENOTSUP != EOPNOTSUPP
 537         case ENOTSUP:           return "ENOTSUP";
 538 #endif
 539         case ENOTTY:            return "ENOTTY";
 540         case ENOTUNIQ:          return "ENOTUNIQ";
 541         case ENXIO:             return "ENXIO";
 542         case EOPNOTSUPP:        return "EOPNOTSUPP";
 543         case EOVERFLOW:         return "EOVERFLOW";
 544         case EPERM:             return "EPERM";
 545         case EPFNOSUPPORT:      return "EPFNOSUPPORT";
 546         case EPIPE:             return "EPIPE";
 547         case EPROTO:            return "EPROTO";
 548         case EPROTONOSUPPORT:   return "EPROTONOSUPPORT";
 549         case EPROTOTYPE:        return "EPROTOTYPE";
 550         case ERANGE:            return "ERANGE";
 551         case EREMOTE:           return "EREMOTE";
 552         case EREMOTEIO:         return "EREMOTEIO";
 553         case EROFS:             return "EROFS";
 554         case ESHUTDOWN:         return "ESHUTDOWN";
 555         case ESPIPE:            return "ESPIPE";
 556         case ESOCKTNOSUPPORT:   return "ESOCKTNOSUPPORT";
 557         case ESRCH:             return "ESRCH";
 558         case ESTALE:            return "ESTALE";
 559         case ETIME:             return "ETIME";
 560         case ETIMEDOUT:         return "ETIMEDOUT";
 561         case ETXTBSY:           return "ETXTBSY";
 562 #ifdef EUNATCH
 563         case EUNATCH:           return "EUNATCH";
 564 #endif
 565         case EUSERS:            return "EUSERS";
 566         /* case EWOULDBLOCK:    return "EWOULDBLOCK"; */
 567         case EXDEV:             return "EXDEV";
 568 
 569 #ifdef EBADE // Not available on OS X
 570         case EBADE:             return "EBADE";
 571         case EBADFD:            return "EBADFD";
 572         case EBADSLT:           return "EBADSLT";
 573         case EDEADLOCK:         return "EDEADLOCK";
 574         case EBADR:             return "EBADR";
 575         case EBADRQC:           return "EBADRQC";
 576         case ECHRNG:            return "ECHRNG";
 577 #ifdef EISNAM // Not available on OS X, Illumos, Solaris
 578         case EISNAM:            return "EISNAM";
 579         case EKEYEXPIRED:       return "EKEYEXPIRED";
 580         case EKEYREVOKED:       return "EKEYREVOKED";
 581 #endif
 582         case EKEYREJECTED:      return "EKEYREJECTED";
 583         case EL2HLT:            return "EL2HLT";
 584         case EL2NSYNC:          return "EL2NSYNC";
 585         case EL3HLT:            return "EL3HLT";
 586         case EL3RST:            return "EL3RST";
 587         case ELIBBAD:           return "ELIBBAD";
 588         case ELIBMAX:           return "ELIBMAX";
 589         case ELIBSCN:           return "ELIBSCN";
 590         case ELIBEXEC:          return "ELIBEXEC";
 591 #ifdef ENOMEDIUM // Not available on OS X, Illumos, Solaris
 592         case ENOMEDIUM:         return "ENOMEDIUM";
 593         case EMEDIUMTYPE:       return "EMEDIUMTYPE";
 594 #endif
 595         case ENONET:            return "ENONET";
 596         case ENOPKG:            return "ENOPKG";
 597         case EREMCHG:           return "EREMCHG";
 598         case ERESTART:          return "ERESTART";
 599         case ESTRPIPE:          return "ESTRPIPE";
 600 #ifdef EUCLEAN // Not available on OS X, Illumos, Solaris
 601         case EUCLEAN:           return "EUCLEAN";
 602 #endif
 603         case EXFULL:            return "EXFULL";
 604 #endif // EBADE
 605         default:                return "Unknown";
 606     }
 607 }
 608 
 609 /*!
 610  * \brief Get a user-friendly description of a return code
 611  *
 612  * \param[in] rc  Integer return code to convert
 613  *
 614  * \return String description of rc
 615  */
 616 const char *
 617 pcmk_rc_str(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 618 {
 619     if (rc == pcmk_rc_ok) {
 620         return "OK";
 621     }
 622     if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < pcmk__n_rc)) {
 623         return pcmk__rcs[pcmk_rc_error - rc].desc;
 624     }
 625     if (rc < 0) {
 626         return "Error";
 627     }
 628 
 629     // Handle values that could be defined by system or by portability.h
 630     switch (rc) {
 631 #ifdef PCMK__ENOTUNIQ
 632         case ENOTUNIQ:      return "Name not unique on network";
 633 #endif
 634 #ifdef PCMK__ECOMM
 635         case ECOMM:         return "Communication error on send";
 636 #endif
 637 #ifdef PCMK__ELIBACC
 638         case ELIBACC:       return "Can not access a needed shared library";
 639 #endif
 640 #ifdef PCMK__EREMOTEIO
 641         case EREMOTEIO:     return "Remote I/O error";
 642 #endif
 643 #ifdef PCMK__ENOKEY
 644         case ENOKEY:        return "Required key not available";
 645 #endif
 646 #ifdef PCMK__ENODATA
 647         case ENODATA:       return "No data available";
 648 #endif
 649 #ifdef PCMK__ETIME
 650         case ETIME:         return "Timer expired";
 651 #endif
 652 #ifdef PCMK__EKEYREJECTED
 653         case EKEYREJECTED:  return "Key was rejected by service";
 654 #endif
 655         default:            return strerror(rc);
 656     }
 657 }
 658 
 659 // This returns negative values for errors
 660 //! \deprecated Use standard return codes instead
 661 int
 662 pcmk_rc2legacy(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 663 {
 664     if (rc >= 0) {
 665         return -rc; // OK or system errno
 666     }
 667     if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < pcmk__n_rc)) {
 668         return pcmk__rcs[pcmk_rc_error - rc].legacy_rc;
 669     }
 670     return -pcmk_err_generic;
 671 }
 672 
 673 //! \deprecated Use standard return codes instead
 674 int
 675 pcmk_legacy2rc(int legacy_rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 676 {
 677     legacy_rc = abs(legacy_rc);
 678     switch (legacy_rc) {
 679         case pcmk_err_no_quorum:            return pcmk_rc_no_quorum;
 680         case pcmk_err_schema_validation:    return pcmk_rc_schema_validation;
 681         case pcmk_err_schema_unchanged:     return pcmk_rc_schema_unchanged;
 682         case pcmk_err_transform_failed:     return pcmk_rc_transform_failed;
 683         case pcmk_err_old_data:             return pcmk_rc_old_data;
 684         case pcmk_err_diff_failed:          return pcmk_rc_diff_failed;
 685         case pcmk_err_diff_resync:          return pcmk_rc_diff_resync;
 686         case pcmk_err_cib_modified:         return pcmk_rc_cib_modified;
 687         case pcmk_err_cib_backup:           return pcmk_rc_cib_backup;
 688         case pcmk_err_cib_save:             return pcmk_rc_cib_save;
 689         case pcmk_err_cib_corrupt:          return pcmk_rc_cib_corrupt;
 690         case pcmk_err_multiple:             return pcmk_rc_multiple;
 691         case pcmk_err_node_unknown:         return pcmk_rc_node_unknown;
 692         case pcmk_err_already:              return pcmk_rc_already;
 693         case pcmk_err_bad_nvpair:           return pcmk_rc_bad_nvpair;
 694         case pcmk_err_unknown_format:       return pcmk_rc_unknown_format;
 695         case pcmk_err_generic:              return pcmk_rc_error;
 696         case pcmk_ok:                       return pcmk_rc_ok;
 697         default:                            return legacy_rc; // system errno
 698     }
 699 }
 700 
 701 // Exit status codes
 702 
 703 const char *
 704 crm_exit_name(crm_exit_t exit_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 705 {
 706     switch (exit_code) {
 707         case CRM_EX_OK: return "CRM_EX_OK";
 708         case CRM_EX_ERROR: return "CRM_EX_ERROR";
 709         case CRM_EX_INVALID_PARAM: return "CRM_EX_INVALID_PARAM";
 710         case CRM_EX_UNIMPLEMENT_FEATURE: return "CRM_EX_UNIMPLEMENT_FEATURE";
 711         case CRM_EX_INSUFFICIENT_PRIV: return "CRM_EX_INSUFFICIENT_PRIV";
 712         case CRM_EX_NOT_INSTALLED: return "CRM_EX_NOT_INSTALLED";
 713         case CRM_EX_NOT_CONFIGURED: return "CRM_EX_NOT_CONFIGURED";
 714         case CRM_EX_NOT_RUNNING: return "CRM_EX_NOT_RUNNING";
 715         case CRM_EX_PROMOTED: return "CRM_EX_PROMOTED";
 716         case CRM_EX_FAILED_PROMOTED: return "CRM_EX_FAILED_PROMOTED";
 717         case CRM_EX_USAGE: return "CRM_EX_USAGE";
 718         case CRM_EX_DATAERR: return "CRM_EX_DATAERR";
 719         case CRM_EX_NOINPUT: return "CRM_EX_NOINPUT";
 720         case CRM_EX_NOUSER: return "CRM_EX_NOUSER";
 721         case CRM_EX_NOHOST: return "CRM_EX_NOHOST";
 722         case CRM_EX_UNAVAILABLE: return "CRM_EX_UNAVAILABLE";
 723         case CRM_EX_SOFTWARE: return "CRM_EX_SOFTWARE";
 724         case CRM_EX_OSERR: return "CRM_EX_OSERR";
 725         case CRM_EX_OSFILE: return "CRM_EX_OSFILE";
 726         case CRM_EX_CANTCREAT: return "CRM_EX_CANTCREAT";
 727         case CRM_EX_IOERR: return "CRM_EX_IOERR";
 728         case CRM_EX_TEMPFAIL: return "CRM_EX_TEMPFAIL";
 729         case CRM_EX_PROTOCOL: return "CRM_EX_PROTOCOL";
 730         case CRM_EX_NOPERM: return "CRM_EX_NOPERM";
 731         case CRM_EX_CONFIG: return "CRM_EX_CONFIG";
 732         case CRM_EX_FATAL: return "CRM_EX_FATAL";
 733         case CRM_EX_PANIC: return "CRM_EX_PANIC";
 734         case CRM_EX_DISCONNECT: return "CRM_EX_DISCONNECT";
 735         case CRM_EX_DIGEST: return "CRM_EX_DIGEST";
 736         case CRM_EX_NOSUCH: return "CRM_EX_NOSUCH";
 737         case CRM_EX_QUORUM: return "CRM_EX_QUORUM";
 738         case CRM_EX_UNSAFE: return "CRM_EX_UNSAFE";
 739         case CRM_EX_EXISTS: return "CRM_EX_EXISTS";
 740         case CRM_EX_MULTIPLE: return "CRM_EX_MULTIPLE";
 741         case CRM_EX_EXPIRED: return "CRM_EX_EXPIRED";
 742         case CRM_EX_NOT_YET_IN_EFFECT: return "CRM_EX_NOT_YET_IN_EFFECT";
 743         case CRM_EX_INDETERMINATE: return "CRM_EX_INDETERMINATE";
 744         case CRM_EX_UNSATISFIED: return "CRM_EX_UNSATISFIED";
 745         case CRM_EX_NO_DC: return "CRM_EX_NO_DC";
 746         case CRM_EX_OLD: return "CRM_EX_OLD";
 747         case CRM_EX_TIMEOUT: return "CRM_EX_TIMEOUT";
 748         case CRM_EX_DEGRADED: return "CRM_EX_DEGRADED";
 749         case CRM_EX_DEGRADED_PROMOTED: return "CRM_EX_DEGRADED_PROMOTED";
 750         case CRM_EX_NONE: return "CRM_EX_NONE";
 751         case CRM_EX_MAX: return "CRM_EX_UNKNOWN";
 752     }
 753     return "CRM_EX_UNKNOWN";
 754 }
 755 
 756 const char *
 757 crm_exit_str(crm_exit_t exit_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 758 {
 759     switch (exit_code) {
 760         case CRM_EX_OK: return "OK";
 761         case CRM_EX_ERROR: return "Error occurred";
 762         case CRM_EX_INVALID_PARAM: return "Invalid parameter";
 763         case CRM_EX_UNIMPLEMENT_FEATURE: return "Unimplemented";
 764         case CRM_EX_INSUFFICIENT_PRIV: return "Insufficient privileges";
 765         case CRM_EX_NOT_INSTALLED: return "Not installed";
 766         case CRM_EX_NOT_CONFIGURED: return "Not configured";
 767         case CRM_EX_NOT_RUNNING: return "Not running";
 768         case CRM_EX_PROMOTED: return "Promoted";
 769         case CRM_EX_FAILED_PROMOTED: return "Failed in promoted role";
 770         case CRM_EX_USAGE: return "Incorrect usage";
 771         case CRM_EX_DATAERR: return "Invalid data given";
 772         case CRM_EX_NOINPUT: return "Input file not available";
 773         case CRM_EX_NOUSER: return "User does not exist";
 774         case CRM_EX_NOHOST: return "Host does not exist";
 775         case CRM_EX_UNAVAILABLE: return "Necessary service unavailable";
 776         case CRM_EX_SOFTWARE: return "Internal software bug";
 777         case CRM_EX_OSERR: return "Operating system error occurred";
 778         case CRM_EX_OSFILE: return "System file not available";
 779         case CRM_EX_CANTCREAT: return "Cannot create output file";
 780         case CRM_EX_IOERR: return "I/O error occurred";
 781         case CRM_EX_TEMPFAIL: return "Temporary failure, try again";
 782         case CRM_EX_PROTOCOL: return "Protocol violated";
 783         case CRM_EX_NOPERM: return "Insufficient privileges";
 784         case CRM_EX_CONFIG: return "Invalid configuration";
 785         case CRM_EX_FATAL: return "Fatal error occurred, will not respawn";
 786         case CRM_EX_PANIC: return "System panic required";
 787         case CRM_EX_DISCONNECT: return "Not connected";
 788         case CRM_EX_DIGEST: return "Digest mismatch";
 789         case CRM_EX_NOSUCH: return "No such object";
 790         case CRM_EX_QUORUM: return "Quorum required";
 791         case CRM_EX_UNSAFE: return "Operation not safe";
 792         case CRM_EX_EXISTS: return "Requested item already exists";
 793         case CRM_EX_MULTIPLE: return "Multiple items match request";
 794         case CRM_EX_EXPIRED: return "Requested item has expired";
 795         case CRM_EX_NOT_YET_IN_EFFECT: return "Requested item is not yet in effect";
 796         case CRM_EX_INDETERMINATE: return "Could not determine status";
 797         case CRM_EX_UNSATISFIED: return "Not applicable under current conditions";
 798         case CRM_EX_NO_DC: return "DC is not yet elected";
 799         case CRM_EX_OLD: return "Update was older than existing configuration";
 800         case CRM_EX_TIMEOUT: return "Timeout occurred";
 801         case CRM_EX_DEGRADED: return "Service is active but might fail soon";
 802         case CRM_EX_DEGRADED_PROMOTED: return "Service is promoted but might fail soon";
 803         case CRM_EX_NONE: return "No exit status available";
 804         case CRM_EX_MAX: return "Error occurred";
 805     }
 806     if ((exit_code > 128) && (exit_code < CRM_EX_MAX)) {
 807         return "Interrupted by signal";
 808     }
 809     return "Unknown exit status";
 810 }
 811 
 812 /*!
 813  * \brief Map a function return code to the most similar exit code
 814  *
 815  * \param[in] rc  Function return code
 816  *
 817  * \return Most similar exit code
 818  */
 819 crm_exit_t
 820 pcmk_rc2exitc(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 821 {
 822     switch (rc) {
 823         case pcmk_rc_ok:
 824         case pcmk_rc_no_output: // quiet mode, or nothing to output
 825             return CRM_EX_OK;
 826 
 827         case pcmk_rc_no_quorum:
 828             return CRM_EX_QUORUM;
 829 
 830         case pcmk_rc_old_data:
 831             return CRM_EX_OLD;
 832 
 833         case pcmk_rc_cib_corrupt:
 834         case pcmk_rc_schema_validation:
 835         case pcmk_rc_transform_failed:
 836         case pcmk_rc_unpack_error:
 837             return CRM_EX_CONFIG;
 838 
 839         case pcmk_rc_bad_nvpair:
 840             return CRM_EX_INVALID_PARAM;
 841 
 842         case EACCES:
 843             return CRM_EX_INSUFFICIENT_PRIV;
 844 
 845         case EBADF:
 846         case EINVAL:
 847         case EFAULT:
 848         case ENOSYS:
 849         case EOVERFLOW:
 850         case pcmk_rc_underflow:
 851         case pcmk_rc_compression:
 852             return CRM_EX_SOFTWARE;
 853 
 854         case EBADMSG:
 855         case EMSGSIZE:
 856         case ENOMSG:
 857         case ENOPROTOOPT:
 858         case EPROTO:
 859         case EPROTONOSUPPORT:
 860         case EPROTOTYPE:
 861             return CRM_EX_PROTOCOL;
 862 
 863         case ECOMM:
 864         case ENOMEM:
 865             return CRM_EX_OSERR;
 866 
 867         case ECONNABORTED:
 868         case ECONNREFUSED:
 869         case ECONNRESET:
 870         case ENOTCONN:
 871             return CRM_EX_DISCONNECT;
 872 
 873         case EEXIST:
 874         case pcmk_rc_already:
 875             return CRM_EX_EXISTS;
 876 
 877         case EIO:
 878         case pcmk_rc_dot_error:
 879         case pcmk_rc_graph_error:
 880             return CRM_EX_IOERR;
 881 
 882         case ENOTSUP:
 883 #if EOPNOTSUPP != ENOTSUP
 884         case EOPNOTSUPP:
 885 #endif
 886             return CRM_EX_UNIMPLEMENT_FEATURE;
 887 
 888         case ENOTUNIQ:
 889         case pcmk_rc_multiple:
 890             return CRM_EX_MULTIPLE;
 891 
 892         case ENODEV:
 893         case ENOENT:
 894         case ENXIO:
 895         case pcmk_rc_no_transaction:
 896         case pcmk_rc_unknown_format:
 897             return CRM_EX_NOSUCH;
 898 
 899         case pcmk_rc_node_unknown:
 900         case pcmk_rc_ns_resolution:
 901             return CRM_EX_NOHOST;
 902 
 903         case ETIME:
 904         case ETIMEDOUT:
 905             return CRM_EX_TIMEOUT;
 906 
 907         case EAGAIN:
 908         case EBUSY:
 909             return CRM_EX_UNSATISFIED;
 910 
 911         case pcmk_rc_before_range:
 912             return CRM_EX_NOT_YET_IN_EFFECT;
 913 
 914         case pcmk_rc_after_range:
 915             return CRM_EX_EXPIRED;
 916 
 917         case pcmk_rc_undetermined:
 918             return CRM_EX_INDETERMINATE;
 919 
 920         case pcmk_rc_op_unsatisfied:
 921             return CRM_EX_UNSATISFIED;
 922 
 923         case pcmk_rc_within_range:
 924             return CRM_EX_OK;
 925 
 926         case pcmk_rc_no_input:
 927             return CRM_EX_NOINPUT;
 928 
 929         case pcmk_rc_duplicate_id:
 930             return CRM_EX_MULTIPLE;
 931 
 932         case pcmk_rc_bad_input:
 933         case pcmk_rc_bad_xml_patch:
 934             return CRM_EX_DATAERR;
 935 
 936         case pcmk_rc_no_dc:
 937             return CRM_EX_NO_DC;
 938 
 939         default:
 940             return CRM_EX_ERROR;
 941     }
 942 }
 943 
 944 /*!
 945  * \brief Map a function return code to the most similar OCF exit code
 946  *
 947  * \param[in] rc  Function return code
 948  *
 949  * \return Most similar OCF exit code
 950  */
 951 enum ocf_exitcode
 952 pcmk_rc2ocf(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 953 {
 954     switch (rc) {
 955         case pcmk_rc_ok:
 956             return PCMK_OCF_OK;
 957 
 958         case pcmk_rc_bad_nvpair:
 959             return PCMK_OCF_INVALID_PARAM;
 960 
 961         case EACCES:
 962             return PCMK_OCF_INSUFFICIENT_PRIV;
 963 
 964         case ENOTSUP:
 965 #if EOPNOTSUPP != ENOTSUP
 966         case EOPNOTSUPP:
 967 #endif
 968             return PCMK_OCF_UNIMPLEMENT_FEATURE;
 969 
 970         default:
 971             return PCMK_OCF_UNKNOWN_ERROR;
 972     }
 973 }
 974 
 975 
 976 // Other functions
 977 
 978 /*!
 979  * \brief Map a getaddrinfo() return code to the most similar Pacemaker
 980  *        return code
 981  *
 982  * \param[in] gai  getaddrinfo() return code
 983  *
 984  * \return Most similar Pacemaker return code
 985  */
 986 int
 987 pcmk__gaierror2rc(int gai)
     /* [previous][next][first][last][top][bottom][index][help] */
 988 {
 989     switch (gai) {
 990         case 0:
 991             return pcmk_rc_ok;
 992 
 993         case EAI_AGAIN:
 994             return EAGAIN;
 995 
 996         case EAI_BADFLAGS:
 997         case EAI_SERVICE:
 998             return EINVAL;
 999 
1000         case EAI_FAMILY:
1001             return EAFNOSUPPORT;
1002 
1003         case EAI_MEMORY:
1004             return ENOMEM;
1005 
1006         case EAI_NONAME:
1007             return pcmk_rc_node_unknown;
1008 
1009         case EAI_SOCKTYPE:
1010             return ESOCKTNOSUPPORT;
1011 
1012         case EAI_SYSTEM:
1013             return errno;
1014 
1015         default:
1016             return pcmk_rc_ns_resolution;
1017     }
1018 }
1019 
1020 /*!
1021  * \brief Map a bz2 return code to the most similar Pacemaker return code
1022  *
1023  * \param[in] bz2  bz2 return code
1024  *
1025  * \return Most similar Pacemaker return code
1026  */
1027 int
1028 pcmk__bzlib2rc(int bz2)
     /* [previous][next][first][last][top][bottom][index][help] */
1029 {
1030     switch (bz2) {
1031         case BZ_OK:
1032         case BZ_RUN_OK:
1033         case BZ_FLUSH_OK:
1034         case BZ_FINISH_OK:
1035         case BZ_STREAM_END:
1036             return pcmk_rc_ok;
1037 
1038         case BZ_MEM_ERROR:
1039             return ENOMEM;
1040 
1041         case BZ_DATA_ERROR:
1042         case BZ_DATA_ERROR_MAGIC:
1043         case BZ_UNEXPECTED_EOF:
1044             return pcmk_rc_bad_input;
1045 
1046         case BZ_IO_ERROR:
1047             return EIO;
1048 
1049         case BZ_OUTBUFF_FULL:
1050             return EFBIG;
1051 
1052         default:
1053             return pcmk_rc_compression;
1054     }
1055 }
1056 
1057 crm_exit_t
1058 crm_exit(crm_exit_t exit_status)
     /* [previous][next][first][last][top][bottom][index][help] */
1059 {
1060     /* A compiler could theoretically use any type for crm_exit_t, but an int
1061      * should always hold it, so cast to int to keep static analysis happy.
1062      */
1063     if ((((int) exit_status) < 0) || (((int) exit_status) > CRM_EX_MAX)) {
1064         exit_status = CRM_EX_ERROR;
1065     }
1066 
1067     crm_info("Exiting %s " QB_XS " with status %d (%s: %s)",
1068              pcmk__s(crm_system_name, "process"), exit_status,
1069              crm_exit_name(exit_status), crm_exit_str(exit_status));
1070     pcmk_common_cleanup();
1071     exit(exit_status);
1072 }
1073 
1074 /*
1075  * External action results
1076  */
1077 
1078 /*!
1079  * \internal
1080  * \brief Set the result of an action
1081  *
1082  * \param[out] result        Where to set action result
1083  * \param[in]  exit_status   OCF exit status to set
1084  * \param[in]  exec_status   Execution status to set
1085  * \param[in]  exit_reason   Human-friendly description of event to set
1086  */
1087 void
1088 pcmk__set_result(pcmk__action_result_t *result, int exit_status,
     /* [previous][next][first][last][top][bottom][index][help] */
1089                  enum pcmk_exec_status exec_status, const char *exit_reason)
1090 {
1091     if (result == NULL) {
1092         return;
1093     }
1094 
1095     result->exit_status = exit_status;
1096     result->execution_status = exec_status;
1097 
1098     if (!pcmk__str_eq(result->exit_reason, exit_reason, pcmk__str_none)) {
1099         free(result->exit_reason);
1100         result->exit_reason = (exit_reason == NULL)? NULL : strdup(exit_reason);
1101     }
1102 }
1103 
1104 
1105 /*!
1106  * \internal
1107  * \brief Set the result of an action, with a formatted exit reason
1108  *
1109  * \param[out] result        Where to set action result
1110  * \param[in]  exit_status   OCF exit status to set
1111  * \param[in]  exec_status   Execution status to set
1112  * \param[in]  format        printf-style format for a human-friendly
1113  *                           description of reason for result
1114  * \param[in]  ...           arguments for \p format
1115  */
1116 G_GNUC_PRINTF(4, 5)
     /* [previous][next][first][last][top][bottom][index][help] */
1117 void
1118 pcmk__format_result(pcmk__action_result_t *result, int exit_status,
1119                     enum pcmk_exec_status exec_status,
1120                     const char *format, ...)
1121 {
1122     va_list ap;
1123     int len = 0;
1124     char *reason = NULL;
1125 
1126     if (result == NULL) {
1127         return;
1128     }
1129 
1130     result->exit_status = exit_status;
1131     result->execution_status = exec_status;
1132 
1133     if (format != NULL) {
1134         va_start(ap, format);
1135         len = vasprintf(&reason, format, ap);
1136         pcmk__assert(len > 0);
1137         va_end(ap);
1138     }
1139     free(result->exit_reason);
1140     result->exit_reason = reason;
1141 }
1142 
1143 /*!
1144  * \internal
1145  * \brief Set the output of an action
1146  *
1147  * \param[out] result         Action result to set output for
1148  * \param[in]  out            Action output to set (must be dynamically
1149  *                            allocated)
1150  * \param[in]  err            Action error output to set (must be dynamically
1151  *                            allocated)
1152  *
1153  * \note \p result will take ownership of \p out and \p err, so the caller
1154  *       should not free them.
1155  */
1156 void
1157 pcmk__set_result_output(pcmk__action_result_t *result, char *out, char *err)
     /* [previous][next][first][last][top][bottom][index][help] */
1158 {
1159     if (result == NULL) {
1160         return;
1161     }
1162 
1163     free(result->action_stdout);
1164     result->action_stdout = out;
1165 
1166     free(result->action_stderr);
1167     result->action_stderr = err;
1168 }
1169 
1170 /*!
1171  * \internal
1172  * \brief Clear a result's exit reason, output, and error output
1173  *
1174  * \param[in,out] result  Result to reset
1175  */
1176 void
1177 pcmk__reset_result(pcmk__action_result_t *result)
     /* [previous][next][first][last][top][bottom][index][help] */
1178 {
1179     if (result == NULL) {
1180         return;
1181     }
1182 
1183     free(result->exit_reason);
1184     result->exit_reason = NULL;
1185 
1186     free(result->action_stdout);
1187     result->action_stdout = NULL;
1188 
1189     free(result->action_stderr);
1190     result->action_stderr = NULL;
1191 }
1192 
1193 /*!
1194  * \internal
1195  * \brief Copy the result of an action
1196  *
1197  * \param[in]  src  Result to copy
1198  * \param[out] dst  Where to copy \p src to
1199  */
1200 void
1201 pcmk__copy_result(const pcmk__action_result_t *src, pcmk__action_result_t *dst)
     /* [previous][next][first][last][top][bottom][index][help] */
1202 {
1203     CRM_CHECK((src != NULL) && (dst != NULL), return);
1204     dst->exit_status = src->exit_status;
1205     dst->execution_status = src->execution_status;
1206     dst->exit_reason = pcmk__str_copy(src->exit_reason);
1207     dst->action_stdout = pcmk__str_copy(src->action_stdout);
1208     dst->action_stderr = pcmk__str_copy(src->action_stderr);
1209 }

/* [previous][next][first][last][top][bottom][index][help] */