shared,core: add "nm-errno.h"
This will be our extension on top of <errno.h>.
We want to use (integer) error numbers, that can both
contain native errors from <errno.h> and our own defines,
both merge in one domain. That is, we will reserve a small
range of integers for our own defines (that hopefully won't
clash with errors from <errno.h>).
We can use this at places where GError is too cumbersome to use.
The advantage is, that our error numbers extend <errno.h> and can
be mixed.
This is what "src/platform/nm-netlink.h" already does with nl_errno(). Next,
the netlink errors from there will be merged into "nm-errno.h".
Also, platform has NMPlatformError, which are a distinct set of error
numbers. But these work differently in the sense that negative values
represent codes from <errno.h> and positive numbers are our own platform
specific defines. NMPlatformError will also be merged into "nm-errno.h".
"nm-errno.h" will unify the error handling of platform and netlink,
making it more similar to what we are used to from systemd, and give
room to extend it for our own purpose.
2018-12-22 12:41:04 +01:00
|
|
|
/* NetworkManager -- Network link manager
|
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
|
* Boston, MA 02110-1301 USA.
|
|
|
|
|
*
|
|
|
|
|
* Copyright 2018 Red Hat, Inc.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "nm-default.h"
|
|
|
|
|
|
|
|
|
|
#include "nm-errno.h"
|
|
|
|
|
|
2019-01-31 13:17:26 +01:00
|
|
|
#include <pthread.h>
|
|
|
|
|
|
shared,core: add "nm-errno.h"
This will be our extension on top of <errno.h>.
We want to use (integer) error numbers, that can both
contain native errors from <errno.h> and our own defines,
both merge in one domain. That is, we will reserve a small
range of integers for our own defines (that hopefully won't
clash with errors from <errno.h>).
We can use this at places where GError is too cumbersome to use.
The advantage is, that our error numbers extend <errno.h> and can
be mixed.
This is what "src/platform/nm-netlink.h" already does with nl_errno(). Next,
the netlink errors from there will be merged into "nm-errno.h".
Also, platform has NMPlatformError, which are a distinct set of error
numbers. But these work differently in the sense that negative values
represent codes from <errno.h> and positive numbers are our own platform
specific defines. NMPlatformError will also be merged into "nm-errno.h".
"nm-errno.h" will unify the error handling of platform and netlink,
making it more similar to what we are used to from systemd, and give
room to extend it for our own purpose.
2018-12-22 12:41:04 +01:00
|
|
|
/*****************************************************************************/
|
2018-12-22 12:45:01 +01:00
|
|
|
|
2019-01-31 16:37:53 +01:00
|
|
|
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_geterror,
|
|
|
|
|
#if 0
|
|
|
|
|
enum _NMErrno,
|
|
|
|
|
#else
|
|
|
|
|
int,
|
|
|
|
|
#endif
|
2018-12-22 12:45:01 +01:00
|
|
|
NM_UTILS_LOOKUP_DEFAULT (NULL),
|
2018-12-22 13:35:57 +01:00
|
|
|
|
2019-01-31 16:37:53 +01:00
|
|
|
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"),
|
platform: merge NMPlatformError with nm-error
Platform had it's own scheme for reporting errors: NMPlatformError.
Before, NMPlatformError indicated success via zero, negative integer
values are numbers from <errno.h>, and positive integer values are
platform specific codes. This changes now according to nm-error:
success is still zero. Negative values indicate a failure, where the
numeric value is either from <errno.h> or one of our error codes.
The meaning of positive values depends on the functions. Most functions
can only report an error reason (negative) and success (zero). For such
functions, positive values should never be returned (but the caller
should anticipate them).
For some functions, positive values could mean additional information
(but still success). That depends.
This is also what systemd does, except that systemd only returns
(negative) integers from <errno.h>, while we merge our own error codes
into the range of <errno.h>.
The advantage is to get rid of one way how to signal errors. The other
advantage is, that these error codes are compatible with all other
nm-errno values. For example, previously negative values indicated error
codes from <errno.h>, but it did not entail error codes from netlink.
2018-12-22 14:13:05 +01:00
|
|
|
|
2019-01-31 16:37:53 +01:00
|
|
|
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"),
|
platform: merge NMPlatformError with nm-error
Platform had it's own scheme for reporting errors: NMPlatformError.
Before, NMPlatformError indicated success via zero, negative integer
values are numbers from <errno.h>, and positive integer values are
platform specific codes. This changes now according to nm-error:
success is still zero. Negative values indicate a failure, where the
numeric value is either from <errno.h> or one of our error codes.
The meaning of positive values depends on the functions. Most functions
can only report an error reason (negative) and success (zero). For such
functions, positive values should never be returned (but the caller
should anticipate them).
For some functions, positive values could mean additional information
(but still success). That depends.
This is also what systemd does, except that systemd only returns
(negative) integers from <errno.h>, while we merge our own error codes
into the range of <errno.h>.
The advantage is to get rid of one way how to signal errors. The other
advantage is, that these error codes are compatible with all other
nm-errno values. For example, previously negative values indicated error
codes from <errno.h>, but it did not entail error codes from netlink.
2018-12-22 14:13:05 +01:00
|
|
|
|
2019-01-31 16:37:53 +01:00
|
|
|
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),
|
platform: merge NMPlatformError with nm-error
Platform had it's own scheme for reporting errors: NMPlatformError.
Before, NMPlatformError indicated success via zero, negative integer
values are numbers from <errno.h>, and positive integer values are
platform specific codes. This changes now according to nm-error:
success is still zero. Negative values indicate a failure, where the
numeric value is either from <errno.h> or one of our error codes.
The meaning of positive values depends on the functions. Most functions
can only report an error reason (negative) and success (zero). For such
functions, positive values should never be returned (but the caller
should anticipate them).
For some functions, positive values could mean additional information
(but still success). That depends.
This is also what systemd does, except that systemd only returns
(negative) integers from <errno.h>, while we merge our own error codes
into the range of <errno.h>.
The advantage is to get rid of one way how to signal errors. The other
advantage is, that these error codes are compatible with all other
nm-errno values. For example, previously negative values indicated error
codes from <errno.h>, but it did not entail error codes from netlink.
2018-12-22 14:13:05 +01:00
|
|
|
);
|
2018-12-22 12:45:01 +01:00
|
|
|
|
2019-01-31 13:17:26 +01:00
|
|
|
/**
|
|
|
|
|
* nm_strerror():
|
|
|
|
|
* @nmerr: the NetworkManager specific errno to be converted
|
|
|
|
|
* to string.
|
|
|
|
|
*
|
|
|
|
|
* NetworkManager specific error numbers reserve a range in "errno.h" with
|
|
|
|
|
* our own defines. For numbers that don't fall into this range, the numbers
|
|
|
|
|
* are identical to the common error numbers.
|
|
|
|
|
*
|
|
|
|
|
* Idential to strerror(), g_strerror(), nm_strerror_native() for error numbers
|
|
|
|
|
* that are not in the reserved range of NetworkManager specific errors.
|
|
|
|
|
*
|
|
|
|
|
* Returns: (transfer none): the string representation of the error number.
|
|
|
|
|
*/
|
2018-12-22 12:45:01 +01:00
|
|
|
const char *
|
2018-12-22 13:35:57 +01:00
|
|
|
nm_strerror (int nmerr)
|
2018-12-22 12:45:01 +01:00
|
|
|
{
|
|
|
|
|
const char *s;
|
|
|
|
|
|
2018-12-22 12:57:30 +01:00
|
|
|
nmerr = nm_errno (nmerr);
|
2018-12-22 12:45:01 +01:00
|
|
|
|
2018-12-22 12:57:30 +01:00
|
|
|
if (nmerr >= _NM_ERRNO_RESERVED_FIRST) {
|
2018-12-22 13:35:57 +01:00
|
|
|
s = _geterror (nmerr);
|
2018-12-22 12:45:01 +01:00
|
|
|
if (s)
|
|
|
|
|
return s;
|
|
|
|
|
}
|
2019-01-31 13:17:26 +01:00
|
|
|
return nm_strerror_native (nmerr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_strerror_native_r:
|
|
|
|
|
* @errsv: the errno to convert to string.
|
|
|
|
|
* @buf: the output buffer where to write the string to.
|
|
|
|
|
* @buf_size: the length of buffer.
|
|
|
|
|
*
|
|
|
|
|
* This is like strerror_r(), with one difference: depending on the
|
|
|
|
|
* locale, the returned string is guaranteed to be valid UTF-8.
|
|
|
|
|
* Also, there is some confusion as to whether to use glibc's
|
|
|
|
|
* strerror_r() or the POXIX/XSI variant. This is abstracted
|
|
|
|
|
* by the function.
|
|
|
|
|
*
|
|
|
|
|
* Note that the returned buffer may also be a statically allocated
|
|
|
|
|
* buffer, and not the input buffer @buf. Consequently, the returned
|
|
|
|
|
* string may be longer than @buf_size.
|
|
|
|
|
*
|
|
|
|
|
* Returns: (transfer none): a NUL terminated error message. This is either a static
|
|
|
|
|
* string (that is never freed), or the provided @buf argumnt.
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
nm_strerror_native_r (int errsv, char *buf, gsize buf_size)
|
|
|
|
|
{
|
|
|
|
|
char *buf2;
|
|
|
|
|
|
|
|
|
|
nm_assert (buf);
|
|
|
|
|
nm_assert (buf_size > 0);
|
|
|
|
|
|
|
|
|
|
#if (_POSIX_C_SOURCE >= 200112L) && ! _GNU_SOURCE
|
|
|
|
|
/* XSI-compliant */
|
|
|
|
|
{
|
|
|
|
|
int errno_saved = errno;
|
|
|
|
|
|
|
|
|
|
if (strerror_r (errsv, buf, buf_size) != 0) {
|
|
|
|
|
g_snprintf (buf, buf_size, "Unspecified errno %d", errsv);
|
|
|
|
|
errno = errno_saved;
|
|
|
|
|
}
|
|
|
|
|
buf2 = buf;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
/* GNU-specific */
|
|
|
|
|
buf2 = strerror_r (errsv, buf, buf_size);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* like g_strerror(), ensure that the error message is UTF-8. */
|
|
|
|
|
if ( !g_get_charset (NULL)
|
|
|
|
|
&& !g_utf8_validate (buf2, -1, NULL)) {
|
|
|
|
|
gs_free char *msg = NULL;
|
|
|
|
|
|
|
|
|
|
msg = g_locale_to_utf8 (buf2, -1, NULL, NULL, NULL);
|
|
|
|
|
if (msg) {
|
|
|
|
|
g_strlcpy (buf, msg, buf_size);
|
|
|
|
|
buf2 = buf;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return buf2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_strerror_native:
|
|
|
|
|
* @errsv: the errno integer from <errno.h>
|
|
|
|
|
*
|
|
|
|
|
* Like strerror(), but strerror() is not thread-safe and not guaranteed
|
|
|
|
|
* to be UTF-8.
|
|
|
|
|
*
|
|
|
|
|
* g_strerror() is a thread-safe variant of strerror(), however it caches
|
|
|
|
|
* all returned strings in a dictionary. That means, using this on untrusted
|
|
|
|
|
* error numbers can result in this cache to grow without limits.
|
|
|
|
|
*
|
|
|
|
|
* Instead, return a tread-local buffer. This way, it's thread-safe.
|
|
|
|
|
*
|
|
|
|
|
* There is a downside to this: subsequent calls of nm_strerror_native()
|
|
|
|
|
* overwrite the error message.
|
|
|
|
|
*
|
|
|
|
|
* Returns: (transfer none): the text representation of the error number.
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
nm_strerror_native (int errsv)
|
|
|
|
|
{
|
|
|
|
|
static _nm_thread_local char *buf_static = NULL;
|
|
|
|
|
char *buf;
|
|
|
|
|
|
|
|
|
|
buf = buf_static;
|
|
|
|
|
if (G_UNLIKELY (!buf)) {
|
|
|
|
|
int errno_saved = errno;
|
|
|
|
|
pthread_key_t key;
|
|
|
|
|
|
|
|
|
|
buf = g_malloc (NM_STRERROR_BUFSIZE);
|
|
|
|
|
buf_static = buf;
|
|
|
|
|
|
|
|
|
|
if ( pthread_key_create (&key, g_free) != 0
|
|
|
|
|
|| pthread_setspecific (key, buf) != 0) {
|
|
|
|
|
/* Failure. We will leak the buffer when the thread exits.
|
|
|
|
|
*
|
|
|
|
|
* Nothing we can do about it really. For Debug builds we fail with an assertion. */
|
|
|
|
|
nm_assert_not_reached ();
|
|
|
|
|
}
|
|
|
|
|
errno = errno_saved;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nm_strerror_native_r (errsv, buf, NM_STRERROR_BUFSIZE);
|
2018-12-22 12:45:01 +01:00
|
|
|
}
|