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_strerror
  3. pcmk_rc_name
  4. pcmk_rc_str
  5. pcmk_rc2legacy
  6. pcmk_legacy2rc
  7. crm_exit_name
  8. crm_exit_str
  9. crm_errno2exit
  10. pcmk_rc2exitc
  11. pcmk_rc2ocf
  12. bz2_strerror
  13. crm_exit
  14. pcmk__set_result
  15. pcmk__set_result_output
  16. pcmk__reset_result

   1 /*
   2  * Copyright 2004-2021 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 <stdlib.h>
  19 #include <string.h>
  20 #include <qb/qbdefs.h>
  21 
  22 #include <crm/common/mainloop.h>
  23 #include <crm/common/xml.h>
  24 
  25 G_DEFINE_QUARK(pcmk-rc-error-quark, pcmk__rc_error)
     /* [previous][next][first][last][top][bottom][index][help] */
  26 G_DEFINE_QUARK(pcmk-exitc-error-quark, pcmk__exitc_error)
  27 
  28 // @COMPAT Legacy function return codes
  29 
  30 //! \deprecated Use standard return codes and pcmk_rc_name() instead
  31 const char *
  32 pcmk_errorname(int rc)
  33 {
  34     rc = abs(rc);
  35     switch (rc) {
  36         case pcmk_err_generic: return "pcmk_err_generic";
  37         case pcmk_err_no_quorum: return "pcmk_err_no_quorum";
  38         case pcmk_err_schema_validation: return "pcmk_err_schema_validation";
  39         case pcmk_err_transform_failed: return "pcmk_err_transform_failed";
  40         case pcmk_err_old_data: return "pcmk_err_old_data";
  41         case pcmk_err_diff_failed: return "pcmk_err_diff_failed";
  42         case pcmk_err_diff_resync: return "pcmk_err_diff_resync";
  43         case pcmk_err_cib_modified: return "pcmk_err_cib_modified";
  44         case pcmk_err_cib_backup: return "pcmk_err_cib_backup";
  45         case pcmk_err_cib_save: return "pcmk_err_cib_save";
  46         case pcmk_err_cib_corrupt: return "pcmk_err_cib_corrupt";
  47         case pcmk_err_multiple: return "pcmk_err_multiple";
  48         case pcmk_err_node_unknown: return "pcmk_err_node_unknown";
  49         case pcmk_err_already: return "pcmk_err_already";
  50         case pcmk_err_bad_nvpair: return "pcmk_err_bad_nvpair";
  51         case pcmk_err_unknown_format: return "pcmk_err_unknown_format";
  52         default: return pcmk_rc_name(rc); // system errno
  53     }
  54 }
  55 
  56 //! \deprecated Use standard return codes and pcmk_rc_str() instead
  57 const char *
  58 pcmk_strerror(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60     if (rc == 0) {
  61         return "OK";
  62     }
  63 
  64     rc = abs(rc);
  65 
  66     // Of course rc > 0 ... unless someone passed INT_MIN as rc
  67     if ((rc > 0) && (rc < PCMK_ERROR_OFFSET)) {
  68         return strerror(rc);
  69     }
  70 
  71     switch (rc) {
  72         case pcmk_err_generic:
  73             return "Generic Pacemaker error";
  74         case pcmk_err_no_quorum:
  75             return "Operation requires quorum";
  76         case pcmk_err_schema_validation:
  77             return "Update does not conform to the configured schema";
  78         case pcmk_err_transform_failed:
  79             return "Schema transform failed";
  80         case pcmk_err_old_data:
  81             return "Update was older than existing configuration";
  82         case pcmk_err_diff_failed:
  83             return "Application of an update diff failed";
  84         case pcmk_err_diff_resync:
  85             return "Application of an update diff failed, requesting a full refresh";
  86         case pcmk_err_cib_modified:
  87             return "The on-disk configuration was manually modified";
  88         case pcmk_err_cib_backup:
  89             return "Could not archive the previous configuration";
  90         case pcmk_err_cib_save:
  91             return "Could not save the new configuration to disk";
  92         case pcmk_err_cib_corrupt:
  93             return "Could not parse on-disk configuration";
  94         case pcmk_err_multiple:
  95             return "Resource active on multiple nodes";
  96         case pcmk_err_node_unknown:
  97             return "Node not found";
  98         case pcmk_err_already:
  99             return "Situation already as requested";
 100         case pcmk_err_bad_nvpair:
 101             return "Bad name/value pair given";
 102         case pcmk_err_schema_unchanged:
 103             return "Schema is already the latest available";
 104         case pcmk_err_unknown_format:
 105             return "Unknown output format";
 106 
 107             /* The following cases will only be hit on systems for which they are non-standard */
 108             /* coverity[dead_error_condition] False positive on non-Linux */
 109         case ENOTUNIQ:
 110             return "Name not unique on network";
 111             /* coverity[dead_error_condition] False positive on non-Linux */
 112         case ECOMM:
 113             return "Communication error on send";
 114             /* coverity[dead_error_condition] False positive on non-Linux */
 115         case ELIBACC:
 116             return "Can not access a needed shared library";
 117             /* coverity[dead_error_condition] False positive on non-Linux */
 118         case EREMOTEIO:
 119             return "Remote I/O error";
 120             /* coverity[dead_error_condition] False positive on non-Linux */
 121         case EUNATCH:
 122             return "Protocol driver not attached";
 123             /* coverity[dead_error_condition] False positive on non-Linux */
 124         case ENOKEY:
 125             return "Required key not available";
 126     }
 127     crm_err("Unknown error code: %d", rc);
 128     return "Unknown error";
 129 }
 130 
 131 // Standard Pacemaker API return codes
 132 
 133 /* This array is used only for nonzero values of pcmk_rc_e. Its values must be
 134  * kept in the exact reverse order of the enum value numbering (i.e. add new
 135  * values to the end of the array).
 136  */
 137 static struct pcmk__rc_info {
 138     const char *name;
 139     const char *desc;
 140     int legacy_rc;
 141 } pcmk__rcs[] = {
 142     { "pcmk_rc_error",
 143       "Error",
 144       -pcmk_err_generic,
 145     },
 146     { "pcmk_rc_unknown_format",
 147       "Unknown output format",
 148       -pcmk_err_unknown_format,
 149     },
 150     { "pcmk_rc_bad_nvpair",
 151       "Bad name/value pair given",
 152       -pcmk_err_bad_nvpair,
 153     },
 154     { "pcmk_rc_already",
 155       "Already in requested state",
 156       -pcmk_err_already,
 157     },
 158     { "pcmk_rc_node_unknown",
 159       "Node not found",
 160       -pcmk_err_node_unknown,
 161     },
 162     { "pcmk_rc_multiple",
 163       "Resource active on multiple nodes",
 164       -pcmk_err_multiple,
 165     },
 166     { "pcmk_rc_cib_corrupt",
 167       "Could not parse on-disk configuration",
 168       -pcmk_err_cib_corrupt,
 169     },
 170     { "pcmk_rc_cib_save",
 171       "Could not save new configuration to disk",
 172       -pcmk_err_cib_save,
 173     },
 174     { "pcmk_rc_cib_backup",
 175       "Could not archive previous configuration",
 176       -pcmk_err_cib_backup,
 177     },
 178     { "pcmk_rc_cib_modified",
 179       "On-disk configuration was manually modified",
 180       -pcmk_err_cib_modified,
 181     },
 182     { "pcmk_rc_diff_resync",
 183       "Application of update diff failed, requesting full refresh",
 184       -pcmk_err_diff_resync,
 185     },
 186     { "pcmk_rc_diff_failed",
 187       "Application of update diff failed",
 188       -pcmk_err_diff_failed,
 189     },
 190     { "pcmk_rc_old_data",
 191       "Update was older than existing configuration",
 192       -pcmk_err_old_data,
 193     },
 194     { "pcmk_rc_transform_failed",
 195       "Schema transform failed",
 196       -pcmk_err_transform_failed,
 197     },
 198     { "pcmk_rc_schema_unchanged",
 199       "Schema is already the latest available",
 200       -pcmk_err_schema_unchanged,
 201     },
 202     { "pcmk_rc_schema_validation",
 203       "Update does not conform to the configured schema",
 204       -pcmk_err_schema_validation,
 205     },
 206     { "pcmk_rc_no_quorum",
 207       "Operation requires quorum",
 208       -pcmk_err_no_quorum,
 209     },
 210     { "pcmk_rc_ipc_pid_only",
 211       "IPC server process is active but not accepting connections",
 212       -pcmk_err_generic,
 213     },
 214     { "pcmk_rc_ipc_unresponsive",
 215       "IPC server is unresponsive",
 216       -pcmk_err_generic,
 217     },
 218     { "pcmk_rc_ipc_unauthorized",
 219       "IPC server is blocked by unauthorized process",
 220       -pcmk_err_generic,
 221     },
 222     { "pcmk_rc_op_unsatisifed",
 223       "Not applicable under current conditions",
 224       -pcmk_err_generic,
 225     },
 226     { "pcmk_rc_undetermined",
 227       "Result undetermined",
 228       -pcmk_err_generic,
 229     },
 230     { "pcmk_rc_before_range",
 231       "Result occurs before given range",
 232       -pcmk_err_generic,
 233     },
 234     { "pcmk_rc_within_range",
 235       "Result occurs within given range",
 236       -pcmk_err_generic,
 237     },
 238     { "pcmk_rc_after_range",
 239       "Result occurs after given range",
 240       -pcmk_err_generic,
 241     },
 242     { "pcmk_rc_no_output",
 243       "Output message produced no output",
 244       -pcmk_err_generic,
 245     },
 246     { "pcmk_rc_no_input",
 247       "Input file not available",
 248       -pcmk_err_generic,
 249     },
 250     { "pcmk_rc_underflow",
 251       "Value too small to be stored in data type",
 252       -pcmk_err_generic,
 253     },
 254     { "pcmk_rc_dot_error",
 255       "Error writing dot(1) file",
 256       -pcmk_err_generic,
 257     },
 258     { "pcmk_rc_graph_error",
 259       "Error writing graph file",
 260       -pcmk_err_generic,
 261     },
 262     { "pcmk_rc_invalid_transition",
 263       "Cluster simulation produced invalid transition",
 264       -pcmk_err_generic,
 265     },
 266 };
 267 
 268 #define PCMK__N_RC (sizeof(pcmk__rcs) / sizeof(struct pcmk__rc_info))
 269 
 270 /*!
 271  * \brief Get a return code constant name as a string
 272  *
 273  * \param[in] rc  Integer return code to convert
 274  *
 275  * \return String of constant name corresponding to rc
 276  */
 277 const char *
 278 pcmk_rc_name(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 279 {
 280     if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < PCMK__N_RC)) {
 281         return pcmk__rcs[pcmk_rc_error - rc].name;
 282     }
 283     switch (rc) {
 284         case pcmk_rc_ok:        return "pcmk_rc_ok";
 285         case E2BIG:             return "E2BIG";
 286         case EACCES:            return "EACCES";
 287         case EADDRINUSE:        return "EADDRINUSE";
 288         case EADDRNOTAVAIL:     return "EADDRNOTAVAIL";
 289         case EAFNOSUPPORT:      return "EAFNOSUPPORT";
 290         case EAGAIN:            return "EAGAIN";
 291         case EALREADY:          return "EALREADY";
 292         case EBADF:             return "EBADF";
 293         case EBADMSG:           return "EBADMSG";
 294         case EBUSY:             return "EBUSY";
 295         case ECANCELED:         return "ECANCELED";
 296         case ECHILD:            return "ECHILD";
 297         case ECOMM:             return "ECOMM";
 298         case ECONNABORTED:      return "ECONNABORTED";
 299         case ECONNREFUSED:      return "ECONNREFUSED";
 300         case ECONNRESET:        return "ECONNRESET";
 301         /* case EDEADLK:        return "EDEADLK"; */
 302         case EDESTADDRREQ:      return "EDESTADDRREQ";
 303         case EDOM:              return "EDOM";
 304         case EDQUOT:            return "EDQUOT";
 305         case EEXIST:            return "EEXIST";
 306         case EFAULT:            return "EFAULT";
 307         case EFBIG:             return "EFBIG";
 308         case EHOSTDOWN:         return "EHOSTDOWN";
 309         case EHOSTUNREACH:      return "EHOSTUNREACH";
 310         case EIDRM:             return "EIDRM";
 311         case EILSEQ:            return "EILSEQ";
 312         case EINPROGRESS:       return "EINPROGRESS";
 313         case EINTR:             return "EINTR";
 314         case EINVAL:            return "EINVAL";
 315         case EIO:               return "EIO";
 316         case EISCONN:           return "EISCONN";
 317         case EISDIR:            return "EISDIR";
 318         case ELIBACC:           return "ELIBACC";
 319         case ELOOP:             return "ELOOP";
 320         case EMFILE:            return "EMFILE";
 321         case EMLINK:            return "EMLINK";
 322         case EMSGSIZE:          return "EMSGSIZE";
 323 #ifdef EMULTIHOP // Not available on OpenBSD
 324         case EMULTIHOP:         return "EMULTIHOP";
 325 #endif
 326         case ENAMETOOLONG:      return "ENAMETOOLONG";
 327         case ENETDOWN:          return "ENETDOWN";
 328         case ENETRESET:         return "ENETRESET";
 329         case ENETUNREACH:       return "ENETUNREACH";
 330         case ENFILE:            return "ENFILE";
 331         case ENOBUFS:           return "ENOBUFS";
 332         case ENODATA:           return "ENODATA";
 333         case ENODEV:            return "ENODEV";
 334         case ENOENT:            return "ENOENT";
 335         case ENOEXEC:           return "ENOEXEC";
 336         case ENOKEY:            return "ENOKEY";
 337         case ENOLCK:            return "ENOLCK";
 338 #ifdef ENOLINK // Not available on OpenBSD
 339         case ENOLINK:           return "ENOLINK";
 340 #endif
 341         case ENOMEM:            return "ENOMEM";
 342         case ENOMSG:            return "ENOMSG";
 343         case ENOPROTOOPT:       return "ENOPROTOOPT";
 344         case ENOSPC:            return "ENOSPC";
 345         case ENOSR:             return "ENOSR";
 346         case ENOSTR:            return "ENOSTR";
 347         case ENOSYS:            return "ENOSYS";
 348         case ENOTBLK:           return "ENOTBLK";
 349         case ENOTCONN:          return "ENOTCONN";
 350         case ENOTDIR:           return "ENOTDIR";
 351         case ENOTEMPTY:         return "ENOTEMPTY";
 352         case ENOTSOCK:          return "ENOTSOCK";
 353 #if ENOTSUP != EOPNOTSUPP
 354         case ENOTSUP:           return "ENOTSUP";
 355 #endif
 356         case ENOTTY:            return "ENOTTY";
 357         case ENOTUNIQ:          return "ENOTUNIQ";
 358         case ENXIO:             return "ENXIO";
 359         case EOPNOTSUPP:        return "EOPNOTSUPP";
 360         case EOVERFLOW:         return "EOVERFLOW";
 361         case EPERM:             return "EPERM";
 362         case EPFNOSUPPORT:      return "EPFNOSUPPORT";
 363         case EPIPE:             return "EPIPE";
 364         case EPROTO:            return "EPROTO";
 365         case EPROTONOSUPPORT:   return "EPROTONOSUPPORT";
 366         case EPROTOTYPE:        return "EPROTOTYPE";
 367         case ERANGE:            return "ERANGE";
 368         case EREMOTE:           return "EREMOTE";
 369         case EREMOTEIO:         return "EREMOTEIO";
 370         case EROFS:             return "EROFS";
 371         case ESHUTDOWN:         return "ESHUTDOWN";
 372         case ESPIPE:            return "ESPIPE";
 373         case ESOCKTNOSUPPORT:   return "ESOCKTNOSUPPORT";
 374         case ESRCH:             return "ESRCH";
 375         case ESTALE:            return "ESTALE";
 376         case ETIME:             return "ETIME";
 377         case ETIMEDOUT:         return "ETIMEDOUT";
 378         case ETXTBSY:           return "ETXTBSY";
 379         case EUNATCH:           return "EUNATCH";
 380         case EUSERS:            return "EUSERS";
 381         /* case EWOULDBLOCK:    return "EWOULDBLOCK"; */
 382         case EXDEV:             return "EXDEV";
 383 
 384 #ifdef EBADE // Not available on OS X
 385         case EBADE:             return "EBADE";
 386         case EBADFD:            return "EBADFD";
 387         case EBADSLT:           return "EBADSLT";
 388         case EDEADLOCK:         return "EDEADLOCK";
 389         case EBADR:             return "EBADR";
 390         case EBADRQC:           return "EBADRQC";
 391         case ECHRNG:            return "ECHRNG";
 392 #ifdef EISNAM // Not available on OS X, Illumos, Solaris
 393         case EISNAM:            return "EISNAM";
 394         case EKEYEXPIRED:       return "EKEYEXPIRED";
 395         case EKEYREJECTED:      return "EKEYREJECTED";
 396         case EKEYREVOKED:       return "EKEYREVOKED";
 397 #endif
 398         case EL2HLT:            return "EL2HLT";
 399         case EL2NSYNC:          return "EL2NSYNC";
 400         case EL3HLT:            return "EL3HLT";
 401         case EL3RST:            return "EL3RST";
 402         case ELIBBAD:           return "ELIBBAD";
 403         case ELIBMAX:           return "ELIBMAX";
 404         case ELIBSCN:           return "ELIBSCN";
 405         case ELIBEXEC:          return "ELIBEXEC";
 406 #ifdef ENOMEDIUM // Not available on OS X, Illumos, Solaris
 407         case ENOMEDIUM:         return "ENOMEDIUM";
 408         case EMEDIUMTYPE:       return "EMEDIUMTYPE";
 409 #endif
 410         case ENONET:            return "ENONET";
 411         case ENOPKG:            return "ENOPKG";
 412         case EREMCHG:           return "EREMCHG";
 413         case ERESTART:          return "ERESTART";
 414         case ESTRPIPE:          return "ESTRPIPE";
 415 #ifdef EUCLEAN // Not available on OS X, Illumos, Solaris
 416         case EUCLEAN:           return "EUCLEAN";
 417 #endif
 418         case EXFULL:            return "EXFULL";
 419 #endif // EBADE
 420         default:                return "Unknown";
 421     }
 422 }
 423 
 424 /*!
 425  * \brief Get a user-friendly description of a return code
 426  *
 427  * \param[in] rc  Integer return code to convert
 428  *
 429  * \return String description of rc
 430  */
 431 const char *
 432 pcmk_rc_str(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 433 {
 434     if (rc == pcmk_rc_ok) {
 435         return "OK";
 436     }
 437     if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < PCMK__N_RC)) {
 438         return pcmk__rcs[pcmk_rc_error - rc].desc;
 439     }
 440     if (rc < 0) {
 441         return "Unknown error";
 442     }
 443     return strerror(rc);
 444 }
 445 
 446 // This returns negative values for errors
 447 //! \deprecated Use standard return codes instead
 448 int
 449 pcmk_rc2legacy(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 450 {
 451     if (rc >= 0) {
 452         return -rc; // OK or system errno
 453     }
 454     if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < PCMK__N_RC)) {
 455         return pcmk__rcs[pcmk_rc_error - rc].legacy_rc;
 456     }
 457     return -pcmk_err_generic;
 458 }
 459 
 460 //! \deprecated Use standard return codes instead
 461 int
 462 pcmk_legacy2rc(int legacy_rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 463 {
 464     legacy_rc = abs(legacy_rc);
 465     switch (legacy_rc) {
 466         case pcmk_err_no_quorum:            return pcmk_rc_no_quorum;
 467         case pcmk_err_schema_validation:    return pcmk_rc_schema_validation;
 468         case pcmk_err_schema_unchanged:     return pcmk_rc_schema_unchanged;
 469         case pcmk_err_transform_failed:     return pcmk_rc_transform_failed;
 470         case pcmk_err_old_data:             return pcmk_rc_old_data;
 471         case pcmk_err_diff_failed:          return pcmk_rc_diff_failed;
 472         case pcmk_err_diff_resync:          return pcmk_rc_diff_resync;
 473         case pcmk_err_cib_modified:         return pcmk_rc_cib_modified;
 474         case pcmk_err_cib_backup:           return pcmk_rc_cib_backup;
 475         case pcmk_err_cib_save:             return pcmk_rc_cib_save;
 476         case pcmk_err_cib_corrupt:          return pcmk_rc_cib_corrupt;
 477         case pcmk_err_multiple:             return pcmk_rc_multiple;
 478         case pcmk_err_node_unknown:         return pcmk_rc_node_unknown;
 479         case pcmk_err_already:              return pcmk_rc_already;
 480         case pcmk_err_bad_nvpair:           return pcmk_rc_bad_nvpair;
 481         case pcmk_err_unknown_format:       return pcmk_rc_unknown_format;
 482         case pcmk_err_generic:              return pcmk_rc_error;
 483         case pcmk_ok:                       return pcmk_rc_ok;
 484         default:                            return legacy_rc; // system errno
 485     }
 486 }
 487 
 488 // Exit status codes
 489 
 490 const char *
 491 crm_exit_name(crm_exit_t exit_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 492 {
 493     switch (exit_code) {
 494         case CRM_EX_OK: return "CRM_EX_OK";
 495         case CRM_EX_ERROR: return "CRM_EX_ERROR";
 496         case CRM_EX_INVALID_PARAM: return "CRM_EX_INVALID_PARAM";
 497         case CRM_EX_UNIMPLEMENT_FEATURE: return "CRM_EX_UNIMPLEMENT_FEATURE";
 498         case CRM_EX_INSUFFICIENT_PRIV: return "CRM_EX_INSUFFICIENT_PRIV";
 499         case CRM_EX_NOT_INSTALLED: return "CRM_EX_NOT_INSTALLED";
 500         case CRM_EX_NOT_CONFIGURED: return "CRM_EX_NOT_CONFIGURED";
 501         case CRM_EX_NOT_RUNNING: return "CRM_EX_NOT_RUNNING";
 502         case CRM_EX_USAGE: return "CRM_EX_USAGE";
 503         case CRM_EX_DATAERR: return "CRM_EX_DATAERR";
 504         case CRM_EX_NOINPUT: return "CRM_EX_NOINPUT";
 505         case CRM_EX_NOUSER: return "CRM_EX_NOUSER";
 506         case CRM_EX_NOHOST: return "CRM_EX_NOHOST";
 507         case CRM_EX_UNAVAILABLE: return "CRM_EX_UNAVAILABLE";
 508         case CRM_EX_SOFTWARE: return "CRM_EX_SOFTWARE";
 509         case CRM_EX_OSERR: return "CRM_EX_OSERR";
 510         case CRM_EX_OSFILE: return "CRM_EX_OSFILE";
 511         case CRM_EX_CANTCREAT: return "CRM_EX_CANTCREAT";
 512         case CRM_EX_IOERR: return "CRM_EX_IOERR";
 513         case CRM_EX_TEMPFAIL: return "CRM_EX_TEMPFAIL";
 514         case CRM_EX_PROTOCOL: return "CRM_EX_PROTOCOL";
 515         case CRM_EX_NOPERM: return "CRM_EX_NOPERM";
 516         case CRM_EX_CONFIG: return "CRM_EX_CONFIG";
 517         case CRM_EX_FATAL: return "CRM_EX_FATAL";
 518         case CRM_EX_PANIC: return "CRM_EX_PANIC";
 519         case CRM_EX_DISCONNECT: return "CRM_EX_DISCONNECT";
 520         case CRM_EX_DIGEST: return "CRM_EX_DIGEST";
 521         case CRM_EX_NOSUCH: return "CRM_EX_NOSUCH";
 522         case CRM_EX_QUORUM: return "CRM_EX_QUORUM";
 523         case CRM_EX_UNSAFE: return "CRM_EX_UNSAFE";
 524         case CRM_EX_EXISTS: return "CRM_EX_EXISTS";
 525         case CRM_EX_MULTIPLE: return "CRM_EX_MULTIPLE";
 526         case CRM_EX_EXPIRED: return "CRM_EX_EXPIRED";
 527         case CRM_EX_NOT_YET_IN_EFFECT: return "CRM_EX_NOT_YET_IN_EFFECT";
 528         case CRM_EX_INDETERMINATE: return "CRM_EX_INDETERMINATE";
 529         case CRM_EX_UNSATISFIED: return "CRM_EX_UNSATISFIED";
 530         case CRM_EX_OLD: return "CRM_EX_OLD";
 531         case CRM_EX_TIMEOUT: return "CRM_EX_TIMEOUT";
 532         case CRM_EX_DEGRADED: return "CRM_EX_DEGRADED";
 533         case CRM_EX_DEGRADED_PROMOTED: return "CRM_EX_DEGRADED_PROMOTED";
 534         case CRM_EX_MAX: return "CRM_EX_UNKNOWN";
 535     }
 536     return "CRM_EX_UNKNOWN";
 537 }
 538 
 539 const char *
 540 crm_exit_str(crm_exit_t exit_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 541 {
 542     switch (exit_code) {
 543         case CRM_EX_OK: return "OK";
 544         case CRM_EX_ERROR: return "Error occurred";
 545         case CRM_EX_INVALID_PARAM: return "Invalid parameter";
 546         case CRM_EX_UNIMPLEMENT_FEATURE: return "Unimplemented";
 547         case CRM_EX_INSUFFICIENT_PRIV: return "Insufficient privileges";
 548         case CRM_EX_NOT_INSTALLED: return "Not installed";
 549         case CRM_EX_NOT_CONFIGURED: return "Not configured";
 550         case CRM_EX_NOT_RUNNING: return "Not running";
 551         case CRM_EX_USAGE: return "Incorrect usage";
 552         case CRM_EX_DATAERR: return "Invalid data given";
 553         case CRM_EX_NOINPUT: return "Input file not available";
 554         case CRM_EX_NOUSER: return "User does not exist";
 555         case CRM_EX_NOHOST: return "Host does not exist";
 556         case CRM_EX_UNAVAILABLE: return "Necessary service unavailable";
 557         case CRM_EX_SOFTWARE: return "Internal software bug";
 558         case CRM_EX_OSERR: return "Operating system error occurred";
 559         case CRM_EX_OSFILE: return "System file not available";
 560         case CRM_EX_CANTCREAT: return "Cannot create output file";
 561         case CRM_EX_IOERR: return "I/O error occurred";
 562         case CRM_EX_TEMPFAIL: return "Temporary failure, try again";
 563         case CRM_EX_PROTOCOL: return "Protocol violated";
 564         case CRM_EX_NOPERM: return "Insufficient privileges";
 565         case CRM_EX_CONFIG: return "Invalid configuration";
 566         case CRM_EX_FATAL: return "Fatal error occurred, will not respawn";
 567         case CRM_EX_PANIC: return "System panic required";
 568         case CRM_EX_DISCONNECT: return "Not connected";
 569         case CRM_EX_DIGEST: return "Digest mismatch";
 570         case CRM_EX_NOSUCH: return "No such object";
 571         case CRM_EX_QUORUM: return "Quorum required";
 572         case CRM_EX_UNSAFE: return "Operation not safe";
 573         case CRM_EX_EXISTS: return "Requested item already exists";
 574         case CRM_EX_MULTIPLE: return "Multiple items match request";
 575         case CRM_EX_EXPIRED: return "Requested item has expired";
 576         case CRM_EX_NOT_YET_IN_EFFECT: return "Requested item is not yet in effect";
 577         case CRM_EX_INDETERMINATE: return "Could not determine status";
 578         case CRM_EX_UNSATISFIED: return "Not applicable under current conditions";
 579         case CRM_EX_OLD: return "Update was older than existing configuration";
 580         case CRM_EX_TIMEOUT: return "Timeout occurred";
 581         case CRM_EX_DEGRADED: return "Service is active but might fail soon";
 582         case CRM_EX_DEGRADED_PROMOTED: return "Service is promoted but might fail soon";
 583         case CRM_EX_MAX: return "Error occurred";
 584     }
 585     if ((exit_code > 128) && (exit_code < CRM_EX_MAX)) {
 586         return "Interrupted by signal";
 587     }
 588     return "Unknown exit status";
 589 }
 590 
 591 //! \deprecated Use standard return codes and pcmk_rc2exitc() instead
 592 crm_exit_t
 593 crm_errno2exit(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 594 {
 595     rc = abs(rc); // Convenience for functions that return -errno
 596     switch (rc) {
 597         case pcmk_ok:
 598             return CRM_EX_OK;
 599 
 600         case pcmk_err_no_quorum:
 601             return CRM_EX_QUORUM;
 602 
 603         case pcmk_err_old_data:
 604             return CRM_EX_OLD;
 605 
 606         case pcmk_err_schema_validation:
 607         case pcmk_err_transform_failed:
 608             return CRM_EX_CONFIG;
 609 
 610         case pcmk_err_bad_nvpair:
 611             return CRM_EX_INVALID_PARAM;
 612 
 613         case pcmk_err_already:
 614             return CRM_EX_EXISTS;
 615 
 616         case pcmk_err_multiple:
 617             return CRM_EX_MULTIPLE;
 618 
 619         case pcmk_err_node_unknown:
 620         case pcmk_err_unknown_format:
 621             return CRM_EX_NOSUCH;
 622 
 623         default:
 624             return pcmk_rc2exitc(rc); // system errno
 625     }
 626 }
 627 
 628 /*!
 629  * \brief Map a function return code to the most similar exit code
 630  *
 631  * \param[in] rc  Function return code
 632  *
 633  * \return Most similar exit code
 634  */
 635 crm_exit_t
 636 pcmk_rc2exitc(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 637 {
 638     switch (rc) {
 639         case pcmk_rc_ok:
 640             return CRM_EX_OK;
 641 
 642         case pcmk_rc_no_quorum:
 643             return CRM_EX_QUORUM;
 644 
 645         case pcmk_rc_old_data:
 646             return CRM_EX_OLD;
 647 
 648         case pcmk_rc_schema_validation:
 649         case pcmk_rc_transform_failed:
 650             return CRM_EX_CONFIG;
 651 
 652         case pcmk_rc_bad_nvpair:
 653             return CRM_EX_INVALID_PARAM;
 654 
 655         case EACCES:
 656             return CRM_EX_INSUFFICIENT_PRIV;
 657 
 658         case EBADF:
 659         case EINVAL:
 660         case EFAULT:
 661         case ENOSYS:
 662         case EOVERFLOW:
 663         case pcmk_rc_underflow:
 664             return CRM_EX_SOFTWARE;
 665 
 666         case EBADMSG:
 667         case EMSGSIZE:
 668         case ENOMSG:
 669         case ENOPROTOOPT:
 670         case EPROTO:
 671         case EPROTONOSUPPORT:
 672         case EPROTOTYPE:
 673             return CRM_EX_PROTOCOL;
 674 
 675         case ECOMM:
 676         case ENOMEM:
 677             return CRM_EX_OSERR;
 678 
 679         case ECONNABORTED:
 680         case ECONNREFUSED:
 681         case ECONNRESET:
 682         case ENOTCONN:
 683             return CRM_EX_DISCONNECT;
 684 
 685         case EEXIST:
 686         case pcmk_rc_already:
 687             return CRM_EX_EXISTS;
 688 
 689         case EIO:
 690         case pcmk_rc_no_output:
 691         case pcmk_rc_dot_error:
 692         case pcmk_rc_graph_error:
 693             return CRM_EX_IOERR;
 694 
 695         case ENOTSUP:
 696 #if EOPNOTSUPP != ENOTSUP
 697         case EOPNOTSUPP:
 698 #endif
 699             return CRM_EX_UNIMPLEMENT_FEATURE;
 700 
 701         case ENOTUNIQ:
 702         case pcmk_rc_multiple:
 703             return CRM_EX_MULTIPLE;
 704 
 705         case ENXIO:
 706         case pcmk_rc_node_unknown:
 707         case pcmk_rc_unknown_format:
 708             return CRM_EX_NOSUCH;
 709 
 710         case ETIME:
 711         case ETIMEDOUT:
 712             return CRM_EX_TIMEOUT;
 713 
 714         case EAGAIN:
 715         case EBUSY:
 716             return CRM_EX_UNSATISFIED;
 717 
 718         case pcmk_rc_before_range:
 719             return CRM_EX_NOT_YET_IN_EFFECT;
 720 
 721         case pcmk_rc_after_range:
 722             return CRM_EX_EXPIRED;
 723 
 724         case pcmk_rc_undetermined:
 725             return CRM_EX_INDETERMINATE;
 726 
 727         case pcmk_rc_op_unsatisfied:
 728             return CRM_EX_UNSATISFIED;
 729 
 730         case pcmk_rc_within_range:
 731             return CRM_EX_OK;
 732 
 733         case pcmk_rc_no_input:
 734             return CRM_EX_NOINPUT;
 735 
 736         default:
 737             return CRM_EX_ERROR;
 738     }
 739 }
 740 
 741 /*!
 742  * \brief Map a function return code to the most similar OCF exit code
 743  *
 744  * \param[in] rc  Function return code
 745  *
 746  * \return Most similar OCF exit code
 747  */
 748 enum ocf_exitcode
 749 pcmk_rc2ocf(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 750 {
 751     switch (rc) {
 752         case pcmk_rc_ok:
 753             return PCMK_OCF_OK;
 754 
 755         case pcmk_rc_bad_nvpair:
 756             return PCMK_OCF_INVALID_PARAM;
 757 
 758         case EACCES:
 759             return PCMK_OCF_INSUFFICIENT_PRIV;
 760 
 761         case ENOTSUP:
 762 #if EOPNOTSUPP != ENOTSUP
 763         case EOPNOTSUPP:
 764 #endif
 765             return PCMK_OCF_UNIMPLEMENT_FEATURE;
 766 
 767         default:
 768             return PCMK_OCF_UNKNOWN_ERROR;
 769     }
 770 }
 771 
 772 
 773 // Other functions
 774 
 775 const char *
 776 bz2_strerror(int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 777 {
 778     // See ftp://sources.redhat.com/pub/bzip2/docs/manual_3.html#SEC17
 779     switch (rc) {
 780         case BZ_OK:
 781         case BZ_RUN_OK:
 782         case BZ_FLUSH_OK:
 783         case BZ_FINISH_OK:
 784         case BZ_STREAM_END:
 785             return "Ok";
 786         case BZ_CONFIG_ERROR:
 787             return "libbz2 has been improperly compiled on your platform";
 788         case BZ_SEQUENCE_ERROR:
 789             return "library functions called in the wrong order";
 790         case BZ_PARAM_ERROR:
 791             return "parameter is out of range or otherwise incorrect";
 792         case BZ_MEM_ERROR:
 793             return "memory allocation failed";
 794         case BZ_DATA_ERROR:
 795             return "data integrity error is detected during decompression";
 796         case BZ_DATA_ERROR_MAGIC:
 797             return "the compressed stream does not start with the correct magic bytes";
 798         case BZ_IO_ERROR:
 799             return "error reading or writing in the compressed file";
 800         case BZ_UNEXPECTED_EOF:
 801             return "compressed file finishes before the logical end of stream is detected";
 802         case BZ_OUTBUFF_FULL:
 803             return "output data will not fit into the buffer provided";
 804     }
 805     return "Unknown error";
 806 }
 807 
 808 crm_exit_t
 809 crm_exit(crm_exit_t rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 810 {
 811     /* A compiler could theoretically use any type for crm_exit_t, but an int
 812      * should always hold it, so cast to int to keep static analysis happy.
 813      */
 814     if ((((int) rc) < 0) || (((int) rc) > CRM_EX_MAX)) {
 815         rc = CRM_EX_ERROR;
 816     }
 817 
 818     mainloop_cleanup();
 819     crm_xml_cleanup();
 820 
 821     pcmk__cli_option_cleanup();
 822 
 823     if (crm_system_name) {
 824         crm_info("Exiting %s " CRM_XS " with status %d", crm_system_name, rc);
 825         free(crm_system_name);
 826     } else {
 827         crm_trace("Exiting with status %d", rc);
 828     }
 829     qb_log_fini(); // Don't log anything after this point
 830 
 831     exit(rc);
 832 }
 833 
 834 /*
 835  * External action results
 836  */
 837 
 838 /*!
 839  * \internal
 840  * \brief Set the result of an action
 841  *
 842  * \param[out] result        Where to set action result
 843  * \param[in]  exit_status   OCF exit status to set
 844  * \param[in]  exec_status   Execution status to set
 845  * \param[in]  exit_reason   Human-friendly description of event to set
 846  */
 847 void
 848 pcmk__set_result(pcmk__action_result_t *result, int exit_status,
     /* [previous][next][first][last][top][bottom][index][help] */
 849                  enum pcmk_exec_status exec_status, const char *exit_reason)
 850 {
 851     if (result == NULL) {
 852         return;
 853     }
 854 
 855     result->exit_status = exit_status;
 856     result->execution_status = exec_status;
 857 
 858     if (!pcmk__str_eq(result->exit_reason, exit_reason, pcmk__str_none)) {
 859         free(result->exit_reason);
 860         result->exit_reason = (exit_reason == NULL)? NULL : strdup(exit_reason);
 861     }
 862 }
 863 
 864 /*!
 865  * \internal
 866  * \brief Set the output of an action
 867  *
 868  * \param[out] result         Action result to set output for
 869  * \param[in]  out            Action output to set (must be dynamically
 870  *                            allocated)
 871  * \param[in]  err            Action error output to set (must be dynamically
 872  *                            allocated)
 873  *
 874  * \note \p result will take ownership of \p out and \p err, so the caller
 875  *       should not free them.
 876  */
 877 void
 878 pcmk__set_result_output(pcmk__action_result_t *result, char *out, char *err)
     /* [previous][next][first][last][top][bottom][index][help] */
 879 {
 880     if (result == NULL) {
 881         return;
 882     }
 883 
 884     free(result->action_stdout);
 885     result->action_stdout = out;
 886 
 887     free(result->action_stderr);
 888     result->action_stderr = err;
 889 }
 890 
 891 /*!
 892  * \internal
 893  * \brief Clear a result's exit reason, output, and error output
 894  *
 895  * \param[in] result  Result to reset
 896  */
 897 void
 898 pcmk__reset_result(pcmk__action_result_t *result)
     /* [previous][next][first][last][top][bottom][index][help] */
 899 {
 900     if (result == NULL) {
 901         return;
 902     }
 903 
 904     free(result->exit_reason);
 905     result->exit_reason = NULL;
 906 
 907     free(result->action_stdout);
 908     result->action_stdout = NULL;
 909 
 910     free(result->action_stderr);
 911     result->action_stderr = NULL;
 912 }

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