diff options
Diffstat (limited to 'src/libnm-systemd-shared/src/basic/errno-util.h')
-rw-r--r-- | src/libnm-systemd-shared/src/basic/errno-util.h | 142 |
1 files changed, 86 insertions, 56 deletions
diff --git a/src/libnm-systemd-shared/src/basic/errno-util.h b/src/libnm-systemd-shared/src/basic/errno-util.h index 091f99c590..27804e6382 100644 --- a/src/libnm-systemd-shared/src/basic/errno-util.h +++ b/src/libnm-systemd-shared/src/basic/errno-util.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +#include <inttypes.h> #include <stdlib.h> #include <string.h> @@ -73,6 +74,16 @@ static inline int RET_NERRNO(int ret) { return ret; } +/* Collect possible errors in <acc>, so that the first error can be returned. + * Returns (possibly updated) <acc>. */ +#define RET_GATHER(acc, err) \ + ({ \ + int *__a = &(acc), __e = (err); \ + if (*__a >= 0 && __e < 0) \ + *__a = __e; \ + *__a; \ + }) + static inline int errno_or_else(int fallback) { /* To be used when invoking library calls where errno handling is not defined clearly: we return * errno if it is set, and the specified error otherwise. The idea is that the caller initializes @@ -84,12 +95,23 @@ static inline int errno_or_else(int fallback) { return -abs(fallback); } +/* abs(3) says: Trying to take the absolute value of the most negative integer is not defined. */ +#define _DEFINE_ABS_WRAPPER(name) \ + static inline bool ERRNO_IS_##name(intmax_t r) { \ + if (r == INTMAX_MIN) \ + return false; \ + return ERRNO_IS_NEG_##name(-imaxabs(r)); \ + } + +assert_cc(INT_MAX <= INTMAX_MAX); + /* For send()/recv() or read()/write(). */ -static inline bool ERRNO_IS_TRANSIENT(int r) { - return IN_SET(abs(r), - EAGAIN, - EINTR); +static inline bool ERRNO_IS_NEG_TRANSIENT(intmax_t r) { + return IN_SET(r, + -EAGAIN, + -EINTR); } +_DEFINE_ABS_WRAPPER(TRANSIENT); /* Hint #1: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5. * @@ -98,79 +120,87 @@ static inline bool ERRNO_IS_TRANSIENT(int r) { * * Hint #3: When asynchronous connect() on TCP fails because the host never acknowledges a single packet, * kernel tells us that with ETIMEDOUT, see tcp(7). */ -static inline bool ERRNO_IS_DISCONNECT(int r) { - return IN_SET(abs(r), - ECONNABORTED, - ECONNREFUSED, - ECONNRESET, - EHOSTDOWN, - EHOSTUNREACH, - ENETDOWN, - ENETRESET, - ENETUNREACH, - ENONET, - ENOPROTOOPT, - ENOTCONN, - EPIPE, - EPROTO, - ESHUTDOWN, - ETIMEDOUT); +static inline bool ERRNO_IS_NEG_DISCONNECT(intmax_t r) { + return IN_SET(r, + -ECONNABORTED, + -ECONNREFUSED, + -ECONNRESET, + -EHOSTDOWN, + -EHOSTUNREACH, + -ENETDOWN, + -ENETRESET, + -ENETUNREACH, + -ENONET, + -ENOPROTOOPT, + -ENOTCONN, + -EPIPE, + -EPROTO, + -ESHUTDOWN, + -ETIMEDOUT); } +_DEFINE_ABS_WRAPPER(DISCONNECT); /* Transient errors we might get on accept() that we should ignore. As per error handling comment in * the accept(2) man page. */ -static inline bool ERRNO_IS_ACCEPT_AGAIN(int r) { - return ERRNO_IS_DISCONNECT(r) || - ERRNO_IS_TRANSIENT(r) || - abs(r) == EOPNOTSUPP; +static inline bool ERRNO_IS_NEG_ACCEPT_AGAIN(intmax_t r) { + return ERRNO_IS_NEG_DISCONNECT(r) || + ERRNO_IS_NEG_TRANSIENT(r) || + r == -EOPNOTSUPP; } +_DEFINE_ABS_WRAPPER(ACCEPT_AGAIN); /* Resource exhaustion, could be our fault or general system trouble */ -static inline bool ERRNO_IS_RESOURCE(int r) { - return IN_SET(abs(r), - EMFILE, - ENFILE, - ENOMEM); +static inline bool ERRNO_IS_NEG_RESOURCE(intmax_t r) { + return IN_SET(r, + -EMFILE, + -ENFILE, + -ENOMEM); } +_DEFINE_ABS_WRAPPER(RESOURCE); /* Seven different errors for "operation/system call/ioctl/socket feature not supported" */ -static inline bool ERRNO_IS_NOT_SUPPORTED(int r) { - return IN_SET(abs(r), - EOPNOTSUPP, - ENOTTY, - ENOSYS, - EAFNOSUPPORT, - EPFNOSUPPORT, - EPROTONOSUPPORT, - ESOCKTNOSUPPORT); +static inline bool ERRNO_IS_NEG_NOT_SUPPORTED(intmax_t r) { + return IN_SET(r, + -EOPNOTSUPP, + -ENOTTY, + -ENOSYS, + -EAFNOSUPPORT, + -EPFNOSUPPORT, + -EPROTONOSUPPORT, + -ESOCKTNOSUPPORT); } +_DEFINE_ABS_WRAPPER(NOT_SUPPORTED); /* Two different errors for access problems */ -static inline bool ERRNO_IS_PRIVILEGE(int r) { - return IN_SET(abs(r), - EACCES, - EPERM); +static inline bool ERRNO_IS_NEG_PRIVILEGE(intmax_t r) { + return IN_SET(r, + -EACCES, + -EPERM); } +_DEFINE_ABS_WRAPPER(PRIVILEGE); /* Three different errors for "not enough disk space" */ -static inline bool ERRNO_IS_DISK_SPACE(int r) { - return IN_SET(abs(r), - ENOSPC, - EDQUOT, - EFBIG); +static inline bool ERRNO_IS_NEG_DISK_SPACE(intmax_t r) { + return IN_SET(r, + -ENOSPC, + -EDQUOT, + -EFBIG); } +_DEFINE_ABS_WRAPPER(DISK_SPACE); /* Three different errors for "this device does not quite exist" */ -static inline bool ERRNO_IS_DEVICE_ABSENT(int r) { - return IN_SET(abs(r), - ENODEV, - ENXIO, - ENOENT); +static inline bool ERRNO_IS_NEG_DEVICE_ABSENT(intmax_t r) { + return IN_SET(r, + -ENODEV, + -ENXIO, + -ENOENT); } +_DEFINE_ABS_WRAPPER(DEVICE_ABSENT); /* Quite often we want to handle cases where the backing FS doesn't support extended attributes at all and * where it simply doesn't have the requested xattr the same way */ -static inline bool ERRNO_IS_XATTR_ABSENT(int r) { - return abs(r) == ENODATA || - ERRNO_IS_NOT_SUPPORTED(r); +static inline bool ERRNO_IS_NEG_XATTR_ABSENT(intmax_t r) { + return r == -ENODATA || + ERRNO_IS_NEG_NOT_SUPPORTED(r); } +_DEFINE_ABS_WRAPPER(XATTR_ABSENT); |