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

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