diff --git a/shared/nm-utils/nm-errno.c b/shared/nm-utils/nm-errno.c index c87f0b48d6..ddf280766c 100644 --- a/shared/nm-utils/nm-errno.c +++ b/shared/nm-utils/nm-errno.c @@ -24,29 +24,41 @@ /*****************************************************************************/ -NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_geterror, int, +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_geterror, +#if 0 + enum _NMErrno, +#else + int, +#endif NM_UTILS_LOOKUP_DEFAULT (NULL), - NM_UTILS_LOOKUP_STR_ITEM (NME_UNSPEC, "NME_UNSPEC"), - NM_UTILS_LOOKUP_STR_ITEM (NME_BUG, "NME_BUG"), - NM_UTILS_LOOKUP_STR_ITEM (NME_NATIVE_ERRNO, "NME_NATIVE_ERRNO"), + NM_UTILS_LOOKUP_STR_ITEM (NME_ERRNO_SUCCESS, "NME_ERRNO_SUCCESS"), + NM_UTILS_LOOKUP_STR_ITEM (NME_ERRNO_OUT_OF_RANGE, "NME_ERRNO_OUT_OF_RANGE"), - NM_UTILS_LOOKUP_STR_ITEM (NME_NL_ATTRSIZE, "NME_NL_ATTRSIZE"), - NM_UTILS_LOOKUP_STR_ITEM (NME_NL_BAD_SOCK, "NME_NL_BAD_SOCK"), - NM_UTILS_LOOKUP_STR_ITEM (NME_NL_DUMP_INTR, "NME_NL_DUMP_INTR"), - NM_UTILS_LOOKUP_STR_ITEM (NME_NL_MSG_OVERFLOW, "NME_NL_MSG_OVERFLOW"), - NM_UTILS_LOOKUP_STR_ITEM (NME_NL_MSG_TOOSHORT, "NME_NL_MSG_TOOSHORT"), - NM_UTILS_LOOKUP_STR_ITEM (NME_NL_MSG_TRUNC, "NME_NL_MSG_TRUNC"), - NM_UTILS_LOOKUP_STR_ITEM (NME_NL_SEQ_MISMATCH, "NME_NL_SEQ_MISMATCH"), + NM_UTILS_LOOKUP_STR_ITEM (NME_UNSPEC, "NME_UNSPEC"), + NM_UTILS_LOOKUP_STR_ITEM (NME_BUG, "NME_BUG"), + NM_UTILS_LOOKUP_STR_ITEM (NME_NATIVE_ERRNO, "NME_NATIVE_ERRNO"), - NM_UTILS_LOOKUP_STR_ITEM (NME_PL_NOT_FOUND, "not-found"), - NM_UTILS_LOOKUP_STR_ITEM (NME_PL_EXISTS, "exists"), - NM_UTILS_LOOKUP_STR_ITEM (NME_PL_WRONG_TYPE, "wrong-type"), - NM_UTILS_LOOKUP_STR_ITEM (NME_PL_NOT_SLAVE, "not-slave"), - NM_UTILS_LOOKUP_STR_ITEM (NME_PL_NO_FIRMWARE, "no-firmware"), - NM_UTILS_LOOKUP_STR_ITEM (NME_PL_OPNOTSUPP, "not-supported"), - NM_UTILS_LOOKUP_STR_ITEM (NME_PL_NETLINK, "netlink"), - NM_UTILS_LOOKUP_STR_ITEM (NME_PL_CANT_SET_MTU, "cant-set-mtu"), + NM_UTILS_LOOKUP_STR_ITEM (NME_NL_ATTRSIZE, "NME_NL_ATTRSIZE"), + NM_UTILS_LOOKUP_STR_ITEM (NME_NL_BAD_SOCK, "NME_NL_BAD_SOCK"), + NM_UTILS_LOOKUP_STR_ITEM (NME_NL_DUMP_INTR, "NME_NL_DUMP_INTR"), + NM_UTILS_LOOKUP_STR_ITEM (NME_NL_MSG_OVERFLOW, "NME_NL_MSG_OVERFLOW"), + NM_UTILS_LOOKUP_STR_ITEM (NME_NL_MSG_TOOSHORT, "NME_NL_MSG_TOOSHORT"), + NM_UTILS_LOOKUP_STR_ITEM (NME_NL_MSG_TRUNC, "NME_NL_MSG_TRUNC"), + NM_UTILS_LOOKUP_STR_ITEM (NME_NL_SEQ_MISMATCH, "NME_NL_SEQ_MISMATCH"), + NM_UTILS_LOOKUP_STR_ITEM (NME_NL_NOADDR, "NME_NL_NOADDR"), + + NM_UTILS_LOOKUP_STR_ITEM (NME_PL_NOT_FOUND, "not-found"), + NM_UTILS_LOOKUP_STR_ITEM (NME_PL_EXISTS, "exists"), + NM_UTILS_LOOKUP_STR_ITEM (NME_PL_WRONG_TYPE, "wrong-type"), + NM_UTILS_LOOKUP_STR_ITEM (NME_PL_NOT_SLAVE, "not-slave"), + NM_UTILS_LOOKUP_STR_ITEM (NME_PL_NO_FIRMWARE, "no-firmware"), + NM_UTILS_LOOKUP_STR_ITEM (NME_PL_OPNOTSUPP, "not-supported"), + NM_UTILS_LOOKUP_STR_ITEM (NME_PL_NETLINK, "netlink"), + NM_UTILS_LOOKUP_STR_ITEM (NME_PL_CANT_SET_MTU, "cant-set-mtu"), + + NM_UTILS_LOOKUP_ITEM_IGNORE (_NM_ERRNO_MININT), + NM_UTILS_LOOKUP_ITEM_IGNORE (_NM_ERRNO_RESERVED_LAST_PLUS_1), ); const char * diff --git a/shared/nm-utils/nm-errno.h b/shared/nm-utils/nm-errno.h index 3bbf879327..68cf49a0c1 100644 --- a/shared/nm-utils/nm-errno.h +++ b/shared/nm-utils/nm-errno.h @@ -25,11 +25,23 @@ /*****************************************************************************/ -enum { +enum _NMErrno { _NM_ERRNO_MININT = G_MININT, _NM_ERRNO_MAXINT = G_MAXINT, _NM_ERRNO_RESERVED_FIRST = 100000, + + /* when we cannot represent a number as positive number, we resort to this + * number. Basically, the values G_MININT, -NME_ERRNO_SUCCESS, NME_ERRNO_SUCCESS + * and G_MAXINT all map to the same value. */ + NME_ERRNO_OUT_OF_RANGE = G_MAXINT, + + /* Indicate that the original errno was zero. Zero denotes *no error*, but we know something + * went wrong and we want to report some error. This is a placeholder to mean, something + * was wrong, but errno was zero. */ + NME_ERRNO_SUCCESS = G_MAXINT - 1, + + /* an unspecified error. */ NME_UNSPEC = _NM_ERRNO_RESERVED_FIRST, @@ -68,64 +80,93 @@ enum { /*****************************************************************************/ +/* When we receive an errno from a system function, we can safely assume + * that the error number is not negative. We rely on that, and possibly just + * "return -errsv;" to signal an error. We also rely on that, because libc + * is our trusted base: meaning, if it cannot even succeed at setting errno + * according to specification, all bets are off. + * + * This macro returns the input argument, and asserts that the error variable + * is positive. + * + * In a sense, the macro is related to nm_errno_native() function, but the difference + * is that this macro asserts that @errsv is positive, while nm_errno_native() coerces + * negative values to be non-negative. */ +#define NM_ERRNO_NATIVE(errsv) \ + ({ \ + const int _errsv_x = (errsv); \ + \ + nm_assert (_errsv_x > 0); \ + _errsv_x; \ + }) + +/* Normalize native errno. + * + * Our API may return native error codes () as negative values. This function + * takes such an errno, and normalizes it to their positive value. + * + * The special values G_MININT and zero are coerced to NME_ERRNO_OUT_OF_RANGE and NME_ERRNO_SUCCESS + * respectively. + * Other values are coerced to their inverse. + * Other positive values are returned unchanged. + * + * Basically, this normalizes errsv to be positive (taking care of two pathological cases). + */ static inline int nm_errno_native (int errsv) { - /* several API returns negative errno values as errors. Normalize - * negative values to positive values. - * - * As a special case, map G_MININT to G_MAXINT. If you care about the - * distinction, then check for G_MININT before. - * - * Basically, this normalizes a plain errno to be non-negative. */ - return errsv >= 0 - ? errsv - : ((errsv == G_MININT) ? G_MAXINT : -errsv); + switch (errsv) { + case 0: return NME_ERRNO_SUCCESS; + case G_MININT: return NME_ERRNO_OUT_OF_RANGE; + default: + return errsv >= 0 ? errsv : -errsv; + } } +/* Normalizes an nm-error to be positive. + * + * Various API returns negative error codes, and this function converts the negative + * value to its positive. + * + * Note that @nmerr is on the domain of NetworkManager specific error numbers, + * which is not the same as the native error numbers (errsv from ). But + * as far as normalizing goes, nm_errno() does exactly the same remapping as + * nm_errno_native(). */ static inline int nm_errno (int nmerr) { - /* Normalizes an nm-error to be positive. Various API returns negative - * error codes, and this function converts the negative value to its - * positive. - * - * It's very similar to nm_errno_native(), but not exactly. The difference is that - * nm_errno_native() is for plain errno, while nm_errno() is for nm-error numbers. - * Yes, nm-error number are ~almost~ the same as errno, except that a particular - * range (_NM_ERRNO_RESERVED_FIRST, _NM_ERRNO_RESERVED_LAST) is reserved. The difference - * between the two functions is only how G_MININT is mapped. - * - * See also nm_errno_from_native() below. */ - return nmerr >= 0 - ? nmerr - : ((nmerr == G_MININT) ? NME_BUG : -nmerr); + return nm_errno_native (nmerr); } +/* this maps a native errno to a (always non-negative) nm-error number. + * + * Note that nm-error numbers are embedded into the range of regular + * errno. The only difference is, that nm-error numbers reserve a + * range (_NM_ERRNO_RESERVED_FIRST, _NM_ERRNO_RESERVED_LAST) for their + * own purpose. + * + * That means, converting an errno to nm-error number means in + * most cases just returning itself. + * Only pathological cases need special handling: + * + * - 0 is mapped to NME_ERRNO_SUCCESS; + * - G_MININT is mapped to NME_ERRNO_OUT_OF_RANGE; + * - values in the range of (+/-) [_NM_ERRNO_RESERVED_FIRST, _NM_ERRNO_RESERVED_LAST] + * are mapped to NME_NATIVE_ERRNO + * - all other values are their (positive) absolute value. + */ static inline int nm_errno_from_native (int errsv) { - /* this maps a native errno to a (always non-negative) nm-error number. - * - * Note that nm-error numbers are embedded into the range of regular - * errno. The only difference is, that nm-error numbers reserve a - * range (_NM_ERRNO_RESERVED_FIRST, _NM_ERRNO_RESERVED_LAST) for their - * own purpose. - * - * That means, converting an errno to nm-error number means in - * most cases just returning itself (negative values are normalized - * to be positive). Only values G_MININT and [_NM_ERRNO_RESERVED_FIRST, _NM_ERRNO_RESERVED_LAST] - * are coerced to the special value NME_NATIVE_ERRNO, as they cannot - * otherwise be represented in nm-error number domain. */ - if (errsv < 0) { - if (G_UNLIKELY (errsv == G_MININT)) - return NME_NATIVE_ERRNO; - errsv = -errsv; + switch (errsv) { + case 0: return NME_ERRNO_SUCCESS; + case G_MININT: return NME_ERRNO_OUT_OF_RANGE; + default: + return G_UNLIKELY ( errsv >= _NM_ERRNO_RESERVED_FIRST + && errsv <= _NM_ERRNO_RESERVED_LAST) + ? NME_NATIVE_ERRNO + : errsv; } - return G_UNLIKELY ( errsv >= _NM_ERRNO_RESERVED_FIRST - && errsv <= _NM_ERRNO_RESERVED_LAST) - ? NME_NATIVE_ERRNO - : errsv; } const char *nm_strerror (int nmerr); diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h index d9e409f0e6..a8082d4cd0 100644 --- a/shared/nm-utils/nm-shared-utils.h +++ b/shared/nm-utils/nm-shared-utils.h @@ -710,7 +710,7 @@ nm_utils_error_set_literal (GError **error, int error_code, const char *literal) \ ( _errsv >= 0 \ ? _errsv \ - : ( (_errsv == G_MININT) \ + : ( G_UNLIKELY (_errsv == G_MININT) \ ? G_MAXINT \ : -errsv)); \ })))