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-2024 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU Lesser General Public License
   7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #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 };
 430 
 431 /*!
 432  * \internal
 433  * \brief The number of <tt>enum pcmk_rc_e</tt> values, excluding \c pcmk_rc_ok
 434  *
 435  * This constant stores the number of negative standard Pacemaker return codes.
 436  * These represent Pacemaker-custom error codes. The count does not include
 437  * positive system error numbers, nor does it include \c pcmk_rc_ok (success).
 438  */
 439 const size_t pcmk__n_rc = PCMK__NELEM(pcmk__rcs);
 440 
 441 /*!
 442  * \brief Get a return code constant name as a string
 443  *
 444  * \param[in] rc  Integer return code to convert
 445  *
 446  * \return String of constant name corresponding to rc
 447  */
 448 const char *
 449 pcmk_rc_name(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 450 {
 451     if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < pcmk__n_rc)) {
 452         return pcmk__rcs[pcmk_rc_error - rc].name;
 453     }
 454     switch (rc) {
 455         case pcmk_rc_ok:        return "pcmk_rc_ok";
 456         case E2BIG:             return "E2BIG";
 457         case EACCES:            return "EACCES";
 458         case EADDRINUSE:        return "EADDRINUSE";
 459         case EADDRNOTAVAIL:     return "EADDRNOTAVAIL";
 460         case EAFNOSUPPORT:      return "EAFNOSUPPORT";
 461         case EAGAIN:            return "EAGAIN";
 462         case EALREADY:          return "EALREADY";
 463         case EBADF:             return "EBADF";
 464         case EBADMSG:           return "EBADMSG";
 465         case EBUSY:             return "EBUSY";
 466         case ECANCELED:         return "ECANCELED";
 467         case ECHILD:            return "ECHILD";
 468         case ECOMM:             return "ECOMM";
 469         case ECONNABORTED:      return "ECONNABORTED";
 470         case ECONNREFUSED:      return "ECONNREFUSED";
 471         case ECONNRESET:        return "ECONNRESET";
 472         /* case EDEADLK:        return "EDEADLK"; */
 473         case EDESTADDRREQ:      return "EDESTADDRREQ";
 474         case EDOM:              return "EDOM";
 475         case EDQUOT:            return "EDQUOT";
 476         case EEXIST:            return "EEXIST";
 477         case EFAULT:            return "EFAULT";
 478         case EFBIG:             return "EFBIG";
 479         case EHOSTDOWN:         return "EHOSTDOWN";
 480         case EHOSTUNREACH:      return "EHOSTUNREACH";
 481         case EIDRM:             return "EIDRM";
 482         case EILSEQ:            return "EILSEQ";
 483         case EINPROGRESS:       return "EINPROGRESS";
 484         case EINTR:             return "EINTR";
 485         case EINVAL:            return "EINVAL";
 486         case EIO:               return "EIO";
 487         case EISCONN:           return "EISCONN";
 488         case EISDIR:            return "EISDIR";
 489         case ELIBACC:           return "ELIBACC";
 490         case ELOOP:             return "ELOOP";
 491         case EMFILE:            return "EMFILE";
 492         case EMLINK:            return "EMLINK";
 493         case EMSGSIZE:          return "EMSGSIZE";
 494 #ifdef EMULTIHOP // Not available on OpenBSD
 495         case EMULTIHOP:         return "EMULTIHOP";
 496 #endif
 497         case ENAMETOOLONG:      return "ENAMETOOLONG";
 498         case ENETDOWN:          return "ENETDOWN";
 499         case ENETRESET:         return "ENETRESET";
 500         case ENETUNREACH:       return "ENETUNREACH";
 501         case ENFILE:            return "ENFILE";
 502         case ENOBUFS:           return "ENOBUFS";
 503         case ENODATA:           return "ENODATA";
 504         case ENODEV:            return "ENODEV";
 505         case ENOENT:            return "ENOENT";
 506         case ENOEXEC:           return "ENOEXEC";
 507         case ENOKEY:            return "ENOKEY";
 508         case ENOLCK:            return "ENOLCK";
 509 #ifdef ENOLINK // Not available on OpenBSD
 510         case ENOLINK:           return "ENOLINK";
 511 #endif
 512         case ENOMEM:            return "ENOMEM";
 513         case ENOMSG:            return "ENOMSG";
 514         case ENOPROTOOPT:       return "ENOPROTOOPT";
 515         case ENOSPC:            return "ENOSPC";
 516 #ifdef ENOSR
 517         case ENOSR:             return "ENOSR";
 518 #endif
 519 #ifdef ENOSTR
 520         case ENOSTR:            return "ENOSTR";
 521 #endif
 522         case ENOSYS:            return "ENOSYS";
 523         case ENOTBLK:           return "ENOTBLK";
 524         case ENOTCONN:          return "ENOTCONN";
 525         case ENOTDIR:           return "ENOTDIR";
 526         case ENOTEMPTY:         return "ENOTEMPTY";
 527         case ENOTSOCK:          return "ENOTSOCK";
 528 #if ENOTSUP != EOPNOTSUPP
 529         case ENOTSUP:           return "ENOTSUP";
 530 #endif
 531         case ENOTTY:            return "ENOTTY";
 532         case ENOTUNIQ:          return "ENOTUNIQ";
 533         case ENXIO:             return "ENXIO";
 534         case EOPNOTSUPP:        return "EOPNOTSUPP";
 535         case EOVERFLOW:         return "EOVERFLOW";
 536         case EPERM:             return "EPERM";
 537         case EPFNOSUPPORT:      return "EPFNOSUPPORT";
 538         case EPIPE:             return "EPIPE";
 539         case EPROTO:            return "EPROTO";
 540         case EPROTONOSUPPORT:   return "EPROTONOSUPPORT";
 541         case EPROTOTYPE:        return "EPROTOTYPE";
 542         case ERANGE:            return "ERANGE";
 543         case EREMOTE:           return "EREMOTE";
 544         case EREMOTEIO:         return "EREMOTEIO";
 545         case EROFS:             return "EROFS";
 546         case ESHUTDOWN:         return "ESHUTDOWN";
 547         case ESPIPE:            return "ESPIPE";
 548         case ESOCKTNOSUPPORT:   return "ESOCKTNOSUPPORT";
 549         case ESRCH:             return "ESRCH";
 550         case ESTALE:            return "ESTALE";
 551         case ETIME:             return "ETIME";
 552         case ETIMEDOUT:         return "ETIMEDOUT";
 553         case ETXTBSY:           return "ETXTBSY";
 554 #ifdef EUNATCH
 555         case EUNATCH:           return "EUNATCH";
 556 #endif
 557         case EUSERS:            return "EUSERS";
 558         /* case EWOULDBLOCK:    return "EWOULDBLOCK"; */
 559         case EXDEV:             return "EXDEV";
 560 
 561 #ifdef EBADE // Not available on OS X
 562         case EBADE:             return "EBADE";
 563         case EBADFD:            return "EBADFD";
 564         case EBADSLT:           return "EBADSLT";
 565         case EDEADLOCK:         return "EDEADLOCK";
 566         case EBADR:             return "EBADR";
 567         case EBADRQC:           return "EBADRQC";
 568         case ECHRNG:            return "ECHRNG";
 569 #ifdef EISNAM // Not available on OS X, Illumos, Solaris
 570         case EISNAM:            return "EISNAM";
 571         case EKEYEXPIRED:       return "EKEYEXPIRED";
 572         case EKEYREVOKED:       return "EKEYREVOKED";
 573 #endif
 574         case EKEYREJECTED:      return "EKEYREJECTED";
 575         case EL2HLT:            return "EL2HLT";
 576         case EL2NSYNC:          return "EL2NSYNC";
 577         case EL3HLT:            return "EL3HLT";
 578         case EL3RST:            return "EL3RST";
 579         case ELIBBAD:           return "ELIBBAD";
 580         case ELIBMAX:           return "ELIBMAX";
 581         case ELIBSCN:           return "ELIBSCN";
 582         case ELIBEXEC:          return "ELIBEXEC";
 583 #ifdef ENOMEDIUM // Not available on OS X, Illumos, Solaris
 584         case ENOMEDIUM:         return "ENOMEDIUM";
 585         case EMEDIUMTYPE:       return "EMEDIUMTYPE";
 586 #endif
 587         case ENONET:            return "ENONET";
 588         case ENOPKG:            return "ENOPKG";
 589         case EREMCHG:           return "EREMCHG";
 590         case ERESTART:          return "ERESTART";
 591         case ESTRPIPE:          return "ESTRPIPE";
 592 #ifdef EUCLEAN // Not available on OS X, Illumos, Solaris
 593         case EUCLEAN:           return "EUCLEAN";
 594 #endif
 595         case EXFULL:            return "EXFULL";
 596 #endif // EBADE
 597         default:                return "Unknown";
 598     }
 599 }
 600 
 601 /*!
 602  * \brief Get a user-friendly description of a return code
 603  *
 604  * \param[in] rc  Integer return code to convert
 605  *
 606  * \return String description of rc
 607  */
 608 const char *
 609 pcmk_rc_str(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 610 {
 611     if (rc == pcmk_rc_ok) {
 612         return "OK";
 613     }
 614     if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < pcmk__n_rc)) {
 615         return pcmk__rcs[pcmk_rc_error - rc].desc;
 616     }
 617     if (rc < 0) {
 618         return "Error";
 619     }
 620 
 621     // Handle values that could be defined by system or by portability.h
 622     switch (rc) {
 623 #ifdef PCMK__ENOTUNIQ
 624         case ENOTUNIQ:      return "Name not unique on network";
 625 #endif
 626 #ifdef PCMK__ECOMM
 627         case ECOMM:         return "Communication error on send";
 628 #endif
 629 #ifdef PCMK__ELIBACC
 630         case ELIBACC:       return "Can not access a needed shared library";
 631 #endif
 632 #ifdef PCMK__EREMOTEIO
 633         case EREMOTEIO:     return "Remote I/O error";
 634 #endif
 635 #ifdef PCMK__ENOKEY
 636         case ENOKEY:        return "Required key not available";
 637 #endif
 638 #ifdef PCMK__ENODATA
 639         case ENODATA:       return "No data available";
 640 #endif
 641 #ifdef PCMK__ETIME
 642         case ETIME:         return "Timer expired";
 643 #endif
 644 #ifdef PCMK__EKEYREJECTED
 645         case EKEYREJECTED:  return "Key was rejected by service";
 646 #endif
 647         default:            return strerror(rc);
 648     }
 649 }
 650 
 651 // This returns negative values for errors
 652 //! \deprecated Use standard return codes instead
 653 int
 654 pcmk_rc2legacy(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 655 {
 656     if (rc >= 0) {
 657         return -rc; // OK or system errno
 658     }
 659     if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < pcmk__n_rc)) {
 660         return pcmk__rcs[pcmk_rc_error - rc].legacy_rc;
 661     }
 662     return -pcmk_err_generic;
 663 }
 664 
 665 //! \deprecated Use standard return codes instead
 666 int
 667 pcmk_legacy2rc(int legacy_rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 668 {
 669     legacy_rc = abs(legacy_rc);
 670     switch (legacy_rc) {
 671         case pcmk_err_no_quorum:            return pcmk_rc_no_quorum;
 672         case pcmk_err_schema_validation:    return pcmk_rc_schema_validation;
 673         case pcmk_err_schema_unchanged:     return pcmk_rc_schema_unchanged;
 674         case pcmk_err_transform_failed:     return pcmk_rc_transform_failed;
 675         case pcmk_err_old_data:             return pcmk_rc_old_data;
 676         case pcmk_err_diff_failed:          return pcmk_rc_diff_failed;
 677         case pcmk_err_diff_resync:          return pcmk_rc_diff_resync;
 678         case pcmk_err_cib_modified:         return pcmk_rc_cib_modified;
 679         case pcmk_err_cib_backup:           return pcmk_rc_cib_backup;
 680         case pcmk_err_cib_save:             return pcmk_rc_cib_save;
 681         case pcmk_err_cib_corrupt:          return pcmk_rc_cib_corrupt;
 682         case pcmk_err_multiple:             return pcmk_rc_multiple;
 683         case pcmk_err_node_unknown:         return pcmk_rc_node_unknown;
 684         case pcmk_err_already:              return pcmk_rc_already;
 685         case pcmk_err_bad_nvpair:           return pcmk_rc_bad_nvpair;
 686         case pcmk_err_unknown_format:       return pcmk_rc_unknown_format;
 687         case pcmk_err_generic:              return pcmk_rc_error;
 688         case pcmk_ok:                       return pcmk_rc_ok;
 689         default:                            return legacy_rc; // system errno
 690     }
 691 }
 692 
 693 // Exit status codes
 694 
 695 const char *
 696 crm_exit_name(crm_exit_t exit_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 697 {
 698     switch (exit_code) {
 699         case CRM_EX_OK: return "CRM_EX_OK";
 700         case CRM_EX_ERROR: return "CRM_EX_ERROR";
 701         case CRM_EX_INVALID_PARAM: return "CRM_EX_INVALID_PARAM";
 702         case CRM_EX_UNIMPLEMENT_FEATURE: return "CRM_EX_UNIMPLEMENT_FEATURE";
 703         case CRM_EX_INSUFFICIENT_PRIV: return "CRM_EX_INSUFFICIENT_PRIV";
 704         case CRM_EX_NOT_INSTALLED: return "CRM_EX_NOT_INSTALLED";
 705         case CRM_EX_NOT_CONFIGURED: return "CRM_EX_NOT_CONFIGURED";
 706         case CRM_EX_NOT_RUNNING: return "CRM_EX_NOT_RUNNING";
 707         case CRM_EX_PROMOTED: return "CRM_EX_PROMOTED";
 708         case CRM_EX_FAILED_PROMOTED: return "CRM_EX_FAILED_PROMOTED";
 709         case CRM_EX_USAGE: return "CRM_EX_USAGE";
 710         case CRM_EX_DATAERR: return "CRM_EX_DATAERR";
 711         case CRM_EX_NOINPUT: return "CRM_EX_NOINPUT";
 712         case CRM_EX_NOUSER: return "CRM_EX_NOUSER";
 713         case CRM_EX_NOHOST: return "CRM_EX_NOHOST";
 714         case CRM_EX_UNAVAILABLE: return "CRM_EX_UNAVAILABLE";
 715         case CRM_EX_SOFTWARE: return "CRM_EX_SOFTWARE";
 716         case CRM_EX_OSERR: return "CRM_EX_OSERR";
 717         case CRM_EX_OSFILE: return "CRM_EX_OSFILE";
 718         case CRM_EX_CANTCREAT: return "CRM_EX_CANTCREAT";
 719         case CRM_EX_IOERR: return "CRM_EX_IOERR";
 720         case CRM_EX_TEMPFAIL: return "CRM_EX_TEMPFAIL";
 721         case CRM_EX_PROTOCOL: return "CRM_EX_PROTOCOL";
 722         case CRM_EX_NOPERM: return "CRM_EX_NOPERM";
 723         case CRM_EX_CONFIG: return "CRM_EX_CONFIG";
 724         case CRM_EX_FATAL: return "CRM_EX_FATAL";
 725         case CRM_EX_PANIC: return "CRM_EX_PANIC";
 726         case CRM_EX_DISCONNECT: return "CRM_EX_DISCONNECT";
 727         case CRM_EX_DIGEST: return "CRM_EX_DIGEST";
 728         case CRM_EX_NOSUCH: return "CRM_EX_NOSUCH";
 729         case CRM_EX_QUORUM: return "CRM_EX_QUORUM";
 730         case CRM_EX_UNSAFE: return "CRM_EX_UNSAFE";
 731         case CRM_EX_EXISTS: return "CRM_EX_EXISTS";
 732         case CRM_EX_MULTIPLE: return "CRM_EX_MULTIPLE";
 733         case CRM_EX_EXPIRED: return "CRM_EX_EXPIRED";
 734         case CRM_EX_NOT_YET_IN_EFFECT: return "CRM_EX_NOT_YET_IN_EFFECT";
 735         case CRM_EX_INDETERMINATE: return "CRM_EX_INDETERMINATE";
 736         case CRM_EX_UNSATISFIED: return "CRM_EX_UNSATISFIED";
 737         case CRM_EX_OLD: return "CRM_EX_OLD";
 738         case CRM_EX_TIMEOUT: return "CRM_EX_TIMEOUT";
 739         case CRM_EX_DEGRADED: return "CRM_EX_DEGRADED";
 740         case CRM_EX_DEGRADED_PROMOTED: return "CRM_EX_DEGRADED_PROMOTED";
 741         case CRM_EX_NONE: return "CRM_EX_NONE";
 742         case CRM_EX_MAX: return "CRM_EX_UNKNOWN";
 743     }
 744     return "CRM_EX_UNKNOWN";
 745 }
 746 
 747 const char *
 748 crm_exit_str(crm_exit_t exit_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 749 {
 750     switch (exit_code) {
 751         case CRM_EX_OK: return "OK";
 752         case CRM_EX_ERROR: return "Error occurred";
 753         case CRM_EX_INVALID_PARAM: return "Invalid parameter";
 754         case CRM_EX_UNIMPLEMENT_FEATURE: return "Unimplemented";
 755         case CRM_EX_INSUFFICIENT_PRIV: return "Insufficient privileges";
 756         case CRM_EX_NOT_INSTALLED: return "Not installed";
 757         case CRM_EX_NOT_CONFIGURED: return "Not configured";
 758         case CRM_EX_NOT_RUNNING: return "Not running";
 759         case CRM_EX_PROMOTED: return "Promoted";
 760         case CRM_EX_FAILED_PROMOTED: return "Failed in promoted role";
 761         case CRM_EX_USAGE: return "Incorrect usage";
 762         case CRM_EX_DATAERR: return "Invalid data given";
 763         case CRM_EX_NOINPUT: return "Input file not available";
 764         case CRM_EX_NOUSER: return "User does not exist";
 765         case CRM_EX_NOHOST: return "Host does not exist";
 766         case CRM_EX_UNAVAILABLE: return "Necessary service unavailable";
 767         case CRM_EX_SOFTWARE: return "Internal software bug";
 768         case CRM_EX_OSERR: return "Operating system error occurred";
 769         case CRM_EX_OSFILE: return "System file not available";
 770         case CRM_EX_CANTCREAT: return "Cannot create output file";
 771         case CRM_EX_IOERR: return "I/O error occurred";
 772         case CRM_EX_TEMPFAIL: return "Temporary failure, try again";
 773         case CRM_EX_PROTOCOL: return "Protocol violated";
 774         case CRM_EX_NOPERM: return "Insufficient privileges";
 775         case CRM_EX_CONFIG: return "Invalid configuration";
 776         case CRM_EX_FATAL: return "Fatal error occurred, will not respawn";
 777         case CRM_EX_PANIC: return "System panic required";
 778         case CRM_EX_DISCONNECT: return "Not connected";
 779         case CRM_EX_DIGEST: return "Digest mismatch";
 780         case CRM_EX_NOSUCH: return "No such object";
 781         case CRM_EX_QUORUM: return "Quorum required";
 782         case CRM_EX_UNSAFE: return "Operation not safe";
 783         case CRM_EX_EXISTS: return "Requested item already exists";
 784         case CRM_EX_MULTIPLE: return "Multiple items match request";
 785         case CRM_EX_EXPIRED: return "Requested item has expired";
 786         case CRM_EX_NOT_YET_IN_EFFECT: return "Requested item is not yet in effect";
 787         case CRM_EX_INDETERMINATE: return "Could not determine status";
 788         case CRM_EX_UNSATISFIED: return "Not applicable under current conditions";
 789         case CRM_EX_OLD: return "Update was older than existing configuration";
 790         case CRM_EX_TIMEOUT: return "Timeout occurred";
 791         case CRM_EX_DEGRADED: return "Service is active but might fail soon";
 792         case CRM_EX_DEGRADED_PROMOTED: return "Service is promoted but might fail soon";
 793         case CRM_EX_NONE: return "No exit status available";
 794         case CRM_EX_MAX: return "Error occurred";
 795     }
 796     if ((exit_code > 128) && (exit_code < CRM_EX_MAX)) {
 797         return "Interrupted by signal";
 798     }
 799     return "Unknown exit status";
 800 }
 801 
 802 /*!
 803  * \brief Map a function return code to the most similar exit code
 804  *
 805  * \param[in] rc  Function return code
 806  *
 807  * \return Most similar exit code
 808  */
 809 crm_exit_t
 810 pcmk_rc2exitc(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 811 {
 812     switch (rc) {
 813         case pcmk_rc_ok:
 814         case pcmk_rc_no_output: // quiet mode, or nothing to output
 815             return CRM_EX_OK;
 816 
 817         case pcmk_rc_no_quorum:
 818             return CRM_EX_QUORUM;
 819 
 820         case pcmk_rc_old_data:
 821             return CRM_EX_OLD;
 822 
 823         case pcmk_rc_schema_validation:
 824         case pcmk_rc_transform_failed:
 825         case pcmk_rc_unpack_error:
 826             return CRM_EX_CONFIG;
 827 
 828         case pcmk_rc_bad_nvpair:
 829             return CRM_EX_INVALID_PARAM;
 830 
 831         case EACCES:
 832             return CRM_EX_INSUFFICIENT_PRIV;
 833 
 834         case EBADF:
 835         case EINVAL:
 836         case EFAULT:
 837         case ENOSYS:
 838         case EOVERFLOW:
 839         case pcmk_rc_underflow:
 840         case pcmk_rc_compression:
 841             return CRM_EX_SOFTWARE;
 842 
 843         case EBADMSG:
 844         case EMSGSIZE:
 845         case ENOMSG:
 846         case ENOPROTOOPT:
 847         case EPROTO:
 848         case EPROTONOSUPPORT:
 849         case EPROTOTYPE:
 850             return CRM_EX_PROTOCOL;
 851 
 852         case ECOMM:
 853         case ENOMEM:
 854             return CRM_EX_OSERR;
 855 
 856         case ECONNABORTED:
 857         case ECONNREFUSED:
 858         case ECONNRESET:
 859         case ENOTCONN:
 860             return CRM_EX_DISCONNECT;
 861 
 862         case EEXIST:
 863         case pcmk_rc_already:
 864             return CRM_EX_EXISTS;
 865 
 866         case EIO:
 867         case pcmk_rc_dot_error:
 868         case pcmk_rc_graph_error:
 869             return CRM_EX_IOERR;
 870 
 871         case ENOTSUP:
 872 #if EOPNOTSUPP != ENOTSUP
 873         case EOPNOTSUPP:
 874 #endif
 875             return CRM_EX_UNIMPLEMENT_FEATURE;
 876 
 877         case ENOTUNIQ:
 878         case pcmk_rc_multiple:
 879             return CRM_EX_MULTIPLE;
 880 
 881         case ENODEV:
 882         case ENOENT:
 883         case ENXIO:
 884         case pcmk_rc_no_transaction:
 885         case pcmk_rc_unknown_format:
 886             return CRM_EX_NOSUCH;
 887 
 888         case pcmk_rc_node_unknown:
 889         case pcmk_rc_ns_resolution:
 890             return CRM_EX_NOHOST;
 891 
 892         case ETIME:
 893         case ETIMEDOUT:
 894             return CRM_EX_TIMEOUT;
 895 
 896         case EAGAIN:
 897         case EBUSY:
 898             return CRM_EX_UNSATISFIED;
 899 
 900         case pcmk_rc_before_range:
 901             return CRM_EX_NOT_YET_IN_EFFECT;
 902 
 903         case pcmk_rc_after_range:
 904             return CRM_EX_EXPIRED;
 905 
 906         case pcmk_rc_undetermined:
 907             return CRM_EX_INDETERMINATE;
 908 
 909         case pcmk_rc_op_unsatisfied:
 910             return CRM_EX_UNSATISFIED;
 911 
 912         case pcmk_rc_within_range:
 913             return CRM_EX_OK;
 914 
 915         case pcmk_rc_no_input:
 916             return CRM_EX_NOINPUT;
 917 
 918         case pcmk_rc_duplicate_id:
 919             return CRM_EX_MULTIPLE;
 920 
 921         case pcmk_rc_bad_input:
 922         case pcmk_rc_bad_xml_patch:
 923             return CRM_EX_DATAERR;
 924 
 925         default:
 926             return CRM_EX_ERROR;
 927     }
 928 }
 929 
 930 /*!
 931  * \brief Map a function return code to the most similar OCF exit code
 932  *
 933  * \param[in] rc  Function return code
 934  *
 935  * \return Most similar OCF exit code
 936  */
 937 enum ocf_exitcode
 938 pcmk_rc2ocf(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 939 {
 940     switch (rc) {
 941         case pcmk_rc_ok:
 942             return PCMK_OCF_OK;
 943 
 944         case pcmk_rc_bad_nvpair:
 945             return PCMK_OCF_INVALID_PARAM;
 946 
 947         case EACCES:
 948             return PCMK_OCF_INSUFFICIENT_PRIV;
 949 
 950         case ENOTSUP:
 951 #if EOPNOTSUPP != ENOTSUP
 952         case EOPNOTSUPP:
 953 #endif
 954             return PCMK_OCF_UNIMPLEMENT_FEATURE;
 955 
 956         default:
 957             return PCMK_OCF_UNKNOWN_ERROR;
 958     }
 959 }
 960 
 961 
 962 // Other functions
 963 
 964 /*!
 965  * \brief Map a getaddrinfo() return code to the most similar Pacemaker
 966  *        return code
 967  *
 968  * \param[in] gai  getaddrinfo() return code
 969  *
 970  * \return Most similar Pacemaker return code
 971  */
 972 int
 973 pcmk__gaierror2rc(int gai)
     /* [previous][next][first][last][top][bottom][index][help] */
 974 {
 975     switch (gai) {
 976         case 0:
 977             return pcmk_rc_ok;
 978 
 979         case EAI_AGAIN:
 980             return EAGAIN;
 981 
 982         case EAI_BADFLAGS:
 983         case EAI_SERVICE:
 984             return EINVAL;
 985 
 986         case EAI_FAMILY:
 987             return EAFNOSUPPORT;
 988 
 989         case EAI_MEMORY:
 990             return ENOMEM;
 991 
 992         case EAI_NONAME:
 993             return pcmk_rc_node_unknown;
 994 
 995         case EAI_SOCKTYPE:
 996             return ESOCKTNOSUPPORT;
 997 
 998         case EAI_SYSTEM:
 999             return errno;
1000 
1001         default:
1002             return pcmk_rc_ns_resolution;
1003     }
1004 }
1005 
1006 /*!
1007  * \brief Map a bz2 return code to the most similar Pacemaker return code
1008  *
1009  * \param[in] bz2  bz2 return code
1010  *
1011  * \return Most similar Pacemaker return code
1012  */
1013 int
1014 pcmk__bzlib2rc(int bz2)
     /* [previous][next][first][last][top][bottom][index][help] */
1015 {
1016     switch (bz2) {
1017         case BZ_OK:
1018         case BZ_RUN_OK:
1019         case BZ_FLUSH_OK:
1020         case BZ_FINISH_OK:
1021         case BZ_STREAM_END:
1022             return pcmk_rc_ok;
1023 
1024         case BZ_MEM_ERROR:
1025             return ENOMEM;
1026 
1027         case BZ_DATA_ERROR:
1028         case BZ_DATA_ERROR_MAGIC:
1029         case BZ_UNEXPECTED_EOF:
1030             return pcmk_rc_bad_input;
1031 
1032         case BZ_IO_ERROR:
1033             return EIO;
1034 
1035         case BZ_OUTBUFF_FULL:
1036             return EFBIG;
1037 
1038         default:
1039             return pcmk_rc_compression;
1040     }
1041 }
1042 
1043 crm_exit_t
1044 crm_exit(crm_exit_t exit_status)
     /* [previous][next][first][last][top][bottom][index][help] */
1045 {
1046     /* A compiler could theoretically use any type for crm_exit_t, but an int
1047      * should always hold it, so cast to int to keep static analysis happy.
1048      */
1049     if ((((int) exit_status) < 0) || (((int) exit_status) > CRM_EX_MAX)) {
1050         exit_status = CRM_EX_ERROR;
1051     }
1052 
1053     crm_info("Exiting %s " QB_XS " with status %d (%s: %s)",
1054              pcmk__s(crm_system_name, "process"), exit_status,
1055              crm_exit_name(exit_status), crm_exit_str(exit_status));
1056     pcmk_common_cleanup();
1057     exit(exit_status);
1058 }
1059 
1060 /*
1061  * External action results
1062  */
1063 
1064 /*!
1065  * \internal
1066  * \brief Set the result of an action
1067  *
1068  * \param[out] result        Where to set action result
1069  * \param[in]  exit_status   OCF exit status to set
1070  * \param[in]  exec_status   Execution status to set
1071  * \param[in]  exit_reason   Human-friendly description of event to set
1072  */
1073 void
1074 pcmk__set_result(pcmk__action_result_t *result, int exit_status,
     /* [previous][next][first][last][top][bottom][index][help] */
1075                  enum pcmk_exec_status exec_status, const char *exit_reason)
1076 {
1077     if (result == NULL) {
1078         return;
1079     }
1080 
1081     result->exit_status = exit_status;
1082     result->execution_status = exec_status;
1083 
1084     if (!pcmk__str_eq(result->exit_reason, exit_reason, pcmk__str_none)) {
1085         free(result->exit_reason);
1086         result->exit_reason = (exit_reason == NULL)? NULL : strdup(exit_reason);
1087     }
1088 }
1089 
1090 
1091 /*!
1092  * \internal
1093  * \brief Set the result of an action, with a formatted exit reason
1094  *
1095  * \param[out] result        Where to set action result
1096  * \param[in]  exit_status   OCF exit status to set
1097  * \param[in]  exec_status   Execution status to set
1098  * \param[in]  format        printf-style format for a human-friendly
1099  *                           description of reason for result
1100  * \param[in]  ...           arguments for \p format
1101  */
1102 G_GNUC_PRINTF(4, 5)
     /* [previous][next][first][last][top][bottom][index][help] */
1103 void
1104 pcmk__format_result(pcmk__action_result_t *result, int exit_status,
1105                     enum pcmk_exec_status exec_status,
1106                     const char *format, ...)
1107 {
1108     va_list ap;
1109     int len = 0;
1110     char *reason = NULL;
1111 
1112     if (result == NULL) {
1113         return;
1114     }
1115 
1116     result->exit_status = exit_status;
1117     result->execution_status = exec_status;
1118 
1119     if (format != NULL) {
1120         va_start(ap, format);
1121         len = vasprintf(&reason, format, ap);
1122         pcmk__assert(len > 0);
1123         va_end(ap);
1124     }
1125     free(result->exit_reason);
1126     result->exit_reason = reason;
1127 }
1128 
1129 /*!
1130  * \internal
1131  * \brief Set the output of an action
1132  *
1133  * \param[out] result         Action result to set output for
1134  * \param[in]  out            Action output to set (must be dynamically
1135  *                            allocated)
1136  * \param[in]  err            Action error output to set (must be dynamically
1137  *                            allocated)
1138  *
1139  * \note \p result will take ownership of \p out and \p err, so the caller
1140  *       should not free them.
1141  */
1142 void
1143 pcmk__set_result_output(pcmk__action_result_t *result, char *out, char *err)
     /* [previous][next][first][last][top][bottom][index][help] */
1144 {
1145     if (result == NULL) {
1146         return;
1147     }
1148 
1149     free(result->action_stdout);
1150     result->action_stdout = out;
1151 
1152     free(result->action_stderr);
1153     result->action_stderr = err;
1154 }
1155 
1156 /*!
1157  * \internal
1158  * \brief Clear a result's exit reason, output, and error output
1159  *
1160  * \param[in,out] result  Result to reset
1161  */
1162 void
1163 pcmk__reset_result(pcmk__action_result_t *result)
     /* [previous][next][first][last][top][bottom][index][help] */
1164 {
1165     if (result == NULL) {
1166         return;
1167     }
1168 
1169     free(result->exit_reason);
1170     result->exit_reason = NULL;
1171 
1172     free(result->action_stdout);
1173     result->action_stdout = NULL;
1174 
1175     free(result->action_stderr);
1176     result->action_stderr = NULL;
1177 }
1178 
1179 /*!
1180  * \internal
1181  * \brief Copy the result of an action
1182  *
1183  * \param[in]  src  Result to copy
1184  * \param[out] dst  Where to copy \p src to
1185  */
1186 void
1187 pcmk__copy_result(const pcmk__action_result_t *src, pcmk__action_result_t *dst)
     /* [previous][next][first][last][top][bottom][index][help] */
1188 {
1189     CRM_CHECK((src != NULL) && (dst != NULL), return);
1190     dst->exit_status = src->exit_status;
1191     dst->execution_status = src->execution_status;
1192     dst->exit_reason = pcmk__str_copy(src->exit_reason);
1193     dst->action_stdout = pcmk__str_copy(src->action_stdout);
1194     dst->action_stderr = pcmk__str_copy(src->action_stderr);
1195 }

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