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. G_GNUC_PRINTF
  16. pcmk__set_result_output
  17. pcmk__reset_result
  18. pcmk__copy_result

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

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