1 /*
2  * Copyright 2012-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 #ifndef CRM_RESULTS__H
10 #  define CRM_RESULTS__H
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 
16 /*!
17  * \file
18  * \brief Function and executable result codes
19  * \ingroup core
20  */
21 
22 // Lifted from config.h
23 /* The _Noreturn keyword of C11.  */
24 #ifndef _Noreturn
25 # if (defined __cplusplus \
26       && ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
27           || (defined _MSC_VER && 1900 <= _MSC_VER)))
28 #  define _Noreturn [[noreturn]]
29 # elif ((!defined __cplusplus || defined __clang__) \
30         && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0)  \
31             || 4 < __GNUC__ + (7 <= __GNUC_MINOR__)))
32    /* _Noreturn works as-is.  */
33 # elif 2 < __GNUC__ + (8 <= __GNUC_MINOR__) || 0x5110 <= __SUNPRO_C
34 #  define _Noreturn __attribute__ ((__noreturn__))
35 # elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0)
36 #  define _Noreturn __declspec (noreturn)
37 # else
38 #  define _Noreturn
39 # endif
40 #endif
41 
42 #  define CRM_ASSERT(expr) do {                                              \
43         if (!(expr)) {                                                       \
44             crm_abort(__FILE__, __func__, __LINE__, #expr, TRUE, FALSE);     \
45             abort(); /* crm_abort() doesn't always abort! */                 \
46         }                                                                    \
47     } while(0)
48 
49 /*
50  * Function return codes
51  *
52  * Most Pacemaker API functions return an integer return code. There are two
53  * alternative interpretations. The legacy interpration is that the absolute
54  * value of the return code is either a system error number or a custom
55  * pcmk_err_* number. This is less than ideal because system error numbers are
56  * constrained only to the positive int range, so there's the possibility
57  * (though not noticed in the wild) that system errors and custom errors could
58  * collide. The new intepretation is that negative values are from the pcmk_rc_e
59  * enum, and positive values are system error numbers. Both use 0 for success.
60  *
61  * For system error codes, see:
62  * - /usr/include/asm-generic/errno.h
63  * - /usr/include/asm-generic/errno-base.h
64  */
65 
66 // Legacy custom return codes for Pacemaker API functions (deprecated)
67 #  define pcmk_ok                       0
68 #  define PCMK_ERROR_OFFSET             190    /* Replacements on non-linux systems, see include/portability.h */
69 #  define PCMK_CUSTOM_OFFSET            200    /* Purely custom codes */
70 #  define pcmk_err_generic              201
71 #  define pcmk_err_no_quorum            202
72 #  define pcmk_err_schema_validation    203
73 #  define pcmk_err_transform_failed     204
74 #  define pcmk_err_old_data             205
75 #  define pcmk_err_diff_failed          206
76 #  define pcmk_err_diff_resync          207
77 #  define pcmk_err_cib_modified         208
78 #  define pcmk_err_cib_backup           209
79 #  define pcmk_err_cib_save             210
80 #  define pcmk_err_schema_unchanged     211
81 #  define pcmk_err_cib_corrupt          212
82 #  define pcmk_err_multiple             213
83 #  define pcmk_err_node_unknown         214
84 #  define pcmk_err_already              215
85 /* On HPPA 215 is ENOSYM (Unknown error 215), which hopefully never happens. */
86 #ifdef __hppa__
87 #  define pcmk_err_bad_nvpair           250	/* 216 is ENOTSOCK */
88 #  define pcmk_err_unknown_format       252	/* 217 is EDESTADDRREQ */
89 #else
90 #  define pcmk_err_bad_nvpair           216
91 #  define pcmk_err_unknown_format       217
92 #endif
93 
94 /*!
95  * \enum pcmk_rc_e
96  * \brief Return codes for Pacemaker API functions
97  *
98  * Any Pacemaker API function documented as returning a "standard Pacemaker
99  * return code" will return pcmk_rc_ok (0) on success, and one of this
100  * enumeration's other (negative) values or a (positive) system error number
101  * otherwise. The custom codes are at -1001 and lower, so that the caller may
102  * use -1 through -1000 for their own custom values if desired. While generally
103  * referred to as "errors", nonzero values simply indicate a result, which might
104  * or might not be an error depending on the calling context.
105  */
106 enum pcmk_rc_e {
107     /* When adding new values, use consecutively lower numbers, update the array
108      * in lib/common/results.c, and test with crm_error.
109      */
110     pcmk_rc_underflow           = -1028,
111     pcmk_rc_no_input            = -1027,
112     pcmk_rc_no_output           = -1026,
113     pcmk_rc_after_range         = -1025,
114     pcmk_rc_within_range        = -1024,
115     pcmk_rc_before_range        = -1023,
116     pcmk_rc_undetermined        = -1022,
117     pcmk_rc_op_unsatisfied      = -1021,
118     pcmk_rc_ipc_pid_only        = -1020,
119     pcmk_rc_ipc_unresponsive    = -1019,
120     pcmk_rc_ipc_unauthorized    = -1018,
121     pcmk_rc_no_quorum           = -1017,
122     pcmk_rc_schema_validation   = -1016,
123     pcmk_rc_schema_unchanged    = -1015,
124     pcmk_rc_transform_failed    = -1014,
125     pcmk_rc_old_data            = -1013,
126     pcmk_rc_diff_failed         = -1012,
127     pcmk_rc_diff_resync         = -1011,
128     pcmk_rc_cib_modified        = -1010,
129     pcmk_rc_cib_backup          = -1009,
130     pcmk_rc_cib_save            = -1008,
131     pcmk_rc_cib_corrupt         = -1007,
132     pcmk_rc_multiple            = -1006,
133     pcmk_rc_node_unknown        = -1005,
134     pcmk_rc_already             = -1004,
135     pcmk_rc_bad_nvpair          = -1003,
136     pcmk_rc_unknown_format      = -1002,
137     // Developers: Use a more specific code than pcmk_rc_error whenever possible
138     pcmk_rc_error               = -1001,
139 
140     // Values -1 through -1000 reserved for caller use
141 
142     pcmk_rc_ok                  =     0
143 
144     // Positive values reserved for system error numbers
145 };
146 
147 /* Uniform exit codes
148  * Everything is mapped to its OCF equivalent so that Pacemaker only deals with one set of codes
149  */
150 enum ocf_exitcode {
151     PCMK_OCF_OK                   = 0,
152     PCMK_OCF_UNKNOWN_ERROR        = 1,
153     PCMK_OCF_INVALID_PARAM        = 2,
154     PCMK_OCF_UNIMPLEMENT_FEATURE  = 3,
155     PCMK_OCF_INSUFFICIENT_PRIV    = 4,
156     PCMK_OCF_NOT_INSTALLED        = 5,
157     PCMK_OCF_NOT_CONFIGURED       = 6,
158     PCMK_OCF_NOT_RUNNING          = 7,  /* End of overlap with LSB */
159     PCMK_OCF_RUNNING_PROMOTED     = 8,
160     PCMK_OCF_FAILED_PROMOTED      = 9,
161 
162 
163     /* 150-199	reserved for application use */
164     PCMK_OCF_CONNECTION_DIED = 189, // Deprecated (see PCMK_LRM_OP_NOT_CONNECTED)
165 
166     PCMK_OCF_DEGRADED           = 190, // Resource active but more likely to fail soon
167     PCMK_OCF_DEGRADED_PROMOTED  = 191, // Resource promoted but more likely to fail soon
168 
169     PCMK_OCF_EXEC_ERROR    = 192, /* Generic problem invoking the agent */
170     PCMK_OCF_UNKNOWN       = 193, /* State of the service is unknown - used for recording in-flight operations */
171     PCMK_OCF_SIGNAL        = 194,
172     PCMK_OCF_NOT_SUPPORTED = 195,
173     PCMK_OCF_PENDING       = 196,
174     PCMK_OCF_CANCELLED     = 197,
175     PCMK_OCF_TIMEOUT       = 198,
176     PCMK_OCF_OTHER_ERROR   = 199, /* Keep the same codes as PCMK_LSB */
177 
178 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
179     //! \deprecated Use PCMK_OCF_RUNNING_PROMOTED instead
180     PCMK_OCF_RUNNING_MASTER     = PCMK_OCF_RUNNING_PROMOTED,
181 
182     //! \deprecated Use PCMK_OCF_FAILED_PROMOTED instead
183     PCMK_OCF_FAILED_MASTER      = PCMK_OCF_FAILED_PROMOTED,
184 
185     //! \deprecated Use PCMK_OCF_DEGRADED_PROMOTED instead
186     PCMK_OCF_DEGRADED_MASTER    = PCMK_OCF_DEGRADED_PROMOTED,
187 #endif
188 };
189 
190 /*
191  * Exit status codes
192  *
193  * We want well-specified (i.e. OS-invariant) exit status codes for our daemons
194  * and applications so they can be relied on by callers. (Function return codes
195  * and errno's do not make good exit statuses.)
196  *
197  * The only hard rule is that exit statuses must be between 0 and 255; all else
198  * is convention. Universally, 0 is success, and 1 is generic error (excluding
199  * OSes we don't support -- for example, OpenVMS considers 1 success!).
200  *
201  * For init scripts, the LSB gives meaning to 0-7, and sets aside 150-199 for
202  * application use. OCF adds 8-9 and 189-199.
203  *
204  * sysexits.h was an attempt to give additional meanings, but never really
205  * caught on. It uses 0 and 64-78.
206  *
207  * Bash reserves 2 ("incorrect builtin usage") and 126-255 (126 is "command
208  * found but not executable", 127 is "command not found", 128 + n is
209  * "interrupted by signal n").
210  *
211  * tldp.org recommends 64-113 for application use.
212  *
213  * We try to overlap with the above conventions when practical.
214  */
215 typedef enum crm_exit_e {
216     // Common convention
217     CRM_EX_OK                   =   0,
218     CRM_EX_ERROR                =   1,
219 
220     // LSB + OCF
221     CRM_EX_INVALID_PARAM        =   2,
222     CRM_EX_UNIMPLEMENT_FEATURE  =   3,
223     CRM_EX_INSUFFICIENT_PRIV    =   4,
224     CRM_EX_NOT_INSTALLED        =   5,
225     CRM_EX_NOT_CONFIGURED       =   6,
226     CRM_EX_NOT_RUNNING          =   7,
227 
228     // sysexits.h
229     CRM_EX_USAGE                =  64, // command line usage error
230     CRM_EX_DATAERR              =  65, // user-supplied data incorrect
231     CRM_EX_NOINPUT              =  66, // input file not available
232     CRM_EX_NOUSER               =  67, // user does not exist
233     CRM_EX_NOHOST               =  68, // host unknown
234     CRM_EX_UNAVAILABLE          =  69, // needed service unavailable
235     CRM_EX_SOFTWARE             =  70, // internal software bug
236     CRM_EX_OSERR                =  71, // external (OS/environmental) problem
237     CRM_EX_OSFILE               =  72, // system file not usable
238     CRM_EX_CANTCREAT            =  73, // file couldn't be created
239     CRM_EX_IOERR                =  74, // file I/O error
240     CRM_EX_TEMPFAIL             =  75, // try again
241     CRM_EX_PROTOCOL             =  76, // protocol violated
242     CRM_EX_NOPERM               =  77, // non-file permission issue
243     CRM_EX_CONFIG               =  78, // misconfiguration
244 
245     // Custom
246     CRM_EX_FATAL                = 100, // do not respawn
247     CRM_EX_PANIC                = 101, // panic the local host
248     CRM_EX_DISCONNECT           = 102, // lost connection to something
249     CRM_EX_OLD                  = 103, // update older than existing config
250     CRM_EX_DIGEST               = 104, // digest comparison failed
251     CRM_EX_NOSUCH               = 105, // requested item does not exist
252     CRM_EX_QUORUM               = 106, // local partition does not have quorum
253     CRM_EX_UNSAFE               = 107, // requires --force or new conditions
254     CRM_EX_EXISTS               = 108, // requested item already exists
255     CRM_EX_MULTIPLE             = 109, // requested item has multiple matches
256     CRM_EX_EXPIRED              = 110, // requested item has expired
257     CRM_EX_NOT_YET_IN_EFFECT    = 111, // requested item is not in effect
258     CRM_EX_INDETERMINATE        = 112, // could not determine status
259     CRM_EX_UNSATISFIED          = 113, // requested item does not satisfy constraints
260 
261     // Other
262     CRM_EX_TIMEOUT              = 124, // convention from timeout(1)
263     CRM_EX_MAX                  = 255, // ensure crm_exit_t can hold this
264 } crm_exit_t;
265 
266 const char *pcmk_rc_name(int rc);
267 const char *pcmk_rc_str(int rc);
268 crm_exit_t pcmk_rc2exitc(int rc);
269 int pcmk_rc2legacy(int rc);
270 int pcmk_legacy2rc(int legacy_rc);
271 const char *pcmk_strerror(int rc);
272 const char *pcmk_errorname(int rc);
273 const char *bz2_strerror(int rc);
274 crm_exit_t crm_errno2exit(int rc);
275 const char *crm_exit_name(crm_exit_t exit_code);
276 const char *crm_exit_str(crm_exit_t exit_code);
277 _Noreturn crm_exit_t crm_exit(crm_exit_t rc);
278 
279 #ifdef __cplusplus
280 }
281 #endif
282 
283 #endif
284