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. pcmk_errorname
  4. pcmk_strerror
  5. pcmk_rc_name
  6. pcmk_rc_str
  7. pcmk_rc2legacy
  8. pcmk_legacy2rc
  9. crm_exit_name
  10. crm_exit_str
  11. pcmk_rc2exitc
  12. pcmk_rc2ocf
  13. pcmk__gaierror2rc
  14. pcmk__bzlib2rc
  15. crm_exit
  16. pcmk__set_result
  17. G_GNUC_PRINTF
  18. pcmk__set_result_output
  19. pcmk__reset_result
  20. pcmk__copy_result
  21. log_assertion_as
  22. pcmk__abort_as
  23. fail_assert_as
  24. crm_abort
  25. bz2_strerror
  26. crm_errno2exit

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

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